"in" operator in VM uses [[Get]] instead of [[GetOwnProperty]]
- 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.
/cc @fhinkel
@verwaest