mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 04:57:45 +00:00
LibJS: Add an initialize binding hint to all initialize_binding methods
This will allow us to specify things like SyncDispose and perhaps AsyncDispose in the future.
This commit is contained in:
parent
3353cf68f1
commit
a746739cb0
14 changed files with 68 additions and 57 deletions
|
@ -205,8 +205,9 @@ ThrowCompletionOr<void> initialize_bound_name(VM& vm, DeprecatedFlyString const&
|
|||
{
|
||||
// 1. If environment is not undefined, then
|
||||
if (environment) {
|
||||
// a. Perform ! environment.InitializeBinding(name, value).
|
||||
MUST(environment->initialize_binding(vm, name, value));
|
||||
// FIXME: The normal is not included in the explicit resource management spec yet, so there is no spec link for it.
|
||||
// a. Perform ! environment.InitializeBinding(name, value, normal).
|
||||
MUST(environment->initialize_binding(vm, name, value, Environment::InitializeBindingHint::Normal));
|
||||
|
||||
// b. Return unused.
|
||||
return {};
|
||||
|
@ -729,6 +730,7 @@ ThrowCompletionOr<Value> perform_eval(VM& vm, Value x, CallerMode strict_caller,
|
|||
}
|
||||
|
||||
// 19.2.1.3 EvalDeclarationInstantiation ( body, varEnv, lexEnv, privateEnv, strict ), https://tc39.es/ecma262/#sec-evaldeclarationinstantiation
|
||||
// 9.1.1.1 EvalDeclarationInstantiation ( body, varEnv, lexEnv, privateEnv, strict ), https://tc39.es/proposal-explicit-resource-management/#sec-evaldeclarationinstantiation
|
||||
ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& program, Environment* variable_environment, Environment* lexical_environment, PrivateEnvironment* private_environment, bool strict)
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
@ -903,9 +905,9 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
|
|||
// ii. If bindingExists is false, then
|
||||
if (!MUST(variable_environment->has_binding(function_name))) {
|
||||
// i. Perform ! varEnv.CreateMutableBinding(F, true).
|
||||
// ii. Perform ! varEnv.InitializeBinding(F, undefined).
|
||||
MUST(variable_environment->create_mutable_binding(vm, function_name, true));
|
||||
MUST(variable_environment->initialize_binding(vm, function_name, js_undefined()));
|
||||
// ii. Perform ! varEnv.InitializeBinding(F, undefined, normal).
|
||||
MUST(variable_environment->initialize_binding(vm, function_name, js_undefined(), Environment::InitializeBindingHint::Normal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1003,8 +1005,8 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
|
|||
// 2. Perform ! varEnv.CreateMutableBinding(fn, true).
|
||||
MUST(variable_environment->create_mutable_binding(vm, declaration.name(), true));
|
||||
|
||||
// 3. Perform ! varEnv.InitializeBinding(fn, fo).
|
||||
MUST(variable_environment->initialize_binding(vm, declaration.name(), function));
|
||||
// 3. Perform ! varEnv.InitializeBinding(fn, fo, normal).
|
||||
MUST(variable_environment->initialize_binding(vm, declaration.name(), function, Environment::InitializeBindingHint::Normal));
|
||||
}
|
||||
// iii. Else,
|
||||
else {
|
||||
|
@ -1033,8 +1035,8 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
|
|||
// 2. Perform ! varEnv.CreateMutableBinding(vn, true).
|
||||
MUST(variable_environment->create_mutable_binding(vm, var_name, true));
|
||||
|
||||
// 3. Perform ! varEnv.InitializeBinding(vn, undefined).
|
||||
MUST(variable_environment->initialize_binding(vm, var_name, js_undefined()));
|
||||
// 3. Perform ! varEnv.InitializeBinding(vn, undefined, normal).
|
||||
MUST(variable_environment->initialize_binding(vm, var_name, js_undefined(), Environment::InitializeBindingHint::Normal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,26 +96,25 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(VM&, De
|
|||
}
|
||||
|
||||
// 9.1.1.1.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-declarative-environment-records-initializebinding-n-v
|
||||
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(VM& vm, DeprecatedFlyString const& name, Value value)
|
||||
// 4.1.1.1.1 InitializeBinding ( N, V, hint ), https://tc39.es/proposal-explicit-resource-management/#sec-declarative-environment-records
|
||||
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(VM&, DeprecatedFlyString const& name, Value value, Environment::InitializeBindingHint)
|
||||
{
|
||||
auto binding_and_index = find_binding_and_index(name);
|
||||
VERIFY(binding_and_index.has_value());
|
||||
auto& binding = binding_and_index->binding();
|
||||
|
||||
return initialize_binding_direct(vm, binding_and_index->binding(), value);
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding_direct(VM&, Binding& binding, Value 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.
|
||||
// FIXME: 2. If hint is not normal, perform ? AddDisposableResource(envRec, V, hint).
|
||||
|
||||
// 3. 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.
|
||||
// 4. Record that the binding for N in envRec has been initialized.
|
||||
binding.initialized = true;
|
||||
|
||||
// 4. Return unused.
|
||||
// 5. Return unused.
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -132,8 +131,8 @@ ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding(VM& vm, Depr
|
|||
// b. Perform ! envRec.CreateMutableBinding(N, true).
|
||||
MUST(create_mutable_binding(vm, name, true));
|
||||
|
||||
// c. Perform ! envRec.InitializeBinding(N, V).
|
||||
MUST(initialize_binding(vm, name, value));
|
||||
// c. Perform ! envRec.InitializeBinding(N, V, normal).
|
||||
MUST(initialize_binding(vm, name, value, Environment::InitializeBindingHint::Normal));
|
||||
|
||||
// d. Return unused.
|
||||
return {};
|
||||
|
@ -220,7 +219,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::initialize_or_set_mutable_bindin
|
|||
VERIFY(binding_and_index.has_value());
|
||||
|
||||
if (!binding_and_index->binding().initialized)
|
||||
TRY(initialize_binding(vm, name, value));
|
||||
TRY(initialize_binding(vm, name, value, Environment::InitializeBindingHint::Normal));
|
||||
else
|
||||
TRY(set_mutable_binding(vm, name, value, false));
|
||||
return {};
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
virtual ThrowCompletionOr<bool> has_binding(DeprecatedFlyString const& name, Optional<size_t>* = nullptr) const override;
|
||||
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, DeprecatedFlyString const& name, bool can_be_deleted) override;
|
||||
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, DeprecatedFlyString const& name, bool strict) override;
|
||||
virtual ThrowCompletionOr<void> initialize_binding(VM&, DeprecatedFlyString const& name, Value) override;
|
||||
virtual ThrowCompletionOr<void> initialize_binding(VM&, DeprecatedFlyString const& name, Value, InitializeBindingHint) override;
|
||||
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, DeprecatedFlyString const& name, Value, bool strict) override;
|
||||
virtual ThrowCompletionOr<Value> get_binding_value(VM&, DeprecatedFlyString const& name, bool strict) override;
|
||||
virtual ThrowCompletionOr<bool> delete_binding(VM&, DeprecatedFlyString const& name) override;
|
||||
|
@ -60,7 +60,6 @@ public:
|
|||
void shrink_to_fit();
|
||||
|
||||
private:
|
||||
ThrowCompletionOr<void> initialize_binding_direct(VM&, Binding&, Value);
|
||||
ThrowCompletionOr<Value> get_binding_value_direct(VM&, Binding&, bool strict);
|
||||
ThrowCompletionOr<void> set_mutable_binding_direct(VM&, Binding&, Value, bool strict);
|
||||
|
||||
|
|
|
@ -407,7 +407,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|||
|
||||
MUST(environment->create_mutable_binding(vm, parameter_name, false));
|
||||
if (has_duplicates)
|
||||
MUST(environment->initialize_binding(vm, parameter_name, js_undefined()));
|
||||
MUST(environment->initialize_binding(vm, parameter_name, js_undefined(), Environment::InitializeBindingHint::Normal));
|
||||
}
|
||||
|
||||
if (arguments_object_needed) {
|
||||
|
@ -422,7 +422,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|||
else
|
||||
MUST(environment->create_mutable_binding(vm, vm.names.arguments.as_string(), false));
|
||||
|
||||
MUST(environment->initialize_binding(vm, vm.names.arguments.as_string(), arguments_object));
|
||||
MUST(environment->initialize_binding(vm, vm.names.arguments.as_string(), arguments_object, Environment::InitializeBindingHint::Normal));
|
||||
parameter_names.set(vm.names.arguments.as_string());
|
||||
}
|
||||
|
||||
|
@ -488,7 +488,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(vm, name, false));
|
||||
MUST(environment->initialize_binding(vm, name, js_undefined()));
|
||||
MUST(environment->initialize_binding(vm, name, js_undefined(), Environment::InitializeBindingHint::Normal));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|||
else
|
||||
initial_value = MUST(environment->get_binding_value(vm, name, false));
|
||||
|
||||
MUST(var_environment->initialize_binding(vm, name, initial_value));
|
||||
MUST(var_environment->initialize_binding(vm, name, initial_value, Environment::InitializeBindingHint::Normal));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -523,7 +523,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(vm, function_name, false));
|
||||
MUST(var_environment->initialize_binding(vm, function_name, js_undefined()));
|
||||
MUST(var_environment->initialize_binding(vm, function_name, js_undefined(), Environment::InitializeBindingHint::Normal));
|
||||
instantiated_var_names.set(function_name);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,11 @@ class Environment : public Cell {
|
|||
JS_CELL(Environment, Cell);
|
||||
|
||||
public:
|
||||
enum class InitializeBindingHint {
|
||||
Normal,
|
||||
SyncDispose,
|
||||
};
|
||||
|
||||
virtual bool has_this_binding() const { return false; }
|
||||
virtual ThrowCompletionOr<Value> get_this_binding(VM&) const { return Value {}; }
|
||||
|
||||
|
@ -31,7 +36,7 @@ public:
|
|||
virtual ThrowCompletionOr<bool> has_binding([[maybe_unused]] DeprecatedFlyString const& name, [[maybe_unused]] Optional<size_t>* out_index = nullptr) const { return false; }
|
||||
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, [[maybe_unused]] DeprecatedFlyString const& name, [[maybe_unused]] bool can_be_deleted) { return {}; }
|
||||
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, [[maybe_unused]] DeprecatedFlyString const& name, [[maybe_unused]] bool strict) { return {}; }
|
||||
virtual ThrowCompletionOr<void> initialize_binding(VM&, [[maybe_unused]] DeprecatedFlyString const& name, Value) { return {}; }
|
||||
virtual ThrowCompletionOr<void> initialize_binding(VM&, [[maybe_unused]] DeprecatedFlyString const& name, Value, InitializeBindingHint) { return {}; }
|
||||
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, [[maybe_unused]] DeprecatedFlyString const& name, Value, [[maybe_unused]] bool strict) { return {}; }
|
||||
virtual ThrowCompletionOr<Value> get_binding_value(VM&, [[maybe_unused]] DeprecatedFlyString const& name, [[maybe_unused]] bool strict) { return Value {}; }
|
||||
virtual ThrowCompletionOr<bool> delete_binding(VM&, [[maybe_unused]] DeprecatedFlyString const& name) { return false; }
|
||||
|
|
|
@ -78,20 +78,22 @@ ThrowCompletionOr<void> GlobalEnvironment::create_immutable_binding(VM& vm, Depr
|
|||
return MUST(m_declarative_record->create_immutable_binding(vm, name, strict));
|
||||
}
|
||||
|
||||
// 9.1.1.4.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-global-environment-records-initializebinding-n-v
|
||||
ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(VM& vm, DeprecatedFlyString const& name, Value value)
|
||||
// 9.1.1.4.4 InitializeBinding ( N, V, hint ), https://tc39.es/ecma262/#sec-global-environment-records-initializebinding-n-v
|
||||
ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(VM& vm, DeprecatedFlyString const& name, Value value, InitializeBindingHint hint)
|
||||
{
|
||||
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
|
||||
// 2. If ! DclRec.HasBinding(N) is true, then
|
||||
if (MUST(m_declarative_record->has_binding(name))) {
|
||||
// a. Return ! DclRec.InitializeBinding(N, V).
|
||||
return MUST(m_declarative_record->initialize_binding(vm, name, value));
|
||||
// a. Return ! DclRec.InitializeBinding(N, V, hint).
|
||||
return MUST(m_declarative_record->initialize_binding(vm, name, value, hint));
|
||||
}
|
||||
|
||||
// 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(vm, name, value);
|
||||
// 4. Assert: hint is normal.
|
||||
VERIFY(hint == Environment::InitializeBindingHint::Normal);
|
||||
// 5. Let ObjRec be envRec.[[ObjectRecord]].
|
||||
// 6. Return ? ObjRec.InitializeBinding(N, V, normal).
|
||||
return m_object_record->initialize_binding(vm, name, value, Environment::InitializeBindingHint::Normal);
|
||||
}
|
||||
|
||||
// 9.1.1.4.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-global-environment-records-setmutablebinding-n-v-s
|
||||
|
@ -263,8 +265,8 @@ ThrowCompletionOr<void> GlobalEnvironment::create_global_var_binding(DeprecatedF
|
|||
// a. Perform ? ObjRec.CreateMutableBinding(N, D).
|
||||
TRY(m_object_record->create_mutable_binding(vm, name, can_be_deleted));
|
||||
|
||||
// b. Perform ? ObjRec.InitializeBinding(N, undefined).
|
||||
TRY(m_object_record->initialize_binding(vm, name, js_undefined()));
|
||||
// b. Perform ? ObjRec.InitializeBinding(N, undefined, normal).
|
||||
TRY(m_object_record->initialize_binding(vm, name, js_undefined(), Environment::InitializeBindingHint::Normal));
|
||||
}
|
||||
|
||||
// 6. Let varDeclaredNames be envRec.[[VarNames]].
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
virtual ThrowCompletionOr<bool> has_binding(DeprecatedFlyString const& name, Optional<size_t>* = nullptr) const override;
|
||||
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, DeprecatedFlyString const& name, bool can_be_deleted) override;
|
||||
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, DeprecatedFlyString const& name, bool strict) override;
|
||||
virtual ThrowCompletionOr<void> initialize_binding(VM&, DeprecatedFlyString const& name, Value) override;
|
||||
virtual ThrowCompletionOr<void> initialize_binding(VM&, DeprecatedFlyString const& name, Value, Environment::InitializeBindingHint) override;
|
||||
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, DeprecatedFlyString const& name, Value, bool strict) override;
|
||||
virtual ThrowCompletionOr<Value> get_binding_value(VM&, DeprecatedFlyString const& name, bool strict) override;
|
||||
virtual ThrowCompletionOr<bool> delete_binding(VM&, DeprecatedFlyString const& name) override;
|
||||
|
|
|
@ -77,9 +77,12 @@ ThrowCompletionOr<void> ObjectEnvironment::create_immutable_binding(VM&, Depreca
|
|||
}
|
||||
|
||||
// 9.1.1.2.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-object-environment-records-initializebinding-n-v
|
||||
ThrowCompletionOr<void> ObjectEnvironment::initialize_binding(VM& vm, DeprecatedFlyString const& name, Value value)
|
||||
ThrowCompletionOr<void> ObjectEnvironment::initialize_binding(VM& vm, DeprecatedFlyString const& name, Value value, Environment::InitializeBindingHint hint)
|
||||
{
|
||||
// 1. Perform ? envRec.SetMutableBinding(N, V, false).
|
||||
// 1. Assert: hint is normal.
|
||||
VERIFY(hint == Environment::InitializeBindingHint::Normal);
|
||||
|
||||
// 2. Perform ? envRec.SetMutableBinding(N, V, false).
|
||||
TRY(set_mutable_binding(vm, name, value, false));
|
||||
|
||||
// 2. Return unused.
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
virtual ThrowCompletionOr<bool> has_binding(DeprecatedFlyString const& name, Optional<size_t>* = nullptr) const override;
|
||||
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, DeprecatedFlyString const& name, bool can_be_deleted) override;
|
||||
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, DeprecatedFlyString const& name, bool strict) override;
|
||||
virtual ThrowCompletionOr<void> initialize_binding(VM&, DeprecatedFlyString const& name, Value) override;
|
||||
virtual ThrowCompletionOr<void> initialize_binding(VM&, DeprecatedFlyString const& name, Value, Environment::InitializeBindingHint) override;
|
||||
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, DeprecatedFlyString const& name, Value, bool strict) override;
|
||||
virtual ThrowCompletionOr<Value> get_binding_value(VM&, DeprecatedFlyString const& name, bool strict) override;
|
||||
virtual ThrowCompletionOr<bool> delete_binding(VM&, DeprecatedFlyString const& name) override;
|
||||
|
|
|
@ -231,11 +231,12 @@ DeprecatedString Reference::to_deprecated_string() const
|
|||
}
|
||||
|
||||
// 6.2.4.8 InitializeReferencedBinding ( V, W ), https://tc39.es/ecma262/#sec-object.prototype.hasownproperty
|
||||
ThrowCompletionOr<void> Reference::initialize_referenced_binding(VM& vm, Value value) const
|
||||
// 1.2.1.1 InitializeReferencedBinding ( V, W, hint ), https://tc39.es/proposal-explicit-resource-management/#sec-initializereferencedbinding
|
||||
ThrowCompletionOr<void> Reference::initialize_referenced_binding(VM& vm, Value value, Environment::InitializeBindingHint hint) const
|
||||
{
|
||||
VERIFY(!is_unresolvable());
|
||||
VERIFY(m_base_type == BaseType::Environment);
|
||||
return m_base_environment->initialize_binding(vm, m_name.as_string(), value);
|
||||
return m_base_environment->initialize_binding(vm, m_name.as_string(), value, hint);
|
||||
}
|
||||
|
||||
// 6.2.4.9 MakePrivateReference ( baseValue, privateIdentifier ), https://tc39.es/ecma262/#sec-makeprivatereference
|
||||
|
|
|
@ -121,7 +121,7 @@ public:
|
|||
return m_base_type == BaseType::Environment;
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> initialize_referenced_binding(VM&, Value value) const;
|
||||
ThrowCompletionOr<void> initialize_referenced_binding(VM&, Value value, Environment::InitializeBindingHint hint = Environment::InitializeBindingHint::Normal) const;
|
||||
|
||||
ThrowCompletionOr<void> put_value(VM&, Value);
|
||||
ThrowCompletionOr<Value> get_value(VM&) const;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue