Skip to content

Instantly share code, notes, and snippets.

@hax
Created January 18, 2022 12:52
Show Gist options
  • Save hax/86a0817320985d046bebfb392bf9a49b to your computer and use it in GitHub Desktop.
Save hax/86a0817320985d046bebfb392bf9a49b to your computer and use it in GitHub Desktop.
Experimental API

NOTE: This proposal was mainly written 2 years ago, many examples may already outdated, but the whole idea should still apply.

Experimental API

Motivation

I have a dream, that the new JS APIs could be developed like good open source libraries, have reference implementation maintained by champions and volunteers in the whole lifecycle from stage 1 to stage 4, clearly marked as "experimental feature" not "polyfill", follow semver, and available in all platforms (all engines, browsers and node.js) automatically, accept issues and PRs in official github repo, can have branches to test new ideas, allow forks and healthy competition...

Problems

  • How to estimate the developer experiences without real world deployment?
  • How to test and compare alternative designs?

Example: tc39/proposal-upsert#6

It's depend on champion's personal willingness, knowledge, judgement and time resource to investigating all the possibilities, and choose one (though theoretically champion can provide several options, it's not common in practice, increase the burdern significantly) but may not satisfy developers: tc39/proposal-upsert#14

Example: tc39/proposal-string-replaceall#9

In the early stage we have many options, but we are forced to choose one to advance. It's hard to affirm which one is better in such early stage without real world test, it all depends on the wisdom and taste of delegates in the room who was available in that meeting, in some degree it also depends on the speechcraft, english proficiency, even personality (persistence or submissiveness).

Example: Temporal

Very good example! Though still have issues on spec/polyfill sync, and not all developers understand the very unstable status of the polyfill. (should avoid use word "polyfill", should make it clear it's a "reference implementation of a experimental feature")

  • How to test APIs in OO style instead of forcing FP style?

Example: tc39/proposal-array-filtering#5 (comment)

Reviving the good part of bind operator may be a promising solution.

  • How to avoid stage 3 trap?

In most cases, we only have broad real user feedbacks until engines land the feature without flag, but it also make us lose the chance to change anything.

There is also a serious problem: the real threshold is not stage 3, but the deadline of Chrome/Node landing the feature without flag. All other implementors has to follow because of the pressure from the supporters of the feature. This is harmful for standard body governance and the whole ecosystem.

Examples:

  • String.prototype.trimLeft/trimRight (can never drop the old API names)
  • String.prototype.matchAll/replaceAll (we fixed matchAll in stage 4 until we found related issue in replaceAll in stage 3, but not everytime we have the luck and can got consensus --- espeically only implementor agree to put resource to investigate, we can fix things, this give some implementors too big power in the process though it's not their fault)
  • globalThis (achieved stage 3 then changed api name, didn't leave any time for community to engage, and implementors didn't want to put any new resource on possible web compatibility check, make community feedback meaningless, causing huge frustrating)

Possible Solution

Provide a standard mechanism for API designers, implementors, and developers to experiment the new APIs, allow us to collect the feedbacks from real world usage. Syntax, unpolyfillable APIs may not use this mechanism, but some part of it could be splitted and use this mechanism. And it allow the committee put more resource on syntax/unpolyfillable parts instead of wasting time on naming argument like Array.p.select/reject (not means it's not important, but the naming issues is very bikeshed and could be discussed later and better after we got some feedback from developers).

const api = Experimental.tc39('feature@version') // major version is mandatory

Design

  • New API proposals are suggested to provide a reference implementation written in JS after entering stage 1 (allow developers start experiment new APIs from very early stage) and have a latest major version stable at least one year before entering stage 3 (make sure we get enough developer feedbacks)
  • Follow semver, any breaking change should release a new version
  • Devtools could provoide info (you are using an Experimental API) or warning (use a obseleted versions)
  • The experimental features should not modify anything on global namespace and prototype objects before stage 3
  • Leveage reformed bind op proposal to test new APIs on prototype
  • When arrive stage 3, we can release a new version which modify the global things and prototypes
  • Serve the reference implementations of experimental features on some place like https://experimental.tc39.es/feature@version
  • Also release the reference implementations of experimental features via npm @tc39/experimental-* scope packages
  • Browsers could optimize the loading performance of the reference implementations of experimental features, or ship with specific versions which avoid network trips at all
  • Node.js distribution can ship with some @tc3/experimental-* packages by default
  • Browsers/Node.js etc. could collect usage data of Experimental APIs
  • The committee could track and analysis usage data from CDN/npm/browsers/Node.js etc.
  • Implementors could start implement a specific version of the feature in any time as long as the version of the reference implementations and tests of experimental features were available, they can use native implementation override the corresponding version of JS implementation, and free to remove such versions at anytime (so fallback to JS implementation again)
  • If there was any issue in stage 3 which need breaking change of the API, we rollback the proposal to stage 2, let community test at least anther half year
  • When achieve stage 4, we mark the implementation of experimental feature obseleted because it's not experimental any more!(may only release security fix, hope we will never face such issue)
  • Keep all versions available forever (except vulnerable versions) just like normal packages, allow developers depend on specific version of experiment features if they really want, it won't worse than relying on any old versions of any unmaintained packages (like jQuery 1.x)

TLDR: Develop new APIs just as good open source libraries!

Usage

// test.js
const {DateTime} = Experimental.tc39('temporal@2')
const ::{select} = Experimental.tc39('array-select-reject@0.1')

const schedule = [
	new DateTime(2020, 1, 28, 0, 0),
	new DateTime(2019, 12, 3, 0, 0),
	new DateTime(2019, 10, 1, 0, 0),
]
const schedule2020 = schedule::select(dt => dt.year === 2020)

Web

<script src="experimental:tc39/temporal@2"></script>
<script src="experimental:tc39/array-select-reject@0.1"></script>
<script src="test.js"></script>

Node.js

npm install @tc39/experimental-temporal@2.1
npm install @tc39/experimental-array-select-reject@1.0.1
node test.js
  • Auto require '@tc39/experimental-foo' package with version checking

Can be leverage by other API designers in different standard bodies or platforms

Experimental.tc53('feature@version')
Experimental.w3c('feature@version')
Experimental.node('feature@version')

Futher consideration

  • Engines may expose some internal APIs which only available to https://experimental.tc39.es/ origin or @tc39/experimental-* packages

Alternative names for "Experimental"

  • Incubator
  • Unstable

Related discussion

Prior Art

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment