"Subclassing" basic types in DOM - best method?

Alex Russell alex at dojotoolkit.org
Wed Nov 21 03:12:40 PST 2012


On Nov 20, 2012, at 8:08 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

> On Tue, Nov 20, 2012 at 3:28 AM, Alex Russell <alex at dojotoolkit.org> wrote:
>> Actually, looking at this IDL more closely, I see unneeded invariants
>> causing most of the problem. If URLQuery subclasses Map (assuming we make
>> this possible, which we should),
> 
> Already possible.  AWB posted code to WHATWG showing how.  The Map
> constructor is set up to respond correctly to "Map.call(this);",
> blessing the object with the appropriate Map data structure.
> 
>> it only needs to promise to hand back
>> strings, not take them. The behavior can simply be defined as toString()-ing
>> the contents when calling "getAll()". There's no reason to re-defined
>> anything about Map here or prevent the normal Map methods from taking
>> any/any as key/value pairs. That URLQuery might, in normal usage, behave
>> this way is a decision for users of the API.
> 
> Nope, that's not good enough.  For example, you have to do input
> cleanup (replacing lone surrogates with U+FFFD, escaping &, etc.)
> which affects whether two keys are "the same".  This affects set()'s
> replacing behavior, and add()'s coalescing behavior.  Heck, even
> without extra cleanup, just the fact that it requires string keys
> means you need to eagerly preserve the invariant - foo.set([1,2],
> 'bar') and foo.set('1,2', 'bar') should both set the same key.  So,
> the stringifying must be eager.

Well *that's* clearly untrue. It's possible to have any number of other behaviors than "string keys" and put your cleanups in other places (getAll(), etc.). I get that you might not want to do that, but it's a choice, and one we don't have to accept at face value.

>  Additionally, you *must* override the
> plain method anyway, since (if the URLQuery is attached to a URL), it
> synchronously adjusts the underlying URL as well.

I see.

> However, if you do a normal subclass, then people can do silly things
> like "Map.prototype.set(query, key, val);", which would skip
> URLQuery's own set() method, avoiding the invariant preservation and
> the URL manipulation.

So what? Unless there's a reason to disallow that, it seems fine by me. If people have a handle to the query object, one assumes they can already do all manner of silly things.

> We could avoid these problems by only "subclassing" in the sense that
> URLQuery.prototype = new Map();  (or Object.create(Map.prototype)),
> but not invoking the Map constructor and actually storing data in a
> closure-hidden internal Map, so instanceof would work but using Map's
> own methods wouldn't.
> 
> Or, we could ignore the whole thing, and just make sure that we
> ducktype as a Map.

That's some pretty weak sauce. Lining up the types and designing APIs in the native way is the charge, and we have to do our best by it, lest we just continue to add magic to the platform.

>  Anne is fine with either, as long as a resolution
> is forthcoming in a reasonable amount of time (more or less, only
> dependent on things that are already Harmony, such that we can just
> apply them to the spec now, even if the actual impl will be magic
> before the feature is implemented properly).
> 
> ~TJ

--
Alex Russell
slightlyoff at google.com
slightlyoff at chromium.org
alex at dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723



More information about the es-discuss mailing list