@@ -33,6 +33,7 @@ using v8::ObjectTemplate;
33
33
using v8::Persistent;
34
34
using v8::PropertyAttribute;
35
35
using v8::PropertyCallbackInfo;
36
+ using v8::PropertyDescriptor;
36
37
using v8::Script;
37
38
using v8::ScriptCompiler;
38
39
using v8::ScriptOrigin;
@@ -132,41 +133,49 @@ class ContextifyContext {
132
133
return ;
133
134
134
135
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);
164
175
}
165
- Local<Value> args[] = { global, key, sandbox_obj };
166
- clone_property_method->Call (global, arraysize (args), args);
167
- }
168
176
}
169
177
}
178
+ }
170
179
171
180
172
181
// This is an object that just keeps an internal pointer to this
0 commit comments