Stage 4 Draft / November 28, 2018

Function.prototype.toString revision

Introduction

Goals

The original goals of this proposal were

The goals were later revised to include

The goals were revised again to include

The goals were revised yet again to include

1(5.2) Algorithm Conventions

The specification often uses a numbered list to specify steps in an algorithm. These algorithms are used to precisely specify the required semantics of ECMAScript language constructs. The algorithms are not intended to imply the use of any specific implementation technique. In practice, there may be more efficient algorithms available to implement a given feature.

Algorithms may be explicitly parameterized, in which case the names and usage of the parameters must be provided as part of the algorithm's definition. In order to facilitate their use in multiple parts of this specification, some algorithms, called abstract operations, are named and written in parameterized functional form so that they may be referenced by name from within other algorithms. Abstract operations are typically referenced using a functional application style such as operationName(arg1, arg2). Some abstract operations are treated as polymorphically dispatched methods of class-like specification abstractions. Such method-like abstract operations are typically referenced using a method application style such as someValue.operationName(arg1, arg2).

Calls to abstract operations return Completion Records. Abstract operations referenced using the functional application style and the method application style that are prefixed by ? indicate that ReturnIfAbrupt should be applied to the resulting Completion Record. For example, ? operationName() is equivalent to ReturnIfAbrupt(operationName()). Similarly, ? someValue.operationName() is equivalent to ReturnIfAbrupt(someValue.operationName()).

The prefix ! is used to indicate that an abstract operation will never return an abrupt completion and that the resulting Completion Record's value field should be used in place of the return value of the operation. For example, “Let val be ! operationName()” is equivalent to the following algorithm steps:

  1. Let val be operationName().
  2. Assert: val is never an abrupt completion.
  3. If val is a Completion Record, let val be val.[[Value]].

Algorithms may be associated with productions of one of the ECMAScript grammars. A production that has multiple alternative definitions will typically have a distinct algorithm for each alternative. When an algorithm is associated with a grammar production, it may reference the terminal and nonterminal symbols of the production alternative as if they were parameters of the algorithm. When used in this manner, nonterminal symbols refer to the actual alternative definition that is matched when parsing the source text. The source text matched by a grammar production is the portion of the source text that starts at the beginning of the first terminal that participated in the match and ends at the end of the last terminal that participated in the match.

When an algorithm is associated with a production alternative, the alternative is typically shown without any “[ ]” grammar annotations. Such annotations should only affect the syntactic recognition of the alternative and have no effect on the associated semantics for the alternative.

Unless explicitly specified otherwise, all chain productions have an implicit definition for every algorithm that might be applied to that production's left-hand side nonterminal. The implicit definition simply reapplies the same algorithm name with the same parameters, if any, to the chain production's sole right-hand side nonterminal and then returns the result. For example, assume there is a production:

Block:{StatementList}

but there is no corresponding Evaluation algorithm that is explicitly specified for that production. If in some algorithm there is a statement of the form: “Return the result of evaluating Block” it is implicit that an Evaluation algorithm exists of the form:

Runtime Semantics: Evaluation

Block:{StatementList}
  1. Return the result of evaluating StatementList.

For clarity of expression, algorithm steps may be subdivided into sequential substeps. Substeps are indented and may themselves be further divided into indented substeps. Outline numbering conventions are used to identify substeps with the first level of substeps labelled with lower case alphabetic characters and the second level of substeps labelled with lower case roman numerals. If more than three levels are required these rules repeat with the fourth level using numeric labels. For example:

  1. Top-level step
    1. Substep.
    2. Substep.
      1. Subsubstep.
        1. Subsubsubstep
          1. Subsubsubsubstep
            1. Subsubsubsubsubstep

A step or substep may be written as an “if” predicate that conditions its substeps. In this case, the substeps are only applied if the predicate is true. If a step or substep begins with the word “else”, it is a predicate that is the negation of the preceding “if” predicate step at the same level.

A step may specify the iterative application of its substeps.

A step that begins with “Assert:” asserts an invariant condition of its algorithm. Such assertions are used to make explicit algorithmic invariants that would otherwise be implicit. Such assertions add no additional semantic requirements and hence need not be checked by an implementation. They are used simply to clarify algorithms.

Mathematical operations such as addition, subtraction, negation, multiplication, division, and the mathematical functions defined later in this clause should always be understood as computing exact mathematical results on mathematical real numbers, which unless otherwise noted do not include infinities and do not include a negative zero that is distinguished from positive zero. Algorithms in this standard that model floating-point arithmetic include explicit steps, where necessary, to handle infinities and signed zero and to perform rounding. If a mathematical operation or function is applied to a floating-point number, it should be understood as being applied to the exact mathematical value represented by that floating-point number; such a floating-point number must be finite, and if it is +0 or -0 then the corresponding mathematical value is simply 0.

The mathematical function abs(x) produces the absolute value of x, which is -x if x is negative (less than zero) and otherwise is x itself.

The mathematical function min(x1, x2, ..., xN) produces the mathematically smallest of x1 through xN. The mathematical function max(x1, x2, ..., xN) produces the mathematically largest of x1 through xN. The domain and range of these mathematical functions include +∞ and -∞.

The notation “x modulo y” (y must be finite and nonzero) computes a value k of the same sign as y (or zero) such that abs(k) < abs(y) and x-k = q × y for some integer q.

The mathematical function floor(x) produces the largest integer (closest to positive infinity) that is not larger than x.

Note

floor(x) = x-(x modulo 1).

2(9.2) ECMAScript Function Objects

ECMAScript function objects encapsulate parameterized ECMAScript code closed over a lexical environment and support the dynamic evaluation of that code. An ECMAScript function object is an ordinary object and has the same internal slots and the same internal methods as other ordinary objects. The code of an ECMAScript function object may be either strict mode code (10.2.1) or non-strict mode code. An ECMAScript function object whose code is strict mode code is called a strict function. One whose code is not strict mode code is called a non-strict function.

ECMAScript function objects have the additional internal slots listed in Table 1.

Table 1: Internal Slots of ECMAScript Function Objects
Internal SlotTypeDescription
[[Environment]]Lexical EnvironmentThe Lexical Environment that the function was closed over. Used as the outer environment when evaluating the code of the function.
[[FormalParameters]]Parse NodeThe root parse node of the source text that defines the function's formal parameter list.
[[FunctionKind]]StringEither "normal", "classConstructor" or "generator".
[[ECMAScriptCode]]Parse NodeThe root parse node of the source text that defines the function's body.
[[ConstructorKind]]StringEither "base" or "derived".
[[Realm]]Realm RecordThe realm in which the function was created and which provides any intrinsic objects that are accessed when evaluating the function.
[[ScriptOrModule]]Script Record or Module RecordThe script or module in which the function was created.
[[ThisMode]](lexical, strict, global)Defines how this references are interpreted within the formal parameters and code body of the function. lexical means that this refers to the this value of a lexically enclosing function. strict means that the this value is used exactly as provided by an invocation of the function. global means that a this value of undefined is interpreted as a reference to the global object.
[[Strict]]Booleantrue if this is a strict mode function, false if this is not a strict mode function.
[[HomeObject]]ObjectIf the function uses super, this is the object whose [[GetPrototypeOf]] provides the object where super property lookups begin.
[[SourceText]] String The source text that defines the function.

All ECMAScript function objects have the [[Call]] internal method defined here. ECMAScript functions that are also constructors in addition have the [[Construct]] internal method.

3(14.1.19) Runtime Semantics: InstantiateFunctionObject

With parameter scope.

FunctionDeclaration:functionBindingIdentifier(FormalParameters){FunctionBody}
  1. If the function code for FunctionDeclaration is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let name be StringValue of BindingIdentifier.
  3. Let F be FunctionCreate(Normal, FormalParameters, FunctionBody, scope, strict).
  4. Perform MakeConstructor(F).
  5. Perform SetFunctionName(F, name).
  6. Set F.[[SourceText]] to the source text matched by FunctionDeclaration.
  7. Return F.
FunctionDeclaration:function(FormalParameters){FunctionBody}
  1. If the function code for FunctionDeclaration is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let F be FunctionCreate(Normal, FormalParameters, FunctionBody, scope, strict).
  3. Perform MakeConstructor(F).
  4. Perform SetFunctionName(F, "default").
  5. Set F.[[SourceText]] to the source text matched by FunctionDeclaration.
  6. Return F.
Note

An anonymous FunctionDeclaration can only occur as part of an export default declaration.

4(14.1.20) Runtime Semantics: Evaluation

FunctionDeclaration:functionBindingIdentifier(FormalParameters){FunctionBody}
  1. Return NormalCompletion(empty).
Note 1

An alternative semantics is provided in B.3.3.

FunctionDeclaration:function(FormalParameters){FunctionBody}
  1. Return NormalCompletion(empty).
FunctionExpression:function(FormalParameters){FunctionBody}
  1. If the function code for FunctionExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let closure be FunctionCreate(Normal, FormalParameters, FunctionBody, scope, strict).
  4. Perform MakeConstructor(closure).
  5. Set closure.[[SourceText]] to the source text matched by FunctionExpression.
  6. Return closure.
FunctionExpression:functionBindingIdentifier(FormalParameters){FunctionBody}
  1. If the function code for FunctionExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the running execution context's LexicalEnvironment.
  3. Let funcEnv be NewDeclarativeEnvironment(scope).
  4. Let envRec be funcEnv's EnvironmentRecord.
  5. Let name be StringValue of BindingIdentifier.
  6. Perform envRec.CreateImmutableBinding(name, false).
  7. Let closure be FunctionCreate(Normal, FormalParameters, FunctionBody, funcEnv, strict).
  8. Perform MakeConstructor(closure).
  9. Perform SetFunctionName(closure, name).
  10. Set closure.[[SourceText]] to the source text matched by FunctionExpression.
  11. Perform envRec.InitializeBinding(name, closure).
  12. Return closure.
Note 2

The BindingIdentifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the BindingIdentifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.

Note 3

A prototype property is automatically created for every function defined using a FunctionDeclaration or FunctionExpression, to allow for the possibility that the function will be used as a constructor.

FunctionStatementList:[empty]
  1. Return NormalCompletion(undefined).

5(14.2.16) Runtime Semantics: Evaluation

ArrowFunction:ArrowParameters=>ConciseBody
  1. If the function code for this ArrowFunction is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let parameters be CoveredFormalsList of ArrowParameters.
  4. Let closure be FunctionCreate(Arrow, parameters, ConciseBody, scope, strict).
  5. Set closure.[[SourceText]] to the source text matched by ArrowFunction.
  6. Return closure.
Note

An ArrowFunction does not define local bindings for arguments, super, this, or new.target. Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a binding in a lexically enclosing environment. Typically this will be the Function Environment of an immediately enclosing function. Even though an ArrowFunction may contain references to super, the function object created in step 4 is not made into a method by performing MakeMethod. An ArrowFunction that references super is always contained within a non-ArrowFunction and the necessary state to implement super is accessible via the scope that is captured by the function object of the ArrowFunction.

6(14.3.8) Runtime Semantics: DefineMethod

With parameters object and optional parameter functionPrototype.

MethodDefinition:PropertyName(StrictFormalParameters){FunctionBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. If the function code for this MethodDefinition is strict mode code, let strict be true. Otherwise let strict be false.
  4. Let scope be the running execution context's LexicalEnvironment.
  5. If functionPrototype was passed as a parameter, let kind be Normal; otherwise let kind be Method.
  6. Let closure be FunctionCreate(kind, StrictFormalParameters, FunctionBody, scope, strict). If functionPrototype was passed as a parameter, then pass its value as the prototype optional argument of FunctionCreate.
  7. Perform MakeMethod(closure, object).
  8. Set closure.[[SourceText]] to the source text matched by MethodDefinition.
  9. Return the Record{[[Key]]: propKey, [[Closure]]: closure}.

7(14.3.9) Runtime Semantics: PropertyDefinitionEvaluation

With parameters object and enumerable.

MethodDefinition:PropertyName(StrictFormalParameters){FunctionBody}
  1. Let methodDef be DefineMethod of MethodDefinition with argument object.
  2. ReturnIfAbrupt(methodDef).
  3. Perform SetFunctionName(methodDef.[[Closure]], methodDef.[[Key]]).
  4. Let desc be the PropertyDescriptor{[[Value]]: methodDef.[[Closure]], [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true}.
  5. Return ? DefinePropertyOrThrow(object, methodDef.[[Key]], desc).
MethodDefinition:GeneratorMethod

See 14.4.

MethodDefinition:getPropertyName(){FunctionBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. If the function code for this MethodDefinition is strict mode code, let strict be true. Otherwise let strict be false.
  4. Let scope be the running execution context's LexicalEnvironment.
  5. Let formalParameterList be the production FormalParameters:[empty] .
  6. Let closure be FunctionCreate(Method, formalParameterList, FunctionBody, scope, strict).
  7. Perform MakeMethod(closure, object).
  8. Perform SetFunctionName(closure, propKey, "get").
  9. Set closure.[[SourceText]] to the source text matched by MethodDefinition.
  10. Let desc be the PropertyDescriptor{[[Get]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true}.
  11. Return ? DefinePropertyOrThrow(object, propKey, desc).
MethodDefinition:setPropertyName(PropertySetParameterList){FunctionBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. If the function code for this MethodDefinition is strict mode code, let strict be true. Otherwise let strict be false.
  4. Let scope be the running execution context's LexicalEnvironment.
  5. Let closure be FunctionCreate(Method, PropertySetParameterList, FunctionBody, scope, strict).
  6. Perform MakeMethod(closure, object).
  7. Perform SetFunctionName(closure, propKey, "set").
  8. Set closure.[[SourceText]] to the source text matched by MethodDefinition.
  9. Let desc be the PropertyDescriptor{[[Set]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true}.
  10. Return ? DefinePropertyOrThrow(object, propKey, desc).

8(14.4.12) Runtime Semantics: InstantiateFunctionObject

With parameter scope.

GeneratorDeclaration:function*BindingIdentifier(FormalParameters){GeneratorBody}
  1. If the function code for GeneratorDeclaration is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let name be StringValue of BindingIdentifier.
  3. Let F be GeneratorFunctionCreate(Normal, FormalParameters, GeneratorBody, scope, strict).
  4. Let prototype be ObjectCreate(%GeneratorPrototype%).
  5. Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  6. Perform SetFunctionName(F, name).
  7. Set F.[[SourceText]] to the source text matched by GeneratorDeclaration.
  8. Return F.
GeneratorDeclaration:function*(FormalParameters){GeneratorBody}
  1. If the function code for GeneratorDeclaration is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let F be GeneratorFunctionCreate(Normal, FormalParameters, GeneratorBody, scope, strict).
  3. Let prototype be ObjectCreate(%GeneratorPrototype%).
  4. Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  5. Perform SetFunctionName(F, "default").
  6. Set F.[[SourceText]] to the source text matched by GeneratorDeclaration.
  7. Return F.
Note

An anonymous GeneratorDeclaration can only occur as part of an export default declaration.

9(14.4.13) Runtime Semantics: PropertyDefinitionEvaluation

With parameter object and enumerable.

GeneratorMethod:*PropertyName(StrictFormalParameters){GeneratorBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. If the function code for this GeneratorMethod is strict mode code, let strict be true. Otherwise let strict be false.
  4. Let scope be the running execution context's LexicalEnvironment.
  5. Let closure be GeneratorFunctionCreate(Method, StrictFormalParameters, GeneratorBody, scope, strict).
  6. Perform MakeMethod(closure, object).
  7. Let prototype be ObjectCreate(%GeneratorPrototype%).
  8. Perform DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  9. Perform SetFunctionName(closure, propKey).
  10. Set closure.[[SourceText]] to the source text matched by GeneratorMethod.
  11. Let desc be the PropertyDescriptor{[[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true}.
  12. Return ? DefinePropertyOrThrow(object, propKey, desc).

10(14.4.14) Runtime Semantics: Evaluation

GeneratorExpression:function*(FormalParameters){GeneratorBody}
  1. If the function code for this GeneratorExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let closure be GeneratorFunctionCreate(Normal, FormalParameters, GeneratorBody, scope, strict).
  4. Let prototype be ObjectCreate(%GeneratorPrototype%).
  5. Perform DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  6. Set closure.[[SourceText]] to the source text matched by GeneratorExpression.
  7. Return closure.
GeneratorExpression:function*BindingIdentifier(FormalParameters){GeneratorBody}
  1. If the function code for this GeneratorExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the running execution context's LexicalEnvironment.
  3. Let funcEnv be NewDeclarativeEnvironment(scope).
  4. Let envRec be funcEnv's EnvironmentRecord.
  5. Let name be StringValue of BindingIdentifier.
  6. Perform envRec.CreateImmutableBinding(name, false).
  7. Let closure be GeneratorFunctionCreate(Normal, FormalParameters, GeneratorBody, funcEnv, strict).
  8. Let prototype be ObjectCreate(%GeneratorPrototype%).
  9. Perform DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  10. Perform SetFunctionName(closure, name).
  11. Perform envRec.InitializeBinding(name, closure).
  12. Set closure.[[SourceText]] to the source text matched by GeneratorExpression.
  13. Return closure.
Note

The BindingIdentifier in a GeneratorExpression can be referenced from inside the GeneratorExpression's FunctionBody to allow the generator code to call itself recursively. However, unlike in a GeneratorDeclaration, the BindingIdentifier in a GeneratorExpression cannot be referenced from and does not affect the scope enclosing the GeneratorExpression.

11(14.5.11) Runtime Semantics: InstantiateFunctionObject

With parameter scope.

AsyncGeneratorDeclaration:async[no LineTerminator here]function*BindingIdentifier(FormalParameters){AsyncGeneratorBody}
  1. If the function code for AsyncGeneratorDeclaration is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let name be StringValue of BindingIdentifier.
  3. Let F be ! AsyncGeneratorFunctionCreate(Normal, FormalParameters, AsyncGeneratorBody, scope, strict).
  4. Let prototype be ! ObjectCreate(%AsyncGeneratorPrototype%).
  5. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  6. Perform ! SetFunctionName(F, name).
  7. Set F.[[SourceText]] to the source text matched by AsyncGeneratorDeclaration.
  8. Return F.
AsyncGeneratorDeclaration:async[no LineTerminator here]function*(FormalParameters){AsyncGeneratorBody}
  1. If the function code for AsyncGeneratorDeclaration is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let F be AsyncGeneratorFunctionCreate(Normal, FormalParameters, AsyncGeneratorBody, scope, strict).
  3. Let prototype be ObjectCreate(%AsyncGeneratorPrototype%).
  4. Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  5. Perform SetFunctionName(F, "default").
  6. Set F.[[SourceText]] to the source text matched by AsyncGeneratorDeclaration.
  7. Return F.
Note

An anonymous AsyncGeneratorDeclaration can only occur as part of an export default declaration.

12(14.5.12) Runtime Semantics: PropertyDefinitionEvaluation

With parameter object and enumerable.

AsyncGeneratorMethod:async[no LineTerminator here]*PropertyName(UniqueFormalParameters){AsyncGeneratorBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. If the function code for this AsyncGeneratorMethod is strict mode code, let strict be true. Otherwise let strict be false.
  4. Let scope be the running execution context's LexicalEnvironment.
  5. Let closure be ! AsyncGeneratorFunctionCreate(Method, UniqueFormalParameters, AsyncGeneratorBody, scope, strict).
  6. Perform ! MakeMethod(closure, object).
  7. Let prototype be ! ObjectCreate(%AsyncGeneratorPrototype%).
  8. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  9. Perform ! SetFunctionName(closure, propKey).
  10. Set closure.[[SourceText]] to the source text matched by AsyncGeneratorMethod.
  11. Let desc be PropertyDescriptor{[[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true}.
  12. Return ? DefinePropertyOrThrow(object, propKey, desc).

13(14.5.13) Runtime Semantics: Evaluation

AsyncGeneratorExpression:async[no LineTerminator here]function*(FormalParameters){AsyncGeneratorBody}
  1. If the function code for this AsyncGeneratorExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let closure be ! AsyncGeneratorFunctionCreate(Normal, FormalParameters, AsyncGeneratorBody, scope, strict).
  4. Let prototype be ! ObjectCreate(%AsyncGeneratorPrototype%).
  5. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  6. Set closure.[[SourceText]] to the source text matched by AsyncGeneratorExpression.
  7. Return closure.
AsyncGeneratorExpression:async[no LineTerminator here]function*BindingIdentifier(FormalParameters){AsyncGeneratorBody}
  1. If the function code for this AsyncGeneratorExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the running execution context's LexicalEnvironment.
  3. Let funcEnv be ! NewDeclarativeEnvironment(scope).
  4. Let envRec be funcEnv's EnvironmentRecord.
  5. Let name be StringValue of BindingIdentifier.
  6. Perform ! envRec.CreateImmutableBinding(name).
  7. Let closure be ! AsyncGeneratorFunctionCreate(Normal, FormalParameters, AsyncGeneratorBody, funcEnv, strict).
  8. Let prototype be ! ObjectCreate(%AsyncGeneratorPrototype%).
  9. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  10. Perform ! SetFunctionName(closure, name).
  11. Perform ! envRec.InitializeBinding(name, closure).
  12. Set closure.[[SourceText]] to the source text matched by AsyncGeneratorExpression.
  13. Return closure.
Note

The BindingIdentifier in an AsyncGeneratorExpression can be referenced from inside the AsyncGeneratorExpression's AsyncGeneratorBody to allow the generator code to call itself recursively. However, unlike in an AsyncGeneratorDeclaration, the BindingIdentifier in an AsyncGeneratorExpression cannot be referenced from and does not affect the scope enclosing the AsyncGeneratorExpression.

14(14.5.15) Runtime Semantics: BindingClassDeclarationEvaluation

ClassDeclaration:classBindingIdentifierClassTail
  1. Let className be StringValue of BindingIdentifier.
  2. Let value be the result of ClassDefinitionEvaluation of ClassTail with argument className.
  3. ReturnIfAbrupt(value).
  4. Let hasNameProperty be ? HasOwnProperty(value, "name").
  5. If hasNameProperty is false, perform SetFunctionName(value, className).
  6. Set value.[[SourceText]] to the source text matched by ClassDeclaration.
  7. Let env be the running execution context's LexicalEnvironment.
  8. Perform ? InitializeBoundName(className, value, env).
  9. Return value.
ClassDeclaration:classClassTail
  1. ReturnLet value be the result of ClassDefinitionEvaluation of ClassTail with argument undefined.
  2. Set value.[[SourceText]] to the source text matched by ClassDeclaration.
  3. Return value.
Note

ClassDeclaration:classClassTail only occurs as part of an ExportDeclaration and the setting of a name property and establishing its binding are handled as part of the evaluation action for that production. See 15.2.3.9.

15(14.5.16) Runtime Semantics: Evaluation

ClassDeclaration:classBindingIdentifierClassTail
  1. Let status be the result of BindingClassDeclarationEvaluation of this ClassDeclaration.
  2. ReturnIfAbrupt(status).
  3. Return NormalCompletion(empty).
Note 1

ClassDeclaration:classClassTail only occurs as part of an ExportDeclaration and is never directly evaluated.

ClassExpression:classBindingIdentifieroptClassTail
  1. If BindingIdentifieropt is not present, let className be undefined.
  2. Else, let className be StringValue of BindingIdentifier.
  3. Let value be the result of ClassDefinitionEvaluation of ClassTail with argument className.
  4. ReturnIfAbrupt(value).
  5. If className is not undefined, then
    1. Let hasNameProperty be ? HasOwnProperty(value, "name").
    2. If hasNameProperty is false, then
      1. Perform SetFunctionName(value, className).
  6. Set value.[[SourceText]] to the source text matched by ClassExpression.
  7. Return NormalCompletion(value).
Note 2

If the class definition included a name static method then that method is not over-written with a name data property for the class name.

16(14.7.10) Runtime Semantics: InstantiateFunctionObject

With parameter scope.

AsyncFunctionDeclaration:async[no LineTerminator here]functionBindingIdentifier(FormalParameters){AsyncFunctionBody}
  1. If the function code for AsyncFunctionDeclaration is strict mode code, let strict be true. Otherwise, let strict be false.
  2. Let name be StringValue of BindingIdentifier.
  3. Let F be ! AsyncFunctionCreate(Normal, FormalParameters, AsyncFunctionBody, scope, strict).
  4. Perform ! SetFunctionName(F, name).
  5. Set F.[[SourceText]] to the source text matched by AsyncFunctionDeclaration.
  6. Return F.
AsyncFunctionDeclaration:async[no LineTerminator here]function(FormalParameters){AsyncFunctionBody}
  1. If the function code for AsyncFunctionDeclaration is strict mode code, let strict be true. Otherwise, let strict be false.
  2. Let F be ! AsyncFunctionCreate(Normal, FormalParameters, AsyncFunctionBody, scope, strict).
  3. Perform ! SetFunctionName(F, "default").
  4. Set F.[[SourceText]] to the source text matched by AsyncFunctionDeclaration.
  5. Return F.

17(14.7.12) Runtime Semantics: PropertyDefinitionEvaluation

With parameters object and enumerable.

AsyncMethod:async[no LineTerminator here]PropertyName(UniqueFormalParameters){AsyncFunctionBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. If the function code for this AsyncMethod is strict mode code, let strict be true. Otherwise let strict be false.
  4. Let scope be the LexicalEnvironment of the running execution context.
  5. Let closure be ! AsyncFunctionCreate(Method, UniqueFormalParameters, AsyncFunctionBody, scope, strict).
  6. Perform ! MakeMethod(closure, object).
  7. Perform ! SetFunctionName(closure, propKey).
  8. Set closure.[[SourceText]] to the source text matched by AsyncMethod.
  9. Let desc be the PropertyDescriptor{[[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true}.
  10. Return ? DefinePropertyOrThrow(object, propKey, desc).

18(14.7.13) Runtime Semantics: Evaluation

AsyncFunctionDeclaration:async[no LineTerminator here]functionBindingIdentifier(FormalParameters){AsyncFunctionBody}
  1. Return NormalCompletion(empty).
AsyncFunctionDeclaration:async[no LineTerminator here]function(FormalParameters){AsyncFunctionBody}
  1. Return NormalCompletion(empty).
AsyncFunctionExpression:async[no LineTerminator here]function(FormalParameters){AsyncFunctionBody}
  1. If the function code for AsyncFunctionExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let closure be ! AsyncFunctionCreate(Normal, FormalParameters, AsyncFunctionBody, scope, strict).
  4. Set closure.[[SourceText]] to the source text matched by AsyncFunctionExpression.
  5. Return closure.
AsyncFunctionExpression:async[no LineTerminator here]functionBindingIdentifier(FormalParameters){AsyncFunctionBody}
  1. If the function code for AsyncFunctionExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let funcEnv be ! NewDeclarativeEnvironment(scope).
  4. Let envRec be funcEnv's EnvironmentRecord.
  5. Let name be StringValue of BindingIdentifier.
  6. Perform ! envRec.CreateImmutableBinding(name).
  7. Let closure be ! AsyncFunctionCreate(Normal, FormalParameters, AsyncFunctionBody, funcEnv, strict).
  8. Perform ! SetFunctionName(closure, name).
  9. Perform ! envRec.InitializeBinding(name, closure).
  10. Set closure.[[SourceText]] to the source text matched by AsyncFunctionExpression.
  11. Return closure.
AwaitExpression:awaitUnaryExpression
  1. Let exprRef be the result of evaluating UnaryExpression.
  2. Let value be ? GetValue(exprRef).
  3. Return ? Await(value).

19(19.2.1.1.1) Runtime Semantics: CreateDynamicFunction( constructor, newTarget, kind, args )

The abstract operation CreateDynamicFunction is called with arguments constructor, newTarget, kind, and args. constructor is the constructor function that is performing this action, newTarget is the constructor that new was initially applied to, kind is either "normal", "generator", or "async", and args is a List containing the actual argument values that were passed to constructor. The following steps are taken:

  1. Assert: The execution context stack has at least two elements.
  2. Let callerContext be the second to top element of the execution context stack.
  3. Let callerRealm be callerContext's Realm.
  4. Let calleeRealm be the current Realm Record.
  5. Perform ? HostEnsureCanCompileStrings(callerRealm, calleeRealm).
  6. If newTarget is undefined, let newTarget be constructor.
  7. If kind is "normal", then
    1. Let goal be the grammar symbol FunctionBody[~Yield, ~Await].
    2. Let parameterGoal be the grammar symbol FormalParameters[~Yield, ~Await].
    3. Let fallbackProto be "%FunctionPrototype%".
  8. Else if kind is "generator", then
    1. Let goal be the grammar symbol GeneratorBody.
    2. Let parameterGoal be the grammar symbol FormalParameters[+Yield, ~Await].
    3. Let fallbackProto be "%Generator%".
  9. Else,
    1. Assert: kind is "async".
    2. Let goal be the grammar symbol AsyncFunctionBody.
    3. Let parameterGoal be the grammar symbol FormalParameters[~Yield, +Await].
    4. Let fallbackProto be "%AsyncFunctionPrototype%".
  10. Let argCount be the number of elements in args.
  11. Let P be the empty String.
  12. If argCount = 0, let bodyText be the empty String.
  13. Else if argCount = 1, let bodyText be args[0].
  14. Else argCount > 1,
    1. Let firstArg be args[0].
    2. Let P be ? ToString(firstArg).
    3. Let k be 1.
    4. Repeat, while k < argCount-1
      1. Let nextArg be args[k].
      2. Let nextArgString be ? ToString(nextArg).
      3. Let P be the result of concatenating the previous value of P, the String "," (a comma), and nextArgString.
      4. Increase k by 1.
    5. Let bodyText be args[k].
  15. Let bodyText be ? ToString(bodyText).
  16. Let parameters be the result of parsing P, interpreted as UTF-16 encoded Unicode text as described in 6.1.4, using parameterGoal as the goal symbol. Throw a SyntaxError exception if the parse fails.
  17. Let body be the result of parsing bodyText, interpreted as UTF-16 encoded Unicode text as described in 6.1.4, using goal as the goal symbol. Throw a SyntaxError exception if the parse fails.
  18. If bodyText is strict mode code, then let strict be true, else let strict be false.
  19. If any static semantics errors are detected for parameters or body, throw a SyntaxError or a ReferenceError exception, depending on the type of the error. If strict is true, the Early Error rules for UniqueFormalParameters:FormalParameters are applied. Parsing and early error detection may be interweaved in an implementation dependent manner.
  20. If ContainsUseStrict of body is true and IsSimpleParameterList of parameters is false, throw a SyntaxError exception.
  21. If any element of the BoundNames of parameters also occurs in the LexicallyDeclaredNames of body, throw a SyntaxError exception.
  22. If body Contains SuperCall is true, throw a SyntaxError exception.
  23. If parameters Contains SuperCall is true, throw a SyntaxError exception.
  24. If body Contains SuperProperty is true, throw a SyntaxError exception.
  25. If parameters Contains SuperProperty is true, throw a SyntaxError exception.
  26. If kind is "generator", then
    1. If parameters Contains YieldExpression is true, throw a SyntaxError exception.
  27. If kind is "async", then
    1. If parameters Contains AwaitExpression is true, throw a SyntaxError exception.
  28. If strict is true, then
    1. If BoundNames of parameters contains any duplicate elements, throw a SyntaxError exception.
  29. Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
  30. Let F be FunctionAllocate(proto, strict, kind).
  31. Let realmF be F.[[Realm]].
  32. Let scope be realmF.[[GlobalEnv]].
  33. Perform FunctionInitialize(F, Normal, parameters, body, scope).
  34. If kind is "generator", then
    1. Let prototype be ObjectCreate(%GeneratorPrototype%).
    2. Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  35. Else if kind is "normal", perform MakeConstructor(F).
  36. NOTE: Async functions are not constructable and do not have a [[Construct]] internal method or a "prototype" property.
  37. Perform SetFunctionName(F, "anonymous").
  38. Let prefix be the prefix associated with kind in Table 2.
  39. Let sourceText be the String value whose elements are, in order, the code units of prefix, the code units of " anonymous(", the code units of P, 0x000A (LINE FEED), the code units of ") {", 0x000A (LINE FEED), the code units of bodyText, 0x000A (LINE FEED), and the code units of "}".
  40. Set F.[[SourceText]] to sourceText.
  41. Return F.
Note

A prototype property is automatically created for every function created using CreateDynamicFunction, to provide for the possibility that the function will be used as a constructor.

Table 2: Dynamic Function SourceText Prefixes
KindPrefix
"normal""function"
"generator""function*"
"async""async function"
"async generator""async function*"

20HostHasSourceTextAvailable ( func )

HostHasSourceTextAvailable is an implementation-defined abstract operation that allows host environments to prevent the source text from being provided for a given function.

An implementation of HostHasSourceTextAvailable must complete normally in all cases. This operation must be idempotent. Each time it is called with a specific func as its argument, it must return the same completion record. The default implementation of HostHasSourceTextAvailable is to unconditionally return a normal completion with a value of true.

21(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.
  2. 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.
  3. 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 or a built-in Function object, then return an implementation-dependent String source code representation of func. The representation must have the syntax of a NativeFunction. Additionally, if func is a Well-known Intrinsic Object and is not identified as an anonymous function, the portion of the returned String that would be matched by PropertyName must be the initial value of the name property of func.
  2. If func has a [[SourceText]] internal slot and Type(func.[[SourceText]]) is String and ! HostHasSourceTextAvailable(func) is true, then return func.[[SourceText]].
  3. If Type(func) is Object and IsCallable(func) is true, then return an implementation-dependent String source code representation of func. The representation must have the syntax of a NativeFunction.
  4. Throw a TypeError exception.
NativeFunction:functionPropertyName[~Yield, ~Await]opt(FormalParameters[~Yield, ~Await]){[nativecode]}

ACopyright & Software License

Copyright Notice

© 2018 Michael Ficarra

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.