|
@@ -28,29 +28,29 @@
|
|
|
|
|
|
namespace JS {
|
|
|
|
|
|
-ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(GlobalObject& global_object, FlyString name, String source_text, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
|
|
+ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(Realm& realm, FlyString name, String source_text, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
|
|
{
|
|
|
Object* prototype = nullptr;
|
|
|
switch (kind) {
|
|
|
case FunctionKind::Normal:
|
|
|
- prototype = global_object.function_prototype();
|
|
|
+ prototype = realm.global_object().function_prototype();
|
|
|
break;
|
|
|
case FunctionKind::Generator:
|
|
|
- prototype = global_object.generator_function_prototype();
|
|
|
+ prototype = realm.global_object().generator_function_prototype();
|
|
|
break;
|
|
|
case FunctionKind::Async:
|
|
|
- prototype = global_object.async_function_prototype();
|
|
|
+ prototype = realm.global_object().async_function_prototype();
|
|
|
break;
|
|
|
case FunctionKind::AsyncGenerator:
|
|
|
- prototype = global_object.async_generator_function_prototype();
|
|
|
+ prototype = realm.global_object().async_generator_function_prototype();
|
|
|
break;
|
|
|
}
|
|
|
- return global_object.heap().allocate<ECMAScriptFunctionObject>(global_object, move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, parent_environment, private_environment, *prototype, kind, is_strict, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(class_field_initializer_name));
|
|
|
+ return realm.heap().allocate<ECMAScriptFunctionObject>(realm.global_object(), move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, parent_environment, private_environment, *prototype, kind, is_strict, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(class_field_initializer_name));
|
|
|
}
|
|
|
|
|
|
-ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(GlobalObject& global_object, FlyString name, Object& prototype, String source_text, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
|
|
+ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(Realm& realm, FlyString name, Object& prototype, String source_text, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
|
|
{
|
|
|
- return global_object.heap().allocate<ECMAScriptFunctionObject>(global_object, move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, parent_environment, private_environment, prototype, kind, is_strict, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(class_field_initializer_name));
|
|
|
+ return realm.heap().allocate<ECMAScriptFunctionObject>(realm.global_object(), move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, parent_environment, private_environment, prototype, kind, is_strict, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(class_field_initializer_name));
|
|
|
}
|
|
|
|
|
|
ECMAScriptFunctionObject::ECMAScriptFunctionObject(FlyString name, String source_text, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> formal_parameters, i32 function_length, Environment* parent_environment, PrivateEnvironment* private_environment, Object& prototype, FunctionKind kind, bool strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
|
@@ -119,12 +119,12 @@ void ECMAScriptFunctionObject::initialize(Realm& realm)
|
|
|
break;
|
|
|
case FunctionKind::Generator:
|
|
|
// prototype is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
|
|
|
- prototype = Object::create(realm.global_object(), realm.global_object().generator_function_prototype_prototype());
|
|
|
+ prototype = Object::create(realm, realm.global_object().generator_function_prototype_prototype());
|
|
|
break;
|
|
|
case FunctionKind::Async:
|
|
|
break;
|
|
|
case FunctionKind::AsyncGenerator:
|
|
|
- prototype = Object::create(realm.global_object(), realm.global_object().async_generator_function_prototype_prototype());
|
|
|
+ prototype = Object::create(realm, realm.global_object().async_generator_function_prototype_prototype());
|
|
|
break;
|
|
|
}
|
|
|
// 27.7.4 AsyncFunction Instances, https://tc39.es/ecma262/#sec-async-function-instances
|
|
@@ -319,6 +319,8 @@ void ECMAScriptFunctionObject::make_method(Object& home_object)
|
|
|
ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantiation(Interpreter* interpreter)
|
|
|
{
|
|
|
auto& vm = this->vm();
|
|
|
+ auto& global_object = this->global_object();
|
|
|
+ auto& realm = *global_object.associated_realm();
|
|
|
|
|
|
auto& callee_context = vm.running_execution_context();
|
|
|
|
|
@@ -399,24 +401,24 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|
|
if (MUST(environment->has_binding(parameter_name)))
|
|
|
continue;
|
|
|
|
|
|
- MUST(environment->create_mutable_binding(global_object(), parameter_name, false));
|
|
|
+ MUST(environment->create_mutable_binding(global_object, parameter_name, false));
|
|
|
if (has_duplicates)
|
|
|
- MUST(environment->initialize_binding(global_object(), parameter_name, js_undefined()));
|
|
|
+ MUST(environment->initialize_binding(global_object, parameter_name, js_undefined()));
|
|
|
}
|
|
|
|
|
|
if (arguments_object_needed) {
|
|
|
Object* arguments_object;
|
|
|
if (is_strict_mode() || !has_simple_parameter_list())
|
|
|
- arguments_object = create_unmapped_arguments_object(global_object(), vm.running_execution_context().arguments);
|
|
|
+ arguments_object = create_unmapped_arguments_object(global_object, vm.running_execution_context().arguments);
|
|
|
else
|
|
|
- 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())
|
|
|
- MUST(environment->create_immutable_binding(global_object(), vm.names.arguments.as_string(), false));
|
|
|
+ MUST(environment->create_immutable_binding(global_object, vm.names.arguments.as_string(), false));
|
|
|
else
|
|
|
- MUST(environment->create_mutable_binding(global_object(), vm.names.arguments.as_string(), false));
|
|
|
+ MUST(environment->create_mutable_binding(global_object, vm.names.arguments.as_string(), false));
|
|
|
|
|
|
- MUST(environment->initialize_binding(global_object(), vm.names.arguments.as_string(), arguments_object));
|
|
|
+ MUST(environment->initialize_binding(global_object, vm.names.arguments.as_string(), arguments_object));
|
|
|
parameter_names.set(vm.names.arguments.as_string());
|
|
|
}
|
|
|
|
|
@@ -435,7 +437,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|
|
[&](auto const& param) -> ThrowCompletionOr<void> {
|
|
|
Value argument_value;
|
|
|
if (parameter.is_rest) {
|
|
|
- auto* array = MUST(Array::create(global_object(), 0));
|
|
|
+ auto* array = MUST(Array::create(realm, 0));
|
|
|
for (size_t rest_index = i; rest_index < execution_context_arguments.size(); ++rest_index)
|
|
|
array->indexed_properties().append(execution_context_arguments[rest_index]);
|
|
|
argument_value = array;
|
|
@@ -449,7 +451,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|
|
// Resulting value is in the accumulator.
|
|
|
argument_value = value_and_frame.frame->registers.at(0);
|
|
|
} else if (interpreter) {
|
|
|
- argument_value = TRY(parameter.default_value->execute(*interpreter, global_object())).release_value();
|
|
|
+ argument_value = TRY(parameter.default_value->execute(*interpreter, global_object)).release_value();
|
|
|
}
|
|
|
} else {
|
|
|
argument_value = js_undefined();
|
|
@@ -461,12 +463,12 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|
|
Reference reference = TRY(vm.resolve_binding(param, used_environment));
|
|
|
// Here the difference from hasDuplicates is important
|
|
|
if (has_duplicates)
|
|
|
- return reference.put_value(global_object(), argument_value);
|
|
|
+ return reference.put_value(global_object, argument_value);
|
|
|
else
|
|
|
- return reference.initialize_referenced_binding(global_object(), argument_value);
|
|
|
+ return reference.initialize_referenced_binding(global_object, argument_value);
|
|
|
} else if (IsSame<NonnullRefPtr<BindingPattern> const&, decltype(param)>) {
|
|
|
// Here the difference from hasDuplicates is important
|
|
|
- return vm.binding_initialization(param, argument_value, used_environment, global_object());
|
|
|
+ return vm.binding_initialization(param, argument_value, used_environment, global_object);
|
|
|
}
|
|
|
}));
|
|
|
}
|
|
@@ -481,8 +483,8 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|
|
if (scope_body) {
|
|
|
scope_body->for_each_var_declared_name([&](auto const& name) {
|
|
|
if (!parameter_names.contains(name) && instantiated_var_names.set(name) == AK::HashSetResult::InsertedNewEntry) {
|
|
|
- MUST(environment->create_mutable_binding(global_object(), name, false));
|
|
|
- MUST(environment->initialize_binding(global_object(), name, js_undefined()));
|
|
|
+ MUST(environment->create_mutable_binding(global_object, name, false));
|
|
|
+ MUST(environment->initialize_binding(global_object, name, js_undefined()));
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -495,15 +497,15 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|
|
scope_body->for_each_var_declared_name([&](auto const& name) {
|
|
|
if (instantiated_var_names.set(name) != AK::HashSetResult::InsertedNewEntry)
|
|
|
return;
|
|
|
- MUST(var_environment->create_mutable_binding(global_object(), name, false));
|
|
|
+ MUST(var_environment->create_mutable_binding(global_object, name, false));
|
|
|
|
|
|
Value initial_value;
|
|
|
if (!parameter_names.contains(name) || function_names.contains(name))
|
|
|
initial_value = js_undefined();
|
|
|
else
|
|
|
- initial_value = MUST(environment->get_binding_value(global_object(), name, false));
|
|
|
+ initial_value = MUST(environment->get_binding_value(global_object, name, false));
|
|
|
|
|
|
- MUST(var_environment->initialize_binding(global_object(), name, initial_value));
|
|
|
+ MUST(var_environment->initialize_binding(global_object, name, initial_value));
|
|
|
});
|
|
|
}
|
|
|
}
|
|
@@ -516,8 +518,8 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|
|
return;
|
|
|
// The spec says 'initializedBindings' here but that does not exist and it then adds it to 'instantiatedVarNames' so it probably means 'instantiatedVarNames'.
|
|
|
if (!instantiated_var_names.contains(function_name) && function_name != vm.names.arguments.as_string()) {
|
|
|
- MUST(var_environment->create_mutable_binding(global_object(), function_name, false));
|
|
|
- MUST(var_environment->initialize_binding(global_object(), function_name, js_undefined()));
|
|
|
+ MUST(var_environment->create_mutable_binding(global_object, function_name, false));
|
|
|
+ MUST(var_environment->initialize_binding(global_object, function_name, js_undefined()));
|
|
|
instantiated_var_names.set(function_name);
|
|
|
}
|
|
|
|
|
@@ -558,17 +560,17 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|
|
scope_body->for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
|
|
|
declaration.for_each_bound_name([&](auto const& name) {
|
|
|
if (declaration.is_constant_declaration())
|
|
|
- MUST(lex_environment->create_immutable_binding(global_object(), name, true));
|
|
|
+ MUST(lex_environment->create_immutable_binding(global_object, name, true));
|
|
|
else
|
|
|
- MUST(lex_environment->create_mutable_binding(global_object(), name, false));
|
|
|
+ MUST(lex_environment->create_mutable_binding(global_object, name, false));
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
|
|
|
auto* private_environment = callee_context.private_environment;
|
|
|
for (auto& declaration : functions_to_initialize) {
|
|
|
- auto* function = ECMAScriptFunctionObject::create(global_object(), 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));
|
|
|
+ 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));
|
|
|
}
|
|
|
|
|
|
return {};
|
|
@@ -717,14 +719,16 @@ void ECMAScriptFunctionObject::async_function_start(PromiseCapability const& pro
|
|
|
// 27.7.5.2 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext ), https://tc39.es/ecma262/#sec-asyncblockstart
|
|
|
void async_block_start(VM& vm, NonnullRefPtr<Statement> const& async_body, PromiseCapability const& promise_capability, ExecutionContext& async_context)
|
|
|
{
|
|
|
- auto& global_object = vm.current_realm()->global_object();
|
|
|
+ auto& realm = *vm.current_realm();
|
|
|
+ auto& global_object = realm.global_object();
|
|
|
+
|
|
|
// 1. Assert: promiseCapability is a PromiseCapability Record.
|
|
|
|
|
|
// 2. Let runningContext be the running execution context.
|
|
|
auto& running_context = vm.running_execution_context();
|
|
|
|
|
|
// 3. Set the code evaluation state of asyncContext such that when evaluation is resumed for that execution context the following steps will be performed:
|
|
|
- auto* execution_steps = NativeFunction::create(global_object, "", [&async_body, &promise_capability](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> {
|
|
|
+ auto* execution_steps = NativeFunction::create(realm, "", [&async_body, &promise_capability](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> {
|
|
|
// a. Let result be the result of evaluating asyncBody.
|
|
|
auto result = async_body->execute(vm.interpreter(), global_object);
|
|
|
|
|
@@ -778,10 +782,12 @@ void async_block_start(VM& vm, NonnullRefPtr<Statement> const& async_body, Promi
|
|
|
Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
|
|
{
|
|
|
auto& vm = this->vm();
|
|
|
+ auto& global_object = this->global_object();
|
|
|
+ auto& realm = *global_object.associated_realm();
|
|
|
auto* bytecode_interpreter = Bytecode::Interpreter::current();
|
|
|
|
|
|
if (m_kind == FunctionKind::AsyncGenerator)
|
|
|
- return vm.throw_completion<InternalError>(global_object(), ErrorType::NotImplemented, "Async Generator function execution");
|
|
|
+ return vm.throw_completion<InternalError>(global_object, ErrorType::NotImplemented, "Async Generator function execution");
|
|
|
|
|
|
if (bytecode_interpreter) {
|
|
|
if (!m_bytecode_executable) {
|
|
@@ -828,23 +834,23 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
|
|
if (m_kind == FunctionKind::Normal)
|
|
|
return { Completion::Type::Return, result.value_or(js_undefined()), {} };
|
|
|
|
|
|
- auto generator_object = TRY(GeneratorObject::create(global_object(), result, this, vm.running_execution_context().copy(), move(*result_and_frame.frame)));
|
|
|
+ auto generator_object = TRY(GeneratorObject::create(realm, result, this, vm.running_execution_context().copy(), move(*result_and_frame.frame)));
|
|
|
|
|
|
// NOTE: Async functions are entirely transformed to generator functions, and wrapped in a custom driver that returns a promise
|
|
|
// See AwaitExpression::generate_bytecode() for the transformation.
|
|
|
if (m_kind == FunctionKind::Async)
|
|
|
- return { Completion::Type::Return, TRY(AsyncFunctionDriverWrapper::create(global_object(), generator_object)), {} };
|
|
|
+ return { Completion::Type::Return, TRY(AsyncFunctionDriverWrapper::create(realm, generator_object)), {} };
|
|
|
|
|
|
VERIFY(m_kind == FunctionKind::Generator);
|
|
|
return { Completion::Type::Return, generator_object, {} };
|
|
|
} else {
|
|
|
if (m_kind == FunctionKind::Generator)
|
|
|
- return vm.throw_completion<InternalError>(global_object(), ErrorType::NotImplemented, "Generator function execution in AST interpreter");
|
|
|
+ return vm.throw_completion<InternalError>(global_object, ErrorType::NotImplemented, "Generator function execution in AST interpreter");
|
|
|
OwnPtr<Interpreter> local_interpreter;
|
|
|
Interpreter* ast_interpreter = vm.interpreter_if_exists();
|
|
|
|
|
|
if (!ast_interpreter) {
|
|
|
- local_interpreter = Interpreter::create_with_existing_realm(*realm());
|
|
|
+ local_interpreter = Interpreter::create_with_existing_realm(realm);
|
|
|
ast_interpreter = local_interpreter.ptr();
|
|
|
}
|
|
|
|
|
@@ -856,12 +862,12 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
|
|
TRY(function_declaration_instantiation(ast_interpreter));
|
|
|
|
|
|
// 2. Return the result of evaluating FunctionStatementList.
|
|
|
- return m_ecmascript_code->execute(*ast_interpreter, global_object());
|
|
|
+ return m_ecmascript_code->execute(*ast_interpreter, global_object);
|
|
|
}
|
|
|
// AsyncFunctionBody : FunctionBody
|
|
|
else if (m_kind == FunctionKind::Async) {
|
|
|
// 1. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
|
|
- auto promise_capability = MUST(new_promise_capability(global_object(), global_object().promise_constructor()));
|
|
|
+ auto promise_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
|
|
|
|
|
|
// 2. Let declResult be Completion(FunctionDeclarationInstantiation(functionObject, argumentsList)).
|
|
|
auto declaration_result = function_declaration_instantiation(ast_interpreter);
|
|
@@ -869,7 +875,7 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
|
|
// 3. If declResult is an abrupt completion, then
|
|
|
if (declaration_result.is_throw_completion()) {
|
|
|
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « declResult.[[Value]] »).
|
|
|
- MUST(call(global_object(), promise_capability.reject, js_undefined(), *declaration_result.throw_completion().value()));
|
|
|
+ MUST(call(global_object, promise_capability.reject, js_undefined(), *declaration_result.throw_completion().value()));
|
|
|
}
|
|
|
// 4. Else,
|
|
|
else {
|