A Proposal For Formalizing __noSuchMethod__ in ECMAScript 3.1.
On Aug 17, 2008, at 7:31 PM, William Edney wrote:
It is a property on Object.prototype
Actually it's not implemented anywhere by a built-in. The
noSuchMethod name is accessed only when a method call would
otherwise fail because of a primitive-type callee. So, the built-in
is the magic name and attempt to get its value as a "last ditch"
invocation effort. Note that noSuchMethod works for constructor
calls too.
Hope this helps,
This is currently a SpiderMonkey-only extension and we are proposing that it be incorporated into ECMAScript 3.1.
For what its worth, the current rhino engine also supports noSuchMethod. Though I wonder if it makes much of a difference since server-side js still seems to be the poor cousin that everyones keeps forgeting to invite to the party.
Maks.
Maks -
My apologies. I was unaware that Rhino also implemented
noSuchMethod. That's great - the more the merrier.
We've also communicated our desire to have a noSuchMethod
implementation to the team currently doing the excellent Squirrelfish
work for Webkit, so maybe we'll see an implementation there too :-).
Bill and Scott,
I haven't discussed this with anybody else working on the ES3.1 specification so the following is just my opinion. However, it is the position I will take when we discuss the proposal, so here it is:
"Catch Alls" (this is the term that was used by the ES4 designers for this functionality) is something that should be investigated for ES-Harmony but is not something that should be considered for ES3.1.
The primary reason for this conclusion is that we have set a hard deadline of the end of this years for completion of the ES3.1 specification and there would be significant work with unknown impacts required to incorporate the proposed "noSuchMethod" functionality into the specification. The immediate needs for the functionality does not appear to be great enough or broad enough to put the schedule at risk.
Some of my specific issues with the proposal that I think need further work include:
Why just methods? A common use of this sort of functionality is to "proxy" or otherwise emulate the public surface area of an object. This proposal doesn't do it. What about handling access to non-existent data properties (or getters/setters which amount to the same thing)? It seems like we should have a complete solution that works will all kinds of properties, not just "methods" calls.
Another way to say the above, in ES3.0/3.1 specification terminology is: Is it invocation of missing "methods" that we want to handler on a per object basis or is it the reference error conditions in GetValue/PutValue (Section 8.7). Should the handler be expected to complete the operation (method call or data property get/set) or might it just return a replacement Reference value. (This would require reifying References up to the user program level, but it might be the right approach if we also want to enable emulation using ECMAScript code of host object methods that return Reference values).
The full semantics of the feature needs to be expressed in the "formalism" of the ES3.1 specification (or latter the Harmony formalism). This will be necessary of inclusion in the specification but also for fully understanding the proposed semantics.
Is looking for a methods named "noSuchMethod" (or any or name we decided upon) actually the best approach to exposing this function. A known problem with this approach is that it makes it difficult to proxy objects that themselves implement a "noSuchMethod" method. Other approach may or may not have similar problems but we should explore them to be sure one way or another.
ES3.1 has started to try to more clearly distinguish meta operations upon objects (by making them function properties of Object) from normal application object operations. Defining a "noSuchMethod" handler feels like such a meta operations. Perhaps they should only be created via such a function).
Do we understand the security implications?
Do we understand possible performance implications particularly relating to various forms of caching that an implementation might want to do internally?
Are there any interactions with proposed "strict mode" restrictions in ES3.1?
How "future proof" is it relative to other features that are likely to be proposed for Harmony?
Etc.
Seriously, I'm not just trying to just blow you guys off. These are the sort of things I would want to work through before committing this feature to ES3.1 and I know that I don't have the time to do it and work on other things I have to get done for the 3.1 spec. I'd love to see somebody start to work through such details and discuss them here. But I think Harmony is the version you should be targeting.
2008/8/19 Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com>:
Some of my specific issues with the proposal that I think need further work include:
Yet another issue is that noSuchMethod does not work with call/apply. That is, in foo.bar.call(foo) noSuchMethod is not invoked as the engine treats foo.bar as an ordinary property access operation and returns undefined when the property bar does not exist.
To make foo.bar work with the call method one needs special search-only-for-functions operation, like foo.function::bar, which is another SpiderMonkey extension. But this is not transparent as the existing code has to be modified to use the new operation, not the familiar foo.bar. So a generic mechanism, like the catchAll proposal, to proxy arbitrary property access would be more appropriate.
, Igor
On Tue, Aug 19, 2008 at 2:09 AM, Igor Bukanov <igor at mir2.org> wrote:
[...] So a generic mechanism, like the catchAll proposal, to proxy arbitrary property access would be more appropriate.
I agree with need for some kind of generic catchAll, and with the objections to noSuchMethod. I also agree that it's too late for any such thing to make it into ES3.1.
As we discussed in Oslo, I expect there will need to be a significant version between ES3.1 and ES-Harmony. For purposes of discussion here, I will call it ES3.2. The most important difference between ES3.1 and ES3.2 is in the form of the spec, rather than its content. As Brendan says in his Harmony note, we wish to transition the spec formalism to SML+self hosting (along with corresponding changes to the RI).
For additions like catchAlls, whose semantics are likely to be tricky, a major benefit of postponing them to ES3.2 is that the more principled spec formalism is also more likely to reveal subtle semantic difficulties. That said, we should continue to speculate informally of course on what catchAlls should look like.
The java.lang.reflect.Proxy mechanism, the E proxy wiki.erights.org/wiki/Proxy, and the AmbientTalk/2 Mirage prog.vub.ac.be/Publications/2007/vub-prog-tr-07-16.pdf are
all similar, and have all been used to build semi-transparent distributed object systems within the language. I think these ideas can be adapted well to EcmaScript, and would also enable transparent intermediation (such as membranes) between untrusted code and host objects. I hope to post some ideas along these lines soon.
On Aug 19, 2008, at 7:48 AM, Mark S. Miller wrote:
On Tue, Aug 19, 2008 at 2:09 AM, Igor Bukanov <igor at mir2.org> wrote:
[...] So a generic mechanism, like the catchAll proposal, to proxy arbitrary property access would be more appropriate.
I agree with need for some kind of generic catchAll, and with the objections to noSuchMethod. I also agree that it's too late for any such thing to make it into ES3.1.
As we discussed in Oslo, I expect there will need to be a significant version between ES3.1 and ES-Harmony.
It's not clear what ES-Harmony is, but the main idea is a major
successor using a better specification technique, with new syntax
where appropriate, and some new semantics if we agree (new Name, e.g.).
We did not lay out a roadmap including two successors, for sure. That
is, we did not agree to do a 3.2. So I think it's premature to assign
any 3.x version right now. The work is the thing, not the staging
into manageable specs.
Thanks for the pointers to proxy and membrane work. Many
implementations have wrappers of various kinds already. Then there
was the ES4 catchalls proposal, which if you ignore namespaces can be
used as an informative source along with the other precedents. The
trick will be synthesizing a proposal that handles the common cases.
In this light, noSuchMethod may not be fit for standardization as
is, but it covers the Smalltalk-style doesNotUnderstand use cases of
TIBET (Bill Edney and Scott Shattuck).
2008/8/19 Brendan Eich <brendan at mozilla.org>:
On Aug 19, 2008, at 7:48 AM, Mark S. Miller wrote:
As we discussed in Oslo, I expect there will need to be a significant version between ES3.1 and ES-Harmony.
It's not clear what ES-Harmony is, but the main idea is a major successor using a better specification technique, with new syntax where appropriate, and some new semantics if we agree (new Name, e.g.). We did not lay out a roadmap including two successors, for sure. That is, we did not agree to do a 3.2. So I think it's premature to assign any 3.x version right now. The work is the thing, not the staging into manageable specs.
I agree, and I had not meant to imply otherwise. My text above was precise but confusing: "As we discussed ... I expect ...". Thanks for the clarification.
When I try to imagine the process, personally, I do expect that there will need to be a stage between the two -- in order to decouple the substantial changes to the spec formalism from the substantial differences between ES3.1 and ES-Harmony. But as you say, there was no general agreement or disagreement on what the staging should be between ES3.1 and ES-Harmony. Nor does there need to be at this point.
Thanks for the pointers to proxy and membrane work. Many implementations have wrappers of various kinds already. Then there was the ES4 catchalls proposal, which if you ignore namespaces can be used as an informative source along with the other precedents.
Agreed.
A Proposal For Formalizing noSuchMethod in ECMAScript 3.1.
Introduction & History:
Many modern dynamic languages use a generic mechanism for delegation
of methods which are not understood by the target object. These
include Smalltalk ("doesNotUnderstand"), Objective-C ("forward::") and
Ruby ("method_missing").
At Technical Pursuit, Inc. we found this mechanism to be extremely
useful and in 2003 requested that this functionality be added to the
SpiderMonkey open source JavaScript engine. It was implemented that
year, as detailed here:
bugzilla.mozilla.org/show_bug.cgi?id=196097
(many thanks again to Brendan Eich)
This is currently a SpiderMonkey-only extension and we are proposing
that it be incorporated into ECMAScript 3.1.
Rationale:
Dynamic delegation is an extremely powerful tool in designing
lightweight applications whose power comes from avoiding over- specification of getters, setters, and similar boilerplate. The
addition of getters and setters has helped keep boilerplate to a
minimum, but delegation through noSuchMethod can provide even more
capability.
As an example, Ruby on Rails uses this mechanism extensively to
provide powerful object querying when no such actual methods exist on
the target object:
smithEmps = Employee.find_by_last_name('Smith')
where 'find_by_last_name' isn't a real method on the Employee type,
but is dynamically redispatched after triggering the 'method_missing'
method.
Current mechanism:
As it is currently defined in Spidermonkey, the 'noSuchMethod'
functionality is implemented using the syntax for 'Mozilla-specific
extensions' - that is, as 'noSuchMethod'.
It is a property on Object.prototype that can be reimplemented
'further down' the prototype chain. Here is a 'trivial' implementation
that pops an alert() when any object in the system sends a message to
an object that the target does not understand:
Object.prototype.noSuchMethod = function (methodName, sentArgs) { var targetObj;
'\n' + 'Call context (arguments object) callee's caller: ' +
arguments.callee.caller); };
There are several things to note here which are of importance for this
mechanism to be truly useful:
The methodName is supplied to this method. This is required to
determine the actual method name of the method being dispatched.
The 'sent arguments' are supplied to this method. This is important
so that redispatching can occur, since obtaining the actual argument
object(s) to a method was removed from ECMAScript long ago (i.e.
'arguments.caller' - not to be confused with 'arguments.callee.caller'
and are accessible. This is important to be able to produce debugging
backtraces, if necessary, since 'arguments.callee.caller' is still
with us.
Reference Implementation:
In the ECMA committee, there has been strong desire for new language
features to have a 'reference implementation' for testing and
validation purposes. This language feature already has a reference
implementation in a very widely used JavaScript engine.
Conclusion:
We respectfully submit this codification of a very powerful, already
existing and long-tested language feature to the ECMAScript committee
for inclusion in ECMAScript 3.1. We would also volunteer for any work
that needs to be done to codify this in the specification if that
would assist in making this a reality.
Cheers,