In What Javascript Engines Does Function.prototype.toString Not Return The Source Code Of That Function?
Solution 1:
What current Javascript engines don't behave this way?
Your question isn't really well-defined, given that you haven't defined "popular". Is IE6 popular? IE5? IE4? Netscape Navigator? Lynx? The only way to properly answer your question is to enumerate which browsers you wish to support and check them. Unfortunately kangax's table http://kangax.github.io/es5-compat-table/# doesn't test Function.prototype.toString
Chrome's console will even tell you (when you pass anything other than a function o Function.toString.call), that Function.prototype.toString is not generic
mandated in the spec
the spec refrains from making any commitment as to what the behaviour should be when applied to functions
The required behavior is specified in ECMA-262 version 1 (from 1997, http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf) You have to chase it down:
- http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.24 "function ... member of the Object type that is an instance of the standard built-in Function constructor and that may be invoked as a subroutine"
From that, we deduce that functions are objects.
- http://www.ecma-international.org/ecma-262/5.1/#sec-9.8 "Let primValue be ToPrimitive(input argument, hint String)."
So now what is ToPrimitive?
- http://www.ecma-international.org/ecma-262/5.1/#sec-9.1 " The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. "
So we need to know what DefaultValue does
- http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.8 (lots of words that basically say if the thing has a toString method, then call it)
Now we just need to find where Function.prototype.toString is described:
- http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.2 "An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent."
So you are guaranteed that you get a proper javascript representation (not some IL gobbledegook) but not necessarily with the comments. For example, the technique breaks in Firefox 16 (but then you have to ask if it is current).
Solution 2:
So Kangax has returned to the subject matter (intrigued as he was by the fact that Angular uses this hack for core functionality in client-side code) and written up an analysis of the practice, and produced a test table for the state of function decompilation in Javascript.
The takeaway points are that:
- The technique is only remotely reliable for user-defined function declarations.
- Some old mobile browsers will still collapse functional code, allegedly for performance reasons.
- Other old browsers will reveal optimized code, something like what you might get out of Closure Compiler.
- Yet others will remove comments and alter whitespace.
- Internet Explorer will occasionally add comments and whitespace around the functions.
- The AngularJS team seem to think this technique is robust enough to include in their library without explicit caveat. They then tokenize (!) the code and re-evaluate it (!!).
For my purposes, this makes me reasonably confident I can do something relatively undemanding like detect whether a function has an uppercase name or not by parsing it as follows:
/function\s*[A-Z]/.test( fn )
Post a Comment for "In What Javascript Engines Does Function.prototype.toString Not Return The Source Code Of That Function?"