Skip to content

Commit d1f18b0

Browse files
authored
vm,src: add property query interceptors
Fixes: #52720 PR-URL: #53172 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent f2f45a0 commit d1f18b0

File tree

3 files changed

+154
-2
lines changed

3 files changed

+154
-2
lines changed

src/node_contextify.cc

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ using v8::FunctionTemplate;
5151
using v8::HandleScope;
5252
using v8::IndexedPropertyHandlerConfiguration;
5353
using v8::Int32;
54+
using v8::Integer;
5455
using v8::Intercepted;
5556
using v8::Isolate;
5657
using v8::Just;
@@ -176,20 +177,22 @@ void ContextifyContext::InitializeGlobalTemplates(IsolateData* isolate_data) {
176177
NamedPropertyHandlerConfiguration config(
177178
PropertyGetterCallback,
178179
PropertySetterCallback,
179-
PropertyDescriptorCallback,
180+
PropertyQueryCallback,
180181
PropertyDeleterCallback,
181182
PropertyEnumeratorCallback,
182183
PropertyDefinerCallback,
184+
PropertyDescriptorCallback,
183185
{},
184186
PropertyHandlerFlags::kHasNoSideEffect);
185187

186188
IndexedPropertyHandlerConfiguration indexed_config(
187189
IndexedPropertyGetterCallback,
188190
IndexedPropertySetterCallback,
189-
IndexedPropertyDescriptorCallback,
191+
IndexedPropertyQueryCallback,
190192
IndexedPropertyDeleterCallback,
191193
PropertyEnumeratorCallback,
192194
IndexedPropertyDefinerCallback,
195+
IndexedPropertyDescriptorCallback,
193196
{},
194197
PropertyHandlerFlags::kHasNoSideEffect);
195198

@@ -354,12 +357,14 @@ void ContextifyContext::RegisterExternalReferences(
354357
ExternalReferenceRegistry* registry) {
355358
registry->Register(MakeContext);
356359
registry->Register(CompileFunction);
360+
registry->Register(PropertyQueryCallback);
357361
registry->Register(PropertyGetterCallback);
358362
registry->Register(PropertySetterCallback);
359363
registry->Register(PropertyDescriptorCallback);
360364
registry->Register(PropertyDeleterCallback);
361365
registry->Register(PropertyEnumeratorCallback);
362366
registry->Register(PropertyDefinerCallback);
367+
registry->Register(IndexedPropertyQueryCallback);
363368
registry->Register(IndexedPropertyGetterCallback);
364369
registry->Register(IndexedPropertySetterCallback);
365370
registry->Register(IndexedPropertyDescriptorCallback);
@@ -458,6 +463,51 @@ bool ContextifyContext::IsStillInitializing(const ContextifyContext* ctx) {
458463
return ctx == nullptr || ctx->context_.IsEmpty();
459464
}
460465

466+
// static
467+
Intercepted ContextifyContext::PropertyQueryCallback(
468+
Local<Name> property, const PropertyCallbackInfo<Integer>& args) {
469+
ContextifyContext* ctx = ContextifyContext::Get(args);
470+
471+
// Still initializing
472+
if (IsStillInitializing(ctx)) {
473+
return Intercepted::kNo;
474+
}
475+
476+
Local<Context> context = ctx->context();
477+
Local<Object> sandbox = ctx->sandbox();
478+
479+
PropertyAttribute attr;
480+
481+
Maybe<bool> maybe_has = sandbox->HasRealNamedProperty(context, property);
482+
if (maybe_has.IsNothing()) {
483+
return Intercepted::kNo;
484+
} else if (maybe_has.FromJust()) {
485+
Maybe<PropertyAttribute> maybe_attr =
486+
sandbox->GetRealNamedPropertyAttributes(context, property);
487+
if (!maybe_attr.To(&attr)) {
488+
return Intercepted::kNo;
489+
}
490+
args.GetReturnValue().Set(attr);
491+
return Intercepted::kYes;
492+
} else {
493+
maybe_has = ctx->global_proxy()->HasRealNamedProperty(context, property);
494+
if (maybe_has.IsNothing()) {
495+
return Intercepted::kNo;
496+
} else if (maybe_has.FromJust()) {
497+
Maybe<PropertyAttribute> maybe_attr =
498+
ctx->global_proxy()->GetRealNamedPropertyAttributes(context,
499+
property);
500+
if (!maybe_attr.To(&attr)) {
501+
return Intercepted::kNo;
502+
}
503+
args.GetReturnValue().Set(attr);
504+
return Intercepted::kYes;
505+
}
506+
}
507+
508+
return Intercepted::kNo;
509+
}
510+
461511
// static
462512
Intercepted ContextifyContext::PropertyGetterCallback(
463513
Local<Name> property, const PropertyCallbackInfo<Value>& args) {
@@ -709,6 +759,20 @@ void ContextifyContext::PropertyEnumeratorCallback(
709759
args.GetReturnValue().Set(properties);
710760
}
711761

762+
// static
763+
Intercepted ContextifyContext::IndexedPropertyQueryCallback(
764+
uint32_t index, const PropertyCallbackInfo<Integer>& args) {
765+
ContextifyContext* ctx = ContextifyContext::Get(args);
766+
767+
// Still initializing
768+
if (IsStillInitializing(ctx)) {
769+
return Intercepted::kNo;
770+
}
771+
772+
return ContextifyContext::PropertyQueryCallback(
773+
Uint32ToName(ctx->context(), index), args);
774+
}
775+
712776
// static
713777
Intercepted ContextifyContext::IndexedPropertyGetterCallback(
714778
uint32_t index, const PropertyCallbackInfo<Value>& args) {

src/node_contextify.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ class ContextifyContext : public BaseObject {
9696
const errors::TryCatchScope& try_catch);
9797
static void WeakCallback(
9898
const v8::WeakCallbackInfo<ContextifyContext>& data);
99+
static v8::Intercepted PropertyQueryCallback(
100+
v8::Local<v8::Name> property,
101+
const v8::PropertyCallbackInfo<v8::Integer>& args);
99102
static v8::Intercepted PropertyGetterCallback(
100103
v8::Local<v8::Name> property,
101104
const v8::PropertyCallbackInfo<v8::Value>& args);
@@ -115,6 +118,8 @@ class ContextifyContext : public BaseObject {
115118
const v8::PropertyCallbackInfo<v8::Boolean>& args);
116119
static void PropertyEnumeratorCallback(
117120
const v8::PropertyCallbackInfo<v8::Array>& args);
121+
static v8::Intercepted IndexedPropertyQueryCallback(
122+
uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& args);
118123
static v8::Intercepted IndexedPropertyGetterCallback(
119124
uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& args);
120125
static v8::Intercepted IndexedPropertySetterCallback(
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const vm = require('vm');
5+
6+
const sandbox = {
7+
onSelf: 'onSelf',
8+
};
9+
10+
function onSelfGetter() {
11+
return 'onSelfGetter';
12+
}
13+
14+
Object.defineProperty(sandbox, 'onSelfGetter', {
15+
get: onSelfGetter,
16+
});
17+
18+
Object.defineProperty(sandbox, 1, {
19+
value: 'onSelfIndexed',
20+
writable: false,
21+
enumerable: false,
22+
configurable: true,
23+
});
24+
25+
const ctx = vm.createContext(sandbox);
26+
27+
const result = vm.runInContext(`
28+
Object.prototype.onProto = 'onProto';
29+
Object.defineProperty(Object.prototype, 'onProtoGetter', {
30+
get() {
31+
return 'onProtoGetter';
32+
},
33+
});
34+
Object.defineProperty(Object.prototype, 2, {
35+
value: 'onProtoIndexed',
36+
writable: false,
37+
enumerable: false,
38+
configurable: true,
39+
});
40+
41+
const resultHasOwn = {
42+
onSelf: Object.hasOwn(this, 'onSelf'),
43+
onSelfGetter: Object.hasOwn(this, 'onSelfGetter'),
44+
onSelfIndexed: Object.hasOwn(this, 1),
45+
onProto: Object.hasOwn(this, 'onProto'),
46+
onProtoGetter: Object.hasOwn(this, 'onProtoGetter'),
47+
onProtoIndexed: Object.hasOwn(this, 2),
48+
};
49+
50+
const getDesc = (prop) => Object.getOwnPropertyDescriptor(this, prop);
51+
const resultDesc = {
52+
onSelf: getDesc('onSelf'),
53+
onSelfGetter: getDesc('onSelfGetter'),
54+
onSelfIndexed: getDesc(1),
55+
onProto: getDesc('onProto'),
56+
onProtoGetter: getDesc('onProtoGetter'),
57+
onProtoIndexed: getDesc(2),
58+
};
59+
({
60+
resultHasOwn,
61+
resultDesc,
62+
});
63+
`, ctx);
64+
65+
// eslint-disable-next-line no-restricted-properties
66+
assert.deepEqual(result, {
67+
resultHasOwn: {
68+
onSelf: true,
69+
onSelfGetter: true,
70+
onSelfIndexed: true,
71+
onProto: false,
72+
onProtoGetter: false,
73+
onProtoIndexed: false,
74+
},
75+
resultDesc: {
76+
onSelf: { value: 'onSelf', writable: true, enumerable: true, configurable: true },
77+
onSelfGetter: { get: onSelfGetter, set: undefined, enumerable: false, configurable: false },
78+
onSelfIndexed: { value: 'onSelfIndexed', writable: false, enumerable: false, configurable: true },
79+
onProto: undefined,
80+
onProtoGetter: undefined,
81+
onProtoIndexed: undefined,
82+
},
83+
});

0 commit comments

Comments
 (0)