Search code examples
javascriptjsonecmascript-5

Why is toString of JavaScript function implementation-dependent?


From the EcmaScript 5 specification

15.3.4.2 Function.prototype.toString( )

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.

Why is it implementation-dependent? It shouldn't be too hard to make it output standardized string consisting of the original code of the function. Also the reasons that I can come up with such as optimization, doesn't seem to be too heavily used as pretty much all the browsers give the original code as result of toString.

If the toString wouldn't be implementation-dependent and thus would be standardized to be the original code for function (with the new lines etc. handled on standard way), wouldn't it make it possible to include the functions on JSON?

I do realize that the JSON, despite its name, is independent of JavaScript and thus the functions shouldn't be part of it. But this way the functions could in theory be passed with it as strings, without losing the cross-browser support.


Solution

  • Internally, Function.prototype.toString() has to get the function declaration code for the function, which it may or may not have. According to the MDN page, FF used to decompile the function, and now it stores the declaration with the function, so it doesn't have to decompile it.

    Since Gecko 17.0 (Firefox 17 / Thunderbird 17 / SeaMonkey 2.14), Function.prototype.toString() has been implemented by saving the function's source. The decompiler was removed

    *https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString

    Decompiling it requires extra work. Storing it requires extra memory. A given ECMAscript implementation may have different resource requirements.

    Further, if it is decompiled, that is dependent on how it was stored in the first place. An engine may be unable to return comments in the original, because it didn't store them when the function was evaluated. Or whitespace/newlines might be different if the engine collapsed them. Or the engine may have optimized the code, such as by ignoring unreachable code, making it not possible to return that code back in the toString() call.

    ...some engines omit newlines. And others omit comments. And others omit "dead code". And others include comments around (!) function. And others hide source completely...

    *http://perfectionkills.com/state-of-function-decompilation-in-javascript/

    These are just a few reasons why Function.prototype.toString() is implementation dependent.