Browse Source

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: https://github.com/nodejs/node/pull/11102
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
v7.x
AnnaMag 8 years ago
committed by Italo A. Casas
parent
commit
44b17a21ad
No known key found for this signature in database GPG Key ID: 23EFEFE93C4CFFFE
  1. 5
      src/env.h
  2. 73
      src/node_contextify.cc

5
src/env.h

@ -82,6 +82,7 @@ namespace node {
V(oncertcb_string, "oncertcb") \ V(oncertcb_string, "oncertcb") \
V(onclose_string, "_onclose") \ V(onclose_string, "_onclose") \
V(code_string, "code") \ V(code_string, "code") \
V(configurable_string, "configurable") \
V(cwd_string, "cwd") \ V(cwd_string, "cwd") \
V(dest_string, "dest") \ V(dest_string, "dest") \
V(detached_string, "detached") \ V(detached_string, "detached") \
@ -89,6 +90,7 @@ namespace node {
V(domain_string, "domain") \ V(domain_string, "domain") \
V(emitting_top_level_domain_error_string, "_emittingTopLevelDomainError") \ V(emitting_top_level_domain_error_string, "_emittingTopLevelDomainError") \
V(exchange_string, "exchange") \ V(exchange_string, "exchange") \
V(enumerable_string, "enumerable") \
V(idle_string, "idle") \ V(idle_string, "idle") \
V(irq_string, "irq") \ V(irq_string, "irq") \
V(encoding_string, "encoding") \ V(encoding_string, "encoding") \
@ -112,6 +114,7 @@ namespace node {
V(file_string, "file") \ V(file_string, "file") \
V(fingerprint_string, "fingerprint") \ V(fingerprint_string, "fingerprint") \
V(flags_string, "flags") \ V(flags_string, "flags") \
V(get_string, "get") \
V(gid_string, "gid") \ V(gid_string, "gid") \
V(handle_string, "handle") \ V(handle_string, "handle") \
V(heap_total_string, "heapTotal") \ V(heap_total_string, "heapTotal") \
@ -191,6 +194,7 @@ namespace node {
V(service_string, "service") \ V(service_string, "service") \
V(servername_string, "servername") \ V(servername_string, "servername") \
V(session_id_string, "sessionId") \ V(session_id_string, "sessionId") \
V(set_string, "set") \
V(shell_string, "shell") \ V(shell_string, "shell") \
V(signal_string, "signal") \ V(signal_string, "signal") \
V(size_string, "size") \ V(size_string, "size") \
@ -217,6 +221,7 @@ namespace node {
V(username_string, "username") \ V(username_string, "username") \
V(valid_from_string, "valid_from") \ V(valid_from_string, "valid_from") \
V(valid_to_string, "valid_to") \ V(valid_to_string, "valid_to") \
V(value_string, "value") \
V(verify_error_string, "verifyError") \ V(verify_error_string, "verifyError") \
V(version_string, "version") \ V(version_string, "version") \
V(weight_string, "weight") \ V(weight_string, "weight") \

73
src/node_contextify.cc

@ -33,6 +33,7 @@ using v8::ObjectTemplate;
using v8::Persistent; using v8::Persistent;
using v8::PropertyAttribute; using v8::PropertyAttribute;
using v8::PropertyCallbackInfo; using v8::PropertyCallbackInfo;
using v8::PropertyDescriptor;
using v8::Script; using v8::Script;
using v8::ScriptCompiler; using v8::ScriptCompiler;
using v8::ScriptOrigin; using v8::ScriptOrigin;
@ -132,41 +133,49 @@ class ContextifyContext {
return; return;
if (!has.FromJust()) { if (!has.FromJust()) {
// Could also do this like so: Local<Object> desc_vm_context =
// global->GetOwnPropertyDescriptor(context, key)
// PropertyAttribute att = global->GetPropertyAttributes(key_v); .ToLocalChecked().As<Object>();
// Local<Value> val = global->Get(key_v);
// sandbox->ForceSet(key_v, val, att); bool is_accessor =
// desc_vm_context->Has(context, env()->get_string()).FromJust() ||
// However, this doesn't handle ES6-style properties configured with desc_vm_context->Has(context, env()->set_string()).FromJust();
// Object.defineProperty, and that's exactly what we're up against at
// this point. ForceSet(key,val,att) only supports value properties auto define_property_on_sandbox = [&] (PropertyDescriptor* desc) {
// with the ES3-style attribute flags (DontDelete/DontEnum/ReadOnly), desc->set_configurable(desc_vm_context
// which doesn't faithfully capture the full range of configurations ->Get(context, env()->configurable_string()).ToLocalChecked()
// that can be done using Object.defineProperty. ->BooleanValue(context).FromJust());
if (clone_property_method.IsEmpty()) { desc->set_enumerable(desc_vm_context
Local<String> code = FIXED_ONE_BYTE_STRING(env()->isolate(), ->Get(context, env()->enumerable_string()).ToLocalChecked()
"(function cloneProperty(source, key, target) {\n" ->BooleanValue(context).FromJust());
" if (key === 'Proxy') return;\n" sandbox_obj->DefineProperty(context, key, *desc);
" try {\n" };
" var desc = Object.getOwnPropertyDescriptor(source, key);\n"
" if (desc.value === source) desc.value = target;\n" if (is_accessor) {
" Object.defineProperty(target, key, desc);\n" Local<Function> get =
" } catch (e) {\n" desc_vm_context->Get(context, env()->get_string())
" // Catch sealed properties errors\n" .ToLocalChecked().As<Function>();
" }\n" Local<Function> set =
"})"); desc_vm_context->Get(context, env()->set_string())
.ToLocalChecked().As<Function>();
Local<Script> script =
Script::Compile(context, code).ToLocalChecked(); PropertyDescriptor desc(get, set);
clone_property_method = Local<Function>::Cast(script->Run()); define_property_on_sandbox(&desc);
CHECK(clone_property_method->IsFunction()); } else {
Local<Value> value =
desc_vm_context->Get(context, env()->value_string())
.ToLocalChecked();
bool writable =
desc_vm_context->Get(context, env()->writable_string())
.ToLocalChecked()->BooleanValue(context).FromJust();
PropertyDescriptor desc(value, writable);
define_property_on_sandbox(&desc);
} }
Local<Value> args[] = { global, key, sandbox_obj };
clone_property_method->Call(global, arraysize(args), args);
}
} }
} }
}
// This is an object that just keeps an internal pointer to this // This is an object that just keeps an internal pointer to this

Loading…
Cancel
Save