From c296df6b5802a184d4ed7f1afcb001f77efb9fed Mon Sep 17 00:00:00 2001 From: davidot Date: Thu, 30 Dec 2021 23:29:56 +0100 Subject: [PATCH] LibJS: Convert to_reference() to ThrowCompletionOr --- Userland/Libraries/LibJS/AST.cpp | 100 +++++++++--------------- Userland/Libraries/LibJS/AST.h | 10 +-- Userland/Libraries/LibJS/Runtime/VM.cpp | 12 +-- 3 files changed, 45 insertions(+), 77 deletions(-) diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index eb0f869966..22f4580d7a 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -312,9 +312,7 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj { InterpreterNodeScope node_scope { interpreter, *this }; auto& vm = interpreter.vm(); - auto callee_reference = m_callee->to_reference(interpreter, global_object); - if (vm.exception()) - return {}; + auto callee_reference = TRY_OR_DISCARD(m_callee->to_reference(interpreter, global_object)); auto [this_value, callee] = compute_this_and_callee(interpreter, global_object, callee_reference); if (vm.exception()) @@ -682,11 +680,11 @@ struct ForInOfHeadState { if (is(*expression_lhs)) { auto& declaration = static_cast(*expression_lhs); VERIFY(declaration.declarations().first().target().has>()); - lhs_reference = declaration.declarations().first().target().get>()->to_reference(interpreter, global_object); + lhs_reference = TRY(declaration.declarations().first().target().get>()->to_reference(interpreter, global_object)); } else { VERIFY(is(*expression_lhs) || is(*expression_lhs)); auto& expression = static_cast(*expression_lhs); - lhs_reference = expression.to_reference(interpreter, global_object); + lhs_reference = TRY(expression.to_reference(interpreter, global_object)); } } } @@ -709,9 +707,6 @@ struct ForInOfHeadState { } } - if (auto* exception = interpreter.exception()) - return throw_completion(exception->value()); - // i. If destructuring is false, then if (!destructuring) { VERIFY(lhs_reference.has_value()); @@ -1123,12 +1118,12 @@ Value LogicalExpression::execute(Interpreter& interpreter, GlobalObject& global_ VERIFY_NOT_REACHED(); } -Reference Expression::to_reference(Interpreter&, GlobalObject&) const +ThrowCompletionOr Expression::to_reference(Interpreter&, GlobalObject&) const { - return {}; + return Reference {}; } -Reference Identifier::to_reference(Interpreter& interpreter, GlobalObject&) const +ThrowCompletionOr Identifier::to_reference(Interpreter& interpreter, GlobalObject&) const { if (m_cached_environment_coordinate.has_value()) { auto* environment = interpreter.vm().running_execution_context().lexical_environment; @@ -1142,13 +1137,13 @@ Reference Identifier::to_reference(Interpreter& interpreter, GlobalObject&) cons m_cached_environment_coordinate = {}; } - auto reference = TRY_OR_DISCARD(interpreter.vm().resolve_binding(string())); + auto reference = TRY(interpreter.vm().resolve_binding(string())); if (reference.environment_coordinate().has_value()) m_cached_environment_coordinate = reference.environment_coordinate(); return reference; } -Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& global_object) const +ThrowCompletionOr MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& global_object) const { // 13.3.7.1 Runtime Semantics: Evaluation // SuperProperty : super [ Expression ] @@ -1158,7 +1153,7 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& // 1. Let env be GetThisEnvironment(). auto& environment = get_this_environment(interpreter.vm()); // 2. Let actualThis be ? env.GetThisBinding(). - auto actual_this = TRY_OR_DISCARD(environment.get_this_binding(global_object)); + auto actual_this = TRY(environment.get_this_binding(global_object)); PropertyKey property_key; @@ -1168,10 +1163,10 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& // 3. Let propertyNameReference be the result of evaluating Expression. // 4. Let propertyNameValue be ? GetValue(propertyNameReference). auto property_name_value = m_property->execute(interpreter, global_object); - if (interpreter.exception()) - return {}; + if (auto* exception = interpreter.exception()) + return throw_completion(exception->value()); // 5. Let propertyKey be ? ToPropertyKey(propertyNameValue). - property_key = TRY_OR_DISCARD(property_name_value.to_property_key(global_object)); + property_key = TRY(property_name_value.to_property_key(global_object)); } else { // SuperProperty : super . IdentifierName @@ -1184,22 +1179,20 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& bool strict = interpreter.vm().in_strict_mode(); // 7. Return ? MakeSuperPropertyReference(actualThis, propertyKey, strict). - return TRY_OR_DISCARD(make_super_property_reference(global_object, actual_this, property_key, strict)); + return TRY(make_super_property_reference(global_object, actual_this, property_key, strict)); } - auto base_reference = m_object->to_reference(interpreter, global_object); - if (interpreter.exception()) - return {}; + auto base_reference = TRY(m_object->to_reference(interpreter, global_object)); Value base_value; if (base_reference.is_valid_reference()) - base_value = TRY_OR_DISCARD(base_reference.get_value(global_object)); + base_value = TRY(base_reference.get_value(global_object)); else base_value = m_object->execute(interpreter, global_object); - if (interpreter.exception()) - return {}; + if (auto* exception = interpreter.exception()) + return throw_completion(exception->value()); VERIFY(!base_value.is_empty()); // From here on equivalent to @@ -1208,21 +1201,21 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& if (is_computed()) { // Weird order which I can't quite find from the specs. auto value = m_property->execute(interpreter, global_object); - if (interpreter.exception()) - return Reference {}; + if (auto* exception = interpreter.exception()) + return throw_completion(exception->value()); - TRY_OR_DISCARD(require_object_coercible(global_object, base_value)); + TRY(require_object_coercible(global_object, base_value)); VERIFY(!value.is_empty()); property_name = PropertyKey::from_value(global_object, value); - if (interpreter.exception()) - return Reference {}; + if (auto* exception = interpreter.exception()) + return throw_completion(exception->value()); } else if (is(*m_property)) { auto& private_identifier = static_cast(*m_property); return make_private_reference(interpreter.vm(), base_value, private_identifier.string()); } else { property_name = verify_cast(*m_property).string(); - TRY_OR_DISCARD(require_object_coercible(global_object, base_value)); + TRY(require_object_coercible(global_object, base_value)); } if (!property_name.is_valid()) return Reference {}; @@ -1237,17 +1230,13 @@ Value UnaryExpression::execute(Interpreter& interpreter, GlobalObject& global_ob auto& vm = interpreter.vm(); if (m_op == UnaryOp::Delete) { - auto reference = m_lhs->to_reference(interpreter, global_object); - if (interpreter.exception()) - return {}; + auto reference = TRY_OR_DISCARD(m_lhs->to_reference(interpreter, global_object)); return Value(TRY_OR_DISCARD(reference.delete_(global_object))); } Value lhs_result; if (m_op == UnaryOp::Typeof && is(*m_lhs)) { - auto reference = m_lhs->to_reference(interpreter, global_object); - if (interpreter.exception()) - return {}; + auto reference = TRY_OR_DISCARD(m_lhs->to_reference(interpreter, global_object)); if (reference.is_unresolvable()) lhs_result = js_undefined(); @@ -1528,9 +1517,7 @@ ThrowCompletionOr ClassExpression::class_definition_evaluation(Interprete Value super_class; - auto reference = m_super_class->to_reference(interpreter, global_object); - if (auto* exception = interpreter.exception()) - return throw_completion(exception->value()); + auto reference = TRY(m_super_class->to_reference(interpreter, global_object)); if (reference.is_valid_reference()) { super_class = TRY(reference.get_value(global_object)); @@ -2211,9 +2198,7 @@ Value Identifier::execute(Interpreter& interpreter, GlobalObject& global_object) { InterpreterNodeScope node_scope { interpreter, *this }; - auto reference = to_reference(interpreter, global_object); - if (interpreter.exception()) - return {}; + auto reference = TRY_OR_DISCARD(to_reference(interpreter, global_object)); return TRY_OR_DISCARD(reference.get_value(global_object)); } @@ -2269,9 +2254,7 @@ Value AssignmentExpression::execute(Interpreter& interpreter, GlobalObject& glob // AssignmentExpression : LeftHandSideExpression = AssignmentExpression return m_lhs.visit( [&](NonnullRefPtr& lhs) -> JS::Value { - auto reference = lhs->to_reference(interpreter, global_object); - if (interpreter.exception()) - return {}; + auto reference = TRY_OR_DISCARD(lhs->to_reference(interpreter, global_object)); Value rhs_result; if (lhs->is_identifier()) { @@ -2300,9 +2283,7 @@ Value AssignmentExpression::execute(Interpreter& interpreter, GlobalObject& glob VERIFY(m_lhs.has>()); auto& lhs_expression = *m_lhs.get>(); - auto reference = lhs_expression.to_reference(interpreter, global_object); - if (interpreter.exception()) - return {}; + auto reference = TRY_OR_DISCARD(lhs_expression.to_reference(interpreter, global_object)); auto lhs_result = TRY_OR_DISCARD(reference.get_value(global_object)); @@ -2399,10 +2380,7 @@ Value UpdateExpression::execute(Interpreter& interpreter, GlobalObject& global_o { InterpreterNodeScope node_scope { interpreter, *this }; - auto reference = m_argument->to_reference(interpreter, global_object); - - if (interpreter.exception()) - return {}; + auto reference = TRY_OR_DISCARD(m_argument->to_reference(interpreter, global_object)); auto old_value = TRY_OR_DISCARD(reference.get_value(global_object)); old_value = TRY_OR_DISCARD(old_value.to_numeric(global_object)); @@ -2521,9 +2499,7 @@ Value VariableDeclaration::execute(Interpreter& interpreter, GlobalObject& globa if (auto* init = declarator.init()) { TRY_OR_DISCARD(declarator.target().visit( [&](NonnullRefPtr const& id) -> ThrowCompletionOr { - auto reference = id->to_reference(interpreter, global_object); - if (auto* exception = interpreter.exception()) - return throw_completion(exception->value()); + auto reference = TRY(id->to_reference(interpreter, global_object)); auto initializer_result = TRY_OR_DISCARD(interpreter.vm().named_evaluation_if_anonymous_function(global_object, *init, id->string())); VERIFY(!initializer_result.is_empty()); @@ -2544,7 +2520,7 @@ Value VariableDeclaration::execute(Interpreter& interpreter, GlobalObject& globa } else if (m_declaration_kind != DeclarationKind::Var) { VERIFY(declarator.target().has>()); auto& identifier = declarator.target().get>(); - auto reference = identifier->to_reference(interpreter, global_object); + auto reference = TRY_OR_DISCARD(identifier->to_reference(interpreter, global_object)); TRY_OR_DISCARD(reference.initialize_referenced_binding(global_object, js_undefined())); } } @@ -2742,9 +2718,7 @@ Value MemberExpression::execute(Interpreter& interpreter, GlobalObject& global_o { InterpreterNodeScope node_scope { interpreter, *this }; - auto reference = to_reference(interpreter, global_object); - if (interpreter.exception()) - return {}; + auto reference = TRY_OR_DISCARD(to_reference(interpreter, global_object)); return TRY_OR_DISCARD(reference.get_value(global_object)); } @@ -2793,7 +2767,7 @@ void OptionalChain::dump(int indent) const Optional OptionalChain::to_reference_and_value(JS::Interpreter& interpreter, JS::GlobalObject& global_object) const { // Note: This is wrapped in an optional to allow base_reference = ... - Optional base_reference = m_base->to_reference(interpreter, global_object); + Optional base_reference = TRY_OR_DISCARD(m_base->to_reference(interpreter, global_object)); auto base = base_reference->is_unresolvable() ? m_base->execute(interpreter, global_object) : TRY_OR_DISCARD(base_reference->get_value(global_object)); if (interpreter.exception()) return {}; @@ -2831,7 +2805,7 @@ Optional OptionalChain::to_reference_and_value base_reference = JS::Reference {}; base = expression->execute(interpreter, global_object); } else { - base_reference = expression->to_reference(interpreter, global_object); + base_reference = TRY_OR_DISCARD(expression->to_reference(interpreter, global_object)); base = TRY_OR_DISCARD(base_reference->get_value(global_object)); } if (interpreter.exception()) @@ -2849,11 +2823,11 @@ Value OptionalChain::execute(Interpreter& interpreter, GlobalObject& global_obje return {}; } -JS::Reference OptionalChain::to_reference(Interpreter& interpreter, GlobalObject& global_object) const +ThrowCompletionOr OptionalChain::to_reference(Interpreter& interpreter, GlobalObject& global_object) const { if (auto result = to_reference_and_value(interpreter, global_object); result.has_value()) return result.release_value().reference; - return {}; + return JS::Reference {}; } void MetaProperty::dump(int indent) const diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index f129586dfb..9e2ee6dd0b 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -389,7 +389,7 @@ public: : ASTNode(source_range) { } - virtual Reference to_reference(Interpreter&, GlobalObject&) const; + virtual ThrowCompletionOr to_reference(Interpreter&, GlobalObject&) const; }; class Declaration : public Statement { @@ -1046,7 +1046,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Reference to_reference(Interpreter&, GlobalObject&) const override; + virtual ThrowCompletionOr to_reference(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: @@ -1610,7 +1610,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Reference to_reference(Interpreter&, GlobalObject&) const override; + virtual ThrowCompletionOr to_reference(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; bool is_computed() const { return m_computed; } @@ -1663,7 +1663,7 @@ public: } virtual Value execute(Interpreter& interpreter, GlobalObject& global_object) const override; - virtual JS::Reference to_reference(Interpreter& interpreter, GlobalObject& global_object) const override; + virtual ThrowCompletionOr to_reference(Interpreter& interpreter, GlobalObject& global_object) const override; virtual void dump(int indent) const override; private: @@ -1895,7 +1895,7 @@ public: } virtual Value execute(Interpreter&, GlobalObject&) const override { return m_value; } - virtual Reference to_reference(Interpreter&, GlobalObject&) const override { return m_reference; } + virtual ThrowCompletionOr to_reference(Interpreter&, GlobalObject&) const override { return m_reference; } private: Reference m_reference; diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 50472808cd..3bf65f2aa2 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -239,7 +239,7 @@ ThrowCompletionOr VM::property_binding_initialization(BindingPattern const if (auto identifier_ptr = property.name.get_pointer>()) { assignment_target = TRY(resolve_binding((*identifier_ptr)->string(), environment)); } else if (auto member_ptr = property.alias.get_pointer>()) { - assignment_target = (*member_ptr)->to_reference(interpreter(), global_object); + assignment_target = TRY((*member_ptr)->to_reference(interpreter(), global_object)); } else { VERIFY_NOT_REACHED(); } @@ -303,10 +303,7 @@ ThrowCompletionOr VM::property_binding_initialization(BindingPattern const }, [&](NonnullRefPtr const&) -> ThrowCompletionOr> { return Optional {}; }, [&](NonnullRefPtr const& member_expression) -> ThrowCompletionOr> { - auto reference = member_expression->to_reference(interpreter(), global_object); - if (auto* thrown_exception = exception()) - return JS::throw_completion(thrown_exception->value()); - return reference; + return TRY(member_expression->to_reference(interpreter(), global_object)); })); if (auto* thrown_exception = exception()) @@ -353,10 +350,7 @@ ThrowCompletionOr VM::iterator_binding_initialization(BindingPattern const }, [&](NonnullRefPtr const&) -> ThrowCompletionOr> { return Optional {}; }, [&](NonnullRefPtr const& member_expression) -> ThrowCompletionOr> { - auto reference = member_expression->to_reference(interpreter(), global_object); - if (auto* thrown_exception = exception()) - return JS::throw_completion(thrown_exception->value()); - return reference; + return TRY(member_expression->to_reference(interpreter(), global_object)); })); if (entry.is_rest) {