From ff771cb1a5f6dcf6ca861a792123afbcd40b8642 Mon Sep 17 00:00:00 2001 From: Michael Ficarra Date: Mon, 26 Sep 2022 16:56:05 -0600 Subject: [PATCH] fixes #218: defien built-in async function objects --- spec.html | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 187 insertions(+), 6 deletions(-) diff --git a/spec.html b/spec.html index b527d10..c1e2a25 100644 --- a/spec.html +++ b/spec.html @@ -127,6 +127,105 @@

Well-Known Intrinsic Objects

+ +

Built-in Function Objects

+ +

+ If a built-in function object is not implemented as an ECMAScript function it must provide [[Call]] and [[Construct]] internal methods that conform to the following definitions: + Unless otherwise specified, a built-in function object must provide [[Call]] and [[Construct]] internal methods that conform to the following definitions: +

+ + +

+ CreateBuiltinFunction ( + _behaviour_: an Abstract Closure, a set of algorithm steps, or some other definition of a function's behaviour provided in this specification, + _length_: a non-negative integer or +∞, + _name_: a property key or a Private Name, + _additionalInternalSlotsList_: a List of names of internal slots, + optional _realm_: a Realm Record, + optional _prototype_: an Object or *null*, + optional _prefix_: a String, + ): a function object +

+
+
description
+
_additionalInternalSlotsList_ contains the names of additional internal slots that must be defined as part of the object. This operation creates a built-in function object.
+
+ + 1. If _realm_ is not present, set _realm_ to the current Realm Record. + 1. If _prototype_ is not present, set _prototype_ to _realm_.[[Intrinsics]].[[%Function.prototype%]]. + 1. Let _internalSlotsList_ be a List containing the names of all the internal slots that requires for the built-in function object that is about to be created. + 1. Append to _internalSlotsList_ the elements of _additionalInternalSlotsList_. + 1. If _behaviour_ is described as async, then + 1. Let _func_ be a new built-in async function object that, when called, performs the action described by _behaviour_ using the provided arguments as the values of the corresponding parameters specified by _behaviour_. The new function object has internal slots whose names are the elements of _internalSlotsList_, and an [[InitialName]] internal slot. + 1. Else, + 1. Let _func_ be a new built-in function object that, when called, performs the action described by _behaviour_ using the provided arguments as the values of the corresponding parameters specified by _behaviour_. The new function object has internal slots whose names are the elements of _internalSlotsList_, and an [[InitialName]] internal slot. + 1. Set _func_.[[Prototype]] to _prototype_. + 1. Set _func_.[[Extensible]] to *true*. + 1. Set _func_.[[Realm]] to _realm_. + 1. Set _func_.[[InitialName]] to *null*. + 1. Perform SetFunctionLength(_func_, _length_). + 1. If _prefix_ is not present, then + 1. Perform SetFunctionName(_func_, _name_). + 1. Else, + 1. Perform SetFunctionName(_func_, _name_, _prefix_). + 1. Return _func_. + +

Each built-in function defined in this specification is created by calling the CreateBuiltinFunction abstract operation.

+
+
+ + +

Built-in Async Function Objects

+

Built-in async function objects are built-in function objects that provide alternative [[Call]] and [[Construct]] internal methods that conform to the following definitions:

+ + +

+ [[Call]] ( + _thisArgument_: an ECMAScript language value, + _argumentsList_: a List of ECMAScript language values, + ): a normal completion containing an ECMAScript language value +

+
+
for
+
a built-in async function object _F_
+
+ + 1. Let _callerContext_ be the running execution context. + 1. If _callerContext_ is not already suspended, suspend _callerContext_. + 1. Let _calleeContext_ be a new execution context. + 1. Set the Function of _calleeContext_ to _F_. + 1. Let _calleeRealm_ be _F_.[[Realm]]. + 1. Set the Realm of _calleeContext_ to _calleeRealm_. + 1. Set the ScriptOrModule of _calleeContext_ to *null*. + 1. Perform any necessary implementation-defined initialization of _calleeContext_. + 1. Push _calleeContext_ onto the execution context stack; _calleeContext_ is now the running execution context. + 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). + 1. Let _resultsClosure_ be a new Abstract Closure that captures _F_, _thisArgument_, and _argumentsList_ and performs the following steps when called: + 1. Return the result of evaluating _F_ in a manner that conforms to the specification of _F_. _thisArgument_ is the *this* value, _argumentsList_ provides the named parameters, and the NewTarget value is *undefined*. + 1. Perform AsyncFunctionStart(_promiseCapability_, _resultsClosure_). + 1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context. + 1. Return _promiseCapability_. + +
+ + +

+ [[Construct]] ( + _argumentsList_: a List of ECMAScript language values, + _newTarget_: a constructor, + ): either a normal completion containing an Object or a throw completion +

+
+
for
+
a built-in async function object _F_
+
+ + 1. Throw a *TypeError* exception. + +
+
+

Abstract Operations

@@ -448,6 +547,7 @@

Iterator.prototype.constructor

Iterator.prototype.map ( _mapper_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_mapper_) is *false*, throw a *TypeError* exception. @@ -466,6 +566,7 @@

Iterator.prototype.map ( _mapper_ )

Iterator.prototype.filter ( _filterer_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_filterer_) is *false*, throw a *TypeError* exception. @@ -485,6 +586,7 @@

Iterator.prototype.filter ( _filterer_ )

Iterator.prototype.take ( _limit_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _numLimit_ be ? ToNumber(_limit_). @@ -508,6 +610,7 @@

Iterator.prototype.take ( _limit_ )

Iterator.prototype.drop ( _limit_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _numLimit_ be ? ToNumber(_limit_). @@ -532,6 +635,7 @@

Iterator.prototype.drop ( _limit_ )

Iterator.prototype.indexed ( )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and performs the following steps when called: @@ -550,6 +654,7 @@

Iterator.prototype.indexed ( )

Iterator.prototype.flatMap ( _mapper_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_mapper_) is *false*, throw a *TypeError* exception. @@ -582,6 +687,7 @@

Iterator.prototype.flatMap ( _mapper_ )

Iterator.prototype.reduce ( _reducer_ [ , _initialValue_ ] )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_reducer_) is *false*, throw a *TypeError* exception. @@ -603,6 +709,7 @@

Iterator.prototype.reduce ( _reducer_ [ , _initialValue_ ] )

Iterator.prototype.toArray ( )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _items_ be a new empty List. @@ -616,6 +723,7 @@

Iterator.prototype.toArray ( )

Iterator.prototype.toAsync ( )

+

This method performs the following steps when called:

1. Let _syncIteratorRecord_ be ? GetIteratorDirect(*this* value). 1. Let _asyncIteratorRecord_ be CreateAsyncFromSyncIterator(_syncIteratorRecord_). @@ -627,6 +735,7 @@

Iterator.prototype.toAsync ( )

Iterator.prototype.forEach ( _fn_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_fn_) is *false*, throw a *TypeError* exception. @@ -641,6 +750,7 @@

Iterator.prototype.forEach ( _fn_ )

Iterator.prototype.some ( _fn_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_fn_) is *false*, throw a *TypeError* exception. @@ -656,6 +766,7 @@

Iterator.prototype.some ( _fn_ )

Iterator.prototype.every ( _fn_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_fn_) is *false*, throw a *TypeError* exception. @@ -671,6 +782,7 @@

Iterator.prototype.every ( _fn_ )

Iterator.prototype.find ( _fn_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_fn_) is *false*, throw a *TypeError* exception. @@ -709,6 +821,7 @@

AsyncIterator.prototype.constructor

AsyncIterator.prototype.map ( _mapper_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_mapper_) is *false*, throw a *TypeError* exception. @@ -729,6 +842,7 @@

AsyncIterator.prototype.map ( _mapper_ )

AsyncIterator.prototype.filter ( _filterer_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_filterer_) is *false*, throw a *TypeError* exception. @@ -750,6 +864,7 @@

AsyncIterator.prototype.filter ( _filterer_ )

AsyncIterator.prototype.take ( _limit_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _numLimit_ be ? ToNumber(_limit_). @@ -773,6 +888,7 @@

AsyncIterator.prototype.take ( _limit_ )

AsyncIterator.prototype.drop ( _limit_ )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _numLimit_ be ? ToNumber(_limit_). @@ -797,6 +913,7 @@

AsyncIterator.prototype.drop ( _limit_ )

AsyncIterator.prototype.indexed ( )

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and performs the following steps when called: @@ -815,7 +932,7 @@

AsyncIterator.prototype.indexed ( )

AsyncIterator.prototype.flatMap ( _mapper_ )

-

AsyncIterator.prototype.flatMap is a built-in async generator function which, when called, performs the following steps:

+

This method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_mapper_) is *false*, throw a *TypeError* exception. @@ -857,6 +974,7 @@

AsyncIterator.prototype.flatMap ( _mapper_ )

AsyncIterator.prototype.reduce ( _reducer_ [ , _initialValue_ ] )

+

This async method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_reducer_) is *false*, throw a *TypeError* exception. @@ -880,7 +998,7 @@

AsyncIterator.prototype.reduce ( _reducer_ [ , _initialValue_ ] )

AsyncIterator.prototype.toArray ( )

-

AsyncIterator.prototype.toArray is a built-in async function which, when called, performs the following steps:

+

This async method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _items_ be a new empty List. @@ -894,7 +1012,7 @@

AsyncIterator.prototype.toArray ( )

AsyncIterator.prototype.forEach ( _fn_ )

-

AsyncIterator.prototype.forEach is a built-in async function which, when called, performs the following steps:

+

This async method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_fn_) is *false*, throw a *TypeError* exception. @@ -911,7 +1029,7 @@

AsyncIterator.prototype.forEach ( _fn_ )

AsyncIterator.prototype.some ( _fn_ )

-

AsyncIterator.prototype.some is a built-in async function which, when called, performs the following steps:

+

This async method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_fn_) is *false*, throw a *TypeError* exception. @@ -929,7 +1047,7 @@

AsyncIterator.prototype.some ( _fn_ )

AsyncIterator.prototype.every ( _fn_ )

-

AsyncIterator.prototype.every is a built-in async function which, when called, performs the following steps:

+

This async method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_fn_) is *false*, throw a *TypeError* exception. @@ -947,7 +1065,7 @@

AsyncIterator.prototype.every ( _fn_ )

AsyncIterator.prototype.find ( _fn_ )

-

AsyncIterator.prototype.find is a built-in async function which, when called, performs the following steps:

+

This async method performs the following steps when called:

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_fn_) is *false*, throw a *TypeError* exception. @@ -972,6 +1090,69 @@

AsyncIterator.prototype [ @@toStringTag ]

+ + +

AsyncFunction Objects

+ +

Async Functions Abstract Operations

+ + +

+ AsyncFunctionStart ( + _promiseCapability_: a PromiseCapability Record, + _asyncFunctionBody_: a |FunctionBody| Parse Node or an |ExpressionBody| Parse Node or an Abstract Closure with no parameters, + ): ~unused~ +

+
+
+ + 1. Let _runningContext_ be the running execution context. + 1. Let _asyncContext_ be a copy of _runningContext_. + 1. NOTE: Copying the execution state is required for AsyncBlockStart to resume its execution. It is ill-defined to resume a currently executing context. + 1. Perform AsyncBlockStart(_promiseCapability_, _asyncFunctionBody_, _asyncContext_). + 1. Return ~unused~. + +
+ + +

+ AsyncBlockStart ( + _promiseCapability_: a PromiseCapability Record, + _asyncBody_: a Parse Node or an Abstract Closure with no parameters, + _asyncContext_: an execution context, + ) +

+
+
+ + 1. Assert: _promiseCapability_ is a PromiseCapability Record. + 1. Let _runningContext_ be the running execution context. + 1. [fence-effects="user-code"] Set the code evaluation state of _asyncContext_ such that when evaluation is resumed for that execution context the following steps will be performed: + 1. If _asyncBody_ is a Parse Node, then + 1. Let _result_ be the result of evaluating _asyncBody_. + 1. Else, + 1. Assert: _asyncBody_ is an Abstract Closure with no parameters. + 1. Let _result_ be _asyncBody_(). + 1. Let _result_ be the result of evaluating _asyncBody_. + 1. Assert: If we return here, the async function either threw an exception or performed an implicit or explicit return; all awaiting is done. + 1. Remove _asyncContext_ from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context. + 1. If _result_.[[Type]] is ~normal~, then + 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « *undefined* »). + 1. Else if _result_.[[Type]] is ~return~, then + 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _result_.[[Value]] »). + 1. Else, + 1. Assert: _result_.[[Type]] is ~throw~. + 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _result_.[[Value]] »). + 1. [id="step-asyncblockstart-return-undefined"] Return. + 1. Push _asyncContext_ onto the execution context stack; _asyncContext_ is now the running execution context. + 1. Resume the suspended evaluation of _asyncContext_. Let _result_ be the value returned by the resumed computation. + 1. Assert: When we return here, _asyncContext_ has already been removed from the execution context stack and _runningContext_ is the currently running execution context. + 1. Assert: _result_ is a normal completion with a value of *undefined*. The possible sources of completion values are Await or, if the async function doesn't await anything, step above. + 1. Return. + +
+
+