diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index d054b2d24a..3fcd3dd82a 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -713,9 +713,9 @@ Reference Expression::to_reference(Interpreter&, GlobalObject&) const return {}; } -Reference Identifier::to_reference(Interpreter& interpreter, GlobalObject& global_object) const +Reference Identifier::to_reference(Interpreter& interpreter, GlobalObject&) const { - return interpreter.vm().resolve_binding(global_object, string()); + return interpreter.vm().resolve_binding(string()); } Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& global_object) const diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 26be7d6b00..381d9d965e 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -392,17 +392,43 @@ Value VM::get_variable(const FlyString& name, GlobalObject& global_object) return value; } -// 9.4.2 ResolveBinding ( name [ , env ] ), https://tc39.es/ecma262/#sec-resolvebinding -Reference VM::resolve_binding(GlobalObject& global_object, FlyString const& name, Environment*) +// 9.1.2.1 GetIdentifierReference ( env, name, strict ), https://tc39.es/ecma262/#sec-getidentifierreference +Reference VM::get_identifier_reference(Environment* environment, FlyString const& name, bool strict) { - // FIXME: This implementation of ResolveBinding is non-conforming. + // 1. If env is the value null, then + if (!environment) { + // a. Return the Reference Record { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }. + return Reference { Reference::BaseType::Unresolvable, name, strict }; + } - for (auto* environment = lexical_environment(); environment && environment->outer_environment(); environment = environment->outer_environment()) { + // FIXME: The remainder of this function is non-conforming. + + auto& global_object = environment->global_object(); + for (; environment && environment->outer_environment(); environment = environment->outer_environment()) { auto possible_match = environment->get_from_environment(name); if (possible_match.has_value()) - return Reference { *environment, name, in_strict_mode() }; + return Reference { *environment, name, strict }; } - return Reference { global_object.environment(), name, in_strict_mode() }; + return Reference { global_object.environment(), name, strict }; +} + +// 9.4.2 ResolveBinding ( name [ , env ] ), https://tc39.es/ecma262/#sec-resolvebinding +Reference VM::resolve_binding(FlyString const& name, Environment* environment) +{ + // 1. If env is not present or if env is undefined, then + if (!environment) { + // a. Set env to the running execution context's LexicalEnvironment. + environment = running_execution_context().lexical_environment; + } + + // 2. Assert: env is an Environment Record. + VERIFY(environment); + + // 3. If the code matching the syntactic production that is being evaluated is contained in strict mode code, let strict be true; else let strict be false. + bool strict = in_strict_mode(); + + // 4. Return ? GetIdentifierReference(env, name, strict). + return get_identifier_reference(environment, name, strict); } Value VM::construct(FunctionObject& function, FunctionObject& new_target, Optional arguments) diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index 2c0b1bdaec..06e5783d54 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -204,7 +204,8 @@ public: void assign(const FlyString& target, Value, GlobalObject&, bool first_assignment = false, Environment* specific_scope = nullptr); void assign(const NonnullRefPtr& target, Value, GlobalObject&, bool first_assignment = false, Environment* specific_scope = nullptr); - Reference resolve_binding(GlobalObject&, FlyString const&, Environment* = nullptr); + Reference resolve_binding(FlyString const&, Environment* = nullptr); + Reference get_identifier_reference(Environment*, FlyString const&, bool strict); template void throw_exception(GlobalObject& global_object, Args&&... args)