title: Function.prototype.toString revision
status: proposal
stage: 1
contributors: Michael Ficarra
toc: true
Introduction
Goals
The original goals of this proposal were
-
remove the forward-incompatible requirement
If the implementation cannot produce a source code string that meets these criteria then it must return a string for which `eval` will throw a *SyntaxError* exception.
- clarify the "functionally equivalent" requirement
- standardise the string representation of built-in functions and host objects
- clarify requirement of representation based on the "actual characteristics" of an object
The revised goals of this proposal also include
- ensure that the string's parse contains the same function body and parameter list as the original
(19.2.3.5) Function.prototype.toString()
When the `toString` method is called with an object _func_ as its *this* value, the following steps are taken:
1. If _func_ is a Bound Function exotic object, then
1. Return an implementation-dependent String source code representation of _func_. The representation must conform to the rules below. It is implementation dependent whether the representation includes bound function information or information about the target function.
1. If Type(_func_) is Object and is either a built-in function object or has an [[ECMAScriptCode]] internal slot, then
1. Return an implementation-dependent String source code representation of _func_. The representation must conform to the rules below.
1. Throw a *TypeError* exception.
`toString` Representation Requirements:
- The string representation must have the syntax of a |FunctionDeclaration|, |FunctionExpression|, |GeneratorDeclaration|, |GeneratorExpression|, |ClassDeclaration|, |ClassExpression|, |ArrowFunction|, |MethodDefinition|, or |GeneratorMethod| depending upon the actual characteristics of the object.
- The use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent.
- If the object was defined using ECMAScript code and the returned string representation is not in the form of a |MethodDefinition| or |GeneratorMethod| then the representation must be such that if the string is evaluated, using `eval` in a lexical context that is equivalent to the lexical context used to create the original object, it will result in a new functionally equivalent object. In that case the returned source code must not mention freely any variables that were not mentioned freely by the original function's source code, even if these “extra” names were originally in scope.
- If the implementation cannot produce a source code string that meets these criteria then it must return a string for which `eval` will throw a *SyntaxError* exception.
1. If _func_ is a Bound Function exotic object, then return an implementation-dependent string source code representation of _func_. It is implementation dependent whether the representation includes bound function information or information about the target function. The representation must conform to the `toString` Representation Requirements below.
1. If Type(_func_) is Object and IsCallable(_func_) is *true*, then return an implementation-dependent string source code representation of _func_. The representation must conform to the `toString` Representation Requirements below.
1. Throw a *TypeError* exception.
`toString` Representation Requirements:
- If _func_ was defined using |FunctionExpression| or |FunctionDeclaration|, then a parse of the string representation using |FunctionExpression| as the goal symbol must succeed with a parse tree having _func_.[[ECMAScriptCode]] in the |FunctionBody| position and _func_.[[FormalParameters]] in the |FormalParameters| position.
- Else if _func_ was defined using |ClassExpression| or |ClassDeclaration|,
- If a parse of
constructor(...args){ super(...args); }
or constructor(){}
using |MethodDefinition| as the goal symbol succeeds with a parse tree having _func_.[[ECMAScriptCode]] in the |FunctionBody| position and _func_.[[FormalParameters]] in the |StrictFormalParameters| position, then the string representation must have the syntax of a |ClassExpression|.
- Else, a parse of the string representation using |ClassExpression| as the goal symbol must succeed with a parse tree having _func_.[[ECMAScriptCode]] in the |FunctionBody| position of the constructor method and _func_.[[FormalParameters]] in the |StrictFormalParameters| position of the constructor method.
- Else if _func_ was defined using |GeneratorExpression| or |GeneratorDeclaration|, then a parse of the string representation using |GeneratorExpression| as the goal symbol must succeed with a parse tree having _func_.[[ECMAScriptCode]] in the |GeneratorBody| position and _func_.[[FormalParameters]] in the |FormalParameters| position.
- Else if _func_ was defined using |ArrowFunction|, then a parse of the string representation using |ArrowFunction| as the goal symbol must succeed with a parse tree having _func_.[[ECMAScriptCode]] in the |ConciseBody| position and _func_.[[FormalParameters]] as CoveredFormalsList of the parse tree in the |ArrowParameters| position.
- Else if _func_ was defined using |GeneratorMethod|, then a parse of the string representation using |GeneratorMethod| as the goal symbol must succeed with a parse tree having _func_.[[ECMAScriptCode]] in the |GeneratorBody| position and _func_.[[FormalParameters]] in the |StrictFormalParameters| position.
- Else if _func_ was defined using |Getter|, then a parse of the string representation using |Getter| as the goal symbol must succeed with a parse tree having _func_.[[ECMAScriptCode]] in the |FunctionBody| position.
- Else if _func_ was defined using |Setter|, then a parse of the string representation using |Setter| as the goal symbol must succeed with a parse tree having _func_.[[ECMAScriptCode]] in the |FunctionBody| position and _func_.[[FormalParameters]] in the |PropertySetParameterList| position.
- Else if _func_ was defined using |MethodDefinition|, then a parse of the string representation using |MethodDefinition| as the goal symbol must succeed with a parse tree having _func_.[[ECMAScriptCode]] in the |FunctionBody| position and _func_.[[FormalParameters]] in the |StrictFormalParameters| position.
- Else if _func_ has an [[ECMAScriptCode]] internal slot, then a parse of the string representation using |FunctionExpression| as the goal symbol must succeed with a parse tree having _func_.[[ECMAScriptCode]] in the |FunctionBody| position. If _func_ has a [[FormalParameters]] internal slot, then additionally a parse of the string representation using |FunctionExpression| as the goal symbol must succeed with a parse tree having _func_.[[FormalParameters]] in the |FormalParameters| position.
- Else, the string representation must have the syntax of a |NativeFunction|.
If we want to be more explicit here, I can have FunctionInitialize/FunctionCreate set an internal slot with info about the original representation
Do we preserve function name? If so, do unnamed FDs and CDs in export default position cause problems here?
Functions created using the Function constructor are not defined using ECMAScript code, but do have an [[ECMAScriptCode]] internal slot.
NativeFunction :
`function` BindingIdentifier? `(` FormalParameters `)` `{` `[` `native` `code` `]` `}`
(14.3) Method Definitions
Syntax
MethodDefinition[Yield] :
PropertyName[?Yield] `(` StrictFormalParameters `)` `{` FunctionBody `}`
GeneratorMethod[?Yield]
`get` PropertyName[?Yield] `(` `)` `{` FunctionBody `}`
`set` PropertyName[?Yield] `(` PropertySetParameterList `)` `{` FunctionBody `}`
MethodDefinition[Yield] :
PropertyName[?Yield] `(` StrictFormalParameters `)` `{` FunctionBody `}`
GeneratorMethod[?Yield]
Getter[?Yield]
Setter[?Yield]
Getter[Yield] :
`get` PropertyName[?Yield] `(` `)` `{` FunctionBody `}`
Setter[Yield] :
`set` PropertyName[?Yield] `(` PropertySetParameterList `)` `{` FunctionBody `}`
Other existing references to the 3rd and 4th alternatives in the MethodDefinition grammar will need to be changed.