summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime')
-rw-r--r--Userland/Libraries/LibJS/Runtime/AsyncFromSyncIteratorPrototype.cpp26
-rw-r--r--Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.cpp3
-rw-r--r--Userland/Libraries/LibJS/Runtime/AsyncGenerator.cpp4
-rw-r--r--Userland/Libraries/LibJS/Runtime/AsyncGeneratorRequest.h4
-rw-r--r--Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp10
-rw-r--r--Userland/Libraries/LibJS/Runtime/Promise.cpp13
-rw-r--r--Userland/Libraries/LibJS/Runtime/Promise.h2
-rw-r--r--Userland/Libraries/LibJS/Runtime/PromiseCapability.cpp27
-rw-r--r--Userland/Libraries/LibJS/Runtime/PromiseCapability.h87
-rw-r--r--Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp32
-rw-r--r--Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp17
-rw-r--r--Userland/Libraries/LibJS/Runtime/PromiseReaction.cpp15
-rw-r--r--Userland/Libraries/LibJS/Runtime/PromiseReaction.h8
-rw-r--r--Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp40
-rw-r--r--Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.h20
-rw-r--r--Userland/Libraries/LibJS/Runtime/ShadowRealm.cpp2
-rw-r--r--Userland/Libraries/LibJS/Runtime/VM.cpp26
-rw-r--r--Userland/Libraries/LibJS/Runtime/VM.h8
18 files changed, 187 insertions, 157 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/AsyncFromSyncIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/AsyncFromSyncIteratorPrototype.cpp
index 1b3aa73bc4..e8899b7c63 100644
--- a/Userland/Libraries/LibJS/Runtime/AsyncFromSyncIteratorPrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/AsyncFromSyncIteratorPrototype.cpp
@@ -38,15 +38,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(vm, 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(vm, 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(vm, promise_capability, promise_resolve(vm, *realm.intrinsics().promise_constructor(), value));
+ auto value_wrapper = TRY_OR_MUST_REJECT(vm, &promise_capability, promise_resolve(vm, *realm.intrinsics().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) -> ThrowCompletionOr<Value> {
@@ -59,10 +59,10 @@ static Object* async_from_sync_iterator_continuation(VM& vm, Object& result, Pro
auto* on_fulfilled = NativeFunction::create(realm, move(unwrap), 1, "");
// 11. Perform PerformPromiseThen(valueWrapper, onFulfilled, undefined, promiseCapability).
- verify_cast<Promise>(value_wrapper)->perform_then(move(on_fulfilled), js_undefined(), promise_capability);
+ verify_cast<Promise>(value_wrapper)->perform_then(move(on_fulfilled), js_undefined(), &promise_capability);
// 12. Return promiseCapability.[[Promise]].
- return promise_capability.promise;
+ return promise_capability.promise();
}
// 27.1.4.2.1 %AsyncFromSyncIteratorPrototype%.next ( [ value ] ), https://tc39.es/ecma262/#sec-%asyncfromsynciteratorprototype%.next
@@ -118,10 +118,10 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::return_)
auto* iter_result = create_iterator_result_object(vm, vm.argument(0), true);
// b. Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »).
- MUST(call(vm, *promise_capability.resolve, js_undefined(), iter_result));
+ MUST(call(vm, *promise_capability->resolve(), js_undefined(), iter_result));
// c. Return promiseCapability.[[Promise]].
- return promise_capability.promise;
+ return promise_capability->promise();
}
// 8. If value is present, then
@@ -137,9 +137,9 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::return_)
if (!result.is_object()) {
auto* error = TypeError::create(realm, String::formatted(ErrorType::NotAnObject.message(), "SyncIteratorReturnResult"));
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
- MUST(call(vm, *promise_capability.reject, js_undefined(), error));
+ MUST(call(vm, *promise_capability->reject(), js_undefined(), error));
// b. Return promiseCapability.[[Promise]].
- return promise_capability.promise;
+ return promise_capability->promise();
}
// 12. Return AsyncFromSyncIteratorContinuation(result, promiseCapability).
@@ -168,9 +168,9 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::throw_)
// 7. If throw is undefined, then
if (throw_method == nullptr) {
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « value »).
- MUST(call(vm, *promise_capability.reject, js_undefined(), vm.argument(0)));
+ MUST(call(vm, *promise_capability->reject(), js_undefined(), vm.argument(0)));
// b. Return promiseCapability.[[Promise]].
- return promise_capability.promise;
+ return promise_capability->promise();
}
// 8. If value is present, then
// a. Let result be Completion(Call(throw, syncIterator, « value »)).
@@ -185,10 +185,10 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::throw_)
if (!result.is_object()) {
auto* error = TypeError::create(realm, String::formatted(ErrorType::NotAnObject.message(), "SyncIteratorThrowResult"));
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
- MUST(call(vm, *promise_capability.reject, js_undefined(), error));
+ MUST(call(vm, *promise_capability->reject(), js_undefined(), error));
// b. Return promiseCapability.[[Promise]].
- return promise_capability.promise;
+ return promise_capability->promise();
}
// 12. Return AsyncFromSyncIteratorContinuation(result, promiseCapability).
diff --git a/Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.cpp b/Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.cpp
index d6977d61a9..4226026f88 100644
--- a/Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.cpp
+++ b/Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.cpp
@@ -59,7 +59,8 @@ ThrowCompletionOr<Value> AsyncFunctionDriverWrapper::react_to_async_task_complet
if (TRY(result.get(vm, vm.names.done)).to_boolean())
return promise;
- return promise->perform_then(m_on_fulfillment, m_on_rejection, PromiseCapability { promise, m_on_fulfillment, m_on_rejection });
+ auto promise_capability = PromiseCapability::create(vm, promise, m_on_fulfillment, m_on_rejection);
+ return promise->perform_then(m_on_fulfillment, m_on_rejection, promise_capability);
}
void AsyncFunctionDriverWrapper::visit_edges(Cell::Visitor& visitor)
diff --git a/Userland/Libraries/LibJS/Runtime/AsyncGenerator.cpp b/Userland/Libraries/LibJS/Runtime/AsyncGenerator.cpp
index db83d52a25..f3eb5a3be5 100644
--- a/Userland/Libraries/LibJS/Runtime/AsyncGenerator.cpp
+++ b/Userland/Libraries/LibJS/Runtime/AsyncGenerator.cpp
@@ -21,9 +21,7 @@ void AsyncGenerator::visit_edges(Cell::Visitor& visitor)
for (auto const& request : m_async_generator_queue) {
if (request.completion.value().has_value())
visitor.visit(*request.completion.value());
- visitor.visit(request.capability.promise);
- visitor.visit(request.capability.reject);
- visitor.visit(request.capability.resolve);
+ visitor.visit(request.capability);
}
}
diff --git a/Userland/Libraries/LibJS/Runtime/AsyncGeneratorRequest.h b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorRequest.h
index ddfd38857b..7be045fab0 100644
--- a/Userland/Libraries/LibJS/Runtime/AsyncGeneratorRequest.h
+++ b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorRequest.h
@@ -13,8 +13,8 @@ namespace JS {
// 27.6.3.1 AsyncGeneratorRequest Records, https://tc39.es/ecma262/#sec-asyncgeneratorrequest-records
struct AsyncGeneratorRequest {
- Completion completion; // [[Completion]]
- PromiseCapability capability; // [[Capability]]
+ Completion completion; // [[Completion]]
+ NonnullGCPtr<PromiseCapability> capability; // [[Capability]]
};
}
diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp
index 1341da4f49..5fd32e9cae 100644
--- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp
+++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp
@@ -743,12 +743,12 @@ void async_block_start(VM& vm, NonnullRefPtr<Statement> const& async_body, Promi
// d. If result.[[Type]] is normal, then
if (result.type() == Completion::Type::Normal) {
// i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
- MUST(call(vm, promise_capability.resolve, js_undefined(), js_undefined()));
+ MUST(call(vm, *promise_capability.resolve(), js_undefined(), js_undefined()));
}
// e. Else if result.[[Type]] is return, then
else if (result.type() == Completion::Type::Return) {
// i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »).
- MUST(call(vm, promise_capability.resolve, js_undefined(), *result.value()));
+ MUST(call(vm, *promise_capability.resolve(), js_undefined(), *result.value()));
}
// f. Else,
else {
@@ -756,7 +756,7 @@ void async_block_start(VM& vm, NonnullRefPtr<Statement> const& async_body, Promi
VERIFY(result.type() == Completion::Type::Throw);
// ii. Perform ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »).
- MUST(call(vm, promise_capability.reject, js_undefined(), *result.value()));
+ MUST(call(vm, *promise_capability.reject(), js_undefined(), *result.value()));
}
// g. Return unused.
// NOTE: We don't support returning an empty/optional/unused value here.
@@ -877,7 +877,7 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
// 3. If declResult is an abrupt completion, then
if (declaration_result.is_throw_completion()) {
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « declResult.[[Value]] »).
- MUST(call(vm, promise_capability.reject, js_undefined(), *declaration_result.throw_completion().value()));
+ MUST(call(vm, *promise_capability->reject(), js_undefined(), *declaration_result.throw_completion().value()));
}
// 4. Else,
else {
@@ -886,7 +886,7 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
}
// 5. Return Completion Record { [[Type]]: return, [[Value]]: promiseCapability.[[Promise]], [[Target]]: empty }.
- return Completion { Completion::Type::Return, promise_capability.promise, {} };
+ return Completion { Completion::Type::Return, promise_capability->promise(), {} };
}
}
VERIFY_NOT_REACHED();
diff --git a/Userland/Libraries/LibJS/Runtime/Promise.cpp b/Userland/Libraries/LibJS/Runtime/Promise.cpp
index 40637f2151..5d688babdf 100644
--- a/Userland/Libraries/LibJS/Runtime/Promise.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Promise.cpp
@@ -36,10 +36,10 @@ ThrowCompletionOr<Object*> promise_resolve(VM& vm, Object& constructor, Value va
auto promise_capability = TRY(new_promise_capability(vm, &constructor));
// 3. Perform ? Call(promiseCapability.[[Resolve]], undefined, « x »).
- (void)TRY(call(vm, *promise_capability.resolve, js_undefined(), value));
+ (void)TRY(call(vm, *promise_capability->resolve(), js_undefined(), value));
// 4. Return promiseCapability.[[Promise]].
- return promise_capability.promise;
+ return promise_capability->promise().ptr();
}
Promise* Promise::create(Realm& realm)
@@ -288,7 +288,7 @@ void Promise::trigger_reactions() const
}
// 27.2.5.4.1 PerformPromiseThen ( promise, onFulfilled, onRejected [ , resultCapability ] ), https://tc39.es/ecma262/#sec-performpromisethen
-Value Promise::perform_then(Value on_fulfilled, Value on_rejected, Optional<PromiseCapability> result_capability)
+Value Promise::perform_then(Value on_fulfilled, Value on_rejected, GCPtr<PromiseCapability> result_capability)
{
auto& vm = this->vm();
@@ -377,7 +377,7 @@ Value Promise::perform_then(Value on_fulfilled, Value on_rejected, Optional<Prom
m_is_handled = true;
// 13. If resultCapability is undefined, then
- if (!result_capability.has_value()) {
+ if (result_capability == nullptr) {
// a. Return undefined.
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / perform_then()]: No result PromiseCapability, returning undefined", this);
return js_undefined();
@@ -385,9 +385,8 @@ Value Promise::perform_then(Value on_fulfilled, Value on_rejected, Optional<Prom
// 14. Else,
// a. Return resultCapability.[[Promise]].
- auto* promise = result_capability.value().promise;
- dbgln_if(PROMISE_DEBUG, "[Promise @ {} / perform_then()]: Returning Promise @ {} from result PromiseCapability @ {}", this, promise, &result_capability.value());
- return promise;
+ dbgln_if(PROMISE_DEBUG, "[Promise @ {} / perform_then()]: Returning Promise @ {} from result PromiseCapability @ {}", this, result_capability->promise().ptr(), result_capability.ptr());
+ return result_capability->promise();
}
void Promise::visit_edges(Cell::Visitor& visitor)
diff --git a/Userland/Libraries/LibJS/Runtime/Promise.h b/Userland/Libraries/LibJS/Runtime/Promise.h
index 82692393dc..790e3482e4 100644
--- a/Userland/Libraries/LibJS/Runtime/Promise.h
+++ b/Userland/Libraries/LibJS/Runtime/Promise.h
@@ -42,7 +42,7 @@ public:
void fulfill(Value value);
void reject(Value reason);
- Value perform_then(Value on_fulfilled, Value on_rejected, Optional<PromiseCapability> result_capability);
+ Value perform_then(Value on_fulfilled, Value on_rejected, GCPtr<PromiseCapability> result_capability);
bool is_handled() const { return m_is_handled; }
void set_is_handled() { m_is_handled = true; }
diff --git a/Userland/Libraries/LibJS/Runtime/PromiseCapability.cpp b/Userland/Libraries/LibJS/Runtime/PromiseCapability.cpp
index b75cf4093c..5c56801c0a 100644
--- a/Userland/Libraries/LibJS/Runtime/PromiseCapability.cpp
+++ b/Userland/Libraries/LibJS/Runtime/PromiseCapability.cpp
@@ -11,8 +11,27 @@
namespace JS {
+NonnullGCPtr<PromiseCapability> PromiseCapability::create(VM& vm, GCPtr<Object> promise, GCPtr<FunctionObject> resolve, GCPtr<FunctionObject> reject)
+{
+ return NonnullGCPtr { *vm.heap().allocate_without_realm<PromiseCapability>(promise, resolve, reject) };
+}
+
+PromiseCapability::PromiseCapability(GCPtr<Object> promise, GCPtr<FunctionObject> resolve, GCPtr<FunctionObject> reject)
+ : m_promise(promise)
+ , m_resolve(resolve)
+ , m_reject(reject)
+{
+}
+
+void PromiseCapability::visit_edges(Cell::Visitor& visitor)
+{
+ visitor.visit(m_promise);
+ visitor.visit(m_resolve);
+ visitor.visit(m_reject);
+}
+
// 27.2.1.5 NewPromiseCapability ( C ), https://tc39.es/ecma262/#sec-newpromisecapability
-ThrowCompletionOr<PromiseCapability> new_promise_capability(VM& vm, Value constructor)
+ThrowCompletionOr<NonnullGCPtr<PromiseCapability>> new_promise_capability(VM& vm, Value constructor)
{
auto& realm = *vm.current_realm();
@@ -70,11 +89,11 @@ ThrowCompletionOr<PromiseCapability> new_promise_capability(VM& vm, Value constr
// 9. Set promiseCapability.[[Promise]] to promise.
// 10. Return promiseCapability.
- return PromiseCapability {
+ return PromiseCapability::create(
+ vm,
promise,
&promise_capability_functions.resolve.as_function(),
- &promise_capability_functions.reject.as_function(),
- };
+ &promise_capability_functions.reject.as_function());
}
}
diff --git a/Userland/Libraries/LibJS/Runtime/PromiseCapability.h b/Userland/Libraries/LibJS/Runtime/PromiseCapability.h
index 12d88b542f..c2cee43deb 100644
--- a/Userland/Libraries/LibJS/Runtime/PromiseCapability.h
+++ b/Userland/Libraries/LibJS/Runtime/PromiseCapability.h
@@ -13,27 +13,48 @@
namespace JS {
// 27.2.1.1 PromiseCapability Records, https://tc39.es/ecma262/#sec-promisecapability-records
-struct PromiseCapability {
- Object* promise { nullptr };
- FunctionObject* resolve { nullptr };
- FunctionObject* reject { nullptr };
+class PromiseCapability final : public Cell {
+ JS_CELL(PromiseCapability, Cell);
+
+public:
+ static NonnullGCPtr<PromiseCapability> create(VM& vm, GCPtr<Object> promise, GCPtr<FunctionObject> resolve, GCPtr<FunctionObject> reject);
+
+ virtual ~PromiseCapability() = default;
+
+ [[nodiscard]] GCPtr<Object> promise() const { return m_promise; }
+ void set_promise(NonnullGCPtr<Object> promise) { m_promise = promise; }
+
+ [[nodiscard]] GCPtr<FunctionObject> resolve() const { return m_resolve; }
+ void set_resolve(NonnullGCPtr<FunctionObject> resolve) { m_resolve = resolve; }
+
+ [[nodiscard]] GCPtr<FunctionObject> reject() const { return m_reject; }
+ void set_reject(NonnullGCPtr<FunctionObject> reject) { m_reject = reject; }
+
+private:
+ PromiseCapability(GCPtr<Object>, GCPtr<FunctionObject>, GCPtr<FunctionObject>);
+
+ virtual void visit_edges(Visitor&) override;
+
+ GCPtr<Object> m_promise;
+ GCPtr<FunctionObject> m_resolve;
+ GCPtr<FunctionObject> m_reject;
};
// 27.2.1.1.1 IfAbruptRejectPromise ( value, capability ), https://tc39.es/ecma262/#sec-ifabruptrejectpromise
-#define __TRY_OR_REJECT(vm, 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(vm, *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 _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(vm, *(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) \
@@ -43,23 +64,23 @@ struct PromiseCapability {
__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(vm, 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(vm, *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 _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(vm, *(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(VM& vm, Value constructor);
+ThrowCompletionOr<NonnullGCPtr<PromiseCapability>> new_promise_capability(VM& vm, Value constructor);
}
diff --git a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp
index 2aead988f0..65fed311f1 100644
--- a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp
+++ b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp
@@ -39,7 +39,7 @@ static ThrowCompletionOr<Value> get_promise_resolve(VM& vm, Value constructor)
using EndOfElementsCallback = Function<ThrowCompletionOr<Value>(PromiseValueList&)>;
using InvokeElementFunctionCallback = Function<ThrowCompletionOr<Value>(PromiseValueList&, RemainingElements&, Value, size_t)>;
-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)
+static ThrowCompletionOr<Value> perform_promise_common(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability const& result_capability, Value promise_resolve, EndOfElementsCallback end_of_list, InvokeElementFunctionCallback invoke_element_function)
{
VERIFY(constructor.is_constructor());
VERIFY(promise_resolve.is_function());
@@ -79,7 +79,7 @@ static ThrowCompletionOr<Value> perform_promise_common(VM& vm, Iterator& iterato
}
// iv. Return resultCapability.[[Promise]].
- return result_capability.promise;
+ return result_capability.promise();
}
// e. Let nextValue be Completion(IteratorValue(next)).
@@ -113,7 +113,7 @@ static ThrowCompletionOr<Value> perform_promise_common(VM& vm, Iterator& iterato
}
// 27.2.4.1.2 PerformPromiseAll ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiseall
-static ThrowCompletionOr<Value> perform_promise_all(VM& vm, 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 const& result_capability, Value promise_resolve)
{
auto& realm = *vm.current_realm();
@@ -124,10 +124,10 @@ static ThrowCompletionOr<Value> perform_promise_all(VM& vm, Iterator& iterator_r
auto* values_array = Array::create_from(realm, values.values());
// 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
- TRY(call(vm, *result_capability.resolve, js_undefined(), values_array));
+ TRY(call(vm, *result_capability.resolve(), js_undefined(), values_array));
// iv. Return resultCapability.[[Promise]].
- return Value(result_capability.promise);
+ return result_capability.promise();
},
[&](PromiseValueList& values, RemainingElements& remaining_elements_count, Value next_promise, size_t index) {
// j. Let steps be the algorithm steps defined in Promise.all Resolve Element Functions.
@@ -142,12 +142,12 @@ static ThrowCompletionOr<Value> perform_promise_all(VM& vm, Iterator& iterator_r
on_fulfilled->define_direct_property(vm.names.name, js_string(vm, String::empty()), Attribute::Configurable);
// s. Perform ? Invoke(nextPromise, "then", « onFulfilled, resultCapability.[[Reject]] »).
- return next_promise.invoke(vm, vm.names.then, on_fulfilled, result_capability.reject);
+ return next_promise.invoke(vm, vm.names.then, on_fulfilled, result_capability.reject());
});
}
// 27.2.4.2.1 PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiseallsettled
-static ThrowCompletionOr<Value> perform_promise_all_settled(VM& vm, 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 const& result_capability, Value promise_resolve)
{
auto& realm = *vm.current_realm();
@@ -156,9 +156,9 @@ static ThrowCompletionOr<Value> perform_promise_all_settled(VM& vm, Iterator& it
[&](PromiseValueList& values) -> ThrowCompletionOr<Value> {
auto* values_array = Array::create_from(realm, values.values());
- TRY(call(vm, *result_capability.resolve, js_undefined(), values_array));
+ TRY(call(vm, *result_capability.resolve(), js_undefined(), values_array));
- return Value(result_capability.promise);
+ return result_capability.promise();
},
[&](PromiseValueList& values, RemainingElements& remaining_elements_count, Value next_promise, size_t index) {
// j. Let stepsFulfilled be the algorithm steps defined in Promise.allSettled Resolve Element Functions.
@@ -190,7 +190,7 @@ static ThrowCompletionOr<Value> perform_promise_all_settled(VM& vm, Iterator& it
}
// 27.2.4.3.1 PerformPromiseAny ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiseany
-static ThrowCompletionOr<Value> perform_promise_any(VM& vm, 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 const& result_capability, Value promise_resolve)
{
auto& realm = *vm.current_realm();
@@ -220,22 +220,22 @@ static ThrowCompletionOr<Value> perform_promise_any(VM& vm, Iterator& iterator_r
on_rejected->define_direct_property(vm.names.name, js_string(vm, String::empty()), Attribute::Configurable);
// s. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], onRejected »).
- return next_promise.invoke(vm, vm.names.then, result_capability.resolve, on_rejected);
+ return next_promise.invoke(vm, vm.names.then, result_capability.resolve(), on_rejected);
});
}
// 27.2.4.5.1 PerformPromiseRace ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiserace
-static ThrowCompletionOr<Value> perform_promise_race(VM& vm, 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 const& result_capability, Value promise_resolve)
{
return perform_promise_common(
vm, iterator_record, constructor, result_capability, promise_resolve,
[&](PromiseValueList&) -> ThrowCompletionOr<Value> {
// ii. Return resultCapability.[[Promise]].
- return Value(result_capability.promise);
+ return result_capability.promise();
},
[&](PromiseValueList&, RemainingElements&, Value next_promise, size_t) {
// i. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »).
- return next_promise.invoke(vm, vm.names.then, result_capability.resolve, result_capability.reject);
+ return next_promise.invoke(vm, vm.names.then, result_capability.resolve(), result_capability.reject());
});
}
@@ -456,10 +456,10 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::reject)
auto promise_capability = TRY(new_promise_capability(vm, constructor));
// 3. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »).
- [[maybe_unused]] auto result = TRY(JS::call(vm, *promise_capability.reject, js_undefined(), reason));
+ [[maybe_unused]] auto result = TRY(JS::call(vm, *promise_capability->reject(), js_undefined(), reason));
// 4. Return promiseCapability.[[Promise]].
- return promise_capability.promise;
+ return promise_capability->promise();
}
// 27.2.4.7 Promise.resolve ( x ), https://tc39.es/ecma262/#sec-promise.resolve
diff --git a/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp b/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp
index a31ed65060..1eb425d476 100644
--- a/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp
+++ b/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp
@@ -20,7 +20,7 @@ namespace JS {
static ThrowCompletionOr<Value> run_reaction_job(VM& vm, PromiseReaction& reaction, Value argument)
{
// a. Let promiseCapability be reaction.[[Capability]].
- auto& promise_capability = reaction.capability();
+ auto promise_capability = reaction.capability();
// b. Let type be reaction.[[Type]].
auto type = reaction.type();
@@ -58,7 +58,7 @@ static ThrowCompletionOr<Value> run_reaction_job(VM& vm, PromiseReaction& reacti
}
// f. If promiseCapability is undefined, then
- if (!promise_capability.has_value()) {
+ if (promise_capability == nullptr) {
// i. Assert: handlerResult is not an abrupt completion.
VERIFY(!handler_result.is_abrupt());
@@ -74,15 +74,15 @@ static ThrowCompletionOr<Value> run_reaction_job(VM& vm, PromiseReaction& reacti
// h. If handlerResult is an abrupt completion, then
if (handler_result.is_abrupt()) {
// i. Return ? Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »).
- auto* reject_function = promise_capability.value().reject;
- dbgln_if(PROMISE_DEBUG, "run_reaction_job: Calling PromiseCapability's reject function @ {}", reject_function);
+ auto reject_function = promise_capability->reject();
+ dbgln_if(PROMISE_DEBUG, "run_reaction_job: Calling PromiseCapability's reject function @ {}", reject_function.ptr());
return call(vm, *reject_function, js_undefined(), *handler_result.value());
}
// i. Else,
else {
// i. Return ? Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »).
- auto* resolve_function = promise_capability.value().resolve;
- dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob]: Calling PromiseCapability's resolve function @ {}", resolve_function);
+ auto resolve_function = promise_capability->resolve();
+ dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob]: Calling PromiseCapability's resolve function @ {}", resolve_function.ptr());
return call(vm, *resolve_function, js_undefined(), *handler_result.value());
}
}
@@ -165,9 +165,8 @@ PromiseJob create_promise_resolve_thenable_job(VM& vm, Promise& promise_to_resol
VERIFY(then_realm);
// 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 = [&vm, promise_to_resolve = make_handle(&promise_to_resolve), thenable = make_handle(thenable), then = move(then)]() mutable {
+ // See run_resolve_thenable_job() for "the following steps".
+ 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);
};
diff --git a/Userland/Libraries/LibJS/Runtime/PromiseReaction.cpp b/Userland/Libraries/LibJS/Runtime/PromiseReaction.cpp
index a6f2e392e0..abe81da6f2 100644
--- a/Userland/Libraries/LibJS/Runtime/PromiseReaction.cpp
+++ b/Userland/Libraries/LibJS/Runtime/PromiseReaction.cpp
@@ -10,14 +10,14 @@
namespace JS {
-PromiseReaction* PromiseReaction::create(VM& vm, Type type, Optional<PromiseCapability> capability, Optional<JobCallback> handler)
+PromiseReaction* PromiseReaction::create(VM& vm, Type type, GCPtr<PromiseCapability> capability, Optional<JobCallback> handler)
{
- return vm.heap().allocate_without_realm<PromiseReaction>(type, move(capability), move(handler));
+ return vm.heap().allocate_without_realm<PromiseReaction>(type, capability, move(handler));
}
-PromiseReaction::PromiseReaction(Type type, Optional<PromiseCapability> capability, Optional<JobCallback> handler)
+PromiseReaction::PromiseReaction(Type type, GCPtr<PromiseCapability> capability, Optional<JobCallback> handler)
: m_type(type)
- , m_capability(move(capability))
+ , m_capability(capability)
, m_handler(move(handler))
{
}
@@ -25,12 +25,7 @@ PromiseReaction::PromiseReaction(Type type, Optional<PromiseCapability> capabili
void PromiseReaction::visit_edges(Cell::Visitor& visitor)
{
Cell::visit_edges(visitor);
- if (m_capability.has_value()) {
- auto& capability = m_capability.value();
- visitor.visit(capability.promise);
- visitor.visit(capability.resolve);
- visitor.visit(capability.reject);
- }
+ visitor.visit(m_capability);
}
}
diff --git a/Userland/Libraries/LibJS/Runtime/PromiseReaction.h b/Userland/Libraries/LibJS/Runtime/PromiseReaction.h
index 58d6dd63af..ef913c80c7 100644
--- a/Userland/Libraries/LibJS/Runtime/PromiseReaction.h
+++ b/Userland/Libraries/LibJS/Runtime/PromiseReaction.h
@@ -23,23 +23,23 @@ public:
Reject,
};
- static PromiseReaction* create(VM& vm, Type type, Optional<PromiseCapability> capability, Optional<JobCallback> handler);
+ static PromiseReaction* create(VM& vm, Type type, GCPtr<PromiseCapability> capability, Optional<JobCallback> handler);
virtual ~PromiseReaction() = default;
Type type() const { return m_type; }
- Optional<PromiseCapability> const& capability() const { return m_capability; }
+ GCPtr<PromiseCapability> capability() const { return m_capability; }
Optional<JobCallback>& handler() { return m_handler; }
Optional<JobCallback> const& handler() const { return m_handler; }
private:
- PromiseReaction(Type type, Optional<PromiseCapability> capability, Optional<JobCallback> handler);
+ PromiseReaction(Type type, GCPtr<PromiseCapability> capability, Optional<JobCallback> handler);
virtual void visit_edges(Visitor&) override;
Type m_type;
- Optional<PromiseCapability> m_capability;
+ GCPtr<PromiseCapability> m_capability;
Optional<JobCallback> m_handler;
};
diff --git a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp
index a967474cd3..35824d5d37 100644
--- a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp
+++ b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp
@@ -20,11 +20,11 @@ void PromiseValueList::visit_edges(Visitor& visitor)
visitor.visit(val);
}
-PromiseResolvingElementFunction::PromiseResolvingElementFunction(size_t index, PromiseValueList& values, PromiseCapability capability, RemainingElements& remaining_elements, Object& prototype)
+PromiseResolvingElementFunction::PromiseResolvingElementFunction(size_t index, PromiseValueList& values, NonnullGCPtr<PromiseCapability> capability, RemainingElements& remaining_elements, Object& prototype)
: NativeFunction(prototype)
, m_index(index)
, m_values(values)
- , m_capability(move(capability))
+ , m_capability(capability)
, m_remaining_elements(remaining_elements)
{
}
@@ -49,19 +49,17 @@ void PromiseResolvingElementFunction::visit_edges(Cell::Visitor& visitor)
Base::visit_edges(visitor);
visitor.visit(&m_values);
- visitor.visit(m_capability.promise);
- visitor.visit(m_capability.resolve);
- visitor.visit(m_capability.reject);
+ visitor.visit(m_capability);
visitor.visit(&m_remaining_elements);
}
-PromiseAllResolveElementFunction* PromiseAllResolveElementFunction::create(Realm& realm, size_t index, PromiseValueList& values, PromiseCapability capability, RemainingElements& remaining_elements)
+PromiseAllResolveElementFunction* PromiseAllResolveElementFunction::create(Realm& realm, size_t index, PromiseValueList& values, NonnullGCPtr<PromiseCapability> capability, RemainingElements& remaining_elements)
{
return realm.heap().allocate<PromiseAllResolveElementFunction>(realm, index, values, capability, remaining_elements, *realm.intrinsics().function_prototype());
}
-PromiseAllResolveElementFunction::PromiseAllResolveElementFunction(size_t index, PromiseValueList& values, PromiseCapability capability, RemainingElements& remaining_elements, Object& prototype)
- : PromiseResolvingElementFunction(index, values, move(capability), remaining_elements, prototype)
+PromiseAllResolveElementFunction::PromiseAllResolveElementFunction(size_t index, PromiseValueList& values, NonnullGCPtr<PromiseCapability> capability, RemainingElements& remaining_elements, Object& prototype)
+ : PromiseResolvingElementFunction(index, values, capability, remaining_elements, prototype)
{
}
@@ -80,20 +78,20 @@ ThrowCompletionOr<Value> PromiseAllResolveElementFunction::resolve_element()
auto* values_array = Array::create_from(realm, m_values.values());
// b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
- return JS::call(vm, *m_capability.resolve, js_undefined(), values_array);
+ return JS::call(vm, *m_capability->resolve(), js_undefined(), values_array);
}
// 11. Return undefined.
return js_undefined();
}
-PromiseAllSettledResolveElementFunction* PromiseAllSettledResolveElementFunction::create(Realm& realm, size_t index, PromiseValueList& values, PromiseCapability capability, RemainingElements& remaining_elements)
+PromiseAllSettledResolveElementFunction* PromiseAllSettledResolveElementFunction::create(Realm& realm, size_t index, PromiseValueList& values, NonnullGCPtr<PromiseCapability> capability, RemainingElements& remaining_elements)
{
return realm.heap().allocate<PromiseAllSettledResolveElementFunction>(realm, index, values, capability, remaining_elements, *realm.intrinsics().function_prototype());
}
-PromiseAllSettledResolveElementFunction::PromiseAllSettledResolveElementFunction(size_t index, PromiseValueList& values, PromiseCapability capability, RemainingElements& remaining_elements, Object& prototype)
- : PromiseResolvingElementFunction(index, values, move(capability), remaining_elements, prototype)
+PromiseAllSettledResolveElementFunction::PromiseAllSettledResolveElementFunction(size_t index, PromiseValueList& values, NonnullGCPtr<PromiseCapability> capability, RemainingElements& remaining_elements, Object& prototype)
+ : PromiseResolvingElementFunction(index, values, capability, remaining_elements, prototype)
{
}
@@ -121,20 +119,20 @@ ThrowCompletionOr<Value> PromiseAllSettledResolveElementFunction::resolve_elemen
auto* values_array = Array::create_from(realm, m_values.values());
// b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
- return JS::call(vm, *m_capability.resolve, js_undefined(), values_array);
+ return JS::call(vm, *m_capability->resolve(), js_undefined(), values_array);
}
// 15. Return undefined.
return js_undefined();
}
-PromiseAllSettledRejectElementFunction* PromiseAllSettledRejectElementFunction::create(Realm& realm, size_t index, PromiseValueList& values, PromiseCapability capability, RemainingElements& remaining_elements)
+PromiseAllSettledRejectElementFunction* PromiseAllSettledRejectElementFunction::create(Realm& realm, size_t index, PromiseValueList& values, NonnullGCPtr<PromiseCapability> capability, RemainingElements& remaining_elements)
{
return realm.heap().allocate<PromiseAllSettledRejectElementFunction>(realm, index, values, capability, remaining_elements, *realm.intrinsics().function_prototype());
}
-PromiseAllSettledRejectElementFunction::PromiseAllSettledRejectElementFunction(size_t index, PromiseValueList& values, PromiseCapability capability, RemainingElements& remaining_elements, Object& prototype)
- : PromiseResolvingElementFunction(index, values, move(capability), remaining_elements, prototype)
+PromiseAllSettledRejectElementFunction::PromiseAllSettledRejectElementFunction(size_t index, PromiseValueList& values, NonnullGCPtr<PromiseCapability> capability, RemainingElements& remaining_elements, Object& prototype)
+ : PromiseResolvingElementFunction(index, values, capability, remaining_elements, prototype)
{
}
@@ -162,20 +160,20 @@ ThrowCompletionOr<Value> PromiseAllSettledRejectElementFunction::resolve_element
auto* values_array = Array::create_from(realm, m_values.values());
// b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
- return JS::call(vm, *m_capability.resolve, js_undefined(), values_array);
+ return JS::call(vm, *m_capability->resolve(), js_undefined(), values_array);
}
// 15. Return undefined.
return js_undefined();
}
-PromiseAnyRejectElementFunction* PromiseAnyRejectElementFunction::create(Realm& realm, size_t index, PromiseValueList& errors, PromiseCapability capability, RemainingElements& remaining_elements)
+PromiseAnyRejectElementFunction* PromiseAnyRejectElementFunction::create(Realm& realm, size_t index, PromiseValueList& errors, NonnullGCPtr<PromiseCapability> capability, RemainingElements& remaining_elements)
{
return realm.heap().allocate<PromiseAnyRejectElementFunction>(realm, index, errors, capability, remaining_elements, *realm.intrinsics().function_prototype());
}
-PromiseAnyRejectElementFunction::PromiseAnyRejectElementFunction(size_t index, PromiseValueList& errors, PromiseCapability capability, RemainingElements& remaining_elements, Object& prototype)
- : PromiseResolvingElementFunction(index, errors, move(capability), remaining_elements, prototype)
+PromiseAnyRejectElementFunction::PromiseAnyRejectElementFunction(size_t index, PromiseValueList& errors, NonnullGCPtr<PromiseCapability> capability, RemainingElements& remaining_elements, Object& prototype)
+ : PromiseResolvingElementFunction(index, errors, capability, remaining_elements, prototype)
{
}
@@ -198,7 +196,7 @@ ThrowCompletionOr<Value> PromiseAnyRejectElementFunction::resolve_element()
MUST(error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true }));
// c. Return ? Call(promiseCapability.[[Reject]], undefined, « error »).
- return JS::call(vm, *m_capability.reject, js_undefined(), error);
+ return JS::call(vm, *m_capability->reject(), js_undefined(), error);
}
return js_undefined();
diff --git a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.h b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.h
index 62cb018009..bbfeff46ad 100644
--- a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.h
+++ b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.h
@@ -51,13 +51,13 @@ public:
virtual ThrowCompletionOr<Value> call() override;
protected:
- explicit PromiseResolvingElementFunction(size_t, PromiseValueList&, PromiseCapability, RemainingElements&, Object& prototype);
+ explicit PromiseResolvingElementFunction(size_t, PromiseValueList&, NonnullGCPtr<PromiseCapability>, RemainingElements&, Object& prototype);
virtual ThrowCompletionOr<Value> resolve_element() = 0;
size_t m_index { 0 };
PromiseValueList& m_values;
- PromiseCapability m_capability;
+ NonnullGCPtr<PromiseCapability> m_capability;
RemainingElements& m_remaining_elements;
private:
@@ -71,12 +71,12 @@ class PromiseAllResolveElementFunction final : public PromiseResolvingElementFun
JS_OBJECT(PromiseResolvingFunction, NativeFunction);
public:
- static PromiseAllResolveElementFunction* create(Realm&, size_t, PromiseValueList&, PromiseCapability, RemainingElements&);
+ static PromiseAllResolveElementFunction* create(Realm&, size_t, PromiseValueList&, NonnullGCPtr<PromiseCapability>, RemainingElements&);
virtual ~PromiseAllResolveElementFunction() override = default;
private:
- explicit PromiseAllResolveElementFunction(size_t, PromiseValueList&, PromiseCapability, RemainingElements&, Object& prototype);
+ explicit PromiseAllResolveElementFunction(size_t, PromiseValueList&, NonnullGCPtr<PromiseCapability>, RemainingElements&, Object& prototype);
virtual ThrowCompletionOr<Value> resolve_element() override;
};
@@ -86,12 +86,12 @@ class PromiseAllSettledResolveElementFunction final : public PromiseResolvingEle
JS_OBJECT(PromiseResolvingFunction, NativeFunction);
public:
- static PromiseAllSettledResolveElementFunction* create(Realm&, size_t, PromiseValueList&, PromiseCapability, RemainingElements&);
+ static PromiseAllSettledResolveElementFunction* create(Realm&, size_t, PromiseValueList&, NonnullGCPtr<PromiseCapability>, RemainingElements&);
virtual ~PromiseAllSettledResolveElementFunction() override = default;
private:
- explicit PromiseAllSettledResolveElementFunction(size_t, PromiseValueList&, PromiseCapability, RemainingElements&, Object& prototype);
+ explicit PromiseAllSettledResolveElementFunction(size_t, PromiseValueList&, NonnullGCPtr<PromiseCapability>, RemainingElements&, Object& prototype);
virtual ThrowCompletionOr<Value> resolve_element() override;
};
@@ -101,12 +101,12 @@ class PromiseAllSettledRejectElementFunction final : public PromiseResolvingElem
JS_OBJECT(PromiseResolvingFunction, PromiseResolvingElementFunction);
public:
- static PromiseAllSettledRejectElementFunction* create(Realm&, size_t, PromiseValueList&, PromiseCapability, RemainingElements&);
+ static PromiseAllSettledRejectElementFunction* create(Realm&, size_t, PromiseValueList&, NonnullGCPtr<PromiseCapability>, RemainingElements&);
virtual ~PromiseAllSettledRejectElementFunction() override = default;
private:
- explicit PromiseAllSettledRejectElementFunction(size_t, PromiseValueList&, PromiseCapability, RemainingElements&, Object& prototype);
+ explicit PromiseAllSettledRejectElementFunction(size_t, PromiseValueList&, NonnullGCPtr<PromiseCapability>, RemainingElements&, Object& prototype);
virtual ThrowCompletionOr<Value> resolve_element() override;
};
@@ -116,12 +116,12 @@ class PromiseAnyRejectElementFunction final : public PromiseResolvingElementFunc
JS_OBJECT(PromiseResolvingFunction, PromiseResolvingElementFunction);
public:
- static PromiseAnyRejectElementFunction* create(Realm&, size_t, PromiseValueList&, PromiseCapability, RemainingElements&);
+ static PromiseAnyRejectElementFunction* create(Realm&, size_t, PromiseValueList&, NonnullGCPtr<PromiseCapability>, RemainingElements&);
virtual ~PromiseAnyRejectElementFunction() override = default;
private:
- explicit PromiseAnyRejectElementFunction(size_t, PromiseValueList&, PromiseCapability, RemainingElements&, Object& prototype);
+ explicit PromiseAnyRejectElementFunction(size_t, PromiseValueList&, NonnullGCPtr<PromiseCapability>, RemainingElements&, Object& prototype);
virtual ThrowCompletionOr<Value> resolve_element() override;
};
diff --git a/Userland/Libraries/LibJS/Runtime/ShadowRealm.cpp b/Userland/Libraries/LibJS/Runtime/ShadowRealm.cpp
index 74b4cad7f4..cf85dd83b1 100644
--- a/Userland/Libraries/LibJS/Runtime/ShadowRealm.cpp
+++ b/Userland/Libraries/LibJS/Runtime/ShadowRealm.cpp
@@ -276,7 +276,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(VM& vm, String specifier_stri
});
// 13. Return PerformPromiseThen(innerCapability.[[Promise]], onFulfilled, callerRealm.[[Intrinsics]].[[%ThrowTypeError%]], promiseCapability).
- return verify_cast<Promise>(inner_capability.promise)->perform_then(on_fulfilled, throw_type_error, promise_capability);
+ return verify_cast<Promise>(inner_capability->promise().ptr())->perform_then(on_fulfilled, throw_type_error, promise_capability);
}
// 3.1.5 GetWrappedValue ( callerRealm: a Realm Record, value: unknown, ), https://tc39.es/proposal-shadowrealm/#sec-getwrappedvalue
diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp
index 1b15a1571d..40a17de1c1 100644
--- a/Userland/Libraries/LibJS/Runtime/VM.cpp
+++ b/Userland/Libraries/LibJS/Runtime/VM.cpp
@@ -70,7 +70,7 @@ VM::VM(OwnPtr<CustomData> custom_data)
return resolve_imported_module(move(referencing_script_or_module), specifier);
};
- host_import_module_dynamically = [&](ScriptOrModule, ModuleRequest const&, PromiseCapability promise_capability) {
+ host_import_module_dynamically = [&](ScriptOrModule, ModuleRequest const&, PromiseCapability const& promise_capability) {
// By default, we throw on dynamic imports this is to prevent arbitrary file access by scripts.
VERIFY(current_realm());
auto& realm = *current_realm();
@@ -85,11 +85,11 @@ VM::VM(OwnPtr<CustomData> custom_data)
NativeFunction::create(realm, "", [](auto&) -> ThrowCompletionOr<Value> {
VERIFY_NOT_REACHED();
}),
- NativeFunction::create(realm, "", [reject = make_handle(promise_capability.reject)](auto& vm) -> ThrowCompletionOr<Value> {
+ NativeFunction::create(realm, "", [&promise_capability](auto& vm) -> ThrowCompletionOr<Value> {
auto error = vm.argument(0);
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « error »).
- MUST(call(vm, reject.cell(), js_undefined(), error));
+ MUST(call(vm, *promise_capability.reject(), js_undefined(), error));
// b. Return undefined.
return js_undefined();
@@ -97,7 +97,7 @@ VM::VM(OwnPtr<CustomData> custom_data)
{});
};
- host_finish_dynamic_import = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier, PromiseCapability promise_capability, Promise* promise) {
+ host_finish_dynamic_import = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier, PromiseCapability const& promise_capability, Promise* promise) {
return finish_dynamic_import(move(referencing_script_or_module), specifier, promise_capability, promise);
};
@@ -146,7 +146,7 @@ VM::VM(OwnPtr<CustomData> custom_data)
void VM::enable_default_host_import_module_dynamically_hook()
{
- host_import_module_dynamically = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier, PromiseCapability promise_capability) {
+ host_import_module_dynamically = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier, PromiseCapability const& promise_capability) {
return import_module_dynamically(move(referencing_script_or_module), specifier, promise_capability);
};
}
@@ -976,7 +976,7 @@ ThrowCompletionOr<NonnullGCPtr<Module>> VM::resolve_imported_module(ScriptOrModu
}
// 16.2.1.8 HostImportModuleDynamically ( referencingScriptOrModule, specifier, promiseCapability ), https://tc39.es/ecma262/#sec-hostimportmoduledynamically
-void VM::import_module_dynamically(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability promise_capability)
+void VM::import_module_dynamically(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability const& promise_capability)
{
auto& realm = *current_realm();
@@ -995,7 +995,7 @@ void VM::import_module_dynamically(ScriptOrModule referencing_script_or_module,
auto* promise = Promise::create(realm);
ScopeGuard finish_dynamic_import = [&] {
- host_finish_dynamic_import(referencing_script_or_module, move(module_request), promise_capability, promise);
+ host_finish_dynamic_import(referencing_script_or_module, module_request, promise_capability, promise);
};
// Generally within ECMA262 we always get a referencing_script_or_moulde. However, ShadowRealm gives an explicit null.
@@ -1034,14 +1034,14 @@ void VM::import_module_dynamically(ScriptOrModule referencing_script_or_module,
}
// 16.2.1.9 FinishDynamicImport ( referencingScriptOrModule, specifier, promiseCapability, innerPromise ), https://tc39.es/ecma262/#sec-finishdynamicimport
-void VM::finish_dynamic_import(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability promise_capability, Promise* inner_promise)
+void VM::finish_dynamic_import(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability const& promise_capability, Promise* inner_promise)
{
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] finish_dynamic_import on {}", module_request.module_specifier);
auto& realm = *current_realm();
// 1. Let fulfilledClosure be a new Abstract Closure with parameters (result) that captures referencingScriptOrModule, specifier, and promiseCapability and performs the following steps when called:
- auto fulfilled_closure = [referencing_script_or_module, module_request = move(module_request), resolve_function = make_handle(promise_capability.resolve), reject_function = make_handle(promise_capability.reject)](VM& vm) -> ThrowCompletionOr<Value> {
+ auto fulfilled_closure = [referencing_script_or_module = move(referencing_script_or_module), module_request = move(module_request), &promise_capability](VM& vm) -> ThrowCompletionOr<Value> {
auto result = vm.argument(0);
// a. Assert: result is undefined.
VERIFY(result.is_undefined());
@@ -1057,12 +1057,12 @@ void VM::finish_dynamic_import(ScriptOrModule referencing_script_or_module, Modu
// e. If namespace is an abrupt completion, then
if (namespace_.is_throw_completion()) {
// i. Perform ! Call(promiseCapability.[[Reject]], undefined, « namespace.[[Value]] »).
- MUST(call(vm, reject_function.cell(), js_undefined(), *namespace_.throw_completion().value()));
+ MUST(call(vm, *promise_capability.reject(), js_undefined(), *namespace_.throw_completion().value()));
}
// f. Else,
else {
// i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « namespace.[[Value]] »).
- MUST(call(vm, resolve_function.cell(), js_undefined(), namespace_.release_value()));
+ MUST(call(vm, *promise_capability.resolve(), js_undefined(), namespace_.release_value()));
}
// g. Return unused.
// NOTE: We don't support returning an empty/optional/unused value here.
@@ -1073,10 +1073,10 @@ void VM::finish_dynamic_import(ScriptOrModule referencing_script_or_module, Modu
auto* on_fulfilled = NativeFunction::create(realm, move(fulfilled_closure), 0, "");
// 3. Let rejectedClosure be a new Abstract Closure with parameters (error) that captures promiseCapability and performs the following steps when called:
- auto rejected_closure = [rejected_function = make_handle(promise_capability.reject)](VM& vm) -> ThrowCompletionOr<Value> {
+ auto rejected_closure = [&promise_capability](VM& vm) -> ThrowCompletionOr<Value> {
auto error = vm.argument(0);
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « error »).
- MUST(call(vm, rejected_function.cell(), js_undefined(), error));
+ MUST(call(vm, *promise_capability.reject(), js_undefined(), error));
// b. Return unused.
// NOTE: We don't support returning an empty/optional/unused value here.
diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h
index 5d037e8013..63e5a2e52c 100644
--- a/Userland/Libraries/LibJS/Runtime/VM.h
+++ b/Userland/Libraries/LibJS/Runtime/VM.h
@@ -223,8 +223,8 @@ public:
ScriptOrModule get_active_script_or_module() const;
Function<ThrowCompletionOr<NonnullGCPtr<Module>>(ScriptOrModule, ModuleRequest const&)> host_resolve_imported_module;
- Function<void(ScriptOrModule, ModuleRequest, PromiseCapability)> host_import_module_dynamically;
- Function<void(ScriptOrModule, ModuleRequest const&, PromiseCapability, Promise*)> host_finish_dynamic_import;
+ Function<void(ScriptOrModule, ModuleRequest, PromiseCapability const&)> host_import_module_dynamically;
+ Function<void(ScriptOrModule, ModuleRequest const&, PromiseCapability const&, Promise*)> host_finish_dynamic_import;
Function<HashMap<PropertyKey, Value>(SourceTextModule const&)> host_get_import_meta_properties;
Function<void(Object*, SourceTextModule const&)> host_finalize_import_meta;
@@ -250,8 +250,8 @@ private:
ThrowCompletionOr<NonnullGCPtr<Module>> resolve_imported_module(ScriptOrModule referencing_script_or_module, ModuleRequest const& module_request);
ThrowCompletionOr<void> link_and_eval_module(Module& module);
- void import_module_dynamically(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability promise_capability);
- void finish_dynamic_import(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability promise_capability, Promise* inner_promise);
+ void import_module_dynamically(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability const& promise_capability);
+ void finish_dynamic_import(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability const& promise_capability, Promise* inner_promise);
HashMap<String, PrimitiveString*> m_string_cache;