summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2021-10-09 19:16:24 +0100
committerLinus Groh <mail@linusgroh.de>2021-10-09 21:53:47 +0100
commitae397541fb47f339f481246b46a9bfe60bfb43da (patch)
tree2ccf47a8401593766a38d3eb0b3ea4a85ff0d15f
parent2691c656390f8cb699867f57cc2b762e1645d9f9 (diff)
downloadserenity-ae397541fb47f339f481246b46a9bfe60bfb43da.zip
LibJS: Convert initialize_binding() to ThrowCompletionOr
Also add spec step comments to it while we're here.
-rw-r--r--Userland/Libraries/LibJS/AST.cpp10
-rw-r--r--Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp13
-rw-r--r--Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp15
-rw-r--r--Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h2
-rw-r--r--Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp11
-rw-r--r--Userland/Libraries/LibJS/Runtime/Environment.h2
-rw-r--r--Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp19
-rw-r--r--Userland/Libraries/LibJS/Runtime/GlobalEnvironment.h2
-rw-r--r--Userland/Libraries/LibJS/Runtime/ObjectEnvironment.cpp6
-rw-r--r--Userland/Libraries/LibJS/Runtime/ObjectEnvironment.h2
-rw-r--r--Userland/Libraries/LibJS/Runtime/Reference.h2
-rw-r--r--Userland/Libraries/LibJS/Runtime/VM.cpp2
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);