1 of 14

Update: Restricting subclassing support in built-in methods – Data

Yulia Startsev & Matthew Gaudet, Mozilla

2 of 14

Reminder:

This proposal is about trying to remove some of the forms of subclassing of built-in types in the JS language

3 of 14

Type I: minimal support (Not Proposed for Removal)

4 of 14

Type II: subclass instance creation in built-in methods

5 of 14

Type III: customizable subclass instance creation in built-in methods

6 of 14

Type IV: delegation to property lookups in built-in methods

7 of 14

Proposal:

“We propose to remove support for Type II, Type III, and Type IV subclassing, and only keep Type I.”

Hypothesis:

  • These subclassing types of built-in methods are both rare and harmful, and thus the language would be improved if we removed them. Furthermore, removal could be web compatible.

8 of 14

Experiment: Counting actual subclassing on the web

Bug 1896505 - Add use-counter telemetry for subclassing types

Annotate our code to report when a document actually performs subclassing.

  • Bucket by subclassing enabled builtin.

9 of 14

  • Compatibility risk of unshipping @@species is real. Chrome counters estimate 2% of pages modify .constructor or @@species on Array, RegExp, and Promise
    • Both an undercount (eg. does not count modifying .constructor) and an overcount (shims)
  • Manual inspection revealed an outdated core-js shim unconditionally installing a function() { return this; } as the @@species getter.
    • Everything that we have found so far has been core-js.
    • We are looking for more ideas of how to test this.
  • Out of 1k sampled sites out of 400k, all 26 traps were from coreJS. Core-js is used by babel that would not be affected by removing subclassing.

10 of 14

Our Results:

We Are Surprised by these Results.

Submission Date

2024-08-22

Array Type II

6.9211%

Array Type III

16.5238%

ArrayBuffer Type III

0.0000%

SharedArrayBuffer Type III

0.0000%

TypedArray Type II

0.0001%

TypedArray Type III

0.2482%

RegExp Type III

11.2277%

RegExp Type IV

16.0279%

Promise Type II

21.3367%

Promise Type III

17.2540%

11 of 14

Concurrence with previous results:

  • Hand inspection of subclassing shows much of the reporting is core-js doing feature detection.
    • While we considered attempting to separate out core-js from telemetry, we decided to present at plenary instead.
    • Given that we’re talking about millions of pages loaded per day, it seems that even if we could eliminate core-js, we expect that it likely would still be problematic on real web sites.

12 of 14

New Results:

  • Unlike previous results we instrumented things, so we can concretely conclude that these paths in the spec are being hit.
    • There’s some flex on the interpretation – e.g. cross global operations
    • But we also are not counting (most) silly cases like static get [Symbol.species]() { return this; } that have the same behaviour as not-having overridden species.
  • We also instrumented which Builtins are being affected: Can show vastly different rates.
    • Promise, Array & RegExp are subclassed surprisingly frequently.
    • Nearly zero subclassing of ArrayBuffers (rate: 1 per 5 million page loads for Array Buffer Type III, below 1 per billion page loads for Shared Array Buffer Type III).
    • Low subclassing of TypedArrays

13 of 14

Possible Forward Futures

  • Abandon the proposal entirely.
  • Exclusively remove subclassing support from ArrayBuffers – Based on our telemetry we believe there’s a high likelihood that this is web compatible.

We think that it is worthwhile to attempt to remove ArrayBuffer support. Unused functionality nearby sensitive code like ABs seems like asking for trouble.

We should still adopt a rationale that future built-in subclassing beyond Type I should be strongly discouraged.

14 of 14

Careful Design

This is yet more evidence that design of JS has to be considered carefully: Unshipping errors ranges from incredibly hard to outright impossible.