Closed
Description
- Version: master
- Platform: all
- Subsystem: vm
const globals = {};
const handlers = {};
const realHandlers = Reflect.ownKeys(Reflect).reduce((handlers, p) => {
handlers[p] = (t, ...args) => {
// Avoid printing the Receiver argument, which can lead to an infinite loop.
console.log(p, ...(p === 'get' || p === 'set' ? args.slice(0, -1) : args));
return Reflect[p](t, ...args);
};
return handlers;
}, {});
const proxy = vm.createContext(new Proxy(globals, handlers));
// Indirection needed to mitigate against #17465
// https://github.com/nodejs/node/issues/17465
const globalProxy = vm.runInContext('this', proxy);
for (const k of Reflect.ownKeys(globalProxy)) {
Object.defineProperty(globals, k, Object.getOwnPropertyDescriptor(globalProxy, k));
}
Object.assign(handlers, realHandlers);
'a' in proxy;
// prints "has a"
// returns false
vm.runInContext('"a" in this', proxy);
// prints "get a"
// returns true (because of https://github.com/nodejs/node/issues/17465)
By spec, the in
operator uses the object's [[HasProperty]] internal method, which I overrode with a Proxy trap. That's why the bare 'a' in proxy
prints has a
.
On the other hand, V8 doesn't quite support overriding [[HasProperty]] with the modern version of the NamedPropertyHandlerConfiguration
constructor, only
- [[Get]]
getter
- [[Set]]
setter
- [[GetOwnProperty]]
descriptor
- [[Delete]]
deleter
- [[OwnPropertyKeys]]
enumerator
- [[DefineOwnProperty]]
definer
Thus I would expect the default [[HasProperty]] internal method to be used, i.e. OrdinaryHasProperty, which in turns calls the object's [[GetOwnProperty]] internal method. I.e. the descriptor
should be called. Yet this isn't the case shown above -- only GenericNamedPropertyGetterCallback
is called.