Today ES classes are currently limited to declarative specification of
4 | methods, but declarative specification of fields is left to ad-hoc expando
5 | mutations on class instances in various places.
6 |
7 |
This proposal aims to provide a declarative mechanism for specifying fields
8 | intended to be placed on classes. Such a mechanism is useful for both developers
9 | and tooling alike as it provides a place to specify the intended properties.
7 | title: Public Class Fields
8 | stage: 2
9 | contributors: Jeff Morrison
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NOTE: This proposal has been merged with the [Private Fields proposal](https://github.com/tc39/proposal-private-fields) to form a single unified proposal [here](https://github.com/tc39/proposal-class-fields).
2 |
3 | Please do not create new issues/PRs on this repo.
4 |
5 | # ES Class Fields & Static Properties
6 |
7 | This presents two related proposals: "class instance fields" and "class static fields". "Class instance fields" describe properties intended to exist on instances of a class (and may optionally include initializer expressions for said properties). "Class static fields" are declarative properties that exist on the class object itself (and may optionally include initializer expressions for said properties).
8 |
9 | Latest spec text: https://tc39.github.io/proposal-class-public-fields/
10 |
--------------------------------------------------------------------------------
/spec/new-productions.htm:
--------------------------------------------------------------------------------
1 |
37 |
38 | ClassElementList: ClassElement
39 |
40 | 1. If |ClassElement| is the production
41 | ClassElement : PublicFieldDefinition, return
42 | a List containing |ClassElement|.
43 | 1. If |ClassElement| is the production
44 | ClassElement : static PublicFieldDefinition,
45 | return a List containing |ClassElement|.
46 | 1. Return a new empty List.
47 |
48 |
49 | ClassElementList: ClassElementList ClassElement
50 |
51 | 1. Let _list_ be ClassPublicFields of |ClassElementList|.
52 | 1. If |ClassElement| is the production
53 | ClassElement : PublicFieldDefinition, append
54 | |ClassElement| to the end of _list_.
55 | 1. If |ClassElement| is the production
56 | ClassElement : static PublicFieldDefinition,
57 | append |ClassElement| to the end of _list_.
58 | 1. Return _list_.
59 |
60 |
61 |
62 |
63 |
ClassPublicFieldDefinitionEvaluation
64 |
65 |
With parameters _isStatic_ and _homeObject_.
66 |
67 |
68 | PublicFieldDefinition : PropertyName[?Yield] Initializer? ;
69 |
70 |
71 | 1. Let _fieldName_ be the result of performing PropName of |PropertyName|.
72 | 1. If |Initializer_opt| is present,
73 | 1. Let _lex_ be the Lexical Environment of the running execution context.
74 | 1. Let _initializer_ be FunctionCreate(~Method~, ~empty~, |Initializer_opt|, _lex_, *true*).
75 | 1. Perform MakeMethod(_initializer_, _homeObject_).
76 | 1. Else, let _initializer_ be ~empty~.
77 | 1. Return Record{
78 | [[name]]: _fieldName_,
79 | [[initializer]]: _initializer_,
80 | [[static]]: _isStatic_,
81 | }.
82 |
83 |
84 |
85 |
86 |
101 |
102 |
103 | 1. Assert: Type(_F_) is Object.
104 | 1. Assert: _F_ is an ECMAScript function object.
105 | 1. Let _publicFieldRecords_ be the value of _F_'s [[PublicFields]] internal slot.
106 | 1. For each item _fieldRecord_ in order from _publicFieldRecords_,
107 | 1. If _fieldRecord_.[[static]] is *true*, then
108 | 1. Let _fieldName_ be _fieldRecord_.[[name]].
109 | 1. Let _initializer_ be _fieldRecord_.[[initializer]].
110 | 1. If _initializer_ is not ~empty~, then
111 | 1. Let _initValue_ be ? Call(_initializer_, *undefined*).
112 | 1. Else, let _initValue_ be *undefined*.
113 | 1. Let _desc_ be PropertyDescriptor {
114 | [[configurable]]: *false*,
115 | [[enumerable]]: *true*,
116 | [[writable]]: *true*,
117 | [[value]]: _initValue_
118 | }.
119 | 1. Perform ?DefinePropertyOrThrow (_F_, _fieldName_, _desc_).
120 | 1. Return.
121 |
122 |
123 |
124 |
125 |
128 | TODO: Factor out the lexical environment wrangling and do that at the
129 | callsites of this procedure.
130 |
131 |
132 | We likely want to execute public and private fields their coalesced order of
133 | definition, so when the two proposals merge we'll probably want to merge
134 | their initialization procedures as well.
135 |
136 |
137 |
138 | 1. Assert: Type ( _O_ ) is Object.
139 | 1. Assert: Assert _constructor_ is an ECMAScript function object.
140 | 1. Let _publicFieldRecords_ be the value of _constructor_'s [[PublicFields]] internal slot.
141 | 1. For each item _fieldRecord_ in order from _publicFieldRecords_,
142 | 1. If _fieldRecord_.[[static]] is *false*, then
143 | 1. Let _fieldName_ be _fieldRecord_.[[name]]
144 | 1. Let _initializer_ be _fieldRecord_.[[initializer]].
145 | 1. If _initializer_ is not ~empty~, then
146 | 1. Let _initValue_ be ? Call(_initializer_, _O_).
147 | 1. Else,
148 | 1. Let _initValue_ be ~undefined~.
149 | 1. Let _desc_ be PropertyDescriptor {
150 | [[configurable]]: *false*,
151 | [[enumerable]]: *true*,
152 | [[writable]]: *true*,
153 | [[value]]: _initValue_
154 | }
155 | 1. Perform ? DefinePropertyOrThrow (_O_, _fieldName_, _desc_)
156 | 1. Set the running execution context's LexicalEnvironment to _lex_.
157 | 1. Return.
158 |
159 |
160 |
--------------------------------------------------------------------------------
/spec/modified-productions.htm:
--------------------------------------------------------------------------------
1 |
87 | ClassTail : ClassHeritage? `{` ClassBody? `}`
88 |
89 | 1. Let _lex_ be the LexicalEnvironment of the running execution context.
90 | 1. Let _classScope_ be NewDeclarativeEnvironment(_lex_).
91 | 1. Let _classScopeEnvRec_ be _classScope_'s EnvironmentRecord.
92 | 1. If _className_ is not *undefined*, then
93 | 1. Perform _classScopeEnvRec_.CreateImmutableBinding(_className_, *true*).
94 | 1. If |ClassHeritage_opt| is not present, then
95 | 1. Let _protoParent_ be the intrinsic object %ObjectPrototype%.
96 | 1. Let _constructorParent_ be the intrinsic object %FunctionPrototype%.
97 | 1. Else,
98 | 1. Set the running execution context's LexicalEnvironment to _classScope_.
99 | 1. Let _superclass_ be the result of evaluating |ClassHeritage|.
100 | 1. Set the running execution context's LexicalEnvironment to _lex_.
101 | 1. ReturnIfAbrupt(_superclass_).
102 | 1. If _superclass_ is *null*, then
103 | 1. Let _protoParent_ be *null*.
104 | 1. Let _constructorParent_ be the intrinsic object %FunctionPrototype%.
105 | 1. Else if IsConstructor(_superclass_) is *false*, throw a *TypeError* exception.
106 | 1. Else,
107 | 1. Let _protoParent_ be ? Get(_superclass_, `"prototype"`).
108 | 1. If Type(_protoParent_) is neither Object nor Null, throw a *TypeError* exception.
109 | 1. Let _constructorParent_ be _superclass_.
110 | 1. Let _proto_ be ObjectCreate(_protoParent_).
111 | 1. If |ClassBody_opt| is not present, let _constructor_ be ~empty~.
112 | 1. Else, let _constructor_ be ConstructorMethod of |ClassBody|.
113 | 1. If _constructor_ is ~empty~, then
114 | 1. If |ClassHeritage_opt| is present and _protoParent_ is not *null*, then
115 | 1. Let _constructor_ be the result of parsing the source text
116 |
constructor(... args){ super (...args);}
117 | using the syntactic grammar with the goal symbol |MethodDefinition[~Yield]|.
118 | 1. Else,
119 | 1. Let _constructor_ be the result of parsing the source text
120 |
constructor( ){ }
121 | using the syntactic grammar with the goal symbol |MethodDefinition[~Yield]|.
122 | 1. Set the running execution context's LexicalEnvironment to _classScope_.
123 | 1. Let _constructorInfo_ be the result of performing DefineMethod for _constructor_ with arguments _proto_ and _constructorParent_ as the optional _functionPrototype_ argument.
124 | 1. Assert: _constructorInfo_ is not an abrupt completion.
125 | 1. Let _F_ be _constructorInfo_.[[Closure]].
126 | 1. If |ClassHeritage_opt| is present and _protoParent_ is not *null*, then set _F_.[[ConstructorKind]] to `"derived"`.
127 | 1. Perform MakeConstructor(_F_, *false*, _proto_).
128 | 1. Perform MakeClassConstructor(_F_).
129 | 1. Perform CreateMethodProperty(_proto_, `"constructor"`, _F_).
130 | 1. If |ClassBody_opt| is not present, let _methods_ be a new empty List.
131 | 1. Else, let _methods_ be NonConstructorMethodDefinitions of |ClassBody|.
132 | 1. For each |ClassElement| _m_ in order from _methods_
133 | 1. If IsStatic of _m_ is *false*, then
134 | 1. Let _status_ be the result of performing PropertyDefinitionEvaluation for _m_ with arguments _proto_ and *false*.
135 | 1. Else,
136 | 1. Let _status_ be the result of performing PropertyDefinitionEvaluation for _m_ with arguments _F_ and *false*.
137 | 1. If _status_ is an abrupt completion, then
138 | 1. Set the running execution context's LexicalEnvironment to _lex_.
139 | 1. Return Completion(_status_).
140 | 1. Set the running execution context's LexicalEnvironment to _lex_.
141 | 1. If _className_ is not *undefined*, then
142 | 1. Perform _classScopeEnvRec_.InitializeBinding(_className_, _F_).
143 | 1. If |ClassBody_opt| is not present, let _publicFields_ be a new empty List.
144 | 1. Else, let _publicFields_ be the result of performing
145 | ClassPublicFields of |ClassBody|.
146 | 1. Let _publicFieldRecords_ be a new empty List.
147 | 1. For each item _publicField_ in order from _publicFields_,
148 | 1. Let _isStatic_ be the result of performing IsStatic of _publicField_.
149 | 1. If _isStatic_, let _homeObject_ be _F_, otherwise let _homeObject_ be _proto_.
150 | 1. Let _fieldRecord_ be the result of performing
151 | ClassPublicFieldDefinitionEvaluation for _publicField_ with arguments
152 | _isStatic_ and _homeObject_.
153 | 1. Append _fieldRecord_ to _publicFieldRecords_.
154 | 1. Set the value of _F_'s [[PublicFields]] internal slot to _publicFieldRecords_.
155 | 1. Set the running execution context's LexicalEnvironment to _classScope_.
156 | 1. Let _result_ be InitializePublicStaticFields(_F_).
157 | 1. If _result_ is an abrupt completion, then
158 | 1. Set the running execution context's LexicalEnvironment to _lex_.
159 | 1. Return Completion(_result_)
160 | 1. Set the running execution context's LexicalEnvironment to _lex_.
161 | 1. Return _F_.
162 |
163 |
164 |
165 |
166 |
167 |
[[Construct]] ( _argumentsList_, _newTarget_)
168 |
169 | The [[Construct]] internal method for an ECMAScript Function object _F_ is
170 | called with parameters _argumentsList_ and _newTarget_. _argumentsList_ is
171 | a possibly empty List of ECMAScript language values. The following steps are
172 | taken:
173 |
174 |
175 | 1. Assert: _F_ is an ECMAScript function object.
176 | 1. Assert: Type(_newTarget_) is Object.
177 | 1. Let _callerContext_ be the running execution context.
178 | 1. Let _kind_ be _F_.[[ConstructorKind]].
179 | 1. If _kind_ is `"base"`, then
180 | 1. Let _thisArgument_ be ? OrdinaryCreateFromConstructor(_newTarget_, `"%ObjectPrototype%"`).
181 | 1. Let _calleeContext_ be PrepareForOrdinaryCall(_F_, _newTarget_).
182 | 1. Assert: _calleeContext_ is now the running execution context.
183 | 1. If _kind_ is `"base"`, then
184 | 1. Perform OrdinaryCallBindThis(_F_, _calleeContext_, _thisArgument_).
185 | 1. Let _result_ be InitializePublicInstanceFields(_thisArgument_, _F_).
186 | 1. If _result_ is an abrupt completion, then
187 | 1. Remove _calleeContext_ from execution context stack and restore
188 | _callerContext_ as the running execution context.
189 | 1. Return Completion(_result_).
190 | 1. Let _constructorEnv_ be the LexicalEnvironment of _calleeContext_.
191 | 1. Let _envRec_ be _constructorEnv_'s EnvironmentRecord.
192 | 1. Let _result_ be OrdinaryCallEvaluateBody(_F_, _argumentsList_).
193 | 1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context.
194 | 1. If _result_.[[Type]] is ~return~, then
195 | 1. If Type(_result_.[[Value]]) is Object, return NormalCompletion(_result_.[[Value]]).
196 | 1. If _kind_ is `"base"`, return NormalCompletion(_thisArgument_).
197 | 1. If _result_.[[Value]] is not *undefined*, throw a *TypeError* exception.
198 | 1. Else, ReturnIfAbrupt(_result_).
199 | 1. Return ? _envRec_.GetThisBinding().
200 |
201 |
202 |
203 |
204 |
The `super` Keyword
205 |
206 |
207 |
Runtime Semantics: Evaluation
208 | SuperCall : `super` Arguments
209 |
210 | 1. Let _newTarget_ be GetNewTarget().
211 | 1. If _newTarget_ is *undefined*, throw a *ReferenceError* exception.
212 | 1. Let _func_ be ? GetSuperConstructor().
213 | 1. Let _argList_ be ArgumentListEvaluation of |Arguments|.
214 | 1. ReturnIfAbrupt(_argList_).
215 | 1. Let _result_ be ? Construct(_func_, _argList_, _newTarget_).
216 | 1. Let _thisER_ be GetThisEnvironment( ).
217 | 1. Perform ? InitializePublicInstanceFields(_thisValue_, _F_).
218 | 1. Return ? _thisER_.BindThisValue(_result_).
219 |
220 |
221 |
222 |
223 |
224 |