Skip to content

Commit fae782c

Browse files
committed
Use promise_group instead for promise all and all settled
1 parent 016e959 commit fae782c

File tree

1 file changed

+125
-206
lines changed

1 file changed

+125
-206
lines changed

nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_constructor.rs

Lines changed: 125 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -234,114 +234,15 @@ impl PromiseConstructor {
234234
agent: &mut Agent,
235235
this_value: Value,
236236
arguments: ArgumentsList,
237-
mut gc: GcScope<'gc, '_>,
237+
gc: GcScope<'gc, '_>,
238238
) -> JsResult<'gc, Value<'gc>> {
239-
let this_value = this_value.bind(gc.nogc());
240-
let arguments = arguments.bind(gc.nogc());
241-
let iterable = arguments.get(0).scope(agent, gc.nogc());
242-
243-
// 1. Let C be the this value.
244-
if this_value
245-
!= agent
246-
.current_realm_record()
247-
.intrinsics()
248-
.promise()
249-
.into_value()
250-
{
251-
return Err(throw_promise_subclassing_not_supported(
252-
agent,
253-
gc.into_nogc(),
254-
));
255-
}
256-
257-
// 2. Let promiseCapability be ? NewPromiseCapability(C).
258-
let Some(constructor) = is_constructor(agent, this_value) else {
259-
return Err(agent.throw_exception_with_static_message(
260-
ExceptionType::TypeError,
261-
"Expected the this value to be a constructor.",
262-
gc.into_nogc(),
263-
));
264-
};
265-
let constructor = constructor.scope(agent, gc.nogc());
266-
let promise_capability = PromiseCapability::new(agent, gc.nogc());
267-
let promise = promise_capability.promise().scope(agent, gc.nogc());
268-
269-
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
270-
let promise_resolve = get_promise_resolve(agent, constructor.get(agent), gc.reborrow())
271-
.unbind()
272-
.bind(gc.nogc());
273-
274-
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
275-
let promise_capability = PromiseCapability {
276-
promise: promise.get(agent).bind(gc.nogc()),
277-
must_be_unresolved: true,
278-
};
279-
let promise_resolve =
280-
if_abrupt_reject_promise_m!(agent, promise_resolve, promise_capability, gc);
281-
let promise_resolve = promise_resolve.scope(agent, gc.nogc());
282-
283-
// 5. Let iteratorRecord be Completion(GetIterator(iterable, sync)).
284-
let iterator_record = get_iterator(agent, iterable.get(agent), false, gc.reborrow())
285-
.unbind()
286-
.bind(gc.nogc());
287-
288-
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
289-
let promise_capability = PromiseCapability {
290-
promise: promise.get(agent).bind(gc.nogc()),
291-
must_be_unresolved: true,
292-
};
293-
let MaybeInvalidIteratorRecord {
294-
iterator,
295-
next_method,
296-
} = if_abrupt_reject_promise_m!(agent, iterator_record, promise_capability, gc);
297-
298-
let iterator = iterator.scope(agent, gc.nogc());
299-
300-
// 7. Let result be Completion(PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve)).
301-
let mut iterator_done = false;
302-
let result = perform_promise_group(
239+
promise_group(
303240
agent,
304-
iterator.clone(),
305-
next_method.unbind(),
306-
constructor,
307-
promise_capability.unbind(),
308-
promise_resolve,
309-
&mut iterator_done,
241+
this_value,
242+
arguments,
310243
PromiseGroupType::PromiseAll,
311-
gc.reborrow(),
244+
gc,
312245
)
313-
.unbind()
314-
.bind(gc.nogc());
315-
316-
// 8. If result is an abrupt completion, then
317-
let result = match result {
318-
Err(mut result) => {
319-
// a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
320-
if !iterator_done {
321-
result = iterator_close_with_error(
322-
agent,
323-
iterator.get(agent),
324-
result.unbind(),
325-
gc.reborrow(),
326-
)
327-
.unbind()
328-
.bind(gc.nogc());
329-
}
330-
331-
// b. IfAbruptRejectPromise(result, promiseCapability).
332-
let promise_capability = PromiseCapability {
333-
promise: promise.get(agent).bind(gc.nogc()),
334-
must_be_unresolved: true,
335-
};
336-
// a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
337-
promise_capability.reject(agent, result.value().unbind(), gc.nogc());
338-
// b. Return capability.[[Promise]].
339-
promise_capability.promise()
340-
}
341-
Ok(result) => result,
342-
};
343-
// 9. Return ! result.
344-
Ok(result.into_value().unbind())
345246
}
346247

347248
/// ### [27.2.4.2 Promise.allSettled ( iterable )](https://tc39.es/ecma262/#sec-promise.allsettled)
@@ -353,112 +254,15 @@ impl PromiseConstructor {
353254
agent: &mut Agent,
354255
this_value: Value,
355256
arguments: ArgumentsList,
356-
mut gc: GcScope<'gc, '_>,
257+
gc: GcScope<'gc, '_>,
357258
) -> JsResult<'gc, Value<'gc>> {
358-
let this_value = this_value.bind(gc.nogc());
359-
let arguments = arguments.bind(gc.nogc());
360-
let iterable = arguments.get(0).scope(agent, gc.nogc());
361-
362-
// 1. Let C be the this value.
363-
if this_value
364-
!= agent
365-
.current_realm_record()
366-
.intrinsics()
367-
.promise()
368-
.into_value()
369-
{
370-
return Err(throw_promise_subclassing_not_supported(
371-
agent,
372-
gc.into_nogc(),
373-
));
374-
}
375-
376-
// 2. Let promiseCapability be ? NewPromiseCapability(C).
377-
let Some(constructor) = is_constructor(agent, this_value) else {
378-
return Err(agent.throw_exception_with_static_message(
379-
ExceptionType::TypeError,
380-
"Expected the this value to be a constructor.",
381-
gc.into_nogc(),
382-
));
383-
};
384-
let constructor = constructor.scope(agent, gc.nogc());
385-
let promise_capability = PromiseCapability::new(agent, gc.nogc());
386-
let promise = promise_capability.promise().scope(agent, gc.nogc());
387-
388-
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
389-
let promise_resolve = get_promise_resolve(agent, constructor.get(agent), gc.reborrow())
390-
.unbind()
391-
.bind(gc.nogc());
392-
393-
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
394-
let promise_capability = PromiseCapability {
395-
promise: promise.get(agent).bind(gc.nogc()),
396-
must_be_unresolved: true,
397-
};
398-
let promise_resolve =
399-
if_abrupt_reject_promise_m!(agent, promise_resolve, promise_capability, gc);
400-
let promise_resolve = promise_resolve.scope(agent, gc.nogc());
401-
402-
// 5. Let iteratorRecord be Completion(GetIterator(iterable, sync)).
403-
let iterator_record = get_iterator(agent, iterable.get(agent), false, gc.reborrow())
404-
.unbind()
405-
.bind(gc.nogc());
406-
407-
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
408-
let promise_capability = PromiseCapability {
409-
promise: promise.get(agent).bind(gc.nogc()),
410-
must_be_unresolved: true,
411-
};
412-
let MaybeInvalidIteratorRecord {
413-
iterator,
414-
next_method,
415-
} = if_abrupt_reject_promise_m!(agent, iterator_record, promise_capability, gc);
416-
417-
let iterator = iterator.scope(agent, gc.nogc());
418-
419-
// 7. Let result be Completion(PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve)).
420-
let mut iterator_done = false;
421-
let result = perform_promise_group(
259+
promise_group(
422260
agent,
423-
iterator.clone(),
424-
next_method.unbind(),
425-
constructor,
426-
promise_capability.unbind(),
427-
promise_resolve,
428-
&mut iterator_done,
261+
this_value,
262+
arguments,
429263
PromiseGroupType::PromiseAllSettled,
430-
gc.reborrow(),
264+
gc,
431265
)
432-
.unbind()
433-
.bind(gc.nogc());
434-
435-
// 8. If result is an abrupt completion, then
436-
let result = match result {
437-
Err(mut result) => {
438-
// a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
439-
if !iterator_done {
440-
result = iterator_close_with_error(
441-
agent,
442-
iterator.get(agent),
443-
result.unbind(),
444-
gc.reborrow(),
445-
)
446-
.unbind()
447-
.bind(gc.nogc());
448-
}
449-
450-
// b. IfAbruptRejectPromise(result, promiseCapability).
451-
let promise_capability = PromiseCapability {
452-
promise: promise.get(agent).bind(gc.nogc()),
453-
must_be_unresolved: true,
454-
};
455-
promise_capability.reject(agent, result.value().unbind(), gc.nogc());
456-
promise_capability.promise()
457-
}
458-
Ok(result) => result,
459-
};
460-
// 9. Return ! result.
461-
Ok(result.into_value().unbind())
462266
}
463267

464268
/// ### [27.2.4.3 Promise.any ( iterable )](https://tc39.es/ecma262/#sec-promise.any)
@@ -764,6 +568,121 @@ fn get_promise_resolve<'gc>(
764568
Ok(promise_resolve.unbind())
765569
}
766570

571+
fn promise_group<'gc>(
572+
agent: &mut Agent,
573+
this_value: Value,
574+
arguments: ArgumentsList,
575+
promise_group_type: PromiseGroupType,
576+
mut gc: GcScope<'gc, '_>,
577+
) -> JsResult<'gc, Value<'gc>> {
578+
let this_value = this_value.bind(gc.nogc());
579+
let arguments = arguments.bind(gc.nogc());
580+
let iterable = arguments.get(0).scope(agent, gc.nogc());
581+
582+
// 1. Let C be the this value.
583+
if this_value
584+
!= agent
585+
.current_realm_record()
586+
.intrinsics()
587+
.promise()
588+
.into_value()
589+
{
590+
return Err(throw_promise_subclassing_not_supported(
591+
agent,
592+
gc.into_nogc(),
593+
));
594+
}
595+
596+
// 2. Let promiseCapability be ? NewPromiseCapability(C).
597+
let Some(constructor) = is_constructor(agent, this_value) else {
598+
return Err(agent.throw_exception_with_static_message(
599+
ExceptionType::TypeError,
600+
"Expected the this value to be a constructor.",
601+
gc.into_nogc(),
602+
));
603+
};
604+
let constructor = constructor.scope(agent, gc.nogc());
605+
let promise_capability = PromiseCapability::new(agent, gc.nogc());
606+
let promise = promise_capability.promise().scope(agent, gc.nogc());
607+
608+
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
609+
let promise_resolve = get_promise_resolve(agent, constructor.get(agent), gc.reborrow())
610+
.unbind()
611+
.bind(gc.nogc());
612+
613+
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
614+
let promise_capability = PromiseCapability {
615+
promise: promise.get(agent).bind(gc.nogc()),
616+
must_be_unresolved: true,
617+
};
618+
let promise_resolve =
619+
if_abrupt_reject_promise_m!(agent, promise_resolve, promise_capability, gc);
620+
let promise_resolve = promise_resolve.scope(agent, gc.nogc());
621+
622+
// 5. Let iteratorRecord be Completion(GetIterator(iterable, sync)).
623+
let iterator_record = get_iterator(agent, iterable.get(agent), false, gc.reborrow())
624+
.unbind()
625+
.bind(gc.nogc());
626+
627+
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
628+
let promise_capability = PromiseCapability {
629+
promise: promise.get(agent).bind(gc.nogc()),
630+
must_be_unresolved: true,
631+
};
632+
let MaybeInvalidIteratorRecord {
633+
iterator,
634+
next_method,
635+
} = if_abrupt_reject_promise_m!(agent, iterator_record, promise_capability, gc);
636+
637+
let iterator = iterator.scope(agent, gc.nogc());
638+
639+
// 7. Let result be Completion(PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve)).
640+
let mut iterator_done = false;
641+
let result = perform_promise_group(
642+
agent,
643+
iterator.clone(),
644+
next_method.unbind(),
645+
constructor,
646+
promise_capability.unbind(),
647+
promise_resolve,
648+
&mut iterator_done,
649+
promise_group_type,
650+
gc.reborrow(),
651+
)
652+
.unbind()
653+
.bind(gc.nogc());
654+
655+
// 8. If result is an abrupt completion, then
656+
let result = match result {
657+
Err(mut result) => {
658+
// a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
659+
if !iterator_done {
660+
result = iterator_close_with_error(
661+
agent,
662+
iterator.get(agent),
663+
result.unbind(),
664+
gc.reborrow(),
665+
)
666+
.unbind()
667+
.bind(gc.nogc());
668+
}
669+
670+
// b. IfAbruptRejectPromise(result, promiseCapability).
671+
let promise_capability = PromiseCapability {
672+
promise: promise.get(agent).bind(gc.nogc()),
673+
must_be_unresolved: true,
674+
};
675+
// a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
676+
promise_capability.reject(agent, result.value().unbind(), gc.nogc());
677+
// b. Return capability.[[Promise]].
678+
promise_capability.promise()
679+
}
680+
Ok(result) => result,
681+
};
682+
// 9. Return ! result.
683+
Ok(result.into_value().unbind())
684+
}
685+
767686
/// ### [27.2.4.1.2 PerformPromiseAll ( iteratorRecord, constructor, resultCapability, promiseResolve )](https://tc39.es/ecma262/#sec-performpromiseall)
768687
/// ### [27.2.4.2.1 PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability, promiseResolve )](https://tc39.es/ecma262/#sec-performpromiseallsettled)
769688
#[allow(clippy::too_many_arguments)]

0 commit comments

Comments
 (0)