LibJS: Convert initialize_binding() to ThrowCompletionOr
Also add spec step comments to it while we're here.
This commit is contained in:
parent
2691c65639
commit
ae397541fb
Notes:
sideshowbarker
2024-07-18 02:52:24 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/ae397541fb4 Pull-request: https://github.com/SerenityOS/serenity/pull/10413 Reviewed-by: https://github.com/IdanHo ✅
12 changed files with 50 additions and 36 deletions
|
@ -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);
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue