Skip navigation.

miscoded

the web is a hack

jQuery relies on function decompile, won't work on Opera mobile

, , ,

A colleague just noticed that the otherwise excellent jQuery JS library has an "isFunction" method that relies on decompiling functions to figure out if they really, really are functions. This is not a good idea because decompiling functions is an optional feature of the ES-262 spec. It is slow and requires too many resources for certain low-end platforms, so it is not supported by any of the Opera Mobile versions.

Here's the code, complete with a frustrated comment from John Resig himself:
// This may seem like some crazy code, but trust me when I say that this
// is the only cross-browser way to do this. --John
isFunction: function( fn ) {
return !!fn && typeof fn != "string" && !fn.nodeName && 
fn.constructor != Array && /function/i.test( fn + "" );
}


John, I feel your pain and that code clearly took quite some effort and testing across various browsers passing in various types of objects - IE collections allowing ()-reference, anyone? It wouldn't surprise me if Opera is one of the culprits that caused you problems here since we try to support some of IE's weirdness and hence "typeof" sometimes returns 'function' when you'd expect it not to.

So I'm sorry to break it to you, but /function/i.test( fn + "" ) won't do what you think on Opera's mobile versions, causing really-hard-to-track-down bugs.

May I suggest adding the below workaround somewhere?
if( (function(){}).toString().match(/\^[ecmascript/i) ) Function.prototype.toString = function(){return 'function'};


Should be all you need..

RSnake wants your briefest self-replicating snippetSite patching updates

Comments

HeroreV 14. January 2008, 22:44

Where does Ecma-262 say that Function.prototype.toString() is optional? Because I'm not seeing that.

If this has been causing so many problems, why not have it return something like:
function () { [function 1234567] }
Where the number is unique? That would be fast and satisfy most of the uses I've heard of.

hallvors 15. January 2008, 02:57

Hm.. I've been told by almighty developers that it was optional. What I see in the spec is a bit ambiguous: section 15.3.4.2 says that Function.prototype.toString output is "implementation dependent" but reading more closely the same paragraph says that it "has the syntax of a FunctionDeclaration". So we're actually wrong to output "[ecmascript code]" but we can output "function dontdecompileme(){}" and the spec is satisfied :-p

The unique string suggestion is useful. I think we should do that for mobile. (off to update the bugs..)

thinkdrastic 15. January 2008, 10:36

I take it you'll be reporting this on the jQuery bug tracker? :smile:

http://dev.jquery.com/

Andrew Gregory 15. January 2008, 12:02

Just thinking "out loud" as it were... could Function.prototype.toString return not just a unique ID, but something able to be eval()d to a working function equivalent to the original function? ... I don't know... "function f(){return opera.getFunction(1234567).call(this,arguments);}". I'm not even sure if that sort of thing is possible?

hallvors 16. January 2008, 15:19

Filed trac report on dev.jquery, thanks for reminder to do so.

artyname 17. January 2008, 12:25

Actually prototype.js also relies on function decompile to parse names of function arguments. Thus some advanced inheritance techniques of this library won't work on mobile devices. Probably this problem may be solved this way:

function (arg1, arg2, arg3...) { [function 1234567] }

_Grey_ 18. January 2008, 18:17

@hallvord: I think it's not Opera supporting IE's weirdness that's the problem there... I think the main problem is that DOM methods in IE are in fact COM methods and of type "object" not of type "function". I don't know why there isn't a check for "typeof fn == 'function' ", though, so there may be other problems, too.

I personally would replace the COM methods in IE in this case, with real ecmascript functions (wrapped around the native "objects"). I'm not sure if this is in line with JQuery policies though...

Anonymous 13. January 2009, 02:22

Lox writes:

Opera Mobile doesn't support prototype.js either.

haavard 27. January 2009, 15:57

"Opera Mobile" is a pretty broad target. Are you referring to Opera Mobile 8.65 or Opera Mobile 9.5? Or something else?

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