[heycam/webidl] Are operations on the `[[BackingMap]]` and `[[BackingSet]]` page-hookable? And if not, why not? (#254)

I was sure I had filed this before, but I can't find it...

Consider this testcase:

    <script>
    Object.defineProperty(Set.prototype, "size", { value: 42 });
    var set = document.fonts;
    alert(set.size);
    </script>

What should get alerted?  Per spec as currently written we end up at https://heycam.github.io/webidl/#es-set-size we end up (in step 5) doing:

> Return the result of calling the [[Get]] internal method of _set_ passing “size” and _set_ as arguments.

where _set_ is the `[[BackingSet]]` of the object.  And the `[[BackingSet]]` is defined like so:

> Any object that implements an interface that has a setlike declaration must have a [[BackingSet]] internal slot, which is initially set to a newly created Set object.

So what should get alerted?  Browsers alert 0 if there are no font-face rules.  As an implementor, I would prefer to alert 0 in general.  But if the `[[BackingSet]]` is created in the same Realm as the object itself, then you ought to get 42, right?

We should specify how this actually works.  I see three possible options:

1.  Specify that the `[[BackingSet]]` is created in the global of the IDL object, leave everything as is.  Then this testcase should alert 42, which doesn't match browsers.
2.  Specify that the `[[BackingSet]]` is created in a separate global, leave everything as is.  Then this testcase should alert 0.
3.  Specify that the `size` getter invokes the original value of the `Set.prototype.size` getter.  Then this testcase should alert 0.  Same with the various other forwarding getters.

Options 2 and 3 are _not_ black-box identical.  The reason is that `entries` will return you an iterator, and you can tell which global the `Set`'s internal `entries` function comes from by looking at the prototype of that iterator.  In fact, you can distinguish not only options 2 and 3 from each other but also different variants of option 2 (e.g. a single separate global for all interfaces, one separate global per interface, one separate global per object, etc).

My personal feeling is that we should go with option 3, with the `[[BackingSet]]` created in the IDL object's global.  That's certainly how maplike/setlike are implemented in Gecko.  Note that FontFaceSet is NOT implemented as a setlike in Gecko for the moment, though.  It looks like we ship no actual setlikes so far, and only one maplike: RTCStatsReport.  Unfortunately, I have yet to figure out how to get my hands on an RTCStatsReport to see how it behaves in other browsers...

Doing black-box testing of FontFaceSet in Blink, it looks like the iterator it returns from `entries()` doesn't have `%SetIteratorPrototype%` (from any global) as its prototype.  So Blink is not following the spec for this part either so far.  Grepping Blink's idl, this is the only setlike, and the only maplikes are the MIDIInput/OutputMaps.  Those don't use an object with `%MapIteratorPrototype%` as its proto either.  That makes it hard to tell whether Blink is doing option 2 or option 3, of course, since at least for `entries` it's not doing either one.

@tobie @domenic @heycam @annevk 

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/heycam/webidl/issues/254

Received on Monday, 12 December 2016 21:41:05 UTC