-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
vm: properly handle defining props on any value #46615
Conversation
I ran JS tests but forgot to check the linting. Will run linters and update the PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
@addaleax would ou have time to take another look? rom what I understand it looks good but you have more context (pun intended) than me here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vdeturckheim Not really, unfortunately … I’d mostly just look at the test changes here, and they seem reasonable to me, so I have no concerns about this landing in general
src/node_contextify.cc
Outdated
if (is_declared_on_sandbox && | ||
ctx->sandbox() | ||
->GetOwnPropertyDescriptor(context, property) | ||
.ToLocal(&desc) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably should be returning early here if this .ToLocal()
returns false
(i.e. getting the property descriptor throws an exception), and probably also if the HasOwnProperty
calls below return empty Maybe
s, rather than still trying to call sandbox()->Set()
later on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought of that too but I finally concluded: calling the set will have the benefit to apply the right behaviour. But no strong opinion at all 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But should we really do the Set()
call if there if an exception occurred? Right now, this code is doing the equivalent of
let err;
let is_get_set_property = false;
let desc;
try {
desc = Object.getOwnPropertyDescriptor(sandbox, property);
} catch (err_) {
err = err_;
}
if (err === undefined && typeof desc === 'object' && desc !== null) {
let has_get = false, has_set = false;
try {
has_get = Object.hasOwn(desc, 'get');
} catch (err_) {
err = err_;
}
try {
has_set = Object.hasOwn(desc, 'set');
} catch (err_) {
err = err_;
}
is_get_set_property = has_get || has_set;
}
sandbox[property] = value;
if (err) throw err;
if (is_get_set_property)
return value;
when it might be a bit more intuitive to do the equivalent of
let is_get_set_property = false;
const desc = Object.getOwnPropertyDescriptor(sandbox, property);
if (typeof desc === 'object' && desc !== null) {
is_get_set_property = Object.hasOwn(desc, 'get') || Object.hasOwn(desc, 'set');
}
sandbox[property] = value;
if (is_get_set_property)
return value;
.
If we do want to unconditionally set sandbox[property] = value
, then maybe we should do that before the rest of the checks (and also return early in case of an exception during that assignment)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I remember well I mostly preserved the call to Set as it was done all the time starting at 18.2.0. So I may have thought 'well let's not drop it from these cases for now to reduce risks of breaking things possibly not well covered'. But in the meantime as I covered the change by many extra tests (e2e), we may give it a try. I'll not be able to do it in the coming days, but I can either attempt to do on this PR when I'll be back or on another one. Anyway, I'll add some more checks if I do add it so that we get sure that these possible edge cases also get well covered (in some scenarios I tried during my manual checks, calling or not the Set was similar).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we do want to unconditionally set sandbox[property] = value, then maybe we should do that before the rest of the checks (and also return early in case of an exception during that assignment)?
I will update the PR to follow your suggestion by moving the line:
USE(ctx->sandbox()->Set(context, property, value));
Before the if statement.
It might be a bit more intuitive to do the equivalent of
Will try to rework it asap too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the suggestions @addaleax
I reworked a bit the code since your last review. I'm just wondering if you had better/shorter suggestions for the two following if blocks?
Local<Value> desc;
if (is_declared_on_sandbox &&
ctx->sandbox()
->GetOwnPropertyDescriptor(context, property)
.ToLocal(&desc) &&
desc->IsObject()) {
if (desc_obj->HasOwnProperty(context, env->get_string()).FromMaybe(false) ||
desc_obj->HasOwnProperty(context, env->set_string()).FromMaybe(false))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first one seems correct as-is (and generally, it’s a bit unfortunate that “correct” and “shorter” are usually conflicting goals when working with V8 Maybe
s).
I think what still needs to be addressed here is:
and also return early in case of an exception during that assignment
i.e. replace USE(ctx->sandbox()->Set(context, property, value));
with if (ctx->sandbox()->Set(context, property, value).IsNothing()) return;
or similar
and currently, the PR here uses desc_obj->HasOwnProperty(context, env->get_string()).FromJust()
, which should probably also use proper error handling (i.e. .To()
or .FromMaybe()
instead of .FromJust()
) since otherwise an exception here would crash the process.
While it was supposed to fix most of the remaining issues, nodejs#46458 missed some in strict mode. This PR adds some additional checks. It also clarifies what we are really checking to execute or not the `GetReturnValue`.
Cc @addaleax @vdeturckheim, sorry for the force push, I rebased the branch on main and stashed commits related to the feedbacks you gave me altogether. The last suggestions made by @addaleax have been handled in the commit called Apply comments of 2nd review. |
Landed in aa6e9c8 |
While it was supposed to fix most of the remaining issues, #46458 missed some in strict mode. This PR adds some additional checks. It also clarifies what we are really checking to execute or not the `GetReturnValue`. PR-URL: #46615 Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
While it was supposed to fix most of the remaining issues, #46458 missed some in strict mode. This PR adds some additional checks. It also clarifies what we are really checking to execute or not the `GetReturnValue`. PR-URL: #46615 Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This PR is a follow-up of nodejs#46615. When bumping V8 for node 18, various bugs appeared around vm. Some have been fixed along the flow, but there is at least one remaining and described at: jestjs/jest#13338. The current fix does nothing on node 20: the new bump of v8 done for node 20 seems to fix it. But it would fix the problem in both node 18 and node 19.
This PR is a follow-up of nodejs#46615. When bumping V8 for node 18, various bugs appeared around vm. Some have been fixed along the flow, but there is at least one remaining and described at: jestjs/jest#13338. The current fix does nothing on node 20: the new bump of v8 done for node 20 seems to fix it. But it would fix the problem in both node 18 and node 19. I confirmed it would fix node 19 by cherry-picking the commit on v19.x-staging and launching `make -j4 jstest` on it.
This PR is a follow-up of #46615. When bumping V8 for node 18, various bugs appeared around vm. Some have been fixed along the flow, but there is at least one remaining and described at: jestjs/jest#13338. The current fix does nothing on node 20: the new bump of v8 done for node 20 seems to fix it. But it would fix the problem in both node 18 and node 19. I confirmed it would fix node 19 by cherry-picking the commit on v19.x-staging and launching `make -j4 jstest` on it. PR-URL: #47572 Reviewed-By: James M Snell <jasnell@gmail.com>
This PR is a follow-up of #46615. When bumping V8 for node 18, various bugs appeared around vm. Some have been fixed along the flow, but there is at least one remaining and described at: jestjs/jest#13338. The current fix does nothing on node 20: the new bump of v8 done for node 20 seems to fix it. But it would fix the problem in both node 18 and node 19. I confirmed it would fix node 19 by cherry-picking the commit on v19.x-staging and launching `make -j4 jstest` on it. PR-URL: #47572 Reviewed-By: James M Snell <jasnell@gmail.com>
While it was supposed to fix most of the remaining issues, #46458 missed some in strict mode. This PR adds some additional checks. It also clarifies what we are really checking to execute or not the `GetReturnValue`. PR-URL: #46615 Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
I landed this on v18.x-staging in fb90b6b |
This PR is a follow-up of #46615. When bumping V8 for node 18, various bugs appeared around vm. Some have been fixed along the flow, but there is at least one remaining and described at: jestjs/jest#13338. The current fix does nothing on node 20: the new bump of v8 done for node 20 seems to fix it. But it would fix the problem in both node 18 and node 19. I confirmed it would fix node 19 by cherry-picking the commit on v19.x-staging and launching `make -j4 jstest` on it. PR-URL: #47572 Reviewed-By: James M Snell <jasnell@gmail.com>
This PR is a follow-up of nodejs#46615. When bumping V8 for node 18, various bugs appeared around vm. Some have been fixed along the flow, but there is at least one remaining and described at: jestjs/jest#13338. The current fix does nothing on node 20: the new bump of v8 done for node 20 seems to fix it. But it would fix the problem in both node 18 and node 19. I confirmed it would fix node 19 by cherry-picking the commit on v19.x-staging and launching `make -j4 jstest` on it. PR-URL: nodejs#47572 Reviewed-By: James M Snell <jasnell@gmail.com>
This PR is a follow-up of nodejs#46615. When bumping V8 for node 18, various bugs appeared around vm. Some have been fixed along the flow, but there is at least one remaining and described at: jestjs/jest#13338. The current fix does nothing on node 20: the new bump of v8 done for node 20 seems to fix it. But it would fix the problem in both node 18 and node 19. I confirmed it would fix node 19 by cherry-picking the commit on v19.x-staging and launching `make -j4 jstest` on it. PR-URL: nodejs#47572 Reviewed-By: James M Snell <jasnell@gmail.com>
This PR is a follow-up of nodejs#46615. When bumping V8 for node 18, various bugs appeared around vm. Some have been fixed along the flow, but there is at least one remaining and described at: jestjs/jest#13338. The current fix does nothing on node 20: the new bump of v8 done for node 20 seems to fix it. But it would fix the problem in both node 18 and node 19. I confirmed it would fix node 19 by cherry-picking the commit on v19.x-staging and launching `make -j4 jstest` on it. PR-URL: nodejs#47572 Reviewed-By: James M Snell <jasnell@gmail.com>
While it was supposed to fix most of the remaining issues, #46458 missed some in strict mode.
This PR adds some additional checks.
It also clarifies what we are really checking to execute or not the
GetReturnValue
. Theis_function
I resurrected from 17.x was actually not a good option as it made some assignations of non-function values starting to fail. It seems that while it was relevant in 17.x, it was probably not the best option for 18.x.Fix #43129
Here is a quick overview of what worked or not for each version of node:
OwnPropertySymbols should list new symbols
OwnPropertyNames should list new keys
Override proxy with function
Override proxy with number
Override proxy with number on basic value
Override proxy with number on unknown value
Override proxy with function on symbol
Override proxy with number
Override proxy with number on basic value on symbol
Override proxy with number on unknown value on symbol