On May 5, 2009, at 3:09 PM, Allen Wirfs-Brock wrote:
My comfort level in this starts to fall significantly as we get into
the hit or miss space. That is the point it suddenly feels like it
is trying to be (or should be trying to be) a complete meta-object
protocol rather than just a reification of failed property accesses.
The former is interesting but I think it is much harder to justify,
design, and efficiently implement than the latter. For now, I'm not
convinced that we have a compelling need for the full meta-object
protocol. If nothing else designing a simple catch all handler model
is good practice for designing a full MOP.
Agreed, but here we are. Meet Scott Isaacs and Web Sandbox :-).
We need to be pragmatic or the design could be cut down too far. I
completely agree that we shouldn't slide down the slippery slope; my
"Art of the Meta-Object Protocol" is in a box somewhere for a
reason ;-). But real-world use-cases are pressing upon us.
Other than creeping toward being a MOP, my main concern is that the
current design proposal just feel like it is getting too complex
(needing to know which are hit or miss only operations, needing to
understand how language level operations decompose into sequences of
meta level operations). In addition, I think the terminology should
better reflect the common user level understanding of the language.
That would prefer "get" or "getValue" (or [[Get]] or GetValue? :-P).
The spec language and common user-level understanding are miles if not
light-years apart.
A simpler model would only have these handlers
assign called on any explicit assignment to a non-existent property
Still does not connote "non-existent".
invoke called on any call to a non-existent property
I am with you, although the above objection stands, and
doesNotUnderstand, method_missing, and __noSuchMethod__ (ignoring __
ugliness) all have their strong points.
construct called anytime new is used with a non-existent property
Ditto last comment.
delete delete a non-existent property
Sure (hard to care about this case), but the ability to use catchalls
to emulate arrays may be an important use-case for virtualizing
systems. If delete can't be handled for existent properties then
length can't be updated.
getValue called on any implicit or explicit non-existent property
access to that is not one of the above
What is an implicit property access other than the above? I added
"has" because property lookup does not getValue, and must not, but
unless you ignore catchalls on the global object and objects named by
with statement heads, you need "has" too.
At most one of the above is called on any property reference, and
only if the property does not exist.
Besides making it impossible to virtualize arraylikes, this will make
virtual DOMs hard to implement efficiently.
I thought a bit about various schemes for dealing with catch alls
along the prototype chain but the complexity rapidly grows.
Yes, we do not want to go up the proto chain twice, or any such thing.
I concluded that it is probably better to just let a handler set
implement its own prototype lookup logic if it wants to allow for
prototype inheritance of catch all provided properties (that also
supplies a use case for Object.create(null))
Right, that was the ES4 design's decision too.
But we need DefaultAction to avoid recursive divergence on the direct
("own") object.
Does this provide enough to support your E4X scenario?
No, but thinking about it more, that scenario needs invoke to be
called not only for missing property reference, but also for non-
callable value in an existing property. See the <room> example. That
is *not* how __noSuchMethod__ works in SpiderMonkey:
js> o = {p:1, __noSuchMethod__: function (id, args) { print(id,
uneval(args)); }}
[object Object]
js> o.p
1
js> o.p()
typein:3: TypeError: o.p is not a function
js> delete o.p
true
js> o.p()
p []
js> o.p(1,2,3)
p [1, 2, 3]
So perhaps invoke could be for non-callable (including non-existent,
i.e., imputed-undefined-value) properties.
/be
Allen
-----Original Message-----
From: Brendan Eich [mailto:[email protected]]
Sent: Tuesday, May 05, 2009 11:32 AM
To: Allen Wirfs-Brock
Cc: es-discuss Steen
Subject: Re: Improving ECMAScript as a compilation target
On May 5, 2009, at 12:26 AM, Brendan Eich wrote:
Still, as noted for delete above, full virtualization might want
every- and first- forms of all of the hooks. Instead of the add/set
split I wrote up, we could drop add and split all the hooks in two,
burdening the uncommon case with the longer name (everySet and set;
blech). I'm resisting this, it feels overdesigned, besides making
for ugly names.
The current design tries to distinguish hooks run for every access
(whether or not the property exists) from those run only if the
property does not exist:
hit or miss: get, set, delete
miss only: has (before get), add (before set)
miss at least: invoke, construct
Thus has : get :: add : set. If you want a hook that is called when a
property not in the object is about to be the subject of a get, use
has. If you want to hook into property creation via set of an id for
which no property exists in the object, use add. In any case, get and
set are always called.
The symmetry breaks because DefaultAction for set is to create the
missing property, whereas for get it is to return undefined. But this
symmetry break could help minimize the API and avoid a "has" hit/miss
hint arguments, getHit/getMiss, etc., hooks.
Because of its boolean result, delete should probably be called
whether or not the property exists. Again this design intentionally
shies away from deleteHit/deleteMiss hook bloat.
The case for invoke based on __noSuchMethod__/doesNotUnderstand/
method_missing is analogous to has for get and add for set. But again
this does not allow self-hosting E4X (something you may not care
about, but I do, since SpiderMonkey's E4X implementation should be
self-hosted to reduce code size and attack surface) and things like
it. There's no corresponding "hit or miss", always-called hook for
invoke, if we stick to this course.
I surmise that construct is in the same category as invoke, but I
could be wrong.
Alternative scheme, which still avoids requiring method cons'ing/
memoizing:
hit or miss: get, set, delete, invoke, construct
miss only: has, getMiss, setMiss, deleteMiss, invokeMiss,
constructMiss
Rationale: has is still useful when we do want to reify for whatever
reason; invokeMiss is __noSuchMethod__; the short names work for the
universal if not always-most-common cases.
/be
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss