Non-generic traps for non-generic objects (was: Overriding Map/etc with get/set hooks?)

Tab Atkins Jr. jackalmage at gmail.com
Fri May 24 18:28:35 PDT 2013


On Fri, May 24, 2013 at 4:14 PM, Jason Orendorff
<jason.orendorff at gmail.com> wrote:
> On Fri, May 24, 2013 at 4:52 PM, Tab Atkins Jr. <jackalmage at gmail.com>
> wrote:
>> The problem is that the Map#set method grabs an *internal property*,
>> bypassing Proxies, etc., so you can't defend against it.  If I could
>> intercept access to [[MapData]] via proxy traps (like David suggests
>> in the OP), everything would be *perfect* - every single problem I
>> have would be resolved successfully, as would every additional
>> possibility that Jason brings up.
>
> I don't see how trapping access to [[MapData]] satisfactorily solves your
> original problem. What spec text would you write?  Would you define the DOM
> object in question to be a proxy?

Oh, easy.  I'd define that, whenever you attempt to get or set
something in the map, both the key and the value are coerced to
strings before the operation proceeds.  As well, whenever you set or
delete something, the other data structure (the style rule) is updated
accordingly.

Check out the spec in question:
<http://dev.w3.org/csswg/css-variables/#the-cssvariablesdeclaration-interface>.
 I already have spec text that works *perfectly*, except that it's an
"object map"; that is, you do "style.vars.foo = bar;", not
"style.vars.set('foo', bar);".

I want to do *exactly the same thing*, except that instead of doing
something every time you get/set/create/delete a property, I want to
react to when you get/set/create/delete *a key/value pair in the map*.
 That way I use the soon-to-be-familiar Map API, and get free interop
with any code that expects to manipulate Maps.

>> If Maps used a Map.MapDataSymbol, I could intercept it via proxies by
>> adding it to the symbol whitelist and do what I needed.  Of course,
>> the object represented by [[MapData]] is too abstract to *actually* do
>> that, but we could expose some interactions for it.
>
> But that would look like... Map.
>
> So we would have turned Map into a wrapper around a [[MapData]] object
> that's what Maps are now (a concrete, non-hookable map).

Kinda.  If Maps had only four operations (get, set, delete, iterate)
and I was *guaranteed* that that's all it would ever have, I'd have no
problem just writing my own, since that's what I'll have to do in the
spec anyway.  That's what [[MapData]] kinda is - a *simplified* map
with only a handful of basic operations.

The problem is that there are further Map functions that are built as
relying directly on [[MapData]] rather than in terms of the "basic"
operations, so to replace Map, I have to redefine those as well, even
though the existing definition is perfectly adequate.

(When I wrote my own suite of collection classes, I did indeed define
a "simplified map" that was the core of the real Map class, but
couldn't be instantiated on its own.)

> It seems rather heavyweight. You can already get about the same effect just
> by writing that wrapper yourself.

As I've argued and demonstrated in these threads already, no, you
can't just do it yourself.  Every solution fails in at least some
details, usually trading security against convenience or the other way
around.  This isn't acceptable, given that I can produce a *perfect*
"object map" with existing Proxy operations.

~TJ


More information about the es-discuss mailing list