Why is Set Incompatible with Proxy?
JavaScript Set appears to be entirely incompatible with JavaScript proxies, attempting to Proxy()
a Set()
var p = new Proxy(new Set(), {
add(target, val, receiver) {
console.log('in add: ', target, val, receiver)
}
})
p.add(55)
results in a VMError:
Uncaught TypeError: Method Set.prototype.add called on incompatible receiver [object Object]
at Proxy.add (native)
at <anonymous>:1:3
In fact, proxying a Set()
in any way breaks it categorically - even if our proxy handler does nothing at all! Compare p = new Proxy({}, {})
vs p = new Proxy(new Set(), {})
. (This applies both in Firefox (52.0.2) and Chromium (57.0.2987.133).)
I can't seem to find a credible reference or documentation for this, why cannot JavaScript Proxy
a Set
object and why is it hitting a VM Error?
I am attempting to
Proxy()
aSet()
However, you haven't used any of the available traps - there is no add
one. All that you can intercept in the call p.add(55)
is the property access to .add
on the proxy, which goes through the get
trap and returns a function.
If you want to intercept calls to the add
method, you don't need a proxy at all, better (subclass and) overwrite that method similar to how .set
was overridden here and here for Map
.
proxying a
Set()
in any way breaks it categorically
Yes, because the proxy is not a Set
any more.
var s = new Set([42]);
var p = new Proxy(s, {});
s.has(42) // true
console.log(s === p) // false
p.has.call(s, 42) // true
p.has(42) // exception - calls `has` on `p`, not on `s`
Calling Set
methods on objects that are no True Sets does throw an exception (which e.g. can be used for detecting them). For your particular case, see ECMAScript 6 §23.2.3.1:
"If
S
does not have a[[SetData]]
internal slot, throw aTypeError
exception."
And indeed, p
is a proxy (which does have the internal Proxy methods and slots, especially [[ProxyHandler]]
and [[ProxyTarget]]
) instead of a set like s
with its [[SetData]]
internal slot.
You reasonably were expecting that "if a trap has not been defined, the default behavior is to forward the operation to the target", however that only applies to standard behaviours like property access, and not the internal slots of exotic objects.