Modified algorithms
Static Semantics: PropName
FieldDefinition : ClassElementName Initializer?
1. Return PropName of |ClassElementName|.
ClassElementName[Yield, Await] : PropertyName[?Yield, ?Await]
1. Return PropName of |PropertyName|.
ClassElementName[Yield, Await] : PrivateIdentifier
1. Return ~empty~.
Runtime Semantics: Evaluation
ClassElementName[Yield, Await] : PropertyName[?Yield, ?Await]
1. Return the result of evaluating |PropertyName|.
ClassElementName[Yield, Await] : PrivateIdentifier
1. Let _privateIdentifier_ be StringValue of |PrivateIdentifier|.
1. Let _scope_ be the running execution context's PrivateEnvironment.
1. Let _scopeEnvRec_ be _scope_'s EnvironmentRecord.
1. Return _scopeEnvRec_.GetBindingValue(_bindingName_).
Each time a class declaration executes, distinct internal Private Names are created. This means, that they cannot directly access each other's private state if a method of one is called with the other as a receiver.
Runtime Semantics: ClassElementEvaluation
With parameters _object_ and _enumerable_.
ClassElement : FieldDefinition `;`
1. Return ClassFieldDefinitionEvaluation of |FieldDefinition| with parameter _object_.
ClassElement : MethodDefinition
ClassElement : `static` MethodDefinition
1. Perform ? PropertyDefinitionEvaluation with parameters _object_ and _enumerable_.
1. Return ~empty~.
Runtime Semantics: ClassFieldDefinitionEvaluation
With parameter _homeObject_.
FieldDefinition : ClassElementName Initializer?
1. Let _name_ be the result of evaluating |ClassElementName|.
1. ReturnIfAbrupt(_name_).
1. If |Initializer_opt| is present,
1. Let _lex_ be the Lexical Environment of the running execution context.
1. Let _formalParameterList_ be an instance of the production FormalParameters : [empty].
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _initializer_ be FunctionCreate(~Method~, _formalParameterList_, |Initializer|, _lex_, *true*, _privateScope_).
1. Perform MakeMethod(_initializer_, _homeObject_).
1. Let _isAnonymousFunctionDefinition_ be IsAnonymousFunctionDefinition(|Initializer|).
1. Else,
1. Let _initializer_ be ~empty~.
1. Let _isAnonymousFunctionDeclaration_ be *false*.
1. Return a Record {
[[Name]]: _name_,
[[Initializer]]: _initializer_,
[[IsAnonymousFunctionDefinition]]: _isAnonymousFunctionDefinition_
}.
Runtime Semantics: EvaluateBody
With parameter _functionObject_ and List _argumentsList_.
Initializer :
`=` AssignmentExpression
1. Assert: _argumentsList_ is empty.
1. Let _exprRef_ be the result of evaluating |AssignmentExpression|.
1. Let _exprValue_ be ? GetValue(_exprRef_).
1. Return Completion { [[Type]]: ~return~, [[Value]]: _exprValue_, [[Target]]: ~empty~ }.
FunctionDeclarationInstantiation would not have any observable behaviour here, so its call is omitted.
SetFunctionName ( _F_, _name_ [ , _prefix_ ] )
The abstract operation SetFunctionName requires a Function argument _F_, a String, Symbol, or Private Name argument _name_ and optionally a String argument _prefix_. This operation adds a `name` property to _F_ by performing the following steps:
1. Assert: _F_ is an extensible object that does not have a `name` own property.
1. Assert: Type(_name_) is either Symbol, String, or Private Name.
1. Assert: If _prefix_ was passed, then Type(_prefix_) is String.
1. If Type(_name_) is Symbol, then
1. Let _description_ be _name_'s [[Description]] value.
1. If _description_ is *undefined*, set _name_ to the empty String.
1. Else, set _name_ to the concatenation of `"["`, _description_, and `"]"`.
1. Else if _name_ is a Private Name,
1. Set _name_ to _name_'s [[Description]] value.
1. If _prefix_ was passed, then
1. Set _name_ to the concatenation of _prefix_, code unit 0x0020 (SPACE), and _name_.
1. Return ! DefinePropertyOrThrow(_F_, `"name"`, PropertyDescriptor{[[Value]]: _name_, [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true*}).
DefineField(_receiver_, _fieldRecord_)
1. Assert: Type(_receiver_) is Object.
1. Assert: _fieldRecord_ is a Record as created by ClassFieldDefinitionEvaluation.
1. Let _fieldName_ be _fieldRecord_.[[Name]].
1. Let _initializer_ be _fieldRecord_.[[Initializer]].
1. If _initializer_ is not ~empty~, then
1. Let _initValue_ be ? Call(_initializer_, _receiver_).
1. Else, let _initValue_ be *undefined*.
1. If _fieldRecord_.[[IsAnonymousFunctionDefinition]] is *true*, then
1. Let _hasNameProperty_ be ? HasOwnProperty(_initValue_, `"name"`).
1. If _hasNameProperty_ is *false*, perform SetFunctionName(_initValue_, _fieldName_).
1. If _fieldName_ is a Private Name,
1. Perform ? PrivateFieldAdd(_fieldName_, _receiver_, _initValue_).
1. Else,
1. Assert: IsPropertyKey(_fieldName_) is *true*.
1. Perform ? CreateDataPropertyOrThrow(_receiver_, _fieldName_, _initValue_).
1. Return.
InitializeInstanceFields ( _O_, _constructor_ )
1. Assert: Type ( _O_ ) is Object.
1. Assert: _constructor_ is an ECMAScript function object.
1. Let _fields_ be the value of _constructor_.[[Fields]].
1. For each item _fieldRecord_ in order from _fields_,
1. Perform ? DefineField(_O_, _fieldRecord_).
1. Return.
Private fields are added to the object one by one, interspersed with evaluation of the initializers, following the construction of the receiver. These semantics allow for a later initializer to refer to a previous private field.
Static Semantics: StringValue
PrivateIdentifier ::
`#` IdentifierName
1. Return the String value consisting of the sequence of code units corresponding to |PrivateIdentifier|. In determining the sequence any occurrences of `\\` |UnicodeEscapeSequence| are first replaced with the code point represented by the |UnicodeEscapeSequence| and then the code points of the entire |PrivateIdentifier| are converted to code units by UTF16Encoding () each code point.
Static Semantics: PrivateBoundIdentifiers
FieldDefinition : ClassElementName Initializer?
1. Return PrivateBoundIdentifiers of |ClassElementName|
ClassElementName : PrivateIdentifier
1. Return a new List containing the StringValue of |PrivateIdentifier|.
ClassElementName : PropertyName
1. Return a new empty List.
ClassElement : MethodDefinition `;`
ClassElement : `static` MethodDefinition `;`
ClassElement : `;`
1. Return a new empty List.
ClassElementList : ClassElement
1. Return PrivateBoundIdentifiers of |ClassElement|.
ClassElementList : ClassElementList ClassElement
1. Let _names_ be PrivateBoundIdentifiers of |ClassElementList|.
1. Append to _names_ the elements of PrivateBoundIdentifiers of |ClassElement|.
1. Return _names_.
ClassBody : ClassElementList
1. Return PrivateBoundIdentifiers of |ClassElementList|.
Static Semantics: ContainsArguments
IdentifierReference : Identifier
1. If the StringValue of |Identifier| is `"arguments"`, return *true*.
2. Else, return *false*.
FunctionDeclaration : `function` BindingIdentifier `(` FormalParameters `)` `{` FunctionBody `}`
FunctionDeclaration : `function` `(` FormalParameters `)` `{` FunctionBody `}`
FunctionExpression : `function` BindingIdentifier? `(` FormalParameters `)` `{` FunctionBody `}`
1. Return *false*.
MethodDefinition :
PropertyName `(` UniqueFormalParameters `)` `{` FunctionBody `}`
`get` PropertyName `(` `)` `{` FunctionBody `}`
`set` PropertyName `(` PropertySetParameterList `)` `{` FunctionBody `}`
1. Return the result of ContainsArguments for |PropertyName|.
GeneratorMethod : `*` PropertyName `(` UniqueFormalParameters `)` `{` GeneratorBody `}`
1. Return the result of ContainsArguments for |PropertyName|.
GeneratorDeclaration : `function` `*` BindingIdentifier `(` FormalParameters `)` `{` GeneratorBody `}`
GeneratorDeclaration : `function` `*` `(` FormalParameters `)` `{` GeneratorBody `}`
GeneratorExpression : `function` `*` BindingIdentifier? `(` FormalParameters `)` `{` GeneratorBody `}`
1. Return *false*.
ClassBody : ClassElementList
1. Return *false*.
AsyncMethod : `async` [no LineTerminator here] PropertyName `(` UniqueFormalParameters `)` `{` AsyncFunctionBody `}`
1. Return the result of ContainsArguments for |PropertyName|.
AsyncFunctionDeclaration : `async` [no LineTerminator here] `function` BindingIdentifier `(` FormalParameters `)` `{` AsyncFunctionBody `}`
AsyncFunctionDeclaration : `async` [no LineTerminator here] `function` `(` FormalParameters `)` `{` AsyncFunctionBody `}`
AsyncFunctionExpression : `async` [no LineTerminator here] `function` `(` FormalParameters `)` `{` AsyncFunctionBody `}`
AsyncFunctionExpression : `async` [no LineTerminator here] `function` BindingIdentifier `(` FormalParameters `)` `{` AsyncFunctionBody `}`
1. Return *false*.
For all other grammatical productions, recurse on all nonterminals. If any piece returns *true*, then return *true*. Otherwise return *false*.
TODO: Elaborate the preceding paragraph with spec text inserted in each relevant place
Class Definitions
Static Semantics: IsStatic
ClassElement : FieldDefinition
1. Return *false*.
Runtime Semantics: ClassDefinitionEvaluation
With parameter _className_.
ClassTail : ClassHeritage? `{` ClassBody? `}`
1. Let _lex_ be the LexicalEnvironment of the running execution context.
1. Let _classScope_ be NewDeclarativeEnvironment(_lex_).
1. Let _classScopeEnvRec_ be _classScope_'s EnvironmentRecord.
1. If _className_ is not *undefined*, then
1. Perform _classScopeEnvRec_.CreateImmutableBinding(_className_, *true*).
1. Let _outerPrivateEnvironment_ be the PrivateEnvironment of the running execution context.
1. Let _classPrivateEnvironment_ be NewDeclarativeEnvironment(_outerPrivateEnvironment_).
1. Let _classPrivateEnvRec_ be _classPrivateEnvironment_'s EnvironmentRecord.
1. If |ClassBody_opt| is present, then
1. For each element _dn_ of the PrivateBoundIdentifiers of |ClassBody_opt|,
1. Perform _classPrivateEnvRec_.CreateImmutableBinding(_dn_, *true*).
1. Let _privateName_ be NewPrivateName(_dn_).
1. Perform ! _classPrivateEnvRec_.InitializeBinding(_dn_, _privateName_).
1. If |ClassHeritage_opt| is not present, then
1. Let _protoParent_ be the intrinsic object %ObjectPrototype%.
1. Let _constructorParent_ be the intrinsic object %FunctionPrototype%.
1. Else,
1. Set the running execution context's LexicalEnvironment to _classScope_.
1. NOTE: The running execution context's PrivateEnvironment is _outerPrivateEnvironment_ when evaluating |ClassHeritage|.
1. Let _superclass_ be the result of evaluating |ClassHeritage|.
1. Set the running execution context's LexicalEnvironment to _lex_.
1. ReturnIfAbrupt(_superclass_).
1. If _superclass_ is *null*, then
1. Let _protoParent_ be *null*.
1. Let _constructorParent_ be the intrinsic object %FunctionPrototype%.
1. Else if IsConstructor(_superclass_) is *false*, throw a *TypeError* exception.
1. Else,
1. Let _protoParent_ be ? Get(_superclass_, `"prototype"`).
1. If Type(_protoParent_) is neither Object nor Null, throw a *TypeError* exception.
1. Let _constructorParent_ be _superclass_.
1. Let _proto_ be ObjectCreate(_protoParent_).
1. If |ClassBody_opt| is not present, let _constructor_ be ~empty~.
1. Else, let _constructor_ be ConstructorMethod of |ClassBody|.
1. If _constructor_ is ~empty~, then
1. If |ClassHeritage_opt| is present and _protoParent_ is not *null*, then
1. Let _constructor_ be the result of parsing the source text
constructor(... args){ super (...args);}
using the syntactic grammar with the goal symbol |MethodDefinition[~Yield]|.
1. Else,
1. Let _constructor_ be the result of parsing the source text
constructor( ){ }
using the syntactic grammar with the goal symbol |MethodDefinition[~Yield]|.
1. Set the running execution context's LexicalEnvironment to _classScope_.
1. Set the running execution context's PrivateEnvironment to _classPrivateEnvironment_.
1. Let _constructorInfo_ be the result of performing DefineMethod for _constructor_ with arguments _proto_ and _constructorParent_ as the optional _functionPrototype_ argument.
1. Assert: _constructorInfo_ is not an abrupt completion.
1. Let _F_ be _constructorInfo_.[[Closure]].
1. If |ClassHeritage_opt| is present and _protoParent_ is not *null*, then set _F_.[[ConstructorKind]] to `"derived"`.
1. Perform MakeConstructor(_F_, *false*, _proto_).
1. Perform MakeClassConstructor(_F_).
1. Perform CreateMethodProperty(_proto_, `"constructor"`, _F_).
1. If |ClassBody_opt| is not present, let _methods__elements_ be a new empty List.
1. Else, let _methods__elements_ be NonConstructorMethodDefinitions of |ClassBody|.
1. Let _instanceFields_ be a new empty List.
1. For each |ClassElement| _m__e_ in order from _methods__elements_
1. If IsStatic of _m__e_ is *false*, then
1. Let _field_ be the result of performing PropertyDefinitionEvaluation for _m_ClassElementEvaluation for _e_ with arguments _proto_ and *false*.
1. Else,
1. Let _field_ be the result of performing PropertyDefinitionEvaluation for _m_ClassElementEvaluation for _e_ with arguments _F_ and *false*.
1. If _field_ is an abrupt completion, then
1. Set the running execution context's LexicalEnvironment to _lex_.
1. Set the running execution context's PrivateEnvironment to _outerPrivateEnvironment_.
1. Return Completion(_field_).
1. If _field_ is not ~empty~, append _field_ to _instanceFields_.
1. Set the running execution context's LexicalEnvironment to _lex_.
1. If _className_ is not *undefined*, then
1. Perform _classScopeEnvRec_.InitializeBinding(_className_, _F_).
1. Set _F_.[[Fields]] to _instanceFields_.
1. Set the running execution context's PrivateEnvironment to _outerPrivateEnvironment_.
1. Return _F_.
[[Construct]] ( _argumentsList_, _newTarget_)
The [[Construct]] internal method for an ECMAScript Function object _F_ is
called with parameters _argumentsList_ and _newTarget_. _argumentsList_ is
a possibly empty List of ECMAScript language values. The following steps are
taken:
1. Assert: _F_ is an ECMAScript function object.
1. Assert: Type(_newTarget_) is Object.
1. Let _callerContext_ be the running execution context.
1. Let _kind_ be _F_.[[ConstructorKind]].
1. If _kind_ is `"base"`, then
1. Let _thisArgument_ be ? OrdinaryCreateFromConstructor(_newTarget_, `"%ObjectPrototype%"`).
1. Let _calleeContext_ be PrepareForOrdinaryCall(_F_, _newTarget_).
1. Assert: _calleeContext_ is now the running execution context.
1. If _kind_ is `"base"`, then
1. Perform OrdinaryCallBindThis(_F_, _calleeContext_, _thisArgument_).
1. Let _result_ be InitializeInstanceFields(_thisArgument_, _F_).
1. If _result_ is an abrupt completion, then
1. Remove _calleeContext_ from execution context stack and restore
_callerContext_ as the running execution context.
1. Return Completion(_result_).
1. Let _constructorEnv_ be the LexicalEnvironment of _calleeContext_.
1. Let _envRec_ be _constructorEnv_'s EnvironmentRecord.
1. Let _result_ be OrdinaryCallEvaluateBody(_F_, _argumentsList_).
1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context.
1. If _result_.[[Type]] is ~return~, then
1. If Type(_result_.[[Value]]) is Object, return NormalCompletion(_result_.[[Value]]).
1. If _kind_ is `"base"`, return NormalCompletion(_thisArgument_).
1. If _result_.[[Value]] is not *undefined*, throw a *TypeError* exception.
1. Else, ReturnIfAbrupt(_result_).
1. Return ? _envRec_.GetThisBinding().
Fields are added by the base class constructor when the super chain reaches up to that, rather than by the subclass constructor when creating the object, in order to be analogous to ES2015 subclassable builtins. See this GitHub thread for more discussion.
The `super` Keyword
Runtime Semantics: Evaluation
SuperCall : `super` Arguments
1. Let _newTarget_ be GetNewTarget().
1. If _newTarget_ is *undefined*, throw a *ReferenceError* exception.
1. Let _func_ be ? GetSuperConstructor().
1. Let _argList_ be ArgumentListEvaluation of |Arguments|.
1. ReturnIfAbrupt(_argList_).
1. Let _result_ be ? Construct(_func_, _argList_, _newTarget_).
1. Let _thisER_ be GetThisEnvironment( ).
1. ReturnPerform ? _thisER_.BindThisValue(_result_).
1. Let _F_ be _thisER_.[[FunctionObject]].
1. Assert: _F_ is an ECMAScript function object.
1. Perform ? InitializeInstanceFields(_result_, _F_).
1. Return _result_.
The `delete` Operator
Runtime Semantics: Evaluation
UnaryExpression : `delete` UnaryExpression
1. Let _ref_ be the result of evaluating |UnaryExpression|.
1. ReturnIfAbrupt(_ref_).
1. If Type(_ref_) is not Reference, return *true*.
1. If IsUnresolvableReference(_ref_) is *true*, then
1. Assert: IsStrictReference(_ref_) is *false*.
1. Return *true*.
1. If IsPropertyReference(_ref_) is *true*, then
1. Assert: IsPrivateReference(_ref_) is *false*.
1. If IsSuperReference(_ref_), throw a *ReferenceError* exception.
1. Let _baseObj_ be ! ToObject(GetBase(_ref_)).
1. Let _deleteStatus_ be ? _baseObj_.[[Delete]](GetReferencedName(_ref_)).
1. If _deleteStatus_ is *false* and IsStrictReference(_ref_) is *true*, throw a *TypeError* exception.
1. Return _deleteStatus_.
1. Else _ref_ is a Reference to an Environment Record binding,
1. Let _bindings_ be GetBase(_ref_).
1. Return ? _bindings_.DeleteBinding(GetReferencedName(_ref_)).
When a `delete` operator occurs within strict mode code, a *SyntaxError* exception is thrown if its |UnaryExpression| is a direct reference to a variable, function argument, or function name. In addition, if a `delete` operator occurs within strict mode code and the property to be deleted has the attribute { [[Configurable]]: *false* }, a *TypeError* exception is thrown.
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.
1. Let _callerContext_ be the second to top element of the execution context stack.
1. Let _callerRealm_ be _callerContext_'s Realm.
1. Let _calleeRealm_ be the current Realm Record.
1. Perform ? HostEnsureCanCompileStrings(_callerRealm_, _calleeRealm_).
1. If _newTarget_ is *undefined*, set _newTarget_ to _constructor_.
1. If _kind_ is `"normal"`, then
1. Let _goal_ be the grammar symbol |FunctionBody[~Yield, ~Await]|.
1. Let _parameterGoal_ be the grammar symbol |FormalParameters[~Yield, ~Await]|.
1. Let _fallbackProto_ be `"%FunctionPrototype%"`.
1. Else if _kind_ is `"generator"`, then
1. Let _goal_ be the grammar symbol |GeneratorBody|.
1. Let _parameterGoal_ be the grammar symbol |FormalParameters[+Yield, ~Await]|.
1. Let _fallbackProto_ be `"%Generator%"`.
1. Else,
1. Assert: _kind_ is `"async"`.
1. Let _goal_ be the grammar symbol |AsyncFunctionBody|.
1. Let _parameterGoal_ be the grammar symbol |FormalParameters[~Yield, +Await]|.
1. Let _fallbackProto_ be `"%AsyncFunctionPrototype%"`.
1. Let _argCount_ be the number of elements in _args_.
1. Let _P_ be the empty String.
1. If _argCount_ = 0, let _bodyText_ be the empty String.
1. Else if _argCount_ = 1, let _bodyText_ be _args_[0].
1. Else _argCount_ > 1,
1. Let _firstArg_ be _args_[0].
1. Set _P_ to ? ToString(_firstArg_).
1. Let _k_ be 1.
1. Repeat, while _k_ < _argCount_-1
1. Let _nextArg_ be _args_[_k_].
1. Let _nextArgString_ be ? ToString(_nextArg_).
1. Set _P_ to the result of concatenating the previous value of _P_, the String `","` (a comma), and _nextArgString_.
1. Increase _k_ by 1.
1. Let _bodyText_ be _args_[_k_].
1. Set _bodyText_ to ? ToString(_bodyText_).
1. Let _parameters_ be the result of parsing _P_, interpreted as UTF-16 encoded Unicode text as described in , using _parameterGoal_ as the goal symbol. Throw a *SyntaxError* exception if the parse fails.
1. Let _body_ be the result of parsing _bodyText_, interpreted as UTF-16 encoded Unicode text as described in , using _goal_ as the goal symbol. Throw a *SyntaxError* exception if the parse fails.
1. Let _strict_ be ContainsUseStrict of _body_.
1. 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.
1. If _strict_ is *true* and IsSimpleParameterList of _parameters_ is *false*, throw a *SyntaxError* exception.
1. If any element of the BoundNames of _parameters_ also occurs in the LexicallyDeclaredNames of _body_, throw a *SyntaxError* exception.
1. If _body_ Contains |SuperCall| is *true*, throw a *SyntaxError* exception.
1. If _parameters_ Contains |SuperCall| is *true*, throw a *SyntaxError* exception.
1. If _body_ Contains |SuperProperty| is *true*, throw a *SyntaxError* exception.
1. If _parameters_ Contains |SuperProperty| is *true*, throw a *SyntaxError* exception.
1. If _kind_ is `"generator"`, then
1. If _parameters_ Contains |YieldExpression| is *true*, throw a *SyntaxError* exception.
1. If _kind_ is `"async"`, then
1. If _parameters_ Contains |AwaitExpression| is *true*, throw a *SyntaxError* exception.
1. If _strict_ is *true*, then
1. If BoundNames of _parameters_ contains any duplicate elements, throw a *SyntaxError* exception.
1. Let _privateIdentifiers_ be an empty List.
1. If AllPrivateIdentifiersValid of _body_ with the argument _privateIdentifiers_ is *false*, throw a *SyntaxError* exception.
1. If AllPrivateIdentifiersValid of _parameters_ with the argument _privateIdentifiers_ is *false*, throw a *SyntaxError* exception.
1. Let _proto_ be ? GetPrototypeFromConstructor(_newTarget_, _fallbackProto_).
1. Let _F_ be FunctionAllocate(_proto_, _strict_, _kind_).
1. Let _realmF_ be _F_.[[Realm]].
1. Let _scope_ be _realmF_.[[GlobalEnv]].
1. Let _privateScope_ be NewDeclarativeEnvironment(*null*).
1. Perform FunctionInitialize(_F_, ~Normal~, _parameters_, _body_, _scope_, _privateScope_).
1. If _kind_ is `"generator"`, then
1. Let _prototype_ be ObjectCreate(%GeneratorPrototype%).
1. Perform DefinePropertyOrThrow(_F_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. Else if _kind_ is `"normal"`, perform MakeConstructor(_F_).
1. NOTE: Async functions are not constructable and do not have a [[Construct]] internal method or a `"prototype"` property.
1. Perform SetFunctionName(_F_, `"anonymous"`).
1. Return _F_.
A `prototype` property is created for every non-async function created using CreateDynamicFunction to provide for the possibility that the function will be used as a constructor.
eval ( _x_ )
Runtime Semantics: PerformEval ( _x_, _evalRealm_, _strictCaller_, _direct_ )
The abstract operation PerformEval with arguments _x_, _evalRealm_, _strictCaller_, and _direct_ performs the following steps:
1. Assert: If _direct_ is *false*, then _strictCaller_ is also *false*.
1. If Type(_x_) is not String, return _x_.
1. Let _thisEnvRec_ be ! GetThisEnvironment().
1. If _thisEnvRec_ is a function Environment Record, then
1. Let _F_ be _thisEnvRec_.[[FunctionObject]].
1. Let _inFunction_ be *true*.
1. Let _inMethod_ be _thisEnvRec_.HasSuperBinding().
1. If _F_.[[ConstructorKind]] is `"derived"`, let _inDerivedConstructor_ be *true*; otherwise, let _inDerivedConstructor_ be *false*.
1. Else,
1. Let _inFunction_ be *false*.
1. Let _inMethod_ be *false*.
1. Let _inDerivedConstructor_ be *false*.
1. Let _script_ be the ECMAScript code that is the result of parsing _x_, interpreted as UTF-16 encoded Unicode text as described in , for the goal symbol |Script|. If _inFunction_ is *false*, additional early error rules from are applied. If _inMethod_ is *false*, additional early error rules from are applied. If _inDerivedConstructor_ is *false*, additional early error rules from are applied. If the parse fails, throw a *SyntaxError* exception. If any early errors are detected, throw a *SyntaxError* or a *ReferenceError* exception, depending on the type of the error (but see also clause ). Parsing and early error detection may be interweaved in an implementation-dependent manner.
1. If _script_ Contains |ScriptBody| is *false*, return *undefined*.
1. Let _body_ be the |ScriptBody| of _script_.
1. If _strictCaller_ is *true*, let _strictEval_ be *true*.
1. Else, let _strictEval_ be IsStrict of _script_.
1. Let _ctx_ be the running execution context.
1. NOTE: If _direct_ is *true*, _ctx_ will be the execution context that performed the direct eval. If _direct_ is *false*, _ctx_ will be the execution context for the invocation of the `eval` function.
1. If _direct_ is *true*, then
1. Let _lexEnv_ be NewDeclarativeEnvironment(_ctx_'s LexicalEnvironment).
1. Let _varEnv_ be _ctx_'s VariableEnvironment.
1. Let _privateEnv_ be _ctx_'s PrivateEnvironment.
1. Else,
1. Let _lexEnv_ be NewDeclarativeEnvironment(_evalRealm_.[[GlobalEnv]]).
1. Let _varEnv_ be _evalRealm_.[[GlobalEnv]].
1. Let _privateEnv_ be NewDeclarativeEnvironment(*null*).
1. If _strictEval_ is *true*, set _varEnv_ to _lexEnv_.
1. If _ctx_ is not already suspended, suspend _ctx_.
1. Let _evalCxt_ be a new ECMAScript code execution context.
1. Set the _evalCxt_'s Function to *null*.
1. Set the _evalCxt_'s Realm to _evalRealm_.
1. Set the _evalCxt_'s ScriptOrModule to _ctx_'s ScriptOrModule.
1. Set the _evalCxt_'s VariableEnvironment to _varEnv_.
1. Set the _evalCxt_'s LexicalEnvironment to _lexEnv_.
1. Set the _evalCxt_'s PrivateEnvironment to _privateEnv_.
1. Push _evalCxt_ on to the execution context stack; _evalCxt_ is now the running execution context.
1. Let _result_ be EvalDeclarationInstantiation(_body_, _varEnv_, _lexEnv_, _privateEnv_, _strictEval_).
1. If _result_.[[Type]] is ~normal~, then
1. Set _result_ to the result of evaluating _body_.
1. If _result_.[[Type]] is ~normal~ and _result_.[[Value]] is ~empty~, then
1. Set _result_ to NormalCompletion(*undefined*).
1. Suspend _evalCxt_ and remove it from the execution context stack.
1. Resume the context that is now on the top of the execution context stack as the running execution context.
1. Return Completion(_result_).
Additional Early Error Rules for Eval Inside |Initializer|
These static semantics are applied by PerformEval when a direct eval call occurs inside a class field initializer.
ScriptBody : StatementList
Runtime Semantics: EvalDeclarationInstantiation( _body_, _varEnv_, _lexEnv_, _privateEnv_, _strict_ )
When the abstract operation EvalDeclarationInstantiation is called with arguments _body_, _varEnv_, _lexEnv_, _privateEnv_, and _strict_, the following steps are taken:
1. Let _varNames_ be the VarDeclaredNames of _body_.
1. Let _varDeclarations_ be the VarScopedDeclarations of _body_.
1. Let _lexEnvRec_ be _lexEnv_'s EnvironmentRecord.
1. Let _varEnvRec_ be _varEnv_'s EnvironmentRecord.
1. If _strict_ is *false*, then
1. If _varEnvRec_ is a global Environment Record, then
1. For each _name_ in _varNames_, do
1. If _varEnvRec_.HasLexicalDeclaration(_name_) is *true*, throw a *SyntaxError* exception.
1. NOTE: `eval` will not create a global var declaration that would be shadowed by a global lexical declaration.
1. Let _thisLex_ be _lexEnv_.
1. Assert: The following loop will terminate.
1. Repeat while _thisLex_ is not the same as _varEnv_,
1. Let _thisEnvRec_ be _thisLex_'s EnvironmentRecord.
1. If _thisEnvRec_ is not an object Environment Record, then
1. NOTE: The environment of with statements cannot contain any lexical declaration so it doesn't need to be checked for var/let hoisting conflicts.
1. For each _name_ in _varNames_, do
1. If _thisEnvRec_.HasBinding(_name_) is *true*, then
1. Throw a *SyntaxError* exception.
1. NOTE: Annex defines alternate semantics for the above step.
1. NOTE: A direct eval will not hoist var declaration over a like-named lexical declaration.
1. Let _thisLex_ be _thisLex_'s outer environment reference.
1. Let _privateIdentifiers_ be an empty List.
1. Let _privateEnv_ be _privateEnv_.
1. Repeat while _privateEnv_ is not *null*,
1. For each binding named _N_ in _privateEnv_,
1. If _privateIdentifiers_ does not contain _N_, append _N_ to _privateIdentifiers_.
1. Let _privateEnv_ be _privateEnv_'s outer environment reference.
1. If AllPrivateIdentifiersValid of _body_ with the argument _privateIdentifiers_ is *false*, throw a *SyntaxError* exception.
1. Let _functionsToInitialize_ be a new empty List.
1. Let _declaredFunctionNames_ be a new empty List.
1. For each _d_ in _varDeclarations_, in reverse list order do
1. If _d_ is neither a |VariableDeclaration| nor a |ForBinding| nor a |BindingIdentifier|, then
1. Assert: _d_ is either a |FunctionDeclaration|, a |GeneratorDeclaration|, or an |AsyncFunctionDeclaration|.
1. NOTE If there are multiple function declarations for the same name, the last declaration is used.
1. Let _fn_ be the sole element of the BoundNames of _d_.
1. If _fn_ is not an element of _declaredFunctionNames_, then
1. If _varEnvRec_ is a global Environment Record, then
1. Let _fnDefinable_ be ? _varEnvRec_.CanDeclareGlobalFunction(_fn_).
1. If _fnDefinable_ is *false*, throw a *TypeError* exception.
1. Append _fn_ to _declaredFunctionNames_.
1. Insert _d_ as the first element of _functionsToInitialize_.
1. NOTE: Annex adds additional steps at this point.
1. Let _declaredVarNames_ be a new empty List.
1. For each _d_ in _varDeclarations_, do
1. If _d_ is a |VariableDeclaration|, a |ForBinding|, or a |BindingIdentifier|, then
1. For each String _vn_ in the BoundNames of _d_, do
1. If _vn_ is not an element of _declaredFunctionNames_, then
1. If _varEnvRec_ is a global Environment Record, then
1. Let _vnDefinable_ be ? _varEnvRec_.CanDeclareGlobalVar(_vn_).
1. If _vnDefinable_ is *false*, throw a *TypeError* exception.
1. If _vn_ is not an element of _declaredVarNames_, then
1. Append _vn_ to _declaredVarNames_.
1. NOTE: No abnormal terminations occur after this algorithm step unless _varEnvRec_ is a global Environment Record and the global object is a Proxy exotic object.
1. Let _lexDeclarations_ be the LexicallyScopedDeclarations of _body_.
1. For each element _d_ in _lexDeclarations_ do
1. NOTE Lexically declared names are only instantiated here but not initialized.
1. For each element _dn_ of the BoundNames of _d_ do
1. If IsConstantDeclaration of _d_ is *true*, then
1. Perform ? _lexEnvRec_.CreateImmutableBinding(_dn_, *true*).
1. Else,
1. Perform ? _lexEnvRec_.CreateMutableBinding(_dn_, *false*).
1. For each Parse Node _f_ in _functionsToInitialize_, do
1. Let _fn_ be the sole element of the BoundNames of _f_.
1. Let _fo_ be the result of performing InstantiateFunctionObject for _f_ with arguments _lexEnv_ and _privateEnv_.
1. If _varEnvRec_ is a global Environment Record, then
1. Perform ? _varEnvRec_.CreateGlobalFunctionBinding(_fn_, _fo_, *true*).
1. Else,
1. Let _bindingExists_ be _varEnvRec_.HasBinding(_fn_).
1. If _bindingExists_ is *false*, then
1. Let _status_ be ! _varEnvRec_.CreateMutableBinding(_fn_, *true*).
1. Assert: _status_ is not an abrupt completion because of validation preceding step 12.
1. Perform ! _varEnvRec_.InitializeBinding(_fn_, _fo_).
1. Else,
1. Perform ! _varEnvRec_.SetMutableBinding(_fn_, _fo_, *false*).
1. For each String _vn_ in _declaredVarNames_, in list order do
1. If _varEnvRec_ is a global Environment Record, then
1. Perform ? _varEnvRec_.CreateGlobalVarBinding(_vn_, *true*).
1. Else,
1. Let _bindingExists_ be _varEnvRec_.HasBinding(_vn_).
1. If _bindingExists_ is *false*, then
1. Let _status_ be ! _varEnvRec_.CreateMutableBinding(_vn_, *true*).
1. Assert: _status_ is not an abrupt completion because of validation preceding step 12.
1. Perform ! _varEnvRec_.InitializeBinding(_vn_, *undefined*).
1. Return NormalCompletion(~empty~).
ModuleDeclarationEnvironmentSetup( _module_ )
The ModuleDeclarationEnvironmentSetup abstract operation is used by InnerModuleInstantiation to initialize the Lexical Environment of the module, including resolving all imported bindings.
This abstract operation performs the following steps:
1. For each ExportEntry Record _e_ in _module_.[[IndirectExportEntries]], do
1. Let _resolution_ be ? _module_.ResolveExport(_e_.[[ExportName]], « »).
1. If _resolution_ is *null* or `"ambiguous"`, throw a *SyntaxError* exception.
1. Assert: _resolution_ is a ResolvedBinding Record.
1. Assert: All named exports from _module_ are resolvable.
1. Let _realm_ be _module_.[[Realm]].
1. Assert: _realm_ is not *undefined*.
1. Let _env_ be NewModuleEnvironment(_realm_.[[GlobalEnv]]).
1. Set _module_.[[Environment]] to _env_.
1. Let _envRec_ be _env_'s EnvironmentRecord.
1. For each ImportEntry Record _in_ in _module_.[[ImportEntries]], do
1. Let _importedModule_ be ! HostResolveImportedModule(_module_, _in_.[[ModuleRequest]]).
1. NOTE: The above call cannot fail because imported module requests are a subset of _module_.[[RequestedModules]], and these have been resolved earlier in this algorithm.
1. If _in_.[[ImportName]] is `"*"`, then
1. Let _namespace_ be ? GetModuleNamespace(_importedModule_).
1. Perform ! _envRec_.CreateImmutableBinding(_in_.[[LocalName]], *true*).
1. Call _envRec_.InitializeBinding(_in_.[[LocalName]], _namespace_).
1. Else,
1. Let _resolution_ be ? _importedModule_.ResolveExport(_in_.[[ImportName]], « »).
1. If _resolution_ is *null* or `"ambiguous"`, throw a *SyntaxError* exception.
1. Call _envRec_.CreateImportBinding(_in_.[[LocalName]], _resolution_.[[Module]], _resolution_.[[BindingName]]).
1. Let _code_ be _module_.[[ECMAScriptCode]].
1. Let _varDeclarations_ be the VarScopedDeclarations of _code_.
1. Let _declaredVarNames_ be a new empty List.
1. For each element _d_ in _varDeclarations_, do
1. For each element _dn_ of the BoundNames of _d_, do
1. If _dn_ is not an element of _declaredVarNames_, then
1. Perform ! _envRec_.CreateMutableBinding(_dn_, *false*).
1. Call _envRec_.InitializeBinding(_dn_, *undefined*).
1. Append _dn_ to _declaredVarNames_.
1. Let _lexDeclarations_ be the LexicallyScopedDeclarations of _code_.
1. Let _privateEnv_ be NewDeclarativeEnvironment(*null*).
1. For each element _d_ in _lexDeclarations_, do
1. For each element _dn_ of the BoundNames of _d_, do
1. If IsConstantDeclaration of _d_ is *true*, then
1. Perform ! _envRec_.CreateImmutableBinding(_dn_, *true*).
1. Else,
1. Perform ! _envRec_.CreateMutableBinding(_dn_, *false*).
1
1. Let _fo_ be the result of performing InstantiateFunctionObject for _d_ with arguments _env_ and _privateEnv_.
1. Call _envRec_.InitializeBinding(_dn_, _fo_).
FunctionDeclarationInstantiation ( _func_, _argumentsList_ )
When an execution context is established for evaluating an ECMAScript function a new function Environment Record is created and bindings for each formal parameter are instantiated in that Environment Record. Each declaration in the function body is also instantiated. If the function's formal parameters do not include any default value initializers then the body declarations are instantiated in the same Environment Record as the parameters. If default value parameter initializers exist, a second Environment Record is created for the body declarations. Formal parameters and functions are initialized as part of FunctionDeclarationInstantiation. All other bindings are initialized during evaluation of the function body.
FunctionDeclarationInstantiation is performed as follows using arguments _func_ and _argumentsList_. _func_ is the function object for which the execution context is being established.
1. Let _calleeContext_ be the running execution context.
1. Let _env_ be the LexicalEnvironment of _calleeContext_.
1. Let _envRec_ be _env_'s EnvironmentRecord.
1. Let _code_ be _func_.[[ECMAScriptCode]].
1. Let _strict_ be _func_.[[Strict]].
1. Let _formals_ be _func_.[[FormalParameters]].
1. Let _parameterNames_ be the BoundNames of _formals_.
1. If _parameterNames_ has any duplicate entries, let _hasDuplicates_ be *true*. Otherwise, let _hasDuplicates_ be *false*.
1. Let _simpleParameterList_ be IsSimpleParameterList of _formals_.
1. Let _hasParameterExpressions_ be ContainsExpression of _formals_.
1. Let _varNames_ be the VarDeclaredNames of _code_.
1. Let _varDeclarations_ be the VarScopedDeclarations of _code_.
1. Let _lexicalNames_ be the LexicallyDeclaredNames of _code_.
1. Let _functionNames_ be a new empty List.
1. Let _functionsToInitialize_ be a new empty List.
1. For each _d_ in _varDeclarations_, in reverse list order, do
1. If _d_ is neither a |VariableDeclaration| nor a |ForBinding| nor a |BindingIdentifier|, then
1. Assert: _d_ is either a |FunctionDeclaration|, a |GeneratorDeclaration|, an |AsyncFunctionDeclaration|, or an |AsyncGeneratorDeclaration|.
1. Let _fn_ be the sole element of the BoundNames of _d_.
1. If _fn_ is not an element of _functionNames_, then
1. Insert _fn_ as the first element of _functionNames_.
1. NOTE: If there are multiple function declarations for the same name, the last declaration is used.
1. Insert _d_ as the first element of _functionsToInitialize_.
1. Let _argumentsObjectNeeded_ be *true*.
1. If _func_.[[ThisMode]] is ~lexical~, then
1. NOTE: Arrow functions never have an arguments objects.
1. Set _argumentsObjectNeeded_ to *false*.
1. Else if `"arguments"` is an element of _parameterNames_, then
1. Set _argumentsObjectNeeded_ to *false*.
1. Else if _hasParameterExpressions_ is *false*, then
1. If `"arguments"` is an element of _functionNames_ or if `"arguments"` is an element of _lexicalNames_, then
1. Set _argumentsObjectNeeded_ to *false*.
1. For each String _paramName_ in _parameterNames_, do
1. Let _alreadyDeclared_ be _envRec_.HasBinding(_paramName_).
1. NOTE: Early errors ensure that duplicate parameter names can only occur in non-strict functions that do not have parameter default values or rest parameters.
1. If _alreadyDeclared_ is *false*, then
1. Perform ! _envRec_.CreateMutableBinding(_paramName_, *false*).
1. If _hasDuplicates_ is *true*, then
1. Perform ! _envRec_.InitializeBinding(_paramName_, *undefined*).
1. If _argumentsObjectNeeded_ is *true*, then
1. If _strict_ is *true* or if _simpleParameterList_ is *false*, then
1. Let _ao_ be CreateUnmappedArgumentsObject(_argumentsList_).
1. Else,
1. NOTE: mapped argument object is only provided for non-strict functions that don't have a rest parameter, any parameter default value initializers, or any destructured parameters.
1. Let _ao_ be CreateMappedArgumentsObject(_func_, _formals_, _argumentsList_, _envRec_).
1. If _strict_ is *true*, then
1. Perform ! _envRec_.CreateImmutableBinding(`"arguments"`, *false*).
1. Else,
1. Perform ! _envRec_.CreateMutableBinding(`"arguments"`, *false*).
1. Call _envRec_.InitializeBinding(`"arguments"`, _ao_).
1. Let _parameterBindings_ be a new List of _parameterNames_ with `"arguments"` appended.
1. Else,
1. Let _parameterBindings_ be _parameterNames_.
1. Let _iteratorRecord_ be CreateListIteratorRecord(_argumentsList_).
1. If _hasDuplicates_ is *true*, then
1. Perform ? IteratorBindingInitialization for _formals_ with _iteratorRecord_ and *undefined* as arguments.
1. Else,
1. Perform ? IteratorBindingInitialization for _formals_ with _iteratorRecord_ and _env_ as arguments.
1. If _hasParameterExpressions_ is *false*, then
1. NOTE: Only a single lexical environment is needed for the parameters and top-level vars.
1. Let _instantiatedVarNames_ be a copy of the List _parameterBindings_.
1. For each _n_ in _varNames_, do
1. If _n_ is not an element of _instantiatedVarNames_, then
1. Append _n_ to _instantiatedVarNames_.
1. Perform ! _envRec_.CreateMutableBinding(_n_, *false*).
1. Call _envRec_.InitializeBinding(_n_, *undefined*).
1. Let _varEnv_ be _env_.
1. Let _varEnvRec_ be _envRec_.
1. Else,
1. NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
1. Let _varEnv_ be NewDeclarativeEnvironment(_env_).
1. Let _varEnvRec_ be _varEnv_'s EnvironmentRecord.
1. Set the VariableEnvironment of _calleeContext_ to _varEnv_.
1. Let _instantiatedVarNames_ be a new empty List.
1. For each _n_ in _varNames_, do
1. If _n_ is not an element of _instantiatedVarNames_, then
1. Append _n_ to _instantiatedVarNames_.
1. Perform ! _varEnvRec_.CreateMutableBinding(_n_, *false*).
1. If _n_ is not an element of _parameterBindings_ or if _n_ is an element of _functionNames_, let _initialValue_ be *undefined*.
1. Else,
1. Let _initialValue_ be ! _envRec_.GetBindingValue(_n_, *false*).
1. Call _varEnvRec_.InitializeBinding(_n_, _initialValue_).
1. NOTE: vars whose names are the same as a formal parameter, initially have the same value as the corresponding initialized parameter.
1. NOTE: Annex adds additional steps at this point.
1. If _strict_ is *false*, then
1. Let _lexEnv_ be NewDeclarativeEnvironment(_varEnv_).
1. NOTE: Non-strict functions use a separate lexical Environment Record for top-level lexical declarations so that a direct eval can determine whether any var scoped declarations introduced by the eval code conflict with pre-existing top-level lexically scoped declarations. This is not needed for strict functions because a strict direct eval always places all declarations into a new Environment Record.
1. Else, let _lexEnv_ be _varEnv_.
1. Let _lexEnvRec_ be _lexEnv_'s EnvironmentRecord.
1. Set the LexicalEnvironment of _calleeContext_ to _lexEnv_.
1. Let _lexDeclarations_ be the LexicallyScopedDeclarations of _code_.
1. For each element _d_ in _lexDeclarations_, do
1. NOTE: A lexically declared name cannot be the same as a function/generator declaration, formal parameter, or a var name. Lexically declared names are only instantiated here but not initialized.
1. For each element _dn_ of the BoundNames of _d_, do
1. If IsConstantDeclaration of _d_ is *true*, then
1. Perform ! _lexEnvRec_.CreateImmutableBinding(_dn_, *true*).
1. Else,
1. Perform ! _lexEnvRec_.CreateMutableBinding(_dn_, *false*).
1. Let _privateEnv_ be the PrivateEnvironment of _calleeContext_.
1. For each Parse Node _f_ in _functionsToInitialize_, do
1. Let _fn_ be the sole element of the BoundNames of _f_.
1. Let _fo_ be the result of performing InstantiateFunctionObject for _f_ with arguments _lexEnv_ and _privateEnv_.
1. Perform ! _varEnvRec_.SetMutableBinding(_fn_, _fo_, *false*).
1. Return NormalCompletion(~empty~).
provides an extension to the above algorithm that is necessary for backwards compatibility with web browser implementations of ECMAScript that predate ECMAScript 2015.
Parameter |Initializer|s may contain direct eval expressions. Any top level declarations of such evals are only visible to the eval code (). The creation of the environment for such declarations is described in .
Runtime Semantics: BlockDeclarationInstantiation( _code_, _env_ )
When a |Block| or |CaseBlock| is evaluated a new declarative Environment Record is created and bindings for each block scoped variable, constant, function, or class declared in the block are instantiated in the Environment Record.
BlockDeclarationInstantiation is performed as follows using arguments _code_ and _env_. _code_ is the Parse Node corresponding to the body of the block. _env_ is the Lexical Environment in which bindings are to be created.
1. Let _envRec_ be _env_'s EnvironmentRecord.
1. Assert: _envRec_ is a declarative Environment Record.
1. Let _declarations_ be the LexicallyScopedDeclarations of _code_.
1. Let _privateEnv_ be the running execution context's PrivateEnvironment.
1. For each element _d_ in _declarations_, do
1. For each element _dn_ of the BoundNames of _d_, do
1. If IsConstantDeclaration of _d_ is *true*, then
1. Perform ! _envRec_.CreateImmutableBinding(_dn_, *true*).
1. Else,
1. Perform ! _envRec_.CreateMutableBinding(_dn_, *false*).
1. If _d_ is a |FunctionDeclaration|, a |GeneratorDeclaration|, an |AsyncFunctionDeclaration|, or an |AsyncGeneratorDeclaration|, then
1. Let _fn_ be the sole element of the BoundNames of _d_.
1. Let _fo_ be the result of performing InstantiateFunctionObject for _d_ with arguments _env_ and _privateEnv_.
1. Perform _envRec_.InitializeBinding(_fn_, _fo_).
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*.
1. Let _scope_ be the LexicalEnvironment of the running execution context.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _parameters_ be CoveredFormalsList of |ArrowParameters|.
1. Let _closure_ be FunctionCreate(~Arrow~, _parameters_, |ConciseBody|, _scope_, _privateScope_, _strict_).
1. Return _closure_.
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*.
1. Let _scope_ be the LexicalEnvironment of the running execution context.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _closure_ be GeneratorFunctionCreate(~Normal~, |FormalParameters|, |GeneratorBody|, _scope_, _privateScope_, _strict_).
1. Let _prototype_ be ObjectCreate(%GeneratorPrototype%).
1. Perform DefinePropertyOrThrow(_closure_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. 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*.
1. Let _scope_ be the running execution context's LexicalEnvironment.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _funcEnv_ be NewDeclarativeEnvironment(_scope_).
1. Let _envRec_ be _funcEnv_'s EnvironmentRecord.
1. Let _name_ be StringValue of |BindingIdentifier|.
1. Perform _envRec_.CreateImmutableBinding(_name_, *false*).
1. Let _closure_ be GeneratorFunctionCreate(~Normal~, |FormalParameters|, |GeneratorBody|, _funcEnv_, _privateScope_, _strict_).
1. Let _prototype_ be ObjectCreate(%GeneratorPrototype%).
1. Perform DefinePropertyOrThrow(_closure_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. Perform SetFunctionName(_closure_, _name_).
1. Perform _envRec_.InitializeBinding(_name_, _closure_).
1. Return _closure_.
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*.
1. Let _scope_ be the LexicalEnvironment of the running execution context.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _closure_ be ! AsyncGeneratorFunctionCreate(~Normal~, |FormalParameters|, |AsyncGeneratorBody|, _scope_, _privateScope_, _strict_).
1. Let _prototype_ be ! ObjectCreate(%AsyncGeneratorPrototype%).
1. Perform ! DefinePropertyOrThrow(_closure_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. 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*.
1. Let _scope_ be the running execution context's LexicalEnvironment.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _funcEnv_ be ! NewDeclarativeEnvironment(_scope_).
1. Let _envRec_ be _funcEnv_'s EnvironmentRecord.
1. Let _name_ be StringValue of |BindingIdentifier|.
1. Perform ! _envRec_.CreateImmutableBinding(_name_).
1. Let _closure_ be ! AsyncGeneratorFunctionCreate(~Normal~, |FormalParameters|, |AsyncGeneratorBody|, _funcEnv_, _privateScope_, _strict_).
1. Let _prototype_ be ! ObjectCreate(%AsyncGeneratorPrototype%).
1. Perform ! DefinePropertyOrThrow(_closure_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. Perform ! SetFunctionName(_closure_, _name_).
1. Perform ! _envRec_.InitializeBinding(_name_, _closure_).
1. Return _closure_.
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*.
1. Let _scope_ be the LexicalEnvironment of the running execution context.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _closure_ be ! AsyncFunctionCreate(~Normal~, |FormalParameters|, |AsyncFunctionBody|, _scope_, _privateScope_, _strict_).
1. Return _closure_.
AsyncFunctionExpression : `async` [no LineTerminator here] `function` BindingIdentifier `(` FormalParameters `)` `{` AsyncFunctionBody `}`
1. If the function code for |AsyncFunctionExpression| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*.
1. Let _scope_ be the LexicalEnvironment of the running execution context.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _funcEnv_ be ! NewDeclarativeEnvironment(_scope_).
1. Let _envRec_ be _funcEnv_'s EnvironmentRecord.
1. Let _name_ be StringValue of |BindingIdentifier|.
1. Perform ! _envRec_.CreateImmutableBinding(_name_).
1. Let _closure_ be ! AsyncFunctionCreate(~Normal~, |FormalParameters|, |AsyncFunctionBody|, _funcEnv_, _privateScope_, _strict_).
1. Perform ! SetFunctionName(_closure_, _name_).
1. Perform ! _envRec_.InitializeBinding(_name_, _closure_).
1. Return _closure_.
AsyncArrowFunction : `async` [no LineTerminator here] AsyncArrowBindingIdentifier [no LineTerminator here] `=>` AsyncConciseBody
1. If the function code for this |AsyncArrowFunction| is strict mode code, let _strict_ be *true*. Otherwise, let _strict_ be *false*.
1. Let _scope_ be the LexicalEnvironment of the running execution context.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _parameters_ be |AsyncArrowBindingIdentifier|.
1. Let _closure_ be ! AsyncFunctionCreate(~Arrow~, _parameters_, |AsyncConciseBody|, _scope_, _privateScope_, _strict_).
1. Return _closure_.
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead [no LineTerminator here] `=>` AsyncConciseBody
1. If the function code for this |AsyncArrowFunction| is strict mode code, let _strict_ be *true*. Otherwise, let _strict_ be *false*.
1. Let _scope_ be the LexicalEnvironment of the running execution context.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _head_ be CoveredAsyncArrowHead of |CoverCallExpressionAndAsyncArrowHead|.
1. Let _parameters_ be the |ArrowFormalParameters| of _head_.
1. Let _closure_ be ! AsyncFunctionCreate(~Arrow~, _parameters_, |AsyncConciseBody|, _scope_, _privateScope_, _strict_).
1. Return _closure_.
Runtime Semantics: DefineMethod
With parameters _object_ and optional parameter _functionPrototype_.
MethodDefinition : PropertyName `(` UniqueFormalParameters `)` `{` FunctionBody `}`
1. Let _propKey_ be the result of evaluating |PropertyName|.
1. ReturnIfAbrupt(_propKey_).
1. If the function code for this |MethodDefinition| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*.
1. Let _scope_ be the running execution context's LexicalEnvironment.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. If _functionPrototype_ is present as a parameter, then
1. Let _kind_ be ~Normal~.
1. Let _prototype_ be _functionPrototype_.
1. Else,
1. Let _kind_ be ~Method~.
1. Let _prototype_ be the intrinsic object %FunctionPrototype%.
1. Let _closure_ be FunctionCreate(_kind_, |UniqueFormalParameters|, |FunctionBody|, _scope_, _privateScope_, _strict_, _prototype_).
1. Perform MakeMethod(_closure_, _object_).
1. Return the Record{[[Key]]: _propKey_, [[Closure]]: _closure_}.
Runtime Semantics: PropertyDefinitionEvaluation
With parameters _object_ and _enumerable_.
MethodDefinition : `get` PropertyName `(` `)` `{` FunctionBody `}`
1. Let _propKey_ be the result of evaluating |PropertyName|.
1. ReturnIfAbrupt(_propKey_).
1. If the function code for this |MethodDefinition| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*.
1. Let _scope_ be the running execution context's LexicalEnvironment.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _formalParameterList_ be an instance of the production FormalParameters : [empty].
1. Let _closure_ be FunctionCreate(~Method~, _formalParameterList_, |FunctionBody|, _scope_, _privateScope_, _strict_).
1. Perform MakeMethod(_closure_, _object_).
1. Perform SetFunctionName(_closure_, _propKey_, `"get"`).
1. Let _desc_ be the PropertyDescriptor{[[Get]]: _closure_, [[Enumerable]]: _enumerable_, [[Configurable]]: *true*}.
1. Return ? DefinePropertyOrThrow(_object_, _propKey_, _desc_).
MethodDefinition : `set` PropertyName `(` PropertySetParameterList `)` `{` FunctionBody `}`
1. Let _propKey_ be the result of evaluating |PropertyName|.
1. ReturnIfAbrupt(_propKey_).
1. If the function code for this |MethodDefinition| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*.
1. Let _scope_ be the running execution context's LexicalEnvironment.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _closure_ be FunctionCreate(~Method~, |PropertySetParameterList|, |FunctionBody|, _scope_, _privateScope_, _strict_).
1. Perform MakeMethod(_closure_, _object_).
1. Perform SetFunctionName(_closure_, _propKey_, `"set"`).
1. Let _desc_ be the PropertyDescriptor{[[Set]]: _closure_, [[Enumerable]]: _enumerable_, [[Configurable]]: *true*}.
1. Return ? DefinePropertyOrThrow(_object_, _propKey_, _desc_).
GeneratorMethod : `*` PropertyName `(` UniqueFormalParameters `)` `{` GeneratorBody `}`
1. Let _propKey_ be the result of evaluating |PropertyName|.
1. ReturnIfAbrupt(_propKey_).
1. If the function code for this |GeneratorMethod| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*.
1. Let _scope_ be the running execution context's LexicalEnvironment.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _closure_ be GeneratorFunctionCreate(~Method~, |UniqueFormalParameters|, |GeneratorBody|, _scope_, _privateScope_, _strict_).
1. Perform MakeMethod(_closure_, _object_).
1. Let _prototype_ be ObjectCreate(%GeneratorPrototype%).
1. Perform DefinePropertyOrThrow(_closure_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. Perform SetFunctionName(_closure_, _propKey_).
1. Let _desc_ be the PropertyDescriptor{[[Value]]: _closure_, [[Writable]]: *true*, [[Enumerable]]: _enumerable_, [[Configurable]]: *true*}.
1. Return ? DefinePropertyOrThrow(_object_, _propKey_, _desc_).
AsyncGeneratorMethod : `async` [no LineTerminator here] `*` PropertyName `(` UniqueFormalParameters `)` `{` AsyncGeneratorBody `}`
1. Let _propKey_ be the result of evaluating |PropertyName|.
1. ReturnIfAbrupt(_propKey_).
1. If the function code for this |AsyncGeneratorMethod| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*.
1. Let _scope_ be the running execution context's LexicalEnvironment.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _closure_ be ! AsyncGeneratorFunctionCreate(~Method~, |UniqueFormalParameters|, |AsyncGeneratorBody|, _scope_, _privateScope_, _strict_).
1. Perform ! MakeMethod(_closure_, _object_).
1. Let _prototype_ be ! ObjectCreate(%AsyncGeneratorPrototype%).
1. Perform ! DefinePropertyOrThrow(_closure_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. Perform ! SetFunctionName(_closure_, _propKey_).
1. Let _desc_ be PropertyDescriptor{[[Value]]: _closure_, [[Writable]]: *true*, [[Enumerable]]: _enumerable_, [[Configurable]]: *true*}.
1. Return ? DefinePropertyOrThrow(_object_, _propKey_, _desc_).
AsyncMethod : `async` [no LineTerminator here] PropertyName `(` UniqueFormalParameters `)` `{` AsyncFunctionBody `}`
1. Let _propKey_ be the result of evaluating |PropertyName|.
1. ReturnIfAbrupt(_propKey_).
1. If the function code for this |AsyncMethod| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*.
1. Let _scope_ be the LexicalEnvironment of the running execution context.
1. Let _privateScope_ be the PrivateEnvironment of the running execution context.
1. Let _closure_ be ! AsyncFunctionCreate(~Method~, |UniqueFormalParameters|, |AsyncFunctionBody|, _scope_, _privateScope_, _strict_).
1. Perform ! MakeMethod(_closure_, _object_).
1. Perform ! SetFunctionName(_closure_, _propKey_).
1. Let _desc_ be the PropertyDescriptor{[[Value]]: _closure_, [[Writable]]: *true*, [[Enumerable]]: _enumerable_, [[Configurable]]: *true*}.
1. Return ? DefinePropertyOrThrow(_object_, _propKey_, _desc_).
Private Names and references
The Private Name specification type is used to describe a globally unique record which represents a private field. A Private Name may be installed on any ECMAScript object with the PrivateFieldAdd internal algorithm, and then read or written using PrivateFieldGet and PrivateFieldSet.
Each Private Name holds the following information:
Field
|
Type
|
Description
|
[[Description]]
|
~string~
|
The string value passed to NewPrivateName when creating this Private Name.
|
The list of fields in Private Names is expanded by the private methods and accessor proposal which is closely following this one.
All ECMAScript objects have a new additional internal slot, [[PrivateFieldValues]], which is a List of Records of the form { [[PrivateName]]: Private Name, [[PrivateFieldValue]]: ECMAScript value }. This List represents the values of the private fields for the object. All objects, including Proxies and all host environment-provided objects, have this internal slot, but primitives such as Numbers do not.
Private fields are designed to have semantics analogous to WeakMaps. However, the implied garbage collection semantics are weaker: If all the references to a WeakMap are inaccessible, but there is still a reference to a key which was in the WeakMap, one would expect the value to be eventually collected. However, Private Names specifically do not have this connotation: because the reference from the Private Name to the Value is in a Record which the Object points to, the value would not be collected, even if nothing else points to the Private Name.
Private Names are a specification type here, not directly observable to ECMAScript code. However, in a decorator integration strawman, an object wrapping Private Names would be exposed to allow greater metaprogramming.
Private fields are deliberately inaccessible outside of the class body. It is proposed that there could be an "escape hatch" to access them though some sort of reflective mechanism; see the GitHub thread. This proposal deliberately omits any such escape hatch.
Notational Conventions
When the phrase newly created object appears in this specification, perfom the following steps on the resulting object _obj_:
1. Set _obj_.[[PrivateFieldValues]] to an empty List.
NewPrivateName ( _description_ )
1. Return a new unique Private Name whose [[Description]] value is _description_.
PrivateFieldFind (_P_, _O_)
1. Assert: _P_ is a Private Name.
1. Assert: _O_ is an object with a [[PrivateFieldValues]] internal slot.
1. For each element _entry_ in _O_.[[PrivateFieldValues]],
1. If _entry_.[[PrivateName]] is _P_, return _entry_.
1. Return ~empty~.
PrivateFieldAdd (_P_, _O_, _value_)
1. Assert: _P_ is a Private Name.
1. Assert: Type(_O_) is Object.
1. Let _entry_ be PrivateFieldFind(_P_, _O_).
1. If _entry_ is not ~empty~, throw a *TypeError* exception.
1. Append { [[PrivateName]]: P, [[PrivateFieldValue]]: _value_ } to _O_.[[PrivateFieldValues]].
PrivateFieldGet (_P_, _O_ )
1. Assert: _P_ is a Private Name.
1. Assert: Type(_O_) is Object.
1. Let _entry_ be PrivateFieldFind(_P_, _O_).
1. If _entry_ is ~empty~, throw a *TypeError* exception.
1. Return _entry_.[[PrivateFieldValue]].
PrivateFieldSet (_P_, _O_, _value_ )
1. Assert: _P_ is a Private Name.
1. Assert: Type(_O_) is Object.
1. Let _entry_ be PrivateFieldFind(_P_, _O_).
1. If _entry_ is ~empty~, throw a *TypeError* exception.
1. Set _entry_.[[PrivateFieldValue]] to _value_.
Runtime Semantics: Evaluation
MemberExpression : MemberExpression `.` PrivateIdentifier
1. Let _baseReference_ be the result of evaluating |MemberExpression|.
1. Let _baseValue_ be ? GetValue(_baseReference_).
1. Let _bv_ be ? RequireObjectCoercible(_baseValue_).
1. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|.
1. Return MakePrivateReference(_bv_, _fieldNameString_).
CallExpression : CallExpression `.` PrivateIdentifier
1. Let _baseReference_ be the result of evaluating |CallExpression|.
1. Let _baseValue_ be ? GetValue(_baseReference_).
1. Let _bv_ be ? RequireObjectCoercible(_baseValue_).
1. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|.
1. Return MakePrivateReference(_bv_, _fieldNameString_).
Runtime Semantics: ChainEvaluation
With parameters _baseValue_ and _baseReference_.
OptionalChain : `?.` PrivateIdentifier
1. Let _bv_ be ? RequireObjectCoercible(_baseValue_).
1. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|.
1. Return MakePrivateReference(_bv_, _fieldNameString_).
OptionalChain : OptionalChain `.` PrivateIdentifier
1. Let _optionalChain_ be |OptionalChain|.
1. Let _newReference_ be ? ChainEvaluation of _optionalChain_ with arguments _baseValue_ and _baseReference_.
1. Let _newValue_ be ? GetValue(_newReference_).
1. Let _nv_ be ? RequireObjectCoercible(_newValue_).
1. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|.
1. Return MakePrivateReference(_nv_, _fieldNameString_).
The Reference Specification Type
The Reference type is used to explain the behaviour of such operators as `delete`, `typeof`, the assignment operators, the `super` keyword and other language features. For example, the left-hand operand of an assignment is expected to produce a reference.
A Reference is a resolved name or property binding. A Reference consists of three components, the base value, the referenced name, and the Boolean valued strict reference flag. The base value is either *undefined*, an Object, a Boolean, a String, a Symbol, a Number, or an Environment Record (). A _base_ value of *undefined* indicates that the Reference could not be resolved to a binding. The referenced name is a String value or a Symbol value, or a Private Name.
A Super Reference is a Reference that is used to represent a name binding that was expressed using the super keyword. A Super Reference has an additional _thisValue_ component and its _base_ value will never be an Environment Record.
The following abstract operations are used in this specification to access the components of references:
-
GetBase(V). Returns the _base_ value component of the reference V.
-
GetReferencedName(V). Returns the referenced name component of the reference V.
-
IsStrictReference(V). Returns the strict reference flag component of the reference V.
-
HasPrimitiveBase(V). Returns *true* if Type(_base_) is Boolean, String, Symbol, or Number.
-
IsPropertyReference(V). Returns *true* if either the _base_ value is an object or HasPrimitiveBase(V) is *true*; otherwise returns *false*.
-
IsUnresolvableReference(V). Returns *true* if the _base_ value is *undefined* and *false* otherwise.
-
IsSuperReference(V). Returns *true* if this reference has a _thisValue_ component.
-
IsPrivateReference(V). Returns *true* if the referenced name component of the reference V is a Private Name.
The following abstract operations are used in this specification to operate on references:
GetValue ( _V_ )
1. ReturnIfAbrupt(_V_).
1. If Type(_V_) is not Reference, return _V_.
1. Let _base_ be GetBase(_V_).
1. If IsUnresolvableReference(_V_), throw a *ReferenceError* exception.
1. If IsPropertyReference(_V_), then
1. If HasPrimitiveBase(_V_), then
1. Assert: In this case, _base_ will never be *null* or *undefined*.
1. Let _base_ be ToObject(_base_).
1. If IsPrivateReference(_V_), then
1. Return ? PrivateFieldGet(GetReferencedName(_V_), _base_).
1. Return ? _base_.[[Get]](GetReferencedName(_V_), GetThisValue(_V_)).
1. Else _base_ must be an Environment Record,
1. Return ? _base_.GetBindingValue(GetReferencedName(_V_), IsStrictReference(_V_)) (see ).
The object that may be created in step 5.a.ii is not accessible outside of the above abstract operation and the ordinary object [[Get]] internal method. An implementation might choose to avoid the actual creation of the object.
PutValue ( _V_, _W_ )
1. ReturnIfAbrupt(_V_).
1. ReturnIfAbrupt(_W_).
1. If Type(_V_) is not Reference, throw a *ReferenceError* exception.
1. Let _base_ be GetBase(_V_).
1. If IsUnresolvableReference(_V_), then
1. If IsStrictReference(_V_) is *true*, then
1. Throw a *ReferenceError* exception.
1. Let _globalObj_ be GetGlobalObject().
1. Return ? Set(_globalObj_, GetReferencedName(_V_), _W_, *false*).
1. Else if IsPropertyReference(_V_), then
1. If HasPrimitiveBase(_V_) is *true*, then
1. Assert: In this case, _base_ will never be *null* or *undefined*.
1. Set _base_ to ToObject(_base_).
1. If IsPrivateReference(_V_), then
1. Return ? PrivateFieldSet(GetReferencedName(_V_), _base_, _W_).
1. Else,
1. Let _succeeded_ be ? _base_.[[Set]](GetReferencedName(_V_), _W_, GetThisValue(_V_)).
1. If _succeeded_ is *false* and IsStrictReference(_V_) is *true*, throw a *TypeError* exception.
1. Return.
1. Else _base_ must be an Environment Record.
1. Return ? _base_.SetMutableBinding(GetReferencedName(_V_), _W_, IsStrictReference(_V_)) (see ).
The object that may be created in step 6.a.ii is not accessible outside of the above algorithm and the ordinary object [[Set]] internal method. An implementation might choose to avoid the actual creation of that object.
MakePrivateReference ( _baseValue_, _privateIdentifier_ )
1. Let _env_ be the running execution context's PrivateEnvironment.
1. Let _privateNameBinding_ be ! ResolveBinding(_privateIdentifier_, _env_).
1. Let _privateName_ be GetValue(_privateNameBinding_).
1. Assert: _privateName_ is a Private Name.
1. Return a value of type Reference whose base value is _baseValue_, whose referenced name is _privateName_, whose strict reference flag is *true*.
Lexically Scoped Private Identifiers
Private identifiers follow typical lexical scoping logic. This section contains amended algorithms for managing the scope of private identifiers.
Execution Contexts
Component
|
Purpose
|
LexicalEnvironment
|
Identifies the Lexical Environment used to resolve identifier references made by code within this execution context.
|
VariableEnvironment
|
Identifies the Lexical Environment whose EnvironmentRecord holds bindings created by |VariableStatement|s within this execution context.
|
PrivateEnvironment
|
Identifies the Lexical Environment whose EnvironmentRecord holds internal Private Names created by |FieldDefinition|s.
|
The PrivateEnvironment Lexical Context is always a chain of Declaration Contexts. Each name begins with `"#"`.
Private Names could have been specified by lumping it all into the LexicalEnvironment. However, this would create false conflicts with object environment records that would need to be resolved. Further, it seems logically cleaner to separate out the distinct namespace into a distinct object.
ECMAScript Function Objects
ECMAScript function objects have the additional internal slots listed in .
Internal Slot
|
Type
|
Description
|
[[Environment]]
|
Lexical Environment
|
The Lexical Environment that the function was closed over. Used as the outer environment when evaluating the code of the function.
|
[[PrivateEnvironment]]
|
Lexical Environment
|
The Lexical Environment for Private Names that the function was closed over. Used as the outer environment for Private Names when evaluating the code of the function.
|
[[FormalParameters]]
|
Parse Node
|
The root parse node of the source text that defines the function's formal parameter list.
|
[[FunctionKind]]
|
String
|
Either `"normal"`, `"classConstructor"`, `"generator"`, or `"async"`.
|
[[ECMAScriptCode]]
|
Parse Node
|
The root parse node of the source text that defines the function's body.
|
[[ConstructorKind]]
|
String
|
Either `"base"` or `"derived"`.
|
[[Realm]]
|
Realm Record
|
The 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 Record
|
The 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]]
|
Boolean
|
*true* if this is a strict function, *false* if this is a non-strict function.
|
[[HomeObject]]
|
Object
|
If the function uses `super`, this is the object whose [[GetPrototypeOf]] provides the object where `super` property lookups begin.
|
[[Fields]]
|
List of Records as created by ClassFieldDefinitionEvaluation
|
If the function is a class with instancefield declarations, this is a list of records representing those fields and their initializers.
|
FunctionInitialize ( _F_, _kind_, _ParameterList_, _Body_, _Scope_, _PrivateScope_ )
The abstract operation FunctionInitialize requires the arguments: a function object _F_, _kind_ which is one of (Normal, Method, Arrow), a parameter list Parse Node specified by _ParameterList_, a body Parse Node specified by _Body_, a Lexical Environment specified by _Scope_, and a Lexical environment _PrivateScope_. FunctionInitialize performs the following steps:
1. Let _len_ be the ExpectedArgumentCount of _ParameterList_.
1. Perform ! SetFunctionLength(_F_, _len_).
1. Let _Strict_ be _F_.[[Strict]].
1. Set _F_.[[Environment]] to _Scope_.
1. Set _F_.[[PrivateEnvironment]] to _PrivateScope_.
1. Set _F_.[[FormalParameters]] to _ParameterList_.
1. Set _F_.[[ECMAScriptCode]] to _Body_.
1. Set _F_.[[ScriptOrModule]] to GetActiveScriptOrModule().
1. If _kind_ is ~Arrow~, set _F_.[[ThisMode]] to ~lexical~.
1. Else if _Strict_ is *true*, set _F_.[[ThisMode]] to ~strict~.
1. Else, set _F_.[[ThisMode]] to ~global~.
1. Return _F_.
FunctionCreate ( _kind_, _ParameterList_, _Body_, _Scope_, _PrivateScope_, _Strict_ [ , _prototype_ ] )
The abstract operation FunctionCreate requires the arguments: _kind_ which is one of (Normal, Method, Arrow), a parameter list Parse Node specified by _ParameterList_, a body Parse Node specified by _Body_, a Lexical Environment specified by _Scope_, a Lexical Environment specified by _PrivateScope_, a Boolean flag _Strict_, and optionally, an object _prototype_. FunctionCreate performs the following steps:
1. If _prototype_ is not present, then
1. Set _prototype_ to the intrinsic object %FunctionPrototype%.
1. If _kind_ is not ~Normal~, let _allocKind_ be `"non-constructor"`.
1. Else, let _allocKind_ be `"normal"`.
1. Let _F_ be FunctionAllocate(_prototype_, _Strict_, _allocKind_).
1. Return FunctionInitialize(_F_, _kind_, _ParameterList_, _Body_, _Scope_, _PrivateScope_).
GeneratorFunctionCreate ( _kind_, _ParameterList_, _Body_, _Scope_, _PrivateScope_, _Strict_ )
The abstract operation GeneratorFunctionCreate requires the arguments: _kind_ which is one of (Normal, Method), a parameter list Parse Node specified by _ParameterList_, a body Parse Node specified by _Body_, a Lexical Environment specified by _Scope_, a Lexical Environment specified by _PrivateScope_, and a Boolean flag _Strict_. GeneratorFunctionCreate performs the following steps:
1. Let _functionPrototype_ be the intrinsic object %Generator%.
1. Let _F_ be FunctionAllocate(_functionPrototype_, _Strict_, `"generator"`).
1. Return FunctionInitialize(_F_, _kind_, _ParameterList_, _Body_, _Scope_, _PrivateScope_).
AsyncGeneratorFunctionCreate (_kind_, _ParameterList_, _Body_, _Scope_, _PrivateScope_, _Strict_)
The abstract operation AsyncGeneratorFunctionCreate requires the arguments: _kind_ which is one of (~Normal~, ~Method~), a parameter list Parse Node specified by _ParameterList_, a body Parse Node specified by _Body_, a Lexical Environment specified by _Scope_, a Lexical Environment specified by _PrivateScope_, and a Boolean flag _Strict_. AsyncGeneratorFunctionCreate performs the following steps:
1. Let _functionPrototype_ be the intrinsic object %AsyncGenerator%.
1. Let _F_ be ! FunctionAllocate(_functionPrototype_, _Strict_, `"generator"`).
1. Return ! FunctionInitialize(_F_, _kind_, _ParameterList_, _Body_, _Scope_, _PrivateScope_).
AsyncFunctionCreate ( _kind_, _parameters_, _body_, _Scope_, _PrivateScope_, _Strict_ )
The abstract operation AsyncFunctionCreate requires the arguments: _kind_ which is one of (~Normal~, ~Method~, ~Arrow~), a parameter list Parse Node specified by _parameters_, a body Parse Node specified by _body_, a Lexical Environment specified by _Scope_, a Lexical Environment specified by _PrivateScope_, and a Boolean flag _Strict_. AsyncFunctionCreate performs the following steps:
1. Let _functionPrototype_ be the intrinsic object %AsyncFunctionPrototype%.
2. Let _F_ be ! FunctionAllocate(_functionPrototype_, _Strict_, `"async"`).
3. Return ! FunctionInitialize(_F_, _kind_, _parameters_, _body_, _Scope_, _PrivateScope_).
ScriptEvaluation ( _scriptRecord_ )
1. Let _globalEnv_ be _scriptRecord_.[[Realm]].[[GlobalEnv]].
1. Let _scriptCxt_ be a new ECMAScript code execution context.
1. Set the Function of _scriptCxt_ to *null*.
1. Set the Realm of _scriptCxt_ to _scriptRecord_.[[Realm]].
1. Set the ScriptOrModule of _scriptCxt_ to _scriptRecord_.
1. Set the VariableEnvironment of _scriptCxt_ to _globalEnv_.
1. Set the LexicalEnvironment of _scriptCxt_ to _globalEnv_.
1. Let _privateEnv_ be NewDeclarativeEnvironment(*null*).
1. Set the PrivateEnvironment of _scriptCxt_ to _privateEnv_.
1. Suspend the currently running execution context.
1. Push _scriptCxt_ on to the execution context stack; _scriptCxt_ is now the running execution context.
1. Let _scriptBody_ be _scriptRecord_.[[ECMAScriptCode]].
1. Let _result_ be GlobalDeclarationInstantiation(_scriptBody_, _globalEnv_).
1. If _result_.[[Type]] is ~normal~, then
1. Set _result_ to the result of evaluating _scriptBody_.
1. If _result_.[[Type]] is ~normal~ and _result_.[[Value]] is ~empty~, then
1. Set _result_ to NormalCompletion(*undefined*).
1. Suspend _scriptCxt_ and remove it from the execution context stack.
1. Assert: The execution context stack is not empty.
1. Resume the context that is now on the top of the execution context stack as the running execution context.
1. Return Completion(_result_).
PrepareForOrdinaryCall ( _F_, _newTarget_ )
When the abstract operation PrepareForOrdinaryCall is called with function object _F_ and ECMAScript language value _newTarget_, the following steps are taken:
1. Assert: Type(_newTarget_) is Undefined or Object.
1. Let _callerContext_ be the running execution context.
1. Let _calleeContext_ be a new ECMAScript code execution context.
1. Set the Function of _calleeContext_ to _F_.
1. Let _calleeRealm_ be _F_.[[Realm]].
1. Set the Realm of _calleeContext_ to _calleeRealm_.
1. Set the ScriptOrModule of _calleeContext_ to _F_.[[ScriptOrModule]].
1. Let _localEnv_ be NewFunctionEnvironment(_F_, _newTarget_).
1. Set the LexicalEnvironment of _calleeContext_ to _localEnv_.
1. Set the VariableEnvironment of _calleeContext_ to _localEnv_.
1. Set the PrivateEnvironment of _calleeContext_ to _F_.[[PrivateEnvironment]].
1. If _callerContext_ is not already suspended, suspend _callerContext_.
1. Push _calleeContext_ onto the execution context stack; _calleeContext_ is now the running execution context.
1. NOTE: Any exception objects produced after this point are associated with _calleeRealm_.
1. Return _calleeContext_.
Runtime Semantics: InstantiateFunctionObject
With parameters _scope_ and _privateScope_.
FunctionDeclaration : `function` BindingIdentifier `(` FormalParameters `)` `{` FunctionBody `}`
1. If the function code for |FunctionDeclaration| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*.
1. Let _name_ be StringValue of |BindingIdentifier|.
1. Let _F_ be FunctionCreate(~Normal~, |FormalParameters|, |FunctionBody|, _scope_, _privateScope_, _strict_).
1. Perform MakeConstructor(_F_).
1. Perform SetFunctionName(_F_, _name_).
1. Return _F_.
FunctionDeclaration : `function` `(` FormalParameters `)` `{` FunctionBody `}`
1. Let _F_ be FunctionCreate(~Normal~, |FormalParameters|, |FunctionBody|, _scope_, _privateScope_, *true*).
1. Perform MakeConstructor(_F_).
1. Perform SetFunctionName(_F_, `"default"`).
1. Return _F_.
An anonymous |FunctionDeclaration| can only occur as part of an `export default` declaration, and its function code is therefore always strict mode code.
Runtime Semantics: InstantiateFunctionObject
With parameters _scope_ and _privateScope_.
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*.
1. Let _name_ be StringValue of |BindingIdentifier|.
1. Let _F_ be GeneratorFunctionCreate(~Normal~, |FormalParameters|, |GeneratorBody|, _scope_, _privateScope_, _strict_).
1. Let _prototype_ be ObjectCreate(%GeneratorPrototype%).
1. Perform DefinePropertyOrThrow(_F_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. Perform SetFunctionName(_F_, _name_).
1. Return _F_.
GeneratorDeclaration : `function` `*` `(` FormalParameters `)` `{` GeneratorBody `}`
1. Let _F_ be GeneratorFunctionCreate(~Normal~, |FormalParameters|, |GeneratorBody|, _scope_, _privateScope_, *true*).
1. Let _prototype_ be ObjectCreate(%GeneratorPrototype%).
1. Perform DefinePropertyOrThrow(_F_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. Perform SetFunctionName(_F_, `"default"`).
1. Return _F_.
An anonymous |GeneratorDeclaration| can only occur as part of an `export default` declaration, and its function code is therefore always strict mode code.
Runtime Semantics: InstantiateFunctionObject
With parameters _scope_ and _privateScope_.
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*.
1. Let _name_ be StringValue of |BindingIdentifier|.
1. Let _F_ be ! AsyncGeneratorFunctionCreate(~Normal~, |FormalParameters|, |AsyncGeneratorBody|, _scope_, _privateScope_, _strict_).
1. Let _prototype_ be ! ObjectCreate(%AsyncGeneratorPrototype%).
1. Perform ! DefinePropertyOrThrow(_F_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. Perform ! SetFunctionName(_F_, _name_).
1. 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*.
1. Let _F_ be AsyncGeneratorFunctionCreate(~Normal~, |FormalParameters|, |AsyncGeneratorBody|, _scope_, _privateScope_, _strict_).
1. Let _prototype_ be ObjectCreate(%AsyncGeneratorPrototype%).
1. Perform DefinePropertyOrThrow(_F_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}).
1. Perform SetFunctionName(_F_, `"default"`).
1. Return _F_.
An anonymous |AsyncGeneratorDeclaration| can only occur as part of an `export default` declaration.
Runtime Semantics: InstantiateFunctionObject
With parameters _scope_ and _privateScope_.
AsyncFunctionDeclaration : `async` [no LineTerminator here] `function` BindingIdentifier `(` FormalParameters `)` `{` AsyncFunctionBody `}`
1. If the function code for |AsyncFunctionDeclaration| is strict mode code, let _strict_ be *true*. Otherwise, let _strict_ be *false*.
1. Let _name_ be StringValue of |BindingIdentifier|.
1. Let _F_ be ! AsyncFunctionCreate(~Normal~, |FormalParameters|, |AsyncFunctionBody|, _scope_, _privateScope_, _strict_).
1. Perform ! SetFunctionName(_F_, _name_).
1. 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*.
1. Let _F_ be ! AsyncFunctionCreate(~Normal~, |FormalParameters|, |AsyncFunctionBody|, _scope_, _privateScope_, _strict_).
1. Perform ! SetFunctionName(_F_, `"default"`).
1. Return _F_.
Automatic Semicolon Insertion
Most ECMAScript statements and declarations must beare logically terminated with a semicolon. Such semicolons may always appear explicitly in the source text. For convenience, however, such semicolons may be omitted from the source text in certain situations. These situations are described by saying that semicolons are automatically inserted into the source code token stream in those situations.
Rules of Automatic Semicolon Insertion
In the following rules, “token” means the actual recognized lexical token determined using the current lexical goal symbol as described in clause .
There are three basic rules of semicolon insertion:
-
When, as the source text is parsed from left to right, a token (called the offending token) is encountered that is not allowed by any production of the grammar, then a semicolon is automatically inserted before the offending token if one or more of the following conditions is true:
-
The offending token is separated from the previous token by at least one |LineTerminator|.
-
The offending token is `}`.
-
The previous token is `)` and the inserted semicolon would then be parsed as the terminating semicolon of a do-while statement ().
-
When, as the source text is parsed from left to right, the end of the input stream of tokens is encountered and the parser is unable to parse the input token stream as a single instance of the goal nonterminal, then a semicolon is automatically inserted at the end of the input stream.
-
When, as the source text is parsed from left to right, a token is encountered that is allowed by some production of the grammar, but the production is a restricted production and the token would be the first token for a terminal or nonterminal immediately following the annotation “[no |LineTerminator| here]” within the restricted production (and therefore such a token is called a restricted token), and the restricted token is separated from the previous token by at least one |LineTerminator|, then a semicolon is automatically inserted before the restricted token.
However, there is an additional overriding condition on the preceding rules: a semicolon is never inserted automatically if the semicolon would then be parsed as an empty statement or if that semicolon would become one of the two semicolons in the header of a `for` statement (see ).
The following are the only restricted productions in the grammar:
UpdateExpression[Yield, Await] :
LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] `++`
LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] `--`
ContinueStatement[Yield, Await] :
`continue` `;`
`continue` [no LineTerminator here] LabelIdentifier[?Yield, ?Await] `;`
BreakStatement[Yield, Await] :
`break` `;`
`break` [no LineTerminator here] LabelIdentifier[?Yield, ?Await] `;`
ReturnStatement[Yield, Await] :
`return` `;`
`return` [no LineTerminator here] Expression[+In, ?Yield, ?Await] `;`
ThrowStatement[Yield, Await] :
`throw` [no LineTerminator here] Expression[+In, ?Yield, ?Await] `;`
ArrowFunction[In, Yield, Await] :
ArrowParameters[?Yield, ?Await] [no LineTerminator here] `=>` ConciseBody[?In]
YieldExpression[In, Await] :
`yield` [no LineTerminator here] `*` AssignmentExpression[?In, +Yield, ?Await]
`yield` [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await]
The practical effect of these restricted productions is as follows:
-
When a `++` or `--` token is encountered where the parser would treat it as a postfix operator, and at least one |LineTerminator| occurred between the preceding token and the `++` or `--` token, then a semicolon is automatically inserted before the `++` or `--` token.
-
When a `continue`, `break`, `return`, `throw`, or `yield` token is encountered and a |LineTerminator| is encountered before the next token, a semicolon is automatically inserted after the `continue`, `break`, `return`, `throw`, or `yield` token.
The resulting practical advice to ECMAScript programmers is:
-
A postfix `++` or `--` operator should appear on the same line as its operand.
-
An |Expression| in a `return` or `throw` statement or an |AssignmentExpression| in a `yield` expression should start on the same line as the `return`, `throw`, or `yield` token.
-
A |LabelIdentifier| in a `break` or `continue` statement should be on the same line as the `break` or `continue` token.
Automatic semicolon insertion applies for all source text, including class bodies. In particular, semicolons may be omitted after class field declarations in certain conditions. Although the same insertion logic described above applies within class bodies, the practicalities of writing class bodies in a semicolon-free style differs between class bodies and other ECMAScript code; see for some consequences of this property.
Examples of Automatic Semicolon Insertion
This section is non-normative.
The source
{ 1 2 } 3
is not a valid sentence in the ECMAScript grammar, even with the automatic semicolon insertion rules. In contrast, the source
{ 1
2 } 3
is also not a valid ECMAScript sentence, but is transformed by automatic semicolon insertion into the following:
{ 1
;2 ;} 3;
which is a valid ECMAScript sentence.
The source
for (a; b
)
is not a valid ECMAScript sentence and is not altered by automatic semicolon insertion because the semicolon is needed for the header of a `for` statement. Automatic semicolon insertion never inserts one of the two semicolons in the header of a `for` statement.
The source
return
a + b
is transformed by automatic semicolon insertion into the following:
return;
a + b;
The expression `a + b` is not treated as a value to be returned by the `return` statement, because a |LineTerminator| separates it from the token `return`.
The source
a = b
++c
is transformed by automatic semicolon insertion into the following:
a = b;
++c;
The token `++` is not treated as a postfix operator applying to the variable `b`, because a |LineTerminator| occurs between `b` and `++`.
The source
if (a > b)
else c = d
is not a valid ECMAScript sentence and is not altered by automatic semicolon insertion before the `else` token, even though no production of the grammar applies at that point, because an automatically inserted semicolon would then be parsed as an empty statement.
The source
a = b + c
(d + e).print()
is not transformed by automatic semicolon insertion, because the parenthesized expression that begins the second line can be interpreted as an argument list for a function call:
a = b + c(d + e).print()
In the circumstance that an assignment statement must begin with a left parenthesis, it is a good idea for the programmer to provide an explicit semicolon at the end of the preceding statement rather than to rely on automatic semicolon insertion.
Hazards of Automatic Semicolon Insertion
This section is non-normative.
ECMAScript programs can be written in a style with very few semicolons, based on a heavy dependence on automatic semicolon insertion. However, as described above, semicolons are not inserted at every newline, and some of these cases which do not have an automatically inserted semicolon can be counter-intuitive or confusing.
As new syntactic features are added to ECMAScript, additional cases requiring explicit semicolons emerge over time. As such, consistently explicit semicolon use is recommended.
The term "automatic semicolon insertion hazard" refers, informally, to a place where a developer may expect a semicolon to be inserted, but according to the rules described above, it is not. The rest of this section describes a number of automatic semicolon insertion hazards in this version of ECMAScript.
Automatic Semicolon Insertion Hazards in Statement Lists
In a |StatementList|, many |StatementListItem|s end in semicolons, which may be omitted using automatic semicolon insertion. As a consequence of the rules above, at the end of a line ending an expression, a semicolon will be required if the following line begins with any of the following:
- An opening parenthesis (
(
). Without a semicolon, the two lines together will be treated as a function call.
- An opening square bracket (
[
). Without a semicolon, the two lines together will be treated as property access, rather than an array literal.
- A template string (
`
). Without a semicolon, the two lines together will be interpreted as tagged template literal, with the previous expression as the function tag.
- Unary
+
or -
. Without a semicolon, the two lines together will be interpreted as a usage of the corresponding infix operator.
- A RegExp literal. Without a semicolon, the two lines together may be parsed instead as a division, for example if the RegExp has flags.
Automatic Semicolon Insertion Hazards in the Top Level of Class Bodies
At the top level of class bodies, the only significant case where semicolons are used is in field declarations. As a consequence of the rules above, at the end of a field declaration with an initializer expression, a semicolon is required if the following line begins with any of the following:
- A computed property name field or method. Without a semicolon, a field declaration with a computed property name will be treated as a property access; a method with a computed property name would be a Syntax Error.
- A generator method. A missing semicolon is a Syntax Error.
- A field named
in
or instanceof
. Without a semicolon, those tokens will instead be interpreted as an operator.
Additionally, the declaration of a field named get
, set
or static
, if it does not have an initializer, is not at the end of the class body, and is not followed by a non-static non-async generator method, requires a semicolon. Without a semicolon, these tokens will be treated as modifiers to the following class element declaration. Note that async
does not have this property, as async method declarations do not permit a newline between the async
token and the method name.