-
Notifications
You must be signed in to change notification settings - Fork 27
[WIP] Add first spec draft #15
Changes from 7 commits
183ab38
667f5ec
03ca27d
521c6b8
027fc60
765624b
7704822
7954185
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ | |
stage: 0 | ||
location: https://tc39.github.io/proposal-promise-any/ | ||
copyright: false | ||
contributors: Mathias Bynens | ||
contributors: Mathias Bynens & Sergey Rubanov | ||
</pre> | ||
<script src="ecmarkup.js" defer></script> | ||
<link rel="stylesheet" href="ecmarkup.css"> | ||
|
@@ -32,4 +32,106 @@ | |
} | ||
</style> | ||
|
||
TODO | ||
<emu-clause id="sec-native-error-types-used-in-this-standard-aggregateerror"> | ||
<h1>AggregateError ( errors, message )</h1> | ||
<p>When the *AggregateError* function is called with arguments _errors_ and _message_, the following steps are taken:</p> | ||
<emu-alg> | ||
1. If NewTarget is *undefined*, let _newTarget_ be the active function object, else let _newTarget_ be NewTarget. | ||
1. Let O be ? OrdinaryCreateFromConstructor(_newTarget_, `"%AggregateErrorPrototype%"`, « [[ErrorData]] »). | ||
1. Let _errorsIterator_ be ? GetMethod(_errors_, @@iterator). | ||
1. Let _errorsList_ ? IterableToList(_errors_, _errorsIterator_). | ||
1. Let _errorsArray_ be CreateArrayFromList(_errorsList_). | ||
1. Perform ! CreateDataProperty(_O_, `"errors"`, _errorsArray_). | ||
1. If _message_ is not _undefined_, then | ||
1. Let msg be ? ToString(_message_). | ||
1. Let msgDesc be the PropertyDescriptor { [[Value]]: _msg_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *true* }. | ||
1. Perform ! DefinePropertyOrThrow(_O_, `"message"`, _msgDesc_). | ||
1. Return _O_. | ||
</emu-alg> | ||
</emu-clause> | ||
|
||
<emu-intro id="intro"> | ||
<h1>Introduction</h1> | ||
<p>`Promise.any()` accepts an array of promises and returns a promise that is fulfilled by the first given promise to be fulfilled, or rejected with an array of rejection reasons if all of the given promises are rejected.</p> | ||
</emu-intro> | ||
|
||
<emu-clause id="sec-promise.any"> | ||
<h1>Promise.any ( _iterable_ )</h1> | ||
<p>The `any` function returns a promise that is fulfilled by the first given promise to be fulfilled, or rejected with an array of rejection reasons if all of the given promises are rejected. It resolves all elements of the passed iterable to promises as it runs this algorithm.</p> | ||
<emu-alg> | ||
1. Let _C_ be the *this* value. | ||
1. If Type(_C_) is not Object, throw a *TypeError* exception. | ||
1. Let _promiseCapability_ be ? NewPromiseCapability(_C_). | ||
1. Let _iteratorRecord_ be GetIterator(_iterable_). | ||
1. IfAbruptRejectPromise(_iteratorRecord_, _promiseCapability_). | ||
1. Let _result_ be PerformPromiseAny(_iteratorRecord_, _C_, _promiseCapability_). | ||
1. If _result_ is an abrupt completion, then | ||
1. If _iteratorRecord_.[[Done]] is *false*, set _result_ to IteratorClose(_iteratorRecord_, _result_). | ||
1. IfAbruptRejectPromise(_result_, _promiseCapability_). | ||
1. Return Completion(_result_). | ||
</emu-alg> | ||
<emu-note> | ||
<p>The `any` function requires its *this* value to be a constructor function that supports the parameter conventions of the `Promise` constructor.</p> | ||
</emu-note> | ||
|
||
<emu-clause id="sec-performpromiseany" aoid="PerformPromiseAny"> | ||
<h1>Runtime Semantics: PerformPromiseAny ( _iteratorRecord_, _constructor_, _resultCapability_ )</h1> | ||
<p>When the PerformPromiseAny abstract operation is called with arguments _iteratorRecord_, _constructor_, and _resultCapability_, the following steps are taken:</p> | ||
<emu-alg> | ||
1. Assert: ! IsConstructor(_constructor_) is *true*. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add an assertion about iteratorRecord? |
||
1. Assert: _resultCapability_ is a PromiseCapability Record. | ||
1. Let _values_ be a new empty List. | ||
1. Let _remainingElementsCount_ be a new Record { [[Value]]: 1 }. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems weird to have a record here and pass it around. Is keeping a count like this the only solution? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at existing ECMAScript Specification Types, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh sure, i wasn't suggesting a JS object or anything :-) more that, is passing around a counter the only viable approach? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I got it. Not sure to be honest 🤔 I need to do some more research to answer this question 🕵️♀️ |
||
1. Let _index_ be 0. | ||
1. Repeat, | ||
1. Let _next_ be IteratorStep(_iteratorRecord_). | ||
1. If _next_ is an abrupt completion, set _iteratorRecord_.[[Done]] to *true*. | ||
1. ReturnIfAbrupt(_next_). | ||
1. If _next_ is *false*, then | ||
1. Set _iteratorRecord_.[[Done]] to *true*. | ||
1. Set _remainingElementsCount_.[[Value]] to _remainingElementsCount_.[[Value]] - 1. | ||
1. If _remainingElementsCount_.[[Value]] is 0, then | ||
1. Let _valuesArray_ be CreateArrayFromList(_values_). | ||
1. Perform ? Call(_resultCapability_.[[Resolve]], *undefined*, « _valuesArray_ »). | ||
1. Return _resultCapability_.[[Promise]]. | ||
1. Let _nextValue_ be IteratorValue(_next_). | ||
1. If _nextValue_ is an abrupt completion, set _iteratorRecord_.[[Done]] to *true*. | ||
1. ReturnIfAbrupt(_nextValue_). | ||
1. Append *undefined* to _values_. | ||
1. Let _nextPromise_ be ? Invoke(_constructor_, `"resolve"`, « _nextValue_ »). | ||
1. Let _steps_ be the algorithm steps defined in <emu-xref href="#sec-promise.any-reject-element-functions" title></emu-xref>. | ||
1. Let _rejectElement_ be CreateBuiltinFunction(_steps_, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). | ||
1. Set _rejectElement_.[[AlreadyCalled]] to a new Record { [[Value]]: *false* }. | ||
1. Set _rejectElement_.[[Index]] to _index_. | ||
1. Set _rejectElement_.[[Values]] to _values_. | ||
1. Set _rejectElement_.[[Capability]] to _resultCapability_. | ||
1. Set _rejectElement_.[[RemainingElements]] to _remainingElementsCount_. | ||
1. Set _remainingElementsCount_.[[Value]] to _remainingElementsCount_.[[Value]] + 1. | ||
1. Perform ? Invoke(_nextPromise_, `"then"`, « _resultCapability_, _rejectElement_[[Reject]] »). | ||
1. Increase _index_ by 1. | ||
</emu-alg> | ||
</emu-clause> | ||
|
||
<emu-clause id="sec-promise.any-reject-element-functions"> | ||
<h1>`Promise.any` Reject Element Functions</h1> | ||
<p>A `Promise.any` reject element function is an anonymous built-in function that is used to reject a specific `Promise.any` element. Each `Promise.any` reject element function has [[Index]], [[Values]], [[Capability]], [[RemainingElements]], and [[AlreadyCalled]] internal slots.</p> | ||
<p>When a `Promise.any` reject element function is called with argument _x_, the following steps are taken:</p> | ||
<emu-alg> | ||
1. Let _F_ be the active function object. | ||
1. Let _alreadyCalled_ be _F_.[[AlreadyCalled]]. | ||
1. If _alreadyCalled_.[[Value]] is *true*, return *undefined*. | ||
1. Set _alreadyCalled_.[[Value]] to *true*. | ||
1. Let _index_ be _F_.[[Index]]. | ||
1. Let _values_ be _F_.[[Values]]. | ||
1. Let _promiseCapability_ be _F_.[[Capability]]. | ||
1. Let _remainingElementsCount_ be _F_.[[RemainingElements]]. | ||
1. Set _values_[_index_] to _x_. | ||
1. Set _remainingElementsCount_.[[Value]] to _remainingElementsCount_.[[Value]] - 1. | ||
1. If _remainingElementsCount_.[[Value]] is 0, then | ||
1. Let _valuesArray_ be CreateArrayFromList(_values_). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably should be something like
I'm not sure There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't yet have a convention for how to specify an error object which has a required property. I think I would do something like
The "a newly created WhateverError object" phrasing is used elsewhere. Doing it this way hopefully makes it clear that engines are required to provide |
||
1. Return ? Call(*undefined*, _promiseCapability_.[[Reject]], « _valuesArray_ »). | ||
1. Return *undefined*. | ||
</emu-alg> | ||
<p>The `"length"` property of a `Promise.any` resolve element function is 1.</p> | ||
</emu-clause> | ||
</emu-clause> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ljharb should this be
instead?
ref: https://github.com/tc39/ecma262/pull/1376/files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, good one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chicoxyzzy once that PR lands, yes, it decidedly should be :-) until then, tho, you'd need to create a new intrinsic for the prototype for this spec to be correct.