diff options
12 files changed, 50 insertions, 36 deletions
diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index b1a059607e..18fbcd45b6 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -201,7 +201,7 @@ Value FunctionExpression::instantiate_ordinary_function_expression(Interpreter& // FIXME: 7. Perform MakeConstructor(closure). if (has_own_name) - scope->initialize_binding(global_object, name(), closure); + MUST(scope->initialize_binding(global_object, name(), closure)); return closure; } @@ -576,7 +576,7 @@ Value ForStatement::execute(Interpreter& interpreter, GlobalObject& global_objec if (auto* exception = interpreter.exception()) return throw_completion(exception->value()); VERIFY(!last_value.is_empty()); - this_iteration_env->initialize_binding(global_object, name, last_value); + MUST(this_iteration_env->initialize_binding(global_object, name, last_value)); } interpreter.vm().running_execution_context().lexical_environment = this_iteration_env; @@ -1188,7 +1188,7 @@ Value ClassDeclaration::execute(Interpreter& interpreter, GlobalObject& global_o auto class_constructor = TRY_OR_DISCARD(m_class_expression->class_definition_evaluation(interpreter, global_object, name, name)); if (interpreter.lexical_environment()) { - interpreter.lexical_environment()->initialize_binding(global_object, name, class_constructor); + MUST(interpreter.lexical_environment()->initialize_binding(global_object, name, class_constructor)); } else { auto reference = interpreter.vm().resolve_binding(name); @@ -1330,7 +1330,7 @@ ThrowCompletionOr<Value> ClassExpression::class_definition_evaluation(Interprete vm.running_execution_context().lexical_environment = environment; restore_environment.disarm(); if (!binding_name.is_null()) - class_scope->initialize_binding(global_object, binding_name, class_constructor); + MUST(class_scope->initialize_binding(global_object, binding_name, class_constructor)); return Value(class_constructor); } @@ -2782,7 +2782,7 @@ Value TryStatement::execute(Interpreter& interpreter, GlobalObject& global_objec m_handler->parameter().visit( [&](FlyString const& parameter) { - catch_scope->initialize_binding(global_object, parameter, exception->value()); + (void)catch_scope->initialize_binding(global_object, parameter, exception->value()); }, [&](NonnullRefPtr<BindingPattern> const& pattern) { (void)interpreter.vm().binding_initialization(pattern, exception->value(), catch_scope, global_object); diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index 63a513254f..73a735e13f 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -630,8 +630,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo } else { if (!MUST(variable_environment->has_binding(function_name))) { MUST(variable_environment->create_mutable_binding(global_object, function_name, true)); - variable_environment->initialize_binding(global_object, function_name, js_undefined()); - VERIFY(!vm.exception()); + MUST(variable_environment->initialize_binding(global_object, function_name, js_undefined())); } } @@ -704,12 +703,12 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo if (!binding_exists) { TRY(variable_environment->create_mutable_binding(global_object, declaration.name(), true)); - variable_environment->initialize_binding(global_object, declaration.name(), function); + TRY(variable_environment->initialize_binding(global_object, declaration.name(), function)); } else { variable_environment->set_mutable_binding(global_object, declaration.name(), function, false); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); } - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); } } @@ -723,9 +722,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo if (!binding_exists) { TRY(variable_environment->create_mutable_binding(global_object, var_name, true)); - variable_environment->initialize_binding(global_object, var_name, js_undefined()); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + TRY(variable_environment->initialize_binding(global_object, var_name, js_undefined())); } } } diff --git a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp index 0aa77544e3..ff7b4e971d 100644 --- a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp +++ b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp @@ -86,14 +86,23 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(GlobalO } // 9.1.1.1.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-declarative-environment-records-initializebinding-n-v -void DeclarativeEnvironment::initialize_binding(GlobalObject&, FlyString const& name, Value value) +ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(GlobalObject&, FlyString const& name, Value value) { auto it = m_names.find(name); VERIFY(it != m_names.end()); auto& binding = m_bindings[it->value]; + + // 1. Assert: envRec must have an uninitialized binding for N. VERIFY(binding.initialized == false); + + // 2. Set the bound value for N in envRec to V. binding.value = value; + + // 3. Record that the binding for N in envRec has been initialized. binding.initialized = true; + + // 4. Return NormalCompletion(empty). + return {}; } // 9.1.1.1.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-setmutablebinding-n-v-s @@ -106,7 +115,7 @@ void DeclarativeEnvironment::set_mutable_binding(GlobalObject& global_object, Fl return; } (void)create_mutable_binding(global_object, name, true); - initialize_binding(global_object, name, value); + (void)initialize_binding(global_object, name, value); return; } @@ -171,7 +180,7 @@ void DeclarativeEnvironment::initialize_or_set_mutable_binding(Badge<ScopeNode>, VERIFY(it != m_names.end()); auto& binding = m_bindings[it->value]; if (!binding.initialized) - initialize_binding(global_object, name, value); + MUST(initialize_binding(global_object, name, value)); else set_mutable_binding(global_object, name, value, false); } diff --git a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h index 51413459ea..00fdee176a 100644 --- a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h +++ b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h @@ -25,7 +25,7 @@ public: virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override; virtual ThrowCompletionOr<void> create_mutable_binding(GlobalObject&, FlyString const& name, bool can_be_deleted) override; virtual ThrowCompletionOr<void> create_immutable_binding(GlobalObject&, FlyString const& name, bool strict) override; - virtual void initialize_binding(GlobalObject&, FlyString const& name, Value) override; + virtual ThrowCompletionOr<void> initialize_binding(GlobalObject&, FlyString const& name, Value) override; virtual void set_mutable_binding(GlobalObject&, FlyString const& name, Value, bool strict) override; virtual Value get_binding_value(GlobalObject&, FlyString const& name, bool strict) override; virtual bool delete_binding(GlobalObject&, FlyString const& name) override; diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index 065b6046e2..2a9df717c6 100644 --- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -362,8 +362,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia MUST(environment->create_mutable_binding(global_object(), parameter_name, false)); if (has_duplicates) - environment->initialize_binding(global_object(), parameter_name, js_undefined()); - VERIFY(!vm.exception()); + MUST(environment->initialize_binding(global_object(), parameter_name, js_undefined())); } if (arguments_object_needed) { @@ -378,7 +377,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia else MUST(environment->create_mutable_binding(global_object(), vm.names.arguments.as_string(), false)); - environment->initialize_binding(global_object(), vm.names.arguments.as_string(), arguments_object); + MUST(environment->initialize_binding(global_object(), vm.names.arguments.as_string(), arguments_object)); parameter_names.set(vm.names.arguments.as_string()); } @@ -446,7 +445,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia scope_body->for_each_var_declared_name([&](auto const& name) { if (!parameter_names.contains(name) && instantiated_var_names.set(name) == AK::HashSetResult::InsertedNewEntry) { MUST(environment->create_mutable_binding(global_object(), name, false)); - environment->initialize_binding(global_object(), name, js_undefined()); + MUST(environment->initialize_binding(global_object(), name, js_undefined())); } }); } @@ -467,7 +466,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia else initial_value = environment->get_binding_value(global_object(), name, false); - var_environment->initialize_binding(global_object(), name, initial_value); + MUST(var_environment->initialize_binding(global_object(), name, initial_value)); return IterationDecision::Continue; }); @@ -483,7 +482,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia // The spec says 'initializedBindings' here but that does not exist and it then adds it to 'instantiatedVarNames' so it probably means 'instantiatedVarNames'. if (!instantiated_var_names.contains(function_name) && function_name != vm.names.arguments.as_string()) { MUST(var_environment->create_mutable_binding(global_object(), function_name, false)); - var_environment->initialize_binding(global_object(), function_name, js_undefined()); + MUST(var_environment->initialize_binding(global_object(), function_name, js_undefined())); instantiated_var_names.set(function_name); } diff --git a/Userland/Libraries/LibJS/Runtime/Environment.h b/Userland/Libraries/LibJS/Runtime/Environment.h index 5b1552ba58..cb727429c9 100644 --- a/Userland/Libraries/LibJS/Runtime/Environment.h +++ b/Userland/Libraries/LibJS/Runtime/Environment.h @@ -36,7 +36,7 @@ public: virtual ThrowCompletionOr<bool> has_binding([[maybe_unused]] FlyString const& name, [[maybe_unused]] Optional<size_t>* out_index = nullptr) const { return false; } virtual ThrowCompletionOr<void> create_mutable_binding(GlobalObject&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool can_be_deleted) { return {}; } virtual ThrowCompletionOr<void> create_immutable_binding(GlobalObject&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) { return {}; } - virtual void initialize_binding(GlobalObject&, [[maybe_unused]] FlyString const& name, Value) { } + virtual ThrowCompletionOr<void> initialize_binding(GlobalObject&, [[maybe_unused]] FlyString const& name, Value) { return {}; } virtual void set_mutable_binding(GlobalObject&, [[maybe_unused]] FlyString const& name, Value, [[maybe_unused]] bool strict) { } virtual Value get_binding_value(GlobalObject&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) { return {}; } virtual bool delete_binding(GlobalObject&, [[maybe_unused]] FlyString const& name) { return false; } diff --git a/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp b/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp index c6e5043180..5a8f9e1bcf 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp +++ b/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp @@ -76,13 +76,19 @@ ThrowCompletionOr<void> GlobalEnvironment::create_immutable_binding(GlobalObject } // 9.1.1.4.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-global-environment-records-initializebinding-n-v -void GlobalEnvironment::initialize_binding(GlobalObject& global_object, FlyString const& name, Value value) +ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(GlobalObject& global_object, FlyString const& name, Value value) { + // 1. Let DclRec be envRec.[[DeclarativeRecord]]. + // 2. If DclRec.HasBinding(N) is true, then if (MUST(m_declarative_record->has_binding(name))) { - m_declarative_record->initialize_binding(global_object, name, value); - return; + // a. Return DclRec.InitializeBinding(N, V). + return m_declarative_record->initialize_binding(global_object, name, value); } - m_object_record->initialize_binding(global_object, name, value); + + // 3. Assert: If the binding exists, it must be in the object Environment Record. + // 4. Let ObjRec be envRec.[[ObjectRecord]]. + // 5. Return ? ObjRec.InitializeBinding(N, V). + return m_object_record->initialize_binding(global_object, name, value); } // 9.1.1.4.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-global-environment-records-setmutablebinding-n-v-s @@ -172,7 +178,6 @@ bool GlobalEnvironment::can_declare_global_function(FlyString const& name) const // 9.1.1.4.17 CreateGlobalVarBinding ( N, D ), https://tc39.es/ecma262/#sec-createglobalvarbinding void GlobalEnvironment::create_global_var_binding(FlyString const& name, bool can_be_deleted) { - auto& vm = this->vm(); auto& global_object = m_object_record->binding_object(); auto has_property_or_error = global_object.has_own_property(name); if (has_property_or_error.is_error()) @@ -186,8 +191,8 @@ void GlobalEnvironment::create_global_var_binding(FlyString const& name, bool ca auto result = m_object_record->create_mutable_binding(m_object_record->global_object(), name, can_be_deleted); if (result.is_error()) return; - m_object_record->initialize_binding(m_object_record->global_object(), name, js_undefined()); - if (vm.exception()) + result = m_object_record->initialize_binding(m_object_record->global_object(), name, js_undefined()); + if (result.is_error()) return; } if (!m_var_names.contains_slow(name)) diff --git a/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.h b/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.h index 2b47f1ac67..48bb53a9a7 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.h +++ b/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.h @@ -22,7 +22,7 @@ public: virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override; virtual ThrowCompletionOr<void> create_mutable_binding(GlobalObject&, FlyString const& name, bool can_be_deleted) override; virtual ThrowCompletionOr<void> create_immutable_binding(GlobalObject&, FlyString const& name, bool strict) override; - virtual void initialize_binding(GlobalObject&, FlyString const& name, Value) override; + virtual ThrowCompletionOr<void> initialize_binding(GlobalObject&, FlyString const& name, Value) override; virtual void set_mutable_binding(GlobalObject&, FlyString const& name, Value, bool strict) override; virtual Value get_binding_value(GlobalObject&, FlyString const& name, bool strict) override; virtual bool delete_binding(GlobalObject&, FlyString const& name) override; diff --git a/Userland/Libraries/LibJS/Runtime/ObjectEnvironment.cpp b/Userland/Libraries/LibJS/Runtime/ObjectEnvironment.cpp index 8561991dd2..4e24a85300 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectEnvironment.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectEnvironment.cpp @@ -76,9 +76,13 @@ ThrowCompletionOr<void> ObjectEnvironment::create_immutable_binding(GlobalObject } // 9.1.1.2.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-object-environment-records-initializebinding-n-v -void ObjectEnvironment::initialize_binding(GlobalObject& global_object, FlyString const& name, Value value) +ThrowCompletionOr<void> ObjectEnvironment::initialize_binding(GlobalObject& global_object, FlyString const& name, Value value) { + // 1. Return ? envRec.SetMutableBinding(N, V, false). set_mutable_binding(global_object, name, value, false); + if (auto* exception = vm().exception()) + return throw_completion(exception->value()); + return {}; } // 9.1.1.2.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-object-environment-records-setmutablebinding-n-v-s diff --git a/Userland/Libraries/LibJS/Runtime/ObjectEnvironment.h b/Userland/Libraries/LibJS/Runtime/ObjectEnvironment.h index 54d685e666..fa068cd193 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectEnvironment.h +++ b/Userland/Libraries/LibJS/Runtime/ObjectEnvironment.h @@ -23,7 +23,7 @@ public: virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override; virtual ThrowCompletionOr<void> create_mutable_binding(GlobalObject&, FlyString const& name, bool can_be_deleted) override; virtual ThrowCompletionOr<void> create_immutable_binding(GlobalObject&, FlyString const& name, bool strict) override; - virtual void initialize_binding(GlobalObject&, FlyString const& name, Value) override; + virtual ThrowCompletionOr<void> initialize_binding(GlobalObject&, FlyString const& name, Value) override; virtual void set_mutable_binding(GlobalObject&, FlyString const& name, Value, bool strict) override; virtual Value get_binding_value(GlobalObject&, FlyString const& name, bool strict) override; virtual bool delete_binding(GlobalObject&, FlyString const& name) override; diff --git a/Userland/Libraries/LibJS/Runtime/Reference.h b/Userland/Libraries/LibJS/Runtime/Reference.h index 0b991ca0fc..3999b025ca 100644 --- a/Userland/Libraries/LibJS/Runtime/Reference.h +++ b/Userland/Libraries/LibJS/Runtime/Reference.h @@ -110,7 +110,7 @@ public: { VERIFY(!is_unresolvable()); VERIFY(m_base_type == BaseType::Environment); - m_base_environment->initialize_binding(global_object, m_name.as_string(), value); + (void)m_base_environment->initialize_binding(global_object, m_name.as_string(), value); } void put_value(GlobalObject&, Value); diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 02fb5e0a2f..40d9faadf2 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -178,7 +178,7 @@ ThrowCompletionOr<void> VM::destructuring_assignment_evaluation(NonnullRefPtr<Bi ThrowCompletionOr<void> VM::binding_initialization(FlyString const& target, Value value, Environment* environment, GlobalObject& global_object) { if (environment) { - environment->initialize_binding(global_object, target, value); + MUST(environment->initialize_binding(global_object, target, value)); return {}; } auto reference = resolve_binding(target); |