src: refactor of CopyProperties with V8 5.5 DefineProperty #11102

Closed
wants to merge 1 commit into
from

Conversation

@AnnaMag
Member

AnnaMag commented Feb 1, 2017

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines
Affected 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.

@AnnaMag

This comment has been minimized.

Show comment
Hide comment
Member

AnnaMag commented Feb 1, 2017

cc/ @fhinkel

@AnnaMag AnnaMag changed the title from refactor of CopyProperties in node_contextify.cc using V8 5.5 DefineProperty to src: refactor of CopyProperties in node_contextify.cc using V8 5.5 DefineProperty Feb 1, 2017

src/node_contextify.cc
+ ->GetOwnPropertyDescriptor(context, key).ToLocalChecked());
+
+ bool isAccessor = object_from_vm_context
+ ->Has(context, String::NewFromUtf8(env()->isolate(), "get"))

This comment has been minimized.

@mscdex

mscdex Feb 1, 2017

Contributor

I don't know what the norm/rule is offhand, but perhaps we should make these persistent strings (defined in src/env.h)?

@mscdex

mscdex Feb 1, 2017

Contributor

I don't know what the norm/rule is offhand, but perhaps we should make these persistent strings (defined in src/env.h)?

This comment has been minimized.

@kunalspathak

kunalspathak Feb 1, 2017

Contributor

That's correct. We should create pre-allocated string in env.h else this will allocate v8::String every time we call CopyProperties.

@kunalspathak

kunalspathak Feb 1, 2017

Contributor

That's correct. We should create pre-allocated string in env.h else this will allocate v8::String every time we call CopyProperties.

This comment has been minimized.

@jasnell

jasnell Feb 1, 2017

Member

Generally, if the string is going to be used frequently or more than once. I'm definitely + 1 on making these persistent.

@jasnell

jasnell Feb 1, 2017

Member

Generally, if the string is going to be used frequently or more than once. I'm definitely + 1 on making these persistent.

This comment has been minimized.

@AnnaMag

AnnaMag Feb 2, 2017

Member

changes included. Thanks!

@AnnaMag

AnnaMag Feb 2, 2017

Member

changes included. Thanks!

@fhinkel

This comment has been minimized.

Show comment
Hide comment
@fhinkel

fhinkel Feb 1, 2017

Member

Can you change to commit message so it matches our guidelines please? It should be at most 50 characters long.

Member

fhinkel commented Feb 1, 2017

Can you change to commit message so it matches our guidelines please? It should be at most 50 characters long.

src/node_contextify.cc
+ ->Get(context, String::NewFromUtf8(env()->isolate(), "writable"))
+ .ToLocalChecked())->BooleanValue();
+
+ desc = new PropertyDescriptor(value, writable);

This comment has been minimized.

@kunalspathak

kunalspathak Feb 1, 2017

Contributor

Who manages the lifetime of desc? When will get cleaned up?

@kunalspathak

kunalspathak Feb 1, 2017

Contributor

Who manages the lifetime of desc? When will get cleaned up?

This comment has been minimized.

@fhinkel

fhinkel Feb 1, 2017

Member

It's deleted at the end of the function.

@fhinkel

fhinkel Feb 1, 2017

Member

It's deleted at the end of the function.

This comment has been minimized.

@kunalspathak

kunalspathak Feb 1, 2017

Contributor

ah, didn't notice that. Thanks @fhinkel

@kunalspathak

kunalspathak Feb 1, 2017

Contributor

ah, didn't notice that. Thanks @fhinkel

@AnnaMag AnnaMag changed the title from src: refactor of CopyProperties in node_contextify.cc using V8 5.5 DefineProperty to src: refactor of CopyProperties with V8 5.5 DefineProperty Feb 2, 2017

src/node_contextify.cc
- 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());

This comment has been minimized.

@TimothyGu

TimothyGu Feb 2, 2017

Member

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>();
@TimothyGu

TimothyGu Feb 2, 2017

Member

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>();

This comment has been minimized.

@AnnaMag

AnnaMag Feb 2, 2017

Member

True- I didn't realize this file was the only one in src/ using Local<T>::Cast.
Good point!

@AnnaMag

AnnaMag Feb 2, 2017

Member

True- I didn't realize this file was the only one in src/ using Local<T>::Cast.
Good point!

src/node_contextify.cc
+ if (!isAccessor) {
+ Local<Value> value = Local<Value>::Cast(desc_from_vm_context
+ ->Get(context, env()->value_string())
+ .ToLocalChecked());

This comment has been minimized.

@TimothyGu

TimothyGu Feb 2, 2017

Member

Same here (Local<Value>), though in this case you don't even need to cast because Get() returns a MaybeLocal<Value>.

@TimothyGu

TimothyGu Feb 2, 2017

Member

Same here (Local<Value>), though in this case you don't even need to cast because Get() returns a MaybeLocal<Value>.

This comment has been minimized.

@AnnaMag

AnnaMag Feb 2, 2017

Member

Thanks!

@AnnaMag

AnnaMag Feb 2, 2017

Member

Thanks!

src/node_contextify.cc
}
}
+}

This comment has been minimized.

@TimothyGu

TimothyGu Feb 2, 2017

Member

This line seems to prevent the file from compiling.

@TimothyGu

TimothyGu Feb 2, 2017

Member

This line seems to prevent the file from compiling.

This comment has been minimized.

@AnnaMag

AnnaMag Feb 2, 2017

Member

Thanks @TimothyGu.
I have just re-compiled it and re-run the tests. All seems to be working fine.

@AnnaMag

AnnaMag Feb 2, 2017

Member

Thanks @TimothyGu.
I have just re-compiled it and re-run the tests. All seems to be working fine.

@fhinkel

fhinkel approved these changes Feb 3, 2017

src/node_contextify.cc
+ global->GetOwnPropertyDescriptor(context, key)
+ .ToLocalChecked().As<Object>();
+
+ bool isAccessor = desc_from_vm_context

This comment has been minimized.

@bnoordhuis

bnoordhuis Feb 3, 2017

Member

Style: can you name this is_accessor?

@bnoordhuis

bnoordhuis Feb 3, 2017

Member

Style: can you name this is_accessor?

src/node_contextify.cc
+ ->Has(context, env()->get_string())
+ .FromJust() || desc_from_vm_context
+ ->Has(context, env()->set_string())
+ .FromJust();

This comment has been minimized.

@bnoordhuis

bnoordhuis Feb 3, 2017

Member

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?

@bnoordhuis

bnoordhuis Feb 3, 2017

Member

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
+
+ bool writable = desc_from_vm_context
+ ->Get(context, env()->writable_string()).ToLocalChecked()
+ .As<Value>()->BooleanValue();

This comment has been minimized.

@bnoordhuis

bnoordhuis Feb 3, 2017

Member

You don't have to cast to Value.

@bnoordhuis

bnoordhuis Feb 3, 2017

Member

You don't have to cast to Value.

src/node_contextify.cc
+
+ PropertyDescriptor* desc;
+
+ if (!isAccessor) {

This comment has been minimized.

@bnoordhuis

bnoordhuis Feb 3, 2017

Member

Minor style issue: don't negate in conditionals unless necessary. Remove the ! and swap the else/then clauses, it's easier to read.

@bnoordhuis

bnoordhuis Feb 3, 2017

Member

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
+ .As<Value>()->BooleanValue());
+ desc->set_enumerable(desc_from_vm_context
+ ->Get(context, env()->enumerable_string()).ToLocalChecked()
+ .As<Value>()->BooleanValue());

This comment has been minimized.

@bnoordhuis

bnoordhuis Feb 3, 2017

Member

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);
}
@bnoordhuis

bnoordhuis Feb 3, 2017

Member

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);
}

This comment has been minimized.

@AnnaMag

AnnaMag Feb 3, 2017

Member

I did not find a way to avoid doubling the DefineProperty call after configure(&desc):

sandbox_obj->DefineProperty(context, key, desc);

Is it ok?

@AnnaMag

AnnaMag Feb 3, 2017

Member

I did not find a way to avoid doubling the DefineProperty call after configure(&desc):

sandbox_obj->DefineProperty(context, key, desc);

Is it ok?

@AnnaMag

This comment has been minimized.

Show comment
Hide comment
@AnnaMag

AnnaMag Feb 3, 2017

Member

@bnoordhuis, updated. Thanks!

Member

AnnaMag commented Feb 3, 2017

@bnoordhuis, updated. Thanks!

@bnoordhuis

Almost there.

src/node_contextify.cc
+
+ PropertyDescriptor desc(get, set);
+ configure(&desc);
+ sandbox_obj->DefineProperty(context, key, desc);

This comment has been minimized.

@bnoordhuis

bnoordhuis Feb 4, 2017

Member

You can move the DefineProperty call into lambda. Invoke it with sandbox_obj->DefineProperty(context, key, *desc); (note the star.)

@bnoordhuis

bnoordhuis Feb 4, 2017

Member

You can move the DefineProperty call into lambda. Invoke it with sandbox_obj->DefineProperty(context, key, *desc); (note the star.)

This comment has been minimized.

@fhinkel

fhinkel Feb 4, 2017

Member

If we call sandbox->DefineProperty() inside configure, which should probably rename the lambda. Maybe define_property_on_sandbox()?

@fhinkel

fhinkel Feb 4, 2017

Member

If we call sandbox->DefineProperty() inside configure, which should probably rename the lambda. Maybe define_property_on_sandbox()?

This comment has been minimized.

@AnnaMag

AnnaMag Feb 4, 2017

Member

I included the improvements and suggestions. Thanks!

@AnnaMag

AnnaMag Feb 4, 2017

Member

I included the improvements and suggestions. Thanks!

src/node_contextify.cc
+ .As<Value>()->BooleanValue());
+ desc->set_enumerable(desc_vm_context
+ ->Get(context, env()->enumerable_string()).ToLocalChecked()
+ .As<Value>()->BooleanValue());

This comment has been minimized.

@bnoordhuis

bnoordhuis Feb 4, 2017

Member

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.)

@bnoordhuis

bnoordhuis Feb 4, 2017

Member

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.)

src: refactor CopyProperties to remove JS
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
+ ->Get(context, env()->enumerable_string()).ToLocalChecked()
+ ->BooleanValue(context).FromJust());
+ sandbox_obj->DefineProperty(context, key, *desc);
+ };

This comment has been minimized.

@bnoordhuis

bnoordhuis Feb 4, 2017

Member

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.

@bnoordhuis

bnoordhuis Feb 4, 2017

Member

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.

@jasnell

jasnell approved these changes Feb 4, 2017

@fhinkel

This comment has been minimized.

Show comment
Hide comment
@fhinkel

fhinkel Feb 5, 2017

Member

Thanks! Landed in 67af1ad.

Member

fhinkel commented Feb 5, 2017

Thanks! Landed in 67af1ad.

fhinkel added a commit to fhinkel/node that referenced this pull request Feb 5, 2017

src: refactor CopyProperties to remove JS
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>

@fhinkel fhinkel closed this Feb 5, 2017

@italoacasas

This comment has been minimized.

Show comment
Hide comment
@italoacasas

italoacasas Feb 5, 2017

Member

In order to land this on v7 we need to wait for the v8 5.5 backport #11029

Member

italoacasas commented Feb 5, 2017

In order to land this on v7 we need to wait for the v8 5.5 backport #11029

italoacasas added a commit that referenced this pull request Feb 10, 2017

src: refactor CopyProperties to remove JS
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>

italoacasas added a commit to italoacasas/node that referenced this pull request Feb 14, 2017

src: refactor CopyProperties to remove JS
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>

KryDos added a commit to KryDos/node that referenced this pull request Feb 25, 2017

src: refactor CopyProperties to remove JS
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment