From 726d631527162e4868c7d6afcee0c81e4a3e5364 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Thu, 15 Apr 2021 00:20:16 +0200 Subject: LibJS: Use references in CallExpression::compute_this_and_callee() This has the nice side effect of giving us a decent error message for something like undefined.foo() - another useless "ToObject on null or undefined" gone. :^) Also turn the various ternary operators into two separate if branches, they don't really share that much. --- Userland/Libraries/LibJS/AST.cpp | 41 ++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) (limited to 'Userland/Libraries/LibJS') diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index ca7c4a444a..8ec30ab1ae 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -147,22 +147,35 @@ CallExpression::ThisAndCallee CallExpression::compute_this_and_callee(Interprete if (is(*m_callee)) { auto& member_expression = static_cast(*m_callee); - bool is_super_property_lookup = is(member_expression.object()); - auto lookup_target = is_super_property_lookup ? interpreter.current_environment()->get_super_base() : member_expression.object().execute(interpreter, global_object); - if (vm.exception()) - return {}; - if (is_super_property_lookup && lookup_target.is_nullish()) { - vm.throw_exception(global_object, ErrorType::ObjectPrototypeNullOrUndefinedOnSuperPropertyAccess, lookup_target.to_string_without_side_effects()); - return {}; + Value callee; + Object* this_value = nullptr; + + if (is(member_expression.object())) { + auto super_base = interpreter.current_environment()->get_super_base(); + if (super_base.is_nullish()) { + vm.throw_exception(global_object, ErrorType::ObjectPrototypeNullOrUndefinedOnSuperPropertyAccess, super_base.to_string_without_side_effects()); + return {}; + } + auto property_name = member_expression.computed_property_name(interpreter, global_object); + if (!property_name.is_valid()) + return {}; + auto reference = Reference(super_base, property_name); + callee = reference.get(global_object); + if (vm.exception()) + return {}; + this_value = &vm.this_value(global_object).as_object(); + } else { + auto reference = member_expression.to_reference(interpreter, global_object); + if (vm.exception()) + return {}; + callee = reference.get(global_object); + if (vm.exception()) + return {}; + this_value = reference.base().to_object(global_object); + if (vm.exception()) + return {}; } - auto* this_value = is_super_property_lookup ? &vm.this_value(global_object).as_object() : lookup_target.to_object(global_object); - if (vm.exception()) - return {}; - auto property_name = member_expression.computed_property_name(interpreter, global_object); - if (!property_name.is_valid()) - return {}; - auto callee = lookup_target.to_object(global_object)->get(property_name).value_or(js_undefined()); return { this_value, callee }; } return { &global_object, m_callee->execute(interpreter, global_object) }; -- cgit v1.2.3