Stage 3 Draft / October 7, 2019

Static class features

Introduction

This document specifies parts of the class features proposals which were split off in the November 2017 TC39 meeting from class fields and private methods proposals, for further consideration and advancement. In that meeting, static public fields, static private fields and static private methods were split off from the earlier "Stage 3" proposal and demoted to "Stage 2".

This proposal defines static public fields, static private fields, and static private methods. For further context and motivation, see the explainer document.

This specification is phrased as a diff against the combination of the private methods and class fields proposals.

1Syntax

ClassElement[Yield, Await]:MethodDefinition[?Yield, ?Await] staticMethodDefinition[?Yield, ?Await] FieldDefinition[?Yield, ?Await]; staticFieldDefinition[?Yield, ?Await]; ;

1.1Static Semantics: Early Errors

ClassBody:ClassElementList
  • It is a Syntax Error if PrivateBoundNames of ClassBody contains any duplicate entries, unless the name is used once for a getter and once for a setter and in no other entries, and the getter and setter are either both static or both non-static.
ClassElement:staticFieldDefinition;
  • It is a Syntax Error if PropName of FieldDefinition is "prototype" or "constructor".
ClassElement:staticMethodDefinition
  • It is a Syntax Error if PrivateBoundIdentifiers of MethodDefinition is non-empty.
Editor's Note
Removing this early error enables static private methods.

2Algorithms

2.1Runtime Semantics: ClassElementEvaluation

With parameters homeObject, enumerable and placement.

ClassElement:staticFieldDefinition;
  1. Return ClassFieldDefinitionEvaluation of FieldDefinition with parameters "static" and homeObject.

2.2Runtime Semantics: ClassDefinitionEvaluation

With parameter className.

ClassTail:ClassHeritageopt{ClassBodyopt}
  1. Let lex be the LexicalEnvironment of the running execution context.
  2. Let classScope be NewDeclarativeEnvironment(lex).
  3. Let classScopeEnvRec be classScope's EnvironmentRecord.
  4. If className is not undefined, then
    1. Perform classScopeEnvRec.CreateImmutableBinding(className, true).
  5. Let outerPrivateEnvironment be the PrivateEnvironment of the running execution context.
  6. Let classPrivateEnvironment be NewDeclarativeEnvironment(outerPrivateEnvironment).
  7. Let classPrivateEnvRec be classPrivateEnvironment's EnvironmentRecord.
  8. If ClassBodyopt is present, then
    1. For each element dn of the PrivateBoundIdentifiers of ClassBodyopt,
      1. Perform classPrivateEnvRec.CreateImmutableBinding(dn, true).
  9. If ClassHeritageopt is not present, then
    1. Let protoParent be the intrinsic object %ObjectPrototype%.
    2. Let constructorParent be the intrinsic object %FunctionPrototype%.
  10. Else,
    1. Set the running execution context's LexicalEnvironment to classScope.
    2. NOTE: The running execution context's PrivateEnvironment is outerPrivateEnvironment when evaluating ClassHeritage.
    3. Let superclass be the result of evaluating ClassHeritage.
    4. Set the running execution context's LexicalEnvironment to lex.
    5. ReturnIfAbrupt(superclass).
    6. If superclass is null, then
      1. Let protoParent be null.
      2. Let constructorParent be the intrinsic object %FunctionPrototype%.
    7. Else if IsConstructor(superclass) is false, throw a TypeError exception.
    8. 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.
  11. Let proto be ObjectCreate(protoParent).
  12. If ClassBodyopt is not present, let constructor be empty.
  13. Else, let constructor be ConstructorMethod of ClassBody.
  14. If constructor is empty, then
    1. If ClassHeritageopt 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].
    2. Else,
      1. Let constructor be the result of parsing the source text
        constructor( ){ }
        using the syntactic grammar with the goal symbol MethodDefinition[~Yield].
  15. Set the running execution context's LexicalEnvironment to classScope.
  16. Set the running execution context's PrivateEnvironment to classPrivateEnvironment.
  17. Let constructorInfo be the result of performing DefineMethod for constructor with arguments proto and constructorParent as the optional functionPrototype argument.
  18. Assert: constructorInfo is not an abrupt completion.
  19. Let F be constructorInfo.[[Closure]].
  20. If ClassHeritageopt is present and protoParent is not null, then set F.[[ConstructorKind]] to "derived".
  21. Perform MakeConstructor(F, false, proto).
  22. Perform MakeClassConstructor(F).
  23. Perform CreateMethodProperty(proto, "constructor", F).
  24. If ClassBodyopt is not present, let methods be a new empty List.
  25. Else, let elements be NonConstructorMethodDefinitions of ClassBody.
  26. Let instanceFields be a new empty List.
  27. Let staticFields be a new empty List.
  28. For each ClassElement e in order from elements,
    1. If IsStatic of e is false, then
      1. Let field be the result of performing ClassElementEvaluation for e with arguments proto and false.
    2. Else,
      1. Let field be the result of performing PropertyDefinitionEvaluation for mClassElementEvaluation for e with arguments F and false.
    3. If field is an abrupt completion, then
      1. Set the running execution context's LexicalEnvironment to lex.
      2. Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
      3. Return Completion(field).
    4. If field is not empty,
      1. If IsStatic of e is false, append field to instanceFields.
      2. Otherwise, append field to staticFields.
  29. Set the running execution context's LexicalEnvironment to lex.
  30. If className is not undefined, then
    1. Perform classScopeEnvRec.InitializeBinding(className, F).
  31. Set F.[[Fields]] to instanceFields.
  32. If PrivateBoundIdentifiers of ClassBody contains a Private Name P such that P's [[Kind]] field is either "method" or "accessor" and P's [[Brand]] field is proto,
    1. Set F.[[PrivateBrand]] to proto.
  33. If PrivateBoundIdentifiers of ClassBody contains a Private Name P such that P's [[Kind]] field is either "method" or "accessor" and P's [[Brand]] is F,
    1. PrivateBrandAdd(F, F).
  34. For each item fieldRecord in order from staticFields,
    1. Perform ? DefineField(F, fieldRecord).
  35. Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
  36. Return F.

ACopyright & Software License

Copyright Notice

© 2019 Daniel Ehrenberg, Jeff Morrison, Kevin Smith, Kevin Gibbons

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.