TC39 meeting, June 1-4 2020


At this meeting we covered a lot of ground. It was the first four day meeting, with each meeting at 5 hours. This meeting did not see any stage 2 proposals advance to stage 3, so in terms of implementation work, we do not have new tasks. However, we do have significant review work. One large proposal, Temporal, will be seeking stage 3 at an upcoming meeting. Decorators also needs to be discussed again.

In terms of exciting proposals for developers, Record and Tuple are continuing steady development, and Do notation was brought back.

The SpiderMonkey team also presented a few things at this meeting.

  • Yulia Startsev presented a new proposal to restrict builtin subclassing.
  • Jason Orendorff also clarified aspects of the Iterator helpers specification, and we came to a satisfactory conclusion there.

There were a couple of high level editorial changes at this meeting. One was around what do implementation defined, implementation dependent, host defined, host dependant mean in the spec, concretely. We now have an answer.

Need Review:

Needs implementation:

  • None

Needs minor change:

Keep an eye on…

Normative Spec Changes


Introducing: Unicode support

  • Notes
  • Slides
  • Proposal Link
  • Summary: We reference the most recent Unicode Specification in ECMA-262, however we always have to update three tables related to regexp. The proposal was to normatively describe the process by which these tables are derived. This was contentious, but the text itself was not.
  • Impact on SM: None,
  • Outcome: It was recommended that the text become non-normative. The reason for this was so that we specify our process, but still have the final call on what is included in the specification.

Proposals Seeking Advancement to Stage 4


String.prototype.replaceAll for Stage 4

  • Notes
  • Slides
  • Proposal Link
  • Summary: Currently there is no way to replace all instances of a substring in a string without use of a global regexp. String.prototype.replace only affects the first occurrence when used with a string argument. This proposal adds a new method to the String prototype - replaceAll. This would give developers a straight-forward way to accomplish a common operation.
  • Impact on SM: None, already implemented,
  • Outcome: Consensus for stage 4

Proposals Seeking Advancement to Stage 3


Function Implementation Hiding for stage 3

  • Notes
  • Slides
  • Proposal Link
  • Summary: Function implementation hiding sought to introduce two new directives, hide source and sensitve. The first was for source code level black boxing, and hiding information from stack traces, while the second was from making certain calls invisible.
  • Impact on SM: None,
  • Outcome: We blocked this proposal unilaterally. The reason for blocking sensitive is that part of it’s motivation is around security, which will not work in a world with spectre – as such it doesn’t make sense to add this from a browsers perspective. We blocked hide source on the basis that it introduces a new directive – something very contentious, for aruably limited benefit. The rational for the proposal has drifted over time, and the potential of this being a performance improvement disappeared, along with other aspects of the proposal. Adding a directive only for the reason of blackboxing doesn’t justify the implementation and re-introducing directives. However this problem should be explored more, from a fresh perspective.

Intl.Segmenter for Stage 3

  • Notes
  • Slides
  • Proposal Link
  • Summary: introduces locale specific sentence segmentation. For example, an English sentence is easy to segment at the character or world level. “Two chickens in a garden” can be split on any space. This doesn’t work for languages that do not use a space or similar as a word boundary. For example the same sentence in Japanese “にわにはにわにわとり” needs specific rules. “にわには” (in the garden), “にわ” (two) and “にわとり” (chicken) are the best word segementation points. Intl.Segmenter provides an API for this. Thank you to Makoto Kato for the clarification.
  • Impact on SM: None, yet.
  • Outcome: Did not advance to stage 3 due to two technicalities: the proposal was posted late and had not been reviewed by all stage 3 reviewers. There was an additional reason that this did not advance. It made changes related to the “exotic internal slot” discussion, an invariant that is not yet accepted by all TC39 members. Discussion on this is ongoing.

Proposals Seeking Advancement to Stage 2


Ergonomic brand checks for private fields for stage 2

  • Notes
  • Proposal Link
  • Summary: Support proper ergonomic brand checks for classes. This proposal aims at improving the integrity of code and ensuring you can trust that an object is what an object says it is. This is a pretty specific detail to how JS works – typeof is unreliable because it can be spoofed. A proper brandcheck should not be spoofable. One example of a proper brand check is Array.is(), this utility allows any JS class to do this. The draw back? It is inconsistent with how the in keyword works. Previously in only worked with strings, and now it will work with private fields. There isn’t room here to describe it fully, but check out the proposal for more info.
  • Impact on SM: We should start looking at implementation,
  • Outcome: Proposal is now stage 2

Do expressions for stage 2

  • Notes
  • Slides
  • Proposal Link
  • One Liner: x = do { y } // same as x = y
  • Summary: Do expressions introduces a way to do complex assignments without using functions. Where you may have previously called out into a function, you could use a do expression as a light weight alternative. One issue that was raised is that this would require users are familiar with the return value of an expression. A simple example is an integer, where 1 will return 1. A return value that might not be so obvious is from an assignment, where x = y will return undefined. There was some contention around this issue.
  • Impact on SM: None.
  • Outcome: The proposal did not advance due to a technicality – the spec text was not available and could not be read before the meeeting.

Intl.NumberFormat V3 for stage 2

  • Notes
  • Slides
  • Proposal Link
  • Summary: Introduces a batch of new features for numbereFormat including formatRange, a grouping enum for how a number should be grouped (ie 1000 or 1,000), new rounding / precision options, string interpretation as decimals, and rounding modes (half up, half down, etc)
  • Impact on SM: Will require review,
  • Outcome: Consensus for stage 2.

Intl.DurationFormat for Stage 2

  • Notes
  • Slides
  • Proposal Link
  • Summary: Introduces durationFormat, a way to format time. For example 10000 seconds is also 2 hours, 46 minutes, and 40 seconds. This is useful for applications that need to display durations in different ways.
  • Impact on SM: Will require review,
  • Outcome: Consensus for stage 2.

Module Attributes for Stage 2

  • Notes
  • Slides
  • Proposal Link
  • One line Summary: import json from “./foo.json” if { type: “json” };
  • Summary: Introduce the ability to import file types other than JS, such as import x from "y" if {type: ...}. This would allow importing JSON and other file types.
  • Outcome: Consensus for stage 2.

Proposals Seeking Advancement to Stage 1


Symbols as WeakMap keys for Stage 1

  • Notes
  • Slides
  • Proposal Link
  • Summary: From the proposal: This proposal aims to solve a problem space introduced by the Record & Tuple Proposal; how can we reference and access non-primitive values in a primitive? We see Symbols, dereferenced through WeakMaps, as the most reasonable way forward to reference Objects from Records and Tuples, given all the constraints raised in the discussion so far.
  • Outcome: Consensus on stage 1

Deep path properties

  • Notes
  • Slides
  • Proposal Link
  • One Liner: const rec = #{ a.b.c: 123 }; // modify deeply nested properties in records
  • Summary: Record literals sometimes include deeply nested structures, but the syntax for describing them (either as a fresh value, or based on a previous value via spread syntax) can be cumbersome and/or verbose. Deep path properties for Record literals provides a solution to this problem, by introducing a new syntax for describing deeply nested structures in a more succinct and readable way.
  • Outcome: Consensus on stage 1

Restrict subclassing support for built-in methods Stage 1

  • Notes
  • Slides
  • Proposal Link
  • Summary: This proposal seeks to restrict subclassing of built-in methods. The goal here is to remove something from the spec in a backwards compliant way, and at the moment this appears to be possible. The discussion centers around @@species and other aspects of subclassing built-in methods. At present, engines have to implement built-in methods twice: once in a spec compliant way, and once in a fast way. Google’s project zero also found a number of security issues with subclassing, and we also had a significant security issue due to this feature. It would also make the work of spec authors who interact with TC39 easier, and less error prone. The feature so far does not seem to have wide adoption, in spite of being in the wild for a long time.
  • Impact on SM: I (@codehag) am one of the champions, and have research work to do,
  • Outcome: Consensus for stage 1

Async Context

  • Notes
  • Slides
  • Proposal Link
  • Summary: The goal of the proposal is to provide a mechanism to ergonomically track async contexts in JavaScript. There are multiple implementations in different platforms and frameworks like async_hooks in Node.js and zones.js in Angular that provides async contexts and async tasks tracking. These modules works well on their own platform/impl, however they are not in quite same per API shapes compared with each other. Library owners might have to adopt both two, or more, to keep a persistent async context across async tasks execution.
  • Outcome: Consensus was not reached. The proposal was blocked for its use of dynamic scoping, and it covered similar ground as promise cancellation. The problem space is worthwhile, but needs a different solution.

Intl Enumeration API for Stage 1

  • Notes
  • Slides
  • Proposal Link
  • Summary: Introduces helper methods that list previously defined options in the spec.
  • Outcome: Consensus for stage 1

Smart Unit Preferences in Intl.NumberFormat for Stage 1

  • Notes
  • Slides
  • Proposal Link
  • Summary: Represent measurements in a localized way. For example km or miles.
  • Outcome: Consensus for stage 1

Generic Comparison

  • Notes
  • Slides
  • Proposal Link
  • Summary: Introduces a generic comparison operator <=> that returns either -1, 0 or 1. The initial goal was comparing arrays, but they expanded it to also include comparing dates such as today <=> tomorrow.
  • Outcome: Consensus was not reached for the spaceship operator <=>. However a method Array.prototype.equals had support, and this has reached stage 1.

.item() for Stage 1

  • Notes
  • Slides
  • Proposal Link
  • Summary: Introduces relative indexing to JS, similar to pythons list[-1] (returns the last element relative to the end of the array) which is not possible in JS. Has similarities to Array.prototye.last().
  • Outcome: Consensus for stage 1

Updates on Ongoing work


Promise.{all,allSettled,race} should check “resolve” before iterating

  • Notes
  • Proposal Link
  • Summary: Detail - This change makes it possible to implement Promise.all, .allSettled, and .race in ECMAScript using a for of loop.
  • Impact on SM: We need to implement the change,
  • Outcome: What is the outcome?

Logical assignment status update

  • Notes
  • Issue
  • Proposal Link
  • One-liner: a = null; a ??= b // a == b
  • Summary: Logical assignment hit an interesting snag around how people might model this when thinking about the feature. Should a ??= b desugar down to a ?? (a = b) or a = a ?? b ? This question is important in the case of function. For the latter case foo ??= function () {}, the function will not be assigned a name. In the former, th ename will be foo.
  • Impact on SM: We needed to modify our implementation,
  • Outcome: Committee decided that, given that Logical assignment has some differences with compound assignment, and that many would expect it to result in a named function, that a named function is a good way to go.

Iterator Helpers

  • Notes
  • Slides
  • Proposal Link
  • One-liner: (function* foo() { yield 1})().map(x=>x*x).next() // 2
  • Summary: The Iterator Helpers proposal brings many of the helper methods of Array objects to iterator objects. For example, Array.prototype.map might be used in the following way [1,1,1].map(x=>x*x). This would allow you to do the same with iterators. For example function* foo() { yield 1; } could produce an object const x = foo(). You would be able to map over it like so const y = x.map(x=>x*x). Calling y.next() would return the mapped value 2. This update was around the specific spec mechanism around how to do that.
  • Impact on SM: We raised this issue so we could implement it (Thanks Adam!)
  • Outcome: The solution that was adopted is described here

Record & Tuple (status update)

  • Notes
  • Slides
  • Proposal Link
  • One-liner: Immutable, but standardized
  • Summary: Records and tuples introduce immutable data collections of primitives to JS. There are some ambiguities to clarify around equality, namely positive and negative zero in js. How symbols should be treated was also discussed. Destructuring was discussed and omitted for the time being. The proposal will seek Stage 2 in July
  • Impact on SM: None
  • Outcome: Discussion heavily centered around equality and user expectations. It was not fully resolved.

AggregateError errors update

  • Notes
  • Slides
  • Proposal Link
  • Summary: This change is related to Promise.any and errors. Previously, the errors were stored on an own property as a normal array. The issue initially sought to change this to a getter that constructs the array from the contents of an inner slots. The discussion here turned around, and the change was reversed.
  • Impact on SM: Required a change,
  • Outcome: Change reversed

AggregateError constructor update

  • Notes
  • Slides
  • Proposal Link
  • Summary: This change is related to Promise.any and errors. The spec text for AggregateError ctor and Error ctor was intended to do the same thing. This PR unified them in order to make this clearer.
  • Impact on SM: None, spec change,
  • Outcome: Accepted

Temporal Update

  • Notes
  • Slides
  • Proposal Link
  • Summary: Temporal introduces a new global that seeks to address a number of pain points in the Date object by introducing a new top level namespace Temporal. They have released a polyfill for feedback, and will be seeking stage 3 in the coming months.
  • Impact on SM: We need to start reviewing Temporal, as it will be a large change,
  • Outcome: Implementers will get a heads up before Stage 3 Request.

Decorators update

  • Notes
  • Slides
  • Proposal Link
  • Summary: Introduces a set of builtin decorators. These builtin decorators can be composed to make custom ones. This proposal addresses concerns from implementers around the previous iteration of decorators.
  • Impact on SM: Need to review again – Will be seeing stage 3 soon,

Arbitrary Module Namespace Names

  • Notes
  • Slides
  • Summary: allow forwarding non-identifier names, such as import {'nice to meet you' as _} from 'foo';. Not seeking advancement yet.

Built in modules Update Towards Stage 2

  • Notes
  • Slides
  • Proposal Link
  • Summary: Proposal for adding a mechanism for enabling a more extensive standard library in JavaScript via a collection of built in modules. With this infrastructure in place it will be possible to start iterating on standard library features as additional modules.
  • Impact on SM: We should review the current status, there is some concern around how this interacts with the global object, and what this will mean for interop.

Realms, Stage 2 update

  • Notes
  • Slides
  • Proposal Link
  • Summary: This update covers how Realms and compartments have changed in relation to eachother to enable Virtualization. Realms exposes the ability to create a new global without the use of an iframe, will all of the intrinsics (think Array, etc) unique to that realm. Compartments, on the other hand, create a global that shares it’s intrinsics with it’s parent. The goal is the ability to do virtualization in a syncronous way. There is some concern about this from browsers, as this syncronicity goes against design goals chrome expressed in Whatwg.
  • Outcome: The proposal will go for a TAG review.