最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why is Set Incompatible with Proxy? - Stack Overflow

programmeradmin3浏览0评论

JavaScript Set appears to be entirely inpatible 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 inpatible 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?

JavaScript Set appears to be entirely inpatible 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 inpatible 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?

Share Improve this question edited Jun 3, 2023 at 18:19 dumbass 27.2k4 gold badges36 silver badges73 bronze badges asked May 12, 2017 at 1:27 user3467349user3467349 3,1915 gold badges38 silver badges64 bronze badges 9
  • There is no add trap in proxies. It looks like you're looking for a subclass, not a proxy (which is not a Set and can't be used with Set methods) – Bergi Commented May 12, 2017 at 3:33
  • @Bergi Where do you see this answered? The answer for Map does not apply to Set and neither does it explain why an empty handler will break a Set Proxy. As for the lack of a trap: is this documented anywhere? Why does an empty trap {} cause VMErrors for a Set Proxy? – user3467349 Commented May 12, 2017 at 10:47
  • No, I'm not looking for a subclass, please read the question before closing it as duplicate next time... – user3467349 Commented May 12, 2017 at 10:55
  • The explanation does apply, Maps and Sets work alike. And really, it does look like you're looking to intercept add method calls, for which subclasses are the easiest solution. – Bergi Commented May 12, 2017 at 13:17
  • I'm asked 2 questions which are clearly stated in my question (neither of which are answered in the linked to 'duplicate' questions): Where is it documented (or is it) that Proxy is inpatible with Set? Why does it cause a VMError even on an empty handler? No where in my question does it ask "how do I intercept add calls". – user3467349 Commented May 12, 2017 at 13:32
 |  Show 4 more ments

1 Answer 1

Reset to default 20

I am attempting to Proxy() a Set()

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 a TypeError 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.

发布评论

评论列表(0)

  1. 暂无评论