Function.prototype.toString Change Proposal

# Garrett Smith (16 years ago)

ES5 Committee,

In Function.prototype.toString, the representation should be a "Function Definition". The current text requires a "FunctionDeclaration". Many (if not most) implementations today, do not follow the standard in the following cases:

  1. anonymous function
  2. native code

Example:- javascript: alert([parseInt, function(){}].join('\n\n'));

Many browsers produce a result something like: function parseInt() { [native code] }

function () { }

An implementation could probably change the first to produce a result such as:-

function () { /* [native code] */ }

That should be harmless, and wacky scripts that try to parse [native code] could continue to do so without breaking.

For an anonymous function, an implementation could produce:-

function anonymous(){}

But that would be a bit odd, as the function does not have the identifier "anonymous".

The specification should allow FunctionExpression, so that:-

function(){}

  • would be legal.

This change would have no negative impact on existing scripts, and would allow existing implementations to continue to exhibit the behavior they exhibit today, legally.

The proposed text is as follows:-

| 15.3.4.2 Function.prototype.toString ( ) | | An implementation-dependent representation of the | function is returned. This representation has the | syntax of a Function Definition. Note in particular | that the use and placement of white space, line | terminators, and semicolons within the representation | string is implementation-dependent.

Garrett

# Oliver Hunt (16 years ago)

On Sep 17, 2009, at 11:52 PM, Garrett Smith wrote:

ES5 Committee,

In Function.prototype.toString, the representation should be a "Function Definition". The current text requires a "FunctionDeclaration". Many (if not most) implementations today, do not follow the standard in the following cases:

  1. anonymous function
  2. native code

Example:- javascript: alert([parseInt, function(){}].join('\n\n'));

Many browsers produce a result something like: function parseInt() { [native code] }

function () { }

An implementation could probably change the first to produce a
result such as:-

function () { /* [native code] */ }

That should be harmless, and wacky scripts that try to parse [native code] could continue to do so without breaking.

For an anonymous function, an implementation could produce:-

function anonymous(){}

But that would be a bit odd, as the function does not have the identifier "anonymous".

The specification should allow FunctionExpression, so that:-

function(){}

Alas these changes would break things -- In JSC we have had many bug
reports due about site breakage, which ended up being due to slight
changes in in the formatting of function [[ToString]] conversion. Any
changes to it are immensely risky (we've had at least a couple of bugs
that were due to specific spaces and newlines not being in the "right"
place), the degree of changes you're asking for are almost certain to
break sites.

# Garrett Smith (16 years ago)

On Thu, Sep 17, 2009 at 11:57 PM, Oliver Hunt <oliver at apple.com> wrote:

On Sep 17, 2009, at 11:52 PM, Garrett Smith wrote:

ES5 Committee,

In Function.prototype.toString, the representation should be a "Function Definition". The current text requires a "FunctionDeclaration". Many (if not most) implementations today, do not follow the standard in the following cases:

  1. anonymous function
  2. native code

Example:- javascript: alert([parseInt, function(){}].join('\n\n'));

Many browsers produce a result something like: function parseInt() {   [native code] }

function () { }

An implementation could probably change the first to produce a result such as:-

function () { /* [native code] */ }

That should be harmless, and wacky scripts that try to parse [native code] could continue to do so without breaking.

For an anonymous function, an implementation could produce:-

function anonymous(){}

But that would be a bit odd, as the function does not have the identifier "anonymous".

The specification should allow FunctionExpression, so that:-

function(){}

Alas these changes would break things -- In JSC we have had many bug reports due about site breakage, which ended up being due to slight changes in in the formatting of function [[ToString]] conversion.  Any changes to it are immensely risky (we've had at least a couple of bugs that were due to specific spaces and newlines not being in the "right" place), the degree of changes you're asking for are almost certain to break sites.

How?

javascript: alert(function(){})

Safari 4 elerts: "function () {}"

The current specification doesn't allow that.

Why not?

The current specification requires the result of Function.prototype.toString to be a FunctionDeclaration and "function(){}" is not a FunctionDeclaration representation.

So it seems you want Safari to change, but the specification to remain. I would have to disagree, as that might break sites (and for absolutely no good reason).

I propose that browsers today stay as they are (Safari, Firefox, Chrome, IE, etc all produce that result). The specification should allow them to do so.

Garrett

# Oliver Hunt (16 years ago)

How?

javascript: alert(function(){})

Safari 4 elerts: "function () {}"

The current specification doesn't allow that.

Why not?

The current specification requires the result of Function.prototype.toString to be a FunctionDeclaration and "function(){}" is not a FunctionDeclaration representation.

So it seems you want Safari to change, but the specification to remain. I would have to disagree, as that might break sites (and for absolutely no good reason).

I propose that browsers today stay as they are (Safari, Firefox, Chrome, IE, etc all produce that result). The specification should allow them to do so.

I was referring mainly to the changes in representation of the native
functions sorry. I'm also unsure whether it would be possible to add
'anonymous' as a function name. I vaguely recall one site failing
when we removed the space on either side of the ()'s so that does
worry me. I also believe the eBay (at least in the past) did string
replacement on the result of function.toString to create new functions
which caused us a headache back then as well.

# Garrett Smith (16 years ago)

On Fri, Sep 18, 2009 at 12:26 AM, Oliver Hunt <oliver at apple.com> wrote:

How?

javascript: alert(function(){})

Safari 4 elerts: "function () {}"

The current specification doesn't allow that.

Why not?

The current specification requires the result of Function.prototype.toString to be a FunctionDeclaration and "function(){}" is not  a FunctionDeclaration representation.

So it seems you want Safari to change, but the specification to remain. I would have to disagree, as that might break sites (and for absolutely no good reason).

I propose that browsers today stay as they are (Safari, Firefox, Chrome, IE, etc all produce that result).  The specification should allow them to do so.

I was referring mainly to the changes in representation of the native functions sorry.

That would be an implementation's choice. Opera does that for some non-ecma functions (like alert), but not for parseInt.

javascript: alert([parseInt, alert, function(){}].join('\n')); function () { [native code] } function alert() { /* source code not available */ } function(){}

  1. not legal
  2. legal
  3. not legal

I'm also unsure whether it would be possible to add

'anonymous' as a function name.

I don't think an Identifier should be required and browsers do return a FunctionExpression with no Identifier for that case ( (function(){}).toString() ). I see no reason to require a change in that. Instead, the spec should allow that behavior.

The proposed change in the text is to replace "Function Declaration" with "Function Definition". That means that FunctionExpression representation where the Identifier is optional (and usually omitted) would be legal.

I really can't see how that would cause any compatibility issues. If anything, it should help absolve the currently non-conforming (major) browsers.

I vaguely recall one site failing when we

removed the space on either side of the ()'s so that does worry me.

That is the "implementation dependent" part.

Here is the complete proposed text, again:-

| 15.3.4.2 Function.prototype.toString ( ) | | An implementation-dependent representation of the | function is returned. This representation has the | syntax of a Function Definition. Note in particular | that the use and placement of white space, line | terminators, and semicolons within the representation | string is implementation-dependent.

I also

believe the eBay (at least in the past) did string replacement on the result of function.toString to create new functions which caused us a headache back then as well.

I bet it did!

Garrett