-
Notifications
You must be signed in to change notification settings - Fork 30k
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
src: refactor of CopyProperties with V8 5.5 DefineProperty #11102
Conversation
cc/ @fhinkel |
src/node_contextify.cc
Outdated
->GetOwnPropertyDescriptor(context, key).ToLocalChecked()); | ||
|
||
bool isAccessor = object_from_vm_context | ||
->Has(context, String::NewFromUtf8(env()->isolate(), "get")) |
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 don't know what the norm/rule is offhand, but perhaps we should make these persistent strings (defined in src/env.h)?
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.
That's correct. We should create pre-allocated string in env.h
else this will allocate v8::String
every time we call CopyProperties
.
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.
Generally, if the string is going to be used frequently or more than once. I'm definitely + 1 on making these persistent.
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.
changes included. Thanks!
Can you change to commit message so it matches our guidelines please? It should be at most 50 characters long. |
src/node_contextify.cc
Outdated
->Get(context, String::NewFromUtf8(env()->isolate(), "writable")) | ||
.ToLocalChecked())->BooleanValue(); | ||
|
||
desc = new PropertyDescriptor(value, writable); |
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.
Who manages the lifetime of desc
? When will get cleaned up?
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.
It's deleted at the end of the function.
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.
ah, didn't notice that. Thanks @fhinkel
ba5235e
to
93ae019
Compare
src/node_contextify.cc
Outdated
clone_property_method = Local<Function>::Cast(script->Run()); | ||
CHECK(clone_property_method->IsFunction()); | ||
Local<Object> desc_from_vm_context = Local<Object>::Cast(global | ||
->GetOwnPropertyDescriptor(context, key).ToLocalChecked()); |
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 think it's more common to use As<T>()
than using Local<T>::Cast
in the codebase, like
Local<Object> desc_from_vm_context = global->GetOwnPropertyDescriptor(context, key)
.ToLocalChecked().As<Object>();
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.
True- I didn't realize this file was the only one in src/ using Local<T>::Cast
.
Good point!
src/node_contextify.cc
Outdated
if (!isAccessor) { | ||
Local<Value> value = Local<Value>::Cast(desc_from_vm_context | ||
->Get(context, env()->value_string()) | ||
.ToLocalChecked()); |
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.
Same here (Local<Value>
), though in this case you don't even need to cast because Get()
returns a MaybeLocal<Value>
.
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!
src/node_contextify.cc
Outdated
} | ||
} | ||
} |
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.
This line seems to prevent the file from compiling.
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 @TimothyGu.
I have just re-compiled it and re-run the tests. All seems to be working fine.
a525064
to
128aeb2
Compare
src/node_contextify.cc
Outdated
global->GetOwnPropertyDescriptor(context, key) | ||
.ToLocalChecked().As<Object>(); | ||
|
||
bool isAccessor = desc_from_vm_context |
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.
Style: can you name this is_accessor
?
src/node_contextify.cc
Outdated
->Has(context, env()->get_string()) | ||
.FromJust() || desc_from_vm_context | ||
->Has(context, env()->set_string()) | ||
.FromJust(); |
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.
This is mostly just personal preference but it's kind of a run-on line of code that's arguably more legible when written like this:
bool is_accessor =
desc_from_vm_context->Has(context, env()->get_string())
.FromJust() ||
desc_from_vm_context->Has(context, env()->set_string())
.FromJust();
If you shorten desc_from_vm_context
you can probably even make it fit on fewer lines.
But whatever you do, the convention in core is to break after the '=' when the RHS doesn't fit on a single line. Can you update that here and below?
src/node_contextify.cc
Outdated
|
||
bool writable = desc_from_vm_context | ||
->Get(context, env()->writable_string()).ToLocalChecked() | ||
.As<Value>()->BooleanValue(); |
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.
You don't have to cast to Value.
src/node_contextify.cc
Outdated
|
||
PropertyDescriptor* desc; | ||
|
||
if (!isAccessor) { |
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.
Minor style issue: don't negate in conditionals unless necessary. Remove the ! and swap the else/then clauses, it's easier to read.
src/node_contextify.cc
Outdated
.As<Value>()->BooleanValue()); | ||
desc->set_enumerable(desc_from_vm_context | ||
->Get(context, env()->enumerable_string()).ToLocalChecked() | ||
.As<Value>()->BooleanValue()); |
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.
You can get rid of the desc = new PropertyDescriptor(...)
and delete desc
calls if you wrap this code in a lambda, like this:
auto configure = [&] (PropertyDescriptor* desc) {
// ...
};
Which you then call like this:
if (is_accessor) {
// ...
PropertyDescriptor desc(get, set);
configure(&desc);
} else {
// ...
PropertyDescriptor desc(value, writable);
configure(&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.
I did not find a way to avoid doubling the DefineProperty
call after configure(&desc)
:
sandbox_obj->DefineProperty(context, key, desc);
Is it ok?
@bnoordhuis, updated. Thanks! |
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.
Almost there.
src/node_contextify.cc
Outdated
|
||
PropertyDescriptor desc(get, set); | ||
configure(&desc); | ||
sandbox_obj->DefineProperty(context, key, 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.
You can move the DefineProperty call into lambda. Invoke it with sandbox_obj->DefineProperty(context, key, *desc);
(note the star.)
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 call sandbox->DefineProperty()
inside configure
, which should probably rename the lambda. Maybe define_property_on_sandbox()
?
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 included the improvements and suggestions. Thanks!
src/node_contextify.cc
Outdated
.As<Value>()->BooleanValue()); | ||
desc->set_enumerable(desc_vm_context | ||
->Get(context, env()->enumerable_string()).ToLocalChecked() | ||
.As<Value>()->BooleanValue()); |
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.
You don't need the casts to Value here, it's already a Value. Can you use the BooleanValue() overloads that take a v8::Context? (Below too.)
CopyProperties() is refactored to use the V8 5.5 DefineProperty() API call. The change does not alter current behaviour. It is a step prior to removing the function CopyProperties, which becomes reduntant after fixes of V8 SetNamedPropertyHandler in 5.5. V8. Strings used as property attributes (value, enumerable etc) and accessors are defined as persistent strings in src/env.h
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.
->Get(context, env()->enumerable_string()).ToLocalChecked() | ||
->BooleanValue(context).FromJust()); | ||
sandbox_obj->DefineProperty(context, key, *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 normally indent code inside lambdas with two spaces, like regular functions. However, if the linter doesn't complain, I guess I shouldn't either.
Thanks! Landed in 67af1ad. |
CopyProperties() is refactored to use the V8 5.5 DefineProperty() API call. The change does not alter current behaviour. It is a step prior to removing the function CopyProperties, which becomes reduntant after fixes of V8 SetNamedPropertyHandler in 5.5. V8. Strings used as property attributes (value, enumerable etc) and accessors are defined as persistent strings in src/env.h PR-URL: nodejs#11102 Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
In order to land this on v7 we need to wait for the v8 5.5 backport #11029 |
CopyProperties() is refactored to use the V8 5.5 DefineProperty() API call. The change does not alter current behaviour. It is a step prior to removing the function CopyProperties, which becomes reduntant after fixes of V8 SetNamedPropertyHandler in 5.5. V8. Strings used as property attributes (value, enumerable etc) and accessors are defined as persistent strings in src/env.h PR-URL: #11102 Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
CopyProperties() is refactored to use the V8 5.5 DefineProperty() API call. The change does not alter current behaviour. It is a step prior to removing the function CopyProperties, which becomes reduntant after fixes of V8 SetNamedPropertyHandler in 5.5. V8. Strings used as property attributes (value, enumerable etc) and accessors are defined as persistent strings in src/env.h PR-URL: nodejs#11102 Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
CopyProperties() is refactored to use the V8 5.5 DefineProperty() API call. The change does not alter current behaviour. It is a step prior to removing the function CopyProperties, which becomes reduntant after fixes of V8 SetNamedPropertyHandler in 5.5. V8. Strings used as property attributes (value, enumerable etc) and accessors are defined as persistent strings in src/env.h PR-URL: nodejs#11102 Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
vm: remove JavaScript code from CopyProperties()
CopyProperties() is refactored to use the V8 5.5 DefineProperty() API call.
The change maintains current behavior. This is step 1
in removing the CopyProperties() function (follow-up PR).
API improvements fix V8 SetNamedPropertyHandler
to properly treat the ES6 syntax and CopyProperties()
becomes redundant.
Strings used as property attributes and accessors
are defined as persistent strings in src/env.h.