• Stars
    star
    1,002
  • Rank 43,952 (Top 0.9 %)
  • Language
    HTML
  • License
    BSD 3-Clause "New...
  • Created almost 7 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Proposal to add partial application to ECMAScript

Partial Application Syntax for ECMAScript

This proposal introduces syntax for a new calling convention (using ~()) to allow you to partially apply an argument list to a call or new expression through the combination of applied arguments (actual values) and placeholder arguments (unbound arguments that become parameters in the resulting partially applied function).

Status

Stage: 1
Champion: Ron Buckton (@rbuckton)

For more information see the TC39 proposal process.

Authors

  • Ron Buckton (@rbuckton)

Proposal

Partial function application allows you to fix a number of arguments to a function call, returning a new function. Partial application is supported after a fashion in ECMAScript today through the use of either Function.prototype.bind or arrow functions:

function add(x, y) { return x + y; }

// Function.prototype.bind
const addOne = add.bind(null, 1);
addOne(2); // 3

// arrow functions
const addTen = x => add(x, 10);
addTen(2); // 12

However, there are several of limitations with these approaches:

  • Function.prototype.bind can only fix the leading arguments of a function.
  • Function.prototype.bind requires you explicitly specify the this receiver.
  • Arrow functions lazily re-evaluate their bodies, which can introduce unintended side-effects.

To resolve these concerns, we propose the introduction of the following new language features:

  • A new calling convention, ~(), to indicate a partial application of a call or new expression which results in a partially applied function.
  • Using the ? token to act as a placeholder argument for any non-fixed argument in a partial application.
  • Using the ? token followed by a decimal integer literal (i.e., ?0) to act as an ordinal placeholder argument for non-fixed arguments bound to a specific ordinal parameter in the resulting partially applied function.
  • Using the ... token to act as a rest placeholder argument for any excess arguments.
const add = (x, y) => x + y;
const identity = x => x;

// apply from the left:
const addOne = add~(1, ?);
addOne(2); // 3

// apply from the right:
const addTen = add~(?, 10);
addTen(2); // 12

// accept a fixed argument list:
const numbers = ["1", "2", "3"].map(parseInt~(?, 10)); // [1, 2, 3]

// specify ordinal placeholder arguments:
const indices = [1, 2, 3].map(identity~(?1)); // [0, 1, 2]

// bind `console` as receiver and accepts exactly one argument:
[1, 2, 3].forEach(console.log~(?));
// prints:
// 1
// 2
// 3

// emulate n-ary arguments like Function.prototype.bind:
const logger = console.log~("[service]", ...);
logger("foo", "bar"); // prints: [service] foo bar

Syntax

The ~() Partial Application Calling Convention

A partially applied call uses a separate calling convention than a normal call. Instead of using () to call or construct a value, you initiate a partial call using ~(). A partially applied call without a placeholder argument essentially fixes any provided arguments into a new function. If the expression being invoked produces a Reference, the this binding of the Reference is preserved. Excess arguments supplied to the resulting function are ignored by default (for more information, see Fixed Arity and Variable Arity later on in this document).

const sayNothing = console.log~();
const sayHi = console.log~("Hello!");

sayNothing();       // prints:
sayNothing("Shhh"); // prints:

sayHi();            // prints: Hello!

const bob = {
  name: "Bob",
  introduce() {
    console.log(`Hello, my name is ${this.name}.`);
  }
};

const introduceBob = bob.introduce~();
introduceBob();     // prints: Hello, my name is Bob.

This would not be the first new calling convention in ECMAScript, which also has tagged templates (i.e., tag`text${expr}`) and nullish function evaluation (i.e., f?.()).

The ? Placeholder Argument

The ? Placeholder Argument can be supplied one or more times at the top level of the argument list of a call or new expression (e.g. f~(?) or o.f~(?)). ? is not an expression, rather it is a syntactic element that indicates special behavior (much like how `...` AssignmentExpression indicates spread, yet is itself not an expression).

// valid
f~(x, ?)          // partial application from left
f~(?, x)          // partial application from right
f~(?, x, ?)       // partial application for any arg
o.f~(x, ?)        // partial application from left
o.f~(?, x)        // partial application from right
o.f~(?, x, ?)     // partial application for any arg
super.f~(?)       // partial application allowed for call on |SuperProperty|
new C~(?)         // partial application of constructor

// invalid
f~(x + ?)         // `?` not in top-level Arguments of call
x + ?             // `?` not in top-level Arguments of call
?.f~()            // `?` not in top-level Arguments of call
super~(?)         // `?` not supported in |SuperCall|
import~(?)        // `?` not supported in |ImportCall|

The ?0 (?1, ?2, etc.) Ordinal Placeholder Argument

The ? token can be followed by a decimal integer value ≥ 0 indicating a fixed ordinal position (i.e., ?0) denoting an Ordinal Placeholder Argument. Ordinal placeholder arguments are especially useful for adapting existing functions to be used as callbacks to other functions expect arguments in a different order:

const printAB = (a, b) => console.log(`${a}, ${b}`);
const acceptBA = (cb) => cb("b", "a");
acceptBA(printAB~(?1, ?0));                // prints: a, b

In addition, ordinal placeholder arguments can be repeated multiple times within a partial application, allowing repeated references to the same argument value:

const add = (x, y) => x + y;
const dup = add(?0, ?0);
console.log(dup(3));                       // prints: 6

Non-ordinal placeholder arguments are implicitly ordered sequentially from left to right. This means that an expression like f~(?, ?) is essentially equivalent to f~(?0, ?1). If a partial application contains a mix of ordinal placeholder arguments and non-ordinal placeholder arguments, ordinal placeholder arguments do not affect the implicit order assigned to non-ordinal placeholder arguments:

const printABC = (a = "arg0", b = "arg1", c = "arg2") => console.log(`${a}, ${b}, ${c}`);
printABC(1, 2, 3);                         // prints: 1, 2, 3
printABC();                                // prints: arg0, arg1, arg2

const printCAA = printABC~(?2, ?, ?0);     // equivalent to: printABC~(?2, ?0, ?0)
printCAA(1, 2, 3);                         // prints: 3, 1, 1
printCAA(1, 2);                            // prints: arg0, 1, 1

const printCxx = printABC~(?2);
printCxx(1, 2, 3);                         // prints: 3, arg1, arg2

By having ordinal placeholder arguments independent of the ordering for non-ordinal placeholder arguments, we avoid refactoring hazards due to the insertion a new ordinal placeholder into an existing partial application.

inserting an ordinal placeholder as the first argument:

-  const g = f~(?, ?, ?);                   // equivalent to: f~(?0, ?1, ?2)
+  const g = f~(?2, ?, ?, ?);               // equivalent to: f~(?2, ?0, ?1, ?2)

inserting an ordinal placeholder between other placeholders:

-  const g = f~(?, ?, ?);                   // equivalent to: f~(?0, ?1, ?2)
+  const g = f~(?, ?, ?0, ?);               // equivalent to: f~(?0, ?1, ?0, ?2)

Fixed Arity

By default, partial application uses a fixed argument list: Normal arguments are evaluated and bound to their respective argument position, and placeholder arguments (?) and ordinal-placeholder arguments (?0, etc.) are bound to specific argument positions in the resulting partially applied function. As a result, excess arguments passed to a partially applied function have no specific position in which they should be inserted. While this behavior differs from f.bind(), a fixed argument list allows us to avoid unintentionally accepting excess arguments:

// (a)
[1, 2, 3].forEach(console.log.bind(console, "element:"));
// prints:
// element: 1 0 1,2,3
// element: 2 1 1,2,3
// element: 3 2 1,2,3

// (b)
[1, 2, 3].forEach(x => console.log("element:", x));
// prints:
// element: 1
// element: 2
// element: 3

// (c)
[1, 2, 3].forEach(console.log~("element:", ?));
// prints:
// element: 1
// element: 2
// element: 3

In the example above, (a) prints extraneous information due to the fact that forEach not only passes the value of each element as an argument, but also the index of the element and the array in which the element is contained.

In the case of (b), the arrow function has a fixed arity. No matter how many excess arguments are passed to the callback, only the x parameter is forwarded onto the call.

The intention of partial application is to emulate a normal call like console.log("element:", 1), where evaluation of the "applied" portions occurs eagerly with only the placeholder arguments being "unapplied". This means that excess arguments have no place to go as part of evaluation. As a result, (c) behaves similar to (b) in that only a single argument is accepted by the partial function application and passed through to console.log.

Variable Arity: Pass Through Remaining Arguments using ...

However, sometimes you may need the variable arity provided by Function.prototype.bind. To support this, partial application includes a ... rest placeholder argument with a specific meaning: Take the rest of the arguments supplied to the partial function and spread them into this position:

const writeLog = (header, ...args) => console.log(header, ...args);
const writeAppLog = writeLog~("[app]", ...);
writeAppLog("Hello", "World!");
// prints:
// [app] Hello World!

const writeAppLogWithBreak = writeAppLog~(..., "\n---");
writeAppLogWithBreak("End of section");
// prints:
// [app] End of section
// ---

A partial application may only have a single ... rest placeholder argument in its argument list, though it may spread in other values using ...expr as you might in a normal call:

const arr = [1, 2, 3];

// The following would be a SyntaxError as the `...` placeholder may only appear once:
// const g = console.log~(?, ..., ...);

// However, a normal spread is perfectly valid. Below, `...arr` will be evaluated immediately
// and spread into the list of applied arguments:
const g = console.log~(?, ...arr, ...);
g("a", "b", "c");                           // prints: a, 1, 2, 3, b, c

Semantics

A call or new expression that uses the ~() calling convention results in a partially applied function. This result is a new function with a parameter for each placeholder argument (i.e., ?, ?0, etc.) in the argument list. If the partial application contains a ... rest placeholder argument, a rest parameter is added as the final parameter of the resulting partially applied function. Any non-placeholder arguments in the argument list becomes fixed in their positions. This is illustrated by the following syntactic conversion:

const g = f~(?, 1, ?);

is roughly identical in its behavior to:

const g = (() => {
  // applied values
  const _callee = f;
  const _applied0 = 1;

  // partially applied function
  return function (_0, _1) { return _callee(_0, _applied0, _1); };
})();

In addition to fixing the callee and any applied arguments, we also fix the the this receiver in the resulting partially applied function. As such, o.f~(?) will maintain o as the this receiver when calling o.f. This can be illustrated by the following syntactic conversion:

const g = o.f~(?, 1);

is roughly identical in its behavior to:

const g = (() => {
  // applied values
  const _receiver_ = o;
  const _callee = _receiver_.f;
  const _applied0 = 1;

  // partially applied function
  return function (_0) { return _callee.call(_receiver_, _0, _applied0); };
})();

The following is a list of additional semantic rules:

  • Given f~(), the expression f is evaluated immediately, returning a partially applied function that always calls the value of f with no parameters.
  • Given f~(?), the expression f is evaluated immediately, returning a partially applied function with a single parameter that always calls the value of f with that parameter as its sole argument.
  • Given f~(?, x), the non-placeholder argument x is evaluated immediately and fixed in its position.
  • Given f~(?), excess arguments supplied to the partially applied function result are ignored.
  • Given f~(?, ?) the partially applied function result will have a parameter for each placeholder token that is supplied in that token's position in the argument list.
  • Given f~(this, ?), the this in the argument list is the lexical this.
  • Given f~(?), the this receiver of the function f is fixed as undefined in the partially applied function result.
  • Given f~(?), the length of the partially applied function result is equal to the number of ? placeholder tokens in the argument list.
  • Given f~(?), the name of the partially applied function result is f.name.
  • Given o.f~(?), the references to o and o.f are evaluated immediately.
  • Given o.f~(?), the this receiver of the function o.f is fixed as o in the partially applied function result.
  • Given new C~(), the result is a function that returns a new instance of C.
    • NOTE: This is not easily achievable with .bind() today (if at all).
  • Given const g = new C~(), g.name is "bound C".
  • Given const g = new C~(), g.length is 0 (based on length derived from placeholder arguments).
  • Given const g = new C~(), Object.getPrototypeOf(g) is C.
  • Given new (f~()), the partial application of f returns a new function that can be constructed via new, similar to new (f.bind(null)).
  • Given f?.~() (a partially applied, optional call), if f is null or undefined, the result is undefined. Otherwise, the result is the partial application of f~().
  • Given o?.f~() (a partially applied call in an optional chain), if o is null or undefined, the result is undefined. Otherwise, the result is the partial application of o.f~().

Parsing

While this proposal leverages the existing ? token used in conditional expressions, it does not introduce parsing ambiguity as the ? placeholder token can only be used in an argument list and cannot have an expression immediately preceding it (e.g. f~(a? is definitely a conditional while f~(? is definitely a placeholder).

Grammar

MemberExpression[Yield, Await] :
  ...
  `new` MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await, ~Partial]

CallExpression[Yield, Await] :
  CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await, +Partial]

CoverCallExpressionAndAsyncArrowHead[Yield, Await]:
  MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await, +Partial]

CallMemberExpression[Yield, Await] :
  MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await, +Partial]

SuperCall[Yield, Await] :
  `super` Arguments[?Yield, ?Await, ~Partial]

OptionalChain[Yield, Await] :
  `?.` Arguments[?Yield, ?Await, +Partial]
  ...
  OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await, +Partial]
  ...

Arguments[Yield, Await, Partial] :
  `(` ArgumentList[?Yield, ?Await, ~Partial] `)`
  `(` ArgumentList[?Yield, ?Await, ~Partial], `,` `)`
  [+Partial] [no LineTerminator here] `~` `(` ArgumentList[?Yield, ?Await, +Partial] `)`
  [+Partial] [no LineTerminator here] `~` `(` ArgumentList[?Yield, ?Await, +Partial] `,` `)`

ArgumentList[Yield, Await, Partial] :
  AssignmentExpression[+In, ?Yield, ?Await]
  `...` AssignmentExpression[+In, ?Yield, ?Await]
  ArgumentList[?Yield, ?Await, ?Partial] `,` AssignmentExpression[+In, ?Yield, ?Await]
  ArgumentList[?Yield, ?Await, ?Partial] `,` `...` AssignmentExpression[+In, ?Yield, ?Await]
  [+Partial] `?` DecimalIntegerLiteral?
  [+Partial] `...`
  [+Partial] ArgumentList[?Yield, ?Await, ?Partial] `,` `?` DecimalIntegerLiteral?
  [+Partial] ArgumentList[?Yield, ?Await, ?Partial] `,` `...`

NOTE: It is a SyntaxError for a partial call to have more than one ... placeholder.

Examples

Logging with Timestamps

const log = console.log~({ toString() { return `[${new Date().toISOString()}]` } }, ?);
log("test"); // [2018-07-17T23:25:36.984Z] test

Event Handlers

button.addEventListener("click", this.onClick~(?));

Bound methods

class Collator {
  constructor() {
    this.compare = this.compare~(?, ?);
  }
  compare(a, b) { ... }
}

Passing state through callbacks

// doWork expects a callback of `(err, value) => void`
function doWork(callback) { ... }
function onWorkCompleted(err, value, state) { ... }
doWork(onWorkCompleted~(?, ?, { key: "value" }));

Uncurry this

const slice = Array.prototype.slice.call~(?, ?, ?);
slice({ 0: "a", 1: "b", length: 2 }, 1, 2); // ["b"]

You can also find a number of desugaring examples in EXAMPLES.md.

Relationships to Other Proposals/Language Features

Partial Application and Pipeline

The Pipeline Proposal recently advanced to Stage 2 using the Hack-style for pipelines. While partial application was intended to dovetail with F#-style pipelines, this recent change does not diminish the value of partial application. In fact, the move to Hack-style mitigates the requirement that partial application not have a prefix token, which was a blocking concern from some members of TC39. That said, there is still a place for partial application in conjunction with pipeline:

const add = (x, y) => x + y;
const greaterThan = (x, y) => x > y;

// using Hack-style pipes
elements
  |> map(^, add~(?, 1))
  |> filter(^, greaterThan~(?, 5));

This creates a visual distinction between the topic variable in a Hack-style pipe (^ currently, although that has not been finalized), a partial call (~()), and a placeholder argument (?) that should aid in readability and improve developer intuition about their code will evaluate.

Partial Application and Optional Chaining

Partial Application is supported within an OptionalChain, per the Semantics and Grammar sections, above. As partial application is tied to Arguments, the ~( calling convention would follow ?. in an optional call:

const maybeAddOne = add?.~(?, 1); // undefined | Function
const maybeLog = console?.log~(?); // undefined | Function

Per the semantics of OptionalChain, in both of the examples above the ?. token short-circuits evaluation of the rest of the chain. As a result, if the callee is nullish then the result of both expressions would be undefined. If the callee is not nullish, then the result would be the partial application of the callee.

Open Questions/Concerns

Choosing a different token than ?

There have been suggestions to consider another token aside from ?, given that optional chaining may be using ?. and nullish coalesce may be using ??. It is our opinion that such a token change is unnecessary, as ? may only be used on its own in an argument list and may not be combined with these operators (e.g. f~(??.a ?? c) is not legal). The ? token's visual meaning best aligns with this proposal, and its fairly easy to write similarly complex expressions today using existing tokens (e.g. f(+i+++j-i---j) or f([[][]][[]])). A valid, clean example of both partial application, optional chaining, and nullish coalesce is not actually difficult to read in most cases: f~(?, a?.b ?? c).

Definitions

  • Partial Application — A call or new expression with zero or more placeholder arguments, where applied expressions are immediately evaluated and fixed in their respective positions in the invocation.
    A partial application is denoted by an argument list surrounded by ~()
    Example: f~()
  • Partially Applied Function — A function that is the result of a partial application.
  • Applied Expressions — The callee, receiver, and any non-placeholder arguments of a partial application.
    Also: applied.
    Antonyms: unapplied.
  • Callee — The value of the function or method to be invoked (for a call) or instantiated (for new expressions).
  • Receiver — If the Callee is a method invocation, the receiver is the object that will be passed to the call as its this binding.
  • Fix — Eagerly evaluate an expression and store its position within a partially application.
    Also: fixed, fixing.
  • Non-Placeholder Argument — An Applied Expression that takes up an entire argument position.
  • Placeholder Argument — An argument that is not yet applied in a partial application. A placeholder argument results in one or more parameter bindings in a resulting partially applied function.
  • Non-Ordinal Placeholder Argument — A placeholder argument representing a single unapplied argument. Non-ordinal placeholder arguments are implicitly ordered sequentially from left to right.
    A non-ordinal placeholder argument is denoted by a ? token that takes up an entire an argument position.
    Example: f~(?)
  • Ordinal Placeholder Argument — A placeholder argument representing a single unapplied argument with a specified ordinal position in the parameter list of the resulting partially applied function.
    An ordinal placeholder argument is denoted by a ? token followed by an unsigned integer indicating the ordinal position of the resulting parameter.
    Example: f~(?1, ?0)
  • Rest Placeholder Argument — A placeholder argument representing any excess arguments passed to the resulting partially applied function.
    A rest placeholder argument is denoted by a ... token that takes up an entire argument position.
    Example: f~(...)

Resources

TODO

The following is a high-level list of tasks to progress through each stage of the TC39 proposal process:

Stage 1 Entrance Criteria

  • Identified a "champion" who will advance the addition.
  • Prose outlining the problem or need and the general shape of a solution.
  • Illustrative examples of usage.
  • High-level API (proposal does not introduce an API).

Stage 2 Entrance Criteria

Stage 3 Entrance Criteria

Stage 4 Entrance Criteria

  • Test262 acceptance tests have been written for mainline usage scenarios and merged.
  • Two compatible implementations which pass the acceptance tests: [1], [2].
  • A pull request has been sent to tc39/ecma262 with the integrated spec text.
  • The ECMAScript editor has signed off on the pull request.

More Repositories

1

proposals

Tracking ECMAScript Proposals
17,177
star
2

ecma262

Status, process, and documents for ECMA-262
HTML
14,437
star
3

proposal-pipeline-operator

A proposal for adding a useful pipe operator to JavaScript.
HTML
7,380
star
4

proposal-pattern-matching

Pattern matching syntax for ECMAScript
HTML
5,341
star
5

proposal-optional-chaining

HTML
4,952
star
6

proposal-type-annotations

ECMAScript proposal for type syntax that is erased - Stage 1
JavaScript
4,090
star
7

proposal-temporal

Provides standard objects and functions for working with dates and times.
HTML
3,135
star
8

proposal-observable

Observables for ECMAScript
JavaScript
3,032
star
9

proposal-signals

A proposal to add signals to JavaScript.
TypeScript
2,668
star
10

proposal-decorators

Decorators for ES6 classes
2,640
star
11

proposal-record-tuple

ECMAScript proposal for the Record and Tuple value types. | Stage 2: it will change!
HTML
2,423
star
12

test262

Official ECMAScript Conformance Test Suite
JavaScript
2,073
star
13

proposal-dynamic-import

import() proposal for JavaScript
HTML
1,859
star
14

proposal-bind-operator

This-Binding Syntax for ECMAScript
1,736
star
15

proposal-class-fields

Orthogonally-informed combination of public and private fields proposals
HTML
1,720
star
16

proposal-async-await

Async/await for ECMAScript
HTML
1,577
star
17

proposal-object-rest-spread

Rest/Spread Properties for ECMAScript
HTML
1,496
star
18

proposal-shadowrealm

ECMAScript Proposal, specs, and reference implementation for Realms
HTML
1,365
star
19

proposal-nullish-coalescing

Nullish coalescing proposal x ?? y
HTML
1,233
star
20

proposal-iterator-helpers

Methods for working with iterators in ECMAScript
HTML
1,220
star
21

proposal-top-level-await

top-level `await` proposal for ECMAScript (stage 4)
HTML
1,082
star
22

proposal-do-expressions

Proposal for `do` expressions
HTML
990
star
23

agendas

TC39 meeting agendas
JavaScript
952
star
24

proposal-binary-ast

Binary AST proposal for ECMAScript
945
star
25

proposal-built-in-modules

HTML
886
star
26

proposal-async-iteration

Asynchronous iteration for JavaScript
HTML
854
star
27

proposal-explicit-resource-management

ECMAScript Explicit Resource Management
JavaScript
671
star
28

proposal-operator-overloading

JavaScript
610
star
29

proposal-string-dedent

TC39 Proposal to remove common leading indentation from multiline template strings
HTML
588
star
30

proposal-bigint

Arbitrary precision integers in JavaScript
HTML
560
star
31

proposal-set-methods

Proposal for new Set methods in JS
HTML
557
star
32

proposal-import-attributes

Proposal for syntax to import ES modules with assertions
HTML
538
star
33

ecmascript_simd

SIMD numeric type for EcmaScript
JavaScript
536
star
34

proposal-slice-notation

HTML
515
star
35

proposal-change-array-by-copy

Provides additional methods on Array.prototype and TypedArray.prototype to enable changes on the array by returning a new copy of it with the change.
HTML
509
star
36

ecma402

Status, process, and documents for ECMA 402
HTML
506
star
37

notes

TC39 meeting notes
JavaScript
496
star
38

proposal-class-public-fields

Stage 2 proposal for public class fields in ECMAScript
HTML
489
star
39

proposal-iterator.range

A proposal for ECMAScript to add a built-in Iterator.range()
HTML
464
star
40

proposal-uuid

UUID proposal for ECMAScript (Stage 1)
JavaScript
462
star
41

proposal-throw-expressions

Proposal for ECMAScript 'throw' expressions
JavaScript
425
star
42

proposal-module-expressions

HTML
424
star
43

proposal-UnambiguousJavaScriptGrammar

413
star
44

proposal-decimal

Built-in decimal datatype in JavaScript
HTML
408
star
45

proposal-array-grouping

A proposal to make grouping of array items easier
HTML
407
star
46

proposal-async-context

Async Context for JavaScript
HTML
406
star
47

proposal-weakrefs

WeakRefs
HTML
404
star
48

proposal-error-cause

TC39 proposal for accumulating errors
HTML
378
star
49

proposal-ecmascript-sharedmem

Shared memory and atomics for ECMAscript
HTML
376
star
50

proposal-cancelable-promises

Former home of the now-withdrawn cancelable promises proposal for JavaScript
Shell
376
star
51

proposal-relative-indexing-method

A TC39 proposal to add an .at() method to all the basic indexable classes (Array, String, TypedArray)
HTML
351
star
52

proposal-first-class-protocols

a proposal to bring protocol-based interfaces to ECMAScript users
350
star
53

proposal-global

ECMAScript Proposal, specs, and reference implementation for `global`
HTML
346
star
54

proposal-private-methods

Private methods and getter/setters for ES6 classes
HTML
344
star
55

proposal-numeric-separator

A proposal to add numeric literal separators in JavaScript.
HTML
327
star
56

proposal-private-fields

A Private Fields Proposal for ECMAScript
HTML
320
star
57

proposal-object-from-entries

TC39 proposal for Object.fromEntries
HTML
317
star
58

proposal-module-declarations

JavaScript Module Declarations
HTML
314
star
59

proposal-promise-allSettled

ECMAScript Proposal, specs, and reference implementation for Promise.allSettled
HTML
314
star
60

tc39.github.io

Get involved in specifying JavaScript
HTML
313
star
61

proposal-regex-escaping

Proposal for investigating RegExp escaping for the ECMAScript standard
JavaScript
309
star
62

proposal-await.ops

Introduce await.all / await.race / await.allSettled / await.any to simplify the usage of Promises
HTML
308
star
63

proposal-logical-assignment

A proposal to combine Logical Operators and Assignment Expressions
HTML
302
star
64

proposal-export-default-from

Proposal to add `export v from "mod";` to ECMAScript.
HTML
297
star
65

proposal-promise-finally

ECMAScript Proposal, specs, and reference implementation for Promise.prototype.finally
HTML
278
star
66

proposal-asset-references

Proposal to ECMAScript to add first-class location references relative to a module
268
star
67

proposal-cancellation

Proposal for a Cancellation API for ECMAScript
HTML
262
star
68

proposal-json-modules

Proposal to import JSON files as modules
HTML
259
star
69

proposal-promise-with-resolvers

HTML
255
star
70

proposal-string-replaceall

ECMAScript proposal: String.prototype.replaceAll
HTML
254
star
71

proposal-export-ns-from

Proposal to add `export * as ns from "mod";` to ECMAScript.
HTML
241
star
72

proposal-ses

Draft proposal for SES (Secure EcmaScript)
HTML
217
star
73

proposal-structs

JavaScript Structs: Fixed Layout Objects
216
star
74

proposal-intl-relative-time

`Intl.RelativeTimeFormat` specification [draft]
HTML
215
star
75

proposal-flatMap

proposal for flatten and flatMap on arrays
HTML
215
star
76

proposal-json-parse-with-source

Proposal for extending JSON.parse to expose input source text.
HTML
204
star
77

ecmarkup

An HTML superset/Markdown subset source format for ECMAScript and related specifications
TypeScript
201
star
78

proposal-promise-any

ECMAScript proposal: Promise.any
HTML
198
star
79

proposal-decorators-previous

Decorators for ECMAScript
HTML
184
star
80

proposal-smart-pipelines

Old archived draft proposal for smart pipelines. Go to the new Hack-pipes proposal at js-choi/proposal-hack-pipes.
HTML
181
star
81

proposal-defer-import-eval

A proposal for introducing a way to defer evaluate of a module
HTML
174
star
82

proposal-array-filtering

A proposal to make filtering arrays easier
HTML
171
star
83

proposal-optional-chaining-assignment

`a?.b = c` proposal
168
star
84

proposal-array-from-async

Draft specification for a proposed Array.fromAsync method in JavaScript.
HTML
167
star
85

proposal-extractors

Extractors for ECMAScript
JavaScript
166
star
86

proposal-upsert

ECMAScript Proposal, specs, and reference implementation for Map.prototype.upsert
HTML
165
star
87

proposal-ptc-syntax

Discussion and specification for an explicit syntactic opt-in for Tail Calls.
HTML
165
star
88

how-we-work

Documentation of how TC39 operates and how to participate
161
star
89

proposal-collection-methods

HTML
160
star
90

proposal-Array.prototype.includes

Spec, tests, reference implementation, and docs for ESnext-track Array.prototype.includes
HTML
157
star
91

proposal-error-stacks

ECMAScript Proposal, specs, and reference implementation for Error.prototype.stack / System.getStack
HTML
156
star
92

proposal-promise-try

ECMAScript Proposal, specs, and reference implementation for Promise.try
HTML
154
star
93

proposal-hashbang

#! for JS
HTML
148
star
94

proposal-resizablearraybuffer

Proposal for resizable array buffers
HTML
145
star
95

proposal-import-meta

import.meta proposal for JavaScript
HTML
145
star
96

proposal-intl-segmenter

Unicode text segmentation for ECMAScript
HTML
145
star
97

proposal-extensions

Extensions proposal for ECMAScript
HTML
143
star
98

proposal-seeded-random

Proposal for an options argument to be added to JS's Math.random() function, and some options to start it with.
HTML
143
star
99

proposal-intl-duration-format

141
star
100

proposal-regexp-unicode-property-escapes

Proposal to add Unicode property escapes `\p{…}` and `\P{…}` to regular expressions in ECMAScript.
HTML
134
star