From 481c2960162d552e01253e32bb8198df0e09f825 Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Fri, 12 Jan 2018 18:10:16 +0100 Subject: [PATCH] Switch to lexically declarations in classes Based on feedback in #4 --- .ALTERNATIVES.md.swp | Bin 0 -> 45056 bytes .README.md.swp | Bin 0 -> 28672 bytes .spec.html.swp | Bin 0 -> 36864 bytes ALTERNATIVES.md | 298 +++++++ README.md | 399 ++------- github_deploy_key | 51 ++ github_deploy_key.pub | 1 + out.html | 1966 +++++++++++++++++++++++++++++++++++++++++ patch | 136 +++ 9 files changed, 2544 insertions(+), 307 deletions(-) create mode 100644 .ALTERNATIVES.md.swp create mode 100644 .README.md.swp create mode 100644 .spec.html.swp create mode 100644 ALTERNATIVES.md create mode 100644 github_deploy_key create mode 100644 github_deploy_key.pub create mode 100644 out.html create mode 100644 patch diff --git a/.ALTERNATIVES.md.swp b/.ALTERNATIVES.md.swp new file mode 100644 index 0000000000000000000000000000000000000000..3ad30fde7434e8bb749528c799c1aea5d0276ff8 GIT binary patch literal 45056 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

CbX&6Ty0?q=z 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 'hello' +Base.set('xyz'); + +Sub.get(); // => 'xyz' in this alternative, TypeError in the main proposal +Sub.set('abc'); // TypeError +``` + +## Imitate a prototype chain for static private field semantics + +In [this PR](https://github.com/tc39/proposal-static-class-features/pull/7), logic is drafted to give inherited static private fields semantics which are similar to inherited public static fields: There is, in effect, a "private prototype chain" which is maintained; reads to private static fields go up that prototype chain, while writes are reflected only in that one constructor. + +This alternative is rejected due to its high complexity and implementation requirements, which do not seem justified by use cases or programmer demand, especially in the presence of the lexically scoped function alternative. + +## Restricting static private field access to `static.#foo` + +Jordan Harband [suggested](https://github.com/tc39/proposal-class-fields/issues/43#issuecomment-328874041) that we make `static.` a syntax for referring to a property of the immediately enclosing class. If we add this feature, we could say that private static fields and methods may *only* be accessed that way. This has the disadvantage that, in the case of nested classes, there is no way to access the outer class's private static methods. However, as a mitigation, programmers may copy that method into another local variable before entering into another nested class, making it still available. + +With this alternative, the above code sample could be written as follows: + +```js +class Base { + static #field = 'hello'; + + static get() { + return static.#field; + } + + static set(value) { + return static.#field = value; + } +} + +class Sub extends Base {} + +Base.get(); // => 'hello' +Base.set('xyz'); + +Sub.get(); // => 'xyz' +Sub.set('abc'); + +Base.get(); // 'abc' +``` + +Here, `static` refers to the base class, not the subclass, so issues about access on subclass instances do not occur. + +## Restricting static field private access to `ClassName.#foo` + +The syntax for accessing private static fields and methods would be restricted to using the class name textually as the receiver. This would make it a SyntaxError to use `this.#privateMethod()` within a static method, for example. However, this would be a somewhat new kind of way to use scopes for early errors. Unlike var/let conflict early errors, this is much more speculative--the class name might actually be shadowed locally, which the early error would not catch, leading to a TypeError. In the championed semantics, such checks would be expected to be part of a linter or type system instead. + +With this alternative, the above code sample could be written as follows: + +```js +class Base { + static #field = 'hello'; + + static get() { + return Base.#field; + } + + static set(value) { + return Base.#field = value; + } +} + +class Sub extends Base {} + +Base.get(); // => 'hello' +Base.set('xyz'); + +Sub.get(); // => 'xyz' +Sub.set('abc'); + +Base.get(); // 'abc' +``` + +Here, explicit references the base class, not the subclass, so issues about access on subclass instances do not occur. A reference like `this.#field` would be an early error, helping to avoid errors by programmers. + +## Prototype chain walk for private fields and methods + +Ron Buckton [has](https://github.com/tc39/proposal-class-fields/issues/43#issuecomment-348045445) [proposed](https://github.com/tc39/proposal-private-methods/issues/18) that private field and method access could reach up the prototype chain. There are two ways that this could be specified, both of which have significant issues: +- **Go up the normal prototype chain with \[\[GetPrototypeOf]]**. This would be observable and interceptible by proxies, violating a design goal of private fields that they not be manipulated that way. +- **Use a separate, parallel, immutable prototype chain**. This alternative would add extra complexity, and break the way that other use of classes consistently works together with runtime mutations in the prototype chain. + +A positive aspect of Ron's proposal is that it preserves identical behavior with respect to subclassing as public static fields. + +## Switching all fields to being based on accessors + +The idea here is to avoid the subclassing overwriting hazard by changing the semantics of all field declarations: Rather than being own properties that are shadowed by a Set on a subclass, they are accessors (getter/setter pairs). In the case of instance fields, the accessor would read or write on the receiver. In the case of static fields, presumably, the read and write would happen on the superclass where they are defined, ignoring the receiver (otherwise, the TypeError issue from private static fields is then ported to public static fields as well, as the subclass constructor would not have its own value!). Private static fields would also follow this accessor pattern. In all cases, the getter would throw a TypeError when the receiver is an object which does not "have" the private field (e.g., its initializer has not run yet), an effectively new TDZ, which could reduce programmer errors. + +Some downsides of this proposal: +- **Public fields would no longer be own properties**. This may be rather confusing for programmers, who may expect features like object spread to include public instance fields. +- **Does not help implementations and might hurt startup time (maybe)**. This idea was initially proposed as part of a concept for having 'static shape', which could provide more predictability for implementers and programmers. At least on the implementation side, however, there would either have to be checks on each access to see if the field was initialized, or the initialization state would have to show up in its "hidden class". Either way, there's no efficiency gain if the fields are "already there, just in TDZ". In some implementations, startup time could be even worse than with own properties, until the system learns to optimize out the accessors. +- **Loses the object model--we'd have to start again**. Data properties have an object model permitting non-writable, non-enumerable and non-configurable properties, including its use by `Object.freeze`. If we want to provide these sorts of capabilities to public fields, they would have to be built again separately. + +For these reasons, the public fields proposal has been based on own properties. diff --git a/README.md b/README.md index 78ee68f..04e4cd2 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,20 @@ -# Static class features +# Static private fields and lexical declarations in classes Champion: Daniel Ehrenberg Stage 2 -This proposal tracks the "static" (i.e., of the constructor) aspects of the [class fields](http://github.com/tc39/proposal-class-fields) and [private methods](https://github.com/tc39/proposal-private-methods) proposals. In the November 2017 TC39 meeting, the static dimensions of these proposals were demoted to Stage 2, to be broken out into a separate proposal while the instance dimensions remain at Stage 3. This repository is created to explore the aspects which are still at Stage 2, to determine how to proceed to Stage 3 with some version of them. +This proposal: +1. **Adds Public static fields as previously proposed**. Public static fields are own data properties of the constructor in which they are defined, which is evaluated after the class's TDZ has ended. +1. **Adds lexical declarations in class bodies**. Lexical declarations are prefixed by a contextual keyword to differentiate them from other class elements. +1. **Does not add private static fields and private static methods**. The use cases presented for private static are met by lexical declarations. -The current proposal is similar to the previous semantics, with one modification: -1. **Public and private static fields are initialized only once in the class where they are defined, not additionally in subclasses**. [see below](https://github.com/tc39/proposal-static-class-features/blob/master/README.md#static-field-initialization) -1. **Private static methods can be called with the superclass or any subclasses as the receiver; otherwise, TypeError** (NEW) -1. **Private static fields can only be referenced with the class as the receiver; TypeError when used with anything else**. [see below](https://github.com/tc39/proposal-static-class-features/blob/master/README.md#static-private-access-on-subclasses) - -Note that private fields and methods are only accessible within the class body where they are defined; the new change here only pertains to what happens when methods in that superclass body is invoked with a receiver which is a subclass constructor. +This proposal was created to track the "static" (i.e., of the constructor) aspects of the [class fields](http://github.com/tc39/proposal-class-fields) and [private methods](https://github.com/tc39/proposal-private-methods) proposals. In the November 2017 TC39 meeting, the static dimensions of these proposals were demoted to Stage 2, to be broken out into a separate proposal while the instance dimensions remain at Stage 3. Although lexical declarations are significantly different from the previous proposal of static private methods and fields, ## Static public fields Like static public methods, static public fields take a common idiom which was possible to write without class syntax and make it more ergonomic, have more declarative-feeling syntax (although the semantics are quite imperative), and allow free ordering with other class elements. -### Semantics - -Define an own property on the constructor which is set to the value of the initializer expression. The initializer is evaluated in a scope where the binding of the class is available--unlike in computed property names, the class can be referred to from inside initializers without leading to a ReferenceError. - -Alternate semantics are discussed in ["Initializing fields on subclasses"](#initializing-fields-on-subclasses). However, they are not proposed here, for reasons detailed in that section. These semantics are justified in more detail in ["Static field initialization"](#static-field-initialization). - ### Use case ```js @@ -43,6 +35,12 @@ CustomDate.epoch = new CustomDate(0); Declaring static properties in the class body is hoped to be cleaner and doing a better job of meeting programmer expectations of what classes should be for. It's claimed that the latter workaround is a common idiom, and it would be a nice convenience for programmers if the property declaration could be lifted into the class body, matching how methods are placed there. +### Semantics + +Define an own property on the constructor which is set to the value of the initializer expression. The initializer is evaluated in a scope where the binding of the class is available--unlike in computed property names, the class can be referred to from inside initializers without leading to a ReferenceError. + +Alternate semantics are discussed in ["Initializing fields on subclasses"](#initializing-fields-on-subclasses). However, they are not proposed here, for reasons detailed in that section. These semantics are justified in more detail in ["Static field initialization"](#static-field-initialization). + ### Why only initialize static fields once Kevin Gibbons [raised a concern](https://github.com/tc39/proposal-class-fields/issues/43#issuecomment-340517955) that JavaScript programmers may not be used to having objects with mutated properties which are exposed on the prototype chain, the way that static fields are inherited and may be overwritten. Some reasons why this is not that bad: @@ -85,25 +83,57 @@ Counter.count; // 3, own property SubCounter.count; // 2, own property ``` -See [Initializing fields on subclasses](#initializing-fields-on-subclasses) for more details on an alternative proposed semantics and why it was not selected. +### Why not to reinitialize public fields on subclasses -## Static private methods and accessors +Kevin Gibbons has proposed that class fields have their initialisers re-run on subclasses. This would address the static private subclassing issue by adding those to subclasses as well, leading to no TypeError on use. -### Semantics +With this alternate, the initial counter example would have the following semantics: + +```js +// NOTE: COUTNERFACTUAL SEMANTICS BELOW +static Counter { + static count = 0; + static inc() { this.count++; } +} +class SubCounter extends Counter { } + +Counter.hasOwnProperty("count"); // true +SubCounter.hasOwnProperty("count"); // true + +Counter.count; // 0, own property +SubCounter.count; // 0, own property + +Counter.inc(); // undefined +Counter.count; // 1, own property +SubCounter.count; // 0, own property + +// ++ is just dealing iwth own properties the whole time +SubCounter.inc(); + +Counter.hasOwnProperty("count"); // true +SubCounter.hasOwnProperty("count"); // true + +Counter.count; // 1, own property +SubCounter.count; // 1, own property + +Counter.inc(); Counter.inc(); +Counter.count; // 3, own property +SubCounter.count; // 1, own property +``` -Like [instance private methods](https://github.com/tc39/proposal-private-methods/blob/master/DETAILS.md), static private methods are conceptually non-writable private fields on objects whose value is the method. There is no prototype chain access in private fields or methods; instead, the methods are installed in each object that would be able to access the method through prototype chain lookups. +However, these alternate semantics have certain disadvantages: +- Subclassing in JS has always been "declarative" so far, not actually executing anything from the superclass. It's really not clear this is the kind of hook we want to add to suddenly execute code here. +- The use cases that have been presented so far for expecting the reinitialization semantics seem to use subclassing as a sort of way to create a new stateful class (e.g., with its own cache or counter, or copy of some other object). These could be accomplished with a factory function which returns a class, without requiring that this is how static fields work in general for cases that are not asking for this behavior. -In the case of instance private methods, this is instances of the class and subclasses; for static private methods, this is the constructor and subclass constructors. Invoking a private method on an object where it is missing causes a TypeError. +## Lexically scoped declarations in classes -In specification terms, when a subclass is created which extends another class, the non-writable and accessor private 'fields' (namely, the private methods and accessors) of the super class are copied to the subclass. This makes it so that the private methods and accessors can be called on the subclass. +This proposal adds lexically scoped function, let, const and class declarations in class bodies. To make the syntax intuitively unambiguous, these declarations are prefixed by a yet-to-be-determined keyword. In this explainer, `` is used in place of a particular token; see [#9](https://github.com/tc39/proposal-static-class-features/issues/9) for discussion of which token should be selected. ### Use case -Static private methods can be useful whenever there is shared behavior to extract into a function which uses private fields, but which doesn't work cleanly as an instance method. For example, multiple factory static methods may share part of their implementation, including parts which run both before and after construction of the instance. See [#4](https://github.com/tc39/proposal-static-class-features/issues/4) for more context about the following example. +Based on the example at [#4](https://github.com/tc39/proposal-static-class-features/issues/4) by Domenic Denicola: ```js -export const registry = new JSDOMRegistry(); - export class JSDOM { #createdBy; @@ -115,15 +145,16 @@ export class JSDOM { url = normalizeFromURLOptions(url, options); const body = await getBodyFromURL(url); - return JSDOM.#finalizeFactoryCreated(body, options, "fromURL"); + return finalizeFactoryCreated(body, options, "fromURL"); } static async fromFile(filename, options = {}) { const body = await getBodyFromFilename(filename); - return JSDOM.#finalizeFactoryCreated(body, options, "fromFile"); + return finalizeFactoryCreated(body, options, "fromFile"); } - static #finalizeFactoryCreated(body, options, factoryName) { + const registry = new JSDOMRegistry(); + function finalizeFactoryCreated(body, options, factoryName) { normalizeOptions(options); let jsdom = new JSDOM(body, options): jsdom.#createdBy = factoryName; @@ -133,311 +164,65 @@ export class JSDOM { } ``` -In [Issue #1](https://github.com/tc39/proposal-static-class-features/issues/1), there is further discussion about whether this feature is well-motivated. In particular, static private methods can typically be replaced by either lexically scoped function declarations outside the class declaration, or by private instance methods. However, the current proposal is to include them, due to the use cases in [#4](https://github.com/tc39/proposal-static-class-features/issues/4). - -### Subclassing use case - -As described above, static private methods may be invoked with subclass instances as the receiver. Note that this does *not* mean that subclass bodies may call private methods from superclasses--the methods are private, not protected, and it would be a SyntaxError to call the method from a place where it's not syntactically present. - -In the below example, a public static method `from` is refactored, using a private static method. This private static method has an extension point which can be overridden by subclasses, which is that it calls the `of` method. All of this is in service of factory functions for creating new instances. If the private method `#from` were only callable with `MyArray` as the receiver, a `TypeError` would result. - -```js -class MyArray { - static #from(obj) { - this.of.apply(...obj); - } - static from(obj) { - // This function gets large and complex, with parts shared with - // other static methods, so an inner portion #from is factored out - return this.#from(obj); - } -} - -class SubMyArray extends MyArray { - static of(...args) { - let obj = new SubMyArray(); - let i = 0; - for (let arg of args) { - obj[i] = arg; - i++; - } - } -} - -let subarr = MySubArray.from([1, 2, 3]); -``` - -## Static private fields - ### Semantics -Unlike static private methods, static private fields are private fields just of the constructor. If a static private field is read with the receiver being a subclass, a TypeError will be triggered. - -As with static public fields, the initializer is evaluated in a scope where the binding of the class is available--unlike in computed property names, the class can be referred to from inside initializers without leading to a ReferenceError. As described in [Why only initialize static fields once](#why-only-initialize-static-fields-once), the initializer is evaluated only once. - -### Use case - -```js -class ColorFinder { - static #red = "#ff0000"; - static #blue = "#00ff00"; - static #green = "#0000ff"; - - static colorName(name) { - switch (name) { - case "red": return ColorFinder.#red; - case "blue": return ColorFinder.#blue; - case "green": return ColorFinder.#green; - default: throw new RangeError("unknown color"); - } - } - - // Somehow use colorName -} -``` - -In [Issue #1](https://github.com/tc39/proposal-static-class-features/issues/1), there is further discussion about whether this feature is well-motivated. In particular, static private fields can typically be subsumed by lexically scoped variables outside the class declaration. Static private fields are motivated mostly by a desire to allow free ordering of things inside classes and consistency with other class features. It's also possible that some initialzer expressions may want to refer to private names declared inside the class, e.g., in [this gist](https://gist.github.com/littledan/19c09a09d2afe7558cdfd6fdae18f956). - -The behavior of private static methods have, in copying to subclass constructors, does not apply to private static fields. This is due to the complexity and lack of a good option for semantics which are analogous to static public fields, as explained below. - -### TypeError case - -Justin Ridgewell [expressed concern](https://github.com/tc39/proposal-class-fields/issues/43) about the TypeError that results from static private field access from subclasses. Here's an example of that TypeError, which occurs when code ported from the above static public fields example is switched to private fields: - -```js -static Counter { - static #count = 0; - static inc() { this.#count++; } - static get count() { return this.#count; } -} -class SubCounter extends Counter { } - -Counter.inc(); // undefined -Counter.count; // 1 - -SubCounter.inc(); // TypeError - -Counter.count; // 1 -SubCounter.count; // TypeError -``` - -A TypeError is used here because no acceptable alternative would have the semantics which are analogous to static public fields. Some alternatives are discussed below. - -#### Why this TypeError is not so bad - -The above concern is hoped to be not too serious because: -- Programmers can avoid the issue by instead writing `ClassName.#field`. This phrasing should be easier to understand, anyway--no need to worry about what `this` refers to. -- It is not so bad to repeat the class name when accessing a private static field. When implementing a recursive function, the name of the function needs to be repeated; this case is similar. -- It is statically known whether a private name refers to a static or instance-related class field. Therefore, implementations should be able to make helpful error messages for instance issues that say "TypeError: The private field #foo is only present on instances of ClassName, but it was accessed on an object which was not an instance", or, "TypeError: The static private method #bar is only present on the class ClassName; but it was accessed on a subclass or other object", etc. -- Linters could flag uses of `foo.#field` where `foo` is not the name of the class and `#field` is a static private field, and discourage its use that way. -- Type systems which want to be slightly more accepting could trigger an error on any class with a class which is subclassed and has public method which uses a private method or field without the class's name being the receiver. In the case of TypeScript, [this is already not polymorphic](https://github.com/Microsoft/TypeScript/issues/5863) so it would already flag instances of `this.#field` for a private static method call within a public static method. -- Beginners can just learn the rule (helped by linters, type systems and error messages) to refer to the class when calling static private methods. Advanced users can learn the simple mental model that corresponds to the specification: private things are represented by a WeakMap, and public things by ordinary properties. When it's by the instance, the WeakMap has a key for each instance; when it's static, the WeakMap has a single key, for the constructor. -- A guaranteed TypeError when the code runs on the subclass is a relatively easy to debug failure mode. This is how JS responds, at a high level, when you access an undefined variable as well, or read a property on undefined. A silent other interpretation would be the real footgun. -- TC39 has worked hard on other guaranteed exceptions, such as the "temporal dead zone"--a ReferenceError from reading `let`- or `const`-declared variables whose declaration has not yet been reached. Here, a runtime error was considered very useful for programmers and a way of preventing a "footgun". In this case, we're getting such a guaranteed error. - -## Programmer mental model - -These proposed semantics are designed to be learnable by beginners as well as understandable at a deep level by experts, without any mismatch. The semantics here aren't just "something that works well in the spec", but rather a design which remains intuitive and consistent through multiple lenses. +Class bodies already contain a lexical scope, in which the class name is bound to the value of the class. In this same lexical scope, this feature adds additional bindings. -### Beginner, simplified semantics +These lexical bindings add another time when code observably executes. This execution is proposed to tie in with [Brian Terlson and Yehuda Katz's broader proposal for class evaluation order](https://github.com/tc39/tc39-notes/blob/master/es7/2016-05/classevalorder.pdf) as follows: +- Function declarations (including async functions, generators and async generators) are hoisted up to the top of the class scope, initialized before the `extends` clause is evaluated. +- `let`, `const` and `class` delarations involve some evaluation. For the same reason as for static field initializers, it is helpful if the class is no longer in TDZ when they are executed. Therefore, the statements are executed interspersed with static field initializers (and possibly [element finalizers](https://github.com/tc39/proposal-decorators/issues/42) from decorators), top-to-bottom. Until they evaluate, the variables defined are in TDZ. -To make something inaccessible from outside the class, put a `#` at the beginning of the name. When a field or method has `static`, that means it is on the class, not on instances. To access static class elements, use the syntax `ClassName.element` or `ClassName.#element`, depending on whether the name contains a `#`. Note that the latter case is available only inside the class declaration. If you make a mistake in accessing private class elements, JS will throw `TypeError` when the code is run to make it easier to catch the programming error. To catch errors earlier in development, try using a linter or type system. +## No static private fields, methods and accessors -### Expert, complete semantics +Previously, private static fields and methods were proposed. The original proposal for private static fields and methods was that the constructor object where they were defined would have these as private fields, and no other objects would have it. However, Justin Ridgewell, [pointed out](https://github.com/tc39/proposal-class-fields/issues/43) that this would be unexpectedly through TypeErrors in the case of subclassing. -Public and private class elements are analogous to each other, with the difference being that public class elements are implemented as properties on the object, and private class elements are like a WeakMap, or internal slot. The rest of this section is written in terms of a WeakMap, but could be phrased equally in terms of internal slots. +Lexical declarations enable the known use cases of static private fields and methods. Due to the combination of the hazards of use and the lack of motivation, this proposal posits that static private features are unlikely to be a justified addition in the future. -Public class elements are defined with \[\[DefineOwnProperty]] when they are added to the relevant object, and private class elements have a corresponding WeakMap, mapping objects to their values, which an object is added to when the element is defined for the object. For instance fields, this relevant object is the instance; for static fields, this relevant object is the constructor. +## Public instance methods remain as previously proposed -Private methods are a special case--they are made to be inherited, either from the prototype or a superclass, but the prototype chain is not accessed when a private method is read. Instead of inheriting, private methods are added as own fields on all of the relevant objects, whether it's all instances inheriting from the class for ordinary methods, or all subclasses of a constructor for a static method. +Lexical declarations can sometimes be used for situations that would otherwise be used for private methods. However, the champion do not plan to withdraw the proposal even if lexically scoped function declarations in classes are accepted by TC39 for the following reasons: +- Private methods provide an easy path to refactoring from public to private--no need to rephrase methods or their callsites, just add a # before the definition and usages. +- Private methods give access to the right `this` value naturally, without using `Function.prototype.call`, which is core to making the refactoring easy. +- Private methods support super property access, which is a syntax error in function declarations. +- Private methods are terse and convenient to use, with semantics which is naturally analogous to othre class elements. They should be sufficient for the majority of shared but not exposed behavior in classes. +- Private methods do not have the TypeError hazards which private static methods have--they are installed in the constructor, so they are present according to the prototype chain of the class hierarchy at the time the instance was constructed. -Static fields are syntax sugar for defining a property or private field of a constructor after the rest of the class definition runs. As such, they are able to access or instantiate the class in their initializer. Static fields are installed on just the particular constructor, whether as an own property or a key in a singleton WeakMap. - -The above semantics are orthogonal and consistent among private vs public, static vs instance, and field vs method, making it easy for advanced programmers to do appropriate refactorings between features. - -## "Back pocket" alternatives - -These alternatives are not currently proposed by the champion, but are considered possibly feasible alternatives. - -### Omit static private fields - -The most realistic "hazard" cases for private access on subclasses was in the use of private static methods from subclasses. Because private methods are immutable, they don't suffer the same mismatch as static fields, where semantics need to be defined when they are overwritten (which is ultimately an issue making it difficult to support private static fields on subclasses). For this reason, private methods could just be installed on subclass constructors and made callable with those as a receiver. - -You could argue that the different set of "relevant objects" for private static methods is somewhat analogous to the way that the set of objects is different for private instance methods vs public instance methods (the set of instances vs the prototype, or the constructor and subclasses vs the constructor). In effect, these semantics provide the equivalent of a "private prototype chain walk" for the state of the prototype chain when the instance was constructed. This alternative would meet many of the presented use cases and avoid the "hazard" semantics, but it is a bit ad-hoc and doesn't explain why static private fields are omitted. - -### Allow static private fields to be read from subclasses - -If we want to get static private fields to be as close as possible to static public fields when it comes to inheritance semantics: The shadowing property of writes to properties on the prototype chain is very weird and complicated, and wouldn't make sense to replicate; on the other hand, reads up the prototype chain are simple and intelligible. We could allow reads, but not writes, to take place from subclasses. The reads would reflect writes that happen later to the superclass's static private field. - -This alternative is currently not selected because it would be pretty complicated, and lead to a complicated mental model. It would still not make public and private static fields completely parallel, as writes from subclasses are not allowed. +### Use case -Here's an example of code which would be enabled by this alternative (based on code by Justin Ridgewell): +The [private methods explainer](https://github.com/tc39/proposal-private-methods) walks through an example of incrementally refactoring code to make more use of private methods and accessors. The following is the final stage of the code, with the full refactoring in place. ```js -class Base { - static #field = 'hello'; - - static get() { - return this.#field; - } +class Counter extends HTMLElement { + #xValue = 0; - static set(value) { - return this.#field = value; + get #x() { return #xValue; } + set #x(value) { + this.#xValue = value; + window.requestAnimationFrame(this.#render.bind(this)); } -} - -class Sub extends Base {} - -Base.get(); // => 'hello' -Base.set('xyz'); - -Sub.get(); // => 'xyz' in this alternative, TypeError in the main proposal -Sub.set('abc'); // TypeError -``` - -### Restricting static private field access to `static.#foo` -Jordan Harband [suggested](https://github.com/tc39/proposal-class-fields/issues/43#issuecomment-328874041) that we make `static.` a syntax for referring to a property of the immediately enclosing class. If we add this feature, we could say that private static fields and methods may *only* be accessed that way. This has the disadvantage that, in the case of nested classes, there is no way to access the outer class's private static methods. However, as a mitigation, programmers may copy that method into another local variable before entering into another nested class, making it still available. - -With this alternative, the above code sample could be written as follows: - -```js -class Base { - static #field = 'hello'; - - static get() { - return static.#field; + #clicked() { + this.#x++; } - static set(value) { - return static.#field = value; + constructor() { + super(); + this.onclick = this.#clicked.bind(this); } -} - -class Sub extends Base {} -Base.get(); // => 'hello' -Base.set('xyz'); + connectedCallback() { this.#render(); } -Sub.get(); // => 'xyz' -Sub.set('abc'); - -Base.get(); // 'abc' -``` - -Here, `static` refers to the base class, not the subclass, so issues about access on subclass instances do not occur. - -### Restricting static field private access to `ClassName.#foo` - -The syntax for accessing private static fields and methods would be restricted to using the class name textually as the receiver. This would make it a SyntaxError to use `this.#privateMethod()` within a static method, for example. However, this would be a somewhat new kind of way to use scopes for early errors. Unlike var/let conflict early errors, this is much more speculative--the class name might actually be shadowed locally, which the early error would not catch, leading to a TypeError. In the championed semantics, such checks would be expected to be part of a linter or type system instead. - -With this alternative, the above code sample could be written as follows: - -```js -class Base { - static #field = 'hello'; - - static get() { - return Base.#field; + #render() { + this.textContent = this.#x.toString(); } - - static set(value) { - return Base.#field = value; - } -} - -class Sub extends Base {} - -Base.get(); // => 'hello' -Base.set('xyz'); - -Sub.get(); // => 'xyz' -Sub.set('abc'); - -Base.get(); // 'abc' -``` - -Here, explicit references the base class, not the subclass, so issues about access on subclass instances do not occur. A reference like `this.#field` would be an early error, helping to avoid errors by programmers. - -## Alternate proposals not selected - -Several alternatives have been discussed within TC39. This repository is not pursuing these ideas further. Some may be feasible, but are not selected by the champion for reasons described below. - -### Initializing fields on subclasses - -Kevin Gibbons has proposed that class fields have their initialisers re-run on subclasses. This would address the static private subclassing issue by adding those to subclasses as well, leading to no TypeError on use. - -With this alternate, the initial counter example would have the following semantics: - -```js -static Counter { - static count = 0; - static inc() { this.count++; } } -class SubCounter extends Counter { } - -Counter.hasOwnProperty("count"); // true -SubCounter.hasOwnProperty("count"); // true - -Counter.count; // 0, own property -SubCounter.count; // 0, own property - -Counter.inc(); // undefined -Counter.count; // 1, own property -SubCounter.count; // 0, own property - -// ++ is just dealing iwth own properties the whole time -SubCounter.inc(); - -Counter.hasOwnProperty("count"); // true -SubCounter.hasOwnProperty("count"); // true - -Counter.count; // 1, own property -SubCounter.count; // 1, own property - -Counter.inc(); Counter.inc(); -Counter.count; // 3, own property -SubCounter.count; // 1, own property +window.customElements.define('num-counter', Counter); ``` -However, this proposal has certain disadvantages: -- Subclassing in JS has always been "declarative" so far, not actually executing anything from the superclass. It's really not clear this is the kind of hook we want to add to suddenly execute code here. -- The use cases that have been presented so far for expecting the reinitialization semantics seem to use subclassing as a sort of way to create a new stateful class (e.g., with its own cache or counter, or copy of some other object). These could be accomplished with a factory function which returns a class, without requiring that this is how static fields work in general for cases that are not asking for this behavior. - -### Prototype chain walk for private fields and methods - -Ron Buckton [has](https://github.com/tc39/proposal-class-fields/issues/43#issuecomment-348045445) [proposed](https://github.com/tc39/proposal-private-methods/issues/18) that private field and method access could reach up the prototype chain. There are two ways that this could be specified, both of which have significant issues: -- **Go up the normal prototype chain with \[\[GetPrototypeOf]]**. This would be observable and interceptible by proxies, violating a design goal of private fields that they not be manipulated that way. -- **Use a separate, parallel, immutable prototype chain**. This alternative would add extra complexity, and break the way that other use of classes consistently works together with runtime mutations in the prototype chain. - -A positive aspect of Ron's proposal is that it preserves identical behavior with respect to subclassing as public static fields. - -### Lexically scoped variables and function declarations in classes - -Allen Wirfs-Brock has proposed lexically scoped functions and variables within class bodies. The syntax that Allen proposed was an ordinary function declaration or let/const declaration in the top level of a class body: - -```js -class Foo { - function bar() { } // lexically scoped to the class body - static method() { bar() } // method on the constructor -} -``` - -However, that proposed syntax may be unintuitive: keywords like function and let don't exactly scream, "unlike the other things in this list, this declaration is not exported and it's also not specific to the instance". For that reason, this repository proposes that static class features have a shape analogous to a field or method declaration. ([see discussion in bug](https://github.com/tc39/proposal-static-class-features/issues/4#issuecomment-354515761)). - -### Omitting static private fields and methods - -This alternative was previously proposed in this repository. The alternative is dispreferred due to [the use cases in Issue #4](https://github.com/tc39/proposal-static-class-features/issues/4). - -A related alternative is moving ahead with static public fields while continuing development on static private fields. This repository is devoted to a full exploration of the problem space and is currently at Stage 2 which has been requested by committee members to proceed; it is not currently proposed to advance some parts and not others. - -### Switching all fields to being based on accessors +## Proposal status -The idea here is to avoid the subclassing overwriting hazard by changing the semantics of all field declarations: Rather than being own properties that are shadowed by a Set on a subclass, they are accessors (getter/setter pairs). In the case of instance fields, the accessor would read or write on the receiver. In the case of static fields, presumably, the read and write would happen on the superclass where they are defined, ignoring the receiver (otherwise, the TypeError issue from private static fields is then ported to public static fields as well, as the subclass constructor would not have its own value!). Private static fields would also follow this accessor pattern. In all cases, the getter would throw a TypeError when the receiver is an object which does not "have" the private field (e.g., its initializer has not run yet), an effectively new TDZ, which could reduce programmer errors. +Static public fields are implemented in Babel and V8 behind a flag, and had test262 tests written (though currently have been removed due to this proposal being at Stage 2). -Some downsides of this proposal: -- **Public fields would no longer be own properties**. This may be rather confusing for programmers, who may expect features like object spread to include public instance fields. -- **Does not help implementations and might hurt startup time (maybe)**. This idea was initially proposed as part of a concept for having 'static shape', which could provide more predictability for implementers and programmers. At least on the implementation side, however, there would either have to be checks on each access to see if the field was initialized, or the initialization state would have to show up in its "hidden class". Either way, there's no efficiency gain if the fields are "already there, just in TDZ". In some implementations, startup time could be even worse than with own properties, until the system learns to optimize out the accessors. -- **Loses the object model--we'd have to start again**. Data properties have an object model permitting non-writable, non-enumerable and non-configurable properties, including its use by `Object.freeze`. If we want to provide these sorts of capabilities to public fields, they would have to be built again separately. +Lexical declarations in classes do not currently have any implementations or tests. -For these reasons, the public fields proposal has been based on own properties. +Alternatives to this proposal are considered in [ALTERNATIVES.md]. diff --git a/github_deploy_key b/github_deploy_key new file mode 100644 index 0000000..de901d0 --- /dev/null +++ b/github_deploy_key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/github_deploy_key.pub b/github_deploy_key.pub new file mode 100644 index 0000000..a19517c --- /dev/null +++ b/github_deploy_key.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDKa6WVkvoRyQgeucyKMowuJzOe6e2oP8wjHpKXTxxpsMa+bEnutA13Lrz4BPFnAwTY4WPHxCG2xQ9HpWZWKujUNicixO7X/C/jOHrPUmzl9s8PDPcMEo5oNObF9fer1bB2pYar0QomhR4Tray8EKwvF6llW7KpHDakKzuOyp5zWVxKHnxL/xwUnfJtfe4U9IfAR+Sld1OuVWA4h8tpevWareYSpTvvOmGXyMbINarRSQ49O/GnSaHts5RaHufAke5Ed71x/xBn8YUVUqlHcpXziRE0Hx8l6AX1EzqdTTj5Fe84V3nTjs1VydgIc+kBLQ3bvcxvncjAJSNVgm7vCIozdN3hzXtlyRDD8PTEwnJi516v+JDzOrnBPL5ea/a+8ZLWJ1m0sWfe1b59Dgs7qn3FJPDtPHWc7Ji1fkAFmt9OfZ+ODytrkd4FThycgZ+XlDou2CCHC8/lpaoMKbel7fgR/Iyzxm2BrtdHc2HTqT4J9v8ffYqtgPVr23efa5NcIfV0J9yxvTEeARG+HOEAaFlPLDSq5cFt9ktDopEMWoYrhEI7kkzb6waglPTHffIthFfMZYEiPm9V55FfO1/DVGJpVjZD4M6oRsM1h8c5s2BYO5CUZ/xnIhhAGK1f8YZFJtOIWUn9M67+lWCjckAGWeG4VWBfnoJ0jSsiEVvhW8fHwQ== littledan@igalia.com diff --git a/out.html b/out.html new file mode 100644 index 0000000..b281aad --- /dev/null +++ b/out.html @@ -0,0 +1,1966 @@ + + +Static class features

Stage 2 Draft / January 15, 2018

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 only static public fields. Static private fields and static private methods are omitted, with rationale documented in this bug. This specification text maintains the previously proposed semantics that each static public field is created just once, on the class it is defined, and not additional times for each subclass, as motivated in this bug. For further context and motivation, see the explainer document for this proposal.

+
+ + +

1Syntax

+ + + ClassElement[Yield, Await]:MethodDefinition[?Yield, ?Await] + staticMethodDefinition[?Yield, ?Await] + FieldDefinition[?Yield, ?Await]; + staticFieldDefinition[?Yield, ?Await]; + <placeholder>Declaration + ; + + + +

1.1Static Semantics: Early Errors

+ + ClassElement:staticFieldDefinition; + +
    +
  • + It is a Syntax Error if PropName of FieldDefinition is "prototype" or "constructor". + +
  • +
+
+ +
+ + +

2Algorithms

+ + +

2.1Runtime Semantics: ClassElementEvaluation

+

With parameters object and enumerable.

+ + + ClassElement:staticFieldDefinition; + +
  1. Return ClassFieldDefinitionEvaluation of FieldDefinition with parameter true and object. +
+ + + ClassElement:FieldDefinition; + +
  1. Return ClassFieldDefinitionEvaluation of FieldDefinition with parameter false and object. +
+ + + ClassElement:<placeholder>Declaration + +
  1. Return a List containing Record { + [[Declaration]]: Declaration + [[Static]]: true, + [[IsAnonymousFunctionDefinition]]: false + }. +
+
+ + +

2.2Runtime Semantics: ClassFieldDefinitionEvaluation

+ +

With parameters isStatic and homeObject.

+ + + FieldDefinition:ClassElementNameInitializeropt + +
  1. Let fieldName be the result of evaluating ClassElementName.
  2. ReturnIfAbrupt(fieldName).
  3. If Initializeropt is present,
    1. Let lex be the Lexical Environment of the running execution context.
    2. Let formalParameterList be an instance of the production + FormalParameters:[empty] +.
    3. Let initializer be FunctionCreate(Method, formalParameterList, Initializer, lex, true).
    4. Perform MakeMethod(initializer, homeObject).
    5. Let isAnonymousFunctionDefinition be IsAnonymousFunctionDefinition(Initializer).
  4. Else,
    1. Let initializer be empty.
    2. Let isAnonymousFunctionDeclaration be false.
  5. Return a List containing Record { + [[Name]]: fieldName, + [[Initializer]]: initializer, + [[Static]]: isStatic, + [[IsAnonymousFunctionDefinition]]: isAnonymousFunctionDefinition + }. +
+
+ + +

2.3InitializeStaticFields(F)

+ +
  1. Assert: Type(F) is Object.
  2. Assert: F is an ECMAScript function object.
  3. Let fieldRecords be the value of F's [[Fields]] internal slot.
  4. For each item fieldRecord in order from fieldRecords,
    1. If fieldRecord.[[Static]] is true, then
      1. If fieldRecord has a [[Declaration]] field,
        1. Let ret be the result of evaluating fieldRecord.[[Declaration]].
        2. ReturnIfAbrupt(ret).
      2. Else,
        1. Perform ? DefineField(F, fieldRecord).
  5. Return. +
+
+ + +

2.4InitializeInstanceFields ( O, constructor )

+ +
  1. Assert: Type ( O ) is Object.
  2. Assert: Assert constructor is an ECMAScript function object.
  3. Let fieldRecords be the value of constructor's [[Fields]] internal slot.
  4. For each item fieldRecord in order from fieldRecords,
    1. If fieldRecord.[[Static]] is false, then
      1. Perform ? DefineField(O, fieldRecord).
  5. Return. +
+ + +

2.4.1Static Semantics: IsStatic

+ + + ClassElement:staticFieldDefinition + +
  1. Return true. +
+
+ + +

2.4.2Static Semantics: LexicallyScopedDeclarations

+ + + ClassBody:ClassElementList + +
  1. Return the LexicallyScopedDeclarations of ClassElementList. +
+ + ClassElementList:ClassElementListClassElement + +
  1. Let declarations be LexicallyScopedDeclarations of ClassElementList.
  2. Append to declarations the elements of the LexicallyScopedDeclarations of ClassElement.
  3. Return declarations. +
+ + ClassElementList:ClassElement + +
  1. Return the LexicallyScopedDeclarations of ClassElement. +
+ + ClassElement:MethodDefinition + + + ClassElement:staticMethodDefinition + + + FieldDefinition[Yield, Await]:; + + + + ClassElement:; + +
  1. Return a new empty List. +
+ + ClassElement:<placeholder>Declaration + +
  1. Return a new List containing DeclarationPart of Declaration. +
+
+ + +

2.4.3Runtime 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 PrivateNameEnvironment 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 PrivateBoundNames of ClassBodyopt,
      1. Perform classPrivateEnvRec.CreateImmutableBinding(dn, true).
  9. Perform ! BlockDeclarationInstantiation(ClassBody, classScopeEnvRec).
  10. If ClassHeritageopt is not present, then
    1. Let protoParent be the intrinsic object %ObjectPrototype%.
    2. Let constructorParent be the intrinsic object %FunctionPrototype%.
  11. Else,
    1. Set the running execution context's LexicalEnvironment to classScope.
    2. NOTE: The running execution context's PrivateNameEnvironment 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.
  12. Let proto be ObjectCreate(protoParent).
  13. If ClassBodyopt is not present, let constructor be empty.
  14. Else, let constructor be ConstructorMethod of ClassBody.
  15. 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].
  16. Set the running execution context's LexicalEnvironment to classScope.
  17. Set the running execution context's PrivateNameEnvironment to classPrivateEnvironment.
  18. Let constructorInfo be the result of performing DefineMethod for constructor with arguments proto and constructorParent as the optional functionPrototype argument.
  19. Assert: constructorInfo is not an abrupt completion.
  20. Let F be constructorInfo.[[Closure]].
  21. If ClassHeritageopt is present and protoParent is not null, then set F.[[ConstructorKind]] to "derived".
  22. Perform MakeConstructor(F, false, proto).
  23. Perform MakeClassConstructor(F).
  24. Perform CreateMethodProperty(proto, "constructor", F).
  25. If ClassBodyopt is not present, let methods be a new empty List.
  26. Else, let elements be NonConstructorMethodDefinitions of ClassBody.
  27. Let fieldRecords be a new empty List.
  28. For each ClassElement e in order from elements
    1. If IsStatic of e is false, then
      1. Let fields be the result of performing ClassElementEvaluation for e with arguments proto and false.
    2. Else,
      1. Let fields be the result of performing ClassElementEvaluation for e with arguments F and false.
    3. If fields is an abrupt completion, then
      1. Set the running execution context's LexicalEnvironment to lex.
      2. Set the running execution context's PrivateNameEnvironment to outerPrivateEnvironment.
      3. Return Completion(status).
    4. Append to fieldRecords the elements of fields.
  29. If className is not undefined, then
    1. Perform classScopeEnvRec.InitializeBinding(className, F).
  30. Set the running execution context's LexicalEnvironment to lex.
  31. Set the value of F's [[Fields]] internal slot to fieldRecords.
  32. Let result be InitializeStaticFields(F).
  33. If result is an abrupt completion, then
    1. Set the running execution context's LexicalEnvironment to lex.
    2. Set the running execution context's PrivateNameEnvironment to outerPrivateEnvironment.
    3. Return Completion(result).
  34. Set the running execution context's LexicalEnvironment to lex.
  35. Set the running execution context's PrivateNameEnvironment to outerPrivateEnvironment.
  36. Return F. +
+
+ +
+
+

ACopyright & Software License

+ +

Copyright Notice

+

© 2018 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 http://www.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. +
  3. 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.
  4. +
  5. 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.
  6. +
+ +

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.

+ +
\ No newline at end of file diff --git a/patch b/patch new file mode 100644 index 0000000..9364615 --- /dev/null +++ b/patch @@ -0,0 +1,136 @@ +commit 96f31f16ffba5a74978438c3137825a49e15dbdf +Author: Daniel Ehrenberg +Date: Fri Dec 15 18:10:24 2017 +0100 + + Normative: Remove static fields + + At the November 2017 TC39 meeting, the committee decided to demote + static fields (both public and private) to a separate Stage 2 proposal. + That proposal is being developed in + https://github.com/tc39/proposal-static-class-features/ + + This patch removes static class fields from the class fields proposal + in order to follow up on it in that other repository. + +diff --git a/spec.html b/spec.html +index 3f7099c..533daf8 100644 +--- a/spec.html ++++ b/spec.html +@@ -1,7 +1,7 @@ + + + +@@ -109,7 +109,6 @@ emu-example pre { + MethodDefinition[?Yield, ?Await] + `static` MethodDefinition[?Yield, ?Await] + FieldDefinition[?Yield, ?Await] `;` +- `static` FieldDefinition[?Yield, ?Await] `;` + `;` + + MemberExpression[Yield, Await] : +@@ -151,13 +150,6 @@ emu-example pre { +
  • It is a Syntax Error if PrivateBoundNames of |ClassBody| contains any duplicate entries.
  • + + +- ClassElement : `static` FieldDefinition `;` +-
      +-
    • +- It is a Syntax Error if PropName of |FieldDefinition| is `"prototype"` or `"constructor"`. +-
    • +-
    +- + ClassElement : FieldDefinition `;` +
      +
    • +@@ -297,14 +289,9 @@ emu-example pre { +

      Runtime Semantics: ClassElementEvaluation

      +

      With parameters _object_ and _enumerable_.

      + +- ClassElement : `static` FieldDefinition `;` +- +- 1. Return ClassFieldDefinitionEvaluation of |FieldDefinition| with parameter *true* and _object_. +- +- + ClassElement : FieldDefinition `;` + +- 1. Return ClassFieldDefinitionEvaluation of |FieldDefinition| with parameter *false* and _object_. ++ 1. Return ClassFieldDefinitionEvaluation of |FieldDefinition| with parameter _object_. + + + ClassElement : MethodDefinition +@@ -319,7 +306,7 @@ emu-example pre { + +

      Runtime Semantics: ClassFieldDefinitionEvaluation

      + +-

      With parameters _isStatic_ and _homeObject_.

      ++

      With parameter _homeObject_.

      + + + FieldDefinition : ClassElementName Initializer? +@@ -339,7 +326,6 @@ emu-example pre { + 1. Return a List containing Record { + [[Name]]: _fieldName_, + [[Initializer]]: _initializer_, +- [[Static]]: _isStatic_, + [[IsAnonymousFunctionDefinition]]: _isAnonymousFunctionDefinition_ + }. + +@@ -404,20 +390,6 @@ emu-example pre { + TODO: Set the running execution context's PrivateNameEnvironment when calling a function (Issue #40). + + +- +-

      InitializeStaticFields(_F_)

      +- +- +- 1. Assert: Type(_F_) is Object. +- 1. Assert: _F_ is an ECMAScript function object. +- 1. Let _fieldRecords_ be the value of _F_'s [[Fields]] internal slot. +- 1. For each item _fieldRecord_ in order from _fieldRecords_, +- 1. If _fieldRecord_.[[static]] is *true*, then +- 1. Perform ? DefineField(_F_, _fieldRecord_). +- 1. Return. +- +-
      +- + +

      InitializeInstanceFields ( _O_, _constructor_ )

      + +@@ -426,8 +398,7 @@ emu-example pre { + 1. Assert: Assert _constructor_ is an ECMAScript function object. + 1. Let _fieldRecords_ be the value of _constructor_'s [[Fields]] internal slot. + 1. For each item _fieldRecord_ in order from _fieldRecords_, +- 1. If _fieldRecord_.[[static]] is *false*, then +- 1. Perform ? DefineField(_O_, _fieldRecord_). ++ 1. Perform ? DefineField(_O_, _fieldRecord_). + 1. Return. + + Private fields are added to the object one by one, interspersed with evaluation of the initializers, following the construction of the receiver. These semantics allow for a later initializer to refer to a previously private field. +@@ -592,11 +563,6 @@ emu-example pre { + + 1. Return *false*. + +- +- ClassElement : `static` FieldDefinition +- +- 1. Return *true*. +- + +
      + +@@ -673,10 +639,6 @@ emu-example pre { + 1. Set the value of _F_'s [[Fields]] internal slot to _fieldRecords_. + 1. Set the running execution context's LexicalEnvironment to _classScope_. + 1. Set the running execution context's PrivateNameEnvironment to _outerPrivateEnvironment_. +- 1. Let _result_ be InitializeStaticFields(_F_). +- 1. If _result_ is an abrupt completion, then +- 1. Set the running execution context's LexicalEnvironment to _lex_. +- 1. Return Completion(_result_). + 1. Set the running execution context's LexicalEnvironment to _lex_. + 1. Return _F_. +