@@ -50,10 +50,13 @@ using v8::FunctionCallbackInfo;
5050using v8::FunctionTemplate;
5151using v8::HandleScope;
5252using v8::IndexedPropertyHandlerConfiguration;
53+ using v8::IndexFilter;
5354using v8::Int32;
55+ using v8::Integer;
5456using v8::Intercepted;
5557using v8::Isolate;
5658using v8::Just;
59+ using v8::KeyCollectionMode;
5760using v8::Local;
5861using v8::Maybe;
5962using v8::MaybeLocal;
@@ -72,6 +75,7 @@ using v8::Promise;
7275using v8::PropertyAttribute;
7376using v8::PropertyCallbackInfo;
7477using v8::PropertyDescriptor;
78+ using v8::PropertyFilter;
7579using v8::PropertyHandlerFlags;
7680using v8::Script;
7781using v8::ScriptCompiler;
@@ -175,20 +179,22 @@ void ContextifyContext::InitializeGlobalTemplates(IsolateData* isolate_data) {
175179 NamedPropertyHandlerConfiguration config (
176180 PropertyGetterCallback,
177181 PropertySetterCallback,
178- PropertyDescriptorCallback ,
182+ PropertyQueryCallback ,
179183 PropertyDeleterCallback,
180184 PropertyEnumeratorCallback,
181185 PropertyDefinerCallback,
186+ PropertyDescriptorCallback,
182187 {},
183188 PropertyHandlerFlags::kHasNoSideEffect );
184189
185190 IndexedPropertyHandlerConfiguration indexed_config (
186191 IndexedPropertyGetterCallback,
187192 IndexedPropertySetterCallback,
188- IndexedPropertyDescriptorCallback ,
193+ IndexedPropertyQueryCallback ,
189194 IndexedPropertyDeleterCallback,
190- PropertyEnumeratorCallback ,
195+ IndexedPropertyEnumeratorCallback ,
191196 IndexedPropertyDefinerCallback,
197+ IndexedPropertyDescriptorCallback,
192198 {},
193199 PropertyHandlerFlags::kHasNoSideEffect );
194200
@@ -353,17 +359,20 @@ void ContextifyContext::RegisterExternalReferences(
353359 ExternalReferenceRegistry* registry) {
354360 registry->Register (MakeContext);
355361 registry->Register (CompileFunction);
362+ registry->Register (PropertyQueryCallback);
356363 registry->Register (PropertyGetterCallback);
357364 registry->Register (PropertySetterCallback);
358365 registry->Register (PropertyDescriptorCallback);
359366 registry->Register (PropertyDeleterCallback);
360367 registry->Register (PropertyEnumeratorCallback);
361368 registry->Register (PropertyDefinerCallback);
369+ registry->Register (IndexedPropertyQueryCallback);
362370 registry->Register (IndexedPropertyGetterCallback);
363371 registry->Register (IndexedPropertySetterCallback);
364372 registry->Register (IndexedPropertyDescriptorCallback);
365373 registry->Register (IndexedPropertyDeleterCallback);
366374 registry->Register (IndexedPropertyDefinerCallback);
375+ registry->Register (IndexedPropertyEnumeratorCallback);
367376}
368377
369378// makeContext(sandbox, name, origin, strings, wasm);
@@ -451,6 +460,51 @@ bool ContextifyContext::IsStillInitializing(const ContextifyContext* ctx) {
451460 return ctx == nullptr || ctx->context_ .IsEmpty ();
452461}
453462
463+ // static
464+ Intercepted ContextifyContext::PropertyQueryCallback (
465+ Local<Name> property, const PropertyCallbackInfo<Integer>& args) {
466+ ContextifyContext* ctx = ContextifyContext::Get (args);
467+
468+ // Still initializing
469+ if (IsStillInitializing (ctx)) {
470+ return Intercepted::kNo ;
471+ }
472+
473+ Local<Context> context = ctx->context ();
474+ Local<Object> sandbox = ctx->sandbox ();
475+
476+ PropertyAttribute attr;
477+
478+ Maybe<bool > maybe_has = sandbox->HasRealNamedProperty (context, property);
479+ if (maybe_has.IsNothing ()) {
480+ return Intercepted::kNo ;
481+ } else if (maybe_has.FromJust ()) {
482+ Maybe<PropertyAttribute> maybe_attr =
483+ sandbox->GetRealNamedPropertyAttributes (context, property);
484+ if (!maybe_attr.To (&attr)) {
485+ return Intercepted::kNo ;
486+ }
487+ args.GetReturnValue ().Set (attr);
488+ return Intercepted::kYes ;
489+ } else {
490+ maybe_has = ctx->global_proxy ()->HasRealNamedProperty (context, property);
491+ if (maybe_has.IsNothing ()) {
492+ return Intercepted::kNo ;
493+ } else if (maybe_has.FromJust ()) {
494+ Maybe<PropertyAttribute> maybe_attr =
495+ ctx->global_proxy ()->GetRealNamedPropertyAttributes (context,
496+ property);
497+ if (!maybe_attr.To (&attr)) {
498+ return Intercepted::kNo ;
499+ }
500+ args.GetReturnValue ().Set (attr);
501+ return Intercepted::kYes ;
502+ }
503+ }
504+
505+ return Intercepted::kNo ;
506+ }
507+
454508// static
455509Intercepted ContextifyContext::PropertyGetterCallback (
456510 Local<Name> property, const PropertyCallbackInfo<Value>& args) {
@@ -695,13 +749,70 @@ void ContextifyContext::PropertyEnumeratorCallback(
695749 if (IsStillInitializing (ctx)) return ;
696750
697751 Local<Array> properties;
698-
699- if (!ctx->sandbox ()->GetPropertyNames (ctx->context ()).ToLocal (&properties))
752+ // Only get named properties, exclude symbols and indices.
753+ if (!ctx->sandbox ()
754+ ->GetPropertyNames (
755+ ctx->context (),
756+ KeyCollectionMode::kIncludePrototypes ,
757+ static_cast <PropertyFilter>(PropertyFilter::ONLY_ENUMERABLE |
758+ PropertyFilter::SKIP_SYMBOLS),
759+ IndexFilter::kSkipIndices )
760+ .ToLocal (&properties))
700761 return ;
701762
702763 args.GetReturnValue ().Set (properties);
703764}
704765
766+ // static
767+ void ContextifyContext::IndexedPropertyEnumeratorCallback (
768+ const PropertyCallbackInfo<Array>& args) {
769+ Isolate* isolate = args.GetIsolate ();
770+ HandleScope scope (isolate);
771+ ContextifyContext* ctx = ContextifyContext::Get (args);
772+ Local<Context> context = ctx->context ();
773+
774+ // Still initializing
775+ if (IsStillInitializing (ctx)) return ;
776+
777+ Local<Array> properties;
778+
779+ // By default, GetPropertyNames returns string and number property names, and
780+ // doesn't convert the numbers to strings.
781+ if (!ctx->sandbox ()->GetPropertyNames (context).ToLocal (&properties)) return ;
782+
783+ std::vector<v8::Global<Value>> properties_vec;
784+ if (FromV8Array (context, properties, &properties_vec).IsNothing ()) {
785+ return ;
786+ }
787+
788+ // Filter out non-number property names.
789+ std::vector<Local<Value>> indices;
790+ for (uint32_t i = 0 ; i < properties->Length (); i++) {
791+ Local<Value> prop = properties_vec[i].Get (isolate);
792+ if (!prop->IsNumber ()) {
793+ continue ;
794+ }
795+ indices.push_back (prop);
796+ }
797+
798+ args.GetReturnValue ().Set (
799+ Array::New (args.GetIsolate (), indices.data (), indices.size ()));
800+ }
801+
802+ // static
803+ Intercepted ContextifyContext::IndexedPropertyQueryCallback (
804+ uint32_t index, const PropertyCallbackInfo<Integer>& args) {
805+ ContextifyContext* ctx = ContextifyContext::Get (args);
806+
807+ // Still initializing
808+ if (IsStillInitializing (ctx)) {
809+ return Intercepted::kNo ;
810+ }
811+
812+ return ContextifyContext::PropertyQueryCallback (
813+ Uint32ToName (ctx->context (), index), args);
814+ }
815+
705816// static
706817Intercepted ContextifyContext::IndexedPropertyGetterCallback (
707818 uint32_t index, const PropertyCallbackInfo<Value>& args) {
0 commit comments