Skip navigation.

miscoded

the web is a hack

spot a subtle JS error here..

, , ,

The other day I ran into weird errors while editing the Y!Mail patch in browser.js. The whole thing stopped working, and it took me a while to see the problem. Can you see it?

// need to fake someMethod
Element.prototype.someMethod=function(){
    // faking someMethod here
}
// we also have an insertBefore problem so let's fix that too
(function(oF){
    // tweaking insertBefore here
})(Element.prototype.insertBefore);


What was wrong? Hats off if you can see it without running the code.. :smile:

how to use or survive WebForms2event capture explained

Comments

RobbieGee 5. October 2006, 22:01

I believe it's lacking a semicolon after the first anonymous function declaration.

No, I was wrong, linebreak should save that.

RobbieGee 5. October 2006, 22:17

AHA! Wait a second, it is related to the semicolon!

What will happen is that Element.prototype.someMethod will contain what was returned from function(){ something } with the argument to that being the result from the second anynomous declaration.

Correct? :-)

RobbieGee 5. October 2006, 22:25

Just to expand so my thinking is clearer to others that might read this, the interpreter will compute the result as follows:

1. Element.prototype.someMethod is to be filled, to know with what, we must compute the next statement.
1.1 function(){ faking someMethod here } is being returned as an object, but it is followed by a parenthesis, indicating we want to call that function right away.
1.1.1 In order to compute the parameter, we must compute what function(Element.prototype.insertBefore){tweaking insertBefore here} returns, which is null
1.2 We can now find what function(){faking sometMethod) returns by giving it the parameter 'null' - which it ignores and returns null.
2. Element.prototype.someMethod is now null

cwolves 5. October 2006, 22:40

Or to put it simplier (I hope)...

The 2nd function is being passed as an argument to the first because of the parenthesis and lack of semi-colon. Removing the parenthesis or adding the semi-colon should fix it.

hallvors 5. October 2006, 22:44

You're basically right. (AFAIK in your 1.1.1 above is wrong because the "insertBefore" function isn't run at this point but simply passed as an argument to the someMethod function).

It took me a while to understand this issue - sort of masked by all the lines of comments between the blocks, and by the fact that in many of the redefined functions I'm just passing arguments on to the real function without knowing what they are so it was very non-obvious where to start looking in the big Y!Mail scripts when a function that expected an HTML element received a function object :wink:

Shows why optional semi-colons maybe wasn't a good idea - they become really weird bugs in the few cases where they aren't in fact optional after all..

RobbieGee 5. October 2006, 23:03

hallvors (and cwolves): You're right about 1.1.1 being wrong, testing it reveals that the entire function object is being passed as a parameter. I just figured that it would go on forever as long as there were more parenthesis'. Good job finding this doozy! I'm learning so much from all this, please keep posting :-)

However, next time we meet I'm going to demand that you tip your hat at me as promised ;-P

cwolves 6. October 2006, 02:57

RobbieGee -

What's actually happening is that the 2nd function is getting passed as a parameter to the 1st. The next set of parenthesis (Element.prototype.insertBefore) is being passed as a parameter to the result of the first function. Since the first function doesn't return a function itself, you should get an error. And actually if the 2nd set of parenthesis wasn't there, the problem would have probably never been noticed.

x=function(a){
return function(b){ alert(a+b); }
}

(a=5)(b=6);

Also note that this only happens because you're assigning the first function to a variable. If the first function was just a function (wasn't a prototype), this wouldn't happen.

xErath 6. October 2006, 04:27

insertBefore is declared in Node, not Element :smile:

I came up with the exact same problem when making my syntax highlighter script. Now to avoid problems I ALWAYS place semicolons where there can be one.

feldgendler 6. October 2006, 05:28

I wonder why they made the semicolons optional -- to make the grammar slightly more ambiguous?

hallvors 7. October 2006, 15:02

Bonus points to xErath for noticing a second bug - just typing in the demo for the sake of the post, I knew I should have copied and pasted it ;-)

feldgendler: simply to make it easier for beginners. It is in fact quite a lot easier to get things working when the browser forgives you for forgetting a semi-colon - in theory it is a great feature for a newbie-gentle scripting language.

feldgendler 9. October 2006, 07:58

If semicolons were strictly required, a missing semicolon would be a bug which can be spotted at the very first run. In reality, a missing semicolon in an obscure place like this is a bug which can take hours to locate.

cwolves 13. October 2006, 14:40

Although I've never encountered this before in my own code, I amazingly enough just ran into it, only what, a week after your post? Took me about a second to recognize, thanks to this discussion :-)


Number.prototype.NaN0=function(){return isNaN(this)?0:this;}

(function classNamespace(){
var C = function() {
...

:-)

feldgendler 15. October 2006, 07:36

Does the ECMAScript spec define how to handle such ambiguities? I didn't dive so deeply into the spec.

xErath 8. November 2006, 06:18

Does the ECMAScript spec define how to handle such ambiguities? I didn't dive so deeply into the spec.


It's not an ambiguity. Removing uneeded white-space revals
function(...){
...
}( ... )
So you're clearly declaring a function, and calling it at the same time.

It's a matter of perspicacity.

feldgendler 10. November 2006, 06:04

expression
(expression)

can be interpreted either as a function call or as two statements between which a semicolon has been omitted. Here is the amiguity.

hallvors 21. November 2006, 01:44

xErath: what does perspicacity mean? Lovely word :smile:

_Grey_ 25. November 2006, 15:17

Hallvors. You should be an idol :wink:

Double-click "perspicacity" in xErath's post, rightclick highlighted text, choose "Dictionary" and you're done P:

hallvors 29. January 2007, 11:54

Live and re-learn :-p. Thanks

How to use Quote function:

  1. Select some text
  2. Click on the Quote link

Write a comment

Comment
(BBcode and HTML is turned off for anonymous user comments.)

If you can't read the words, press the small reload icon.


Smilies