Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In what Javascript engines does Function.prototype.toString not return the source code of that function?

EDIT: To be explicit, I am not looking for advice or opinions on the qualitative merit of the various issues implied by the functionality in question — neither am I looking for a reliable solution to a practical problem; I am simply looking for technical, verifiable answers to the question in the title. I have appended the question with a list of non-conforming browsers.

Using a function's .toString method will typically render the source code for that function. The problem is that this behaviour isn't specified — the spec refrains from making any commitment as to what the behaviour should be when applied to functions. Chrome's console will even tell you (when you pass anything other than a function to Function.toString.call), that Function.prototype.toString is not generic

This blog post suggests this can be used as a method to produce a readable syntax for multi-line strings (by storing the string as a multi-line comment in the body of a no-op function). The author suggests this usage in the context of writing Node.js applications with the clause that this behaviour is only reliable because Node.js runs in a controlled environment. But in Javascript's native web, anything can come along and interpret it, and we shouldn't rely on unspecified behaviour.

In practice though, I've set up a fiddle which renders a select box whose contents are determined by a large multi-line string to test the code, and every browser on my workstation (Chrome 27, Firefox 21, Opera 12, Safari 5, Internet Explorer 8) executes as intended.

What current Javascript engines don't behave as follows?

Given that:

function uncomment(fn){
  return fn.toString().split(/\/\*\n|\n\*\//g).slice(1,-1).join();
}

The following:

uncomment(function(){/*
erg
arg
*/});

Should output:

erg
arg

List of non-conforming browsers:

  • Firefox 16
like image 583
Barney Avatar asked Jun 05 '13 10:06

Barney


People also ask

What does toString return in JavaScript?

The toString() method returns a string representing the object.

Do all JavaScript objects have a toString method?

Every JavaScript object has a toString() method. The toString() method is used internally by JavaScript when an object needs to be displayed as a text (like in HTML), or when an object needs to be used as a string.

Is there a toString method in JavaScript?

toString . For user-defined Function objects, the toString method returns a string containing the source text segment which was used to define the function. JavaScript calls the toString method automatically when a Function is to be represented as a text value, e.g. when a function is concatenated with a string.

What is the opposite of toString in JavaScript?

toString() method when called on a number is the opposite of parseInt, meaning it converts the decimal to any number system between 2 and 36.


1 Answers

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).

like image 128
SheetJS Avatar answered Oct 13 '22 00:10

SheetJS