Skip to content
This repository was archived by the owner on Jan 25, 2022. It is now read-only.

Commit f0eb1e0

Browse files
committed
Update README.md
1 parent c0ab1eb commit f0eb1e0

File tree

1 file changed

+111
-8
lines changed

1 file changed

+111
-8
lines changed

‎README.md‎

Lines changed: 111 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,30 +78,32 @@ class ClassWithInits {
7878
}
7979
```
8080

81-
##### Property Declarations Without Initializers
81+
##### Instance Property Declarations Without Initializers
8282

8383
When no initializer is specified for a declared property, the act of executing a property initializer will simply be a no-op. This is useful for scenarios where initialization needs to happen somewhere other than in the declarative init position (ex. If the property depends on constructor-injected data and thus needs to be initialized inside the construtor, or if the property is managed externally by something like a decorator or framework).
8484

8585
Additionally, it's sometimes useful for derived classes to "silently" specify a class property that may have been setup on a base class (either using or not using property declarations). For this reason, a declaration with no initializer should not attempt to overwrite data potentially written by a base class.
8686

87-
##### Property Declarations With Initializers
87+
##### Instance Property Declarations With Initializers
8888

8989
When a property with an initializer is specifed on a **non-derived class (AKA a class without an `extends` clause)**, the initializers are declared and executed in the order they are specified in the class definition. Execution of the initializers happens during the internal "initialization" process that occurs immediately *before* entering the constructor.
9090

9191
When an initializer is specified on a **derived class (AKA a class with an `extends` clause)**, the initializers are declared and executed in the order they are specified in the class definition. Execution of the initializers happens at the end of the internal "initialization" process that occurs while executing `super()` in the derived constructor. This means that if a derived constructor never calls `super()`, instance properties specified on the derived class will not be initialized since property initialization is considered a part of the [SuperCall Evaluation process](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-super-keyword-runtime-semantics-evaluation).
9292

93-
##### Property Declaration & Execution Process
93+
##### Instance Property Declaration Process
9494

95-
The process of declaring a property happens at the time of [class definition evaluation](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-classdefinitionevaluation). The process for executing a property's initializer happens at class instantiation time and depends on wether the class is a "base" class (AKA has no `extends` clause) or is a "derived" class (AKA has an `extends` clause). The differences between these two cases is described above in [Property Declarations Without Initializers](#property-declarations-without-initializers) and [Property Declarations With Initializers](#property-declarations-with-initializers).
96-
97-
The high level process for declaring class properties is as follows for each property in the order the properties are declared. (for sake of definition we assume a name for the class being defined is `DefinedClass`):
95+
The process of declaring a property happens at the time of [class definition evaluation](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-classdefinitionevaluation). This process is roughly defined as follows for each property in the order the properties are declared. (for sake of definition we assume a name for the class being defined is `DefinedClass`):
9896

9997
1. If the property name is computed, evaluate the computed property expression to a string to conclude the name of the property.
10098
2. Create a function whose body simply executes the initializer expression and returns the result. This function's parent scope should be set to the scope of the class body. To be super clear: This scope should sit sibling to the scope of any of the class's method bodies.
10199
3. If the `DefinedClass.prototype[Symbol.ClassProperties]` object is not already set, create and set it.
102100
4. On the `DefinedClass.prototype[Symbol.ClassProperties]` object, store the function generated in step 2 under the key matching the name of the property being evaluated.
103101

104-
The purpose for generating and storing these "thunk" functions is a means of deferring the execution of the initialization expression until the class is constructed; Thus, the high level process for executing class property initializers is as follows -- once for each property in the order the properties are declared:
102+
The purpose for generating and storing these "thunk" functions is a means of deferring the execution of the initialization expression until the class is constructed; Thus,
103+
104+
##### Instance Property Initialization Process
105+
106+
The process for executing a property initializers happens at class instantiation time and depends on wether the class is a "base" class (AKA has no `extends` clause) or is a "derived" class (AKA has an `extends` clause). The differences between these two cases is described above in [Property Declarations Without Initializers](#property-declarations-without-initializers) and [Property Declarations With Initializers](#property-declarations-with-initializers). The following describes the process for initializing each class property initializer (intended to run once for each property in the order the properties are declared):
105107

106108
1. For each entry on `DefinedClass.prototype[Symbol.ClassProperties]`, call the value as a function with a `this` value equal to the `this` value of the object being constructed.
107109
2. Define the result of the call in step 1 as a property on the `this` object with a key corresponding to the key of the `DefinedClass.prototype[Symbol.ClassProperties]` entry currently being evaluated. It should be defined with the following descriptor:
@@ -163,4 +165,105 @@ Note that we store the static property thunk functions on `ClassDefinition[Symbo
163165

164166
## Spec Text
165167

166-
\<\<TODO>>
168+
##### [14.5 Class Definitions](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-class-definitions)
169+
170+
```
171+
ClassPropertyInitializer :
172+
PropertyName ;
173+
PropertyName = AssignmentExpression ;
174+
175+
ClassElement :
176+
MethodDefinition
177+
static MethodDefinition
178+
ClassPropertyInitializer
179+
static _ClassPropertyInitializer
180+
;
181+
```
182+
183+
##### *(new)* 14.5.x Static Semantics: GetDeclaredClassProperties
184+
185+
_ClassElementList_ : _ClassElement_
186+
187+
1. If _ClassElement_ is the production _ClassElement_ : _ClassPropertyInitializer_, return a List containing _ClassElement_.
188+
2. If _ClassElement_ is the production _ClassElement_ : `static` _ClassPropertyInitializer_, return a list containing _ClassElement_.
189+
3. Else return a new empty List.
190+
191+
_ClassElementList_ : _ClassElementList_ _ClassElement_
192+
193+
1. Let _list_ be PropertyInitializerList of _ClassElementList_
194+
2. If _ClassElement_ is the production _ClassElement_ : _ClassPropertyInitializer_, append _ClassElement_ to the end of _list_.
195+
3. If _ClassElement_ is the production _ClassElement_ : `static` _ClassPropertyInitializer_, append _ClassElement_ to the end of _list_.
196+
4. Return _list_.
197+
198+
#### [14.5.14 Runtime Semantics: ClassDefinitionEvaluation](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-classdefinitionevaluation)
199+
200+
1. Let _lex_ be the LexicalEnvironment of the running execution context.
201+
2. Let _classScope_ be NewDeclarativeEnvironment(_lex_).
202+
3. Let _classScopeEnvRec_ be _classScope_’s environment record.
203+
4. If _className_ is not undefined, then
204+
1. Perform _classScopeEnvRec_.CreateImmutableBinding(_className_, true).
205+
5. If _ClassHeritage_<sub>opt</sub> is not present, then
206+
1. Let _protoParent_ be the intrinsic object %ObjectPrototype%.
207+
2. Let _constructorParent_ be the intrinsic object %FunctionPrototype%.
208+
6. Else
209+
1. Set the running execution context’s LexicalEnvironment to _classScope_.
210+
2. Let _superclass_ be the result of evaluating _ClassHeritage_.
211+
3. Set the running execution context’s LexicalEnvironment to _lex_.
212+
4. ReturnIfAbrupt(_superclass_).
213+
5. If _superclass_ is null, then
214+
1. Let _protoParent_ be null.
215+
2. Let _constructorParent_ be the intrinsic object %FunctionPrototype%.
216+
6. Else if IsConstructor(_superclass_) is false, throw a TypeError exception.
217+
7. Else
218+
1. If _superclass_ has a [[FunctionKind]] internal slot whose value is "generator", throw a TypeError exception.
219+
2. Let _protoParent_ be Get(superclass, "prototype").
220+
3. ReturnIfAbrupt(_protoParent_).
221+
4. If Type(_protoParent_) is neither Object nor Null, throw a TypeError exception.
222+
5. Let _constructorParent_ be _superclass_.
223+
7. Let _proto_ be ObjectCreate(_protoParent_).
224+
8. If _ClassBody_<sub>opt</sub> is not present, let _constructor_ be empty.
225+
9. Else, let _constructor_ be ConstructorMethod of _ClassBody_.
226+
10. If _constructor_ is empty, then,
227+
1. If _ClassHeritage_<sub>opt</sub> is present, then
228+
1. Let _constructor_ be the result of parsing the String "constructor(... args){ super (...args);}" using the syntactic grammar with the goal symbol _MethodDefinition_.
229+
2. Else,
230+
1. Let _constructor_ be the result of parsing the String "constructor( ){ }" using the syntactic grammar with the goal symbol _MethodDefinition_.
231+
11. Set the running execution context’s LexicalEnvironment to _classScope_.
232+
12. Let _constructorInfo_ be the result of performing DefineMethod for _constructor_ with arguments _proto_ and _constructorParent_ as the optional _functionPrototype_ argument.
233+
13. Assert: _constructorInfo_ is not an abrupt completion.
234+
14. Let _F_ be _constructorInfo_.[[closure]]
235+
15. If _ClassHeritage_<sub>opt</sub> is present, set _F_’s [[ConstructorKind]] internal slot to "derived".
236+
16. Perform MakeConstructor(_F_, false, _proto_).
237+
17. Perform MakeClassConstructor(_F_).
238+
18. Perform CreateMethodProperty(_proto_, "constructor", _F_).
239+
19. If _ClassBody_<sub>opt</sub> is not present, let _methods_ be a new empty List.
240+
20. Else, let _methods_ be NonConstructorMethodDefinitions of _ClassBody_.
241+
21. For each _ClassElement_ _m_ in order from _methods_
242+
1. If IsStatic of _m_ is false, then
243+
1. Let _status_ be the result of performing PropertyDefinitionEvaluation for _m_ with arguments _proto_ and false.
244+
2. Else,
245+
1. Let _status_ be the result of performing PropertyDefinitionEvaluation for _m_ with arguments _F_ and false.
246+
3. If _status_ is an abrupt completion, then
247+
1. Set the running execution context’s LexicalEnvironment to _lex_.
248+
2. Return _status_.
249+
22. **If _ClassBody_<sub>opt</sub> is not present, let _propertyDecls_ be a new empty List.**
250+
23. **Else, let _propertyDecls_ be GetDeclaredClassProperties of _ClassBody_.**
251+
24. **For each _ClassElement_ _i_ in order from _propertyDecls_**
252+
1. **let _propName_ be the result of performing PropName of _i_**
253+
2. **TODO: If HasRHSExpression of _i_, then**
254+
1. **TODO: Let _initFunc_ be a function with an outer environment set to that of the class body that returns the result of executing the RHS expression**
255+
3. **Else,**
256+
1. **TODO: Let _initFunc_ be null**
257+
4. **If IsStatic of _i_ is false, then**
258+
1. **TODO: Let _propertyStore_ be GetClassPropertyStore of _proto_**
259+
2. **TODO: Object.defineProperty(_propertyStore_, _propName_, {configurable: true, enumerable: true, writable: true, value: _initFunc_})
260+
5. **Else,**
261+
1. **TODO: Let _propertyStore_ be GetClassPropertyStore of _F_**
262+
2. **TODO: Object.defineProperty(_propertyStore_, _propName_, {configurable: true, enumerable: true, writable: true, value: _initFunc_})
263+
3. **TODO: If HasRHSInitializer of _i_ is true, then**
264+
1. Let _propValue_ be the result of calling _initFunc_
265+
2. **TODO: Object.defineProperty(_F_, _propName_, {configurable: true, enumerable: true, writable: true, value: _propValue})
266+
25. Set the running execution context’s LexicalEnvironment to _lex_.
267+
26. If _className_ is not undefined, then
268+
1. Perform _classScopeEnvRec_.InitializeBinding(_className_, _F_).
269+
27. Return _F_.

0 commit comments

Comments
 (0)