mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-09 04:37:52 +03:00
LibJS: Replace GlobalObject with VM in Promise AOs [Part 8/19]
This commit is contained in:
parent
ccdfa2320c
commit
d74f8039eb
Notes:
sideshowbarker
2024-07-17 08:00:27 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/d74f8039eb Pull-request: https://github.com/SerenityOS/serenity/pull/14973 Reviewed-by: https://github.com/davidot ✅
@ -3359,11 +3359,11 @@ Completion ImportCall::execute(Interpreter& interpreter) const
|
||||
// Note: options_value is undefined by default.
|
||||
|
||||
// 6. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
||||
auto promise_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
||||
auto promise_capability = MUST(new_promise_capability(vm, global_object.promise_constructor()));
|
||||
|
||||
// 7. Let specifierString be Completion(ToString(specifier)).
|
||||
// 8. IfAbruptRejectPromise(specifierString, promiseCapability).
|
||||
auto specifier_string = TRY_OR_REJECT_WITH_VALUE(global_object, promise_capability, specifier->to_string(vm));
|
||||
auto specifier_string = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, specifier->to_string(vm));
|
||||
|
||||
// 9. Let assertions be a new empty List.
|
||||
Vector<ModuleRequest::Assertion> assertions;
|
||||
@ -3382,7 +3382,7 @@ Completion ImportCall::execute(Interpreter& interpreter) const
|
||||
|
||||
// b. Let assertionsObj be Get(options, "assert").
|
||||
// c. IfAbruptRejectPromise(assertionsObj, promiseCapability).
|
||||
auto assertion_object = TRY_OR_REJECT_WITH_VALUE(global_object, promise_capability, options_value.get(vm, vm.names.assert));
|
||||
auto assertion_object = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, options_value.get(vm, vm.names.assert));
|
||||
|
||||
// d. If assertionsObj is not undefined,
|
||||
if (!assertion_object.is_undefined()) {
|
||||
@ -3398,10 +3398,10 @@ Completion ImportCall::execute(Interpreter& interpreter) const
|
||||
|
||||
// ii. Let keys be EnumerableOwnPropertyNames(assertionsObj, key).
|
||||
// iii. IfAbruptRejectPromise(keys, promiseCapability).
|
||||
auto keys = TRY_OR_REJECT_WITH_VALUE(global_object, promise_capability, assertion_object.as_object().enumerable_own_property_names(Object::PropertyKind::Key));
|
||||
auto keys = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, assertion_object.as_object().enumerable_own_property_names(Object::PropertyKind::Key));
|
||||
|
||||
// iv. Let supportedAssertions be ! HostGetSupportedImportAssertions().
|
||||
auto supported_assertions = interpreter.vm().host_get_supported_import_assertions();
|
||||
auto supported_assertions = vm.host_get_supported_import_assertions();
|
||||
|
||||
// v. For each String key of keys,
|
||||
for (auto const& key : keys) {
|
||||
@ -3409,7 +3409,7 @@ Completion ImportCall::execute(Interpreter& interpreter) const
|
||||
|
||||
// 1. Let value be Get(assertionsObj, key).
|
||||
// 2. IfAbruptRejectPromise(value, promiseCapability).
|
||||
auto value = TRY_OR_REJECT_WITH_VALUE(global_object, promise_capability, assertion_object.get(vm, property_key));
|
||||
auto value = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, assertion_object.get(vm, property_key));
|
||||
|
||||
// 3. If Type(value) is not String, then
|
||||
if (!value.is_string()) {
|
||||
|
@ -201,7 +201,7 @@ ThrowCompletionOr<Promise*> CyclicModule::evaluate(VM& vm)
|
||||
|
||||
// 6. Let capability be ! NewPromiseCapability(%Promise%).
|
||||
// 7. Set module.[[TopLevelCapability]] to capability.
|
||||
m_top_level_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
||||
m_top_level_capability = MUST(new_promise_capability(vm, global_object.promise_constructor()));
|
||||
|
||||
// 8. Let result be Completion(InnerModuleEvaluation(module, stack, 0)).
|
||||
auto result = inner_module_evaluation(vm, stack, 0);
|
||||
@ -443,7 +443,7 @@ void CyclicModule::execute_async_module(VM& vm)
|
||||
VERIFY(m_has_top_level_await);
|
||||
|
||||
// 3. Let capability be ! NewPromiseCapability(%Promise%).
|
||||
auto capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
||||
auto capability = MUST(new_promise_capability(vm, global_object.promise_constructor()));
|
||||
|
||||
// 4. Let fulfilledClosure be a new Abstract Closure with no parameters that captures module and performs the following steps when called:
|
||||
auto fulfilled_closure = [&](VM& vm, GlobalObject&) -> ThrowCompletionOr<Value> {
|
||||
|
@ -39,15 +39,15 @@ static Object* async_from_sync_iterator_continuation(VM& vm, Object& result, Pro
|
||||
// 1. NOTE: Because promiseCapability is derived from the intrinsic %Promise%, the calls to promiseCapability.[[Reject]] entailed by the use IfAbruptRejectPromise below are guaranteed not to throw.
|
||||
// 2. Let done be Completion(IteratorComplete(result)).
|
||||
// 3. IfAbruptRejectPromise(done, promiseCapability).
|
||||
auto done = TRY_OR_MUST_REJECT(global_object, promise_capability, iterator_complete(vm, result));
|
||||
auto done = TRY_OR_MUST_REJECT(vm, promise_capability, iterator_complete(vm, result));
|
||||
|
||||
// 4. Let value be Completion(IteratorValue(result)).
|
||||
// 5. IfAbruptRejectPromise(value, promiseCapability).
|
||||
auto value = TRY_OR_MUST_REJECT(global_object, promise_capability, iterator_value(vm, result));
|
||||
auto value = TRY_OR_MUST_REJECT(vm, promise_capability, iterator_value(vm, result));
|
||||
|
||||
// 6. Let valueWrapper be PromiseResolve(%Promise%, value).
|
||||
// 7. IfAbruptRejectPromise(valueWrapper, promiseCapability).
|
||||
auto value_wrapper = TRY_OR_MUST_REJECT(global_object, promise_capability, promise_resolve(global_object, *global_object.promise_constructor(), value));
|
||||
auto value_wrapper = TRY_OR_MUST_REJECT(vm, promise_capability, promise_resolve(vm, *global_object.promise_constructor(), value));
|
||||
|
||||
// 8. Let unwrap be a new Abstract Closure with parameters (value) that captures done and performs the following steps when called:
|
||||
auto unwrap = [done](VM& vm, GlobalObject&) -> ThrowCompletionOr<Value> {
|
||||
@ -74,7 +74,7 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::next)
|
||||
auto* this_object = MUST(typed_this_object(vm));
|
||||
|
||||
// 3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
||||
auto promise_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
||||
auto promise_capability = MUST(new_promise_capability(vm, global_object.promise_constructor()));
|
||||
|
||||
// 4. Let syncIteratorRecord be O.[[SyncIteratorRecord]].
|
||||
auto& sync_iterator_record = this_object->sync_iterator_record();
|
||||
@ -84,7 +84,7 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::next)
|
||||
// 6. Else,
|
||||
// a. Let result be Completion(IteratorNext(syncIteratorRecord)).
|
||||
// 7. IfAbruptRejectPromise(result, promiseCapability).
|
||||
auto* result = TRY_OR_REJECT(global_object, promise_capability,
|
||||
auto* result = TRY_OR_REJECT(vm, promise_capability,
|
||||
(vm.argument_count() > 0 ? iterator_next(vm, sync_iterator_record, vm.argument(0))
|
||||
: iterator_next(vm, sync_iterator_record)));
|
||||
|
||||
@ -102,14 +102,14 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::return_)
|
||||
auto* this_object = MUST(typed_this_object(vm));
|
||||
|
||||
// 3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
||||
auto promise_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
||||
auto promise_capability = MUST(new_promise_capability(vm, global_object.promise_constructor()));
|
||||
|
||||
// 4. Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
|
||||
auto* sync_iterator = this_object->sync_iterator_record().iterator;
|
||||
|
||||
// 5. Let return be Completion(GetMethod(syncIterator, "return")).
|
||||
// 6. IfAbruptRejectPromise(return, promiseCapability).
|
||||
auto* return_method = TRY_OR_REJECT(global_object, promise_capability, Value(sync_iterator).get_method(vm, vm.names.return_));
|
||||
auto* return_method = TRY_OR_REJECT(vm, promise_capability, Value(sync_iterator).get_method(vm, vm.names.return_));
|
||||
|
||||
// 7. If return is undefined, then
|
||||
if (return_method == nullptr) {
|
||||
@ -128,7 +128,7 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::return_)
|
||||
// 9. Else,
|
||||
// a. Let result be Completion(Call(return, syncIterator)).
|
||||
// 10. IfAbruptRejectPromise(result, promiseCapability).
|
||||
auto result = TRY_OR_REJECT(global_object, promise_capability,
|
||||
auto result = TRY_OR_REJECT(vm, promise_capability,
|
||||
(vm.argument_count() > 0 ? call(global_object, return_method, sync_iterator, vm.argument(0))
|
||||
: call(global_object, return_method, sync_iterator)));
|
||||
|
||||
@ -155,14 +155,14 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::throw_)
|
||||
auto* this_object = MUST(typed_this_object(vm));
|
||||
|
||||
// 3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
||||
auto promise_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
||||
auto promise_capability = MUST(new_promise_capability(vm, global_object.promise_constructor()));
|
||||
|
||||
// 4. Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
|
||||
auto* sync_iterator = this_object->sync_iterator_record().iterator;
|
||||
|
||||
// 5. Let throw be Completion(GetMethod(syncIterator, "throw")).
|
||||
// 6. IfAbruptRejectPromise(throw, promiseCapability).
|
||||
auto* throw_method = TRY_OR_REJECT(global_object, promise_capability, Value(sync_iterator).get_method(vm, vm.names.throw_));
|
||||
auto* throw_method = TRY_OR_REJECT(vm, promise_capability, Value(sync_iterator).get_method(vm, vm.names.throw_));
|
||||
|
||||
// 7. If throw is undefined, then
|
||||
if (throw_method == nullptr) {
|
||||
@ -176,7 +176,7 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::throw_)
|
||||
// 9. Else,
|
||||
// a. Let result be Completion(Call(throw, syncIterator)).
|
||||
// 10. IfAbruptRejectPromise(result, promiseCapability).
|
||||
auto result = TRY_OR_REJECT(global_object, promise_capability,
|
||||
auto result = TRY_OR_REJECT(vm, promise_capability,
|
||||
(vm.argument_count() > 0 ? call(global_object, throw_method, sync_iterator, vm.argument(0))
|
||||
: call(global_object, throw_method, sync_iterator)));
|
||||
|
||||
|
@ -38,7 +38,7 @@ ThrowCompletionOr<Value> await(GlobalObject& global_object, Value value)
|
||||
// NOTE: This is not needed, as we don't suspend anything.
|
||||
|
||||
// 2. Let promise be ? PromiseResolve(%Promise%, value).
|
||||
auto* promise_object = TRY(promise_resolve(global_object, *global_object.promise_constructor(), value));
|
||||
auto* promise_object = TRY(promise_resolve(vm, *global_object.promise_constructor(), value));
|
||||
|
||||
Optional<bool> success;
|
||||
Value result;
|
||||
|
@ -867,7 +867,7 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
||||
// AsyncFunctionBody : FunctionBody
|
||||
else if (m_kind == FunctionKind::Async) {
|
||||
// 1. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
||||
auto promise_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
||||
auto promise_capability = MUST(new_promise_capability(vm, global_object.promise_constructor()));
|
||||
|
||||
// 2. Let declResult be Completion(FunctionDeclarationInstantiation(functionObject, argumentsList)).
|
||||
auto declaration_result = function_declaration_instantiation(ast_interpreter);
|
||||
|
@ -53,7 +53,6 @@ void FinalizationRegistry::remove_dead_cells(Badge<Heap>)
|
||||
ThrowCompletionOr<void> FinalizationRegistry::cleanup(Optional<JobCallback> callback)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 1. Assert: finalizationRegistry has [[Cells]] and [[CleanupCallback]] internal slots.
|
||||
// Note: Ensured by type.
|
||||
@ -73,7 +72,7 @@ ThrowCompletionOr<void> FinalizationRegistry::cleanup(Optional<JobCallback> call
|
||||
it.remove(m_records);
|
||||
|
||||
// c. Perform ? HostCallJobCallback(callback, undefined, « cell.[[HeldValue]] »).
|
||||
TRY(vm.host_call_job_callback(global_object, cleanup_callback, js_undefined(), move(arguments)));
|
||||
TRY(vm.host_call_job_callback(cleanup_callback, js_undefined(), move(arguments)));
|
||||
}
|
||||
|
||||
// 4. Return unused.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
@ -30,8 +30,11 @@ inline JobCallback make_job_callback(FunctionObject& callback)
|
||||
}
|
||||
|
||||
// 9.5.3 HostCallJobCallback ( jobCallback, V, argumentsList ), https://tc39.es/ecma262/#sec-hostcalljobcallback
|
||||
inline ThrowCompletionOr<Value> call_job_callback(GlobalObject& global_object, JobCallback& job_callback, Value this_value, MarkedVector<Value> arguments_list)
|
||||
inline ThrowCompletionOr<Value> call_job_callback(VM& vm, JobCallback& job_callback, Value this_value, MarkedVector<Value> arguments_list)
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
// 1. Assert: IsCallable(jobCallback.[[Callback]]) is true.
|
||||
VERIFY(!job_callback.callback.is_null());
|
||||
|
||||
|
@ -19,9 +19,10 @@
|
||||
namespace JS {
|
||||
|
||||
// 27.2.4.7.1 PromiseResolve ( C, x ), https://tc39.es/ecma262/#sec-promise-resolve
|
||||
ThrowCompletionOr<Object*> promise_resolve(GlobalObject& global_object, Object& constructor, Value value)
|
||||
ThrowCompletionOr<Object*> promise_resolve(VM& vm, Object& constructor, Value value)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
// 1. If IsPromise(x) is true, then
|
||||
if (value.is_object() && is<Promise>(value.as_object())) {
|
||||
@ -34,7 +35,7 @@ ThrowCompletionOr<Object*> promise_resolve(GlobalObject& global_object, Object&
|
||||
}
|
||||
|
||||
// 2. Let promiseCapability be ? NewPromiseCapability(C).
|
||||
auto promise_capability = TRY(new_promise_capability(global_object, &constructor));
|
||||
auto promise_capability = TRY(new_promise_capability(vm, &constructor));
|
||||
|
||||
// 3. Perform ? Call(promiseCapability.[[Resolve]], undefined, « x »).
|
||||
(void)TRY(call(global_object, *promise_capability.resolve, js_undefined(), value));
|
||||
@ -150,7 +151,7 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
|
||||
|
||||
// 14. Let job be NewPromiseResolveThenableJob(promise, resolution, thenJobCallback).
|
||||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Creating PromiseResolveThenableJob for thenable {}", &promise, resolution);
|
||||
auto job = create_promise_resolve_thenable_job(global_object, promise, resolution, move(then_job_callback));
|
||||
auto job = create_promise_resolve_thenable_job(vm, promise, resolution, move(then_job_callback));
|
||||
|
||||
// 15. Perform HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]).
|
||||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Enqueuing job @ {} in realm {}", &promise, &job.job, job.realm);
|
||||
@ -274,7 +275,7 @@ void Promise::trigger_reactions() const
|
||||
for (auto& reaction : reactions) {
|
||||
// a. Let job be NewPromiseReactionJob(reaction, argument).
|
||||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / trigger_reactions()]: Creating PromiseReactionJob for PromiseReaction @ {} with argument {}", this, &reaction, m_result);
|
||||
auto [job, realm] = create_promise_reaction_job(global_object(), *reaction, m_result);
|
||||
auto [job, realm] = create_promise_reaction_job(vm, *reaction, m_result);
|
||||
|
||||
// b. Perform HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]).
|
||||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / trigger_reactions()]: Enqueuing job @ {} in realm {}", this, &job, realm);
|
||||
@ -344,7 +345,7 @@ Value Promise::perform_then(Value on_fulfilled, Value on_rejected, Optional<Prom
|
||||
|
||||
// b. Let fulfillJob be NewPromiseReactionJob(fulfillReaction, value).
|
||||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / perform_then()]: State is State::Fulfilled, creating PromiseReactionJob for PromiseReaction @ {} with argument {}", this, fulfill_reaction, value);
|
||||
auto [fulfill_job, realm] = create_promise_reaction_job(global_object(), *fulfill_reaction, value);
|
||||
auto [fulfill_job, realm] = create_promise_reaction_job(vm, *fulfill_reaction, value);
|
||||
|
||||
// c. Perform HostEnqueuePromiseJob(fulfillJob.[[Job]], fulfillJob.[[Realm]]).
|
||||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / perform_then()]: Enqueuing job @ {} in realm {}", this, &fulfill_job, realm);
|
||||
@ -364,7 +365,7 @@ Value Promise::perform_then(Value on_fulfilled, Value on_rejected, Optional<Prom
|
||||
|
||||
// d. Let rejectJob be NewPromiseReactionJob(rejectReaction, reason).
|
||||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / perform_then()]: State is State::Rejected, creating PromiseReactionJob for PromiseReaction @ {} with argument {}", this, reject_reaction, reason);
|
||||
auto [reject_job, realm] = create_promise_reaction_job(global_object(), *reject_reaction, reason);
|
||||
auto [reject_job, realm] = create_promise_reaction_job(vm, *reject_reaction, reason);
|
||||
|
||||
// e. Perform HostEnqueuePromiseJob(rejectJob.[[Job]], rejectJob.[[Realm]]).
|
||||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / perform_then()]: Enqueuing job @ {} in realm {}", this, &reject_job, realm);
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace JS {
|
||||
|
||||
ThrowCompletionOr<Object*> promise_resolve(GlobalObject&, Object& constructor, Value);
|
||||
ThrowCompletionOr<Object*> promise_resolve(VM&, Object& constructor, Value);
|
||||
|
||||
class Promise : public Object {
|
||||
JS_OBJECT(Promise, Object);
|
||||
|
@ -21,10 +21,9 @@
|
||||
namespace JS {
|
||||
|
||||
// 27.2.4.1.1 GetPromiseResolve ( promiseConstructor ), https://tc39.es/ecma262/#sec-getpromiseresolve
|
||||
static ThrowCompletionOr<Value> get_promise_resolve(GlobalObject& global_object, Value constructor)
|
||||
static ThrowCompletionOr<Value> get_promise_resolve(VM& vm, Value constructor)
|
||||
{
|
||||
VERIFY(constructor.is_constructor());
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
// 1. Let promiseResolve be ? Get(promiseConstructor, "resolve").
|
||||
auto promise_resolve = TRY(constructor.get(vm, vm.names.resolve));
|
||||
@ -40,9 +39,10 @@ static ThrowCompletionOr<Value> get_promise_resolve(GlobalObject& global_object,
|
||||
using EndOfElementsCallback = Function<ThrowCompletionOr<Value>(PromiseValueList&)>;
|
||||
using InvokeElementFunctionCallback = Function<ThrowCompletionOr<Value>(PromiseValueList&, RemainingElements&, Value, size_t)>;
|
||||
|
||||
static ThrowCompletionOr<Value> perform_promise_common(GlobalObject& global_object, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve, EndOfElementsCallback end_of_list, InvokeElementFunctionCallback invoke_element_function)
|
||||
static ThrowCompletionOr<Value> perform_promise_common(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve, EndOfElementsCallback end_of_list, InvokeElementFunctionCallback invoke_element_function)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
VERIFY(constructor.is_constructor());
|
||||
VERIFY(promise_resolve.is_function());
|
||||
@ -116,13 +116,13 @@ static ThrowCompletionOr<Value> perform_promise_common(GlobalObject& global_obje
|
||||
}
|
||||
|
||||
// 27.2.4.1.2 PerformPromiseAll ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiseall
|
||||
static ThrowCompletionOr<Value> perform_promise_all(GlobalObject& global_object, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve)
|
||||
static ThrowCompletionOr<Value> perform_promise_all(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *global_object.associated_realm();
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
return perform_promise_common(
|
||||
global_object, iterator_record, constructor, result_capability, promise_resolve,
|
||||
vm, iterator_record, constructor, result_capability, promise_resolve,
|
||||
[&](PromiseValueList& values) -> ThrowCompletionOr<Value> {
|
||||
// 1. Let valuesArray be CreateArrayFromList(values).
|
||||
auto* values_array = Array::create_from(realm, values.values());
|
||||
@ -151,13 +151,13 @@ static ThrowCompletionOr<Value> perform_promise_all(GlobalObject& global_object,
|
||||
}
|
||||
|
||||
// 27.2.4.2.1 PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiseallsettled
|
||||
static ThrowCompletionOr<Value> perform_promise_all_settled(GlobalObject& global_object, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve)
|
||||
static ThrowCompletionOr<Value> perform_promise_all_settled(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *global_object.associated_realm();
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
return perform_promise_common(
|
||||
global_object, iterator_record, constructor, result_capability, promise_resolve,
|
||||
vm, iterator_record, constructor, result_capability, promise_resolve,
|
||||
[&](PromiseValueList& values) -> ThrowCompletionOr<Value> {
|
||||
auto* values_array = Array::create_from(realm, values.values());
|
||||
|
||||
@ -195,13 +195,12 @@ static ThrowCompletionOr<Value> perform_promise_all_settled(GlobalObject& global
|
||||
}
|
||||
|
||||
// 27.2.4.3.1 PerformPromiseAny ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiseany
|
||||
static ThrowCompletionOr<Value> perform_promise_any(GlobalObject& global_object, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve)
|
||||
static ThrowCompletionOr<Value> perform_promise_any(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *global_object.associated_realm();
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
return perform_promise_common(
|
||||
global_object, iterator_record, constructor, result_capability, promise_resolve,
|
||||
vm, iterator_record, constructor, result_capability, promise_resolve,
|
||||
[&](PromiseValueList& errors) -> ThrowCompletionOr<Value> {
|
||||
// 1. Let error be a newly created AggregateError object.
|
||||
auto* error = AggregateError::create(realm);
|
||||
@ -231,12 +230,10 @@ static ThrowCompletionOr<Value> perform_promise_any(GlobalObject& global_object,
|
||||
}
|
||||
|
||||
// 27.2.4.5.1 PerformPromiseRace ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiserace
|
||||
static ThrowCompletionOr<Value> perform_promise_race(GlobalObject& global_object, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve)
|
||||
static ThrowCompletionOr<Value> perform_promise_race(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
return perform_promise_common(
|
||||
global_object, iterator_record, constructor, result_capability, promise_resolve,
|
||||
vm, iterator_record, constructor, result_capability, promise_resolve,
|
||||
[&](PromiseValueList&) -> ThrowCompletionOr<Value> {
|
||||
// ii. Return resultCapability.[[Promise]].
|
||||
return Value(result_capability.promise);
|
||||
@ -324,18 +321,18 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all)
|
||||
auto* constructor = TRY(vm.this_value().to_object(vm));
|
||||
|
||||
// 2. Let promiseCapability be ? NewPromiseCapability(C).
|
||||
auto promise_capability = TRY(new_promise_capability(global_object, constructor));
|
||||
auto promise_capability = TRY(new_promise_capability(vm, constructor));
|
||||
|
||||
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
|
||||
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
|
||||
auto promise_resolve = TRY_OR_REJECT(global_object, promise_capability, get_promise_resolve(global_object, constructor));
|
||||
auto promise_resolve = TRY_OR_REJECT(vm, promise_capability, get_promise_resolve(vm, constructor));
|
||||
|
||||
// 5. Let iteratorRecord be Completion(GetIterator(iterable)).
|
||||
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
|
||||
auto iterator_record = TRY_OR_REJECT(global_object, promise_capability, get_iterator(vm, vm.argument(0)));
|
||||
auto iterator_record = TRY_OR_REJECT(vm, promise_capability, get_iterator(vm, vm.argument(0)));
|
||||
|
||||
// 7. Let result be Completion(PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve)).
|
||||
auto result = perform_promise_all(global_object, iterator_record, constructor, promise_capability, promise_resolve);
|
||||
auto result = perform_promise_all(vm, iterator_record, constructor, promise_capability, promise_resolve);
|
||||
|
||||
// 8. If result is an abrupt completion, then
|
||||
if (result.is_error()) {
|
||||
@ -344,7 +341,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all)
|
||||
result = iterator_close(vm, iterator_record, result.release_error());
|
||||
|
||||
// b. IfAbruptRejectPromise(result, promiseCapability).
|
||||
TRY_OR_REJECT(global_object, promise_capability, result);
|
||||
TRY_OR_REJECT(vm, promise_capability, result);
|
||||
}
|
||||
|
||||
// 9. Return ? result.
|
||||
@ -358,18 +355,18 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all_settled)
|
||||
auto* constructor = TRY(vm.this_value().to_object(vm));
|
||||
|
||||
// 2. Let promiseCapability be ? NewPromiseCapability(C).
|
||||
auto promise_capability = TRY(new_promise_capability(global_object, constructor));
|
||||
auto promise_capability = TRY(new_promise_capability(vm, constructor));
|
||||
|
||||
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
|
||||
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
|
||||
auto promise_resolve = TRY_OR_REJECT(global_object, promise_capability, get_promise_resolve(global_object, constructor));
|
||||
auto promise_resolve = TRY_OR_REJECT(vm, promise_capability, get_promise_resolve(vm, constructor));
|
||||
|
||||
// 5. Let iteratorRecord be Completion(GetIterator(iterable)).
|
||||
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
|
||||
auto iterator_record = TRY_OR_REJECT(global_object, promise_capability, get_iterator(vm, vm.argument(0)));
|
||||
auto iterator_record = TRY_OR_REJECT(vm, promise_capability, get_iterator(vm, vm.argument(0)));
|
||||
|
||||
// 7. Let result be Completion(PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve)).
|
||||
auto result = perform_promise_all_settled(global_object, iterator_record, constructor, promise_capability, promise_resolve);
|
||||
auto result = perform_promise_all_settled(vm, iterator_record, constructor, promise_capability, promise_resolve);
|
||||
|
||||
// 8. If result is an abrupt completion, then
|
||||
if (result.is_error()) {
|
||||
@ -378,7 +375,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all_settled)
|
||||
result = iterator_close(vm, iterator_record, result.release_error());
|
||||
|
||||
// b. IfAbruptRejectPromise(result, promiseCapability).
|
||||
TRY_OR_REJECT(global_object, promise_capability, result);
|
||||
TRY_OR_REJECT(vm, promise_capability, result);
|
||||
}
|
||||
|
||||
// 9. Return ? result.
|
||||
@ -392,18 +389,18 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::any)
|
||||
auto* constructor = TRY(vm.this_value().to_object(vm));
|
||||
|
||||
// 2. Let promiseCapability be ? NewPromiseCapability(C).
|
||||
auto promise_capability = TRY(new_promise_capability(global_object, constructor));
|
||||
auto promise_capability = TRY(new_promise_capability(vm, constructor));
|
||||
|
||||
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
|
||||
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
|
||||
auto promise_resolve = TRY_OR_REJECT(global_object, promise_capability, get_promise_resolve(global_object, constructor));
|
||||
auto promise_resolve = TRY_OR_REJECT(vm, promise_capability, get_promise_resolve(vm, constructor));
|
||||
|
||||
// 5. Let iteratorRecord be Completion(GetIterator(iterable)).
|
||||
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
|
||||
auto iterator_record = TRY_OR_REJECT(global_object, promise_capability, get_iterator(vm, vm.argument(0)));
|
||||
auto iterator_record = TRY_OR_REJECT(vm, promise_capability, get_iterator(vm, vm.argument(0)));
|
||||
|
||||
// 7. Let result be Completion(PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve)).
|
||||
auto result = perform_promise_any(global_object, iterator_record, constructor, promise_capability, promise_resolve);
|
||||
auto result = perform_promise_any(vm, iterator_record, constructor, promise_capability, promise_resolve);
|
||||
|
||||
// 8. If result is an abrupt completion, then
|
||||
if (result.is_error()) {
|
||||
@ -412,7 +409,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::any)
|
||||
result = iterator_close(vm, iterator_record, result.release_error());
|
||||
|
||||
// b. IfAbruptRejectPromise(result, promiseCapability).
|
||||
TRY_OR_REJECT(global_object, promise_capability, result);
|
||||
TRY_OR_REJECT(vm, promise_capability, result);
|
||||
}
|
||||
|
||||
// 9. Return ? result.
|
||||
@ -426,18 +423,18 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::race)
|
||||
auto* constructor = TRY(vm.this_value().to_object(vm));
|
||||
|
||||
// 2. Let promiseCapability be ? NewPromiseCapability(C).
|
||||
auto promise_capability = TRY(new_promise_capability(global_object, constructor));
|
||||
auto promise_capability = TRY(new_promise_capability(vm, constructor));
|
||||
|
||||
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
|
||||
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
|
||||
auto promise_resolve = TRY_OR_REJECT(global_object, promise_capability, get_promise_resolve(global_object, constructor));
|
||||
auto promise_resolve = TRY_OR_REJECT(vm, promise_capability, get_promise_resolve(vm, constructor));
|
||||
|
||||
// 5. Let iteratorRecord be Completion(GetIterator(iterable)).
|
||||
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
|
||||
auto iterator_record = TRY_OR_REJECT(global_object, promise_capability, get_iterator(vm, vm.argument(0)));
|
||||
auto iterator_record = TRY_OR_REJECT(vm, promise_capability, get_iterator(vm, vm.argument(0)));
|
||||
|
||||
// 7. Let result be Completion(PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve)).
|
||||
auto result = perform_promise_race(global_object, iterator_record, constructor, promise_capability, promise_resolve);
|
||||
auto result = perform_promise_race(vm, iterator_record, constructor, promise_capability, promise_resolve);
|
||||
|
||||
// 8. If result is an abrupt completion, then
|
||||
if (result.is_error()) {
|
||||
@ -446,7 +443,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::race)
|
||||
result = iterator_close(vm, iterator_record, result.release_error());
|
||||
|
||||
// b. IfAbruptRejectPromise(result, promiseCapability).
|
||||
TRY_OR_REJECT(global_object, promise_capability, result);
|
||||
TRY_OR_REJECT(vm, promise_capability, result);
|
||||
}
|
||||
|
||||
// 9. Return ? result.
|
||||
@ -462,7 +459,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::reject)
|
||||
auto* constructor = TRY(vm.this_value().to_object(vm));
|
||||
|
||||
// 2. Let promiseCapability be ? NewPromiseCapability(C).
|
||||
auto promise_capability = TRY(new_promise_capability(global_object, constructor));
|
||||
auto promise_capability = TRY(new_promise_capability(vm, constructor));
|
||||
|
||||
// 3. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »).
|
||||
[[maybe_unused]] auto result = TRY(JS::call(global_object, *promise_capability.reject, js_undefined(), reason));
|
||||
@ -484,7 +481,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::resolve)
|
||||
return vm.throw_completion<TypeError>(ErrorType::NotAnObject, constructor.to_string_without_side_effects());
|
||||
|
||||
// 3. Return ? PromiseResolve(C, x).
|
||||
return TRY(promise_resolve(global_object, constructor.as_object(), value));
|
||||
return TRY(promise_resolve(vm, constructor.as_object(), value));
|
||||
}
|
||||
|
||||
// 27.2.4.8 get Promise [ @@species ], https://tc39.es/ecma262/#sec-get-promise-@@species
|
||||
|
@ -16,9 +16,10 @@
|
||||
namespace JS {
|
||||
|
||||
// 27.2.2.1 NewPromiseReactionJob ( reaction, argument ), https://tc39.es/ecma262/#sec-newpromisereactionjob
|
||||
static ThrowCompletionOr<Value> run_reaction_job(GlobalObject& global_object, PromiseReaction& reaction, Value argument)
|
||||
static ThrowCompletionOr<Value> run_reaction_job(VM& vm, PromiseReaction& reaction, Value argument)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
// a. Let promiseCapability be reaction.[[Capability]].
|
||||
auto& promise_capability = reaction.capability();
|
||||
@ -55,7 +56,7 @@ static ThrowCompletionOr<Value> run_reaction_job(GlobalObject& global_object, Pr
|
||||
dbgln_if(PROMISE_DEBUG, "run_reaction_job: Calling handler callback {} @ {} with argument {}", handler.value().callback.cell()->class_name(), handler.value().callback.cell(), argument);
|
||||
MarkedVector<Value> arguments(vm.heap());
|
||||
arguments.append(argument);
|
||||
handler_result = vm.host_call_job_callback(global_object, handler.value(), js_undefined(), move(arguments));
|
||||
handler_result = vm.host_call_job_callback(handler.value(), js_undefined(), move(arguments));
|
||||
}
|
||||
|
||||
// f. If promiseCapability is undefined, then
|
||||
@ -89,12 +90,15 @@ static ThrowCompletionOr<Value> run_reaction_job(GlobalObject& global_object, Pr
|
||||
}
|
||||
|
||||
// 27.2.2.1 NewPromiseReactionJob ( reaction, argument ), https://tc39.es/ecma262/#sec-newpromisereactionjob
|
||||
PromiseJob create_promise_reaction_job(GlobalObject& global_object, PromiseReaction& reaction, Value argument)
|
||||
PromiseJob create_promise_reaction_job(VM& vm, PromiseReaction& reaction, Value argument)
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
// 1. Let job be a new Job Abstract Closure with no parameters that captures reaction and argument and performs the following steps when called:
|
||||
// See run_reaction_job for "the following steps".
|
||||
auto job = [global_object = make_handle(&global_object), reaction = make_handle(&reaction), argument = make_handle(argument)]() mutable {
|
||||
return run_reaction_job(*global_object.cell(), *reaction.cell(), argument.value());
|
||||
auto job = [&vm, reaction = make_handle(&reaction), argument = make_handle(argument)]() mutable {
|
||||
return run_reaction_job(vm, *reaction.cell(), argument.value());
|
||||
};
|
||||
|
||||
// 2. Let handlerRealm be null.
|
||||
@ -111,7 +115,7 @@ PromiseJob create_promise_reaction_job(GlobalObject& global_object, PromiseReact
|
||||
handler_realm = get_handler_realm_result.release_value();
|
||||
} else {
|
||||
// c. Else, set handlerRealm to the current Realm Record.
|
||||
handler_realm = global_object.vm().current_realm();
|
||||
handler_realm = vm.current_realm();
|
||||
}
|
||||
|
||||
// d. NOTE: handlerRealm is never null unless the handler is undefined. When the handler is a revoked Proxy and no ECMAScript code runs, handlerRealm is used to create error objects.
|
||||
@ -122,9 +126,10 @@ PromiseJob create_promise_reaction_job(GlobalObject& global_object, PromiseReact
|
||||
}
|
||||
|
||||
// 27.2.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then ), https://tc39.es/ecma262/#sec-newpromiseresolvethenablejob
|
||||
static ThrowCompletionOr<Value> run_resolve_thenable_job(GlobalObject& global_object, Promise& promise_to_resolve, Value thenable, JobCallback& then)
|
||||
static ThrowCompletionOr<Value> run_resolve_thenable_job(VM& vm, Promise& promise_to_resolve, Value thenable, JobCallback& then)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
// a. Let resolvingFunctions be CreateResolvingFunctions(promiseToResolve).
|
||||
auto [resolve_function, reject_function] = promise_to_resolve.create_resolving_functions();
|
||||
@ -134,7 +139,7 @@ static ThrowCompletionOr<Value> run_resolve_thenable_job(GlobalObject& global_ob
|
||||
MarkedVector<Value> arguments(vm.heap());
|
||||
arguments.append(Value(&resolve_function));
|
||||
arguments.append(Value(&reject_function));
|
||||
auto then_call_result = vm.host_call_job_callback(global_object, then, thenable, move(arguments));
|
||||
auto then_call_result = vm.host_call_job_callback(then, thenable, move(arguments));
|
||||
|
||||
// c. If thenCallResult is an abrupt completion, then
|
||||
if (then_call_result.is_error()) {
|
||||
@ -149,8 +154,11 @@ static ThrowCompletionOr<Value> run_resolve_thenable_job(GlobalObject& global_ob
|
||||
}
|
||||
|
||||
// 27.2.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then ), https://tc39.es/ecma262/#sec-newpromiseresolvethenablejob
|
||||
PromiseJob create_promise_resolve_thenable_job(GlobalObject& global_object, Promise& promise_to_resolve, Value thenable, JobCallback then)
|
||||
PromiseJob create_promise_resolve_thenable_job(VM& vm, Promise& promise_to_resolve, Value thenable, JobCallback then)
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
// 2. Let getThenRealmResult be Completion(GetFunctionRealm(then.[[Callback]])).
|
||||
auto get_then_realm_result = get_function_realm(global_object, *then.callback.cell());
|
||||
|
||||
@ -161,7 +169,7 @@ PromiseJob create_promise_resolve_thenable_job(GlobalObject& global_object, Prom
|
||||
then_realm = get_then_realm_result.release_value();
|
||||
} else {
|
||||
// 4. Else, let thenRealm be the current Realm Record.
|
||||
then_realm = global_object.vm().current_realm();
|
||||
then_realm = vm.current_realm();
|
||||
}
|
||||
|
||||
// 5. NOTE: thenRealm is never null. When then.[[Callback]] is a revoked Proxy and no code runs, thenRealm is used to create error objects.
|
||||
@ -170,8 +178,8 @@ PromiseJob create_promise_resolve_thenable_job(GlobalObject& global_object, Prom
|
||||
// 1. Let job be a new Job Abstract Closure with no parameters that captures promiseToResolve, thenable, and then and performs the following steps when called:
|
||||
// See PromiseResolveThenableJob::call() for "the following steps".
|
||||
// NOTE: This is done out of order, since `then` is moved into the lambda and `then` would be invalid if it was done at the start.
|
||||
auto job = [global_object = make_handle(&global_object), promise_to_resolve = make_handle(&promise_to_resolve), thenable = make_handle(thenable), then = move(then)]() mutable {
|
||||
return run_resolve_thenable_job(*global_object.cell(), *promise_to_resolve.cell(), thenable.value(), then);
|
||||
auto job = [&vm, promise_to_resolve = make_handle(&promise_to_resolve), thenable = make_handle(thenable), then = move(then)]() mutable {
|
||||
return run_resolve_thenable_job(vm, *promise_to_resolve.cell(), thenable.value(), then);
|
||||
};
|
||||
|
||||
// 6. Return the Record { [[Job]]: job, [[Realm]]: thenRealm }.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
@ -20,7 +20,7 @@ struct PromiseJob {
|
||||
};
|
||||
|
||||
// NOTE: These return a PromiseJob to prevent awkward casting at call sites.
|
||||
PromiseJob create_promise_reaction_job(GlobalObject&, PromiseReaction&, Value argument);
|
||||
PromiseJob create_promise_resolve_thenable_job(GlobalObject&, Promise&, Value thenable, JobCallback then);
|
||||
PromiseJob create_promise_reaction_job(VM&, PromiseReaction&, Value argument);
|
||||
PromiseJob create_promise_resolve_thenable_job(VM&, Promise&, Value thenable, JobCallback then);
|
||||
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::then)
|
||||
auto* constructor = TRY(species_constructor(global_object, *promise, *global_object.promise_constructor()));
|
||||
|
||||
// 4. Let resultCapability be ? NewPromiseCapability(C).
|
||||
auto result_capability = TRY(new_promise_capability(global_object, constructor));
|
||||
auto result_capability = TRY(new_promise_capability(vm, constructor));
|
||||
|
||||
// 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability).
|
||||
return promise->perform_then(on_fulfilled, on_rejected, result_capability);
|
||||
@ -111,7 +111,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
|
||||
auto result = TRY(call(global_object, on_finally, js_undefined()));
|
||||
|
||||
// ii. Let promise be ? PromiseResolve(C, result).
|
||||
auto* promise = TRY(promise_resolve(global_object, constructor, result));
|
||||
auto* promise = TRY(promise_resolve(vm, constructor, result));
|
||||
|
||||
// iii. Let returnValue be a new Abstract Closure with no parameters that captures value and performs the following steps when called:
|
||||
auto return_value = [value_handle = make_handle(value)](auto&, auto&) -> ThrowCompletionOr<Value> {
|
||||
@ -140,7 +140,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
|
||||
auto result = TRY(call(global_object, on_finally, js_undefined()));
|
||||
|
||||
// ii. Let promise be ? PromiseResolve(C, result).
|
||||
auto* promise = TRY(promise_resolve(global_object, constructor, result));
|
||||
auto* promise = TRY(promise_resolve(vm, constructor, result));
|
||||
|
||||
// iii. Let throwReason be a new Abstract Closure with no parameters that captures reason and performs the following steps when called:
|
||||
auto throw_reason = [reason_handle = make_handle(reason)](auto&, auto&) -> ThrowCompletionOr<Value> {
|
||||
|
@ -12,10 +12,10 @@
|
||||
namespace JS {
|
||||
|
||||
// 27.2.1.5 NewPromiseCapability ( C ), https://tc39.es/ecma262/#sec-newpromisecapability
|
||||
ThrowCompletionOr<PromiseCapability> new_promise_capability(GlobalObject& global_object, Value constructor)
|
||||
ThrowCompletionOr<PromiseCapability> new_promise_capability(VM& vm, Value constructor)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *global_object.associated_realm();
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
// 1. If IsConstructor(C) is false, throw a TypeError exception.
|
||||
if (!constructor.is_constructor())
|
||||
|
@ -21,47 +21,51 @@ struct PromiseCapability {
|
||||
};
|
||||
|
||||
// 27.2.1.1.1 IfAbruptRejectPromise ( value, capability ), https://tc39.es/ecma262/#sec-ifabruptrejectpromise
|
||||
#define __TRY_OR_REJECT(global_object, capability, expression, CALL_CHECK) \
|
||||
({ \
|
||||
auto _temporary_try_or_reject_result = (expression); \
|
||||
/* 1. If value is an abrupt completion, then */ \
|
||||
if (_temporary_try_or_reject_result.is_error()) { \
|
||||
/* a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). */ \
|
||||
CALL_CHECK(JS::call(global_object, *capability.reject, js_undefined(), *_temporary_try_or_reject_result.release_error().value())); \
|
||||
\
|
||||
/* b. Return capability.[[Promise]]. */ \
|
||||
return capability.promise; \
|
||||
} \
|
||||
\
|
||||
/* 2. Else if value is a Completion Record, set value to value.[[Value]]. */ \
|
||||
_temporary_try_or_reject_result.release_value(); \
|
||||
#define __TRY_OR_REJECT(vm, capability, expression, CALL_CHECK) \
|
||||
({ \
|
||||
auto& _realm = *vm.current_realm(); \
|
||||
auto& _global_object = _realm.global_object(); \
|
||||
auto _temporary_try_or_reject_result = (expression); \
|
||||
/* 1. If value is an abrupt completion, then */ \
|
||||
if (_temporary_try_or_reject_result.is_error()) { \
|
||||
/* a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). */ \
|
||||
CALL_CHECK(JS::call(_global_object, *capability.reject, js_undefined(), *_temporary_try_or_reject_result.release_error().value())); \
|
||||
\
|
||||
/* b. Return capability.[[Promise]]. */ \
|
||||
return capability.promise; \
|
||||
} \
|
||||
\
|
||||
/* 2. Else if value is a Completion Record, set value to value.[[Value]]. */ \
|
||||
_temporary_try_or_reject_result.release_value(); \
|
||||
})
|
||||
|
||||
#define TRY_OR_REJECT(global_object, capability, expression) \
|
||||
__TRY_OR_REJECT(global_object, capability, expression, TRY)
|
||||
#define TRY_OR_REJECT(vm, capability, expression) \
|
||||
__TRY_OR_REJECT(vm, capability, expression, TRY)
|
||||
|
||||
#define TRY_OR_MUST_REJECT(global_object, capability, expression) \
|
||||
__TRY_OR_REJECT(global_object, capability, expression, MUST)
|
||||
#define TRY_OR_MUST_REJECT(vm, capability, expression) \
|
||||
__TRY_OR_REJECT(vm, capability, expression, MUST)
|
||||
|
||||
// 27.2.1.1.1 IfAbruptRejectPromise ( value, capability ), https://tc39.es/ecma262/#sec-ifabruptrejectpromise
|
||||
#define TRY_OR_REJECT_WITH_VALUE(global_object, capability, expression) \
|
||||
({ \
|
||||
auto _temporary_try_or_reject_result = (expression); \
|
||||
/* 1. If value is an abrupt completion, then */ \
|
||||
if (_temporary_try_or_reject_result.is_error()) { \
|
||||
/* a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). */ \
|
||||
TRY(JS::call(global_object, *capability.reject, js_undefined(), *_temporary_try_or_reject_result.release_error().value())); \
|
||||
\
|
||||
/* b. Return capability.[[Promise]]. */ \
|
||||
return Value { capability.promise }; \
|
||||
} \
|
||||
\
|
||||
/* 2. Else if value is a Completion Record, set value to value.[[Value]]. */ \
|
||||
_temporary_try_or_reject_result.release_value(); \
|
||||
#define TRY_OR_REJECT_WITH_VALUE(vm, capability, expression) \
|
||||
({ \
|
||||
auto& _realm = *vm.current_realm(); \
|
||||
auto& _global_object = _realm.global_object(); \
|
||||
auto _temporary_try_or_reject_result = (expression); \
|
||||
/* 1. If value is an abrupt completion, then */ \
|
||||
if (_temporary_try_or_reject_result.is_error()) { \
|
||||
/* a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). */ \
|
||||
TRY(JS::call(_global_object, *capability.reject, js_undefined(), *_temporary_try_or_reject_result.release_error().value())); \
|
||||
\
|
||||
/* b. Return capability.[[Promise]]. */ \
|
||||
return Value { capability.promise }; \
|
||||
} \
|
||||
\
|
||||
/* 2. Else if value is a Completion Record, set value to value.[[Value]]. */ \
|
||||
_temporary_try_or_reject_result.release_value(); \
|
||||
})
|
||||
|
||||
// 27.2.1.5 NewPromiseCapability ( C ), https://tc39.es/ecma262/#sec-newpromisecapability
|
||||
ThrowCompletionOr<PromiseCapability> new_promise_capability(GlobalObject& global_object, Value constructor);
|
||||
ThrowCompletionOr<PromiseCapability> new_promise_capability(VM& vm, Value constructor);
|
||||
|
||||
// 27.2.1.2 PromiseReaction Records, https://tc39.es/ecma262/#sec-promisereaction-records
|
||||
class PromiseReaction final : public Cell {
|
||||
|
@ -214,7 +214,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object,
|
||||
// 1. Assert: evalContext is an execution context associated to a ShadowRealm instance's [[ExecutionContext]].
|
||||
|
||||
// 2. Let innerCapability be ! NewPromiseCapability(%Promise%).
|
||||
auto inner_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
||||
auto inner_capability = MUST(new_promise_capability(vm, global_object.promise_constructor()));
|
||||
|
||||
// 3. Let runningContext be the running execution context.
|
||||
// 4. If runningContext is not already suspended, suspend runningContext.
|
||||
@ -269,7 +269,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object,
|
||||
auto* on_fulfilled = NativeFunction::create(realm, move(steps), 1, "", &caller_realm);
|
||||
|
||||
// 12. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
||||
auto promise_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
||||
auto promise_capability = MUST(new_promise_capability(vm, global_object.promise_constructor()));
|
||||
|
||||
// NOTE: Even though the spec tells us to use %ThrowTypeError%, it's not observable if we actually do.
|
||||
// Throw a nicer TypeError forwarding the import error message instead (we know the argument is an Error object).
|
||||
|
@ -51,8 +51,8 @@ VM::VM(OwnPtr<CustomData> custom_data)
|
||||
promise_rejection_tracker(promise, operation);
|
||||
};
|
||||
|
||||
host_call_job_callback = [](GlobalObject& global_object, JobCallback& job_callback, Value this_value, MarkedVector<Value> arguments) {
|
||||
return call_job_callback(global_object, job_callback, this_value, move(arguments));
|
||||
host_call_job_callback = [this](JobCallback& job_callback, Value this_value, MarkedVector<Value> arguments) {
|
||||
return call_job_callback(*this, job_callback, this_value, move(arguments));
|
||||
};
|
||||
|
||||
host_enqueue_finalization_registry_cleanup_job = [this](FinalizationRegistry& finalization_registry) {
|
||||
|
@ -229,7 +229,7 @@ public:
|
||||
void enable_default_host_import_module_dynamically_hook();
|
||||
|
||||
Function<void(Promise&, Promise::RejectionOperation)> host_promise_rejection_tracker;
|
||||
Function<ThrowCompletionOr<Value>(GlobalObject&, JobCallback&, Value, MarkedVector<Value>)> host_call_job_callback;
|
||||
Function<ThrowCompletionOr<Value>(JobCallback&, Value, MarkedVector<Value>)> host_call_job_callback;
|
||||
Function<void(FinalizationRegistry&)> host_enqueue_finalization_registry_cleanup_job;
|
||||
Function<void(Function<ThrowCompletionOr<Value>()>, Realm*)> host_enqueue_promise_job;
|
||||
Function<JobCallback(FunctionObject&)> host_make_job_callback;
|
||||
|
@ -128,7 +128,9 @@ JS::VM& main_thread_vm()
|
||||
};
|
||||
|
||||
// 8.1.5.3.1 HostCallJobCallback(callback, V, argumentsList), https://html.spec.whatwg.org/multipage/webappapis.html#hostcalljobcallback
|
||||
vm->host_call_job_callback = [](JS::GlobalObject& global_object, JS::JobCallback& callback, JS::Value this_value, JS::MarkedVector<JS::Value> arguments_list) {
|
||||
vm->host_call_job_callback = [](JS::JobCallback& callback, JS::Value this_value, JS::MarkedVector<JS::Value> arguments_list) {
|
||||
auto& realm = *vm->current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
auto& callback_host_defined = verify_cast<WebEngineCustomJobCallbackData>(*callback.custom_data);
|
||||
|
||||
// 1. Let incumbent settings be callback.[[HostDefined]].[[IncumbentSettings]]. (NOTE: Not necessary)
|
||||
|
Loading…
Reference in New Issue
Block a user