A Proposal For Formalizing __noSuchMethod__ in ECMAScript 3.1.

William Edney bedney at technicalpursuit.com
Sun Aug 17 19:31:28 PDT 2008


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:

https://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;

				alert('No such method:\n' +
					'Target Object: ' + this + '\n' +
					'Target Object Constructor: ' + this.constructor + '\n' +
					'Method Name: ' + methodName + '\n' +
					'Args: ' + sentArgs.join(', ') + '\n' +
					'Call context (arguments object) callee: ' + arguments.callee +  
'\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:

1. The methodName is supplied to this method. This is required to  
determine the actual method name of the method being dispatched.

2. 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'  
- was removed in ECMAScript E3).

3. The actual 'arguments' object to this backstop hook are supplied  
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,

- Bill Edney and Scott Shattuck
- Technical Pursuit, Inc.


More information about the Es-discuss mailing list