diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 3fcd3dd82a..198c573b14 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -720,6 +720,43 @@ Reference Identifier::to_reference(Interpreter& interpreter, GlobalObject&) cons Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& global_object) const { + // 13.3.7.1 Runtime Semantics: Evaluation + // SuperProperty : super [ Expression ] + // SuperProperty : super . IdentifierName + // https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation + if (is(object())) { + // 1. Let env be GetThisEnvironment(). + auto& environment = get_this_environment(interpreter.vm()); + // 2. Let actualThis be ? env.GetThisBinding(). + auto actual_this = environment.get_this_binding(global_object); + + StringOrSymbol property_key; + + if (is_computed()) { + // SuperProperty : super [ Expression ] + + // 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 {}; + // 5. Let propertyKey be ? ToPropertyKey(propertyNameValue). + property_key = property_name_value.to_property_key(global_object); + } else { + // SuperProperty : super . IdentifierName + + // 3. Let propertyKey be StringValue of IdentifierName. + VERIFY(is(property())); + property_key = static_cast(property()).string(); + } + + // 6. If the code matched by this SuperProperty is strict mode code, let strict be true; else let strict be false. + bool strict = interpreter.vm().in_strict_mode(); + + // 7. Return ? MakeSuperPropertyReference(actualThis, propertyKey, strict). + return make_super_property_reference(global_object, actual_this, property_key, strict); + } + auto object_value = m_object->execute(interpreter, global_object); if (interpreter.exception()) return {}; diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index 5e32edcb62..11d4302885 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace JS { @@ -180,6 +181,25 @@ Object* get_super_constructor(VM& vm) return super_constructor; } +// 13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict ) +Reference make_super_property_reference(GlobalObject& global_object, Value actual_this, StringOrSymbol const& property_key, bool strict) +{ + auto& vm = global_object.vm(); + // 1. Let env be GetThisEnvironment(). + auto& env = verify_cast(get_this_environment(vm)); + // 2. Assert: env.HasSuperBinding() is true. + VERIFY(env.has_super_binding()); + // 3. Let baseValue be ? env.GetSuperBase(). + auto base_value = env.get_super_base(); + // 4. Let bv be ? RequireObjectCoercible(baseValue). + auto bv = require_object_coercible(global_object, base_value); + if (vm.exception()) + return {}; + // 5. Return the Reference Record { [[Base]]: bv, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }. + // 6. NOTE: This returns a Super Reference Record. + return Reference { bv, property_key, actual_this, strict }; +} + // 19.2.1.1 PerformEval ( x, callerRealm, strictCaller, direct ), https://tc39.es/ecma262/#sec-performeval Value perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller, EvalMode direct) { diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h index 652fecbd2b..58f2aadee3 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h @@ -18,6 +18,7 @@ DeclarativeEnvironment* new_declarative_environment(Environment&); ObjectEnvironment* new_object_environment(Object&, bool is_with_environment, Environment*); Environment& get_this_environment(VM&); Object* get_super_constructor(VM&); +Reference make_super_property_reference(GlobalObject&, Value actual_this, StringOrSymbol const& property_key, bool strict); Value require_object_coercible(GlobalObject&, Value); size_t length_of_array_like(GlobalObject&, Object const&); MarkedValueList create_list_from_array_like(GlobalObject&, Value, Function(Value)> = {});