stage-0 to stage-4 ECMAscript proposals.

TOC:

Stage 0:

Defensible Classes

Stage-0

// const class const class Point { constructor ( x , y ) { public getX ( ) { return x ; } public getY ( ) { return y ; } } toString ( ) { return `< ${ this . getX ( ) } , ${ this . getY ( ) } >` ; } }

Relationships

Stage-0

x @ r // The object x is in the r relationship with what value? x @ r = y ; // Store that x is in the r relationship with value y.

Stage-0

'abc𝌆def' . at ( 3 ) // → '𝌆'

Stage-0

Reflect . isCallable ( argument ) ;

Stage-0

Reflect . isConstructor ( argument )

Additional metaproperties

Stage-0

function . callee ; // function object that is currently being evaluated by the running execution context.

function . count ; // number of arguments pass to the function.

function . arguments ; // array containing the actual arguments passed to the function.

Function Bind Syntax

Stage-0

// :: which performs this binding and method extraction. Promise . resolve ( 123 ) . then ( :: console . log ) ;

64-Bit Integer Operations

Stage-0

// return the high 32 bit part of the 64 bit addition of (hi0, lo0) and (hi1, lo1) Math . iaddh ( lo0 , hi0 , lo1 , hi1 ) ; // return the high 32 bit part of the 64 bit subtraction of (hi0, lo0) and (hi1, lo1) Math . isubh ( lo0 , hi0 , lo1 , hi1 ) ; // return the high 32 bit part of the signed 64 bit product of the 32 bit numbers a and b Math . imulh ( a , b ) ; // return the high 32 bit part of the unsigned 64 bit product of the 32 bit numbers a and b Math . umulh ( a , b ) ;

Method Parameter Decorators

Stage-0

//decorators that operate on method and constructor parameters.

class MyComponent { refresh ( @ lastRefreshTime timeStamp ) { … } } export function lastRefreshTime ( ... ) { // at minimum, the arguments of this function should contain: // - reference to owner of the parameter (the method) // - parameter index // - parameter name // - is parameter a rest parameter? // store parameter metadata using the same storage mechanism // as the one used for methods }

Function Expression Decorators

Stage-0

scheduleForFrequentReexecution ( @ memoize function ( value ) { value ++ } ) ; export function memoize ( ... ) { // at minimum, the arguments of this function should contain: // - reference to the decorated function expression // - arguments passed into the memoize function (if any) // wrap the decorated function expression memoization implementation and return it }

Zones

Stage-0

//a primitive for context propagation across multiple logically-connected async operations class Zone { constructor ( { name , parent } ) ; name ; get parent ( ) ; fork ( { name } ) ; run ( callback ) ; wrap ( callback ) ; static get current ( ) ; } const loadZone = Zone . current . fork ( { name : "loading zone" } ) ; window . onload = loadZone . wrap ( e => { ... } ) ;

Object enumerables

Stage-0

Object . enumerableKeys ( obj ) ; // Ordered list of keys.

Object . enumerableValues ( obj ) ; // Ordered list of Values.

Object . enumerableEntries ( obj ) ; //Ordered list of key value pairs.

Nested import declarations

Stage-0

describe ( "fancy feature #5" , ( ) => { import { strictEqual } from "assert" ; it ( "should work on the client" , ( ) => { import { check } from "./client.js" ; strictEqual ( check ( ) , "client ok" ) ; } ) ; it ( "should work on the client" , ( ) => { import { check } from "./server.js" ; strictEqual ( check ( ) , "server ok" ) ; } ) ; it ( "should work on both client and server" , ( ) => { import { check } from "./both.js" ; strictEqual ( check ( ) , "both ok" ) ; } ) ; } ) ;

is{Type} APIs

Stage-0

Builtin . is ( Date , vm . runInNewContext ( 'Date' ) ) ; // false Builtin . typeOf ( [ ] ) ; // 'Array' Builtin . typeOf ( new ArrayBuffer ( ) ) ; // 'ArrayBuffer' Builtin . typeOf ( async function foo ( ) { } ) ; // So on.

Orthogonal Class Member Syntax

Stage-0

//A kitchen sink example class Foo { //instance members own x = 0 , y = 0 ; // two data properties own # secret ; // a private field // initial value undefined own * [ Symbol . iterator ] ( ) { yield this . # secret } // a generator method own # callback ( ) { } //a private instance method //class constructor members static # p = new Set ( ) , q = Foo . # p ; // a private field and a property // of the class constructor static get p ( ) { return Foo . # p } //accessor method //prototype methods setCallback ( f ) { this . # callback = f } constructor ( s ) { this . # secret = s ; } }

Pattern Matching Syntax

Stage-0

let getLength = vector => match ( vector ) { { x , y , z } : Math . sqrt ( x ** 2 + y ** 2 + z ** 2 ) , { x , y } : Math . sqrt ( x ** 2 + y ** 2 ) , [ ... ] : vector . length , else : { throw new Error ( "Unknown vector type" ) ; } }

Structured cloning and transfer

Stage-0

StructuredClone ( input , transferList , targetRealm )

WHATWG URL

Stage-0

const base = new URL ( 'http://example.org/foo' ) ; const url = new URL ( 'bar' , base ) ;

Stage 1:

export v from "mod"; statements

Stage-1

export v , { x , y as w } from "mod" ; export v , * as ns from "mod" ;

Observable

Stage-1

// Observable as a Constructor: function listen ( element , eventName ) { return new Observable ( observer => { // Create an event handler which sends data to the sink let handler = event => observer . next ( event ) ; // Attach the event handler element . addEventListener ( eventName , handler , true ) ; // Return a function which will cancel the event stream return ( ) => { // Detach the event handler from the element element . removeEventListener ( eventName , handler , true ) ; } ; } ) ; } // Observable.of creates an Observable of the values provided as arguments Observable . of ( "R" , "G" , "B" ) . subscribe ( { next ( color ) { console . log ( color ) ; } } ) ; // Observable.from converts its argument to an Observable. Observable . from ( [ "R" , "G" , "B" ] ) . subscribe ( { next ( color ) { console . log ( color ) ; } } ) ;

Stage-1

var str = 'Hello world!!!' ; var regexp = / ( \w + ) \W * /g ; console . log ( str . matchAll ( regexp ) ) ; /* [ { 0: "Hello ", 1: "Hello" index: 0, input: "Hello world!!!" }, { 0: "world!!!", 1: "world" index: 6, input: "Hello world!!!" } ] */

WeakRefs

Stage-1

// Make a new weak reference. // The target is a strong pointer to the object that will be pointed // at weakly by the result. // The executor is an optional argument that will be invoked after the // target becomes unreachable. // The holdings is an optional argument that will be provided to the // executor when it is invoked for target. makeWeakRef ( target , executor , holdings ) ;

Frozen Realms

Stage-1

class Realm { // From the prior Realm API proposal const global - > object // access this realm's global object eval ( stringable ) - > any // do an indirect eval in this realm // We expect the rest of earlier proposal to be re-proposed eventually in // some form, but do not rely here on any of the remainder. // New with this proposal static immutableRoot ( ) - > Realm // transitively immutable realm spawn ( endowments ) - > Realm // lightweight child realm }

Math Extensions

Stage-1

// Possible ones: Math . map Math . scale Math . remap Math . clamp Math . constrain Math . toDegrees ( double angrad ) Math . toRadians ( double angdeg )

of and from on collection constructors

Stage-1

Map . of ( ... items ) ; Map . from ( ... items ) ; Set . of ( ... items ) ; Set . from ( ... items ) ; WeakMap . of ( ... items ) ; WeakMap . from ( ... items ) ; WeakSet . of ( ... items ) ; WeakSet . from ( ... items ) ;

Generator arrow functions.

Stage-1

let cat = * ( ) => { yield 'meow' ; }

Date.parse fallback semantics

Stage-1

// New grammar should be used as the "fallback" // when date strings do not conform to the // regular Date Time String Format.

Generator arrow functions (=>*)

Stage-1

// current x => x * x ; ( ... ) => { statements } ( ... ) => ( expr ) // proposed generator arrows... // Irregular ( ) = * > // Hostile to ! (async function) ( ) => * { ... yield . . . } // Not good ( ) => * ( yield a , yield b ) // Ok if 1 token x *= > x * x ; // Bad (ASI) * ( ) => ... // Hostile to ! ( x ) = * { ... }

Stage-1

// Promise.try(function() fn) -> Promise

of and from on collection

Stage-1

CollectionCreate ( C , source [ , mapfn [ , thisArg ] ] ) Map . of ( ... items ) Set . of ( ... items ) WeakMap . of ( ... items ) WeakSet . of ( ... items ) Map . from ( source [ , mapFn [ , thisArg ] ] ) Set . from ( source [ , mapFn [ , thisArg ] ] ) WeakMap . from ( source [ , mapFn [ , thisArg ] ] ) WeakSet . from ( source [ , mapFn [ , thisArg ] ] )

Optional Chaining

Stage-1

obj ? . prop // optional property access obj ? . [ expr ] // ditto func ? . ( ... args ) // optional function or method call new C ? . ( ... args ) // optional constructor invocation

Math.signbit: IEEE-754 sign bit

Stage-1

Math . signbit ( x ) ; /* Returns whether the sign bit of x is set. If n is NaN, the result is false. If n is -0, the result is true. If n is negative, the result is true. Otherwise, the result is false. */

Error Stacks

Stage-1

Error . prototype . stack ; System . getStack ; System . getStackString ; Object . getOwnPropertyDescriptor ( new Error ( ) , 'stack' ) ; Object . getOwnPropertyDescriptor ( Error . prototype , 'stack' ) ;

do expressions

Stage-1

let x = do { let tmp = f ( ) ; tmp * tmp + 1 } ; let x = do { if ( foo ( ) ) { f ( ) } else if ( bar ( ) ) { g ( ) } else { h ( ) } } ;

Realms

Stage-1

let realm = new Realm ( ) ; let outerGlobal = window ; let innerGlobal = realm . global ; let f = realm . evalScript ( "(function() { return 17 })" ) ; f ( ) === 17 // true Reflect . getPrototypeOf ( f ) === outerGlobal . Function . prototype // false Reflect . getPrototypeOf ( f ) === innerGlobal . Function . prototype // true class EmptyRealm extends Realm { constructor ( ... args ) { super ( ... args ) ; } init ( ) { /* do nothing */ } } class FakeWindow extends Realm { init ( ) { super . init ( ) ; // install the standard primordials let global = this . global ; global . document = new FakeDocument ( ... ) ; global . alert = new Proxy ( fakeAlert , { ... } ) ; ... } }

Stage 2:

Template Literal Revision

Stage-2

// The proposal is about fixing those Illegal token errors, avoid restrictions on escape sequences. let document = latex `

ewcommand{\fun}{\textbf{Fun!}} // works just fine

ewcommand{\u nicode } { \textbf{Unicode!}} // Illegal token!

ewcommand{\xe rxes } { \textbf{King!}} // Illegal token! Breve over the h goes \u{ h } ere // Illegal token!

function.sent Meta Property

Stage-2

// Avoid ingnoring the first `next` call. function * adder ( total = 0 ) { let increment = 1 ; do { switch ( request = function . sent ) { case undefined : break ; case "done" : return total ; default : increment = Number ( request ) ; } yield total += increment ; } while ( true ) } let tally = adder ( ) ; tally . next ( 0.1 ) ; // argument no longer ignored tally . next ( 0.1 ) ; tally . next ( 0.1 ) ; let last = tally . next ( "done" ) ; console . log ( last . value ) ; //0.3

Class Property Declarations

Stage-2

// Class instance field class MyClass { myProp = 42 ; constructor ( ) { console . log ( this . myProp ) ; // Prints '42' } } // Static property class MyClass { static myStaticProp = 42 ; constructor ( ) { console . log ( MyClass . myStaticProp ) ; // Prints '42' } }

// Class Static Properties class MyClass { static myStaticProp = 42 ; constructor ( ) { console . log ( MyClass . myStaticProp ) ; // Prints '42' } }

Class and Property Decorators

Stage-2

class C { @ writable ( false ) method ( ) { } } function writable ( value ) { return function ( target , key , descriptor ) { descriptor . writable = value ; return descriptor ; } }

Stage-2

" Hey JS!" . trimStart ( ) ; // "Hey JS!" " Hey JS! " . trimEnd ( ) ; // " Hey JS!" // P.S: trimLeft/trimRight are aliases.

Legacy RegExp features

Stage-2

RegExpAlloc ( newTarget ) ; RegExpBuiltInExec ( R , S ) ; RegExp . input ; RegExp . prototype . compile ( pattern , flags ) ; // modifications

Intl.Segmenter: Unicode segmentation

Stage-2

// Create a segmenter in your locale let segmenter = Intl . Segmenter ( "fr" , { type : "word" } ) ; // Get an iterator over a string let iterator = segmenter . segment ( "Ceci n'est pas une pipe" ) ; // Iterate over it! for ( let { segment , breakType } of iterator ) { console . log ( `segment: ${ segment } breakType: ${ breakType } ` ) ; break ; } // logs the following to the console: // index: Ceci breakType: letter

export * as ns from "mod"; statements

Stage-2

export * as ns from "mod" ; // Exporting the ModuleNameSpace object as a named export.

Stage 3:

global

Stage-3

// global to rule them all. var getGlobal = function ( ) { // the only reliable means to get the global object is // `Function('return this')()` // However, this causes CSP violations in Chrome apps. if ( typeof self !== 'undefined' ) { return self ; } if ( typeof window !== 'undefined' ) { return window ; } if ( typeof global !== 'undefined' ) { return global ; } throw new Error ( 'unable to locate global object' ) ; } ;

Rest and Spread properties

Stage-3

let { x , y , ... z } = { x : 1 , y : 2 , a : 3 , b : 4 } ; // Rest. let n = { x , y , ... z } ; // Spread.

Stage-3

asyncIterator . next ( ) . then ( ( { value , done } ) => /* ... */ ) ;

Function.prototype.toString revision

Stage-3

// String's parse must contains the same // function body and parameter list as the original. O . gOPD ( { get a ( ) { } } , "a" ) . get // "function a(){}" O . gOPD ( { set a ( b ) { } } , "a" ) . set // "function a(b){}"

SIMD APIs

Stage-3

/*a meta-variable ranging over all SIMD types: Float32x4, Int32x4, Int16x8 Int8x16, Uint32x4, Uint16x8, Uint8x16, Bool32x4, Bool16x8 and Bool8x16. */

Lifting Template Literal Restriction

Stage-3

function tag ( strs ) { strs [ 0 ] === undefined strs . raw [ 0 ] === "\\unicode and \\u{55}" ; } tag `\u nicode and \u{55} ` let bad = `bad escape sequence: \u nicode ` ; // throws early error

Shared memory and atomics

Stage-3

var sab = new SharedArrayBuffer ( 1024 ) ; // 1KiB shared memory w . postMessage ( sab , [ sab ] ) // In the worker: var sab ; onmessage = function ( ev ) { sab = ev . data ; // 1KiB shared memory, the same memory as in the parent }

global

stage 3

typeof global ; // object, helps in writing a portable code.

stage 3

import ( `./language-packs/ ${ navigator . language } .js` ) // import(specifier)

RegExp Lookbehind Assertions

Stage-3

const str = '1947' ; // (?<=(\d+)(\d+))$/ => (947) and (1) // Greediness proceeds from right to left // match[1] => 947 and match[2] => 1 // Numbering capture groups // /(?<=\1(.))/ // Referring to capture groups // /(?<!.)/ // Negative assertions

Unicode property escapes in RE

Stage-3

const regexGreekSymbol = / \p { Script = Greek } /u ; regexGreekSymbol . test ( 'π' ) ;

RegExp Named Capture Groups

Stage-3

let { one , two } = / ^ (?< one > . * ) : (?< two > . * ) $ /u . exec ( 'foo:bar' ) ; console . log ( `one: ${ one } , two: ${ two } ` ) ; // prints one: foo, two: bar

s (dotAll) flag for regular expressions

Stage-3

const re = /foo.bar/s ; // Or, `const re = new RegExp('foo.bar', 's');`. re . test ( 'foo

bar' ) ; // → true re . dotAll // → true re . flags // → 's' / foo . bar / s . test ( 'foo

bar' ) ; // → true

Asynchronous Iterators

Stage-3

asyncIterator . next ( ) . then ( result => console . log ( result . value ) ) ; for await ( let line of readLines ( filePath ) ) { print ( line ) ; } async function * readLines ( path ) { let file = await fileOpen ( path ) ; try { while ( ! file . EOF ) yield file . readLine ( ) ; } finally { await file . close ( ) ; } }

Stage-3

somePromise ( ) . then ( ( ) => { } ) . catch ( ( ) => { } ) . finally ( ( ) => { } )

Class Fields

Stage-3