1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 13:07:46 +00:00

LibJS: Convert to_reference() to ThrowCompletionOr

This commit is contained in:
davidot 2021-12-30 23:29:56 +01:00 committed by Linus Groh
parent a24df37713
commit c296df6b58
3 changed files with 45 additions and 77 deletions

View file

@ -312,9 +312,7 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj
{ {
InterpreterNodeScope node_scope { interpreter, *this }; InterpreterNodeScope node_scope { interpreter, *this };
auto& vm = interpreter.vm(); auto& vm = interpreter.vm();
auto callee_reference = m_callee->to_reference(interpreter, global_object); auto callee_reference = TRY_OR_DISCARD(m_callee->to_reference(interpreter, global_object));
if (vm.exception())
return {};
auto [this_value, callee] = compute_this_and_callee(interpreter, global_object, callee_reference); auto [this_value, callee] = compute_this_and_callee(interpreter, global_object, callee_reference);
if (vm.exception()) if (vm.exception())
@ -682,11 +680,11 @@ struct ForInOfHeadState {
if (is<VariableDeclaration>(*expression_lhs)) { if (is<VariableDeclaration>(*expression_lhs)) {
auto& declaration = static_cast<VariableDeclaration const&>(*expression_lhs); auto& declaration = static_cast<VariableDeclaration const&>(*expression_lhs);
VERIFY(declaration.declarations().first().target().has<NonnullRefPtr<Identifier>>()); VERIFY(declaration.declarations().first().target().has<NonnullRefPtr<Identifier>>());
lhs_reference = declaration.declarations().first().target().get<NonnullRefPtr<Identifier>>()->to_reference(interpreter, global_object); lhs_reference = TRY(declaration.declarations().first().target().get<NonnullRefPtr<Identifier>>()->to_reference(interpreter, global_object));
} else { } else {
VERIFY(is<Identifier>(*expression_lhs) || is<MemberExpression>(*expression_lhs)); VERIFY(is<Identifier>(*expression_lhs) || is<MemberExpression>(*expression_lhs));
auto& expression = static_cast<Expression const&>(*expression_lhs); auto& expression = static_cast<Expression const&>(*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 // i. If destructuring is false, then
if (!destructuring) { if (!destructuring) {
VERIFY(lhs_reference.has_value()); VERIFY(lhs_reference.has_value());
@ -1123,12 +1118,12 @@ Value LogicalExpression::execute(Interpreter& interpreter, GlobalObject& global_
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
Reference Expression::to_reference(Interpreter&, GlobalObject&) const ThrowCompletionOr<Reference> Expression::to_reference(Interpreter&, GlobalObject&) const
{ {
return {}; return Reference {};
} }
Reference Identifier::to_reference(Interpreter& interpreter, GlobalObject&) const ThrowCompletionOr<Reference> Identifier::to_reference(Interpreter& interpreter, GlobalObject&) const
{ {
if (m_cached_environment_coordinate.has_value()) { if (m_cached_environment_coordinate.has_value()) {
auto* environment = interpreter.vm().running_execution_context().lexical_environment; 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 = {}; 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()) if (reference.environment_coordinate().has_value())
m_cached_environment_coordinate = reference.environment_coordinate(); m_cached_environment_coordinate = reference.environment_coordinate();
return reference; return reference;
} }
Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& global_object) const ThrowCompletionOr<Reference> MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& global_object) const
{ {
// 13.3.7.1 Runtime Semantics: Evaluation // 13.3.7.1 Runtime Semantics: Evaluation
// SuperProperty : super [ Expression ] // SuperProperty : super [ Expression ]
@ -1158,7 +1153,7 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject&
// 1. Let env be GetThisEnvironment(). // 1. Let env be GetThisEnvironment().
auto& environment = get_this_environment(interpreter.vm()); auto& environment = get_this_environment(interpreter.vm());
// 2. Let actualThis be ? env.GetThisBinding(). // 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; PropertyKey property_key;
@ -1168,10 +1163,10 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject&
// 3. Let propertyNameReference be the result of evaluating Expression. // 3. Let propertyNameReference be the result of evaluating Expression.
// 4. Let propertyNameValue be ? GetValue(propertyNameReference). // 4. Let propertyNameValue be ? GetValue(propertyNameReference).
auto property_name_value = m_property->execute(interpreter, global_object); auto property_name_value = m_property->execute(interpreter, global_object);
if (interpreter.exception()) if (auto* exception = interpreter.exception())
return {}; return throw_completion(exception->value());
// 5. Let propertyKey be ? ToPropertyKey(propertyNameValue). // 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 { } else {
// SuperProperty : super . IdentifierName // SuperProperty : super . IdentifierName
@ -1184,22 +1179,20 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject&
bool strict = interpreter.vm().in_strict_mode(); bool strict = interpreter.vm().in_strict_mode();
// 7. Return ? MakeSuperPropertyReference(actualThis, propertyKey, strict). // 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); auto base_reference = TRY(m_object->to_reference(interpreter, global_object));
if (interpreter.exception())
return {};
Value base_value; Value base_value;
if (base_reference.is_valid_reference()) 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 else
base_value = m_object->execute(interpreter, global_object); base_value = m_object->execute(interpreter, global_object);
if (interpreter.exception()) if (auto* exception = interpreter.exception())
return {}; return throw_completion(exception->value());
VERIFY(!base_value.is_empty()); VERIFY(!base_value.is_empty());
// From here on equivalent to // From here on equivalent to
@ -1208,21 +1201,21 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject&
if (is_computed()) { if (is_computed()) {
// Weird order which I can't quite find from the specs. // Weird order which I can't quite find from the specs.
auto value = m_property->execute(interpreter, global_object); auto value = m_property->execute(interpreter, global_object);
if (interpreter.exception()) if (auto* exception = interpreter.exception())
return Reference {}; 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()); VERIFY(!value.is_empty());
property_name = PropertyKey::from_value(global_object, value); property_name = PropertyKey::from_value(global_object, value);
if (interpreter.exception()) if (auto* exception = interpreter.exception())
return Reference {}; return throw_completion(exception->value());
} else if (is<PrivateIdentifier>(*m_property)) { } else if (is<PrivateIdentifier>(*m_property)) {
auto& private_identifier = static_cast<PrivateIdentifier const&>(*m_property); auto& private_identifier = static_cast<PrivateIdentifier const&>(*m_property);
return make_private_reference(interpreter.vm(), base_value, private_identifier.string()); return make_private_reference(interpreter.vm(), base_value, private_identifier.string());
} else { } else {
property_name = verify_cast<Identifier>(*m_property).string(); property_name = verify_cast<Identifier>(*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()) if (!property_name.is_valid())
return Reference {}; return Reference {};
@ -1237,17 +1230,13 @@ Value UnaryExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
auto& vm = interpreter.vm(); auto& vm = interpreter.vm();
if (m_op == UnaryOp::Delete) { if (m_op == UnaryOp::Delete) {
auto reference = m_lhs->to_reference(interpreter, global_object); auto reference = TRY_OR_DISCARD(m_lhs->to_reference(interpreter, global_object));
if (interpreter.exception())
return {};
return Value(TRY_OR_DISCARD(reference.delete_(global_object))); return Value(TRY_OR_DISCARD(reference.delete_(global_object)));
} }
Value lhs_result; Value lhs_result;
if (m_op == UnaryOp::Typeof && is<Identifier>(*m_lhs)) { if (m_op == UnaryOp::Typeof && is<Identifier>(*m_lhs)) {
auto reference = m_lhs->to_reference(interpreter, global_object); auto reference = TRY_OR_DISCARD(m_lhs->to_reference(interpreter, global_object));
if (interpreter.exception())
return {};
if (reference.is_unresolvable()) if (reference.is_unresolvable())
lhs_result = js_undefined(); lhs_result = js_undefined();
@ -1528,9 +1517,7 @@ ThrowCompletionOr<Value> ClassExpression::class_definition_evaluation(Interprete
Value super_class; Value super_class;
auto reference = m_super_class->to_reference(interpreter, global_object); auto reference = TRY(m_super_class->to_reference(interpreter, global_object));
if (auto* exception = interpreter.exception())
return throw_completion(exception->value());
if (reference.is_valid_reference()) { if (reference.is_valid_reference()) {
super_class = TRY(reference.get_value(global_object)); 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 }; InterpreterNodeScope node_scope { interpreter, *this };
auto reference = to_reference(interpreter, global_object); auto reference = TRY_OR_DISCARD(to_reference(interpreter, global_object));
if (interpreter.exception())
return {};
return TRY_OR_DISCARD(reference.get_value(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 // AssignmentExpression : LeftHandSideExpression = AssignmentExpression
return m_lhs.visit( return m_lhs.visit(
[&](NonnullRefPtr<Expression>& lhs) -> JS::Value { [&](NonnullRefPtr<Expression>& lhs) -> JS::Value {
auto reference = lhs->to_reference(interpreter, global_object); auto reference = TRY_OR_DISCARD(lhs->to_reference(interpreter, global_object));
if (interpreter.exception())
return {};
Value rhs_result; Value rhs_result;
if (lhs->is_identifier()) { if (lhs->is_identifier()) {
@ -2300,9 +2283,7 @@ Value AssignmentExpression::execute(Interpreter& interpreter, GlobalObject& glob
VERIFY(m_lhs.has<NonnullRefPtr<Expression>>()); VERIFY(m_lhs.has<NonnullRefPtr<Expression>>());
auto& lhs_expression = *m_lhs.get<NonnullRefPtr<Expression>>(); auto& lhs_expression = *m_lhs.get<NonnullRefPtr<Expression>>();
auto reference = lhs_expression.to_reference(interpreter, global_object); auto reference = TRY_OR_DISCARD(lhs_expression.to_reference(interpreter, global_object));
if (interpreter.exception())
return {};
auto lhs_result = TRY_OR_DISCARD(reference.get_value(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 }; InterpreterNodeScope node_scope { interpreter, *this };
auto reference = m_argument->to_reference(interpreter, global_object); auto reference = TRY_OR_DISCARD(m_argument->to_reference(interpreter, global_object));
if (interpreter.exception())
return {};
auto old_value = TRY_OR_DISCARD(reference.get_value(global_object)); auto old_value = TRY_OR_DISCARD(reference.get_value(global_object));
old_value = TRY_OR_DISCARD(old_value.to_numeric(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()) { if (auto* init = declarator.init()) {
TRY_OR_DISCARD(declarator.target().visit( TRY_OR_DISCARD(declarator.target().visit(
[&](NonnullRefPtr<Identifier> const& id) -> ThrowCompletionOr<void> { [&](NonnullRefPtr<Identifier> const& id) -> ThrowCompletionOr<void> {
auto reference = id->to_reference(interpreter, global_object); auto reference = TRY(id->to_reference(interpreter, global_object));
if (auto* exception = interpreter.exception())
return throw_completion(exception->value());
auto initializer_result = TRY_OR_DISCARD(interpreter.vm().named_evaluation_if_anonymous_function(global_object, *init, id->string())); auto initializer_result = TRY_OR_DISCARD(interpreter.vm().named_evaluation_if_anonymous_function(global_object, *init, id->string()));
VERIFY(!initializer_result.is_empty()); VERIFY(!initializer_result.is_empty());
@ -2544,7 +2520,7 @@ Value VariableDeclaration::execute(Interpreter& interpreter, GlobalObject& globa
} else if (m_declaration_kind != DeclarationKind::Var) { } else if (m_declaration_kind != DeclarationKind::Var) {
VERIFY(declarator.target().has<NonnullRefPtr<Identifier>>()); VERIFY(declarator.target().has<NonnullRefPtr<Identifier>>());
auto& identifier = declarator.target().get<NonnullRefPtr<Identifier>>(); auto& identifier = declarator.target().get<NonnullRefPtr<Identifier>>();
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())); 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 }; InterpreterNodeScope node_scope { interpreter, *this };
auto reference = to_reference(interpreter, global_object); auto reference = TRY_OR_DISCARD(to_reference(interpreter, global_object));
if (interpreter.exception())
return {};
return TRY_OR_DISCARD(reference.get_value(global_object)); return TRY_OR_DISCARD(reference.get_value(global_object));
} }
@ -2793,7 +2767,7 @@ void OptionalChain::dump(int indent) const
Optional<OptionalChain::ReferenceAndValue> OptionalChain::to_reference_and_value(JS::Interpreter& interpreter, JS::GlobalObject& global_object) const Optional<OptionalChain::ReferenceAndValue> OptionalChain::to_reference_and_value(JS::Interpreter& interpreter, JS::GlobalObject& global_object) const
{ {
// Note: This is wrapped in an optional to allow base_reference = ... // Note: This is wrapped in an optional to allow base_reference = ...
Optional<JS::Reference> base_reference = m_base->to_reference(interpreter, global_object); Optional<JS::Reference> 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)); auto base = base_reference->is_unresolvable() ? m_base->execute(interpreter, global_object) : TRY_OR_DISCARD(base_reference->get_value(global_object));
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
@ -2831,7 +2805,7 @@ Optional<OptionalChain::ReferenceAndValue> OptionalChain::to_reference_and_value
base_reference = JS::Reference {}; base_reference = JS::Reference {};
base = expression->execute(interpreter, global_object); base = expression->execute(interpreter, global_object);
} else { } 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)); base = TRY_OR_DISCARD(base_reference->get_value(global_object));
} }
if (interpreter.exception()) if (interpreter.exception())
@ -2849,11 +2823,11 @@ Value OptionalChain::execute(Interpreter& interpreter, GlobalObject& global_obje
return {}; return {};
} }
JS::Reference OptionalChain::to_reference(Interpreter& interpreter, GlobalObject& global_object) const ThrowCompletionOr<JS::Reference> OptionalChain::to_reference(Interpreter& interpreter, GlobalObject& global_object) const
{ {
if (auto result = to_reference_and_value(interpreter, global_object); result.has_value()) if (auto result = to_reference_and_value(interpreter, global_object); result.has_value())
return result.release_value().reference; return result.release_value().reference;
return {}; return JS::Reference {};
} }
void MetaProperty::dump(int indent) const void MetaProperty::dump(int indent) const

View file

@ -389,7 +389,7 @@ public:
: ASTNode(source_range) : ASTNode(source_range)
{ {
} }
virtual Reference to_reference(Interpreter&, GlobalObject&) const; virtual ThrowCompletionOr<Reference> to_reference(Interpreter&, GlobalObject&) const;
}; };
class Declaration : public Statement { class Declaration : public Statement {
@ -1046,7 +1046,7 @@ public:
virtual Value execute(Interpreter&, GlobalObject&) const override; virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
virtual Reference to_reference(Interpreter&, GlobalObject&) const override; virtual ThrowCompletionOr<Reference> to_reference(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override;
private: private:
@ -1610,7 +1610,7 @@ public:
virtual Value execute(Interpreter&, GlobalObject&) const override; virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
virtual Reference to_reference(Interpreter&, GlobalObject&) const override; virtual ThrowCompletionOr<Reference> to_reference(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override;
bool is_computed() const { return m_computed; } bool is_computed() const { return m_computed; }
@ -1663,7 +1663,7 @@ public:
} }
virtual Value execute(Interpreter& interpreter, GlobalObject& global_object) const override; virtual Value execute(Interpreter& interpreter, GlobalObject& global_object) const override;
virtual JS::Reference to_reference(Interpreter& interpreter, GlobalObject& global_object) const override; virtual ThrowCompletionOr<JS::Reference> to_reference(Interpreter& interpreter, GlobalObject& global_object) const override;
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
private: private:
@ -1895,7 +1895,7 @@ public:
} }
virtual Value execute(Interpreter&, GlobalObject&) const override { return m_value; } virtual Value execute(Interpreter&, GlobalObject&) const override { return m_value; }
virtual Reference to_reference(Interpreter&, GlobalObject&) const override { return m_reference; } virtual ThrowCompletionOr<Reference> to_reference(Interpreter&, GlobalObject&) const override { return m_reference; }
private: private:
Reference m_reference; Reference m_reference;

View file

@ -239,7 +239,7 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
if (auto identifier_ptr = property.name.get_pointer<NonnullRefPtr<Identifier>>()) { if (auto identifier_ptr = property.name.get_pointer<NonnullRefPtr<Identifier>>()) {
assignment_target = TRY(resolve_binding((*identifier_ptr)->string(), environment)); assignment_target = TRY(resolve_binding((*identifier_ptr)->string(), environment));
} else if (auto member_ptr = property.alias.get_pointer<NonnullRefPtr<MemberExpression>>()) { } else if (auto member_ptr = property.alias.get_pointer<NonnullRefPtr<MemberExpression>>()) {
assignment_target = (*member_ptr)->to_reference(interpreter(), global_object); assignment_target = TRY((*member_ptr)->to_reference(interpreter(), global_object));
} else { } else {
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
@ -303,10 +303,7 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
}, },
[&](NonnullRefPtr<BindingPattern> const&) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; }, [&](NonnullRefPtr<BindingPattern> const&) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; },
[&](NonnullRefPtr<MemberExpression> const& member_expression) -> ThrowCompletionOr<Optional<Reference>> { [&](NonnullRefPtr<MemberExpression> const& member_expression) -> ThrowCompletionOr<Optional<Reference>> {
auto reference = member_expression->to_reference(interpreter(), global_object); return TRY(member_expression->to_reference(interpreter(), global_object));
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
return reference;
})); }));
if (auto* thrown_exception = exception()) if (auto* thrown_exception = exception())
@ -353,10 +350,7 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
}, },
[&](NonnullRefPtr<BindingPattern> const&) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; }, [&](NonnullRefPtr<BindingPattern> const&) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; },
[&](NonnullRefPtr<MemberExpression> const& member_expression) -> ThrowCompletionOr<Optional<Reference>> { [&](NonnullRefPtr<MemberExpression> const& member_expression) -> ThrowCompletionOr<Optional<Reference>> {
auto reference = member_expression->to_reference(interpreter(), global_object); return TRY(member_expression->to_reference(interpreter(), global_object));
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
return reference;
})); }));
if (entry.is_rest) { if (entry.is_rest) {