@@ -33,6 +33,7 @@ using v8::ObjectTemplate;
3333using v8::Persistent;
3434using v8::PropertyAttribute;
3535using v8::PropertyCallbackInfo;
36+ using v8::PropertyDescriptor;
3637using v8::Script;
3738using v8::ScriptCompiler;
3839using v8::ScriptOrigin;
@@ -132,41 +133,49 @@ class ContextifyContext {
132133 return ;
133134
134135 if (!has.FromJust ()) {
135- // Could also do this like so:
136- //
137- // PropertyAttribute att = global->GetPropertyAttributes(key_v);
138- // Local<Value> val = global->Get(key_v);
139- // sandbox->ForceSet(key_v, val, att);
140- //
141- // However, this doesn't handle ES6-style properties configured with
142- // Object.defineProperty, and that's exactly what we're up against at
143- // this point. ForceSet(key,val,att) only supports value properties
144- // with the ES3-style attribute flags (DontDelete/DontEnum/ReadOnly),
145- // which doesn't faithfully capture the full range of configurations
146- // that can be done using Object.defineProperty.
147- if (clone_property_method.IsEmpty ()) {
148- Local<String> code = FIXED_ONE_BYTE_STRING (env ()->isolate (),
149- " (function cloneProperty(source, key, target) {\n "
150- " if (key === 'Proxy') return;\n "
151- " try {\n "
152- " var desc = Object.getOwnPropertyDescriptor(source, key);\n "
153- " if (desc.value === source) desc.value = target;\n "
154- " Object.defineProperty(target, key, desc);\n "
155- " } catch (e) {\n "
156- " // Catch sealed properties errors\n "
157- " }\n "
158- " })" );
159-
160- Local<Script> script =
161- Script::Compile (context, code).ToLocalChecked ();
162- clone_property_method = Local<Function>::Cast (script->Run ());
163- CHECK (clone_property_method->IsFunction ());
136+ Local<Object> desc_vm_context =
137+ global->GetOwnPropertyDescriptor (context, key)
138+ .ToLocalChecked ().As <Object>();
139+
140+ bool is_accessor =
141+ desc_vm_context->Has (context, env ()->get_string ()).FromJust () ||
142+ desc_vm_context->Has (context, env ()->set_string ()).FromJust ();
143+
144+ auto define_property_on_sandbox = [&] (PropertyDescriptor* desc) {
145+ desc->set_configurable (desc_vm_context
146+ ->Get (context, env ()->configurable_string ()).ToLocalChecked ()
147+ ->BooleanValue (context).FromJust ());
148+ desc->set_enumerable (desc_vm_context
149+ ->Get (context, env ()->enumerable_string ()).ToLocalChecked ()
150+ ->BooleanValue (context).FromJust ());
151+ sandbox_obj->DefineProperty (context, key, *desc);
152+ };
153+
154+ if (is_accessor) {
155+ Local<Function> get =
156+ desc_vm_context->Get (context, env ()->get_string ())
157+ .ToLocalChecked ().As <Function>();
158+ Local<Function> set =
159+ desc_vm_context->Get (context, env ()->set_string ())
160+ .ToLocalChecked ().As <Function>();
161+
162+ PropertyDescriptor desc (get, set);
163+ define_property_on_sandbox (&desc);
164+ } else {
165+ Local<Value> value =
166+ desc_vm_context->Get (context, env ()->value_string ())
167+ .ToLocalChecked ();
168+
169+ bool writable =
170+ desc_vm_context->Get (context, env ()->writable_string ())
171+ .ToLocalChecked ()->BooleanValue (context).FromJust ();
172+
173+ PropertyDescriptor desc (value, writable);
174+ define_property_on_sandbox (&desc);
164175 }
165- Local<Value> args[] = { global, key, sandbox_obj };
166- clone_property_method->Call (global, arraysize (args), args);
167- }
168176 }
169177 }
178+ }
170179
171180
172181 // This is an object that just keeps an internal pointer to this
0 commit comments