ECMAScript Class Members

Introduction

See the proposal repository for motivation, basic concepts, and code examples.

1Syntax

ClassElement[Yield, Await]:InstanceNonPropertyMemberDeclaration[?Yield, ?Await] DataPropertyDeclaration[?Yield, ?Await] MethodDefinition[?Yield, ?Await] staticMethodDefinition[?Yield, ?Await] ; InstanceNonPropertyMemberDeclaration[Yield, Await]:LetOrConstBindingList[?Yield, ?Await]; LetOrConststaticBindingList[?Yield, ?Await]; DataPropertyDeclaration[Yield, Await]:DataPropertyDefinition staticDataPropertyDefinition DataPropertyDefinition[Yield]:PropertyName[?Yield]Initializer[?In, ?Yield]opt MemberExpression[Yield, Await] PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await][Expression[+In, ?Yield, ?Await]] MemberExpression[?Yield, ?Await].IdentifierName MemberExpression[?Yield, ?Await]::IdentifierName MemberExpression[?Yield, ?Await]TemplateLiteral[?Yield, ?Await] SuperProperty[?Yield, ?Await] MetaProperty newMemberExpression[?Yield, ?Await]Arguments[?Yield, ?Await] CallExpression[Yield, Await]:CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] CallExpression[?Yield, ?Await]Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await][Expression[+In, ?Yield, ?Await]] CallExpression[?Yield, ?Await].IdentifierName CallExpression[?Yield, ?Await]::IdentifierName CallExpression[?Yield, ?Await]TemplateLiteral[?Yield, ?Await]

2Static Semantics

2.1Early Errors

ScriptBody:StatementList ModuleBody:ModuleItemList HiddenMethod:hiddenMethodDefinition ClassBody:ClassElementList ClassElement:ClassInitializer
  1. It is a Syntax Error if HasDirectSuper of ClassInitializer is true.
UnaryExpression:deleteUnaryExpression Note

The last rule means that expressions such as delete (((foo))) produce early errors because of recursive application of the first rule.

2.2PropName

Editor's Note

PropName returns empty for hidden method definitions and non-method class elements.

HiddenMethod:hiddenMethodDefintion
  1. Return empty.
ClassElement:; ClassElement:InstanceVariableDeclaration ClassElement:ClassInitializer
  1. Return empty.

2.3Contains

With parameter symbol.

HiddenMethod:hiddenMethodDefinition
  1. If symbol is MethodDefinition, return true.
  2. Return false.
Note

Static semantic rules that depend upon substructure generally do not look into function definitions.

2.4MethodHasIdentifierName

Editor's Note

MethodHasIdentifierName of a MethodDefinition returns true if it derives a method with an IdentifierName property name.

MethodDefinition:PropertyName(UniqueFormalParameters){FunctionBody} MethodDefinition:getPropertyName(){FunctionBody} MethodDefinition:setPropertyName(PropertySetParameterList){FunctionBody} GeneratorMethod:*PropertyName(UniqueFormalParameters){GeneratorBody} AsyncMethod:async[no LineTerminator here]PropertyName(UniqueFormalParameters){AsyncFunctionBody} AsyncGeneratorMethod:async[no LineTerminator here]*PropertyName(UniqueFormalParameters){AsyncGeneratorBody}
  1. Return MethodHasIdentifierName of PropertyName.
LiteralPropertyName:StringLiteral LiteralPropertyName:NumericLiteral ComputedPropertyName:[AssignmentExpression]
  1. Return false.
LiteralPropertyName:IdentifierName
  1. Return true.

2.5HiddenNames

Editor's Note
HiddenNames of a ClassElementList returns a List containing all of the hidden member names defined in the class body. Each element in the list is a Record of the form {[[Name]]: string, [[Kind]]: string}.
MethodDefinition:PropertyName(UniqueFormalParameters){FunctionBody} GeneratorMethod:*PropertyName(UniqueFormalParameters){GeneratorBody} AsyncMethod:async[no LineTerminator here]PropertyName(UniqueFormalParameters){AsyncFunctionBody} AsyncGeneratorMethod:async[no LineTerminator here]*PropertyName(UniqueFormalParameters){AsyncGeneratorBody}
  1. Let name be PropName of PropertyName.
  2. If name is empty, return a new empty List.
  3. Return a new List containing the Record{ [[Name]]: name, [[Kind]]: "method" }.
MethodDefinition:getPropertyName(){FunctionBody}
  1. Let name be PropName of PropertyName.
  2. If name is empty, return a new empty List.
  3. Return a new List containing the Record{ [[Name]]: name, [[Kind]]: "get" }.
MethodDefinition:setPropertyName(PropertySetParameterList){FunctionBody}
  1. Let name be PropName of PropertyName.
  2. If name is empty, return a new empty List.
  3. Return a new List containing the Record{ [[Name]]: name, [[Kind]]: "set" }.
ClassElementList:ClassElementListClassElement
  1. Let hiddenNames be HiddenNames of ClassElementList.
  2. Let newNames be HiddenNames of ClassElement.
  3. Append the elements of newNames to hiddenNames.
  4. Return hiddenNames.
ClassElement:MethodDefinition ClassElement:staticMethodDefinition ClassElement:; ClassElement:ClassInitializer
  1. Return a new empty List.
InstanceVariableList:BindingIdentifier
  1. Let name be StringValue of BindingIdentifier.
  2. Return a new List containing the Record{ [[Name]]: name, [[Kind]]: "var" }.
InstanceVariableList:InstanceVariableList,BindingIdentifier
  1. Let hiddenNames be HiddenNames of InstanceVariableList.
  2. Let name be StringValue of BindingIdentifier.
  3. Let record be a new Record{ [[Name]]: name, [[Kind]]: "var" }.
  4. Append record to hiddenNames.
  5. Return hiddenNames.

2.6HasDuplicateHiddenNames ( parseNode )

Editor's Note
HasDuplicateHiddenNames returns true if a class body contains more than one definition for a single hidden name, and those definitions do not form an accessor method pair.
  1. Assert: parseNode is ClassElementList.
  2. Let members be HiddenNames of parseNode.
  3. For each element member of members, do
    1. For each element otherMember of members, do
      1. If otherMember is not member and otherMember.[[Name]] is member.[[Name]], then
        1. If otherMember.[[Kind]] is "set", then
          1. If member.[[Kind]] is not "get", return true.
        2. Else if otherMember.[[Kind]] is "get", then
          1. If member.[[Kind]] is not "set", return true.
        3. Else, return true.
  4. Return false.

2.7ContainsInvalidHiddenReferences

Editor's Note
ContainsInvalidHiddenReferences of a parse node returns true if it contains any hidden references that are statically unresolvable or invalid using the initial set of member definitions in the parameter hiddenNames. ContainsInvalidHiddenReferences is a recursively applied semantic rule.

With parameter hiddenNames.

TODO

2.8ClassInitializerElement

Editor's Note
ClassInitializerElement of ClassElementList returns the first ClassInitializer within a class definition. Early errors prevent multiple occurrances of ClassInitializer within a single class definition.
ClassElementList:ClassElement
  1. If ClassElement is ClassElement:ClassInitializer , return ClassElement.
  2. Return empty.
ClassElementList:ClassElementListClassElement
  1. Let head be ClassInitializerElement of ClassElementList.
  2. If head is not empty, return head.
  3. Return ClassInitializerElement of ClassElement.

2.9HasMultipleClassInitializers

Editor's Note
HasMultipleClassInitializers of ClassElementList returns true if the containing class body contains more than one occurance of ClassInitializer.
ClassElementList:ClassElement
  1. Return false.
ClassElementList:ClassElementListClassElement
  1. If ClassElementList Contains ClassInitializer and ClassElement Contains ClassInitializer, return true.
  2. Return false.

2.10IsStatic

ClassElement:MethodDefinition ClassElement:HiddenMethod ClassElement:InstanceVariableDeclaration ClassElement:;
  1. Return false.
ClassElement:staticMethodDefinition ClassElement:staticHiddenMethod ClassElement:ClassInitializer
  1. Return true.

2.11IsHiddenClassElement

Editor's Note
IsHiddenClassElement of ClassElement returns true if the class element is a hidden method or instance variable declaration.
ClassElement:InstanceVariableDeclaration ClassElement:HiddenMethod ClassElement:staticHiddenMethod ClassElement:ClassInitializer
  1. Return true.
ClassElement:; ClassElement:MethodDefinition ClassElement:staticMethodDefinition
  1. Return false.

2.12NonConstructorClassElements

Editor's Note
NonConstructorClassElements of ClassElementList returns all non-empty ClassElement parse nodes other than the class constructor method.
ClassElementList:ClassElement
  1. If ClassElement is ClassElement:; , return a new empty List.
  2. If IsStatic of ClassElement is false and PropName of ClassElement is "constructor", return a new empty List.
  3. Return a List containing ClassElement.
ClassElementList:ClassElementListClassElement
  1. Let list be NonConstructorClassElements of ClassElementList.
  2. If ClassElement is ClassElement:; , return list.
  3. If IsStatic of ClassElement is false and PropName of ClassElement is "constructor", return list.
  4. Append ClassElement to the end of list.
  5. Return list.

3Runtime Semantics

3.1Evaluation

SuperCall:superArguments
  1. Let newTarget be GetNewTarget().
  2. Assert: Type(newTarget) is Object.
  3. Let func be ? GetSuperConstructor().
  4. Let argList be ArgumentListEvaluation of Arguments.
  5. ReturnIfAbrupt(argList).
  6. Let result be ? Construct(func, argList, newTarget).
  7. Let thisER be GetThisEnvironment().
  8. Let activeFunction be thisER.[[FunctionObject]].
  9. Perform ? InitializeInstanceVariables(result, activeFunction).
  10. Return thisER.BindThisValue(result).
MemberExpression:MemberExpression::IdentifierName
  1. Let base be the result of evaluating MemberExpression.
  2. Assert: Type(base) is Object
  3. Let closure be base.[[InstanceClosure]].
  4. If (closure) is Null, throw a TypeError exception.
  5. Let thisER be GetThisEnvironment().
  6. Let activeFunction be thisER.[[FunctionObject]].
  7. If activeFunction is Null, throw a TypeError exception.
  8. Let signatures be activeFunction.[[ClosureSignatures]].
  9. Let signature be closure.[[ClosureSignature]].
  10. If signatures does not contain signature, then throw a TypeError exception.
  11. Let result be GetIdentifierReference(closure, IdentifierName, true);
  12. If Type(result) is an ECMAScript function, then
    1. Let envRec be the Variable Environment Record of closure.
    2. Let inst be envRec.GetThisBinding().
    3. Let result be result.BindThisValue(inst).
  13. Return result.

3.2ObjectCreate ( proto [ , internalSlotsList ] )

The abstract operation ObjectCreate with argument proto (an object or null) is used to specify the runtime creation of new ordinary objects. The optional argument internalSlotsList is a List of the names of additional internal slots that must be defined as part of the object. If the list is not provided, a new empty List is used. This abstract operation performs the following steps:

  1. If internalSlotsList is not present, set internalSlotsList to a new empty List.
  2. Let obj be a newly created object with an internal slot for each name in internalSlotsList.
  3. Set obj's essential internal methods to the default ordinary object definitions specified in 9.1.
  4. Set obj.[[Prototype]] to proto.
  5. Set obj.[[Extensible]] to true.
  6. Set obj.[[InstanceVariables]] to an empty List.
  7. Return obj.

3.3[[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.
  2. Assert: Type(newTarget) is Object.
  3. Let callerContext be the running execution context.
  4. Let kind be F.[[ConstructorKind]].
  5. If kind is "base", then
    1. Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%ObjectPrototype%").
  6. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
  7. Assert: calleeContext is now the running execution context.
  8. If kind is "base", then
    1. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
    2. Perform ! InitializeInstanceVariables(thisArgument, F).
  9. Let constructorEnv be the LexicalEnvironment of calleeContext.
  10. Let envRec be constructorEnv's EnvironmentRecord.
  11. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  12. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  13. If result.[[Type]] is return, then
    1. If Type(result.[[Value]]) is Object, return NormalCompletion(result.[[Value]]).
    2. If kind is "base", return NormalCompletion(thisArgument).
    3. If result.[[Value]] is not undefined, throw a TypeError exception.
  14. Else, ReturnIfAbrupt(result).
  15. Return ? envRec.GetThisBinding().

3.4InitializeInstanceVariables ( obj, constructor )

  1. Assert: Type(obj) is Object.
  2. Assert: constructor is an ECMAScript function object.
  3. Let closureDef be constructor.[[InstanceClosureDefinition]].
  4. If closureDef is an ECMAScript function object, then
    1. Let instanceClosure be EvalInstanceClosureDefinition(closureDef).
    2. Let obj.[[InstanceClosure]] be instanceClosure.
  5. Return.

3.5EvalInstanceClosureDefinition ( closureDef )

  1. Let callerContext be the running execution context.
  2. Let closure be PrepareForOrdinaryCall(closureDef, Undefined).
  3. Assert: closure is now the running execution context.
  4. Let argList be a new empty List.
  5. Perform OrdinaryCallBindThis(closureDef, closure, obj).
  6. Perform OrdinaryCallEvaluateBody(closureDef, argList).
  7. Let result be GetThisEnvironment().
  8. Remove closure from the execution context stack and restore callerContext as the running execution context.
  9. Return result.

ACopyright & Software License

Copyright Notice

© 2018 Ranando King

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.