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 10:02:43 PDT 2013
On Fri, May 24, 2013 at 9:27 AM, Jason Orendorff
<jason.orendorff at gmail.com> wrote:
> Map-like objects people will want include:
> - something that looks like a Map, but backed by something other than
> [[MapData]], like DOM attributes, a JS object's properties, a hash table
> that doesn't retain entry order, or a key-value store;
> - an observable Map;
> - a Map that generates new entries, with default values, if you .get() a
> key that isn't in the map (cf Ruby Hash#default_proc);
> - an immutable Map;
> - a Map that type-checks values, as well as keys;
> - a Map with different GC semantics.
> Tab, is your present use case in CSS Variables (key coercion) the one common
> use case worth addressing? How would we know? Alternatively, can we cover
> all the likely needs by adding hooks?
I don't know about GC semantics (that sounds like something that
really should be built in as something new, like WeakMap), but all the
rest sound totally reasonable, and exactly the kinds of things that
DOM and related APIs will want as they start using real Maps. All of
those exist, today, as various object-based or ad-hoc Map-like APIs.
(Well, I don't know if there's any web API that does the "default
value if you get a nonexistent key" thing, but *I* use defaultdict
*all the time* in Python (and reinvented it in PHP for my own use),
and if there was a way to do that in JS, I'd jump on it.)
> Counterproposal: address this in WebIDL. Add a magic [Maplike] tag that
> means something like:
> - the prose for this interface includes an algorithm for computing the
> list of this object's entries (as key-value pairs, like [[MapData]])
> - the prototype for this interface has methods has, get, forEach, entries,
> keys, and values (and a .size accessor property), and they are defined in
> terms of that algorithm unless the prose says otherwise
> - the prose for this interface includes algorithms for adding and deleting
> entries from this object
> - the prototype for this interface has methods set, delete, and clear,
> defined in terms of that algorithm unless the prose says otherwise
> It would be shorthand for making non-Map objects that walk and quack like a
> Map. From the spec author's perspective, this would eliminate most of the
> boilerplate, and it seems more flexible than hooks.
> All the methods (and the .size getter) would be non-generic, so there would
> be no danger of one type of Map being corrupted by someone .apply()ing a
> method from another type of Map.
> (Maybe this can be done with a Maplike interface and implements-statements
> instead—I don't really know WebIDL.)
This would also be completely acceptable, since it centralizes the
"act like a Map" to WebIDL, rather than distributing it across every
spec. It's just like today's getter/setter/etc keywords in WebIDL,
which map to Proxy operations using some very simple spec prose.
The only additional detail I'd want is for Map to be on the prototype
chain, so methods that authors add to Map show up on these objects as
well. It just wouldn't run the Map constructor on the object, so it
never sprouts a [[MapData]] that can be corrupted.
It's not the *best* solution, because the easy magic is only there for
spec authors, but it's the best so far.
More information about the es-discuss