Stage 1 Draft / September 9, 2020

ECMAScript 'class'-property access expressions

Introduction

This proposal defines new syntax to access static members of the containing lexical class declaration.

See the proposal repository for background material and discussion.

1 Executable Code and Execution Contexts

1.1 Environment Records

1.1.1 The Environment Record Type Hierarchy

The Environment Record abstract class includes the abstract specification methods defined in Table 1. These abstract methods have distinct concrete algorithms for each of the concrete subclasses.

Table 1: Abstract Methods of Environment Records
Method Purpose
HasBinding(N) Determine if an Environment Record has a binding for the String value N. Return true if it does and false if it does not.
CreateMutableBinding(N, D) Create a new but uninitialized mutable binding in an Environment Record. The String value N is the text of the bound name. If the Boolean argument D is true the binding may be subsequently deleted.
CreateImmutableBinding(N, S) Create a new but uninitialized immutable binding in an Environment Record. The String value N is the text of the bound name. If S is true then attempts to set it after it has been initialized will always throw an exception, regardless of the strict mode setting of operations that reference that binding.
InitializeBinding(N, V) Set the value of an already existing but uninitialized binding in an Environment Record. The String value N is the text of the bound name. V is the value for the binding and is a value of any ECMAScript language type.
SetMutableBinding(N, V, S) Set the value of an already existing mutable binding in an Environment Record. The String value N is the text of the bound name. V is the value for the binding and may be a value of any ECMAScript language type. S is a Boolean flag. If S is true and the binding cannot be set throw a TypeError exception.
GetBindingValue(N, S) Returns the value of an already existing binding from an Environment Record. The String value N is the text of the bound name. S is used to identify references originating in strict mode code or that otherwise require strict mode reference semantics. If S is true and the binding does not exist throw a ReferenceError exception. If the binding exists but is uninitialized a ReferenceError is thrown, regardless of the value of S.
DeleteBinding(N) Delete a binding from an Environment Record. The String value N is the text of the bound name. If a binding for N exists, remove the binding and return true. If the binding exists but cannot be removed return false. If the binding does not exist return true.
HasThisBinding() Determine if an Environment Record establishes a this binding. Return true if it does and false if it does not.
HasSuperBinding() Determine if an Environment Record establishes a super method binding. Return true if it does and false if it does not.
HasClassBinding() Determine if an Environment Record establishes a class binding. Return true if it does and false if it does not.
WithBaseObject() If this Environment Record is associated with a with statement, return the with object. Otherwise, return undefined.

1.1.1.1 Declarative Environment Records

1.1.1.1.1 HasClassBinding ( )

Regular declarative Environment Records do not provide a class binding.

  1. Return false.

1.1.1.2 Object Environment Records

1.1.1.2.1 HasClassBinding ( )

Regular object Environment Records do not provide a class binding.

  1. Return false.

1.1.1.3 Function Environment Records

A function Environment Record is a declarative Environment Record that is used to represent the top-level scope of a function and, if the function is not an ArrowFunction, provides a this binding. If a function is not an ArrowFunction function and references super, its function Environment Record also contains the state that is used to perform super method invocations from within the function. If a function is not an ArrowFunction function and references class, its function Environment Record also contains the state that is used to perform class property acccess from within the function.

Function Environment Records have the additional state fields listed in Table 2.

Table 2: Additional Fields of Function Environment Records
Field Name Value Meaning
[[ThisValue]] Any This is the this value used for this invocation of the function.
[[ThisBindingStatus]] lexical | initialized | uninitialized If the value is lexical, this is an ArrowFunction and does not have a local this value.
[[FunctionObject]] Object The function object whose invocation caused this Environment Record to be created.
[[HomeObject]] Object | undefined If the associated function has super property accesses and is not an ArrowFunction, [[HomeObject]] is the object that the function is bound to as a method. The default value for [[HomeObject]] is undefined.
[[InitialClassObject]] Object | undefined If the associated function has class property access and is not an ArrowFunction, [[InitialClassObject]] is the class constructor function object that the function was initially bound to as a method. The default value for [[InitialClassObject]] is undefined.
[[NewTarget]] Object | undefined If this Environment Record was created by the [[Construct]] internal method, [[NewTarget]] is the value of the [[Construct]] newTarget parameter. Otherwise, its value is undefined.

Function Environment Records support all of the declarative Environment Record methods listed in Table 1 and share the same specifications for all of those methods except for HasThisBinding and HasSuperBinding, HasSuperBinding, and HasClassBinding. In addition, function Environment Records support the methods listed in Table 3:

Table 3: Additional Methods of Function Environment Records
Method Purpose
BindThisValue(V) Set the [[ThisValue]] and record that it has been initialized.
GetThisBinding() Return the value of this Environment Record's this binding. Throws a ReferenceError if the this binding has not been initialized.
GetSuperBase() Return the object that is the base for super property accesses bound in this Environment Record. The object is derived from this Environment Record's [[HomeObject]] field. The value undefined indicates that super property accesses will produce runtime errors.
GetClassBinding() Return the object that is the base for class property accesses bound in this Environment Record. The object is derived from this Environment Record's [[InitialClassObject]] field. The value undefined indicates that class property accesses will produce runtime errors.

The behaviour of the additional concrete specification methods for function Environment Records is defined by the following algorithms:

1.1.1.3.1 HasClassBinding ( )

  1. Let envRec be the function Environment Record for which the method was invoked.
  2. If envRec.[[ThisBindingStatus]] is lexical, return false.
  3. If envRec.[[InitialClassObject]] has the value undefined, return false; otherwise, return true.

1.1.1.3.2 GetClassBinding ( )

  1. Let envRec be the function Environment Record for which the method was invoked.
  2. Let classObject be envRec.[[InitialClassObject]].
  3. If classObject has the value undefined, return undefined.
  4. Assert: Type(classObject) is Object.
  5. Return ? classObject.

1.1.1.4 Global Environment Records

1.1.1.4.1 HasClassBinding ( )

  1. Return false.

1.1.2 Environment Record Operations

1.1.2.1 NewFunctionEnvironment ( F, newTarget )

The abstract operation NewFunctionEnvironment takes arguments F and newTarget. It performs the following steps when called:

  1. Assert: F is an ECMAScript function.
  2. Assert: Type(newTarget) is Undefined or Object.
  3. Let env be a new function Environment Record containing no bindings.
  4. Set env.[[FunctionObject]] to F.
  5. If F.[[ThisMode]] is lexical, set env.[[ThisBindingStatus]] to lexical.
  6. Else, set env.[[ThisBindingStatus]] to uninitialized.
  7. Let home be F.[[HomeObject]].
  8. Set env.[[HomeObject]] to home.
  9. Let classObject be F.[[InitialClassObject]].
  10. Set env.[[InitialClassObject]] to classObject.
  11. Set env.[[NewTarget]] to newTarget.
  12. Set env.[[OuterEnv]] to F.[[Environment]].
  13. Return env.

1.2 Execution Contexts

1.2.1 GetClassEnvironment ( )

The abstract operation GetClassEnvironment takes no arguments. It finds the Environment Record that currently supplies the binding of the keyword class for a ClassProperty. It performs the following steps when called:

  1. Let env be GetThisEnvironment().
  2. Let exists be env.HasClassBinding().
  3. If exists is true, return env.
  4. Return undefined.

2 Ordinary and Exotic Object Behaviors

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

In addition to [[Extensible]] and [[Prototype]], ECMAScript function objects also have the internal slots listed in Table 4.

Table 4: Internal Slots of ECMAScript Function Objects
Internal Slot Type Description
[[Environment]] Environment Record The Environment Record that the function was closed over. Used as the outer environment 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.
[[ECMAScriptCode]] Parse Node The root parse node of the source text that defines the function's body.
[[ConstructorKind]] base | derived Whether or not the function is a derived class constructor.
[[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 or null is interpreted as a reference to the global object, and any other this value is first passed to ToObject.
[[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.
[[InitialClassObject]] Object | undefined If the function has class property access, this is the function object where class property lookups begin.
[[SourceText]] sequence of Unicode code points The source text that defines the function.
[[IsClassConstructor]] Boolean Indicates whether the function is a class constructor. (If true, invoking the function's [[Call]] will immediately throw a TypeError exception.)

2.1.1 MakeMethod ( F, homeObject, classObject )

The abstract operation MakeMethod takes arguments F and homeObject, homeObject, and classObject. It configures F as a method. It performs the following steps when called:

  1. Assert: F is an ECMAScript function object.
  2. Assert: Type(homeObject) is Object.
  3. Assert: Type(classObject) is either Object or Undefined.
  4. Set F.[[HomeObject]] to homeObject.
  5. Set F.[[InitialClassObject]] to classObject.
  6. Return NormalCompletion(undefined).

3 ECMAScript Language: Expressions

3.1 Primary Expression

3.1.1 Object Initializer

3.1.1.1 Runtime Semantics: PropertyDefinitionEvaluation

With parameters object and enumerable, enumerable, and optional parameter classObject.

PropertyDefinitionList:PropertyDefinitionList,PropertyDefinition
  1. Assert: classObject is not present or Type(classObject) is Undefined.
  2. Perform ? PropertyDefinitionEvaluation of PropertyDefinitionList with arguments object and enumerable.
  3. Return the result of performing PropertyDefinitionEvaluation of PropertyDefinition with arguments object and enumerable.
PropertyDefinition:...AssignmentExpression
  1. Assert: classObject is not present or Type(classObject) is Undefined.
  2. Let exprValue be the result of evaluating AssignmentExpression.
  3. Let fromValue be ? GetValue(exprValue).
  4. Let excludedNames be a new empty List.
  5. Return ? CopyDataProperties(object, fromValue, excludedNames).
PropertyDefinition:IdentifierReference
  1. Assert: classObject is not present or Type(classObject) is Undefined.
  2. Let propName be StringValue of IdentifierReference.
  3. Let exprValue be the result of evaluating IdentifierReference.
  4. Let propValue be ? GetValue(exprValue).
  5. Assert: enumerable is true.
  6. Assert: object is an ordinary, extensible object with no non-configurable properties.
  7. Return ! CreateDataPropertyOrThrow(object, propName, propValue).
PropertyDefinition:PropertyName:AssignmentExpression
  1. Assert: classObject is not present or Type(classObject) is Undefined.
  2. Let propKey be the result of evaluating PropertyName.
  3. ReturnIfAbrupt(propKey).
  4. If IsAnonymousFunctionDefinition(AssignmentExpression) is true, then
    1. Let propValue be NamedEvaluation of AssignmentExpression with argument propKey.
  5. Else,
    1. Let exprValueRef be the result of evaluating AssignmentExpression.
    2. Let propValue be ? GetValue(exprValueRef).
  6. Assert: enumerable is true.
  7. Assert: object is an ordinary, extensible object with no non-configurable properties.
  8. Return ! CreateDataPropertyOrThrow(object, propKey, propValue).
Note

An alternative semantics for this production is given in B.3.1.

3.2 Left-Hand-Side Expressions

Syntax

MemberExpression[Yield, Await]:PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await][Expression[+In, ?Yield, ?Await]] MemberExpression[?Yield, ?Await].IdentifierName MemberExpression[?Yield, ?Await]TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] ClassProperty[?Yield, ?Await] MetaProperty newMemberExpression[?Yield, ?Await]Arguments[?Yield, ?Await] ClassProperty[Yield, Await]:class[Expression[+In, ?Yield, ?Await]] class.IdentifierName class.PrivateIdentifier

3.2.1 Static Semantics

3.2.1.1 Static Semantics: Contains

With parameter symbol.

MemberExpression:MemberExpression.IdentifierName
  1. If MemberExpression Contains symbol is true, return true.
  2. Return false.
SuperProperty:super.IdentifierName
  1. If symbol is the ReservedWord super, return true.
  2. Return false.
ClassProperty:class.IdentifierName
  1. If symbol is the ReservedWord class, return true.
  2. Return false.
CallExpression:CallExpression.IdentifierName
  1. If CallExpression Contains symbol is true, return true.
  2. Return false.
OptionalChain:?.IdentifierName
  1. Return false.
OptionalChain:OptionalChain.IdentifierName
  1. If OptionalChain Contains symbol is true, return true.
  2. Return false.

3.2.1.2 Static Semantics: IsFunctionDefinition

MemberExpression:MemberExpression[Expression] MemberExpression.IdentifierName MemberExpressionTemplateLiteral SuperProperty ClassProperty MetaProperty newMemberExpressionArguments NewExpression:newNewExpression LeftHandSideExpression:CallExpression OptionalExpression
  1. Return false.

3.2.1.3 Static Semantics: IsDestructuring

MemberExpression:PrimaryExpression
  1. If PrimaryExpression is either an ObjectLiteral or an ArrayLiteral, return true.
  2. Return false.
MemberExpression:MemberExpression[Expression] MemberExpression.IdentifierName MemberExpressionTemplateLiteral SuperProperty ClassProperty MetaProperty newMemberExpressionArguments NewExpression:newNewExpression LeftHandSideExpression:CallExpression OptionalExpression
  1. Return false.

3.2.1.4 Static Semantics: IsIdentifierRef

MemberExpression:MemberExpression[Expression] MemberExpression.IdentifierName MemberExpressionTemplateLiteral SuperProperty ClassProperty MetaProperty newMemberExpressionArguments NewExpression:newNewExpression LeftHandSideExpression:CallExpression OptionalExpression
  1. Return false.

3.2.1.5 Static Semantics: AssignmentTargetType

CallExpression:CallExpression[Expression] CallExpression.IdentifierName MemberExpression:MemberExpression[Expression] MemberExpression.IdentifierName SuperProperty ClassProperty
  1. Return simple.

3.2.2 The class keyword

3.2.2.1 Runtime Semantics: Evaluation

ClassProperty:class[Expression]
  1. Let env be GetClassEnvironment().
  2. If env is undefined throw a TypeError exception.
  3. Let classObject be ? env.GetClassBinding().
  4. If classObject is undefined throw a TypeError exception.
  5. If the code matched by this ClassProperty is strict mode code, let strict be true; else let strict be false.
  6. Return ? EvaluatePropertyAccessWithExpressionKey(classObject, Expression, strict).
ClassProperty:class.IdentifierName
  1. Let env be GetClassEnvironment().
  2. If env is undefined throw a TypeError exception.
  3. Let classObject be ? env.GetClassBinding().
  4. If classObject is undefined throw a TypeError exception.
  5. If the code matched by this ClassProperty is strict mode code, let strict be true; else let strict be false.
  6. Return ? EvaluatePropertyAccessWithIdentifierKey(classObject, IdentifierName, strict).
ClassProperty:class.PrivateIdentifier
  1. Let env be GetClassEnvironment().
  2. If env is undefined throw a TypeError exception.
  3. Let classObject be ? env.GetClassBinding().
  4. If classObject is undefined throw a TypeError exception.
  5. Return ? MakePrivateReference(classObject, PrivateIdentifier).

4 ECMAScript Language: Functions and Classes

4.1 Function Definitions

4.1.1 Static Semantics: Early Errors

FunctionDeclaration:functionBindingIdentifier(FormalParameters){FunctionBody} FunctionDeclaration:function(FormalParameters){FunctionBody} FunctionExpression:functionBindingIdentifieropt(FormalParameters){FunctionBody}

4.2 Arrow Function Definitions

4.2.1 Static Semantics: Contains

With parameter symbol.

ArrowFunction:ArrowParameters=>ConciseBody
  1. If symbol is not one of NewTarget, SuperProperty, SuperCall, ClassProperty, super, class or this, return false.
  2. If ArrowParameters Contains symbol is true, return true.
  3. Return ConciseBody Contains symbol.
Note

Normally, Contains does not look inside most function forms. However, Contains is used to detect new.target, this, and super, super and class-property usage within an ArrowFunction.

4.2.2 Runtime Semantics: NamedEvaluation

With parameter name.

ArrowFunction:ArrowParameters=>ConciseBody
  1. Let scope be the LexicalEnvironment of the running execution context.
  2. Let sourceText be the source text matched by ArrowFunction.
  3. Let parameters be CoveredFormalsList of ArrowParameters.
  4. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, parameters, ConciseBody, lexical-this, scope).
  5. Perform SetFunctionName(closure, name).
  6. Return closure.
Note

An ArrowFunction does not define local bindings for arguments, super, class, this, or new.target. Any reference to arguments, super, class, 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 or class is always contained within a non-ArrowFunction and the necessary state to implement super or class is accessible via the scope that is captured by the function object of the ArrowFunction.

4.3 Method Definitions

4.3.1 Runtime Semantics: DefineMethod

With parameter object and optional parameter functionPrototypeparameters functionPrototype and classObject.

MethodDefinition:PropertyName(UniqueFormalParameters){FunctionBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. Let scope be the running execution context's LexicalEnvironment.
  4. If functionPrototype is present, then
    1. Let prototype be functionPrototype.
  5. Else,
    1. Let prototype be %Function.prototype%.
  6. Let sourceText be the source text matched by MethodDefinition.
  7. Let closure be OrdinaryFunctionCreate(prototype, sourceText, UniqueFormalParameters, FunctionBody, non-lexical-this, scope).
  8. Perform MakeMethod(closure, object, classObject).
  9. Return the Record { [[Key]]: propKey, [[Closure]]: closure }.

4.3.2 Runtime Semantics: PropertyDefinitionEvaluation

With parameters object and enumerable, enumerable, and optional parameter classObject.

MethodDefinition:PropertyName(UniqueFormalParameters){FunctionBody}
  1. Let methodDef be ? DefineMethod of MethodDefinition with argument objectarguments object, undefined, and classObject.
  2. Perform SetFunctionName(methodDef.[[Closure]], methodDef.[[Key]]).
  3. Let desc be the PropertyDescriptor { [[Value]]: methodDef.[[Closure]], [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }.
  4. Return ? DefinePropertyOrThrow(object, methodDef.[[Key]], desc).
MethodDefinition:getPropertyName(){FunctionBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. Let scope be the running execution context's LexicalEnvironment.
  4. Let sourceText be the source text matched by MethodDefinition.
  5. Let formalParameterList be an instance of the production FormalParameters:[empty] .
  6. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameterList, FunctionBody, non-lexical-this, scope).
  7. Perform MakeMethod(closure, object, classObject).
  8. Perform SetFunctionName(closure, propKey, "get").
  9. Let desc be the PropertyDescriptor { [[Get]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }.
  10. Return ? DefinePropertyOrThrow(object, propKey, desc).
MethodDefinition:setPropertyName(PropertySetParameterList){FunctionBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. Let scope be the running execution context's LexicalEnvironment.
  4. Let sourceText be the source text matched by MethodDefinition.
  5. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, PropertySetParameterList, FunctionBody, non-lexical-this, scope).
  6. Perform MakeMethod(closure, object, classObject).
  7. Perform SetFunctionName(closure, propKey, "set").
  8. Let desc be the PropertyDescriptor { [[Set]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }.
  9. Return ? DefinePropertyOrThrow(object, propKey, desc).

4.4 Generator Function Definitions

4.4.1 Static Semantics: Early Errors

GeneratorDeclaration:function*BindingIdentifier(FormalParameters){GeneratorBody} GeneratorDeclaration:function*(FormalParameters){GeneratorBody} GeneratorExpression:function*BindingIdentifieropt(FormalParameters){GeneratorBody}

4.4.2 Runtime Semantics: PropertyDefinitionEvaluation

With parameters object and enumerable, enumerable, and optional parameter classObject.

GeneratorMethod:*PropertyName(UniqueFormalParameters){GeneratorBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. Let scope be the running execution context's LexicalEnvironment.
  4. Let sourceText be the source text matched by GeneratorMethod.
  5. Let closure be OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, UniqueFormalParameters, GeneratorBody, non-lexical-this, scope).
  6. Perform MakeMethod(closure, object, classObject).
  7. Perform SetFunctionName(closure, propKey).
  8. Let prototype be ! OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
  9. Perform DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  10. Let desc be the PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }.
  11. Return ? DefinePropertyOrThrow(object, propKey, desc).

4.5 Async Generator Function Definitions

4.5.1 Static Semantics: Early Errors

AsyncGeneratorDeclaration:asyncfunction*BindingIdentifier(FormalParameters){AsyncGeneratorBody} AsyncGeneratorDeclaration:asyncfunction*(FormalParameters){AsyncGeneratorBody} AsyncGeneratorExpression:asyncfunction*BindingIdentifieropt(FormalParameters){AsyncGeneratorBody}

4.5.2 Runtime Semantics: PropertyDefinitionEvaluation

With parameter object and enumerable, enumerable, and optional parameter classObject.

AsyncGeneratorMethod:async*PropertyName(UniqueFormalParameters){AsyncGeneratorBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. Let scope be the running execution context's LexicalEnvironment.
  4. Let sourceText be the source text matched by AsyncGeneratorMethod.
  5. Let closure be ! OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, UniqueFormalParameters, AsyncGeneratorBody, non-lexical-this, scope).
  6. Perform ! MakeMethod(closure, object, classObject).
  7. Perform ! SetFunctionName(closure, propKey).
  8. Let prototype be ! OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
  9. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  10. Let desc be PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }.
  11. Return ? DefinePropertyOrThrow(object, propKey, desc).

4.6 Class Definitions

4.6.1 Runtime Semantics: ClassDefinitionEvaluation

With parameters classBinding and className.

ClassTail:ClassHeritageopt{ClassBodyopt}
  1. Let env be the LexicalEnvironment of the running execution context.
  2. Let classScope be NewDeclarativeEnvironment(env).
  3. If classBinding is not undefined, then
    1. Perform classScope.CreateImmutableBinding(classBinding, true).
  4. If ClassHeritageopt is not present, then
    1. Let protoParent be %Object.prototype%.
    2. Let constructorParent be %Function.prototype%.
  5. Else,
    1. Set the running execution context's LexicalEnvironment to classScope.
    2. Let superclassRef be the result of evaluating ClassHeritage.
    3. Set the running execution context's LexicalEnvironment to env.
    4. Let superclass be ? GetValue(superclassRef).
    5. If superclass is null, then
      1. Let protoParent be null.
      2. Let constructorParent be %Function.prototype%.
    6. Else if IsConstructor(superclass) is false, throw a TypeError exception.
    7. Else,
      1. Let protoParent be ? Get(superclass, "prototype").
      2. If Type(protoParent) is neither Object nor Null, throw a TypeError exception.
      3. Let constructorParent be superclass.
  6. Let proto be ! OrdinaryObjectCreate(protoParent).
  7. If ClassBodyopt is not present, let constructor be empty.
  8. Else, let constructor be ConstructorMethod of ClassBody.
  9. If constructor is empty, then
    1. If ClassHeritageopt is present, then
      1. Set constructor to the result of parsing the source text
        constructor(...args) { super(...args); }
        using the syntactic grammar with the goal symbol MethodDefinition[~Yield, ~Await].
    2. Else,
      1. Set constructor to the result of parsing the source text
        constructor() {}
        using the syntactic grammar with the goal symbol MethodDefinition[~Yield, ~Await].
  10. Set the running execution context's LexicalEnvironment to classScope.
  11. Let constructorInfo be ! DefineMethod of constructor with arguments proto and constructorParent.
  12. Let F be constructorInfo.[[Closure]].
  13. Perform SetFunctionName(F, className).
  14. Perform MakeConstructor(F, false, proto).
  15. If ClassHeritageopt is present, set F.[[ConstructorKind]] to derived.
  16. Set F.[[InitialClassObject]] to F.
  17. Perform MakeClassConstructor(F).
  18. Perform CreateMethodProperty(proto, "constructor", F).
  19. If ClassBodyopt is not present, let methods be a new empty List.
  20. Else, let methods be NonConstructorMethodDefinitions of ClassBody.
  21. For each ClassElement m of methods, do
    1. If IsStatic of m is false, then
      1. Let status be PropertyDefinitionEvaluation of m with arguments proto and false, false, and F.
    2. Else,
      1. Let status be PropertyDefinitionEvaluation of m with arguments F and false, false, and F.
    3. If status is an abrupt completion, then
      1. Set the running execution context's LexicalEnvironment to env.
      2. Return Completion(status).
  22. Set the running execution context's LexicalEnvironment to env.
  23. If classBinding is not undefined, then
    1. Perform classScope.InitializeBinding(classBinding, F).
  24. Return F.

4.7 Async Function Definitions

4.7.1 Static Semantics: Early Errors

AsyncFunctionDeclaration:asyncfunctionBindingIdentifier(FormalParameters){AsyncFunctionBody} AsyncFunctionDeclaration:asyncfunction(FormalParameters){AsyncFunctionBody} AsyncFunctionExpression:asyncfunction(FormalParameters){AsyncFunctionBody} AsyncFunctionExpression:asyncfunctionBindingIdentifier(FormalParameters){AsyncFunctionBody}

4.7.2 Runtime Semantics: PropertyDefinitionEvaluation

With parameters object and enumerable, enumerable, and optional parameter classObject.

AsyncMethod:asyncPropertyName(UniqueFormalParameters){AsyncFunctionBody}
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. Let scope be the LexicalEnvironment of the running execution context.
  4. Let sourceText be the source text matched by AsyncMethod.
  5. Let closure be ! OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, UniqueFormalParameters, AsyncFunctionBody, non-lexical-this, scope).
  6. Perform ! MakeMethod(closure, object, classObject).
  7. Perform ! SetFunctionName(closure, propKey).
  8. Let desc be the PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }.
  9. Return ? DefinePropertyOrThrow(object, propKey, desc).

4.8 Async Arrow Function Definitions

4.8.1 Static Semantics: Contains

With parameter symbol.

AsyncArrowFunction:asyncAsyncArrowBindingIdentifier=>AsyncConciseBody
  1. If symbol is not one of NewTarget, SuperProperty, SuperCall, ClassProperty, super, class, or this, return false.
  2. Return AsyncConciseBody Contains symbol.
AsyncArrowFunction:CoverCallExpressionAndAsyncArrowHead=>AsyncConciseBody
  1. If symbol is not one of NewTarget, SuperProperty, SuperCall, ClassProperty, super, class, or this, return false.
  2. Let head be CoveredAsyncArrowHead of CoverCallExpressionAndAsyncArrowHead.
  3. If head Contains symbol is true, return true.
  4. Return AsyncConciseBody Contains symbol.
Note
Normally, Contains does not look inside most function forms. However, Contains is used to detect new.target, this, and super, super, and class-property usage within an AsyncArrowFunction.

4.9 Tail Position Calls

4.9.1 Static Semantics: HasCallInTailPosition

4.9.1.1 Expression Rules

Note

A potential tail position call that is immediately followed by return GetValue of the call result is also a possible tail position call. Function calls cannot return reference values, so such a GetValue operation will always return the same value as the actual function call result.

AssignmentExpression:YieldExpression ArrowFunction AsyncArrowFunction LeftHandSideExpression=AssignmentExpression LeftHandSideExpressionAssignmentOperatorAssignmentExpression LeftHandSideExpression&&=AssignmentExpression LeftHandSideExpression||=AssignmentExpression LeftHandSideExpression??=AssignmentExpression BitwiseANDExpression:BitwiseANDExpression&EqualityExpression BitwiseXORExpression:BitwiseXORExpression^BitwiseANDExpression BitwiseORExpression:BitwiseORExpression|BitwiseXORExpression EqualityExpression:EqualityExpression==RelationalExpression EqualityExpression!=RelationalExpression EqualityExpression===RelationalExpression EqualityExpression!==RelationalExpression RelationalExpression:RelationalExpression<ShiftExpression RelationalExpression>ShiftExpression RelationalExpression<=ShiftExpression RelationalExpression>=ShiftExpression RelationalExpressioninstanceofShiftExpression RelationalExpressioninShiftExpression ShiftExpression:ShiftExpression<<AdditiveExpression ShiftExpression>>AdditiveExpression ShiftExpression>>>AdditiveExpression AdditiveExpression:AdditiveExpression+MultiplicativeExpression AdditiveExpression-MultiplicativeExpression MultiplicativeExpression:MultiplicativeExpressionMultiplicativeOperatorExponentiationExpression ExponentiationExpression:UpdateExpression**ExponentiationExpression UpdateExpression:LeftHandSideExpression++ LeftHandSideExpression-- ++UnaryExpression --UnaryExpression UnaryExpression:deleteUnaryExpression voidUnaryExpression typeofUnaryExpression +UnaryExpression -UnaryExpression ~UnaryExpression !UnaryExpression AwaitExpression CallExpression:SuperCall CallExpression[Expression] CallExpression.IdentifierName NewExpression:newNewExpression MemberExpression:MemberExpression[Expression] MemberExpression.IdentifierName SuperProperty ClassProperty MetaProperty newMemberExpressionArguments PrimaryExpression:this IdentifierReference Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral
  1. Return false.

5 ECMAScript Language: Scripts and Modules

5.1 Scripts

5.1.1 Static Semantics: Early Errors

Script:ScriptBody
  • It is a Syntax Error if the LexicallyDeclaredNames of ScriptBody contains any duplicate entries.
  • It is a Syntax Error if any element of the LexicallyDeclaredNames of ScriptBody also occurs in the VarDeclaredNames of ScriptBody.
ScriptBody:StatementList

5.2 modules

5.2.1 Module Semantics

5.2.1.1 Static Semantics: Early Errors

ModuleBody:ModuleItemList Note

The duplicate ExportedNames rule implies that multiple export default ExportDeclaration items within a ModuleBody is a Syntax Error. Additional error conditions relating to conflicting or duplicate declarations are checked during module linking prior to evaluation of a Module. If any such errors are detected the Module is not evaluated.

6 The Global Object

6.1 Function Properties of the Global Object

6.1.1 eval ( x )

6.1.1.1 Runtime Semantics: PerformEval ( x, callerRealm, strictCaller, direct )

The abstract operation PerformEval takes arguments x, callerRealm, strictCaller, and direct. It performs the following steps when called:

  1. Assert: If direct is false, then strictCaller is also false.
  2. If Type(x) is not String, return x.
  3. Let evalRealm be the current Realm Record.
  4. Perform ? HostEnsureCanCompileStrings(callerRealm, evalRealm).
  5. Let inFunction be false.
  6. Let inMethod be false.
  7. Let inDerivedConstructor be false.
  8. If direct is true, then
    1. Let thisEnvRec be ! GetThisEnvironment().
    2. If thisEnvRec is a function Environment Record, then
      1. Let F be thisEnvRec.[[FunctionObject]].
      2. Set inFunction to true.
      3. Set inMethod to thisEnvRec.HasSuperBinding().
      4. If F.[[ConstructorKind]] is derived, set inDerivedConstructor to true.
  9. Perform the following substeps in an implementation-defined order, possibly interleaving parsing and error detection:
    1. Let script be the ECMAScript code that is the result of parsing ! StringToCodePoints(x), for the goal symbol Script. If the parse fails, throw a SyntaxError exception. If any early errors are detected, throw a SyntaxError exception (but see also clause 16).
    2. If script Contains ScriptBody is false, return undefined.
    3. Let body be the ScriptBody of script.
    4. If inFunction is false, and body Contains NewTarget, throw a SyntaxError exception.
    5. If inMethod is false, and body Contains SuperProperty, throw a SyntaxError exception.
    6. If inMethod is false, and body Contains ClassProperty, throw a SyntaxError exception.
    7. If inDerivedConstructor is false, and body Contains SuperCall, throw a SyntaxError exception.
  10. If strictCaller is true, let strictEval be true.
  11. Else, let strictEval be IsStrict of script.
  12. Let runningContext be the running execution context.
  13. NOTE: If direct is true, runningContext will be the execution context that performed the direct eval. If direct is false, runningContext will be the execution context for the invocation of the eval function.
  14. If direct is true, then
    1. Let lexEnv be NewDeclarativeEnvironment(runningContext's LexicalEnvironment).
    2. Let varEnv be runningContext's VariableEnvironment.
  15. Else,
    1. Let lexEnv be NewDeclarativeEnvironment(evalRealm.[[GlobalEnv]]).
    2. Let varEnv be evalRealm.[[GlobalEnv]].
  16. If strictEval is true, set varEnv to lexEnv.
  17. If runningContext is not already suspended, suspend runningContext.
  18. Let evalContext be a new ECMAScript code execution context.
  19. Set evalContext's Function to null.
  20. Set evalContext's Realm to evalRealm.
  21. Set evalContext's ScriptOrModule to runningContext's ScriptOrModule.
  22. Set evalContext's VariableEnvironment to varEnv.
  23. Set evalContext's LexicalEnvironment to lexEnv.
  24. Push evalContext onto the execution context stack; evalContext is now the running execution context.
  25. Let result be EvalDeclarationInstantiation(body, varEnv, lexEnv, strictEval).
  26. If result.[[Type]] is normal, then
    1. Set result to the result of evaluating body.
  27. If result.[[Type]] is normal and result.[[Value]] is empty, then
    1. Set result to NormalCompletion(undefined).
  28. Suspend evalContext and remove it from the execution context stack.
  29. Resume the context that is now on the top of the execution context stack as the running execution context.
  30. Return Completion(result).
Note

The eval code cannot instantiate variable or function bindings in the variable environment of the calling context that invoked the eval if the calling context is evaluating formal parameter initializers or if either the code of the calling context or the eval code is strict mode code. Instead such bindings are instantiated in a new VariableEnvironment that is only accessible to the eval code. Bindings introduced by let, const, or class declarations are always instantiated in a new LexicalEnvironment.

7 Fundamental Objects

7.1 Function Objects

7.1.1 The Function Constructor

7.1.1.1 Function ( p1, p2, ..., pn, body )

7.1.1.1.1 Runtime Semantics: CreateDynamicFunction ( constructor, newTarget, kind, args )

The abstract operation CreateDynamicFunction takes arguments constructor (a constructor), newTarget (a constructor), kind (either normal, generator, async, or asyncGenerator), and args (a List of ECMAScript language values). constructor is the constructor function that is performing this action. newTarget is the constructor that new was initially applied to. args is the argument values that were passed to constructor. It performs the following steps when called:

  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, set newTarget to 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 "%Function.prototype%".
  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 "%GeneratorFunction.prototype%".
  9. Else if kind is async, then
    1. Let goal be the grammar symbol AsyncFunctionBody.
    2. Let parameterGoal be the grammar symbol FormalParameters[~Yield, +Await].
    3. Let fallbackProto be "%AsyncFunction.prototype%".
  10. Else,
    1. Assert: kind is asyncGenerator.
    2. Let goal be the grammar symbol AsyncGeneratorBody.
    3. Let parameterGoal be the grammar symbol FormalParameters[+Yield, +Await].
    4. Let fallbackProto be "%AsyncGeneratorFunction.prototype%".
  11. Let argCount be the number of elements in args.
  12. Let P be the empty String.
  13. If argCount = 0, let bodyArg be the empty String.
  14. Else if argCount = 1, let bodyArg be args[0].
  15. Else,
    1. Assert: argCount > 1.
    2. Let firstArg be args[0].
    3. Set P to ? ToString(firstArg).
    4. Let k be 1.
    5. Repeat, while k < argCount - 1,
      1. Let nextArg be args[k].
      2. Let nextArgString be ? ToString(nextArg).
      3. Set P to the string-concatenation of P, "," (a comma), and nextArgString.
      4. Set k to k + 1.
    6. Let bodyArg be args[k].
  16. Let bodyString be the string-concatenation of 0x000A (LINE FEED), ? ToString(bodyArg), and 0x000A (LINE FEED).
  17. Let prefix be the prefix associated with kind in Table 5.
  18. Let sourceString be the string-concatenation of prefix, " anonymous(", P, 0x000A (LINE FEED), ") {", bodyString, and "}".
  19. Let sourceText be ! StringToCodePoints(sourceString).
  20. Perform the following substeps in an implementation-defined order, possibly interleaving parsing and error detection:
    1. Let parameters be the result of parsing ! StringToCodePoints(P), using parameterGoal as the goal symbol. Throw a SyntaxError exception if the parse fails.
    2. Let body be the result of parsing ! StringToCodePoints(bodyString), using goal as the goal symbol. Throw a SyntaxError exception if the parse fails.
    3. Let strict be ContainsUseStrict of body.
    4. If any static semantics errors are detected for parameters or body, throw a SyntaxError exception. If strict is true, the Early Error rules for UniqueFormalParameters:FormalParameters are applied.
    5. If strict is true and IsSimpleParameterList of parameters is false, throw a SyntaxError exception.
    6. If any element of the BoundNames of parameters also occurs in the LexicallyDeclaredNames of body, throw a SyntaxError exception.
    7. If body Contains SuperCall is true, throw a SyntaxError exception.
    8. If parameters Contains SuperCall is true, throw a SyntaxError exception.
    9. If body Contains SuperProperty is true, throw a SyntaxError exception.
    10. If body Contains ClassProperty is true, throw a SyntaxError exception.
    11. If parameters Contains SuperProperty is true, throw a SyntaxError exception.
    12. If parameters Contains ClassProperty is true, throw a SyntaxError exception.
    13. If kind is generator or asyncGenerator, then
      1. If parameters Contains YieldExpression is true, throw a SyntaxError exception.
    14. If kind is async or asyncGenerator, then
      1. If parameters Contains AwaitExpression is true, throw a SyntaxError exception.
    15. If strict is true, then
      1. If BoundNames of parameters contains any duplicate elements, throw a SyntaxError exception.
  21. Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
  22. Let realmF be the current Realm Record.
  23. Let scope be realmF.[[GlobalEnv]].
  24. Let F be ! OrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, scope).
  25. Perform SetFunctionName(F, "anonymous").
  26. If kind is generator, then
    1. Let prototype be ! OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
    2. Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  27. Else if kind is asyncGenerator, then
    1. Let prototype be ! OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
    2. Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  28. Else if kind is normal, perform MakeConstructor(F).
  29. NOTE: Functions whose kind is async are not constructible and do not have a [[Construct]] internal method or a "prototype" property.
  30. Return F.
Note

CreateDynamicFunction defines a "prototype" property on any function it creates whose kind is not async to provide for the possibility that the function will be used as a constructor.

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

A Copyright & Software License

Copyright Notice

© 2020 Ron Buckton, Ecma International

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 https://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.