LibJS: Make Completion.[[Value]] non-optional

Instead, just use js_undefined() whenever the [[Value]] field is unused.
This avoids a whole bunch of presence checks.
This commit is contained in:
Andreas Kling 2025-04-04 18:11:45 +02:00
parent 7fafaabf56
commit 4e006e3686
65 changed files with 225 additions and 250 deletions

View file

@ -194,7 +194,7 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluatio
VERIFY_NOT_REACHED();
}
return ClassValue { normal_completion({}) };
return ClassValue { normal_completion(js_undefined()) };
} else {
auto& private_name = property_key_or_private_name.get<PrivateName>();
switch (kind()) {
@ -417,8 +417,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
instance_fields.append(move(*class_field_definition_ptr));
} else if (element->class_element_kind() == ClassElement::ElementKind::StaticInitializer) {
// We use Completion to hold the ClassStaticBlockDefinition Record.
VERIFY(element_value.has<Completion>() && element_value.get<Completion>().value().has_value());
auto& element_object = element_value.get<Completion>().value()->as_object();
auto& element_object = element_value.get<Completion>().value().as_object();
VERIFY(is<ECMAScriptFunctionObject>(element_object));
static_elements.append(GC::Ref { static_cast<ECMAScriptFunctionObject&>(element_object) });
}

View file

@ -244,7 +244,7 @@ ThrowCompletionOr<Value> Interpreter::run(Script& script_record, GC::Ptr<Environ
// 12. Let result be Completion(GlobalDeclarationInstantiation(script, globalEnv)).
auto instantiation_result = script.global_declaration_instantiation(vm, global_environment);
Completion result = instantiation_result.is_throw_completion() ? instantiation_result.throw_completion() : normal_completion({});
Completion result = instantiation_result.is_throw_completion() ? instantiation_result.throw_completion() : normal_completion(js_undefined());
// 13. If result.[[Type]] is normal, then
if (result.type() == Completion::Type::Normal) {
@ -269,11 +269,11 @@ ThrowCompletionOr<Value> Interpreter::run(Script& script_record, GC::Ptr<Environ
if (result_or_error.value.is_error())
result = result_or_error.value.release_error();
else
result = result_or_error.return_register_value;
result = result_or_error.return_register_value.value_or(js_undefined());
}
// b. If result is a normal completion and result.[[Value]] is empty, then
if (result.type() == Completion::Type::Normal && !result.value().has_value()) {
if (result.type() == Completion::Type::Normal && result.value().is_empty()) {
// i. Set result to NormalCompletion(undefined).
result = normal_completion(js_undefined());
}
@ -300,11 +300,12 @@ ThrowCompletionOr<Value> Interpreter::run(Script& script_record, GC::Ptr<Environ
// 17. Return ? result.
if (result.is_abrupt()) {
VERIFY(result.type() == Completion::Type::Throw);
return result.release_error();
auto error = result.release_error();
VERIFY(!error.value().is_empty());
return error;
}
VERIFY(result.value().has_value());
return *result.value();
return result.value();
}
ThrowCompletionOr<Value> Interpreter::run(SourceTextModule& module)
@ -359,7 +360,7 @@ Interpreter::HandleExceptionResponse Interpreter::handle_exception(size_t& progr
FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
{
if (vm().did_reach_stack_space_limit()) {
reg(Register::exception()) = vm().throw_completion<InternalError>(ErrorType::CallStackSizeExceeded).release_value().value();
reg(Register::exception()) = vm().throw_completion<InternalError>(ErrorType::CallStackSizeExceeded).value();
return;
}
@ -2940,7 +2941,7 @@ ThrowCompletionOr<void> IteratorClose::execute_impl(Bytecode::Interpreter& inter
auto& iterator = static_cast<IteratorRecord&>(interpreter.get(m_iterator_record).as_cell());
// FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!)
TRY(iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value }));
TRY(iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value.value_or(js_undefined()) }));
return {};
}
@ -2950,7 +2951,7 @@ ThrowCompletionOr<void> AsyncIteratorClose::execute_impl(Bytecode::Interpreter&
auto& iterator = static_cast<IteratorRecord&>(interpreter.get(m_iterator_record).as_cell());
// FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!)
TRY(async_iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value }));
TRY(async_iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value.value_or(js_undefined()) }));
return {};
}

View file

@ -161,7 +161,7 @@ void continue_module_loading(GraphLoadingState& state, ThrowCompletionOr<GC::Ref
auto value = module_completion.throw_completion().value();
// b. Perform ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »).
MUST(call(state.vm(), *state.promise_capability->reject(), js_undefined(), *value));
MUST(call(state.vm(), *state.promise_capability->reject(), js_undefined(), value));
}
// 4. Return UNUSED.
@ -389,10 +389,10 @@ ThrowCompletionOr<Promise*> CyclicModule::evaluate(VM& vm)
// c. Assert: module.[[EvaluationError]] is result.
VERIFY(m_evaluation_error.is_error());
VERIFY(same_value(*m_evaluation_error.throw_completion().value(), *result.throw_completion().value()));
VERIFY(same_value(m_evaluation_error.throw_completion().value(), result.throw_completion().value()));
// d. Perform ! Call(capability.[[Reject]], undefined, « result.[[Value]] »).
MUST(call(vm, *m_top_level_capability->reject(), js_undefined(), *result.throw_completion().value()));
MUST(call(vm, *m_top_level_capability->reject(), js_undefined(), result.throw_completion().value()));
}
// 10. Else,
else {
@ -741,7 +741,7 @@ void CyclicModule::async_module_execution_fulfilled(VM& vm)
// ii. If result is an abrupt completion, then
if (result.is_throw_completion()) {
// 1. Perform AsyncModuleExecutionRejected(m, result.[[Value]]).
module->async_module_execution_rejected(vm, *result.throw_completion().value());
module->async_module_execution_rejected(vm, result.throw_completion().value());
}
// iii. Else,
else {
@ -838,7 +838,7 @@ void continue_dynamic_import(GC::Ref<PromiseCapability> promise_capability, Thro
// 1. If moduleCompletion is an abrupt completion, then
if (module_completion.is_throw_completion()) {
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « moduleCompletion.[[Value]] »).
MUST(call(vm, *promise_capability->reject(), js_undefined(), *module_completion.throw_completion().value()));
MUST(call(vm, *promise_capability->reject(), js_undefined(), module_completion.throw_completion().value()));
// b. Return unused.
return;
@ -874,7 +874,7 @@ void continue_dynamic_import(GC::Ref<PromiseCapability> promise_capability, Thro
// b. If link is an abrupt completion, then
if (link.is_throw_completion()) {
// i. Perform ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »).
MUST(call(vm, *promise_capability->reject(), js_undefined(), *link.throw_completion().value()));
MUST(call(vm, *promise_capability->reject(), js_undefined(), link.throw_completion().value()));
// ii. Return unused.
return js_undefined();

View file

@ -690,7 +690,7 @@ ErrorOr<void> print_intl_date_time_format(JS::PrintContext& print_context, JS::I
return {};
});
if (result.is_throw_completion() && result.throw_completion().value()->is_null())
if (result.is_throw_completion() && result.throw_completion().value().is_null())
return Error::from_errno(ENOMEM); // probably
return {};

View file

@ -1631,10 +1631,10 @@ Completion dispose_resources(VM& vm, DisposeCapability& dispose_capability, Comp
// 1. If completion is a throw completion, then
if (completion.type() == Completion::Type::Throw) {
// a. Set result to result.[[Value]].
auto result_value = result.error().value().value();
auto result_value = result.error().value();
// b. Let suppressed be completion.[[Value]].
auto suppressed = completion.value().value();
auto suppressed = completion.value();
// c. Let error be a newly created SuppressedError object.
auto error = SuppressedError::create(*vm.current_realm());

View file

@ -241,7 +241,7 @@ ThrowCompletionOr<GroupsType> group_by(VM& vm, Value items, Value callback_funct
// f. IfAbruptCloseIterator(key, iteratorRecord).
if (key.is_error())
return Completion { *TRY(iterator_close(vm, iterator_record, key.release_error())) };
return Completion { TRY(iterator_close(vm, iterator_record, key.release_error())) };
// g. If keyCoercion is property, then
if constexpr (IsSame<KeyType, PropertyKey>) {
@ -250,7 +250,7 @@ ThrowCompletionOr<GroupsType> group_by(VM& vm, Value items, Value callback_funct
// ii. IfAbruptCloseIterator(key, iteratorRecord).
if (property_key.is_error())
return Completion { *TRY(iterator_close(vm, iterator_record, property_key.release_error())) };
return Completion { TRY(iterator_close(vm, iterator_record, property_key.release_error())) };
add_value_to_keyed_group(vm, groups, property_key.release_value(), value);
}

View file

@ -60,7 +60,7 @@ ThrowCompletionOr<GC::Ref<Object>> ArrayBufferConstructor::construct(FunctionObj
if (byte_length_or_error.is_error()) {
auto error = byte_length_or_error.release_error();
if (error.value()->is_object() && is<RangeError>(error.value()->as_object())) {
if (error.value().is_object() && is<RangeError>(error.value().as_object())) {
// Re-throw more specific RangeError
return vm.throw_completion<RangeError>(ErrorType::InvalidLength, "array buffer");
}

View file

@ -191,7 +191,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
auto error = vm.throw_completion<TypeError>(ErrorType::ArrayMaxSize);
// 2. Return ? IteratorClose(iteratorRecord, error).
return *TRY(iterator_close(vm, iterator, move(error)));
return TRY(iterator_close(vm, iterator, move(error)));
}
// ii. Let Pk be ! ToString(𝔽(k)).
@ -218,7 +218,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
// 2. IfAbruptCloseIterator(mappedValue, iteratorRecord).
if (mapped_value_or_error.is_error())
return *TRY(iterator_close(vm, iterator, mapped_value_or_error.release_error()));
return TRY(iterator_close(vm, iterator, mapped_value_or_error.release_error()));
mapped_value = mapped_value_or_error.release_value();
}
// vi. Else, let mappedValue be nextValue.
@ -231,7 +231,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
// viii. IfAbruptCloseIterator(defineStatus, iteratorRecord).
if (result_or_error.is_error())
return *TRY(iterator_close(vm, iterator, result_or_error.release_error()));
return TRY(iterator_close(vm, iterator, result_or_error.release_error()));
// ix. Set k to k + 1.
}
@ -374,7 +374,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from_async)
auto error = vm.throw_completion<TypeError>(ErrorType::ArrayMaxSize);
// b. Return ? AsyncIteratorClose(iteratorRecord, error).
return *TRY(async_iterator_close(vm, *iterator_record, move(error)));
return TRY(async_iterator_close(vm, *iterator_record, move(error)));
}
// 2. Let Pk be ! ToString(𝔽(k)).
@ -443,7 +443,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from_async)
// 12. If defineStatus is an abrupt completion, return ? AsyncIteratorClose(iteratorRecord, defineStatus).
if (define_status.is_error())
return *TRY(iterator_close(vm, *iterator_record, define_status.release_error()));
return TRY(iterator_close(vm, *iterator_record, define_status.release_error()));
// 13. Set k to k + 1.
}

View file

@ -141,7 +141,7 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncDisposableStackPrototype::dispose_async)
auto result = TRY_OR_REJECT(vm, promise_capability, dispose_resources(vm, async_disposable_stack.dispose_capability(), normal_completion(js_undefined())));
// 8. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result »).
MUST(call(vm, *promise_capability->resolve(), js_undefined(), *result));
MUST(call(vm, *promise_capability->resolve(), js_undefined(), result));
// 9. Return promiseCapability.[[Promise]].
return promise_capability->promise();

View file

@ -42,8 +42,7 @@ void AsyncGenerator::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
for (auto const& request : m_async_generator_queue) {
if (request.completion.value().has_value())
visitor.visit(*request.completion.value());
visitor.visit(request.completion.value());
visitor.visit(request.capability);
}
visitor.visit(m_generating_function);
@ -155,8 +154,6 @@ void AsyncGenerator::execute(VM& vm, Completion completion)
{
while (true) {
// Loosely based on step 4 of https://tc39.es/ecma262/#sec-asyncgeneratorstart
VERIFY(completion.value().has_value());
auto generated_value = [](Value value) -> Value {
if (value.is_cell())
return static_cast<GeneratorResult const&>(value.as_cell()).result();
@ -349,7 +346,7 @@ void AsyncGenerator::await_return()
VERIFY(completion.type() == Completion::Type::Return);
// 6. Let promiseCompletion be Completion(PromiseResolve(%Promise%, _completion_.[[Value]])).
auto promise_completion = promise_resolve(vm, realm.intrinsics().promise_constructor(), completion.value().value());
auto promise_completion = promise_resolve(vm, realm.intrinsics().promise_constructor(), completion.value());
// 7. If promiseCompletion is an abrupt completion, then
if (promise_completion.is_throw_completion()) {
@ -442,7 +439,7 @@ void AsyncGenerator::complete_step(Completion completion, bool done, Realm* real
auto promise_capability = next.capability;
// 5. Let value be completion.[[Value]].
auto value = completion.value().value();
auto value = completion.value();
// 6. If completion.[[Type]] is throw, then
if (completion.type() == Completion::Type::Throw) {

View file

@ -38,9 +38,8 @@ namespace JS {
if (_temporary_result.is_error()) { \
auto _completion = _temporary_result.release_error(); \
\
VERIFY(_completion.value().has_value()); \
VERIFY(_completion.value()->is_object()); \
VERIFY(::AK::is<JS::InternalError>(_completion.value()->as_object())); \
VERIFY(_completion.value().is_object()); \
VERIFY(::AK::is<JS::InternalError>(_completion.value().as_object())); \
\
return _completion; \
} \
@ -61,13 +60,12 @@ public:
Throw,
};
ALWAYS_INLINE Completion(Type type, Optional<Value> value)
ALWAYS_INLINE Completion(Type type, Value value)
: m_type(type)
, m_value(move(value))
, m_value(value)
{
VERIFY(type != Type::Empty);
if (m_value.has_value())
VERIFY(!m_value->is_empty());
VERIFY(!value.is_empty());
}
Completion(ThrowCompletionOr<Value> const&);
@ -79,11 +77,6 @@ public:
{
}
ALWAYS_INLINE Completion(Optional<Value> value)
: Completion(Type::Normal, move(value))
{
}
ALWAYS_INLINE Completion()
: Completion(js_undefined())
{
@ -99,19 +92,18 @@ public:
VERIFY(m_type != Type::Empty);
return m_type;
}
[[nodiscard]] Optional<Value>& value() { return m_value; }
[[nodiscard]] Optional<Value> const& value() const { return m_value; }
[[nodiscard]] Value& value() { return m_value; }
[[nodiscard]] Value const& value() const { return m_value; }
// "abrupt completion refers to any completion with a [[Type]] value other than normal"
[[nodiscard]] bool is_abrupt() const { return m_type != Type::Normal; }
// These are for compatibility with the TRY() macro in AK.
[[nodiscard]] bool is_error() const { return m_type == Type::Throw; }
[[nodiscard]] Optional<Value> release_value() { return move(m_value); }
[[nodiscard]] Value release_value() { return m_value; }
Completion release_error()
{
VERIFY(is_error());
VERIFY(m_value.has_value());
return { m_type, release_value() };
}
@ -131,7 +123,7 @@ private:
}
Type m_type { Type::Normal }; // [[Type]]
Optional<Value> m_value; // [[Value]]
Value m_value; // [[Value]]
// NOTE: We don't need the [[Target]] slot since control flow is handled in bytecode.
};
@ -244,7 +236,7 @@ public:
// Not `explicit` on purpose so that `return vm.throw_completion<Error>(...);` is possible.
ALWAYS_INLINE ThrowCompletionOr(Completion throw_completion)
: m_value_or_error(ErrorValue { throw_completion.release_error().value().value() })
: m_value_or_error(ErrorValue { throw_completion.release_error().value() })
{
}
@ -314,7 +306,7 @@ public:
ThrowCompletionOr<Value> await(VM&, Value);
// 6.2.4.1 NormalCompletion ( value ), https://tc39.es/ecma262/#sec-normalcompletion
inline Completion normal_completion(Optional<Value> value)
inline Completion normal_completion(Value value)
{
// 1. Return Completion Record { [[Type]]: normal, [[Value]]: value, [[Target]]: empty }.
return { Completion::Type::Normal, move(value) };

View file

@ -15,8 +15,7 @@ CompletionCell::~CompletionCell() = default;
void CompletionCell::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
if (m_completion.value().has_value())
visitor.visit(m_completion.value().value());
visitor.visit(m_completion.value());
}
}

View file

@ -115,7 +115,7 @@ JS_DEFINE_NATIVE_FUNCTION(DisposableStackPrototype::dispose)
disposable_stack->set_disposed();
// 5. Return DisposeResources(disposableStack.[[DisposeCapability]], NormalCompletion(undefined)).
return *TRY(dispose_resources(vm, disposable_stack->dispose_capability(), normal_completion(js_undefined())));
return TRY(dispose_resources(vm, disposable_stack->dispose_capability(), normal_completion(js_undefined())));
}
// 12.3.3.4 get DisposableStack.prototype.disposed, https://tc39.es/proposal-explicit-resource-management/#sec-get-disposablestack.prototype.disposed

View file

@ -436,7 +436,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
// 8. If result.[[Type]] is return, return result.[[Value]].
if (result.type() == Completion::Type::Return)
return *result.value();
return result.value();
// 9. Assert: result is a throw completion.
VERIFY(result.type() == Completion::Type::Throw);
@ -520,15 +520,15 @@ ThrowCompletionOr<GC::Ref<Object>> ECMAScriptFunctionObject::internal_construct(
VERIFY(result.type() == Completion::Type::Return);
// 12. If Type(result.[[Value]]) is Object, return result.[[Value]].
if (result.value()->is_object())
return result.value()->as_object();
if (result.value().is_object())
return result.value().as_object();
// 13. If kind is base, return thisArgument.
if (kind == ConstructorKind::Base)
return *this_argument;
// 14. If result.[[Value]] is not undefined, throw a TypeError exception.
if (!result.value()->is_undefined())
if (!result.value().is_undefined())
return vm.throw_completion<TypeError>(ErrorType::DerivedConstructorReturningInvalidValue);
// 15. Let thisBinding be ? constructorEnv.GetThisBinding().
@ -771,7 +771,7 @@ void async_block_start(VM& vm, T const& async_body, PromiseCapability const& pro
// g. Else if result is a return completion, 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()));
}
// h. Else,
else {
@ -779,7 +779,7 @@ void async_block_start(VM& vm, T const& async_body, PromiseCapability const& pro
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()));
}
// i. Return unused.
// NOTE: We don't support returning an empty/optional/unused value here.

View file

@ -82,8 +82,6 @@ ThrowCompletionOr<Value> GeneratorObject::execute(VM& vm, Completion const& comp
{
// Loosely based on step 4 of https://tc39.es/ecma262/#sec-generatorstart mixed with https://tc39.es/ecma262/#sec-generatoryield at the end.
VERIFY(completion.value().has_value());
auto generated_value = [](Value value) -> Value {
if (value.is_cell())
return static_cast<GeneratorResult const&>(value.as_cell()).result();
@ -167,9 +165,6 @@ ThrowCompletionOr<Value> GeneratorObject::resume(VM& vm, Value value, Optional<S
// 27.5.3.4 GeneratorResumeAbrupt ( generator, abruptCompletion, generatorBrand ), https://tc39.es/ecma262/#sec-generatorresumeabrupt
ThrowCompletionOr<Value> GeneratorObject::resume_abrupt(JS::VM& vm, JS::Completion abrupt_completion, Optional<StringView> const& generator_brand)
{
// Not part of the spec, but the spec assumes abruptCompletion.[[Value]] is not empty.
VERIFY(abrupt_completion.value().has_value());
// 1. Let state be ? GeneratorValidate(generator, generatorBrand).
auto state = TRY(validate(vm, generator_brand));
@ -190,7 +185,7 @@ ThrowCompletionOr<Value> GeneratorObject::resume_abrupt(JS::VM& vm, JS::Completi
// a. If abruptCompletion.[[Type]] is return, then
if (abrupt_completion.type() == Completion::Type::Return) {
// i. Return CreateIterResultObject(abruptCompletion.[[Value]], true).
return create_iterator_result_object(vm, abrupt_completion.value().value(), true);
return create_iterator_result_object(vm, abrupt_completion.value(), true);
}
// b. Return ? abruptCompletion.

View file

@ -43,7 +43,7 @@ Value IteratorHelper::result(Value value)
ThrowCompletionOr<Value> IteratorHelper::close_result(VM& vm, Completion completion)
{
set_generator_state(GeneratorState::Completed);
return *TRY(iterator_close(vm, underlying_iterator(), move(completion)));
return TRY(iterator_close(vm, underlying_iterator(), move(completion)));
}
ThrowCompletionOr<Value> IteratorHelper::execute(VM& vm, JS::Completion const& completion)

View file

@ -56,7 +56,7 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorHelperPrototype::return_)
// b. NOTE: Once a generator enters the completed state it never leaves it and its associated execution context is never resumed. Any execution state associated with O can be discarded at this point.
// c. Perform ? IteratorClose(O.[[UnderlyingIterator]], NormalCompletion(unused)).
TRY(iterator_close(vm, iterator->underlying_iterator(), normal_completion({})));
TRY(iterator_close(vm, iterator->underlying_iterator(), normal_completion(js_undefined())));
// d. Return CreateIterResultObject(undefined, true).
return create_iterator_result_object(vm, js_undefined(), true);

View file

@ -175,11 +175,11 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::every)
// d. IfAbruptCloseIterator(result, iterated).
if (result.is_error())
return *TRY(iterator_close(vm, iterated, result.release_error()));
return TRY(iterator_close(vm, iterated, result.release_error()));
// e. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).
if (!result.value().to_boolean())
return *TRY(iterator_close(vm, iterated, normal_completion(Value { false })));
return TRY(iterator_close(vm, iterated, normal_completion(Value { false })));
// f. Set counter to counter + 1.
++counter;
@ -280,11 +280,11 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::find)
// d. IfAbruptCloseIterator(result, iterated).
if (result.is_error())
return *TRY(iterator_close(vm, iterated, result.release_error()));
return TRY(iterator_close(vm, iterated, result.release_error()));
// e. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(value)).
if (result.value().to_boolean())
return *TRY(iterator_close(vm, iterated, normal_completion(value)));
return TRY(iterator_close(vm, iterated, normal_completion(*value)));
// f. Set counter to counter + 1.
++counter;
@ -466,7 +466,7 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::for_each)
// d. IfAbruptCloseIterator(result, iterated).
if (result.is_error())
return *TRY(iterator_close(vm, iterated, result.release_error()));
return TRY(iterator_close(vm, iterated, result.release_error()));
// e. Set counter to counter + 1.
++counter;
@ -585,7 +585,7 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::reduce)
// d. IfAbruptCloseIterator(result, iterated).
if (result.is_error())
return *TRY(iterator_close(vm, iterated, result.release_error()));
return TRY(iterator_close(vm, iterated, result.release_error()));
// e. Set accumulator to result.[[Value]].
accumulator = result.release_value();
@ -628,11 +628,11 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::some)
// d. IfAbruptCloseIterator(result, iterated).
if (result.is_error())
return *TRY(iterator_close(vm, iterated, result.release_error()));
return TRY(iterator_close(vm, iterated, result.release_error()));
// e. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(true)).
if (result.value().to_boolean())
return *TRY(iterator_close(vm, iterated, normal_completion(Value { true })));
return TRY(iterator_close(vm, iterated, normal_completion(Value { true })));
// f. Set counter to counter + 1.
++counter;

View file

@ -125,7 +125,7 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
if (then.is_throw_completion()) {
// a. Perform RejectPromise(promise, then.[[Value]]).
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Exception while getting 'then' property, rejecting with error", &promise);
promise.reject(*then.throw_completion().value());
promise.reject(then.throw_completion().value());
// b. Return undefined.
return js_undefined();

View file

@ -39,23 +39,23 @@ private:
};
// 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(); \
} \
\
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_try_or_reject_result.release_value())>, \
"Do not return a reference from a fallible expression"); \
\
/* 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(); \
} \
\
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_try_or_reject_result.release_value())>, \
"Do not return a reference from a fallible expression"); \
\
/* 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) \
@ -65,23 +65,23 @@ private:
__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() }; \
} \
\
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_try_or_reject_result.release_value())>, \
"Do not return a reference from a fallible expression"); \
\
/* 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() }; \
} \
\
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_try_or_reject_result.release_value())>, \
"Do not return a reference from a fallible expression"); \
\
/* 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

View file

@ -282,7 +282,7 @@ ThrowCompletionOr<GC::Ref<Object>> PromiseConstructor::construct(FunctionObject&
// 10. If completion is an abrupt completion, then
if (completion.is_error()) {
// a. Perform ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »).
TRY(JS::call(vm, *reject_function, js_undefined(), *completion.release_error().value()));
TRY(JS::call(vm, *reject_function, js_undefined(), completion.release_error().value()));
}
// 11. Return promise.
@ -484,7 +484,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::try_)
// 5. If status is an abrupt completion, then
if (status.is_throw_completion()) {
// a. Perform ? Call(promiseCapability.[[Reject]], undefined, « status.[[Value]] »).
TRY(JS::call(vm, *promise_capability->reject(), js_undefined(), *status.throw_completion().value()));
TRY(JS::call(vm, *promise_capability->reject(), js_undefined(), status.throw_completion().value()));
}
// 6. Else,
else {

View file

@ -62,8 +62,6 @@ static ThrowCompletionOr<Value> run_reaction_job(VM& vm, PromiseReaction& reacti
// ii. Return empty.
dbgln_if(PROMISE_DEBUG, "run_reaction_job: Reaction has no PromiseCapability, returning empty value");
// TODO: This can't return an empty value at the moment, because the implicit conversion to Completion would fail.
// Change it back when this is using completions (`return normal_completion({})`)
return js_undefined();
}
@ -74,14 +72,14 @@ static ThrowCompletionOr<Value> run_reaction_job(VM& vm, PromiseReaction& reacti
// i. Return ? Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »).
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());
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->resolve();
dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob]: Calling PromiseCapability's resolve function @ {}", resolve_function.ptr());
return call(vm, *resolve_function, js_undefined(), *handler_result.value());
return call(vm, *resolve_function, js_undefined(), handler_result.value());
}
}
@ -134,8 +132,8 @@ static ThrowCompletionOr<Value> run_resolve_thenable_job(VM& vm, Promise& promis
// c. If thenCallResult is an abrupt completion, then
if (then_call_result.is_error()) {
// i. Return ? Call(resolvingFunctions.[[Reject]], undefined, « thenCallResult.[[Value]] »).
dbgln_if(PROMISE_DEBUG, "run_resolve_thenable_job: then_call_result is an abrupt completion, calling reject function with value {}", *then_call_result.throw_completion().value());
return call(vm, *reject_function, js_undefined(), *then_call_result.throw_completion().value());
dbgln_if(PROMISE_DEBUG, "run_resolve_thenable_job: then_call_result is an abrupt completion, calling reject function with value {}", then_call_result.throw_completion().value());
return call(vm, *reject_function, js_undefined(), then_call_result.throw_completion().value());
}
// d. Return ? thenCallResult.

View file

@ -376,7 +376,7 @@ JS_DEFINE_NATIVE_FUNCTION(SetPrototype::is_disjoint_from)
// 1. If SetDataHas(O.[[SetData]], next) is true, then
if (set_data_has(set, *next)) {
// a. Perform ? IteratorClose(keysIter, NormalCompletion(UNUSED)).
TRY(iterator_close(vm, keys_iterator, normal_completion({})));
TRY(iterator_close(vm, keys_iterator, normal_completion(js_undefined())));
// b. Return false.
return false;
@ -455,7 +455,7 @@ JS_DEFINE_NATIVE_FUNCTION(SetPrototype::is_superset_of)
// i. If SetDataHas(O.[[SetData]], next) is false, then
if (!set_data_has(set, *next)) {
// 1. Perform ? IteratorClose(keysIter, NormalCompletion(UNUSED)).
TRY(iterator_close(vm, keys_iterator, normal_completion({})));
TRY(iterator_close(vm, keys_iterator, normal_completion(js_undefined())));
// 2. Return false.
return false;

View file

@ -164,7 +164,7 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(VM& vm, StringView source_tex
}
// 12. If result.[[Type]] is normal and result.[[Value]] is empty, then
if (result.type() == Completion::Type::Normal && !result.value().has_value()) {
if (result.type() == Completion::Type::Normal && result.value().is_empty()) {
// a. Set result to NormalCompletion(undefined).
result = normal_completion(js_undefined());
}
@ -184,7 +184,7 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(VM& vm, StringView source_tex
}
// 16. Return ? GetWrappedValue(callerRealm, result.[[Value]]).
return get_wrapped_value(vm, caller_realm, *result.value());
return get_wrapped_value(vm, caller_realm, result.value());
// NOTE: Also see "Editor's Note" in the spec regarding the TypeError above.
}

View file

@ -54,7 +54,7 @@ ThrowCompletionOr<GC::Ref<Object>> SharedArrayBufferConstructor::construct(Funct
if (byte_length_or_error.is_error()) {
auto error = byte_length_or_error.release_error();
if (error.value()->is_object() && is<RangeError>(error.value()->as_object())) {
if (error.value().is_object() && is<RangeError>(error.value().as_object())) {
// Re-throw more specific RangeError
return vm.throw_completion<RangeError>(ErrorType::InvalidLength, "shared array buffer");
}

View file

@ -573,7 +573,7 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
auto array_length_or_error = first_argument.to_index(vm); \
if (array_length_or_error.is_error()) { \
auto error = array_length_or_error.release_error(); \
if (error.value()->is_object() && is<RangeError>(error.value()->as_object())) { \
if (error.value().is_object() && is<RangeError>(error.value().as_object())) { \
/* Re-throw more specific RangeError */ \
return vm.throw_completion<RangeError>(ErrorType::InvalidLength, "typed array"); \
} \

View file

@ -779,7 +779,7 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GC::Ptr<Promise
// AD-HOC: This is basically analogous to what AsyncBlockStart would do.
if (result.is_throw_completion()) {
MUST(call(vm, *capability->reject(), js_undefined(), result.throw_completion().value().value()));
MUST(call(vm, *capability->reject(), js_undefined(), result.throw_completion().value()));
} else {
MUST(call(vm, *capability->resolve(), js_undefined(), result.value()));
}

View file

@ -113,8 +113,7 @@ ThrowCompletionOr<Promise*> SyntheticModule::evaluate(VM& vm)
// Note: Because we expect it to return a promise we convert this here.
auto promise = Promise::create(realm());
if (result.is_error()) {
VERIFY(result.throw_completion().value().has_value());
promise->reject(*result.throw_completion().value());
promise->reject(result.throw_completion().value());
} else {
// Note: This value probably isn't visible to JS code? But undefined is fine anyway.
promise->fulfill(js_undefined());

View file

@ -431,7 +431,7 @@ inline JSFileResult TestRunner::run_file_test(ByteString const& test_path)
suite.most_severe_test_result = Result::Crashed;
Test::Case test_case { "<top-level>"_string, Test::Result::Fail, {}, 0 };
auto error = top_level_result.release_error().release_value().release_value();
auto error = top_level_result.release_error().release_value();
if (error.is_object()) {
StringBuilder detail_builder;

View file

@ -27,7 +27,7 @@ struct BytecodeInterpreter : public Interpreter {
return m_trap.visit(
[](Empty) -> ByteString { VERIFY_NOT_REACHED(); },
[](Trap const& trap) { return trap.reason; },
[](JS::Completion const& completion) { return completion.value()->to_string_without_side_effects().to_byte_string(); });
[](JS::Completion const& completion) { return completion.value().to_string_without_side_effects().to_byte_string(); });
}
virtual void clear_trap() final { m_trap = Empty {}; }

View file

@ -91,7 +91,7 @@ GC::Ref<FontFace> FontFace::construct_impl(JS::Realm& realm, String family, Font
if (maybe_buffer.is_error()) {
VERIFY(maybe_buffer.error().code() == ENOMEM);
auto throw_completion = vm.throw_completion<JS::InternalError>(vm.error_message(JS::VM::ErrorMessage::OutOfMemory));
WebIDL::reject_promise(realm, promise, *throw_completion.value());
WebIDL::reject_promise(realm, promise, throw_completion.value());
} else {
buffer = maybe_buffer.release_value();
}

View file

@ -242,7 +242,7 @@ JS::ThrowCompletionOr<GC::Ref<WebIDL::Promise>> FontFaceSet::load(String const&
auto result = find_matching_font_faces(realm, font_face_set, font, text);
if (result.is_error()) {
HTML::TemporaryExecutionContext execution_context { realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes };
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value());
return;
}

View file

@ -57,7 +57,7 @@ WebIDL::ExceptionOr<GC::Ref<CompressionStream>> CompressionStream::construct_imp
if (auto result = stream->compress_and_enqueue_chunk(chunk); result.is_error()) {
auto throw_completion = Bindings::exception_to_throw_completion(vm, result.exception());
return WebIDL::create_rejected_promise(realm, *throw_completion.release_value());
return WebIDL::create_rejected_promise(realm, throw_completion.release_value());
}
return WebIDL::create_resolved_promise(realm, JS::js_undefined());
@ -70,7 +70,7 @@ WebIDL::ExceptionOr<GC::Ref<CompressionStream>> CompressionStream::construct_imp
if (auto result = stream->compress_flush_and_enqueue(); result.is_error()) {
auto throw_completion = Bindings::exception_to_throw_completion(vm, result.exception());
return WebIDL::create_rejected_promise(realm, *throw_completion.release_value());
return WebIDL::create_rejected_promise(realm, throw_completion.release_value());
}
return WebIDL::create_resolved_promise(realm, JS::js_undefined());

View file

@ -58,7 +58,7 @@ WebIDL::ExceptionOr<GC::Ref<DecompressionStream>> DecompressionStream::construct
if (auto result = stream->decompress_and_enqueue_chunk(chunk); result.is_error()) {
auto throw_completion = Bindings::exception_to_throw_completion(vm, result.exception());
return WebIDL::create_rejected_promise(realm, *throw_completion.release_value());
return WebIDL::create_rejected_promise(realm, throw_completion.release_value());
}
return WebIDL::create_resolved_promise(realm, JS::js_undefined());
@ -71,7 +71,7 @@ WebIDL::ExceptionOr<GC::Ref<DecompressionStream>> DecompressionStream::construct
if (auto result = stream->decompress_flush_and_enqueue(); result.is_error()) {
auto throw_completion = Bindings::exception_to_throw_completion(vm, result.exception());
return WebIDL::create_rejected_promise(realm, *throw_completion.release_value());
return WebIDL::create_rejected_promise(realm, throw_completion.release_value());
}
return WebIDL::create_resolved_promise(realm, JS::js_undefined());

View file

@ -178,7 +178,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::encrypt(AlgorithmIdentifier const& algori
// 10. Let ciphertext be the result of performing the encrypt operation specified by normalizedAlgorithm using algorithm and key and with data as plaintext.
auto cipher_text = normalized_algorithm.methods->encrypt(*normalized_algorithm.parameter, key, data);
if (cipher_text.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), cipher_text.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), cipher_text.release_error()).release_value());
return;
}
@ -235,7 +235,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::decrypt(AlgorithmIdentifier const& algori
// 10. Let plaintext be the result of performing the decrypt operation specified by normalizedAlgorithm using algorithm and key and with data as ciphertext.
auto plain_text = normalized_algorithm.methods->decrypt(*normalized_algorithm.parameter, key, data);
if (plain_text.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), plain_text.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), plain_text.release_error()).release_value());
return;
}
@ -283,7 +283,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::digest(AlgorithmIdentifier const& algorit
auto result = algorithm_object.methods->digest(*algorithm_object.parameter, data_buffer);
if (result.is_exception()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value());
return;
}
@ -324,7 +324,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::generate_key(AlgorithmIdentifier algorith
auto result_or_error = normalized_algorithm.methods->generate_key(*normalized_algorithm.parameter, extractable, key_usages);
if (result_or_error.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value());
return;
}
auto result = result_or_error.release_value();
@ -405,7 +405,7 @@ JS::ThrowCompletionOr<GC::Ref<WebIDL::Promise>> SubtleCrypto::import_key(Binding
// specified by normalizedAlgorithm using keyData, algorithm, format, extractable and usages.
auto maybe_result = normalized_algorithm.methods->import_key(*normalized_algorithm.parameter, format, real_key_data.downcast<CryptoKey::InternalKeyData>(), extractable, key_usages);
if (maybe_result.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), maybe_result.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), maybe_result.release_error()).release_value());
return;
}
auto result = maybe_result.release_value();
@ -451,7 +451,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::export_key(Bindings::KeyFormat format, GC
// FIXME: Stash the AlgorithmMethods on the KeyAlgorithm
auto normalized_algorithm_or_error = normalize_an_algorithm(realm, algorithm.name(), "exportKey"_string);
if (normalized_algorithm_or_error.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), normalized_algorithm_or_error.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), normalized_algorithm_or_error.release_error()).release_value());
return;
}
auto normalized_algorithm = normalized_algorithm_or_error.release_value();
@ -465,7 +465,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::export_key(Bindings::KeyFormat format, GC
// 7. Let result be the result of performing the export key operation specified by the [[algorithm]] internal slot of key using key and format.
auto result_or_error = normalized_algorithm.methods->export_key(format, key);
if (result_or_error.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value());
return;
}
@ -522,7 +522,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::sign(AlgorithmIdentifier const& algorithm
// 10. Let result be the result of performing the sign operation specified by normalizedAlgorithm using key and algorithm and with data as message.
auto result = normalized_algorithm.methods->sign(*normalized_algorithm.parameter, key, data);
if (result.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value());
return;
}
@ -586,7 +586,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::verify(AlgorithmIdentifier const& algorit
// 11. Let result be the result of performing the verify operation specified by normalizedAlgorithm using key, algorithm and signature and with data as message.
auto result = normalized_algorithm.methods->verify(*normalized_algorithm.parameter, key, signature, data);
if (result.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value());
return;
}
@ -633,7 +633,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::derive_bits(AlgorithmIdentifier algorithm
// 9. Let result be the result of creating an ArrayBuffer containing the result of performing the derive bits operation specified by normalizedAlgorithm using baseKey, algorithm and length.
auto result = normalized_algorithm.methods->derive_bits(*normalized_algorithm.parameter, base_key, length_optional);
if (result.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result.release_error()).release_value());
return;
}
@ -695,7 +695,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::derive_key(AlgorithmIdentifier algorithm,
// 13. Let length be the result of performing the get key length algorithm specified by normalizedDerivedKeyAlgorithmLength using derivedKeyType.
auto length_result = normalized_derived_key_algorithm_length.methods->get_key_length(*normalized_derived_key_algorithm_length.parameter);
if (length_result.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), length_result.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), length_result.release_error()).release_value());
return;
}
@ -704,7 +704,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::derive_key(AlgorithmIdentifier algorithm,
if (length_raw_value.is_number()) {
auto maybe_length = length_raw_value.to_u32(vm);
if (!maybe_length.has_value()) {
WebIDL::reject_promise(realm, promise, maybe_length.release_error().release_value().value());
WebIDL::reject_promise(realm, promise, maybe_length.release_error().release_value());
return;
}
@ -714,14 +714,14 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::derive_key(AlgorithmIdentifier algorithm,
// 14. Let secret be the result of performing the derive bits operation specified by normalizedAlgorithm using key, algorithm and length.
auto secret = normalized_algorithm.methods->derive_bits(*normalized_algorithm.parameter, base_key, length);
if (secret.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), secret.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), secret.release_error()).release_value());
return;
}
// 15. Let result be the result of performing the import key operation specified by normalizedDerivedKeyAlgorithmImport using "raw" as format, secret as keyData, derivedKeyType as algorithm and using extractable and usages.
auto result_or_error = normalized_derived_key_algorithm_import.methods->import_key(*normalized_derived_key_algorithm_import.parameter, Bindings::KeyFormat::Raw, secret.release_value()->buffer(), extractable, key_usages);
if (result_or_error.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value());
return;
}
auto result = result_or_error.release_value();
@ -811,13 +811,13 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::wrap_key(Bindings::KeyFormat format, GC::
auto& key_algorithm = as<KeyAlgorithm>(*key->algorithm());
auto normalized_key_algorithm = normalize_an_algorithm(realm, key_algorithm.name(), "exportKey"_string);
if (normalized_key_algorithm.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), normalized_key_algorithm.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), normalized_key_algorithm.release_error()).release_value());
return;
}
auto key_data_or_error = normalized_key_algorithm.release_value().methods->export_key(format, key);
if (key_data_or_error.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), key_data_or_error.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), key_data_or_error.release_error()).release_value());
return;
}
@ -838,7 +838,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::wrap_key(Bindings::KeyFormat format, GC::
// for example, by executing the JSON.stringify algorithm specified in [ECMA-262] in the context of a new global object.
auto maybe_json = JS::JSONObject::stringify_impl(realm.vm(), key_data, JS::Value {}, JS::Value {});
if (maybe_json.is_error()) {
WebIDL::reject_promise(realm, promise, maybe_json.release_error().release_value().value());
WebIDL::reject_promise(realm, promise, maybe_json.release_error().release_value());
return;
}
@ -855,7 +855,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::wrap_key(Bindings::KeyFormat format, GC::
// using algorithm, wrappingKey as key and bytes as plaintext.
auto result_or_error = normalized_algorithm.methods->wrap_key(*normalized_algorithm.parameter, wrapping_key, bytes);
if (result_or_error.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value());
return;
}
@ -868,7 +868,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::wrap_key(Bindings::KeyFormat format, GC::
// using algorithm, wrappingKey as key and bytes as plaintext.
auto result_or_error = normalized_algorithm.methods->encrypt(*normalized_algorithm.parameter, wrapping_key, bytes);
if (result_or_error.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value());
return;
}
@ -975,7 +975,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::unwrap_key(Bindings::KeyFormat format, Ke
}
}();
if (key_or_error.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), key_or_error.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), key_or_error.release_error()).release_value());
return;
}
@ -994,7 +994,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::unwrap_key(Bindings::KeyFormat format, Ke
// Let bytes be the result of executing the parse a JWK algorithm, with key as the data to be parsed.
auto maybe_parsed = Bindings::JsonWebKey::parse(realm, key->buffer());
if (maybe_parsed.is_error()) {
WebIDL::reject_promise(realm, promise, maybe_parsed.release_error().release_value().value());
WebIDL::reject_promise(realm, promise, maybe_parsed.release_error().release_value());
return;
}
@ -1007,7 +1007,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::unwrap_key(Bindings::KeyFormat format, Ke
// using unwrappedKeyAlgorithm as algorithm, format, usages and extractable and with bytes as keyData.
auto result_or_error = normalized_key_algorithm.methods->import_key(*normalized_key_algorithm.parameter, format, bytes.downcast<CryptoKey::InternalKeyData>(), extractable, key_usages);
if (result_or_error.is_error()) {
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value().value());
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), result_or_error.release_error()).release_value());
return;
}

View file

@ -2516,9 +2516,7 @@ JS::ThrowCompletionOr<void> Element::upgrade_element(GC::Ref<HTML::CustomElement
set_custom_element_state(CustomElementState::Precustomized);
// 3. Let constructResult be the result of constructing C, with no arguments.
auto construct_result_optional = TRY(WebIDL::construct(constructor));
VERIFY(construct_result_optional.has_value());
auto construct_result = construct_result_optional.release_value();
auto construct_result = TRY(WebIDL::construct(constructor));
// 4. If SameValue(constructResult, element) is false, then throw a TypeError.
if (!JS::same_value(construct_result, this))

View file

@ -581,10 +581,10 @@ WebIDL::ExceptionOr<GC::Ref<Element>> create_element(Document& document, FlyStri
auto result = TRY(WebIDL::construct(constructor));
// NOTE: IDL does not currently convert the object for us, so we will have to do it here.
if (!result.has_value() || !result->is_object() || !is<HTML::HTMLElement>(result->as_object()))
if (!result.is_object() || !is<HTML::HTMLElement>(result.as_object()))
return JS::throw_completion(JS::TypeError::create(realm, "Custom element constructor must return an object that implements HTMLElement"_string));
GC::Ref<HTML::HTMLElement> element = as<HTML::HTMLElement>(result->as_object());
GC::Ref<HTML::HTMLElement> element = as<HTML::HTMLElement>(result.as_object());
// FIXME: 3. Assert: results custom element state and custom element definition are initialized.

View file

@ -97,7 +97,7 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<GC::Root<DOM::DOMEventLi
if (result.is_error()) {
// 1. Report exception for listeners callbacks corresponding JavaScript objects associated realms global object.
auto& window_or_worker = as<HTML::WindowOrWorkerGlobalScopeMixin>(global);
window_or_worker.report_an_exception(*result.release_error().value());
window_or_worker.report_an_exception(result.release_error().value());
// 2. Set legacyOutputDidListenersThrowFlag if given. (Only used by IndexedDB currently)
legacy_output_did_listeners_throw = true;

View file

@ -715,7 +715,7 @@ JS::ThrowCompletionOr<void> EventTarget::process_event_handler_for_event(FlyStri
return return_value_or_error.release_error();
// FIXME: Ideally, invoke_callback would convert JS::Value to the appropriate return type for us as per the spec, but it doesn't currently.
auto return_value = *return_value_or_error.value();
auto return_value = return_value_or_error.value();
auto is_beforeunload = event.type() == HTML::EventNames::beforeunload;

View file

@ -178,7 +178,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> NodeIterator::filter(Node& node)
m_active = false;
// 8. Return result.
auto result_value = TRY(result.value()->to_i32(vm()));
auto result_value = TRY(result.value().to_i32(vm()));
return static_cast<NodeFilter::Result>(result_value);
}

View file

@ -283,7 +283,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> TreeWalker::filter(Node& node)
m_active = false;
// 8. Return result.
auto result_value = TRY(result.value()->to_i32(vm()));
auto result_value = TRY(result.value().to_i32(vm()));
return static_cast<NodeFilter::Result>(result_value);
}

View file

@ -41,7 +41,7 @@ WebIDL::ExceptionOr<GC::Ref<TextEncoderStream>> TextEncoderStream::construct_imp
if (auto result = stream->encode_and_enqueue_chunk(chunk); result.is_error()) {
auto throw_completion = Bindings::exception_to_throw_completion(vm, result.exception());
return WebIDL::create_rejected_promise(realm, *throw_completion.release_value());
return WebIDL::create_rejected_promise(realm, throw_completion.release_value());
}
return WebIDL::create_resolved_promise(realm, JS::js_undefined());
@ -54,7 +54,7 @@ WebIDL::ExceptionOr<GC::Ref<TextEncoderStream>> TextEncoderStream::construct_imp
if (auto result = stream->encode_and_flush(); result.is_error()) {
auto throw_completion = Bindings::exception_to_throw_completion(vm, result.exception());
return WebIDL::create_rejected_promise(realm, *throw_completion.release_value());
return WebIDL::create_rejected_promise(realm, throw_completion.release_value());
}
return WebIDL::create_resolved_promise(realm, JS::js_undefined());

View file

@ -212,7 +212,7 @@ WebIDL::ExceptionOr<GC::Ref<WebIDL::Promise>> consume_body(JS::Realm& realm, Bod
if (value_or_error.is_error()) {
// We can't call error_steps here without moving it into success_steps, causing a double move when we pause error_steps
// to fully_read, so just reject the promise like error_steps does.
WebIDL::reject_promise(realm, promise, value_or_error.release_error().value().value());
WebIDL::reject_promise(realm, promise, value_or_error.release_error().value());
return;
}

View file

@ -38,7 +38,7 @@ GC::Ref<WebIDL::Promise> fetch(JS::VM& vm, RequestInfo const& input, RequestInit
auto exception_or_request_object = Request::construct_impl(realm, input, init);
if (exception_or_request_object.is_exception()) {
auto throw_completion = Bindings::exception_to_throw_completion(vm, exception_or_request_object.exception());
WebIDL::reject_promise(realm, promise_capability, *throw_completion.value());
WebIDL::reject_promise(realm, promise_capability, throw_completion.value());
return promise_capability;
}
auto request_object = exception_or_request_object.release_value();

View file

@ -94,7 +94,7 @@ void Body::fully_read(JS::Realm& realm, Web::Fetch::Infrastructure::Body::Proces
if (reader.is_exception()) {
auto throw_completion = Bindings::exception_to_throw_completion(realm.vm(), reader.release_error());
error_steps(throw_completion.release_value().value());
error_steps(throw_completion.release_value());
return;
}

View file

@ -350,7 +350,7 @@ GC::Ref<Streams::ReadableStream> Blob::get_stream()
});
if (maybe_error.is_error()) {
readable_stream_error(*stream, maybe_error.release_error().value().value());
readable_stream_error(*stream, maybe_error.release_error().value());
return;
}

View file

@ -1850,8 +1850,8 @@ GC::Ptr<DOM::Document> Navigable::evaluate_javascript_url(URL::URL const& url, U
String result;
// 9. If evaluationStatus is a normal completion, and evaluationStatus.[[Value]] is a String, then set result to evaluationStatus.[[Value]].
if (evaluation_status.type() == JS::Completion::Type::Normal && evaluation_status.value().has_value() && evaluation_status.value()->is_string()) {
result = evaluation_status.value()->as_string().utf8_string();
if (evaluation_status.type() == JS::Completion::Type::Normal && evaluation_status.value().is_string()) {
result = evaluation_status.value().as_string().utf8_string();
} else {
// 10. Otherwise, return null.
return nullptr;

View file

@ -1143,7 +1143,7 @@ bool Navigation::inner_navigate_event_firing_algorithm(
// 1. Append the result of invoking handler with an empty arguments list to promisesList.
auto result = WebIDL::invoke_callback(handler, {});
// This *should* be equivalent to converting a promise to a promise capability
promises_list.append(WebIDL::create_resolved_promise(realm, result.value().value()));
promises_list.append(WebIDL::create_resolved_promise(realm, result.value()));
}
// 3. If promisesList's size is 0, then set promisesList to « a promise resolved with undefined ».

View file

@ -82,7 +82,7 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, GC::Ptr<JS::Envi
// 2. Check if we can run script with realm. If this returns "do not run" then return NormalCompletion(empty).
if (can_run_script(realm) == RunScriptDecision::DoNotRun)
return JS::normal_completion({});
return JS::normal_completion(JS::js_undefined());
// 3. Prepare to run script given realm.
prepare_to_run_script(realm);
@ -112,7 +112,7 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, GC::Ptr<JS::Envi
clean_up_after_running_script(realm);
// 2. Rethrow evaluationStatus.[[Value]].
return JS::throw_completion(*evaluation_status.value());
return JS::throw_completion(evaluation_status.value());
}
// 2. If rethrow errors is true and script's muted errors is true, then:
@ -129,7 +129,7 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, GC::Ptr<JS::Envi
// 1. Report an exception given by evaluationStatus.[[Value]] for realms's global object.
auto& window_or_worker = as<WindowOrWorkerGlobalScopeMixin>(realm.global_object());
window_or_worker.report_an_exception(*evaluation_status.value());
window_or_worker.report_an_exception(evaluation_status.value());
// 2. Clean up after running script with realm.
clean_up_after_running_script(realm);

View file

@ -56,8 +56,7 @@ void report_exception_to_console(JS::Value value, JS::Realm& realm, ErrorInPromi
void report_exception(JS::Completion const& throw_completion, JS::Realm& realm)
{
VERIFY(throw_completion.type() == JS::Completion::Type::Throw);
VERIFY(throw_completion.value().has_value());
report_exception_to_console(*throw_completion.value(), realm, ErrorInPromise::No);
report_exception_to_console(throw_completion.value(), realm, ErrorInPromise::No);
}
}

View file

@ -843,7 +843,7 @@ void fetch_descendants_of_and_link_a_module_script(JS::Realm& realm,
// If this throws an exception, set result's error to rethrow to that exception.
if (linking_result.is_throw_completion())
module_script.set_error_to_rethrow(linking_result.release_error().value().value());
module_script.set_error_to_rethrow(linking_result.release_error().value());
// 2. Run onComplete given moduleScript.
on_complete->function()(module_script);

View file

@ -57,8 +57,7 @@ void ImportMapParseResult::visit_edges(Visitor& visitor)
visitor.visit(exception);
},
[&](JS::Completion const& completion) {
if (completion.value().has_value())
visitor.visit(completion.value().value());
visitor.visit(completion.value());
});
}
}

View file

@ -403,7 +403,7 @@ static void update(JS::VM& vm, GC::Ref<Job> job)
if (job->client) {
auto& realm = job->client->realm();
auto context = HTML::TemporaryExecutionContext(realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
WebIDL::reject_promise(realm, *job->job_promise, *vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Run Service Worker"sv).value());
WebIDL::reject_promise(realm, *job->job_promise, vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Run Service Worker"sv).value());
finish_job(vm, job);
}
});
@ -430,7 +430,7 @@ static void unregister(JS::VM& vm, GC::Ref<Job> job)
if (job->client) {
auto& realm = job->client->realm();
auto context = HTML::TemporaryExecutionContext(realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
WebIDL::reject_promise(realm, *job->job_promise, *vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Service Worker unregistration"sv).value());
WebIDL::reject_promise(realm, *job->job_promise, vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Service Worker unregistration"sv).value());
finish_job(vm, job);
}
}

View file

@ -469,13 +469,13 @@ public:
auto completion = Bindings::exception_to_throw_completion(m_realm->vm(), clone_result.release_error());
// 1. Perform ! ReadableStreamDefaultControllerError(branch1.[[controller]], cloneResult.[[Value]]).
readable_stream_default_controller_error(controller1, completion.value().value());
readable_stream_default_controller_error(controller1, completion.value());
// 2. Perform ! ReadableStreamDefaultControllerError(branch2.[[controller]], cloneResult.[[Value]]).
readable_stream_default_controller_error(controller2, completion.value().value());
readable_stream_default_controller_error(controller2, completion.value());
// 3. Resolve cancelPromise with ! ReadableStreamCancel(stream, cloneResult.[[Value]]).
auto cancel_result = readable_stream_cancel(m_stream, completion.value().value());
auto cancel_result = readable_stream_cancel(m_stream, completion.value());
// Note: We need to manually convert the result to an ECMAScript value here, by extracting its [[Promise]] slot.
WebIDL::resolve_promise(m_realm, m_cancel_promise, cancel_result->promise());
@ -780,13 +780,13 @@ public:
auto completion = Bindings::exception_to_throw_completion(m_realm->vm(), clone_result.release_error());
// 1. Perform ! ReadableByteStreamControllerError(branch1.[[controller]], cloneResult.[[Value]]).
readable_byte_stream_controller_error(controller1, completion.value().value());
readable_byte_stream_controller_error(controller1, completion.value());
// 2. Perform ! ReadableByteStreamControllerError(branch2.[[controller]], cloneResult.[[Value]]).
readable_byte_stream_controller_error(controller2, completion.value().value());
readable_byte_stream_controller_error(controller2, completion.value());
// 3. Resolve cancelPromise with ! ReadableStreamCancel(stream, cloneResult.[[Value]]).
auto cancel_result = readable_stream_cancel(m_stream, completion.value().value());
auto cancel_result = readable_stream_cancel(m_stream, completion.value());
WebIDL::resolve_promise(m_realm, m_cancel_promise, cancel_result->promise());
@ -944,13 +944,13 @@ public:
auto completion = Bindings::exception_to_throw_completion(m_realm->vm(), clone_result.release_error());
// 1. Perform ! ReadableByteStreamControllerError(byobBranch.[[controller]], cloneResult.[[Value]]).
readable_byte_stream_controller_error(byob_controller, completion.value().value());
readable_byte_stream_controller_error(byob_controller, completion.value());
// 2. Perform ! ReadableByteStreamControllerError(otherBranch.[[controller]], cloneResult.[[Value]]).
readable_byte_stream_controller_error(other_controller, completion.value().value());
readable_byte_stream_controller_error(other_controller, completion.value());
// 3. Resolve cancelPromise with ! ReadableStreamCancel(stream, cloneResult.[[Value]]).
auto cancel_result = readable_stream_cancel(m_stream, completion.value().value());
auto cancel_result = readable_stream_cancel(m_stream, completion.value());
WebIDL::resolve_promise(m_realm, m_cancel_promise, cancel_result->promise());
@ -1448,7 +1448,7 @@ WebIDL::ExceptionOr<GC::Ref<ReadableStream>> readable_stream_from_iterable(JS::V
// 2. If nextResult is an abrupt completion, return a promise rejected with nextResult.[[Value]].
if (next_result.is_error())
return WebIDL::create_rejected_promise(realm, *next_result.throw_completion().release_value());
return WebIDL::create_rejected_promise(realm, next_result.throw_completion().release_value());
// 3. Let nextPromise be a promise resolved with nextResult.[[Value]].
auto next_promise = WebIDL::create_resolved_promise(realm, next_result.release_value());
@ -1494,7 +1494,7 @@ WebIDL::ExceptionOr<GC::Ref<ReadableStream>> readable_stream_from_iterable(JS::V
// 3. If returnMethod is an abrupt completion, return a promise rejected with returnMethod.[[Value]].
if (return_method.is_error())
return WebIDL::create_rejected_promise(realm, *return_method.throw_completion().release_value());
return WebIDL::create_rejected_promise(realm, return_method.throw_completion().release_value());
// 4. If returnMethod.[[Value]] is undefined, return a promise resolved with undefined.
if (return_method.value().is_undefined())
@ -1505,7 +1505,7 @@ WebIDL::ExceptionOr<GC::Ref<ReadableStream>> readable_stream_from_iterable(JS::V
// 6. If returnResult is an abrupt completion, return a promise rejected with returnResult.[[Value]].
if (return_result.is_error())
return WebIDL::create_rejected_promise(realm, *return_result.throw_completion().release_value());
return WebIDL::create_rejected_promise(realm, return_result.throw_completion().release_value());
// 7. Let returnPromise be a promise resolved with returnResult.[[Value]].
auto return_promise = WebIDL::create_resolved_promise(realm, return_result.release_value());
@ -1910,7 +1910,7 @@ void readable_byte_stream_controller_pull_into(ReadableByteStreamController& con
if (buffer_result.is_exception()) {
// 1. Perform readIntoRequests error steps, given bufferResult.[[Value]].
auto throw_completion = Bindings::exception_to_throw_completion(vm, buffer_result.exception());
read_into_request.on_error(*throw_completion.release_value());
read_into_request.on_error(throw_completion.release_value());
// 2. Return.
return;
@ -2143,14 +2143,14 @@ WebIDL::ExceptionOr<void> readable_stream_default_controller_enqueue(ReadableStr
// 2. If result is an abrupt completion,
if (result.is_abrupt()) {
// 1. Perform ! ReadableStreamDefaultControllerError(controller, result.[[Value]]).
readable_stream_default_controller_error(controller, result.value().value());
readable_stream_default_controller_error(controller, result.value());
// 2. Return result.
return result;
}
// 3. Let chunkSize be result.[[Value]].
auto chunk_size = result.release_value().release_value();
auto chunk_size = result.release_value();
// 4. Let enqueueResult be EnqueueValueWithSize(controller, chunk, chunkSize).
auto enqueue_result = enqueue_value_with_size(controller, chunk, chunk_size);
@ -2160,7 +2160,7 @@ WebIDL::ExceptionOr<void> readable_stream_default_controller_enqueue(ReadableStr
auto throw_completion = Bindings::throw_dom_exception_if_needed(vm, [&] { return enqueue_result; }).throw_completion();
// 1. Perform ! ReadableStreamDefaultControllerError(controller, enqueueResult.[[Value]]).
readable_stream_default_controller_error(controller, throw_completion.value().value());
readable_stream_default_controller_error(controller, throw_completion.value());
// 2. Return enqueueResult.
// Note: We need to return the throw_completion object here, as enqueue needs to throw the same object that the controller is errored with
@ -2683,7 +2683,7 @@ WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller_from_underly
if (underlying_source.start) {
start_algorithm = GC::create_function(realm.heap(), [controller, underlying_source_value, callback = underlying_source.start]() -> WebIDL::ExceptionOr<JS::Value> {
// Note: callback does not return a promise, so invoke_callback may return an abrupt completion
return TRY(WebIDL::invoke_callback(*callback, underlying_source_value, controller)).release_value();
return TRY(WebIDL::invoke_callback(*callback, underlying_source_value, controller));
});
}
@ -2691,7 +2691,7 @@ WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller_from_underly
if (underlying_source.pull) {
pull_algorithm = GC::create_function(realm.heap(), [&realm, controller, underlying_source_value, callback = underlying_source.pull]() {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source_value, controller)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source_value, controller));
return WebIDL::create_resolved_promise(realm, result);
});
}
@ -2700,7 +2700,7 @@ WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller_from_underly
if (underlying_source.cancel) {
cancel_algorithm = GC::create_function(realm.heap(), [&realm, underlying_source_value, callback = underlying_source.cancel](JS::Value reason) {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source_value, reason)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source_value, reason));
return WebIDL::create_resolved_promise(realm, result);
});
}
@ -3552,7 +3552,7 @@ WebIDL::ExceptionOr<void> readable_byte_stream_controller_enqueue_cloned_chunk_t
auto throw_completion = Bindings::throw_dom_exception_if_needed(vm, [&] { return clone_result; }).throw_completion();
// 1. Perform ! ReadableByteStreamControllerError(controller, cloneResult.[[Value]]).
readable_byte_stream_controller_error(controller, throw_completion.value().value());
readable_byte_stream_controller_error(controller, throw_completion.value());
// 2. Return cloneResult.
// Note: We need to return the throw_completion object here, as enqueue needs to throw the same object that the controller is errored with
@ -4349,7 +4349,7 @@ WebIDL::ExceptionOr<void> set_up_writable_stream_default_controller_from_underly
if (underlying_sink.start) {
start_algorithm = GC::create_function(realm.heap(), [controller, underlying_sink_value, callback = underlying_sink.start]() -> WebIDL::ExceptionOr<JS::Value> {
// Note: callback does not return a promise, so invoke_callback may return an abrupt completion
return TRY(WebIDL::invoke_callback(*callback, underlying_sink_value, controller)).release_value();
return TRY(WebIDL::invoke_callback(*callback, underlying_sink_value, controller));
});
}
@ -4357,7 +4357,7 @@ WebIDL::ExceptionOr<void> set_up_writable_stream_default_controller_from_underly
if (underlying_sink.write) {
write_algorithm = GC::create_function(realm.heap(), [&realm, controller, underlying_sink_value, callback = underlying_sink.write](JS::Value chunk) {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_sink_value, chunk, controller)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_sink_value, chunk, controller));
return WebIDL::create_resolved_promise(realm, result);
});
}
@ -4366,7 +4366,7 @@ WebIDL::ExceptionOr<void> set_up_writable_stream_default_controller_from_underly
if (underlying_sink.close) {
close_algorithm = GC::create_function(realm.heap(), [&realm, underlying_sink_value, callback = underlying_sink.close]() {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_sink_value)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_sink_value));
return WebIDL::create_resolved_promise(realm, result);
});
}
@ -4375,7 +4375,7 @@ WebIDL::ExceptionOr<void> set_up_writable_stream_default_controller_from_underly
if (underlying_sink.abort) {
abort_algorithm = GC::create_function(realm.heap(), [&realm, underlying_sink_value, callback = underlying_sink.abort](JS::Value reason) {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_sink_value, reason)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_sink_value, reason));
return WebIDL::create_resolved_promise(realm, result);
});
}
@ -4510,14 +4510,14 @@ JS::Value writable_stream_default_controller_get_chunk_size(WritableStreamDefaul
// 3. If returnValue is an abrupt completion,
if (return_value.is_abrupt()) {
// 1. Perform ! WritableStreamDefaultControllerErrorIfNeeded(controller, returnValue.[[Value]]).
writable_stream_default_controller_error_if_needed(controller, *return_value.release_value());
writable_stream_default_controller_error_if_needed(controller, return_value.release_value());
// 2. Return 1.
return JS::Value { 1.0 };
}
// 4. Return returnValue.[[Value]].
return *return_value.release_value();
return return_value.release_value();
}
// https://streams.spec.whatwg.org/#writable-stream-default-controller-get-desired-size
@ -4632,7 +4632,7 @@ void writable_stream_default_controller_write(WritableStreamDefaultController& c
auto throw_completion = Bindings::throw_dom_exception_if_needed(vm, [&] { return enqueue_result; }).throw_completion();
// 1. Perform ! WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueResult.[[Value]]).
writable_stream_default_controller_error_if_needed(controller, *throw_completion.release_value());
writable_stream_default_controller_error_if_needed(controller, throw_completion.release_value());
// 2. Return.
return;
@ -4755,7 +4755,7 @@ void set_up_transform_stream_default_controller_from_transformer(TransformStream
// 2. If result is an abrupt completion, return a promise rejected with result.[[Value]].
if (result.is_error()) {
auto throw_completion = Bindings::exception_to_throw_completion(vm, result.exception());
return WebIDL::create_rejected_promise(realm, *throw_completion.release_value());
return WebIDL::create_rejected_promise(realm, throw_completion.release_value());
}
// 3. Otherwise, return a promise resolved with undefined.
@ -4778,7 +4778,7 @@ void set_up_transform_stream_default_controller_from_transformer(TransformStream
if (transformer_dict.transform) {
transform_algorithm = GC::create_function(realm.heap(), [controller, &realm, transformer, callback = transformer_dict.transform](JS::Value chunk) {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, transformer, chunk, controller)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, transformer, chunk, controller));
return WebIDL::create_resolved_promise(realm, result);
});
}
@ -4788,7 +4788,7 @@ void set_up_transform_stream_default_controller_from_transformer(TransformStream
if (transformer_dict.flush) {
flush_algorithm = GC::create_function(realm.heap(), [&realm, transformer, callback = transformer_dict.flush, controller]() {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, transformer, controller)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, transformer, controller));
return WebIDL::create_resolved_promise(realm, result);
});
}
@ -4798,7 +4798,7 @@ void set_up_transform_stream_default_controller_from_transformer(TransformStream
if (transformer_dict.cancel) {
cancel_algorithm = GC::create_function(realm.heap(), [&realm, transformer, callback = transformer_dict.cancel](JS::Value reason) {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, transformer, reason)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, transformer, reason));
return WebIDL::create_resolved_promise(realm, result);
});
}
@ -4845,7 +4845,7 @@ WebIDL::ExceptionOr<void> transform_stream_default_controller_enqueue(TransformS
auto throw_completion = Bindings::exception_to_throw_completion(vm, enqueue_result.exception());
// 1. Perform ! TransformStreamErrorWritableAndUnblockWrite(stream, enqueueResult.[[Value]]).
transform_stream_error_writable_and_unblock_write(*stream, throw_completion.value().value());
transform_stream_error_writable_and_unblock_write(*stream, throw_completion.value());
// 2. Throw stream.[[readable]].[[storedError]].
return JS::throw_completion(stream->readable()->stored_error());
@ -5324,7 +5324,7 @@ WebIDL::ExceptionOr<void> set_up_readable_byte_stream_controller_from_underlying
if (underlying_source_dict.start) {
start_algorithm = GC::create_function(realm.heap(), [controller, underlying_source, callback = underlying_source_dict.start]() -> WebIDL::ExceptionOr<JS::Value> {
// Note: callback does not return a promise, so invoke_callback may return an abrupt completion
return TRY(WebIDL::invoke_callback(*callback, underlying_source, controller)).release_value();
return TRY(WebIDL::invoke_callback(*callback, underlying_source, controller));
});
}
@ -5332,7 +5332,7 @@ WebIDL::ExceptionOr<void> set_up_readable_byte_stream_controller_from_underlying
if (underlying_source_dict.pull) {
pull_algorithm = GC::create_function(realm.heap(), [&realm, controller, underlying_source, callback = underlying_source_dict.pull]() {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source, controller)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source, controller));
return WebIDL::create_resolved_promise(realm, result);
});
}
@ -5341,7 +5341,7 @@ WebIDL::ExceptionOr<void> set_up_readable_byte_stream_controller_from_underlying
if (underlying_source_dict.cancel) {
cancel_algorithm = GC::create_function(realm.heap(), [&realm, underlying_source, callback = underlying_source_dict.cancel](JS::Value reason) {
// Note: callback returns a promise, so invoke_callback will never return an abrupt completion
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source, reason)).release_value();
auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source, reason));
return WebIDL::create_resolved_promise(realm, result);
});
}

View file

@ -149,7 +149,7 @@ void ReadableByteStreamController::pull_steps(GC::Ref<ReadRequest> read_request)
// 2. If buffer is an abrupt completion,
if (buffer.is_throw_completion()) {
// 1. Perform readRequests error steps, given buffer.[[Value]].
read_request->on_error(*buffer.throw_completion().value());
read_request->on_error(buffer.throw_completion().value());
// 2. Return.
return;

View file

@ -63,7 +63,7 @@ WebIDL::ExceptionOr<GC::Ref<TransformStream>> TransformStream::construct_impl(JS
// 12. If transformerDict["start"] exists, then resolve startPromise with the result of invoking
// transformerDict["start"] with argument list « this.[[controller]] » and callback this value transformer.
if (transformer_dict.start) {
auto result = TRY(WebIDL::invoke_callback(*transformer_dict.start, transformer, stream->controller())).release_value();
auto result = TRY(WebIDL::invoke_callback(*transformer_dict.start, transformer, stream->controller()));
WebIDL::resolve_promise(realm, start_promise, result);
}
// 13. Otherwise, resolve startPromise with undefined.

View file

@ -734,7 +734,7 @@ GC::Ref<WebIDL::Promise> compile_potential_webassembly_response(JS::VM& vm, GC::
// 1. Let response be unwrappedSources response.
if (!unwrapped_source.is_object() || !is<Fetch::Response>(unwrapped_source.as_object())) {
WebIDL::reject_promise(realm, return_value, *vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Response").value());
WebIDL::reject_promise(realm, return_value, vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Response").value());
return JS::js_undefined();
}
auto& response_object = static_cast<Fetch::Response&>(unwrapped_source.as_object());
@ -747,19 +747,19 @@ GC::Ref<WebIDL::Promise> compile_potential_webassembly_response(JS::VM& vm, GC::
// Note: extra parameters are not allowed, including the empty `application/wasm;`.
// FIXME: Validate these extra constraints that are not checked by extract_mime_type()
if (auto mime = response->header_list()->extract_mime_type(); !mime.has_value() || mime.value().essence() != "application/wasm"sv) {
WebIDL::reject_promise(realm, return_value, *vm.throw_completion<JS::TypeError>("Response does not match the application/wasm MIME type"sv).value());
WebIDL::reject_promise(realm, return_value, vm.throw_completion<JS::TypeError>("Response does not match the application/wasm MIME type"sv).value());
return JS::js_undefined();
}
// 6. If response is not CORS-same-origin, reject returnValue with a TypeError and abort these substeps.
if (!response->is_cors_same_origin()) {
WebIDL::reject_promise(realm, return_value, *vm.throw_completion<JS::TypeError>("Response is not CORS-same-origin"sv).value());
WebIDL::reject_promise(realm, return_value, vm.throw_completion<JS::TypeError>("Response is not CORS-same-origin"sv).value());
return JS::js_undefined();
}
// 7. If responses status is not an ok status, reject returnValue with a TypeError and abort these substeps.
if (!response_object.ok()) {
WebIDL::reject_promise(realm, return_value, *vm.throw_completion<JS::TypeError>("Response does not represent an ok status"sv).value());
WebIDL::reject_promise(realm, return_value, vm.throw_completion<JS::TypeError>("Response does not represent an ok status"sv).value());
return JS::js_undefined();
}
@ -767,7 +767,7 @@ GC::Ref<WebIDL::Promise> compile_potential_webassembly_response(JS::VM& vm, GC::
auto body_promise_or_error = response_object.array_buffer();
if (body_promise_or_error.is_error()) {
auto throw_completion = Bindings::exception_to_throw_completion(realm.vm(), body_promise_or_error.release_error());
WebIDL::reject_promise(realm, return_value, *throw_completion.value());
WebIDL::reject_promise(realm, return_value, throw_completion.value());
return JS::js_undefined();
}
auto body_promise = body_promise_or_error.release_value();
@ -779,7 +779,7 @@ GC::Ref<WebIDL::Promise> compile_potential_webassembly_response(JS::VM& vm, GC::
auto stable_bytes = WebIDL::get_buffer_source_copy(body_array_buffer.as_object());
if (stable_bytes.is_error()) {
VERIFY(stable_bytes.error().code() == ENOMEM);
WebIDL::reject_promise(HTML::relevant_realm(*return_value->promise()), return_value, *vm.throw_completion<JS::InternalError>(vm.error_message(JS::VM::ErrorMessage::OutOfMemory)).value());
WebIDL::reject_promise(HTML::relevant_realm(*return_value->promise()), return_value, vm.throw_completion<JS::InternalError>(vm.error_message(JS::VM::ErrorMessage::OutOfMemory)).value());
return JS::js_undefined();
}

View file

@ -122,7 +122,7 @@ void execute_script(HTML::BrowsingContext const& browsing_context, String body,
// 3. Upon rejection of scriptPromise with value r, reject promise with value r.
if (script_result.is_throw_completion()) {
WebIDL::reject_promise(realm, promise, *script_result.throw_completion().value());
WebIDL::reject_promise(realm, promise, script_result.throw_completion().value());
}
}));
@ -184,7 +184,7 @@ void execute_async_script(HTML::BrowsingContext const& browsing_context, String
// In order to preserve legacy behavior, the return value only influences the command if it is a
// "thenable" object or if determining this produces an exception.
if (script_result.is_throw_completion()) {
promise->reject(*script_result.throw_completion().value());
promise->reject(script_result.throw_completion().value());
return;
}
@ -197,7 +197,7 @@ void execute_async_script(HTML::BrowsingContext const& browsing_context, String
// 7. If then.[[Type]] is not normal, then reject promise with value then.[[Value]], and abort these steps.
if (then.is_throw_completion()) {
promise->reject(*then.throw_completion().value());
promise->reject(then.throw_completion().value());
return;
}

View file

@ -121,7 +121,7 @@ static ErrorOr<ResultType, WebDriver::Error> clone_an_object(HTML::BrowsingConte
auto source_property_value = value.get(name);
if (source_property_value.is_error()) {
error = WebDriver::Error::from_code(ErrorCode::JavascriptError, "Script returned an error"sv);
return JS::normal_completion({});
return JS::normal_completion(JS::js_undefined());
}
// 3. Let cloned property result be the result of calling the clone algorithm with session, source property
@ -143,7 +143,7 @@ static ErrorOr<ResultType, WebDriver::Error> clone_an_object(HTML::BrowsingConte
// 5. Otherwise, return cloned property result.
else {
error = cloned_property_result.release_error();
return JS::normal_completion({});
return JS::normal_completion(JS::js_undefined());
}
return {};

View file

@ -132,7 +132,7 @@ inline JS::Completion clean_up_on_return(JS::Realm& stored_realm, JS::Realm& rel
return completion;
// 5. Let rejectedPromise be ! Call(%Promise.reject%, %Promise%, «completion.[[Value]]»).
auto rejected_promise = create_rejected_promise(relevant_realm, *completion.release_value());
auto rejected_promise = create_rejected_promise(relevant_realm, completion.release_value());
// 6. Return the result of converting rejectedPromise to the operations return type.
// Note: The operation must return a promise, so no conversion is necessary
@ -308,7 +308,7 @@ JS::Completion invoke_callback(WebIDL::CallbackType& callback, Optional<JS::Valu
// 5. If exceptionBehavior is "rethrow", throw completion.[[Value]].
if (exception_behavior == ExceptionBehavior::Rethrow) {
TRY(JS::throw_completion(*completion.release_value()));
TRY(JS::throw_completion(completion.release_value()));
}
// 6. Otherwise, if exceptionBehavior is "report":
else if (exception_behavior == ExceptionBehavior::Report) {
@ -316,7 +316,7 @@ JS::Completion invoke_callback(WebIDL::CallbackType& callback, Optional<JS::Valu
// 2. Report an exception completion.[[Value]] for relevant realms global object.
auto& window_or_worker = as<HTML::WindowOrWorkerGlobalScopeMixin>(relevant_realm.global_object());
window_or_worker.report_an_exception(*completion.release_value());
window_or_worker.report_an_exception(completion.release_value());
// 3. Return the unique undefined IDL value.
return JS::js_undefined();
@ -326,7 +326,7 @@ JS::Completion invoke_callback(WebIDL::CallbackType& callback, Optional<JS::Valu
VERIFY(callback.operation_returns_promise == OperationReturnsPromise::Yes);
// 8. Let rejectedPromise be ! Call(%Promise.reject%, %Promise%, «completion.[[Value]]»).
auto rejected_promise = create_rejected_promise(relevant_realm, *completion.release_value());
auto rejected_promise = create_rejected_promise(relevant_realm, completion.release_value());
// 9. Return the result of converting rejectedPromise to the callback functions return type.
return JS::Value { rejected_promise->promise() };

View file

@ -166,7 +166,7 @@ struct Formatter<Web::WebIDL::Exception> : Formatter<FormatString> {
},
[&](JS::Completion const& completion) -> ErrorOr<void> {
VERIFY(completion.is_error());
auto value = *completion.value();
auto value = completion.value();
if (value.is_object()) {
auto& object = value.as_object();

View file

@ -293,7 +293,7 @@ void wait_for_all(JS::Realm& realm, Vector<GC::Ref<Promise>> const& promises, Fu
GC::Ref<Promise> create_rejected_promise_from_exception(JS::Realm& realm, Exception exception)
{
auto throw_completion = Bindings::exception_to_throw_completion(realm.vm(), move(exception));
return WebIDL::create_rejected_promise(realm, *throw_completion.value());
return WebIDL::create_rejected_promise(realm, throw_completion.value());
}
}

View file

@ -48,9 +48,9 @@ void WebContentConsoleClient::handle_input(StringView js_source)
// FIXME: Add parse error printouts back once ClassicScript can report parse errors.
auto result = script->run(Web::HTML::ClassicScript::RethrowErrors::No, with_scope);
if (result.value().has_value()) {
m_console_global_environment_extensions->set_most_recent_result(*result.value());
handle_result(*result.value());
if (!result.is_error()) {
m_console_global_environment_extensions->set_most_recent_result(result.value());
handle_result(result.value());
}
}

View file

@ -84,7 +84,7 @@ static ErrorOr<void, TestError> run_program(InterpreterT& interpreter, ScriptOrM
});
if (result.is_error()) {
auto error_value = *result.throw_completion().value();
auto error_value = result.throw_completion().value();
TestError error;
error.phase = NegativePhase::Runtime;
if (error_value.is_object()) {

View file

@ -266,8 +266,7 @@ static ErrorOr<bool> parse_and_run(JS::Realm& realm, StringView source, StringVi
g_last_value = GC::make_root(result.value());
if (result.is_error()) {
VERIFY(result.throw_completion().value().has_value());
TRY(handle_exception(*result.release_error().value()));
TRY(handle_exception(result.release_error().value()));
return false;
}