Skip to content

Commit 5cfcfc0

Browse files
authored
Normative: Shield dynamic import defer against Promise.prototype monkey patch (#77)
1 parent 756db90 commit 5cfcfc0

1 file changed

Lines changed: 123 additions & 3 deletions

File tree

spec.emu

Lines changed: 123 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,7 @@ contributors: Nicolò Ribaudo
493493
1. <ins>Return ~unused~.</ins>
494494
1. <ins>Let _asyncDepsEvaluationPromises_ be a new empty List.</ins>
495495
1. <ins>For each Module Record _dep_ of _evaluationList_, append _dep_.Evaluate() to _asyncDepsEvaluationPromises_.</ins>
496-
1. <ins>Let _iterator_ be CreateListIteratorRecord(_asyncDepsEvaluationPromises_).</ins>
497-
1. <ins>Let _pc_ be ! NewPromiseCapability(%Promise%).</ins>
498-
1. <ins>Let _evaluatePromise_ be ! PerformPromiseAll(_iterator_, %Promise%, _pc_, %Promise.resolve%).</ins>
496+
1. <ins>Let _evaluatePromise_ be SafePerformPromiseAll(_asyncDepsEvaluationPromises_).</ins>
499497
1. <ins>Else,</ins>
500498
1. <ins>Assert: _phase_ is ~evaluation~.</ins>
501499
1. <ins>Let _evaluatePromise_ be _module_.Evaluate().</ins>
@@ -2182,6 +2180,128 @@ contributors: Nicolò Ribaudo
21822180
</emu-clause>
21832181
</emu-clause>
21842182

2183+
<emu-clause id="sec-control-abstraction-objects" number="27">
2184+
<h1>Control Abstraction Objects</h1>
2185+
2186+
<emu-clause id="sec-promise-objects" number="2">
2187+
<h1>Promise Objects</h1>
2188+
2189+
<emu-clause id="sec-properties-of-the-promise-constructor" number="4">
2190+
<h1>Properties of the Promise Constructor</h1>
2191+
2192+
<emu-clause id="sec-promise.all">
2193+
<h1>Promise.all ( _iterable_ )</h1>
2194+
2195+
<emu-clause id="sec-create-promise-all-resolve-element" type="abstract operation">
2196+
<h1>
2197+
<ins>CreatePromiseAllResolveElement (
2198+
_index_: a non-negative integer,
2199+
_values_: a List,
2200+
_resultCapability_: a PromiseCapability Record,
2201+
_remainingElementsCount_: a Record { [[Value]]: a non-negative integer },
2202+
): a function object</ins>
2203+
</h1>
2204+
<dl class="header">
2205+
<dt>description</dt>
2206+
<dd>It creates a resolve element function for use with PerformPromiseAll and SafePerformPromiseAll.</dd>
2207+
</dl>
2208+
<emu-alg>
2209+
1. Let _fulfilledSteps_ be a new Abstract Closure with parameters (_value_) that captures _values_, _resultCapability_, and _remainingElementsCount_ and performs the following steps when called:
2210+
1. Let _F_ be the active function object.
2211+
1. If _F_.[[AlreadyCalled]] is *true*, return *undefined*.
2212+
1. Set _F_.[[AlreadyCalled]] to *true*.
2213+
1. Let _thisIndex_ be _F_.[[Index]].
2214+
1. Set _values_[_thisIndex_] to _value_.
2215+
1. Set _remainingElementsCount_.[[Value]] to _remainingElementsCount_.[[Value]] - 1.
2216+
1. If _remainingElementsCount_.[[Value]] = 0, then
2217+
1. Let _valuesArray_ be CreateArrayFromList(_values_).
2218+
1. Return ? Call(_resultCapability_.[[Resolve]], *undefined*, « _valuesArray_ »).
2219+
1. Return *undefined*.
2220+
1. Let _onFulfilled_ be CreateBuiltinFunction(_fulfilledSteps_, 1, *""*, « [[AlreadyCalled]], [[Index]] »).
2221+
1. Set _onFulfilled_.[[AlreadyCalled]] to *false*.
2222+
1. Set _onFulfilled_.[[Index]] to _index_.
2223+
1. Return _onFulfilled_.
2224+
</emu-alg>
2225+
</emu-clause>
2226+
2227+
<emu-clause id="sec-performpromiseall" oldids="sec-promise.all-resolve-element-functions" type="abstract operation">
2228+
<h1>
2229+
PerformPromiseAll (
2230+
_iteratorRecord_: an Iterator Record,
2231+
_constructor_: a constructor,
2232+
_resultCapability_: a PromiseCapability Record,
2233+
_promiseResolve_: a function object,
2234+
): either a normal completion containing an ECMAScript language value or a throw completion
2235+
</h1>
2236+
<dl class="header">
2237+
</dl>
2238+
<emu-alg>
2239+
1. Let _values_ be a new empty List.
2240+
1. [declared="remainingElementsCount"] NOTE: _remainingElementsCount_ starts at 1 instead of 0 to ensure _resultCapability_.[[Resolve]] is only called once, even in the presence of a misbehaving *"then"* which calls the passed callback before the input iterator is exhausted.
2241+
1. Let _remainingElementsCount_ be the Record { [[Value]]: 1 }.
2242+
1. Let _index_ be 0.
2243+
1. Repeat,
2244+
1. Let _next_ be ? IteratorStepValue(_iteratorRecord_).
2245+
1. If _next_ is ~done~, then
2246+
1. Set _remainingElementsCount_.[[Value]] to _remainingElementsCount_.[[Value]] - 1.
2247+
1. If _remainingElementsCount_.[[Value]] = 0, then
2248+
1. Let _valuesArray_ be CreateArrayFromList(_values_).
2249+
1. Perform ? Call(_resultCapability_.[[Resolve]], *undefined*, « _valuesArray_ »).
2250+
1. Return _resultCapability_.[[Promise]].
2251+
1. Append *undefined* to _values_.
2252+
1. Let _nextPromise_ be ? Call(_promiseResolve_, _constructor_, « _next_ »).
2253+
1. <del>Let _fulfilledSteps_ be a new Abstract Closure with parameters (_value_) that captures _values_, _resultCapability_, and _remainingElementsCount_ and performs the following steps when called:</del>
2254+
1. <del>Let _F_ be the active function object.</del>
2255+
1. <del>If _F_.[[AlreadyCalled]] is *true*, return *undefined*.</del>
2256+
1. <del>Set _F_.[[AlreadyCalled]] to *true*.</del>
2257+
1. <del>Let _thisIndex_ be _F_.[[Index]].</del>
2258+
1. <del>Set _values_[_thisIndex_] to _value_.</del>
2259+
1. <del>Set _remainingElementsCount_.[[Value]] to _remainingElementsCount_.[[Value]] - 1.</del>
2260+
1. <del>If _remainingElementsCount_.[[Value]] = 0, then</del>
2261+
1. <del>Let _valuesArray_ be CreateArrayFromList(_values_).</del>
2262+
1. <del>Return ? Call(_resultCapability_.[[Resolve]], *undefined*, « _valuesArray_ »).</del>
2263+
1. <del>Return *undefined*.</del>
2264+
1. <del>Let _onFulfilled_ be CreateBuiltinFunction(_fulfilledSteps_, 1, *""*, « [[AlreadyCalled]], [[Index]] »).</del>
2265+
1. <del>Set _onFulfilled_.[[AlreadyCalled]] to *false*.</del>
2266+
1. <del>Set _onFulfilled_.[[Index]] to _index_.</del>
2267+
1. <ins>Let _onFulfilled_ be CreatePromiseAllResolveElement(_index_, _values_, _resultCapability_, _remainingElementsCount_).</ins>
2268+
1. Set _index_ to _index_ + 1.
2269+
1. Set _remainingElementsCount_.[[Value]] to _remainingElementsCount_.[[Value]] + 1.
2270+
1. Perform ? Invoke(_nextPromise_, *"then"*, « _onFulfilled_, _resultCapability_.[[Reject]] »).
2271+
</emu-alg>
2272+
</emu-clause>
2273+
2274+
<emu-clause id="sec-safe-perform-promise-all" type="abstract operation">
2275+
<h1>
2276+
<ins>SafePerformPromiseAll (
2277+
_promises_: a List of Promises,
2278+
): a Promise</ins>
2279+
</h1>
2280+
<dl class="header">
2281+
<dt>description</dt>
2282+
<dd>It performs a Promise.all operation on a list of native promises, calling PerformPromiseThen directly instead of looking up *"then"* on each promise.</dd>
2283+
</dl>
2284+
<emu-alg>
2285+
1. Let _resultCapability_ be ! NewPromiseCapability(%Promise%).
2286+
1. If _promises_ is empty, then
2287+
1. Perform ! Call(_resultCapability_.[[Resolve]], *undefined*, « CreateArrayFromList(« ») »).
2288+
1. Return _resultCapability_.[[Promise]].
2289+
1. Let _values_ be a new empty List.
2290+
1. Let _remainingElementsCount_ be the Record { [[Value]]: the number of elements in _promises_ }.
2291+
1. Let _index_ be 0.
2292+
1. For each element _promise_ of _promises_, do
2293+
1. Append *undefined* to _values_.
2294+
1. Let _onFulfilled_ be CreatePromiseAllResolveElement(_index_, _values_, _resultCapability_, _remainingElementsCount_).
2295+
1. Set _index_ to _index_ + 1.
2296+
1. Perform PerformPromiseThen(_promise_, _onFulfilled_, _resultCapability_.[[Reject]]).
2297+
1. Return _resultCapability_.[[Promise]].
2298+
</emu-alg>
2299+
</emu-clause>
2300+
</emu-clause>
2301+
</emu-clause>
2302+
</emu-clause>
2303+
</emu-clause>
2304+
21852305
<emu-clause id="sec-reflection" number="28">
21862306
<h1>Reflection</h1>
21872307

0 commit comments

Comments
 (0)