1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 11:28:12 +00:00

LibJS: Replace GlobalObject with VM in Environment AOs [Part 5/19]

This commit is contained in:
Linus Groh 2022-08-21 15:12:43 +01:00
parent a022e548b8
commit 275a7a0c0a
22 changed files with 222 additions and 205 deletions

View file

@ -251,7 +251,7 @@ Completion Program::execute(Interpreter& interpreter) const
Completion FunctionDeclaration::execute(Interpreter& interpreter) const Completion FunctionDeclaration::execute(Interpreter& interpreter) const
{ {
InterpreterNodeScope node_scope { interpreter, *this }; InterpreterNodeScope node_scope { interpreter, *this };
auto& global_object = interpreter.global_object(); auto& vm = interpreter.vm();
if (m_is_hoisted) { if (m_is_hoisted) {
// Perform special annexB steps see step 3 of: https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation // Perform special annexB steps see step 3 of: https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
@ -263,10 +263,10 @@ Completion FunctionDeclaration::execute(Interpreter& interpreter) const
auto* lexical_environment = interpreter.vm().running_execution_context().lexical_environment; auto* lexical_environment = interpreter.vm().running_execution_context().lexical_environment;
// iii. Let fobj be ! benv.GetBindingValue(F, false). // iii. Let fobj be ! benv.GetBindingValue(F, false).
auto function_object = MUST(lexical_environment->get_binding_value(global_object, name(), false)); auto function_object = MUST(lexical_environment->get_binding_value(vm, name(), false));
// iv. Perform ? genv.SetMutableBinding(F, fobj, false). // iv. Perform ? genv.SetMutableBinding(F, fobj, false).
TRY(variable_environment->set_mutable_binding(global_object, name(), function_object, false)); TRY(variable_environment->set_mutable_binding(vm, name(), function_object, false));
// v. Return unused. // v. Return unused.
return Optional<Value> {}; return Optional<Value> {};
@ -289,6 +289,7 @@ Completion FunctionExpression::execute(Interpreter& interpreter) const
Value FunctionExpression::instantiate_ordinary_function_expression(Interpreter& interpreter, FlyString given_name) const Value FunctionExpression::instantiate_ordinary_function_expression(Interpreter& interpreter, FlyString given_name) const
{ {
auto& global_object = interpreter.global_object(); auto& global_object = interpreter.global_object();
auto& vm = interpreter.vm();
auto& realm = *global_object.associated_realm(); auto& realm = *global_object.associated_realm();
if (given_name.is_empty()) if (given_name.is_empty())
@ -300,10 +301,10 @@ Value FunctionExpression::instantiate_ordinary_function_expression(Interpreter&
if (has_own_name) { if (has_own_name) {
VERIFY(environment); VERIFY(environment);
environment = new_declarative_environment(*environment); environment = new_declarative_environment(*environment);
MUST(environment->create_immutable_binding(global_object, name(), false)); MUST(environment->create_immutable_binding(vm, name(), false));
} }
auto* private_environment = interpreter.vm().running_execution_context().private_environment; auto* private_environment = vm.running_execution_context().private_environment;
auto closure = ECMAScriptFunctionObject::create(realm, used_name, source_text(), body(), parameters(), function_length(), environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); auto closure = ECMAScriptFunctionObject::create(realm, used_name, source_text(), body(), parameters(), function_length(), environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function());
@ -311,7 +312,7 @@ Value FunctionExpression::instantiate_ordinary_function_expression(Interpreter&
// FIXME: 7. Perform MakeConstructor(closure). // FIXME: 7. Perform MakeConstructor(closure).
if (has_own_name) if (has_own_name)
MUST(environment->initialize_binding(global_object, name(), closure)); MUST(environment->initialize_binding(vm, name(), closure));
return closure; return closure;
} }
@ -499,10 +500,10 @@ Completion SuperCall::execute(Interpreter& interpreter) const
auto* result = TRY(construct(global_object, static_cast<FunctionObject&>(*func), move(arg_list), &new_target.as_function())); auto* result = TRY(construct(global_object, static_cast<FunctionObject&>(*func), move(arg_list), &new_target.as_function()));
// 7. Let thisER be GetThisEnvironment(). // 7. Let thisER be GetThisEnvironment().
auto& this_er = verify_cast<FunctionEnvironment>(get_this_environment(interpreter.vm())); auto& this_er = verify_cast<FunctionEnvironment>(get_this_environment(vm));
// 8. Perform ? thisER.BindThisValue(result). // 8. Perform ? thisER.BindThisValue(result).
TRY(this_er.bind_this_value(global_object, result)); TRY(this_er.bind_this_value(vm, result));
// 9. Let F be thisER.[[FunctionObject]]. // 9. Let F be thisER.[[FunctionObject]].
// 10. Assert: F is an ECMAScript function object. // 10. Assert: F is an ECMAScript function object.
@ -743,7 +744,7 @@ Completion ForStatement::execute(Interpreter& interpreter) const
Completion ForStatement::loop_evaluation(Interpreter& interpreter, Vector<FlyString> const& label_set) const Completion ForStatement::loop_evaluation(Interpreter& interpreter, Vector<FlyString> const& label_set) const
{ {
InterpreterNodeScope node_scope { interpreter, *this }; InterpreterNodeScope node_scope { interpreter, *this };
auto& global_object = interpreter.global_object(); auto& vm = interpreter.vm();
// Note we don't always set a new environment but to use RAII we must do this here. // Note we don't always set a new environment but to use RAII we must do this here.
auto* old_environment = interpreter.lexical_environment(); auto* old_environment = interpreter.lexical_environment();
@ -759,9 +760,9 @@ Completion ForStatement::loop_evaluation(Interpreter& interpreter, Vector<FlyStr
auto& declaration = static_cast<VariableDeclaration const&>(*m_init); auto& declaration = static_cast<VariableDeclaration const&>(*m_init);
declaration.for_each_bound_name([&](auto const& name) { declaration.for_each_bound_name([&](auto const& name) {
if (declaration.declaration_kind() == DeclarationKind::Const) { if (declaration.declaration_kind() == DeclarationKind::Const) {
MUST(loop_environment->create_immutable_binding(global_object, name, true)); MUST(loop_environment->create_immutable_binding(vm, name, true));
} else { } else {
MUST(loop_environment->create_mutable_binding(global_object, name, false)); MUST(loop_environment->create_mutable_binding(vm, name, false));
++per_iteration_bindings_size; ++per_iteration_bindings_size;
} }
}); });
@ -885,6 +886,7 @@ struct ForInOfHeadState {
VERIFY(!next_value.is_empty()); VERIFY(!next_value.is_empty());
auto& global_object = interpreter.global_object(); auto& global_object = interpreter.global_object();
auto& vm = interpreter.vm();
Optional<Reference> lhs_reference; Optional<Reference> lhs_reference;
Environment* iteration_environment = nullptr; Environment* iteration_environment = nullptr;
@ -911,9 +913,9 @@ struct ForInOfHeadState {
auto& for_declaration = static_cast<VariableDeclaration const&>(*expression_lhs); auto& for_declaration = static_cast<VariableDeclaration const&>(*expression_lhs);
for_declaration.for_each_bound_name([&](auto const& name) { for_declaration.for_each_bound_name([&](auto const& name) {
if (for_declaration.declaration_kind() == DeclarationKind::Const) if (for_declaration.declaration_kind() == DeclarationKind::Const)
MUST(iteration_environment->create_immutable_binding(global_object, name, false)); MUST(iteration_environment->create_immutable_binding(vm, name, false));
else else
MUST(iteration_environment->create_mutable_binding(global_object, name, true)); MUST(iteration_environment->create_mutable_binding(vm, name, true));
}); });
interpreter.vm().running_execution_context().lexical_environment = iteration_environment; interpreter.vm().running_execution_context().lexical_environment = iteration_environment;
@ -955,6 +957,8 @@ struct ForInOfHeadState {
static ThrowCompletionOr<ForInOfHeadState> for_in_of_head_execute(Interpreter& interpreter, Variant<NonnullRefPtr<ASTNode>, NonnullRefPtr<BindingPattern>> lhs, Expression const& rhs) static ThrowCompletionOr<ForInOfHeadState> for_in_of_head_execute(Interpreter& interpreter, Variant<NonnullRefPtr<ASTNode>, NonnullRefPtr<BindingPattern>> lhs, Expression const& rhs)
{ {
auto& global_object = interpreter.global_object(); auto& global_object = interpreter.global_object();
auto& vm = interpreter.vm();
ForInOfHeadState state(lhs); ForInOfHeadState state(lhs);
if (auto* ast_ptr = lhs.get_pointer<NonnullRefPtr<ASTNode>>(); ast_ptr && is<VariableDeclaration>(*(*ast_ptr))) { if (auto* ast_ptr = lhs.get_pointer<NonnullRefPtr<ASTNode>>(); ast_ptr && is<VariableDeclaration>(*(*ast_ptr))) {
// Runtime Semantics: ForInOfLoopEvaluation, for any of: // Runtime Semantics: ForInOfLoopEvaluation, for any of:
@ -984,7 +988,7 @@ static ThrowCompletionOr<ForInOfHeadState> for_in_of_head_execute(Interpreter& i
state.lhs_kind = ForInOfHeadState::LexicalBinding; state.lhs_kind = ForInOfHeadState::LexicalBinding;
new_environment = new_declarative_environment(*interpreter.lexical_environment()); new_environment = new_declarative_environment(*interpreter.lexical_environment());
variable_declaration.for_each_bound_name([&](auto const& name) { variable_declaration.for_each_bound_name([&](auto const& name) {
MUST(new_environment->create_mutable_binding(global_object, name, false)); MUST(new_environment->create_mutable_binding(vm, name, false));
}); });
} }
@ -1404,9 +1408,10 @@ ThrowCompletionOr<Reference> MemberExpression::to_reference(Interpreter& interpr
// https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation // https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
if (is<SuperExpression>(object())) { if (is<SuperExpression>(object())) {
// 1. Let env be GetThisEnvironment(). // 1. Let env be GetThisEnvironment().
auto& environment = get_this_environment(interpreter.vm()); auto& environment = get_this_environment(vm);
// 2. Let actualThis be ? env.GetThisBinding(). // 2. Let actualThis be ? env.GetThisBinding().
auto actual_this = TRY(environment.get_this_binding(global_object)); auto actual_this = TRY(environment.get_this_binding(vm));
PropertyKey property_key; PropertyKey property_key;
@ -1824,7 +1829,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::class_definition_e
}; };
if (!binding_name.is_null()) if (!binding_name.is_null())
MUST(class_environment->create_immutable_binding(global_object, binding_name, true)); MUST(class_environment->create_immutable_binding(vm, binding_name, true));
auto* outer_private_environment = vm.running_execution_context().private_environment; auto* outer_private_environment = vm.running_execution_context().private_environment;
auto* class_private_environment = new_private_environment(vm, outer_private_environment); auto* class_private_environment = new_private_environment(vm, outer_private_environment);
@ -1949,7 +1954,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::class_definition_e
restore_environment.disarm(); restore_environment.disarm();
if (!binding_name.is_null()) if (!binding_name.is_null())
MUST(class_environment->initialize_binding(global_object, binding_name, class_constructor)); MUST(class_environment->initialize_binding(vm, binding_name, class_constructor));
for (auto& field : instance_fields) for (auto& field : instance_fields)
class_constructor->add_field(field); class_constructor->add_field(field);
@ -2583,10 +2588,10 @@ Completion SpreadExpression::execute(Interpreter& interpreter) const
Completion ThisExpression::execute(Interpreter& interpreter) const Completion ThisExpression::execute(Interpreter& interpreter) const
{ {
InterpreterNodeScope node_scope { interpreter, *this }; InterpreterNodeScope node_scope { interpreter, *this };
auto& global_object = interpreter.global_object(); auto& vm = interpreter.vm();
// 1. Return ? ResolveThisBinding(). // 1. Return ? ResolveThisBinding().
return interpreter.vm().resolve_this_binding(global_object); return vm.resolve_this_binding();
} }
void ThisExpression::dump(int indent) const void ThisExpression::dump(int indent) const
@ -3795,13 +3800,13 @@ Completion TryStatement::execute(Interpreter& interpreter) const
[&](FlyString const& parameter) { [&](FlyString const& parameter) {
// 3. For each element argName of the BoundNames of CatchParameter, do // 3. For each element argName of the BoundNames of CatchParameter, do
// a. Perform ! catchEnv.CreateMutableBinding(argName, false). // a. Perform ! catchEnv.CreateMutableBinding(argName, false).
MUST(catch_environment->create_mutable_binding(global_object, parameter, false)); MUST(catch_environment->create_mutable_binding(vm, parameter, false));
}, },
[&](NonnullRefPtr<BindingPattern> const& pattern) { [&](NonnullRefPtr<BindingPattern> const& pattern) {
// 3. For each element argName of the BoundNames of CatchParameter, do // 3. For each element argName of the BoundNames of CatchParameter, do
pattern->for_each_bound_name([&](auto& name) { pattern->for_each_bound_name([&](auto& name) {
// a. Perform ! catchEnv.CreateMutableBinding(argName, false). // a. Perform ! catchEnv.CreateMutableBinding(argName, false).
MUST(catch_environment->create_mutable_binding(global_object, name, false)); MUST(catch_environment->create_mutable_binding(vm, name, false));
}); });
}); });
@ -3811,7 +3816,7 @@ Completion TryStatement::execute(Interpreter& interpreter) const
// 5. Let status be Completion(BindingInitialization of CatchParameter with arguments thrownValue and catchEnv). // 5. Let status be Completion(BindingInitialization of CatchParameter with arguments thrownValue and catchEnv).
auto status = m_handler->parameter().visit( auto status = m_handler->parameter().visit(
[&](FlyString const& parameter) { [&](FlyString const& parameter) {
return catch_environment->initialize_binding(global_object, parameter, thrown_value); return catch_environment->initialize_binding(vm, parameter, thrown_value);
}, },
[&](NonnullRefPtr<BindingPattern> const& pattern) { [&](NonnullRefPtr<BindingPattern> const& pattern) {
return vm.binding_initialization(pattern, thrown_value, catch_environment, global_object); return vm.binding_initialization(pattern, thrown_value, catch_environment, global_object);
@ -4523,19 +4528,20 @@ void ScopeNode::block_declaration_instantiation(Interpreter& interpreter, Enviro
{ {
// See also B.3.2.6 Changes to BlockDeclarationInstantiation, https://tc39.es/ecma262/#sec-web-compat-blockdeclarationinstantiation // See also B.3.2.6 Changes to BlockDeclarationInstantiation, https://tc39.es/ecma262/#sec-web-compat-blockdeclarationinstantiation
auto& global_object = interpreter.global_object(); auto& global_object = interpreter.global_object();
auto& vm = interpreter.vm();
auto& realm = *global_object.associated_realm(); auto& realm = *global_object.associated_realm();
VERIFY(environment); VERIFY(environment);
auto* private_environment = global_object.vm().running_execution_context().private_environment; auto* private_environment = vm.running_execution_context().private_environment;
// Note: All the calls here are ! and thus we do not need to TRY this callback. // Note: All the calls here are ! and thus we do not need to TRY this callback.
for_each_lexically_scoped_declaration([&](Declaration const& declaration) { for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
auto is_constant_declaration = declaration.is_constant_declaration(); auto is_constant_declaration = declaration.is_constant_declaration();
declaration.for_each_bound_name([&](auto const& name) { declaration.for_each_bound_name([&](auto const& name) {
if (is_constant_declaration) { if (is_constant_declaration) {
MUST(environment->create_immutable_binding(global_object, name, true)); MUST(environment->create_immutable_binding(vm, name, true));
} else { } else {
if (!MUST(environment->has_binding(name))) if (!MUST(environment->has_binding(name)))
MUST(environment->create_mutable_binding(global_object, name, false)); MUST(environment->create_mutable_binding(vm, name, false));
} }
}); });
@ -4543,7 +4549,7 @@ void ScopeNode::block_declaration_instantiation(Interpreter& interpreter, Enviro
auto& function_declaration = static_cast<FunctionDeclaration const&>(declaration); auto& function_declaration = static_cast<FunctionDeclaration const&>(declaration);
auto* function = ECMAScriptFunctionObject::create(realm, function_declaration.name(), function_declaration.source_text(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), environment, private_environment, function_declaration.kind(), function_declaration.is_strict_mode(), function_declaration.might_need_arguments_object(), function_declaration.contains_direct_call_to_eval()); auto* function = ECMAScriptFunctionObject::create(realm, function_declaration.name(), function_declaration.source_text(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), environment, private_environment, function_declaration.kind(), function_declaration.is_strict_mode(), function_declaration.might_need_arguments_object(), function_declaration.contains_direct_call_to_eval());
VERIFY(is<DeclarativeEnvironment>(*environment)); VERIFY(is<DeclarativeEnvironment>(*environment));
static_cast<DeclarativeEnvironment&>(*environment).initialize_or_set_mutable_binding({}, global_object, function_declaration.name(), function); static_cast<DeclarativeEnvironment&>(*environment).initialize_or_set_mutable_binding({}, vm, function_declaration.name(), function);
} }
}); });
} }
@ -4552,6 +4558,7 @@ void ScopeNode::block_declaration_instantiation(Interpreter& interpreter, Enviro
ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& interpreter, GlobalEnvironment& global_environment) const ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& interpreter, GlobalEnvironment& global_environment) const
{ {
auto& global_object = interpreter.global_object(); auto& global_object = interpreter.global_object();
auto& vm = interpreter.vm();
auto& realm = *global_object.associated_realm(); auto& realm = *global_object.associated_realm();
// 1. Let lexNames be the LexicallyDeclaredNames of script. // 1. Let lexNames be the LexicallyDeclaredNames of script.
@ -4560,18 +4567,18 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& i
TRY(for_each_lexically_declared_name([&](FlyString const& name) -> ThrowCompletionOr<void> { TRY(for_each_lexically_declared_name([&](FlyString const& name) -> ThrowCompletionOr<void> {
// a. If env.HasVarDeclaration(name) is true, throw a SyntaxError exception. // a. If env.HasVarDeclaration(name) is true, throw a SyntaxError exception.
if (global_environment.has_var_declaration(name)) if (global_environment.has_var_declaration(name))
return interpreter.vm().throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, name); return vm.throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, name);
// b. If env.HasLexicalDeclaration(name) is true, throw a SyntaxError exception. // b. If env.HasLexicalDeclaration(name) is true, throw a SyntaxError exception.
if (global_environment.has_lexical_declaration(name)) if (global_environment.has_lexical_declaration(name))
return interpreter.vm().throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, name); return vm.throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, name);
// c. Let hasRestrictedGlobal be ? env.HasRestrictedGlobalProperty(name). // c. Let hasRestrictedGlobal be ? env.HasRestrictedGlobalProperty(name).
auto has_restricted_global = TRY(global_environment.has_restricted_global_property(name)); auto has_restricted_global = TRY(global_environment.has_restricted_global_property(name));
// d. If hasRestrictedGlobal is true, throw a SyntaxError exception. // d. If hasRestrictedGlobal is true, throw a SyntaxError exception.
if (has_restricted_global) if (has_restricted_global)
return interpreter.vm().throw_completion<SyntaxError>(ErrorType::RestrictedGlobalProperty, name); return vm.throw_completion<SyntaxError>(ErrorType::RestrictedGlobalProperty, name);
return {}; return {};
})); }));
@ -4580,7 +4587,7 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& i
TRY(for_each_var_declared_name([&](auto const& name) -> ThrowCompletionOr<void> { TRY(for_each_var_declared_name([&](auto const& name) -> ThrowCompletionOr<void> {
// a. If env.HasLexicalDeclaration(name) is true, throw a SyntaxError exception. // a. If env.HasLexicalDeclaration(name) is true, throw a SyntaxError exception.
if (global_environment.has_lexical_declaration(name)) if (global_environment.has_lexical_declaration(name))
return interpreter.vm().throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, name); return vm.throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, name);
return {}; return {};
})); }));
@ -4612,7 +4619,7 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& i
// 2. If fnDefinable is false, throw a TypeError exception. // 2. If fnDefinable is false, throw a TypeError exception.
if (!function_definable) if (!function_definable)
return interpreter.vm().throw_completion<TypeError>(ErrorType::CannotDeclareGlobalFunction, function.name()); return vm.throw_completion<TypeError>(ErrorType::CannotDeclareGlobalFunction, function.name());
// 3. Append fn to declaredFunctionNames. // 3. Append fn to declaredFunctionNames.
// Note: Already done in step iv. above. // Note: Already done in step iv. above.
@ -4641,7 +4648,7 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& i
// b. If vnDefinable is false, throw a TypeError exception. // b. If vnDefinable is false, throw a TypeError exception.
if (!var_definable) if (!var_definable)
return interpreter.vm().throw_completion<TypeError>(ErrorType::CannotDeclareGlobalVariable, name); return vm.throw_completion<TypeError>(ErrorType::CannotDeclareGlobalVariable, name);
// c. If vn is not an element of declaredVarNames, then // c. If vn is not an element of declaredVarNames, then
// i. Append vn to declaredVarNames. // i. Append vn to declaredVarNames.
@ -4715,12 +4722,12 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& i
// i. If IsConstantDeclaration of d is true, then // i. If IsConstantDeclaration of d is true, then
if (declaration.is_constant_declaration()) { if (declaration.is_constant_declaration()) {
// 1. Perform ? env.CreateImmutableBinding(dn, true). // 1. Perform ? env.CreateImmutableBinding(dn, true).
TRY(global_environment.create_immutable_binding(global_object, name, true)); TRY(global_environment.create_immutable_binding(vm, name, true));
} }
// ii. Else, // ii. Else,
else { else {
// 1. Perform ? env.CreateMutableBinding(dn, false). // 1. Perform ? env.CreateMutableBinding(dn, false).
TRY(global_environment.create_mutable_binding(global_object, name, false)); TRY(global_environment.create_mutable_binding(vm, name, false));
} }
return {}; return {};

View file

@ -357,15 +357,15 @@ ThrowCompletionOr<void> CreateVariable::execute_impl(Bytecode::Interpreter& inte
return vm.throw_completion<InternalError>(String::formatted("Lexical environment already has binding '{}'", name)); return vm.throw_completion<InternalError>(String::formatted("Lexical environment already has binding '{}'", name));
if (m_is_immutable) if (m_is_immutable)
vm.lexical_environment()->create_immutable_binding(interpreter.global_object(), name, vm.in_strict_mode()); vm.lexical_environment()->create_immutable_binding(vm, name, vm.in_strict_mode());
else else
vm.lexical_environment()->create_mutable_binding(interpreter.global_object(), name, vm.in_strict_mode()); vm.lexical_environment()->create_mutable_binding(vm, name, vm.in_strict_mode());
} else { } else {
if (!m_is_global) { if (!m_is_global) {
if (m_is_immutable) if (m_is_immutable)
vm.variable_environment()->create_immutable_binding(interpreter.global_object(), name, vm.in_strict_mode()); vm.variable_environment()->create_immutable_binding(vm, name, vm.in_strict_mode());
else else
vm.variable_environment()->create_mutable_binding(interpreter.global_object(), name, vm.in_strict_mode()); vm.variable_environment()->create_mutable_binding(vm, name, vm.in_strict_mode());
} else { } else {
// NOTE: CreateVariable with m_is_global set to true is expected to only be used in GlobalDeclarationInstantiation currently, which only uses "false" for "can_be_deleted". // NOTE: CreateVariable with m_is_global set to true is expected to only be used in GlobalDeclarationInstantiation currently, which only uses "false" for "can_be_deleted".
// The only area that sets "can_be_deleted" to true is EvalDeclarationInstantiation, which is currently fully implemented in C++ and not in Bytecode. // The only area that sets "can_be_deleted" to true is EvalDeclarationInstantiation, which is currently fully implemented in C++ and not in Bytecode.
@ -391,7 +391,7 @@ ThrowCompletionOr<void> SetVariable::execute_impl(Bytecode::Interpreter& interpr
case InitializationMode::InitializeOrSet: case InitializationMode::InitializeOrSet:
VERIFY(reference.is_environment_reference()); VERIFY(reference.is_environment_reference());
VERIFY(reference.base_environment().is_declarative_environment()); VERIFY(reference.base_environment().is_declarative_environment());
TRY(static_cast<DeclarativeEnvironment&>(reference.base_environment()).initialize_or_set_mutable_binding(interpreter.global_object(), name, interpreter.accumulator())); TRY(static_cast<DeclarativeEnvironment&>(reference.base_environment()).initialize_or_set_mutable_binding(vm, name, interpreter.accumulator()));
break; break;
} }
return {}; return {};
@ -433,7 +433,8 @@ ThrowCompletionOr<void> Jump::execute_impl(Bytecode::Interpreter& interpreter) c
ThrowCompletionOr<void> ResolveThisBinding::execute_impl(Bytecode::Interpreter& interpreter) const ThrowCompletionOr<void> ResolveThisBinding::execute_impl(Bytecode::Interpreter& interpreter) const
{ {
interpreter.accumulator() = TRY(interpreter.vm().resolve_this_binding(interpreter.global_object())); auto& vm = interpreter.vm();
interpreter.accumulator() = TRY(vm.resolve_this_binding());
return {}; return {};
} }

View file

@ -218,7 +218,7 @@ ThrowCompletionOr<void> initialize_bound_name(GlobalObject& global_object, FlySt
// 1. If environment is not undefined, then // 1. If environment is not undefined, then
if (environment) { if (environment) {
// a. Perform ! environment.InitializeBinding(name, value). // a. Perform ! environment.InitializeBinding(name, value).
MUST(environment->initialize_binding(global_object, name, value)); MUST(environment->initialize_binding(vm, name, value));
// b. Return unused. // b. Return unused.
return {}; return {};
@ -897,8 +897,8 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
if (!MUST(variable_environment->has_binding(function_name))) { if (!MUST(variable_environment->has_binding(function_name))) {
// i. Perform ! varEnv.CreateMutableBinding(F, true). // i. Perform ! varEnv.CreateMutableBinding(F, true).
// ii. Perform ! varEnv.InitializeBinding(F, undefined). // ii. Perform ! varEnv.InitializeBinding(F, undefined).
MUST(variable_environment->create_mutable_binding(global_object, function_name, true)); MUST(variable_environment->create_mutable_binding(vm, function_name, true));
MUST(variable_environment->initialize_binding(global_object, function_name, js_undefined())); MUST(variable_environment->initialize_binding(vm, function_name, js_undefined()));
} }
} }
} }
@ -960,12 +960,12 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
// i. If IsConstantDeclaration of d is true, then // i. If IsConstantDeclaration of d is true, then
if (declaration.is_constant_declaration()) { if (declaration.is_constant_declaration()) {
// 1. Perform ? lexEnv.CreateImmutableBinding(dn, true). // 1. Perform ? lexEnv.CreateImmutableBinding(dn, true).
TRY(lexical_environment->create_immutable_binding(global_object, name, true)); TRY(lexical_environment->create_immutable_binding(vm, name, true));
} }
// ii. Else, // ii. Else,
else { else {
// 1. Perform ? lexEnv.CreateMutableBinding(dn, false). // 1. Perform ? lexEnv.CreateMutableBinding(dn, false).
TRY(lexical_environment->create_mutable_binding(global_object, name, false)); TRY(lexical_environment->create_mutable_binding(vm, name, false));
} }
return {}; return {};
}); });
@ -991,15 +991,15 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
if (!binding_exists) { if (!binding_exists) {
// 1. NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14. // 1. NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14.
// 2. Perform ! varEnv.CreateMutableBinding(fn, true). // 2. Perform ! varEnv.CreateMutableBinding(fn, true).
MUST(variable_environment->create_mutable_binding(global_object, declaration.name(), true)); MUST(variable_environment->create_mutable_binding(vm, declaration.name(), true));
// 3. Perform ! varEnv.InitializeBinding(fn, fo). // 3. Perform ! varEnv.InitializeBinding(fn, fo).
MUST(variable_environment->initialize_binding(global_object, declaration.name(), function)); MUST(variable_environment->initialize_binding(vm, declaration.name(), function));
} }
// iii. Else, // iii. Else,
else { else {
// 1. Perform ! varEnv.SetMutableBinding(fn, fo, false). // 1. Perform ! varEnv.SetMutableBinding(fn, fo, false).
MUST(variable_environment->set_mutable_binding(global_object, declaration.name(), function, false)); MUST(variable_environment->set_mutable_binding(vm, declaration.name(), function, false));
} }
} }
} }
@ -1021,10 +1021,10 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
if (!binding_exists) { if (!binding_exists) {
// 1. NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14. // 1. NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14.
// 2. Perform ! varEnv.CreateMutableBinding(vn, true). // 2. Perform ! varEnv.CreateMutableBinding(vn, true).
MUST(variable_environment->create_mutable_binding(global_object, var_name, true)); MUST(variable_environment->create_mutable_binding(vm, var_name, true));
// 3. Perform ! varEnv.InitializeBinding(vn, undefined). // 3. Perform ! varEnv.InitializeBinding(vn, undefined).
MUST(variable_environment->initialize_binding(global_object, var_name, js_undefined())); MUST(variable_environment->initialize_binding(vm, var_name, js_undefined()));
} }
} }
} }
@ -1134,11 +1134,11 @@ Object* create_mapped_arguments_object(GlobalObject& global_object, FunctionObje
// 3. Perform ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true }). // 3. Perform ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true }).
object->parameter_map().define_native_accessor( object->parameter_map().define_native_accessor(
PropertyKey { index }, PropertyKey { index },
[&environment, name](VM&, GlobalObject& global_object_getter) -> ThrowCompletionOr<Value> { [&environment, name](VM& vm, GlobalObject&) -> ThrowCompletionOr<Value> {
return MUST(environment.get_binding_value(global_object_getter, name, false)); return MUST(environment.get_binding_value(vm, name, false));
}, },
[&environment, name](VM& vm, GlobalObject& global_object_setter) { [&environment, name](VM& vm, GlobalObject&) {
MUST(environment.set_mutable_binding(global_object_setter, name, vm.argument(0), false)); MUST(environment.set_mutable_binding(vm, name, vm.argument(0), false));
return js_undefined(); return js_undefined();
}, },
Attribute::Configurable); Attribute::Configurable);

View file

@ -56,7 +56,7 @@ ThrowCompletionOr<bool> DeclarativeEnvironment::has_binding(FlyString const& nam
} }
// 9.1.1.1.2 CreateMutableBinding ( N, D ), https://tc39.es/ecma262/#sec-declarative-environment-records-createmutablebinding-n-d // 9.1.1.1.2 CreateMutableBinding ( N, D ), https://tc39.es/ecma262/#sec-declarative-environment-records-createmutablebinding-n-d
ThrowCompletionOr<void> DeclarativeEnvironment::create_mutable_binding(GlobalObject&, FlyString const& name, bool can_be_deleted) ThrowCompletionOr<void> DeclarativeEnvironment::create_mutable_binding(VM&, FlyString const& name, bool can_be_deleted)
{ {
// 1. Assert: envRec does not already have a binding for N. // 1. Assert: envRec does not already have a binding for N.
// NOTE: We skip this to avoid O(n) traversal of m_bindings. // NOTE: We skip this to avoid O(n) traversal of m_bindings.
@ -76,7 +76,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_mutable_binding(GlobalObj
} }
// 9.1.1.1.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-createimmutablebinding-n-s // 9.1.1.1.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-createimmutablebinding-n-s
ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(GlobalObject&, FlyString const& name, bool strict) ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(VM&, FlyString const& name, bool strict)
{ {
// 1. Assert: envRec does not already have a binding for N. // 1. Assert: envRec does not already have a binding for N.
// NOTE: We skip this to avoid O(n) traversal of m_bindings. // NOTE: We skip this to avoid O(n) traversal of m_bindings.
@ -96,15 +96,15 @@ 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 // 9.1.1.1.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-declarative-environment-records-initializebinding-n-v
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(GlobalObject& global_object, FlyString const& name, Value value) ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(VM& vm, FlyString const& name, Value value)
{ {
auto index = find_binding_index(name); auto index = find_binding_index(name);
VERIFY(index.has_value()); VERIFY(index.has_value());
return initialize_binding_direct(global_object, *index, value); return initialize_binding_direct(vm, *index, value);
} }
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding_direct(GlobalObject&, size_t index, Value value) ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding_direct(VM&, size_t index, Value value)
{ {
auto& binding = m_bindings[index]; auto& binding = m_bindings[index];
@ -122,63 +122,63 @@ ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding_direct(Global
} }
// 9.1.1.1.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-setmutablebinding-n-v-s // 9.1.1.1.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-setmutablebinding-n-v-s
ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding(GlobalObject& global_object, FlyString const& name, Value value, bool strict) ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding(VM& vm, FlyString const& name, Value value, bool strict)
{ {
// 1. If envRec does not have a binding for N, then // 1. If envRec does not have a binding for N, then
auto index = find_binding_index(name); auto index = find_binding_index(name);
if (!index.has_value()) { if (!index.has_value()) {
// a. If S is true, throw a ReferenceError exception. // a. If S is true, throw a ReferenceError exception.
if (strict) if (strict)
return vm().throw_completion<ReferenceError>(ErrorType::UnknownIdentifier, name); return vm.throw_completion<ReferenceError>(ErrorType::UnknownIdentifier, name);
// b. Perform ! envRec.CreateMutableBinding(N, true). // b. Perform ! envRec.CreateMutableBinding(N, true).
MUST(create_mutable_binding(global_object, name, true)); MUST(create_mutable_binding(vm, name, true));
// c. Perform ! envRec.InitializeBinding(N, V). // c. Perform ! envRec.InitializeBinding(N, V).
MUST(initialize_binding(global_object, name, value)); MUST(initialize_binding(vm, name, value));
// d. Return unused. // d. Return unused.
return {}; return {};
} }
// 2-5. (extracted into a non-standard function below) // 2-5. (extracted into a non-standard function below)
TRY(set_mutable_binding_direct(global_object, *index, value, strict)); TRY(set_mutable_binding_direct(vm, *index, value, strict));
// 6. Return unused. // 6. Return unused.
return {}; return {};
} }
ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding_direct(GlobalObject&, size_t index, Value value, bool strict) ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding_direct(VM& vm, size_t index, Value value, bool strict)
{ {
auto& binding = m_bindings[index]; auto& binding = m_bindings[index];
if (binding.strict) if (binding.strict)
strict = true; strict = true;
if (!binding.initialized) if (!binding.initialized)
return vm().throw_completion<ReferenceError>(ErrorType::BindingNotInitialized, binding.name); return vm.throw_completion<ReferenceError>(ErrorType::BindingNotInitialized, binding.name);
if (binding.mutable_) { if (binding.mutable_) {
binding.value = value; binding.value = value;
} else { } else {
if (strict) if (strict)
return vm().throw_completion<TypeError>(ErrorType::InvalidAssignToConst); return vm.throw_completion<TypeError>(ErrorType::InvalidAssignToConst);
} }
return {}; return {};
} }
// 9.1.1.1.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-getbindingvalue-n-s // 9.1.1.1.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-getbindingvalue-n-s
ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value(GlobalObject& global_object, FlyString const& name, bool strict) ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value(VM& vm, FlyString const& name, bool strict)
{ {
// 1. Assert: envRec has a binding for N. // 1. Assert: envRec has a binding for N.
auto index = find_binding_index(name); auto index = find_binding_index(name);
VERIFY(index.has_value()); VERIFY(index.has_value());
// 2-3. (extracted into a non-standard function below) // 2-3. (extracted into a non-standard function below)
return get_binding_value_direct(global_object, *index, strict); return get_binding_value_direct(vm, *index, strict);
} }
ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value_direct(GlobalObject&, size_t index, bool) ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value_direct(VM&, size_t index, bool)
{ {
auto& binding = m_bindings[index]; auto& binding = m_bindings[index];
@ -191,7 +191,7 @@ ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value_direct(Global
} }
// 9.1.1.1.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-declarative-environment-records-deletebinding-n // 9.1.1.1.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-declarative-environment-records-deletebinding-n
ThrowCompletionOr<bool> DeclarativeEnvironment::delete_binding(GlobalObject&, FlyString const& name) ThrowCompletionOr<bool> DeclarativeEnvironment::delete_binding(VM&, FlyString const& name)
{ {
// 1. Assert: envRec has a binding for the name that is the value of N. // 1. Assert: envRec has a binding for the name that is the value of N.
auto index = find_binding_index(name); auto index = find_binding_index(name);
@ -211,21 +211,21 @@ ThrowCompletionOr<bool> DeclarativeEnvironment::delete_binding(GlobalObject&, Fl
return true; return true;
} }
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_or_set_mutable_binding(GlobalObject& global_object, FlyString const& name, Value value) ThrowCompletionOr<void> DeclarativeEnvironment::initialize_or_set_mutable_binding(VM& vm, FlyString const& name, Value value)
{ {
auto index = find_binding_index(name); auto index = find_binding_index(name);
VERIFY(index.has_value()); VERIFY(index.has_value());
auto& binding = m_bindings[*index]; auto& binding = m_bindings[*index];
if (!binding.initialized) if (!binding.initialized)
TRY(initialize_binding(global_object, name, value)); TRY(initialize_binding(vm, name, value));
else else
TRY(set_mutable_binding(global_object, name, value, false)); TRY(set_mutable_binding(vm, name, value, false));
return {}; return {};
} }
void DeclarativeEnvironment::initialize_or_set_mutable_binding(Badge<ScopeNode>, GlobalObject& global_object, FlyString const& name, Value value) void DeclarativeEnvironment::initialize_or_set_mutable_binding(Badge<ScopeNode>, VM& vm, FlyString const& name, Value value)
{ {
MUST(initialize_or_set_mutable_binding(global_object, name, value)); MUST(initialize_or_set_mutable_binding(vm, name, value));
} }
} }

View file

@ -35,15 +35,15 @@ public:
virtual ~DeclarativeEnvironment() override = default; virtual ~DeclarativeEnvironment() override = default;
virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override; 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_mutable_binding(VM&, FlyString const& name, bool can_be_deleted) override;
virtual ThrowCompletionOr<void> create_immutable_binding(GlobalObject&, FlyString const& name, bool strict) override; virtual ThrowCompletionOr<void> create_immutable_binding(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<void> initialize_binding(GlobalObject&, FlyString const& name, Value) override; virtual ThrowCompletionOr<void> initialize_binding(VM&, FlyString const& name, Value) override;
virtual ThrowCompletionOr<void> set_mutable_binding(GlobalObject&, FlyString const& name, Value, bool strict) override; virtual ThrowCompletionOr<void> set_mutable_binding(VM&, FlyString const& name, Value, bool strict) override;
virtual ThrowCompletionOr<Value> get_binding_value(GlobalObject&, FlyString const& name, bool strict) override; virtual ThrowCompletionOr<Value> get_binding_value(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(GlobalObject&, FlyString const& name) override; virtual ThrowCompletionOr<bool> delete_binding(VM&, FlyString const& name) override;
void initialize_or_set_mutable_binding(Badge<ScopeNode>, GlobalObject& global_object, FlyString const& name, Value value); void initialize_or_set_mutable_binding(Badge<ScopeNode>, VM&, FlyString const& name, Value value);
ThrowCompletionOr<void> initialize_or_set_mutable_binding(GlobalObject& global_object, FlyString const& name, Value value); ThrowCompletionOr<void> initialize_or_set_mutable_binding(VM&, FlyString const& name, Value value);
// This is not a method defined in the spec! Do not use this in any LibJS (or other spec related) code. // This is not a method defined in the spec! Do not use this in any LibJS (or other spec related) code.
[[nodiscard]] Vector<FlyString> bindings() const [[nodiscard]] Vector<FlyString> bindings() const
@ -57,9 +57,9 @@ public:
return names; return names;
} }
ThrowCompletionOr<void> initialize_binding_direct(GlobalObject&, size_t index, Value); ThrowCompletionOr<void> initialize_binding_direct(VM&, size_t index, Value);
ThrowCompletionOr<Value> get_binding_value_direct(GlobalObject&, size_t index, bool strict); ThrowCompletionOr<Value> get_binding_value_direct(VM&, size_t index, bool strict);
ThrowCompletionOr<void> set_mutable_binding_direct(GlobalObject&, size_t index, Value, bool strict); ThrowCompletionOr<void> set_mutable_binding_direct(VM&, size_t index, Value, bool strict);
protected: protected:
virtual void visit_edges(Visitor&) override; virtual void visit_edges(Visitor&) override;

View file

@ -283,7 +283,7 @@ ThrowCompletionOr<Object*> ECMAScriptFunctionObject::internal_construct(MarkedVe
} }
// 12. Let thisBinding be ? constructorEnv.GetThisBinding(). // 12. Let thisBinding be ? constructorEnv.GetThisBinding().
auto this_binding = TRY(constructor_env->get_this_binding(global_object)); auto this_binding = TRY(constructor_env->get_this_binding(vm));
// 13. Assert: Type(thisBinding) is Object. // 13. Assert: Type(thisBinding) is Object.
VERIFY(this_binding.is_object()); VERIFY(this_binding.is_object());
@ -401,9 +401,9 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
if (MUST(environment->has_binding(parameter_name))) if (MUST(environment->has_binding(parameter_name)))
continue; continue;
MUST(environment->create_mutable_binding(global_object, parameter_name, false)); MUST(environment->create_mutable_binding(vm, parameter_name, false));
if (has_duplicates) if (has_duplicates)
MUST(environment->initialize_binding(global_object, parameter_name, js_undefined())); MUST(environment->initialize_binding(vm, parameter_name, js_undefined()));
} }
if (arguments_object_needed) { if (arguments_object_needed) {
@ -414,11 +414,11 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
arguments_object = create_mapped_arguments_object(global_object, *this, formal_parameters(), vm.running_execution_context().arguments, *environment); arguments_object = create_mapped_arguments_object(global_object, *this, formal_parameters(), vm.running_execution_context().arguments, *environment);
if (is_strict_mode()) if (is_strict_mode())
MUST(environment->create_immutable_binding(global_object, vm.names.arguments.as_string(), false)); MUST(environment->create_immutable_binding(vm, vm.names.arguments.as_string(), false));
else else
MUST(environment->create_mutable_binding(global_object, vm.names.arguments.as_string(), false)); MUST(environment->create_mutable_binding(vm, vm.names.arguments.as_string(), false));
MUST(environment->initialize_binding(global_object, vm.names.arguments.as_string(), arguments_object)); MUST(environment->initialize_binding(vm, vm.names.arguments.as_string(), arguments_object));
parameter_names.set(vm.names.arguments.as_string()); parameter_names.set(vm.names.arguments.as_string());
} }
@ -483,8 +483,8 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
if (scope_body) { if (scope_body) {
scope_body->for_each_var_declared_name([&](auto const& name) { scope_body->for_each_var_declared_name([&](auto const& name) {
if (!parameter_names.contains(name) && instantiated_var_names.set(name) == AK::HashSetResult::InsertedNewEntry) { if (!parameter_names.contains(name) && instantiated_var_names.set(name) == AK::HashSetResult::InsertedNewEntry) {
MUST(environment->create_mutable_binding(global_object, name, false)); MUST(environment->create_mutable_binding(vm, name, false));
MUST(environment->initialize_binding(global_object, name, js_undefined())); MUST(environment->initialize_binding(vm, name, js_undefined()));
} }
}); });
} }
@ -497,15 +497,15 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
scope_body->for_each_var_declared_name([&](auto const& name) { scope_body->for_each_var_declared_name([&](auto const& name) {
if (instantiated_var_names.set(name) != AK::HashSetResult::InsertedNewEntry) if (instantiated_var_names.set(name) != AK::HashSetResult::InsertedNewEntry)
return; return;
MUST(var_environment->create_mutable_binding(global_object, name, false)); MUST(var_environment->create_mutable_binding(vm, name, false));
Value initial_value; Value initial_value;
if (!parameter_names.contains(name) || function_names.contains(name)) if (!parameter_names.contains(name) || function_names.contains(name))
initial_value = js_undefined(); initial_value = js_undefined();
else else
initial_value = MUST(environment->get_binding_value(global_object, name, false)); initial_value = MUST(environment->get_binding_value(vm, name, false));
MUST(var_environment->initialize_binding(global_object, name, initial_value)); MUST(var_environment->initialize_binding(vm, name, initial_value));
}); });
} }
} }
@ -518,8 +518,8 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
return; return;
// The spec says 'initializedBindings' here but that does not exist and it then adds it to 'instantiatedVarNames' so it probably means 'instantiatedVarNames'. // 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()) { 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)); MUST(var_environment->create_mutable_binding(vm, function_name, false));
MUST(var_environment->initialize_binding(global_object, function_name, js_undefined())); MUST(var_environment->initialize_binding(vm, function_name, js_undefined()));
instantiated_var_names.set(function_name); instantiated_var_names.set(function_name);
} }
@ -560,9 +560,9 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
scope_body->for_each_lexically_scoped_declaration([&](Declaration const& declaration) { scope_body->for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
declaration.for_each_bound_name([&](auto const& name) { declaration.for_each_bound_name([&](auto const& name) {
if (declaration.is_constant_declaration()) if (declaration.is_constant_declaration())
MUST(lex_environment->create_immutable_binding(global_object, name, true)); MUST(lex_environment->create_immutable_binding(vm, name, true));
else else
MUST(lex_environment->create_mutable_binding(global_object, name, false)); MUST(lex_environment->create_mutable_binding(vm, name, false));
}); });
}); });
} }
@ -570,7 +570,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
auto* private_environment = callee_context.private_environment; auto* private_environment = callee_context.private_environment;
for (auto& declaration : functions_to_initialize) { for (auto& declaration : functions_to_initialize) {
auto* function = ECMAScriptFunctionObject::create(realm, declaration.name(), declaration.source_text(), declaration.body(), declaration.parameters(), declaration.function_length(), lex_environment, private_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object(), declaration.contains_direct_call_to_eval()); auto* function = ECMAScriptFunctionObject::create(realm, declaration.name(), declaration.source_text(), declaration.body(), declaration.parameters(), declaration.function_length(), lex_environment, private_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object(), declaration.contains_direct_call_to_eval());
MUST(var_environment->set_mutable_binding(global_object, declaration.name(), function, false)); MUST(var_environment->set_mutable_binding(vm, declaration.name(), function, false));
} }
return {}; return {};
@ -692,7 +692,7 @@ void ECMAScriptFunctionObject::ordinary_call_bind_this(ExecutionContext& callee_
// 7. Assert: localEnv is a function Environment Record. // 7. Assert: localEnv is a function Environment Record.
// 8. Assert: The next step never returns an abrupt completion because localEnv.[[ThisBindingStatus]] is not initialized. // 8. Assert: The next step never returns an abrupt completion because localEnv.[[ThisBindingStatus]] is not initialized.
// 9. Perform ! localEnv.BindThisValue(thisValue). // 9. Perform ! localEnv.BindThisValue(thisValue).
MUST(verify_cast<FunctionEnvironment>(local_env)->bind_this_value(global_object(), this_value)); MUST(verify_cast<FunctionEnvironment>(local_env)->bind_this_value(vm, this_value));
// 10. Return unused. // 10. Return unused.
} }

View file

@ -25,17 +25,17 @@ public: \
class Environment : public Cell { class Environment : public Cell {
public: public:
virtual bool has_this_binding() const { return false; } virtual bool has_this_binding() const { return false; }
virtual ThrowCompletionOr<Value> get_this_binding(GlobalObject&) const { return Value {}; } virtual ThrowCompletionOr<Value> get_this_binding(VM&) const { return Value {}; }
virtual Object* with_base_object() const { return nullptr; } virtual Object* with_base_object() const { return nullptr; }
virtual ThrowCompletionOr<bool> has_binding([[maybe_unused]] FlyString const& name, [[maybe_unused]] Optional<size_t>* out_index = nullptr) const { return false; } 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_mutable_binding(VM&, [[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 ThrowCompletionOr<void> create_immutable_binding(VM&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) { return {}; }
virtual ThrowCompletionOr<void> initialize_binding(GlobalObject&, [[maybe_unused]] FlyString const& name, Value) { return {}; } virtual ThrowCompletionOr<void> initialize_binding(VM&, [[maybe_unused]] FlyString const& name, Value) { return {}; }
virtual ThrowCompletionOr<void> set_mutable_binding(GlobalObject&, [[maybe_unused]] FlyString const& name, Value, [[maybe_unused]] bool strict) { return {}; } virtual ThrowCompletionOr<void> set_mutable_binding(VM&, [[maybe_unused]] FlyString const& name, Value, [[maybe_unused]] bool strict) { return {}; }
virtual ThrowCompletionOr<Value> get_binding_value(GlobalObject&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) { return Value {}; } virtual ThrowCompletionOr<Value> get_binding_value(VM&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) { return Value {}; }
virtual ThrowCompletionOr<bool> delete_binding(GlobalObject&, [[maybe_unused]] FlyString const& name) { return false; } virtual ThrowCompletionOr<bool> delete_binding(VM&, [[maybe_unused]] FlyString const& name) { return false; }
// [[OuterEnv]] // [[OuterEnv]]
Environment* outer_environment() { return m_outer_environment; } Environment* outer_environment() { return m_outer_environment; }

View file

@ -61,21 +61,21 @@ bool FunctionEnvironment::has_super_binding() const
} }
// 9.1.1.3.4 GetThisBinding ( ), https://tc39.es/ecma262/#sec-function-environment-records-getthisbinding // 9.1.1.3.4 GetThisBinding ( ), https://tc39.es/ecma262/#sec-function-environment-records-getthisbinding
ThrowCompletionOr<Value> FunctionEnvironment::get_this_binding(GlobalObject&) const ThrowCompletionOr<Value> FunctionEnvironment::get_this_binding(VM& vm) const
{ {
// 1. Assert: envRec.[[ThisBindingStatus]] is not lexical. // 1. Assert: envRec.[[ThisBindingStatus]] is not lexical.
VERIFY(m_this_binding_status != ThisBindingStatus::Lexical); VERIFY(m_this_binding_status != ThisBindingStatus::Lexical);
// 2. If envRec.[[ThisBindingStatus]] is uninitialized, throw a ReferenceError exception. // 2. If envRec.[[ThisBindingStatus]] is uninitialized, throw a ReferenceError exception.
if (m_this_binding_status == ThisBindingStatus::Uninitialized) if (m_this_binding_status == ThisBindingStatus::Uninitialized)
return vm().throw_completion<ReferenceError>(ErrorType::ThisHasNotBeenInitialized); return vm.throw_completion<ReferenceError>(ErrorType::ThisHasNotBeenInitialized);
// 3. Return envRec.[[ThisValue]]. // 3. Return envRec.[[ThisValue]].
return m_this_value; return m_this_value;
} }
// 9.1.1.3.1 BindThisValue ( V ), https://tc39.es/ecma262/#sec-bindthisvalue // 9.1.1.3.1 BindThisValue ( V ), https://tc39.es/ecma262/#sec-bindthisvalue
ThrowCompletionOr<Value> FunctionEnvironment::bind_this_value(GlobalObject&, Value this_value) ThrowCompletionOr<Value> FunctionEnvironment::bind_this_value(VM& vm, Value this_value)
{ {
VERIFY(!this_value.is_empty()); VERIFY(!this_value.is_empty());
@ -84,7 +84,7 @@ ThrowCompletionOr<Value> FunctionEnvironment::bind_this_value(GlobalObject&, Val
// 2. If envRec.[[ThisBindingStatus]] is initialized, throw a ReferenceError exception. // 2. If envRec.[[ThisBindingStatus]] is initialized, throw a ReferenceError exception.
if (m_this_binding_status == ThisBindingStatus::Initialized) if (m_this_binding_status == ThisBindingStatus::Initialized)
return vm().throw_completion<ReferenceError>(ErrorType::ThisIsAlreadyInitialized); return vm.throw_completion<ReferenceError>(ErrorType::ThisIsAlreadyInitialized);
// 3. Set envRec.[[ThisValue]] to V. // 3. Set envRec.[[ThisValue]] to V.
m_this_value = this_value; m_this_value = this_value;

View file

@ -43,8 +43,8 @@ public:
ThrowCompletionOr<Value> get_super_base() const; ThrowCompletionOr<Value> get_super_base() const;
bool has_super_binding() const; bool has_super_binding() const;
virtual bool has_this_binding() const override; virtual bool has_this_binding() const override;
virtual ThrowCompletionOr<Value> get_this_binding(GlobalObject&) const override; virtual ThrowCompletionOr<Value> get_this_binding(VM&) const override;
ThrowCompletionOr<Value> bind_this_value(GlobalObject&, Value); ThrowCompletionOr<Value> bind_this_value(VM&, Value);
private: private:
virtual bool is_function_environment() const override { return true; } virtual bool is_function_environment() const override { return true; }

View file

@ -32,7 +32,7 @@ void GlobalEnvironment::visit_edges(Cell::Visitor& visitor)
} }
// 9.1.1.4.11 GetThisBinding ( ), https://tc39.es/ecma262/#sec-global-environment-records-getthisbinding // 9.1.1.4.11 GetThisBinding ( ), https://tc39.es/ecma262/#sec-global-environment-records-getthisbinding
ThrowCompletionOr<Value> GlobalEnvironment::get_this_binding(GlobalObject&) const ThrowCompletionOr<Value> GlobalEnvironment::get_this_binding(VM&) const
{ {
// 1. Return envRec.[[GlobalThisValue]]. // 1. Return envRec.[[GlobalThisValue]].
return m_global_this_value; return m_global_this_value;
@ -52,83 +52,83 @@ ThrowCompletionOr<bool> GlobalEnvironment::has_binding(FlyString const& name, Op
} }
// 9.1.1.4.2 CreateMutableBinding ( N, D ), https://tc39.es/ecma262/#sec-global-environment-records-createmutablebinding-n-d // 9.1.1.4.2 CreateMutableBinding ( N, D ), https://tc39.es/ecma262/#sec-global-environment-records-createmutablebinding-n-d
ThrowCompletionOr<void> GlobalEnvironment::create_mutable_binding(GlobalObject& global_object, FlyString const& name, bool can_be_deleted) ThrowCompletionOr<void> GlobalEnvironment::create_mutable_binding(VM& vm, FlyString const& name, bool can_be_deleted)
{ {
// 1. Let DclRec be envRec.[[DeclarativeRecord]]. // 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, throw a TypeError exception. // 2. If ! DclRec.HasBinding(N) is true, throw a TypeError exception.
if (MUST(m_declarative_record->has_binding(name))) if (MUST(m_declarative_record->has_binding(name)))
return vm().throw_completion<TypeError>(ErrorType::GlobalEnvironmentAlreadyHasBinding, name); return vm.throw_completion<TypeError>(ErrorType::GlobalEnvironmentAlreadyHasBinding, name);
// 3. Return ! DclRec.CreateMutableBinding(N, D). // 3. Return ! DclRec.CreateMutableBinding(N, D).
return MUST(m_declarative_record->create_mutable_binding(global_object, name, can_be_deleted)); return MUST(m_declarative_record->create_mutable_binding(vm, name, can_be_deleted));
} }
// 9.1.1.4.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-global-environment-records-createimmutablebinding-n-s // 9.1.1.4.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-global-environment-records-createimmutablebinding-n-s
ThrowCompletionOr<void> GlobalEnvironment::create_immutable_binding(GlobalObject& global_object, FlyString const& name, bool strict) ThrowCompletionOr<void> GlobalEnvironment::create_immutable_binding(VM& vm, FlyString const& name, bool strict)
{ {
// 1. Let DclRec be envRec.[[DeclarativeRecord]]. // 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, throw a TypeError exception. // 2. If ! DclRec.HasBinding(N) is true, throw a TypeError exception.
if (MUST(m_declarative_record->has_binding(name))) if (MUST(m_declarative_record->has_binding(name)))
return vm().throw_completion<TypeError>(ErrorType::GlobalEnvironmentAlreadyHasBinding, name); return vm.throw_completion<TypeError>(ErrorType::GlobalEnvironmentAlreadyHasBinding, name);
// 3. Return ! DclRec.CreateImmutableBinding(N, S). // 3. Return ! DclRec.CreateImmutableBinding(N, S).
return MUST(m_declarative_record->create_immutable_binding(global_object, name, strict)); 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 // 9.1.1.4.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-global-environment-records-initializebinding-n-v
ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(GlobalObject& global_object, FlyString const& name, Value value) ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(VM& vm, FlyString const& name, Value value)
{ {
// 1. Let DclRec be envRec.[[DeclarativeRecord]]. // 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, then // 2. If ! DclRec.HasBinding(N) is true, then
if (MUST(m_declarative_record->has_binding(name))) { if (MUST(m_declarative_record->has_binding(name))) {
// a. Return ! DclRec.InitializeBinding(N, V). // a. Return ! DclRec.InitializeBinding(N, V).
return MUST(m_declarative_record->initialize_binding(global_object, name, value)); return MUST(m_declarative_record->initialize_binding(vm, name, value));
} }
// 3. Assert: If the binding exists, it must be in the object Environment Record. // 3. Assert: If the binding exists, it must be in the object Environment Record.
// 4. Let ObjRec be envRec.[[ObjectRecord]]. // 4. Let ObjRec be envRec.[[ObjectRecord]].
// 5. Return ? ObjRec.InitializeBinding(N, V). // 5. Return ? ObjRec.InitializeBinding(N, V).
return m_object_record->initialize_binding(global_object, name, value); return m_object_record->initialize_binding(vm, name, value);
} }
// 9.1.1.4.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-global-environment-records-setmutablebinding-n-v-s // 9.1.1.4.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-global-environment-records-setmutablebinding-n-v-s
ThrowCompletionOr<void> GlobalEnvironment::set_mutable_binding(GlobalObject& global_object, FlyString const& name, Value value, bool strict) ThrowCompletionOr<void> GlobalEnvironment::set_mutable_binding(VM& vm, FlyString const& name, Value value, bool strict)
{ {
// 1. Let DclRec be envRec.[[DeclarativeRecord]]. // 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, then // 2. If ! DclRec.HasBinding(N) is true, then
if (MUST(m_declarative_record->has_binding(name))) { if (MUST(m_declarative_record->has_binding(name))) {
// a. Return ? DclRec.SetMutableBinding(N, V, S). // a. Return ? DclRec.SetMutableBinding(N, V, S).
return m_declarative_record->set_mutable_binding(global_object, name, value, strict); return m_declarative_record->set_mutable_binding(vm, name, value, strict);
} }
// 3. Let ObjRec be envRec.[[ObjectRecord]]. // 3. Let ObjRec be envRec.[[ObjectRecord]].
// 4. Return ? ObjRec.SetMutableBinding(N, V, S). // 4. Return ? ObjRec.SetMutableBinding(N, V, S).
return m_object_record->set_mutable_binding(global_object, name, value, strict); return m_object_record->set_mutable_binding(vm, name, value, strict);
} }
// 9.1.1.4.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-global-environment-records-getbindingvalue-n-s // 9.1.1.4.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-global-environment-records-getbindingvalue-n-s
ThrowCompletionOr<Value> GlobalEnvironment::get_binding_value(GlobalObject& global_object, FlyString const& name, bool strict) ThrowCompletionOr<Value> GlobalEnvironment::get_binding_value(VM& vm, FlyString const& name, bool strict)
{ {
// 1. Let DclRec be envRec.[[DeclarativeRecord]]. // 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, then // 2. If ! DclRec.HasBinding(N) is true, then
if (MUST(m_declarative_record->has_binding(name))) { if (MUST(m_declarative_record->has_binding(name))) {
// a. Return ? DclRec.GetBindingValue(N, S). // a. Return ? DclRec.GetBindingValue(N, S).
return m_declarative_record->get_binding_value(global_object, name, strict); return m_declarative_record->get_binding_value(vm, name, strict);
} }
// 3. Let ObjRec be envRec.[[ObjectRecord]]. // 3. Let ObjRec be envRec.[[ObjectRecord]].
// 4. Return ? ObjRec.GetBindingValue(N, S). // 4. Return ? ObjRec.GetBindingValue(N, S).
return m_object_record->get_binding_value(global_object, name, strict); return m_object_record->get_binding_value(vm, name, strict);
} }
// 9.1.1.4.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-global-environment-records-deletebinding-n // 9.1.1.4.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-global-environment-records-deletebinding-n
ThrowCompletionOr<bool> GlobalEnvironment::delete_binding(GlobalObject& global_object, FlyString const& name) ThrowCompletionOr<bool> GlobalEnvironment::delete_binding(VM& vm, FlyString const& name)
{ {
// 1. Let DclRec be envRec.[[DeclarativeRecord]]. // 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, then // 2. If ! DclRec.HasBinding(N) is true, then
if (MUST(m_declarative_record->has_binding(name))) { if (MUST(m_declarative_record->has_binding(name))) {
// a. Return ! DclRec.DeleteBinding(N). // a. Return ! DclRec.DeleteBinding(N).
return MUST(m_declarative_record->delete_binding(global_object, name)); return MUST(m_declarative_record->delete_binding(vm, name));
} }
// 3. Let ObjRec be envRec.[[ObjectRecord]]. // 3. Let ObjRec be envRec.[[ObjectRecord]].
@ -140,7 +140,7 @@ ThrowCompletionOr<bool> GlobalEnvironment::delete_binding(GlobalObject& global_o
// 6. If existingProp is true, then // 6. If existingProp is true, then
if (existing_prop) { if (existing_prop) {
// a. Let status be ? ObjRec.DeleteBinding(N). // a. Let status be ? ObjRec.DeleteBinding(N).
bool status = TRY(m_object_record->delete_binding(global_object, name)); bool status = TRY(m_object_record->delete_binding(vm, name));
// b. If status is true, then // b. If status is true, then
if (status) { if (status) {
@ -243,6 +243,8 @@ ThrowCompletionOr<bool> GlobalEnvironment::can_declare_global_function(FlyString
// 9.1.1.4.17 CreateGlobalVarBinding ( N, D ), https://tc39.es/ecma262/#sec-createglobalvarbinding // 9.1.1.4.17 CreateGlobalVarBinding ( N, D ), https://tc39.es/ecma262/#sec-createglobalvarbinding
ThrowCompletionOr<void> GlobalEnvironment::create_global_var_binding(FlyString const& name, bool can_be_deleted) ThrowCompletionOr<void> GlobalEnvironment::create_global_var_binding(FlyString const& name, bool can_be_deleted)
{ {
auto& vm = this->vm();
// 1. Let ObjRec be envRec.[[ObjectRecord]]. // 1. Let ObjRec be envRec.[[ObjectRecord]].
// 2. Let globalObject be ObjRec.[[BindingObject]]. // 2. Let globalObject be ObjRec.[[BindingObject]].
auto& global_object = verify_cast<GlobalObject>(m_object_record->binding_object()); auto& global_object = verify_cast<GlobalObject>(m_object_record->binding_object());
@ -256,10 +258,10 @@ ThrowCompletionOr<void> GlobalEnvironment::create_global_var_binding(FlyString c
// 5. If hasProperty is false and extensible is true, then // 5. If hasProperty is false and extensible is true, then
if (!has_property && extensible) { if (!has_property && extensible) {
// a. Perform ? ObjRec.CreateMutableBinding(N, D). // a. Perform ? ObjRec.CreateMutableBinding(N, D).
TRY(m_object_record->create_mutable_binding(global_object, name, can_be_deleted)); TRY(m_object_record->create_mutable_binding(vm, name, can_be_deleted));
// b. Perform ? ObjRec.InitializeBinding(N, undefined). // b. Perform ? ObjRec.InitializeBinding(N, undefined).
TRY(m_object_record->initialize_binding(global_object, name, js_undefined())); TRY(m_object_record->initialize_binding(vm, name, js_undefined()));
} }
// 6. Let varDeclaredNames be envRec.[[VarNames]]. // 6. Let varDeclaredNames be envRec.[[VarNames]].

View file

@ -17,15 +17,15 @@ public:
GlobalEnvironment(GlobalObject&, Object& this_value); GlobalEnvironment(GlobalObject&, Object& this_value);
virtual bool has_this_binding() const final { return true; } virtual bool has_this_binding() const final { return true; }
virtual ThrowCompletionOr<Value> get_this_binding(GlobalObject&) const final; virtual ThrowCompletionOr<Value> get_this_binding(VM&) const final;
virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override; 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_mutable_binding(VM&, FlyString const& name, bool can_be_deleted) override;
virtual ThrowCompletionOr<void> create_immutable_binding(GlobalObject&, FlyString const& name, bool strict) override; virtual ThrowCompletionOr<void> create_immutable_binding(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<void> initialize_binding(GlobalObject&, FlyString const& name, Value) override; virtual ThrowCompletionOr<void> initialize_binding(VM&, FlyString const& name, Value) override;
virtual ThrowCompletionOr<void> set_mutable_binding(GlobalObject&, FlyString const& name, Value, bool strict) override; virtual ThrowCompletionOr<void> set_mutable_binding(VM&, FlyString const& name, Value, bool strict) override;
virtual ThrowCompletionOr<Value> get_binding_value(GlobalObject&, FlyString const& name, bool strict) override; virtual ThrowCompletionOr<Value> get_binding_value(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(GlobalObject&, FlyString const& name) override; virtual ThrowCompletionOr<bool> delete_binding(VM&, FlyString const& name) override;
ObjectEnvironment& object_record() { return *m_object_record; } ObjectEnvironment& object_record() { return *m_object_record; }
Object& global_this_value() { return *m_global_this_value; } Object& global_this_value() { return *m_global_this_value; }

View file

@ -18,7 +18,7 @@ ModuleEnvironment::ModuleEnvironment(Environment* outer_environment)
} }
// 9.1.1.5.1 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-module-environment-records-getbindingvalue-n-s // 9.1.1.5.1 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-module-environment-records-getbindingvalue-n-s
ThrowCompletionOr<Value> ModuleEnvironment::get_binding_value(GlobalObject& global_object, FlyString const& name, bool strict) ThrowCompletionOr<Value> ModuleEnvironment::get_binding_value(VM& vm, FlyString const& name, bool strict)
{ {
// 1. Assert: S is true. // 1. Assert: S is true.
VERIFY(strict); VERIFY(strict);
@ -36,16 +36,16 @@ ThrowCompletionOr<Value> ModuleEnvironment::get_binding_value(GlobalObject& glob
// c. If targetEnv is empty, throw a ReferenceError exception. // c. If targetEnv is empty, throw a ReferenceError exception.
if (!target_env) if (!target_env)
return vm().throw_completion<ReferenceError>(ErrorType::ModuleNoEnvironment); return vm.throw_completion<ReferenceError>(ErrorType::ModuleNoEnvironment);
// d. Return ? targetEnv.GetBindingValue(N2, true). // d. Return ? targetEnv.GetBindingValue(N2, true).
return target_env->get_binding_value(global_object, indirect_binding->binding_name, true); return target_env->get_binding_value(vm, indirect_binding->binding_name, true);
} }
// 4. If the binding for N in envRec is an uninitialized binding, throw a ReferenceError exception. // 4. If the binding for N in envRec is an uninitialized binding, throw a ReferenceError exception.
// 5. Return the value currently bound to N in envRec. // 5. Return the value currently bound to N in envRec.
// Note: Step 4 & 5 are the steps performed by declarative environment GetBindingValue // Note: Step 4 & 5 are the steps performed by declarative environment GetBindingValue
return DeclarativeEnvironment::get_binding_value(global_object, name, strict); return DeclarativeEnvironment::get_binding_value(vm, name, strict);
} }
// Not defined in the spec, see comment in the header. // Not defined in the spec, see comment in the header.
@ -60,14 +60,14 @@ ThrowCompletionOr<bool> ModuleEnvironment::has_binding(FlyString const& name, Op
} }
// 9.1.1.5.2 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-module-environment-records-deletebinding-n // 9.1.1.5.2 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-module-environment-records-deletebinding-n
ThrowCompletionOr<bool> ModuleEnvironment::delete_binding(GlobalObject&, FlyString const&) ThrowCompletionOr<bool> ModuleEnvironment::delete_binding(VM&, FlyString const&)
{ {
// The DeleteBinding concrete method of a module Environment Record is never used within this specification. // The DeleteBinding concrete method of a module Environment Record is never used within this specification.
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
// 9.1.1.5.4 GetThisBinding ( ), https://tc39.es/ecma262/#sec-module-environment-records-getthisbinding // 9.1.1.5.4 GetThisBinding ( ), https://tc39.es/ecma262/#sec-module-environment-records-getthisbinding
ThrowCompletionOr<Value> ModuleEnvironment::get_this_binding(GlobalObject&) const ThrowCompletionOr<Value> ModuleEnvironment::get_this_binding(VM&) const
{ {
// 1. Return undefined. // 1. Return undefined.
return js_undefined(); return js_undefined();

View file

@ -23,10 +23,10 @@ public:
// in Table 18 and share the same specifications for all of those methods except for // in Table 18 and share the same specifications for all of those methods except for
// GetBindingValue, DeleteBinding, HasThisBinding and GetThisBinding. // GetBindingValue, DeleteBinding, HasThisBinding and GetThisBinding.
// In addition, module Environment Records support the methods listed in Table 24. // In addition, module Environment Records support the methods listed in Table 24.
virtual ThrowCompletionOr<Value> get_binding_value(GlobalObject&, FlyString const& name, bool strict) override; virtual ThrowCompletionOr<Value> get_binding_value(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(GlobalObject&, FlyString const& name) override; virtual ThrowCompletionOr<bool> delete_binding(VM&, FlyString const& name) override;
virtual bool has_this_binding() const final { return true; } virtual bool has_this_binding() const final { return true; }
virtual ThrowCompletionOr<Value> get_this_binding(GlobalObject&) const final; virtual ThrowCompletionOr<Value> get_this_binding(VM&) const final;
ThrowCompletionOr<void> create_import_binding(FlyString name, Module* module, FlyString binding_name); ThrowCompletionOr<void> create_import_binding(FlyString name, Module* module, FlyString binding_name);
// Note: Although the spec does not explicitly say this we also have to implement HasBinding as // Note: Although the spec does not explicitly say this we also have to implement HasBinding as

View file

@ -136,6 +136,8 @@ ThrowCompletionOr<bool> ModuleNamespaceObject::internal_has_property(PropertyKey
// 10.4.6.8 [[Get]] ( P, Receiver ), https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-get-p-receiver // 10.4.6.8 [[Get]] ( P, Receiver ), https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-get-p-receiver
ThrowCompletionOr<Value> ModuleNamespaceObject::internal_get(PropertyKey const& property_key, Value receiver) const ThrowCompletionOr<Value> ModuleNamespaceObject::internal_get(PropertyKey const& property_key, Value receiver) const
{ {
auto& vm = this->vm();
// 1. If Type(P) is Symbol, then // 1. If Type(P) is Symbol, then
if (property_key.is_symbol()) { if (property_key.is_symbol()) {
// a. Return ! OrdinaryGet(O, P, Receiver). // a. Return ! OrdinaryGet(O, P, Receiver).
@ -150,7 +152,7 @@ ThrowCompletionOr<Value> ModuleNamespaceObject::internal_get(PropertyKey const&
// 4. Let m be O.[[Module]]. // 4. Let m be O.[[Module]].
// 5. Let binding be ! m.ResolveExport(P). // 5. Let binding be ! m.ResolveExport(P).
auto binding = MUST(m_module->resolve_export(vm(), property_key.to_string())); auto binding = MUST(m_module->resolve_export(vm, property_key.to_string()));
// 6. Assert: binding is a ResolvedBinding Record. // 6. Assert: binding is a ResolvedBinding Record.
VERIFY(binding.is_valid()); VERIFY(binding.is_valid());
@ -164,7 +166,7 @@ ThrowCompletionOr<Value> ModuleNamespaceObject::internal_get(PropertyKey const&
// 9. If binding.[[BindingName]] is namespace, then // 9. If binding.[[BindingName]] is namespace, then
if (binding.is_namespace()) { if (binding.is_namespace()) {
// a. Return ? GetModuleNamespace(targetModule). // a. Return ? GetModuleNamespace(targetModule).
return TRY(target_module->get_module_namespace(vm())); return TRY(target_module->get_module_namespace(vm));
} }
// 10. Let targetEnv be targetModule.[[Environment]]. // 10. Let targetEnv be targetModule.[[Environment]].
@ -172,10 +174,10 @@ ThrowCompletionOr<Value> ModuleNamespaceObject::internal_get(PropertyKey const&
// 11. If targetEnv is empty, throw a ReferenceError exception. // 11. If targetEnv is empty, throw a ReferenceError exception.
if (!target_environment) if (!target_environment)
return vm().throw_completion<ReferenceError>(ErrorType::ModuleNoEnvironment); return vm.throw_completion<ReferenceError>(ErrorType::ModuleNoEnvironment);
// 12. Return ? targetEnv.GetBindingValue(binding.[[BindingName]], true). // 12. Return ? targetEnv.GetBindingValue(binding.[[BindingName]], true).
return target_environment->get_binding_value(global_object(), binding.export_name, true); return target_environment->get_binding_value(vm, binding.export_name, true);
} }
// 10.4.6.9 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-set-p-v-receiver // 10.4.6.9 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-set-p-v-receiver

View file

@ -60,7 +60,7 @@ ThrowCompletionOr<bool> ObjectEnvironment::has_binding(FlyString const& name, Op
} }
// 9.1.1.2.2 CreateMutableBinding ( N, D ), https://tc39.es/ecma262/#sec-object-environment-records-createmutablebinding-n-d // 9.1.1.2.2 CreateMutableBinding ( N, D ), https://tc39.es/ecma262/#sec-object-environment-records-createmutablebinding-n-d
ThrowCompletionOr<void> ObjectEnvironment::create_mutable_binding(GlobalObject&, FlyString const& name, bool can_be_deleted) ThrowCompletionOr<void> ObjectEnvironment::create_mutable_binding(VM&, FlyString const& name, bool can_be_deleted)
{ {
// 1. Let bindingObject be envRec.[[BindingObject]]. // 1. Let bindingObject be envRec.[[BindingObject]].
// 2. Perform ? DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }). // 2. Perform ? DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }).
@ -71,24 +71,24 @@ ThrowCompletionOr<void> ObjectEnvironment::create_mutable_binding(GlobalObject&,
} }
// 9.1.1.2.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-object-environment-records-createimmutablebinding-n-s // 9.1.1.2.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-object-environment-records-createimmutablebinding-n-s
ThrowCompletionOr<void> ObjectEnvironment::create_immutable_binding(GlobalObject&, FlyString const&, bool) ThrowCompletionOr<void> ObjectEnvironment::create_immutable_binding(VM&, FlyString const&, bool)
{ {
// "The CreateImmutableBinding concrete method of an object Environment Record is never used within this specification." // "The CreateImmutableBinding concrete method of an object Environment Record is never used within this specification."
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
// 9.1.1.2.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-object-environment-records-initializebinding-n-v // 9.1.1.2.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-object-environment-records-initializebinding-n-v
ThrowCompletionOr<void> ObjectEnvironment::initialize_binding(GlobalObject& global_object, FlyString const& name, Value value) ThrowCompletionOr<void> ObjectEnvironment::initialize_binding(VM& vm, FlyString const& name, Value value)
{ {
// 1. Perform ? envRec.SetMutableBinding(N, V, false). // 1. Perform ? envRec.SetMutableBinding(N, V, false).
TRY(set_mutable_binding(global_object, name, value, false)); TRY(set_mutable_binding(vm, name, value, false));
// 2. Return unused. // 2. Return unused.
return {}; return {};
} }
// 9.1.1.2.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-object-environment-records-setmutablebinding-n-v-s // 9.1.1.2.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-object-environment-records-setmutablebinding-n-v-s
ThrowCompletionOr<void> ObjectEnvironment::set_mutable_binding(GlobalObject&, FlyString const& name, Value value, bool strict) ThrowCompletionOr<void> ObjectEnvironment::set_mutable_binding(VM&, FlyString const& name, Value value, bool strict)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
@ -123,7 +123,7 @@ ThrowCompletionOr<void> ObjectEnvironment::set_mutable_binding(GlobalObject&, Fl
} }
// 9.1.1.2.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-object-environment-records-getbindingvalue-n-s // 9.1.1.2.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-object-environment-records-getbindingvalue-n-s
ThrowCompletionOr<Value> ObjectEnvironment::get_binding_value(GlobalObject&, FlyString const& name, bool strict) ThrowCompletionOr<Value> ObjectEnvironment::get_binding_value(VM&, FlyString const& name, bool strict)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
@ -144,7 +144,7 @@ ThrowCompletionOr<Value> ObjectEnvironment::get_binding_value(GlobalObject&, Fly
} }
// 9.1.1.2.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-object-environment-records-deletebinding-n // 9.1.1.2.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-object-environment-records-deletebinding-n
ThrowCompletionOr<bool> ObjectEnvironment::delete_binding(GlobalObject&, FlyString const& name) ThrowCompletionOr<bool> ObjectEnvironment::delete_binding(VM&, FlyString const& name)
{ {
// 1. Let bindingObject be envRec.[[BindingObject]]. // 1. Let bindingObject be envRec.[[BindingObject]].
// 2. Return ? bindingObject.[[Delete]](N). // 2. Return ? bindingObject.[[Delete]](N).

View file

@ -21,12 +21,12 @@ public:
ObjectEnvironment(Object& binding_object, IsWithEnvironment, Environment* outer_environment); ObjectEnvironment(Object& binding_object, IsWithEnvironment, Environment* outer_environment);
virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override; 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_mutable_binding(VM&, FlyString const& name, bool can_be_deleted) override;
virtual ThrowCompletionOr<void> create_immutable_binding(GlobalObject&, FlyString const& name, bool strict) override; virtual ThrowCompletionOr<void> create_immutable_binding(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<void> initialize_binding(GlobalObject&, FlyString const& name, Value) override; virtual ThrowCompletionOr<void> initialize_binding(VM&, FlyString const& name, Value) override;
virtual ThrowCompletionOr<void> set_mutable_binding(GlobalObject&, FlyString const& name, Value, bool strict) override; virtual ThrowCompletionOr<void> set_mutable_binding(VM&, FlyString const& name, Value, bool strict) override;
virtual ThrowCompletionOr<Value> get_binding_value(GlobalObject&, FlyString const& name, bool strict) override; virtual ThrowCompletionOr<Value> get_binding_value(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(GlobalObject&, FlyString const& name) override; virtual ThrowCompletionOr<bool> delete_binding(VM&, FlyString const& name) override;
// 9.1.1.2.10 WithBaseObject ( ), https://tc39.es/ecma262/#sec-object-environment-records-withbaseobject // 9.1.1.2.10 WithBaseObject ( ), https://tc39.es/ecma262/#sec-object-environment-records-withbaseobject
virtual Object* with_base_object() const override virtual Object* with_base_object() const override

View file

@ -69,9 +69,9 @@ ThrowCompletionOr<void> Reference::put_value(GlobalObject& global_object, Value
// c. Return ? base.SetMutableBinding(V.[[ReferencedName]], W, V.[[Strict]]) (see 9.1). // c. Return ? base.SetMutableBinding(V.[[ReferencedName]], W, V.[[Strict]]) (see 9.1).
if (m_environment_coordinate.has_value()) if (m_environment_coordinate.has_value())
return static_cast<DeclarativeEnvironment*>(m_base_environment)->set_mutable_binding_direct(global_object, m_environment_coordinate->index, value, m_strict); return static_cast<DeclarativeEnvironment*>(m_base_environment)->set_mutable_binding_direct(vm, m_environment_coordinate->index, value, m_strict);
else else
return m_base_environment->set_mutable_binding(global_object, m_name.as_string(), value, m_strict); return m_base_environment->set_mutable_binding(vm, m_name.as_string(), value, m_strict);
} }
Completion Reference::throw_reference_error(GlobalObject& global_object) const Completion Reference::throw_reference_error(GlobalObject& global_object) const
@ -140,8 +140,8 @@ ThrowCompletionOr<Value> Reference::get_value(GlobalObject& global_object) const
// c. Return ? base.GetBindingValue(V.[[ReferencedName]], V.[[Strict]]) (see 9.1). // c. Return ? base.GetBindingValue(V.[[ReferencedName]], V.[[Strict]]) (see 9.1).
if (m_environment_coordinate.has_value()) if (m_environment_coordinate.has_value())
return static_cast<DeclarativeEnvironment*>(m_base_environment)->get_binding_value_direct(global_object, m_environment_coordinate->index, m_strict); return static_cast<DeclarativeEnvironment*>(m_base_environment)->get_binding_value_direct(vm, m_environment_coordinate->index, m_strict);
return m_base_environment->get_binding_value(global_object, m_name.as_string(), m_strict); return m_base_environment->get_binding_value(vm, m_name.as_string(), m_strict);
} }
// 13.5.1.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation // 13.5.1.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation
@ -195,7 +195,7 @@ ThrowCompletionOr<bool> Reference::delete_(GlobalObject& global_object)
VERIFY(m_base_type == BaseType::Environment); VERIFY(m_base_type == BaseType::Environment);
// c. Return ? base.DeleteBinding(ref.[[ReferencedName]]). // c. Return ? base.DeleteBinding(ref.[[ReferencedName]]).
return m_base_environment->delete_binding(global_object, m_name.as_string()); return m_base_environment->delete_binding(vm, m_name.as_string());
} }
String Reference::to_string() const String Reference::to_string() const
@ -234,6 +234,16 @@ String Reference::to_string() const
return builder.to_string(); return builder.to_string();
} }
// 6.2.4.8 InitializeReferencedBinding ( V, W ), https://tc39.es/ecma262/#sec-object.prototype.hasownproperty
ThrowCompletionOr<void> Reference::initialize_referenced_binding(GlobalObject& global_object, Value value) const
{
auto& vm = global_object.vm();
VERIFY(!is_unresolvable());
VERIFY(m_base_type == BaseType::Environment);
return m_base_environment->initialize_binding(vm, m_name.as_string(), value);
}
// 6.2.4.9 MakePrivateReference ( baseValue, privateIdentifier ), https://tc39.es/ecma262/#sec-makeprivatereference // 6.2.4.9 MakePrivateReference ( baseValue, privateIdentifier ), https://tc39.es/ecma262/#sec-makeprivatereference
Reference make_private_reference(VM& vm, Value base_value, FlyString const& private_identifier) Reference make_private_reference(VM& vm, Value base_value, FlyString const& private_identifier)
{ {

View file

@ -121,13 +121,7 @@ public:
return m_base_type == BaseType::Environment; return m_base_type == BaseType::Environment;
} }
// 6.2.4.8 InitializeReferencedBinding ( V, W ), https://tc39.es/ecma262/#sec-object.prototype.hasownproperty ThrowCompletionOr<void> initialize_referenced_binding(GlobalObject& global_object, Value value) const;
ThrowCompletionOr<void> initialize_referenced_binding(GlobalObject& global_object, Value value) const
{
VERIFY(!is_unresolvable());
VERIFY(m_base_type == BaseType::Environment);
return m_base_environment->initialize_binding(global_object, m_name.as_string(), value);
}
ThrowCompletionOr<void> put_value(GlobalObject&, Value); ThrowCompletionOr<void> put_value(GlobalObject&, Value);
ThrowCompletionOr<Value> get_value(GlobalObject&) const; ThrowCompletionOr<Value> get_value(GlobalObject&) const;

View file

@ -606,12 +606,15 @@ ThrowCompletionOr<void> VM::initialize_instance_elements(Object& object, ECMAScr
} }
// 9.4.4 ResolveThisBinding ( ), https://tc39.es/ecma262/#sec-resolvethisbinding // 9.4.4 ResolveThisBinding ( ), https://tc39.es/ecma262/#sec-resolvethisbinding
ThrowCompletionOr<Value> VM::resolve_this_binding(GlobalObject& global_object) ThrowCompletionOr<Value> VM::resolve_this_binding()
{ {
auto& vm = *this;
// 1. Let envRec be GetThisEnvironment(). // 1. Let envRec be GetThisEnvironment().
auto& environment = get_this_environment(*this); auto& environment = get_this_environment(vm);
// 2. Return ? envRec.GetThisBinding(). // 2. Return ? envRec.GetThisBinding().
return TRY(environment.get_this_binding(global_object)); return TRY(environment.get_this_binding(vm));
} }
String VM::join_arguments(size_t start_index) const String VM::join_arguments(size_t start_index) const

View file

@ -153,7 +153,7 @@ public:
return running_execution_context().this_value; return running_execution_context().this_value;
} }
ThrowCompletionOr<Value> resolve_this_binding(GlobalObject&); ThrowCompletionOr<Value> resolve_this_binding();
StackInfo const& stack_info() const { return m_stack_info; }; StackInfo const& stack_info() const { return m_stack_info; };

View file

@ -325,8 +325,6 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
// 4. Assert: realm is not undefined. // 4. Assert: realm is not undefined.
// Note: This must be true because we use a reference. // Note: This must be true because we use a reference.
auto& global_object = realm().global_object();
// 5. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]). // 5. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
auto* environment = vm.heap().allocate_without_realm<ModuleEnvironment>(&realm().global_environment()); auto* environment = vm.heap().allocate_without_realm<ModuleEnvironment>(&realm().global_environment());
@ -345,10 +343,10 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
auto* namespace_ = TRY(imported_module->get_module_namespace(vm)); auto* namespace_ = TRY(imported_module->get_module_namespace(vm));
// ii. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true). // ii. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
MUST(environment->create_immutable_binding(global_object, import_entry.local_name, true)); MUST(environment->create_immutable_binding(vm, import_entry.local_name, true));
// iii. Perform ! env.InitializeBinding(in.[[LocalName]], namespace). // iii. Perform ! env.InitializeBinding(in.[[LocalName]], namespace).
MUST(environment->initialize_binding(global_object, import_entry.local_name, namespace_)); MUST(environment->initialize_binding(vm, import_entry.local_name, namespace_));
} }
// d. Else, // d. Else,
else { else {
@ -365,10 +363,10 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
auto* namespace_ = TRY(resolution.module->get_module_namespace(vm)); auto* namespace_ = TRY(resolution.module->get_module_namespace(vm));
// 2. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true). // 2. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
MUST(environment->create_immutable_binding(global_object, import_entry.local_name, true)); MUST(environment->create_immutable_binding(vm, import_entry.local_name, true));
// 3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace). // 3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace).
MUST(environment->initialize_binding(global_object, import_entry.local_name, namespace_)); MUST(environment->initialize_binding(vm, import_entry.local_name, namespace_));
} }
// iv. Else, // iv. Else,
else { else {
@ -420,10 +418,10 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
// i. If dn is not an element of declaredVarNames, then // i. If dn is not an element of declaredVarNames, then
if (!declared_var_names.contains_slow(name)) { if (!declared_var_names.contains_slow(name)) {
// 1. Perform ! env.CreateMutableBinding(dn, false). // 1. Perform ! env.CreateMutableBinding(dn, false).
MUST(environment->create_mutable_binding(global_object, name, false)); MUST(environment->create_mutable_binding(vm, name, false));
// 2. Perform ! env.InitializeBinding(dn, undefined). // 2. Perform ! env.InitializeBinding(dn, undefined).
MUST(environment->initialize_binding(global_object, name, js_undefined())); MUST(environment->initialize_binding(vm, name, js_undefined()));
// 3. Append dn to declaredVarNames. // 3. Append dn to declaredVarNames.
declared_var_names.empend(name); declared_var_names.empend(name);
@ -443,12 +441,12 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
// i. If IsConstantDeclaration of d is true, then // i. If IsConstantDeclaration of d is true, then
if (declaration.is_constant_declaration()) { if (declaration.is_constant_declaration()) {
// 1. Perform ! env.CreateImmutableBinding(dn, true). // 1. Perform ! env.CreateImmutableBinding(dn, true).
MUST(environment->create_immutable_binding(global_object, name, true)); MUST(environment->create_immutable_binding(vm, name, true));
} }
// ii. Else, // ii. Else,
else { else {
// 1. Perform ! env.CreateMutableBinding(dn, false). // 1. Perform ! env.CreateMutableBinding(dn, false).
MUST(environment->create_mutable_binding(global_object, name, false)); MUST(environment->create_mutable_binding(vm, name, false));
} }
// iii. If d is a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then // iii. If d is a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
@ -460,7 +458,7 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
auto* function = ECMAScriptFunctionObject::create(realm(), function_declaration.name(), function_declaration.source_text(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), environment, private_environment, function_declaration.kind(), function_declaration.is_strict_mode(), function_declaration.might_need_arguments_object(), function_declaration.contains_direct_call_to_eval()); auto* function = ECMAScriptFunctionObject::create(realm(), function_declaration.name(), function_declaration.source_text(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), environment, private_environment, function_declaration.kind(), function_declaration.is_strict_mode(), function_declaration.might_need_arguments_object(), function_declaration.contains_direct_call_to_eval());
// 2. Perform ! env.InitializeBinding(dn, fo). // 2. Perform ! env.InitializeBinding(dn, fo).
MUST(environment->initialize_binding(global_object, name, function)); MUST(environment->initialize_binding(vm, name, function));
} }
}); });
}); });
@ -479,7 +477,7 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] Adding default export to lexical declarations: local name: {}, Expression: {}", name, statement.class_name()); dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] Adding default export to lexical declarations: local name: {}, Expression: {}", name, statement.class_name());
// 1. Perform ! env.CreateMutableBinding(dn, false). // 1. Perform ! env.CreateMutableBinding(dn, false).
MUST(environment->create_mutable_binding(global_object, name, false)); MUST(environment->create_mutable_binding(vm, name, false));
// Note: Since this is not a function declaration 24.a.iii never applies // Note: Since this is not a function declaration 24.a.iii never applies
} }

View file

@ -50,8 +50,6 @@ ThrowCompletionOr<void> SyntheticModule::link(VM& vm)
// 2. Assert: realm is not undefined. // 2. Assert: realm is not undefined.
// Note: This must be true because we use a reference. // Note: This must be true because we use a reference.
auto& global_object = realm().global_object();
// 3. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]). // 3. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
auto* environment = vm.heap().allocate_without_realm<ModuleEnvironment>(&realm().global_environment()); auto* environment = vm.heap().allocate_without_realm<ModuleEnvironment>(&realm().global_environment());
@ -61,10 +59,10 @@ ThrowCompletionOr<void> SyntheticModule::link(VM& vm)
// 5. For each exportName in module.[[ExportNames]], // 5. For each exportName in module.[[ExportNames]],
for (auto& export_name : m_export_names) { for (auto& export_name : m_export_names) {
// a. Perform ! envRec.CreateMutableBinding(exportName, false). // a. Perform ! envRec.CreateMutableBinding(exportName, false).
MUST(environment->create_mutable_binding(global_object, export_name, false)); MUST(environment->create_mutable_binding(vm, export_name, false));
// b. Perform ! envRec.InitializeBinding(exportName, undefined). // b. Perform ! envRec.InitializeBinding(exportName, undefined).
MUST(environment->initialize_binding(global_object, export_name, js_undefined())); MUST(environment->initialize_binding(vm, export_name, js_undefined()));
} }
// 6. Return unused. // 6. Return unused.
@ -123,9 +121,11 @@ ThrowCompletionOr<Promise*> SyntheticModule::evaluate(VM& vm)
// 1.2.2 SetSyntheticModuleExport ( module, exportName, exportValue ), https://tc39.es/proposal-json-modules/#sec-setsyntheticmoduleexport // 1.2.2 SetSyntheticModuleExport ( module, exportName, exportValue ), https://tc39.es/proposal-json-modules/#sec-setsyntheticmoduleexport
ThrowCompletionOr<void> SyntheticModule::set_synthetic_module_export(FlyString const& export_name, Value export_value) ThrowCompletionOr<void> SyntheticModule::set_synthetic_module_export(FlyString const& export_name, Value export_value)
{ {
auto& vm = this->realm().vm();
// Note: Has some changes from PR: https://github.com/tc39/proposal-json-modules/pull/13. // Note: Has some changes from PR: https://github.com/tc39/proposal-json-modules/pull/13.
// 1. Return ? module.[[Environment]].SetMutableBinding(name, value, true). // 1. Return ? module.[[Environment]].SetMutableBinding(name, value, true).
return environment()->set_mutable_binding(realm().global_object(), export_name, export_value, true); return environment()->set_mutable_binding(vm, export_name, export_value, true);
} }
// 1.3 CreateDefaultExportSyntheticModule ( defaultExport ), https://tc39.es/proposal-json-modules/#sec-create-default-export-synthetic-module // 1.3 CreateDefaultExportSyntheticModule ( defaultExport ), https://tc39.es/proposal-json-modules/#sec-create-default-export-synthetic-module