Those tricky functions!
Are you still trying to write a regex matching decompiled function in Javascript? Perhaps, trying to detect a native method? Here’s a short but fun list of what you’ll be facing in various browsers. This is, of course, all very similar to userAgent adventures; Non-standard feature that is as reliable as my old 28K modem.
It’s probably better to abandon this idea altogether. Or at least not rely on it, and maybe use only for debugging purposes. Or, if you do like adventures after all, at least know what you’re dealing with:
Safari 1.3.x – 2.x
Does not match function expression syntax. Missing identifier.
Object; // (Internal Function)
document.getElementById; // [function]
(function foo(){ return a+b; }); // function(){ return a+b; }
Chrome 1.x
Missing identifier.
window.focus; // function () { [native code] }
Blackberry
Unique representation of function body. Source code is not available for anything but “small” functions
window.XMLHttpRequest;
// function XMLHttpRequest() { [native code for XMLHttpRequest.XMLHttpRequest, arity=1] }
function foo(){ /* ~10 lines of code */ };
// function foo() { \\Source code is not available. [1035593284ED8CD9D0734E9B14EF4F3FF6BE9686] }
Opera 10a
Missing identifier.
Array.prototype.push; // function () { [native code] }
Opera 10a Turbo Edition
Unique representation of function body.
document.getElementById; // function getElementById() { /* source code not available */ }
Caja
Unique representation of function body; Augmented identifier.
function f(){}; // function f() { [cajoled code] }
var f = function(){}; // function f$_var() { [cajoled code] }
Internet Explorer
Unique representation of function.
( /* foo bar */ (((function f(){}) /* baz qux */ ))); // ( /* foo bar */ (((function f(){}) /* baz qux */ )))
Rhino
Unique representation of function body.
({}).hasOwnProperty; // function hasOwnProperty() { [native code for Object.hasOwnProperty, arity=1] }
Mozilla-based browsers (JS1.8+)
Unique function body representation: no curly braces denoting block (when function is created via an expression closure)
String(function f(x, y) x + y); // function f(x, y) x + y
Bound functions in FF4 and WebKit
Unique function body (source code is missing)
(function(){ return x + y; }).bind(); // "function () { "[native code]" }"
Do you have any other examples of strange-looking functions? Please, share. Perhaps, PPK will tell us how other mobile browsers handle function decompilation.
- Added Internet Explorer and its “unique” function representation. Thanks Andrea Giammarchi.
- Added Rhino representation, which appears to be similar to that of Blackberry.
- Updated Safari versions to include 1.3.x (which exhibits same behavior as 2.x)
Edit (1/7/11):
- Added a note about bound functions having “[native code]” in at least 2 implementations
- Added JS 1.8 expression closure syntax
DBJ said:
#This might be on the edge of this theme. But it concerns one function that is “there” but you can not reach it.
Explanation. IE8 javascript does this is OK and as ES3 specifies.
o = {}
typeof o.f === undefined
Object.prototype.toString.call(o.f) === "[object Object]"
But … IE has ActiveX controls. We would love to ignore them. But, there is one which we have to use.
XMLHttpRequest … The problem is very subtle, and as a such it can generate very subtle bugs.
The issue is that in IE (vs others) you can not call the XMLHttpRequest. In IE it is of a type “object”.
// the source of trouble
typeof XMLHttpRequest === "object" // only in IE ?
// it can not be called
XMLHttpRequest()
/*
TypeError
Number : 5
Description : Invalid procedure call or argument
*/
// it must be new-ed, because it is an ActiveX (COM) object
new XMLHttpRequest()
// OK
And (lo and behold) this is a source of a lot of trouble and workarounds.
Especially in libraries and any trying to be generic javascript.
typeof XMLHttpRequest.toString
/* unknown */
Object.prototype.toString.call(XMLHttpRequest.toString)
/*
TypeError
Number : 438
Description : Object doesn't support this property or method
*/
IE team forgot to handle “unknown” in Object.prototype.toString.call() ?
But. Why having “unknown” at all? Why not treat it as undefined, and no confusion ?
// how IE+javascript should behave to be more "ES3"
typeof XMLHttpRequest.toString === undefined
Object.prototype.toString.call(XMLHttpRequest.toString) == "[object Object]"
Even better why not just making it a native global function ? As everybody else, as far as I know?
typeof window.XMLHttpRequest === "function"
Bad decision was made here, I am affraid : http://blogs.msdn.com/ie/archive/2006/01/23/516393.aspx
eisd said:
#DBJ:
The “unknown” type is not restricted to only the XHR object, and it is not a bug on the JScript team’s part that Object.prototype.toString.call does not handle “unknown.” The specification clearly allows for host objects, and the XHR object and other ActiveXObjects should be classified as such, and we should therefore expect the behavior to be erratic and to not necessarily follow the specification.
When the typeof operator returns “unknown” for an ActiveXObject, it means the property or method exists, but JScript does not know exactly what type it is; whereas if typeof returns “undefined,” it literally means there’s nothing there. However, typeof on a non-existent ActiveXObject property will indeed return “undefined” as per the specification.
Lastly, Object.prototype.toString.call(ArbitraryActiveX.property) won’t behave the way you expect it to behave (as the specification warns about host objects). Properties and methods of ActiveXObjects are not the same as native Javascript object properties and methods; hence why you are experiencing the aforementioned errors.