summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2021-04-15 00:20:16 +0200
committerAndreas Kling <kling@serenityos.org>2021-04-15 09:45:20 +0200
commit726d631527162e4868c7d6afcee0c81e4a3e5364 (patch)
tree3655ea8153090c44b827e37e9f2dbda641d76a98 /Userland/Libraries/LibJS
parent94bc8865935215f595036ced6e04cc24c5b457b7 (diff)
downloadserenity-726d631527162e4868c7d6afcee0c81e4a3e5364.zip
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.
Diffstat (limited to 'Userland/Libraries/LibJS')
-rw-r--r--Userland/Libraries/LibJS/AST.cpp41
1 files changed, 27 insertions, 14 deletions
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<MemberExpression>(*m_callee)) {
auto& member_expression = static_cast<const MemberExpression&>(*m_callee);
- bool is_super_property_lookup = is<SuperExpression>(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<TypeError>(global_object, ErrorType::ObjectPrototypeNullOrUndefinedOnSuperPropertyAccess, lookup_target.to_string_without_side_effects());
- return {};
+ Value callee;
+ Object* this_value = nullptr;
+
+ if (is<SuperExpression>(member_expression.object())) {
+ auto super_base = interpreter.current_environment()->get_super_base();
+ if (super_base.is_nullish()) {
+ vm.throw_exception<TypeError>(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) };