Closed Bug 466239 Opened 16 years ago Closed 8 years ago

__noSuchMethod__ not available on the anonynous global object


(Core :: JavaScript Engine, enhancement)

Windows XP
Not set





(Reporter: geekfreak, Unassigned)



(1 file, 2 obsolete files)

User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/2008102920 Firefox/3.0.4 FirePHP/0.2.1
Build Identifier: 

A __noSuchMethod__ handler can be attached to the window object, but as a result of the way resolution happens against the anonymous global no test for the availability of __noSuchMethod__ occurs when the code takes the JSOP_CALLNAME path.

File: mozila/js/src/jsinterp.c

"new window.Bogus()" - JSOP_CALLPROP has js_OnUnknownMethod call at the end which handles __noSuchMethod__.
"new Bogus()" - JSOP_CALLNAME - doesn't.

As esoteric as this appears, I'd like to be able to use this to provide a facility equivalent to the __autoload feature of PHP in our Jaxer project. This would enable class file to be dynamically loaded by intercepting the 'new MyObj()' call, currently it will work for 'new window.MyObj()' but not for objects on that pesky anonymous global.

I realise this may be by design. but looking at the code, it just appears as if the support for __noSuchMethod__ was added to the JSOP_CALLPROP path and not the JSOP_CALLNAME.

Reproducible: Always

Steps to Reproduce:
autoHandler = function autoHandler(id,args){
	function dummy(arghh){
		this.aProperty = "not Bogus anymore "+arghh
	return new dummy(args);


window.__noSuchMethod__ = autoHandler;

var foo = new window.Bogus('foo');
alert("!! "+foo.aProperty);

var foo2 = new Bogus2('foo');
alert("!! "+foo2.aProperty);

Actual Results:  
first call to new window.Bogus() succeeds
second call to new Bogus2() throws 'Bogus2 not defined'

Expected Results:  
call to new Bogus() should trigger the __noSuchMethod__ handler.

I can assign getters and setters to the window object and have them fire from the anonymous global, so my expectation would be the same for __noSuchMethod__
davey:  Care to take a stab at a patch?
Severity: normal → enhancement
Ever confirmed: true
I've set one of our top Mozilla wranglers (Max Stepanov) on it. Should get you a patch early next week.
Here is the patch. Heavily tested in Jaxer environment.
Comment on attachment 350102 [details] [diff] [review]
Handle __noSuchMethod__ for JSOP_CALLNAME

>diff -r 5d1fbada8589 js/src/jsinterp.cpp
>+				if (JS_UNLIKELY(op == JSOP_CALLNAME)) {
>+					jsval vp[2];
>+					LOAD_ATOM(0);
>+					vp[0] = ATOM_KEY(atom);
>+					vp[1] = OBJECT_TO_JSVAL(fp->thisp);
>+					if (!js_OnUnknownMethod(cx, vp))
>+						goto error;

This is wrong since js_OnUnknownMethod assumes that the array passed to it is rooted.
Igor, your comment makes sense. Thanks!
See fixed version attached.
Attachment #350102 - Attachment is obsolete: true
The patch is just a halve-measure. Since it tries to look up __noSuchMethod__ in fp->scopeChain, it will miss __noSuchMethod__ if it is only defined in the parent of the scope chain. I.e. try with it something like:

window.__noSuchMethod__ = autoHandler;

function x()
    var foo2 = Bogus2('foo');
    alert("!! "+foo2.aProperty);


Now, there are 2 different strategies to resolve that. The first is to look for __noSuchMethod__ only in the top-most scope. The second is to look for it in each and every member of the scope chain. That is, should the following example alert "window" or "object"?

this.__noSuchMethod__ = function() { alert("window"); };

var obj = { __noSuchMethod__: function() { alert("object"); } };

with (obj) {
Thanks for suggestions, Igor.  We had a talk with Davey right before submitting v2 patch about looking for __noSuchMethod__ in the scope chain.
Here is the updated patch.
Attachment #350188 - Attachment is obsolete: true
(In reply to comment #8)
> Created an attachment (id=350258) [details]
> Handle __noSuchMethod__ for JSOP_CALLNAME (v3)

The patch does not do the proper lookup. For example, in the case like:

function handler() { alert(1); }

function f()
    var __noSuchMethod__ = handler;

the handler would not be called. 

Now, I am not sure that this is what you want. My preference would be to look up the noSuchMethod only in the top-most scope on the basis that a property is created there when one does nameThatDoesNotExist = someValue; But this is just a preference.
We don't think it should work in case of local__noSuchMethod__ variable.
What we really want to achieve is to be able to resolve nameThatDoesNotExist() as if it would be in context of 'this' (e.g new this.nameThatDoesNotExist())

We have tested variations of the following code example, and the v3 patch satisfies our needs.
this.__noSuchMethod__ = function() { alert("Level 0"); };
var level1 = { __noSuchMethod__: function() { alert("Level 1"); }};
with (level1) {
  (function() {
    var level2 = { __noSuchMethod__: function() { alert("Level 2"); }};
    with (level2) {
      (function() {
        var foo = new Bogus('foo');
(In reply to comment #8)
> Created attachment 350258 [details] [diff] [review]
> Handle __noSuchMethod__ for JSOP_CALLNAME (v3)
> Thanks for suggestions, Igor.  We had a talk with Davey right before submitting
> v2 patch about looking for __noSuchMethod__ in the scope chain.
> Here is the updated patch.

Can you please advise any  analogue of this patch for the latest version ?
The patch changes for Firefox 3.6 could be found at
No efforts has been made to make it to work in Firefox 4.0 yet.
Assignee: general → nobody
Given bug 683218 this should probably be WONTFIX.
Resolving as Won't Fix, because __noSuchMethod__ has been removed (bug 683218).
Closed: 8 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.