mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 06:14:58 +00:00
LibJS: Always allocate ExecutionContext objects on the malloc heap
Instead of allocating these in a mixture of ways, we now always put them on the malloc heap, and keep an intrusive linked list of them that we can iterate for GC marking purposes.
This commit is contained in:
parent
845da3901d
commit
3dc5f467a8
38 changed files with 251 additions and 217 deletions
|
@ -23,7 +23,7 @@ Workbook::Workbook(Vector<NonnullRefPtr<Sheet>>&& sheets, GUI::Window& parent_wi
|
|||
: m_sheets(move(sheets))
|
||||
, m_vm(JS::VM::create().release_value_but_fixme_should_propagate_errors())
|
||||
, m_root_execution_context(JS::create_simple_execution_context<JS::GlobalObject>(m_vm))
|
||||
, m_main_execution_context(m_vm->heap())
|
||||
, m_main_execution_context(JS::ExecutionContext::create(m_vm->heap()))
|
||||
, m_parent_window(parent_window)
|
||||
{
|
||||
auto& realm = *m_root_execution_context->realm;
|
||||
|
@ -31,13 +31,13 @@ Workbook::Workbook(Vector<NonnullRefPtr<Sheet>>&& sheets, GUI::Window& parent_wi
|
|||
m_workbook_object = vm.heap().allocate<WorkbookObject>(realm, realm, *this);
|
||||
realm.global_object().define_direct_property("workbook", workbook_object(), JS::default_attributes);
|
||||
|
||||
m_main_execution_context.this_value = &realm.global_object();
|
||||
m_main_execution_context.function_name = "(global execution context)"sv;
|
||||
m_main_execution_context.lexical_environment = &realm.global_environment();
|
||||
m_main_execution_context.variable_environment = &realm.global_environment();
|
||||
m_main_execution_context.realm = &realm;
|
||||
m_main_execution_context.is_strict_mode = true;
|
||||
m_vm->push_execution_context(m_main_execution_context);
|
||||
m_main_execution_context->this_value = &realm.global_object();
|
||||
m_main_execution_context->function_name = JS::PrimitiveString::create(vm, "(global execution context)"sv);
|
||||
m_main_execution_context->lexical_environment = &realm.global_environment();
|
||||
m_main_execution_context->variable_environment = &realm.global_environment();
|
||||
m_main_execution_context->realm = &realm;
|
||||
m_main_execution_context->is_strict_mode = true;
|
||||
m_vm->push_execution_context(*m_main_execution_context);
|
||||
m_vm->enable_default_host_import_module_dynamically_hook();
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ private:
|
|||
NonnullOwnPtr<JS::ExecutionContext> m_root_execution_context;
|
||||
|
||||
JS::GCPtr<WorkbookObject> m_workbook_object;
|
||||
JS::ExecutionContext m_main_execution_context;
|
||||
NonnullOwnPtr<JS::ExecutionContext> m_main_execution_context;
|
||||
GUI::Window& m_parent_window;
|
||||
|
||||
DeprecatedString m_current_filename;
|
||||
|
|
|
@ -1666,7 +1666,7 @@ void ScopeNode::block_declaration_instantiation(VM& vm, Environment* environment
|
|||
|
||||
// iii. Perform ! env.InitializeBinding(fn, fo). NOTE: This step is replaced in section B.3.2.6.
|
||||
if (function_declaration.name_identifier()->is_local()) {
|
||||
vm.running_execution_context().local_variables[function_declaration.name_identifier()->local_variable_index()] = function;
|
||||
vm.running_execution_context().local(function_declaration.name_identifier()->local_variable_index()) = function;
|
||||
} else {
|
||||
VERIFY(is<DeclarativeEnvironment>(*environment));
|
||||
static_cast<DeclarativeEnvironment&>(*environment).initialize_or_set_mutable_binding({}, vm, function_declaration.name(), function);
|
||||
|
|
|
@ -65,36 +65,36 @@ ThrowCompletionOr<Value> Interpreter::run(Script& script_record, JS::GCPtr<Envir
|
|||
auto& global_environment = script_record.realm().global_environment();
|
||||
|
||||
// 2. Let scriptContext be a new ECMAScript code execution context.
|
||||
ExecutionContext script_context(vm.heap());
|
||||
auto script_context = ExecutionContext::create(vm.heap());
|
||||
|
||||
// 3. Set the Function of scriptContext to null.
|
||||
// NOTE: This was done during execution context construction.
|
||||
|
||||
// 4. Set the Realm of scriptContext to scriptRecord.[[Realm]].
|
||||
script_context.realm = &script_record.realm();
|
||||
script_context->realm = &script_record.realm();
|
||||
|
||||
// 5. Set the ScriptOrModule of scriptContext to scriptRecord.
|
||||
script_context.script_or_module = NonnullGCPtr<Script>(script_record);
|
||||
script_context->script_or_module = NonnullGCPtr<Script>(script_record);
|
||||
|
||||
// 6. Set the VariableEnvironment of scriptContext to globalEnv.
|
||||
script_context.variable_environment = &global_environment;
|
||||
script_context->variable_environment = &global_environment;
|
||||
|
||||
// 7. Set the LexicalEnvironment of scriptContext to globalEnv.
|
||||
script_context.lexical_environment = &global_environment;
|
||||
script_context->lexical_environment = &global_environment;
|
||||
|
||||
// Non-standard: Override the lexical environment if requested.
|
||||
if (lexical_environment_override)
|
||||
script_context.lexical_environment = lexical_environment_override;
|
||||
script_context->lexical_environment = lexical_environment_override;
|
||||
|
||||
// 8. Set the PrivateEnvironment of scriptContext to null.
|
||||
|
||||
// NOTE: This isn't in the spec, but we require it.
|
||||
script_context.is_strict_mode = script_record.parse_node().is_strict_mode();
|
||||
script_context->is_strict_mode = script_record.parse_node().is_strict_mode();
|
||||
|
||||
// FIXME: 9. Suspend the currently running execution context.
|
||||
|
||||
// 10. Push scriptContext onto the execution context stack; scriptContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(script_context, {}));
|
||||
TRY(vm.push_execution_context(*script_context, {}));
|
||||
|
||||
// 11. Let script be scriptRecord.[[ECMAScriptCode]].
|
||||
auto& script = script_record.parse_node();
|
||||
|
@ -183,7 +183,7 @@ ThrowCompletionOr<Value> Interpreter::run(SourceTextModule& module)
|
|||
|
||||
void Interpreter::run_bytecode()
|
||||
{
|
||||
auto* locals = vm().running_execution_context().local_variables.data();
|
||||
auto* locals = vm().running_execution_context().locals.data();
|
||||
auto* registers = this->registers().data();
|
||||
auto& accumulator = this->accumulator();
|
||||
for (;;) {
|
||||
|
@ -1269,7 +1269,7 @@ ThrowCompletionOr<void> TypeofVariable::execute_impl(Bytecode::Interpreter& inte
|
|||
ThrowCompletionOr<void> TypeofLocal::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto& vm = interpreter.vm();
|
||||
auto const& value = vm.running_execution_context().local_variables[m_index];
|
||||
auto const& value = vm.running_execution_context().local(m_index);
|
||||
interpreter.accumulator() = PrimitiveString::create(vm, value.typeof());
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -450,6 +450,9 @@ void Heap::mark_live_cells(HashMap<Cell*, HeapRoot> const& roots)
|
|||
|
||||
MarkingVisitor visitor(*this, roots);
|
||||
|
||||
for (auto& execution_context : m_execution_contexts)
|
||||
execution_context.visit_edges(visitor);
|
||||
|
||||
vm().bytecode_interpreter().visit_edges(visitor);
|
||||
|
||||
visitor.mark_all_live_cells();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <LibJS/Heap/Internals.h>
|
||||
#include <LibJS/Heap/MarkedVector.h>
|
||||
#include <LibJS/Runtime/Completion.h>
|
||||
#include <LibJS/Runtime/ExecutionContext.h>
|
||||
#include <LibJS/Runtime/WeakContainer.h>
|
||||
|
||||
namespace JS {
|
||||
|
@ -77,6 +78,9 @@ public:
|
|||
void did_create_weak_container(Badge<WeakContainer>, WeakContainer&);
|
||||
void did_destroy_weak_container(Badge<WeakContainer>, WeakContainer&);
|
||||
|
||||
void did_create_execution_context(Badge<ExecutionContext>, ExecutionContext&);
|
||||
void did_destroy_execution_context(Badge<ExecutionContext>, ExecutionContext&);
|
||||
|
||||
BlockAllocator& block_allocator() { return m_block_allocator; }
|
||||
|
||||
void uproot_cell(Cell* cell);
|
||||
|
@ -144,6 +148,7 @@ private:
|
|||
HandleImpl::List m_handles;
|
||||
MarkedVectorBase::List m_marked_vectors;
|
||||
WeakContainer::List m_weak_containers;
|
||||
ExecutionContext::List m_execution_contexts;
|
||||
|
||||
Vector<GCPtr<Cell>> m_uprooted_cells;
|
||||
|
||||
|
@ -191,4 +196,16 @@ inline void Heap::did_destroy_weak_container(Badge<WeakContainer>, WeakContainer
|
|||
m_weak_containers.remove(set);
|
||||
}
|
||||
|
||||
inline void Heap::did_create_execution_context(Badge<ExecutionContext>, ExecutionContext& set)
|
||||
{
|
||||
VERIFY(!m_execution_contexts.contains(set));
|
||||
m_execution_contexts.append(set);
|
||||
}
|
||||
|
||||
inline void Heap::did_destroy_execution_context(Badge<ExecutionContext>, ExecutionContext& set)
|
||||
{
|
||||
VERIFY(m_execution_contexts.contains(set));
|
||||
m_execution_contexts.remove(set);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ void NativeExecutable::run(VM& vm, size_t entry_point) const
|
|||
typedef void (*JITCode)(VM&, Value* registers, Value* locals, FlatPtr entry_point_address, ExecutionContext&);
|
||||
((JITCode)m_code)(vm,
|
||||
vm.bytecode_interpreter().registers().data(),
|
||||
vm.running_execution_context().local_variables.data(),
|
||||
vm.running_execution_context().locals.data(),
|
||||
entry_point_address,
|
||||
vm.running_execution_context());
|
||||
}
|
||||
|
|
|
@ -638,31 +638,31 @@ ThrowCompletionOr<Value> perform_eval(VM& vm, Value x, CallerMode strict_caller,
|
|||
// FIXME: We don't have this concept yet.
|
||||
|
||||
// 20. Let evalContext be a new ECMAScript code execution context.
|
||||
ExecutionContext eval_context(vm.heap());
|
||||
auto eval_context = ExecutionContext::create(vm.heap());
|
||||
|
||||
// 21. Set evalContext's Function to null.
|
||||
// NOTE: This was done in the construction of eval_context.
|
||||
|
||||
// 22. Set evalContext's Realm to evalRealm.
|
||||
eval_context.realm = &eval_realm;
|
||||
eval_context->realm = &eval_realm;
|
||||
|
||||
// 23. Set evalContext's ScriptOrModule to runningContext's ScriptOrModule.
|
||||
eval_context.script_or_module = running_context.script_or_module;
|
||||
eval_context->script_or_module = running_context.script_or_module;
|
||||
|
||||
// 24. Set evalContext's VariableEnvironment to varEnv.
|
||||
eval_context.variable_environment = variable_environment;
|
||||
eval_context->variable_environment = variable_environment;
|
||||
|
||||
// 25. Set evalContext's LexicalEnvironment to lexEnv.
|
||||
eval_context.lexical_environment = lexical_environment;
|
||||
eval_context->lexical_environment = lexical_environment;
|
||||
|
||||
// 26. Set evalContext's PrivateEnvironment to privateEnv.
|
||||
eval_context.private_environment = private_environment;
|
||||
eval_context->private_environment = private_environment;
|
||||
|
||||
// NOTE: This isn't in the spec, but we require it.
|
||||
eval_context.is_strict_mode = strict_eval;
|
||||
eval_context->is_strict_mode = strict_eval;
|
||||
|
||||
// 27. Push evalContext onto the execution context stack; evalContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(eval_context, {}));
|
||||
TRY(vm.push_execution_context(*eval_context, {}));
|
||||
|
||||
// NOTE: We use a ScopeGuard to automatically pop the execution context when any of the `TRY`s below return a throw completion.
|
||||
ScopeGuard pop_guard = [&] {
|
||||
|
@ -1025,7 +1025,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
|
|||
}
|
||||
|
||||
// 10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList ), https://tc39.es/ecma262/#sec-createunmappedargumentsobject
|
||||
Object* create_unmapped_arguments_object(VM& vm, Span<Value> arguments)
|
||||
Object* create_unmapped_arguments_object(VM& vm, ReadonlySpan<Value> arguments)
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
|
@ -1065,7 +1065,7 @@ Object* create_unmapped_arguments_object(VM& vm, Span<Value> arguments)
|
|||
}
|
||||
|
||||
// 10.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env ), https://tc39.es/ecma262/#sec-createmappedargumentsobject
|
||||
Object* create_mapped_arguments_object(VM& vm, FunctionObject& function, Vector<FunctionParameter> const& formals, Span<Value> arguments, Environment& environment)
|
||||
Object* create_mapped_arguments_object(VM& vm, FunctionObject& function, Vector<FunctionParameter> const& formals, ReadonlySpan<Value> arguments, Environment& environment)
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
|
|
|
@ -39,8 +39,8 @@ ThrowCompletionOr<void> initialize_bound_name(VM&, DeprecatedFlyString const&, V
|
|||
bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
|
||||
bool validate_and_apply_property_descriptor(Object*, PropertyKey const&, bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
|
||||
ThrowCompletionOr<Object*> get_prototype_from_constructor(VM&, FunctionObject const& constructor, NonnullGCPtr<Object> (Intrinsics::*intrinsic_default_prototype)());
|
||||
Object* create_unmapped_arguments_object(VM&, Span<Value> arguments);
|
||||
Object* create_mapped_arguments_object(VM&, FunctionObject&, Vector<FunctionParameter> const&, Span<Value> arguments, Environment&);
|
||||
Object* create_unmapped_arguments_object(VM&, ReadonlySpan<Value> arguments);
|
||||
Object* create_mapped_arguments_object(VM&, FunctionObject&, Vector<FunctionParameter> const&, ReadonlySpan<Value> arguments, Environment&);
|
||||
|
||||
struct DisposableResource {
|
||||
Value resource_value;
|
||||
|
|
|
@ -45,7 +45,9 @@ ThrowCompletionOr<NonnullGCPtr<Object>> AsyncFunctionConstructor::construct(Func
|
|||
auto* constructor = vm.active_function_object();
|
||||
|
||||
// 2. Let args be the argumentsList that was passed to this function by [[Call]] or [[Construct]].
|
||||
auto& args = vm.running_execution_context().arguments;
|
||||
MarkedVector<Value> args(heap());
|
||||
for (auto argument : vm.running_execution_context().arguments)
|
||||
args.append(argument);
|
||||
|
||||
// 3. Return CreateDynamicFunction(C, NewTarget, async, args).
|
||||
return *TRY(FunctionConstructor::create_dynamic_function(vm, *constructor, &new_target, FunctionKind::Async, args));
|
||||
|
|
|
@ -45,7 +45,8 @@ ThrowCompletionOr<void> AsyncFunctionDriverWrapper::await(JS::Value value)
|
|||
auto& realm = *vm.current_realm();
|
||||
|
||||
// 1. Let asyncContext be the running execution context.
|
||||
m_suspended_execution_context = vm.running_execution_context().copy();
|
||||
if (!m_suspended_execution_context)
|
||||
m_suspended_execution_context = vm.running_execution_context().copy();
|
||||
|
||||
// 2. Let promise be ? PromiseResolve(%Promise%, value).
|
||||
auto* promise_object = TRY(promise_resolve(vm, realm.intrinsics().promise_constructor(), value));
|
||||
|
@ -61,7 +62,7 @@ ThrowCompletionOr<void> AsyncFunctionDriverWrapper::await(JS::Value value)
|
|||
// FIXME: b. Suspend prevContext.
|
||||
|
||||
// c. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(m_suspended_execution_context.value(), {}));
|
||||
TRY(vm.push_execution_context(*m_suspended_execution_context, {}));
|
||||
|
||||
// d. Resume the suspended evaluation of asyncContext using NormalCompletion(v) as the result of the operation that
|
||||
// suspended it.
|
||||
|
@ -89,7 +90,7 @@ ThrowCompletionOr<void> AsyncFunctionDriverWrapper::await(JS::Value value)
|
|||
// FIXME: b. Suspend prevContext.
|
||||
|
||||
// c. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(m_suspended_execution_context.value(), {}));
|
||||
TRY(vm.push_execution_context(*m_suspended_execution_context, {}));
|
||||
|
||||
// d. Resume the suspended evaluation of asyncContext using ThrowCompletion(reason) as the result of the operation that
|
||||
// suspended it.
|
||||
|
@ -191,8 +192,6 @@ void AsyncFunctionDriverWrapper::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(m_top_level_promise);
|
||||
if (m_current_promise)
|
||||
visitor.visit(m_current_promise);
|
||||
if (m_suspended_execution_context.has_value())
|
||||
m_suspended_execution_context->visit_edges(visitor);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ private:
|
|||
NonnullGCPtr<Promise> m_top_level_promise;
|
||||
GCPtr<Promise> m_current_promise { nullptr };
|
||||
Handle<AsyncFunctionDriverWrapper> m_self_handle;
|
||||
Optional<ExecutionContext> m_suspended_execution_context;
|
||||
OwnPtr<ExecutionContext> m_suspended_execution_context;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace JS {
|
|||
|
||||
JS_DEFINE_ALLOCATOR(AsyncGenerator);
|
||||
|
||||
ThrowCompletionOr<NonnullGCPtr<AsyncGenerator>> AsyncGenerator::create(Realm& realm, Value initial_value, ECMAScriptFunctionObject* generating_function, ExecutionContext execution_context, Bytecode::CallFrame frame)
|
||||
ThrowCompletionOr<NonnullGCPtr<AsyncGenerator>> AsyncGenerator::create(Realm& realm, Value initial_value, ECMAScriptFunctionObject* generating_function, NonnullOwnPtr<ExecutionContext> execution_context, Bytecode::CallFrame frame)
|
||||
{
|
||||
auto& vm = realm.vm();
|
||||
// This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
|
||||
|
@ -29,7 +29,7 @@ ThrowCompletionOr<NonnullGCPtr<AsyncGenerator>> AsyncGenerator::create(Realm& re
|
|||
return object;
|
||||
}
|
||||
|
||||
AsyncGenerator::AsyncGenerator(Realm&, Object& prototype, ExecutionContext context)
|
||||
AsyncGenerator::AsyncGenerator(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext> context)
|
||||
: Object(ConstructWithPrototypeTag::Tag, prototype)
|
||||
, m_async_generator_context(move(context))
|
||||
{
|
||||
|
@ -43,7 +43,6 @@ void AsyncGenerator::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(*request.completion.value());
|
||||
visitor.visit(request.capability);
|
||||
}
|
||||
m_async_generator_context.visit_edges(visitor);
|
||||
visitor.visit(m_generating_function);
|
||||
visitor.visit(m_previous_value);
|
||||
if (m_frame.has_value())
|
||||
|
@ -328,7 +327,7 @@ ThrowCompletionOr<void> AsyncGenerator::resume(VM& vm, Completion completion)
|
|||
m_async_generator_state = State::Executing;
|
||||
|
||||
// 6. Push genContext onto the execution context stack; genContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(generator_context, {}));
|
||||
TRY(vm.push_execution_context(*generator_context, {}));
|
||||
|
||||
// 7. Resume the suspended evaluation of genContext using completion as the result of the operation that suspended
|
||||
// it. Let result be the Completion Record returned by the resumed computation.
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
Completed,
|
||||
};
|
||||
|
||||
static ThrowCompletionOr<NonnullGCPtr<AsyncGenerator>> create(Realm&, Value, ECMAScriptFunctionObject*, ExecutionContext, Bytecode::CallFrame);
|
||||
static ThrowCompletionOr<NonnullGCPtr<AsyncGenerator>> create(Realm&, Value, ECMAScriptFunctionObject*, NonnullOwnPtr<ExecutionContext>, Bytecode::CallFrame);
|
||||
|
||||
virtual ~AsyncGenerator() override = default;
|
||||
|
||||
|
@ -44,7 +44,7 @@ public:
|
|||
Optional<String> const& generator_brand() const { return m_generator_brand; }
|
||||
|
||||
private:
|
||||
AsyncGenerator(Realm&, Object& prototype, ExecutionContext);
|
||||
AsyncGenerator(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext>);
|
||||
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
|
@ -53,10 +53,10 @@ private:
|
|||
|
||||
// At the time of constructing an AsyncGenerator, we still need to point to an
|
||||
// execution context on the stack, but later need to 'adopt' it.
|
||||
State m_async_generator_state { State::SuspendedStart }; // [[AsyncGeneratorState]]
|
||||
ExecutionContext m_async_generator_context; // [[AsyncGeneratorContext]]
|
||||
Vector<AsyncGeneratorRequest> m_async_generator_queue; // [[AsyncGeneratorQueue]]
|
||||
Optional<String> m_generator_brand; // [[GeneratorBrand]]
|
||||
State m_async_generator_state { State::SuspendedStart }; // [[AsyncGeneratorState]]
|
||||
NonnullOwnPtr<ExecutionContext> m_async_generator_context; // [[AsyncGeneratorContext]]
|
||||
Vector<AsyncGeneratorRequest> m_async_generator_queue; // [[AsyncGeneratorQueue]]
|
||||
Optional<String> m_generator_brand; // [[GeneratorBrand]]
|
||||
|
||||
GCPtr<ECMAScriptFunctionObject> m_generating_function;
|
||||
Value m_previous_value;
|
||||
|
|
|
@ -46,7 +46,9 @@ ThrowCompletionOr<NonnullGCPtr<Object>> AsyncGeneratorFunctionConstructor::const
|
|||
auto* constructor = vm.active_function_object();
|
||||
|
||||
// 2. Let args be the argumentsList that was passed to this function by [[Call]] or [[Construct]].
|
||||
auto& args = vm.running_execution_context().arguments;
|
||||
MarkedVector<Value> args(heap());
|
||||
for (auto argument : vm.running_execution_context().arguments)
|
||||
args.append(argument);
|
||||
|
||||
// 3. Return ? CreateDynamicFunction(C, NewTarget, asyncGenerator, args).
|
||||
return *TRY(FunctionConstructor::create_dynamic_function(vm, *constructor, &new_target, FunctionKind::AsyncGenerator, args));
|
||||
|
|
|
@ -370,20 +370,20 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
|
|||
// 1. Let callerContext be the running execution context.
|
||||
// NOTE: No-op, kept by the VM in its execution context stack.
|
||||
|
||||
ExecutionContext callee_context(heap());
|
||||
auto callee_context = ExecutionContext::create(heap());
|
||||
|
||||
callee_context.local_variables.resize(m_local_variables_names.size());
|
||||
callee_context->locals.resize(m_local_variables_names.size());
|
||||
|
||||
// Non-standard
|
||||
callee_context.arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context->instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
|
||||
// 2. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
|
||||
// NOTE: We throw if the end of the native stack is reached, so unlike in the spec this _does_ need an exception check.
|
||||
TRY(prepare_for_ordinary_call(callee_context, nullptr));
|
||||
TRY(prepare_for_ordinary_call(*callee_context, nullptr));
|
||||
|
||||
// 3. Assert: calleeContext is now the running execution context.
|
||||
VERIFY(&vm.running_execution_context() == &callee_context);
|
||||
VERIFY(&vm.running_execution_context() == callee_context);
|
||||
|
||||
// 4. If F.[[IsClassConstructor]] is true, then
|
||||
if (m_is_class_constructor) {
|
||||
|
@ -399,7 +399,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
|
|||
}
|
||||
|
||||
// 5. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
|
||||
ordinary_call_bind_this(callee_context, this_argument);
|
||||
ordinary_call_bind_this(*callee_context, this_argument);
|
||||
|
||||
// 6. Let result be Completion(OrdinaryCallEvaluateBody(F, argumentsList)).
|
||||
auto result = ordinary_call_evaluate_body();
|
||||
|
@ -440,25 +440,25 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ECMAScriptFunctionObject::internal_const
|
|||
this_argument = TRY(ordinary_create_from_constructor<Object>(vm, new_target, &Intrinsics::object_prototype, ConstructWithPrototypeTag::Tag));
|
||||
}
|
||||
|
||||
ExecutionContext callee_context(heap());
|
||||
auto callee_context = ExecutionContext::create(heap());
|
||||
|
||||
callee_context.local_variables.resize(m_local_variables_names.size());
|
||||
callee_context->locals.resize(m_local_variables_names.size());
|
||||
|
||||
// Non-standard
|
||||
callee_context.arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context->instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
|
||||
// 4. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
|
||||
// NOTE: We throw if the end of the native stack is reached, so unlike in the spec this _does_ need an exception check.
|
||||
TRY(prepare_for_ordinary_call(callee_context, &new_target));
|
||||
TRY(prepare_for_ordinary_call(*callee_context, &new_target));
|
||||
|
||||
// 5. Assert: calleeContext is now the running execution context.
|
||||
VERIFY(&vm.running_execution_context() == &callee_context);
|
||||
VERIFY(&vm.running_execution_context() == callee_context);
|
||||
|
||||
// 6. If kind is base, then
|
||||
if (kind == ConstructorKind::Base) {
|
||||
// a. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
|
||||
ordinary_call_bind_this(callee_context, this_argument);
|
||||
ordinary_call_bind_this(*callee_context, this_argument);
|
||||
|
||||
// b. Let initializeResult be Completion(InitializeInstanceElements(thisArgument, F)).
|
||||
auto initialize_result = this_argument->initialize_instance_elements(*this);
|
||||
|
@ -474,7 +474,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ECMAScriptFunctionObject::internal_const
|
|||
}
|
||||
|
||||
// 7. Let constructorEnv be the LexicalEnvironment of calleeContext.
|
||||
auto constructor_env = callee_context.lexical_environment;
|
||||
auto constructor_env = callee_context->lexical_environment;
|
||||
|
||||
// 8. Let result be Completion(OrdinaryCallEvaluateBody(F, argumentsList)).
|
||||
auto result = ordinary_call_evaluate_body();
|
||||
|
@ -681,7 +681,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|||
// 26. Else,
|
||||
// a. Perform ? IteratorBindingInitialization of formals with arguments iteratorRecord and env.
|
||||
// NOTE: The spec makes an iterator here to do IteratorBindingInitialization but we just do it manually
|
||||
auto& execution_context_arguments = vm.running_execution_context().arguments;
|
||||
auto execution_context_arguments = vm.running_execution_context().arguments;
|
||||
|
||||
size_t default_parameter_index = 0;
|
||||
for (size_t i = 0; i < m_formal_parameters.size(); ++i) {
|
||||
|
@ -713,7 +713,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|||
|
||||
if constexpr (IsSame<NonnullRefPtr<Identifier const> const&, decltype(param)>) {
|
||||
if (param->is_local()) {
|
||||
callee_context.local_variables[param->local_variable_index()] = argument_value;
|
||||
callee_context.locals[param->local_variable_index()] = argument_value;
|
||||
return {};
|
||||
}
|
||||
Reference reference = TRY(vm.resolve_binding(param->string(), used_environment));
|
||||
|
@ -749,7 +749,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|||
// i. If instantiatedVarNames does not contain n, then
|
||||
// 1. Append n to instantiatedVarNames.
|
||||
if (id.is_local()) {
|
||||
callee_context.local_variables[id.local_variable_index()] = js_undefined();
|
||||
callee_context.locals[id.local_variable_index()] = js_undefined();
|
||||
} else {
|
||||
// 2. Perform ! env.CreateMutableBinding(n, false).
|
||||
// 3. Perform ! env.InitializeBinding(n, undefined).
|
||||
|
@ -804,7 +804,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|||
else {
|
||||
// a. Let initialValue be ! env.GetBindingValue(n, false).
|
||||
if (id.is_local()) {
|
||||
initial_value = callee_context.local_variables[id.local_variable_index()];
|
||||
initial_value = callee_context.locals[id.local_variable_index()];
|
||||
} else {
|
||||
initial_value = MUST(environment->get_binding_value(vm, id.string(), false));
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|||
// 5. Perform ! varEnv.InitializeBinding(n, initialValue).
|
||||
if (id.is_local()) {
|
||||
// NOTE: Local variables are supported only in bytecode interpreter
|
||||
callee_context.local_variables[id.local_variable_index()] = initial_value;
|
||||
callee_context.locals[id.local_variable_index()] = initial_value;
|
||||
} else {
|
||||
MUST(var_environment->initialize_binding(vm, id.string(), initial_value, Environment::InitializeBindingHint::Normal));
|
||||
}
|
||||
|
@ -906,7 +906,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
|||
|
||||
// c. Perform ! varEnv.SetMutableBinding(fn, fo, false).
|
||||
if (declaration.name_identifier()->is_local()) {
|
||||
callee_context.local_variables[declaration.name_identifier()->local_variable_index()] = function;
|
||||
callee_context.locals[declaration.name_identifier()->local_variable_index()] = function;
|
||||
} else {
|
||||
MUST(var_environment->set_mutable_binding(vm, declaration.name(), function, false));
|
||||
}
|
||||
|
@ -1056,7 +1056,7 @@ void async_function_start(VM& vm, PromiseCapability const& promise_capability, T
|
|||
// 3. NOTE: Copying the execution state is required for AsyncBlockStart to resume its execution. It is ill-defined to resume a currently executing context.
|
||||
|
||||
// 4. Perform AsyncBlockStart(promiseCapability, asyncFunctionBody, asyncContext).
|
||||
async_block_start(vm, async_function_body, promise_capability, async_context);
|
||||
async_block_start(vm, async_function_body, promise_capability, *async_context);
|
||||
|
||||
// 5. Return unused.
|
||||
}
|
||||
|
|
|
@ -7,38 +7,44 @@
|
|||
*/
|
||||
|
||||
#include <LibJS/Bytecode/Executable.h>
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/ExecutionContext.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
NonnullOwnPtr<ExecutionContext> ExecutionContext::create(Heap& heap)
|
||||
{
|
||||
return adopt_own(*new ExecutionContext(heap));
|
||||
}
|
||||
|
||||
ExecutionContext::ExecutionContext(Heap& heap)
|
||||
: arguments(heap)
|
||||
, local_variables(heap)
|
||||
: m_heap(heap)
|
||||
{
|
||||
m_heap.did_create_execution_context({}, *this);
|
||||
}
|
||||
|
||||
ExecutionContext::ExecutionContext(MarkedVector<Value> existing_arguments, MarkedVector<Value> existing_local_variables)
|
||||
: arguments(move(existing_arguments))
|
||||
, local_variables(move(existing_local_variables))
|
||||
ExecutionContext::~ExecutionContext()
|
||||
{
|
||||
m_heap.did_destroy_execution_context({}, *this);
|
||||
}
|
||||
|
||||
ExecutionContext ExecutionContext::copy() const
|
||||
NonnullOwnPtr<ExecutionContext> ExecutionContext::copy() const
|
||||
{
|
||||
ExecutionContext copy { arguments, local_variables };
|
||||
|
||||
copy.function = function;
|
||||
copy.realm = realm;
|
||||
copy.script_or_module = script_or_module;
|
||||
copy.lexical_environment = lexical_environment;
|
||||
copy.variable_environment = variable_environment;
|
||||
copy.private_environment = private_environment;
|
||||
copy.instruction_stream_iterator = instruction_stream_iterator;
|
||||
copy.function_name = function_name;
|
||||
copy.this_value = this_value;
|
||||
copy.is_strict_mode = is_strict_mode;
|
||||
|
||||
auto copy = create(m_heap);
|
||||
copy->function = function;
|
||||
copy->realm = realm;
|
||||
copy->script_or_module = script_or_module;
|
||||
copy->lexical_environment = lexical_environment;
|
||||
copy->variable_environment = variable_environment;
|
||||
copy->private_environment = private_environment;
|
||||
copy->instruction_stream_iterator = instruction_stream_iterator;
|
||||
copy->function_name = function_name;
|
||||
copy->this_value = this_value;
|
||||
copy->is_strict_mode = is_strict_mode;
|
||||
copy->executable = executable;
|
||||
copy->arguments = arguments;
|
||||
copy->locals = locals;
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
@ -51,9 +57,14 @@ void ExecutionContext::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(private_environment);
|
||||
visitor.visit(context_owner);
|
||||
visitor.visit(this_value);
|
||||
visitor.visit(executable);
|
||||
if (instruction_stream_iterator.has_value())
|
||||
visitor.visit(const_cast<Bytecode::Executable*>(instruction_stream_iterator.value().executable()));
|
||||
visitor.visit(function_name);
|
||||
for (auto argument : arguments)
|
||||
visitor.visit(argument);
|
||||
for (auto local : locals)
|
||||
visitor.visit(local);
|
||||
script_or_module.visit(
|
||||
[](Empty) {},
|
||||
[&](auto& script_or_module) {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <AK/WeakPtr.h>
|
||||
#include <LibJS/Bytecode/Instruction.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Heap/MarkedVector.h>
|
||||
#include <LibJS/Module.h>
|
||||
#include <LibJS/Runtime/PrivateEnvironment.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
|
@ -24,9 +23,10 @@ using ScriptOrModule = Variant<Empty, NonnullGCPtr<Script>, NonnullGCPtr<Module>
|
|||
|
||||
// 9.4 Execution Contexts, https://tc39.es/ecma262/#sec-execution-contexts
|
||||
struct ExecutionContext {
|
||||
explicit ExecutionContext(Heap& heap);
|
||||
static NonnullOwnPtr<ExecutionContext> create(Heap&);
|
||||
[[nodiscard]] NonnullOwnPtr<ExecutionContext> copy() const;
|
||||
|
||||
[[nodiscard]] ExecutionContext copy() const;
|
||||
~ExecutionContext();
|
||||
|
||||
void visit_edges(Cell::Visitor&);
|
||||
|
||||
|
@ -35,9 +35,15 @@ struct ExecutionContext {
|
|||
static FlatPtr variable_environment_offset() { return OFFSET_OF(ExecutionContext, variable_environment); }
|
||||
|
||||
private:
|
||||
explicit ExecutionContext(MarkedVector<Value> existing_arguments, MarkedVector<Value> existing_local_variables);
|
||||
ExecutionContext(Heap&);
|
||||
|
||||
IntrusiveListNode<ExecutionContext> m_list_node;
|
||||
|
||||
public:
|
||||
Heap& m_heap;
|
||||
|
||||
using List = IntrusiveList<&ExecutionContext::m_list_node>;
|
||||
|
||||
GCPtr<FunctionObject> function; // [[Function]]
|
||||
GCPtr<Realm> realm; // [[Realm]]
|
||||
ScriptOrModule script_or_module; // [[ScriptOrModule]]
|
||||
|
@ -51,8 +57,6 @@ public:
|
|||
Optional<Bytecode::InstructionStreamIterator> instruction_stream_iterator;
|
||||
GCPtr<PrimitiveString> function_name;
|
||||
Value this_value;
|
||||
MarkedVector<Value> arguments;
|
||||
MarkedVector<Value> local_variables;
|
||||
bool is_strict_mode { false };
|
||||
|
||||
GCPtr<Bytecode::Executable> executable;
|
||||
|
@ -60,6 +64,21 @@ public:
|
|||
// https://html.spec.whatwg.org/multipage/webappapis.html#skip-when-determining-incumbent-counter
|
||||
// FIXME: Move this out of LibJS (e.g. by using the CustomData concept), as it's used exclusively by LibWeb.
|
||||
size_t skip_when_determining_incumbent_counter { 0 };
|
||||
|
||||
Value argument(size_t index) const
|
||||
{
|
||||
if (index >= arguments.size()) [[unlikely]]
|
||||
return js_undefined();
|
||||
return arguments[index];
|
||||
}
|
||||
|
||||
Value& local(size_t index)
|
||||
{
|
||||
return locals[index];
|
||||
}
|
||||
|
||||
Vector<Value> arguments;
|
||||
Vector<Value> locals;
|
||||
};
|
||||
|
||||
struct StackTraceElement {
|
||||
|
|
|
@ -268,7 +268,9 @@ ThrowCompletionOr<NonnullGCPtr<Object>> FunctionConstructor::construct(FunctionO
|
|||
auto* constructor = vm.active_function_object();
|
||||
|
||||
// 2. Let args be the argumentsList that was passed to this function by [[Call]] or [[Construct]].
|
||||
auto& args = vm.running_execution_context().arguments;
|
||||
MarkedVector<Value> args(heap());
|
||||
for (auto argument : vm.running_execution_context().arguments)
|
||||
args.append(argument);
|
||||
|
||||
// 3. Return ? CreateDynamicFunction(C, NewTarget, normal, args).
|
||||
return *TRY(create_dynamic_function(vm, *constructor, &new_target, FunctionKind::Normal, args));
|
||||
|
|
|
@ -98,8 +98,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::bind)
|
|||
|
||||
Vector<Value> arguments;
|
||||
if (vm.argument_count() > 1) {
|
||||
arguments = vm.running_execution_context().arguments;
|
||||
arguments.remove(0);
|
||||
arguments.append(vm.running_execution_context().arguments.span().slice(1).data(), vm.argument_count() - 1);
|
||||
}
|
||||
|
||||
// 3. Let F be ? BoundFunctionCreate(Target, thisArg, args).
|
||||
|
|
|
@ -44,7 +44,9 @@ ThrowCompletionOr<NonnullGCPtr<Object>> GeneratorFunctionConstructor::construct(
|
|||
auto* constructor = vm.active_function_object();
|
||||
|
||||
// 2. Let args be the argumentsList that was passed to this function by [[Call]] or [[Construct]].
|
||||
auto& args = vm.running_execution_context().arguments;
|
||||
MarkedVector<Value> args(heap());
|
||||
for (auto argument : vm.running_execution_context().arguments)
|
||||
args.append(argument);
|
||||
|
||||
// 3. Return ? CreateDynamicFunction(C, NewTarget, generator, args).
|
||||
return *TRY(FunctionConstructor::create_dynamic_function(vm, *constructor, &new_target, FunctionKind::Generator, args));
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace JS {
|
|||
|
||||
JS_DEFINE_ALLOCATOR(GeneratorObject);
|
||||
|
||||
ThrowCompletionOr<NonnullGCPtr<GeneratorObject>> GeneratorObject::create(Realm& realm, Value initial_value, ECMAScriptFunctionObject* generating_function, ExecutionContext execution_context, Bytecode::CallFrame frame)
|
||||
ThrowCompletionOr<NonnullGCPtr<GeneratorObject>> GeneratorObject::create(Realm& realm, Value initial_value, ECMAScriptFunctionObject* generating_function, NonnullOwnPtr<ExecutionContext> execution_context, Bytecode::CallFrame frame)
|
||||
{
|
||||
auto& vm = realm.vm();
|
||||
// This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
|
||||
|
@ -37,7 +37,7 @@ ThrowCompletionOr<NonnullGCPtr<GeneratorObject>> GeneratorObject::create(Realm&
|
|||
return object;
|
||||
}
|
||||
|
||||
GeneratorObject::GeneratorObject(Realm&, Object& prototype, ExecutionContext context, Optional<StringView> generator_brand)
|
||||
GeneratorObject::GeneratorObject(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext> context, Optional<StringView> generator_brand)
|
||||
: Object(ConstructWithPrototypeTag::Tag, prototype)
|
||||
, m_execution_context(move(context))
|
||||
, m_generator_brand(move(generator_brand))
|
||||
|
@ -49,7 +49,6 @@ void GeneratorObject::visit_edges(Cell::Visitor& visitor)
|
|||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_generating_function);
|
||||
visitor.visit(m_previous_value);
|
||||
m_execution_context.visit_edges(visitor);
|
||||
if (m_frame.has_value())
|
||||
m_frame->visit_edges(visitor);
|
||||
}
|
||||
|
@ -166,7 +165,7 @@ ThrowCompletionOr<Value> GeneratorObject::resume(VM& vm, Value value, Optional<S
|
|||
// 8. Push genContext onto the execution context stack; genContext is now the running execution context.
|
||||
// NOTE: This is done out of order as to not permanently disable the generator if push_execution_context throws,
|
||||
// as `resume` will immediately throw when [[GeneratorState]] is "executing", never allowing the state to change.
|
||||
TRY(vm.push_execution_context(generator_context, {}));
|
||||
TRY(vm.push_execution_context(*generator_context, {}));
|
||||
|
||||
// 7. Set generator.[[GeneratorState]] to executing.
|
||||
m_generator_state = GeneratorState::Executing;
|
||||
|
@ -228,7 +227,7 @@ ThrowCompletionOr<Value> GeneratorObject::resume_abrupt(JS::VM& vm, JS::Completi
|
|||
// 9. Push genContext onto the execution context stack; genContext is now the running execution context.
|
||||
// NOTE: This is done out of order as to not permanently disable the generator if push_execution_context throws,
|
||||
// as `resume_abrupt` will immediately throw when [[GeneratorState]] is "executing", never allowing the state to change.
|
||||
TRY(vm.push_execution_context(generator_context, {}));
|
||||
TRY(vm.push_execution_context(*generator_context, {}));
|
||||
|
||||
// 8. Set generator.[[GeneratorState]] to executing.
|
||||
m_generator_state = GeneratorState::Executing;
|
||||
|
|
|
@ -17,7 +17,7 @@ class GeneratorObject : public Object {
|
|||
JS_DECLARE_ALLOCATOR(GeneratorObject);
|
||||
|
||||
public:
|
||||
static ThrowCompletionOr<NonnullGCPtr<GeneratorObject>> create(Realm&, Value, ECMAScriptFunctionObject*, ExecutionContext, Bytecode::CallFrame);
|
||||
static ThrowCompletionOr<NonnullGCPtr<GeneratorObject>> create(Realm&, Value, ECMAScriptFunctionObject*, NonnullOwnPtr<ExecutionContext>, Bytecode::CallFrame);
|
||||
virtual ~GeneratorObject() override = default;
|
||||
void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
|
@ -34,13 +34,13 @@ public:
|
|||
void set_generator_state(GeneratorState generator_state) { m_generator_state = generator_state; }
|
||||
|
||||
protected:
|
||||
GeneratorObject(Realm&, Object& prototype, ExecutionContext, Optional<StringView> generator_brand = {});
|
||||
GeneratorObject(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext>, Optional<StringView> generator_brand = {});
|
||||
|
||||
ThrowCompletionOr<GeneratorState> validate(VM&, Optional<StringView> const& generator_brand);
|
||||
virtual ThrowCompletionOr<Value> execute(VM&, JS::Completion const& completion);
|
||||
|
||||
private:
|
||||
ExecutionContext m_execution_context;
|
||||
NonnullOwnPtr<ExecutionContext> m_execution_context;
|
||||
GCPtr<ECMAScriptFunctionObject> m_generating_function;
|
||||
Value m_previous_value;
|
||||
Optional<Bytecode::CallFrame> m_frame;
|
||||
|
|
|
@ -121,11 +121,11 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Read
|
|||
// NOTE: We don't support this concept yet.
|
||||
|
||||
// 3. Let calleeContext be a new execution context.
|
||||
ExecutionContext callee_context(heap());
|
||||
auto callee_context = ExecutionContext::create(heap());
|
||||
|
||||
// 4. Set the Function of calleeContext to F.
|
||||
callee_context.function = this;
|
||||
callee_context.function_name = m_name_string;
|
||||
callee_context->function = this;
|
||||
callee_context->function_name = m_name_string;
|
||||
|
||||
// 5. Let calleeRealm be F.[[Realm]].
|
||||
auto callee_realm = m_realm;
|
||||
|
@ -139,29 +139,29 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Read
|
|||
VERIFY(callee_realm);
|
||||
|
||||
// 6. Set the Realm of calleeContext to calleeRealm.
|
||||
callee_context.realm = callee_realm;
|
||||
callee_context->realm = callee_realm;
|
||||
|
||||
// 7. Set the ScriptOrModule of calleeContext to null.
|
||||
// Note: This is already the default value.
|
||||
|
||||
// 8. Perform any necessary implementation-defined initialization of calleeContext.
|
||||
callee_context.this_value = this_argument;
|
||||
callee_context.arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
callee_context->this_value = this_argument;
|
||||
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context->instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
|
||||
callee_context.lexical_environment = caller_context.lexical_environment;
|
||||
callee_context.variable_environment = caller_context.variable_environment;
|
||||
callee_context->lexical_environment = caller_context.lexical_environment;
|
||||
callee_context->variable_environment = caller_context.variable_environment;
|
||||
// Note: Keeping the private environment is probably only needed because of async methods in classes
|
||||
// calling async_block_start which goes through a NativeFunction here.
|
||||
callee_context.private_environment = caller_context.private_environment;
|
||||
callee_context->private_environment = caller_context.private_environment;
|
||||
|
||||
// NOTE: This is a LibJS specific hack for NativeFunction to inherit the strictness of its caller.
|
||||
callee_context.is_strict_mode = vm.in_strict_mode();
|
||||
callee_context->is_strict_mode = vm.in_strict_mode();
|
||||
|
||||
// </8.> --------------------------------------------------------------------------
|
||||
|
||||
// 9. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(callee_context, {}));
|
||||
TRY(vm.push_execution_context(*callee_context, {}));
|
||||
|
||||
// 10. Let result be the Completion Record that is the result of evaluating F in a manner that conforms to the specification of F. thisArgument is the this value, argumentsList provides the named parameters, and the NewTarget value is undefined.
|
||||
auto result = call();
|
||||
|
@ -185,11 +185,11 @@ ThrowCompletionOr<NonnullGCPtr<Object>> NativeFunction::internal_construct(Reado
|
|||
// NOTE: We don't support this concept yet.
|
||||
|
||||
// 3. Let calleeContext be a new execution context.
|
||||
ExecutionContext callee_context(heap());
|
||||
auto callee_context = ExecutionContext::create(heap());
|
||||
|
||||
// 4. Set the Function of calleeContext to F.
|
||||
callee_context.function = this;
|
||||
callee_context.function_name = m_name_string;
|
||||
callee_context->function = this;
|
||||
callee_context->function_name = m_name_string;
|
||||
|
||||
// 5. Let calleeRealm be F.[[Realm]].
|
||||
auto callee_realm = m_realm;
|
||||
|
@ -203,25 +203,25 @@ ThrowCompletionOr<NonnullGCPtr<Object>> NativeFunction::internal_construct(Reado
|
|||
VERIFY(callee_realm);
|
||||
|
||||
// 6. Set the Realm of calleeContext to calleeRealm.
|
||||
callee_context.realm = callee_realm;
|
||||
callee_context->realm = callee_realm;
|
||||
|
||||
// 7. Set the ScriptOrModule of calleeContext to null.
|
||||
// Note: This is already the default value.
|
||||
|
||||
// 8. Perform any necessary implementation-defined initialization of calleeContext.
|
||||
callee_context.arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context->instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
|
||||
callee_context.lexical_environment = caller_context.lexical_environment;
|
||||
callee_context.variable_environment = caller_context.variable_environment;
|
||||
callee_context->lexical_environment = caller_context.lexical_environment;
|
||||
callee_context->variable_environment = caller_context.variable_environment;
|
||||
|
||||
// NOTE: This is a LibJS specific hack for NativeFunction to inherit the strictness of its caller.
|
||||
callee_context.is_strict_mode = vm.in_strict_mode();
|
||||
callee_context->is_strict_mode = vm.in_strict_mode();
|
||||
|
||||
// </8.> --------------------------------------------------------------------------
|
||||
|
||||
// 9. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(callee_context, {}));
|
||||
TRY(vm.push_execution_context(*callee_context, {}));
|
||||
|
||||
// 10. Let result be the Completion Record that is the result of evaluating F in a manner that conforms to the specification of F. The this value is uninitialized, argumentsList provides the named parameters, and newTarget provides the NewTarget value.
|
||||
auto result = construct(new_target);
|
||||
|
|
|
@ -42,7 +42,7 @@ ThrowCompletionOr<NonnullOwnPtr<ExecutionContext>> Realm::initialize_host_define
|
|||
auto realm = MUST_OR_THROW_OOM(Realm::create(vm));
|
||||
|
||||
// 2. Let newContext be a new execution context.
|
||||
auto new_context = make<ExecutionContext>(vm.heap());
|
||||
auto new_context = ExecutionContext::create(vm.heap());
|
||||
|
||||
// 3. Set the Function of newContext to null.
|
||||
new_context->function = nullptr;
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace JS {
|
|||
|
||||
JS_DEFINE_ALLOCATOR(ShadowRealm);
|
||||
|
||||
ShadowRealm::ShadowRealm(Realm& shadow_realm, ExecutionContext execution_context, Object& prototype)
|
||||
ShadowRealm::ShadowRealm(Realm& shadow_realm, NonnullOwnPtr<ExecutionContext> execution_context, Object& prototype)
|
||||
: Object(ConstructWithPrototypeTag::Tag, prototype)
|
||||
, m_shadow_realm(shadow_realm)
|
||||
, m_execution_context(move(execution_context))
|
||||
|
@ -143,28 +143,28 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(VM& vm, StringView source_tex
|
|||
// NOTE: We don't support this concept yet.
|
||||
|
||||
// 9. Let evalContext be a new ECMAScript code execution context.
|
||||
auto eval_context = ExecutionContext { vm.heap() };
|
||||
auto eval_context = ExecutionContext::create(vm.heap());
|
||||
|
||||
// 10. Set evalContext's Function to null.
|
||||
eval_context.function = nullptr;
|
||||
eval_context->function = nullptr;
|
||||
|
||||
// 11. Set evalContext's Realm to evalRealm.
|
||||
eval_context.realm = &eval_realm;
|
||||
eval_context->realm = &eval_realm;
|
||||
|
||||
// 12. Set evalContext's ScriptOrModule to null.
|
||||
// Note: This is already the default value.
|
||||
|
||||
// 13. Set evalContext's VariableEnvironment to varEnv.
|
||||
eval_context.variable_environment = variable_environment;
|
||||
eval_context->variable_environment = variable_environment;
|
||||
|
||||
// 14. Set evalContext's LexicalEnvironment to lexEnv.
|
||||
eval_context.lexical_environment = lexical_environment;
|
||||
eval_context->lexical_environment = lexical_environment;
|
||||
|
||||
// Non-standard
|
||||
eval_context.is_strict_mode = strict_eval;
|
||||
eval_context->is_strict_mode = strict_eval;
|
||||
|
||||
// 15. Push evalContext onto the execution context stack; evalContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(eval_context, {}));
|
||||
TRY(vm.push_execution_context(*eval_context, {}));
|
||||
|
||||
// 16. Let result be Completion(EvalDeclarationInstantiation(body, varEnv, lexEnv, null, strictEval)).
|
||||
auto eval_result = eval_declaration_instantiation(vm, program, variable_environment, lexical_environment, nullptr, strict_eval);
|
||||
|
|
|
@ -22,17 +22,17 @@ public:
|
|||
|
||||
[[nodiscard]] Realm const& shadow_realm() const { return m_shadow_realm; }
|
||||
[[nodiscard]] Realm& shadow_realm() { return m_shadow_realm; }
|
||||
[[nodiscard]] ExecutionContext const& execution_context() const { return m_execution_context; }
|
||||
[[nodiscard]] ExecutionContext& execution_context() { return m_execution_context; }
|
||||
[[nodiscard]] ExecutionContext const& execution_context() const { return *m_execution_context; }
|
||||
[[nodiscard]] ExecutionContext& execution_context() { return *m_execution_context; }
|
||||
|
||||
private:
|
||||
ShadowRealm(Realm&, ExecutionContext, Object& prototype);
|
||||
ShadowRealm(Realm&, NonnullOwnPtr<ExecutionContext>, Object& prototype);
|
||||
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
// 3.5 Properties of ShadowRealm Instances, https://tc39.es/proposal-shadowrealm/#sec-properties-of-shadowrealm-instances
|
||||
NonnullGCPtr<Realm> m_shadow_realm; // [[ShadowRealm]]
|
||||
ExecutionContext m_execution_context; // [[ExecutionContext]]
|
||||
NonnullGCPtr<Realm> m_shadow_realm; // [[ShadowRealm]]
|
||||
NonnullOwnPtr<ExecutionContext> m_execution_context; // [[ExecutionContext]]
|
||||
};
|
||||
|
||||
ThrowCompletionOr<void> copy_name_and_length(VM&, FunctionObject& function, FunctionObject& target, Optional<StringView> prefix = {}, Optional<unsigned> arg_count = {});
|
||||
|
|
|
@ -47,13 +47,13 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ShadowRealmConstructor::construct(Functi
|
|||
auto realm = MUST_OR_THROW_OOM(Realm::create(vm));
|
||||
|
||||
// 5. Let context be a new execution context.
|
||||
auto context = ExecutionContext { vm.heap() };
|
||||
auto context = ExecutionContext::create(vm.heap());
|
||||
|
||||
// 6. Set the Function of context to null.
|
||||
context.function = nullptr;
|
||||
context->function = nullptr;
|
||||
|
||||
// 7. Set the Realm of context to realmRec.
|
||||
context.realm = realm;
|
||||
context->realm = realm;
|
||||
|
||||
// 8. Set the ScriptOrModule of context to null.
|
||||
// Note: This is already the default value.
|
||||
|
|
|
@ -199,31 +199,6 @@ void VM::gather_roots(HashMap<Cell*, HeapRoot>& roots)
|
|||
for (auto string : m_single_ascii_character_strings)
|
||||
roots.set(string, HeapRoot { .type = HeapRoot::Type::VM });
|
||||
|
||||
auto gather_roots_from_execution_context_stack = [&roots](Vector<ExecutionContext*> const& stack) {
|
||||
for (auto& execution_context : stack) {
|
||||
if (execution_context->this_value.is_cell())
|
||||
roots.set(&execution_context->this_value.as_cell(), { .type = HeapRoot::Type::VM });
|
||||
for (auto& argument : execution_context->arguments) {
|
||||
if (argument.is_cell())
|
||||
roots.set(&argument.as_cell(), HeapRoot { .type = HeapRoot::Type::VM });
|
||||
}
|
||||
roots.set(execution_context->lexical_environment, HeapRoot { .type = HeapRoot::Type::VM });
|
||||
roots.set(execution_context->variable_environment, HeapRoot { .type = HeapRoot::Type::VM });
|
||||
roots.set(execution_context->private_environment, HeapRoot { .type = HeapRoot::Type::VM });
|
||||
if (auto context_owner = execution_context->context_owner)
|
||||
roots.set(context_owner, HeapRoot { .type = HeapRoot::Type::VM });
|
||||
execution_context->script_or_module.visit(
|
||||
[](Empty) {},
|
||||
[&](auto& script_or_module) {
|
||||
roots.set(script_or_module.ptr(), HeapRoot { .type = HeapRoot::Type::VM });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
gather_roots_from_execution_context_stack(m_execution_context_stack);
|
||||
for (auto& saved_stack : m_saved_execution_context_stacks)
|
||||
gather_roots_from_execution_context_stack(saved_stack);
|
||||
|
||||
#define __JS_ENUMERATE(SymbolName, snake_name) \
|
||||
roots.set(m_well_known_symbols.snake_name, HeapRoot { .type = HeapRoot::Type::VM });
|
||||
JS_ENUMERATE_WELL_KNOWN_SYMBOLS
|
||||
|
|
|
@ -150,8 +150,7 @@ public:
|
|||
{
|
||||
if (m_execution_context_stack.is_empty())
|
||||
return {};
|
||||
auto& arguments = running_execution_context().arguments;
|
||||
return index < arguments.size() ? arguments[index] : js_undefined();
|
||||
return running_execution_context().argument(index);
|
||||
}
|
||||
|
||||
Value this_value() const
|
||||
|
|
|
@ -343,6 +343,12 @@ public:
|
|||
return *extract_pointer<Cell>();
|
||||
}
|
||||
|
||||
Cell& as_cell() const
|
||||
{
|
||||
VERIFY(is_cell());
|
||||
return *extract_pointer<Cell>();
|
||||
}
|
||||
|
||||
Accessor& as_accessor()
|
||||
{
|
||||
VERIFY(is_accessor());
|
||||
|
|
|
@ -62,11 +62,11 @@ ThrowCompletionOr<Value> WrappedFunction::internal_call(Value this_argument, Rea
|
|||
// NOTE: No-op, kept by the VM in its execution context stack.
|
||||
|
||||
// 2. Let calleeContext be PrepareForWrappedFunctionCall(F).
|
||||
ExecutionContext callee_context { vm.heap() };
|
||||
prepare_for_wrapped_function_call(*this, callee_context);
|
||||
auto callee_context = ExecutionContext::create(vm.heap());
|
||||
prepare_for_wrapped_function_call(*this, *callee_context);
|
||||
|
||||
// 3. Assert: calleeContext is now the running execution context.
|
||||
VERIFY(&vm.running_execution_context() == &callee_context);
|
||||
VERIFY(&vm.running_execution_context() == callee_context);
|
||||
|
||||
// 4. Let result be OrdinaryWrappedFunctionCall(F, thisArgument, argumentsList).
|
||||
auto result = ordinary_wrapped_function_call(*this, this_argument, arguments_list);
|
||||
|
|
|
@ -108,7 +108,7 @@ SourceTextModule::SourceTextModule(Realm& realm, StringView filename, Script::Ho
|
|||
RefPtr<ExportStatement const> default_export)
|
||||
: CyclicModule(realm, filename, has_top_level_await, move(requested_modules), host_defined)
|
||||
, m_ecmascript_code(move(body))
|
||||
, m_execution_context(realm.heap())
|
||||
, m_execution_context(ExecutionContext::create(realm.heap()))
|
||||
, m_import_entries(move(import_entries))
|
||||
, m_local_export_entries(move(local_export_entries))
|
||||
, m_indirect_export_entries(move(indirect_export_entries))
|
||||
|
@ -410,16 +410,16 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
|
|||
// Note: This must be true because we use a reference.
|
||||
|
||||
// 11. Set the Realm of moduleContext to module.[[Realm]].
|
||||
m_execution_context.realm = &realm();
|
||||
m_execution_context->realm = &realm();
|
||||
|
||||
// 12. Set the ScriptOrModule of moduleContext to module.
|
||||
m_execution_context.script_or_module = NonnullGCPtr<Module>(*this);
|
||||
m_execution_context->script_or_module = NonnullGCPtr<Module>(*this);
|
||||
|
||||
// 13. Set the VariableEnvironment of moduleContext to module.[[Environment]].
|
||||
m_execution_context.variable_environment = environment;
|
||||
m_execution_context->variable_environment = environment;
|
||||
|
||||
// 14. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
|
||||
m_execution_context.lexical_environment = environment;
|
||||
m_execution_context->lexical_environment = environment;
|
||||
|
||||
// 15. Set the PrivateEnvironment of moduleContext to null.
|
||||
|
||||
|
@ -427,7 +427,7 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
|
|||
// Note: We're already working on that one.
|
||||
|
||||
// 17. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(m_execution_context, {}));
|
||||
TRY(vm.push_execution_context(*m_execution_context, {}));
|
||||
|
||||
// 18. Let code be module.[[ECMAScriptCode]].
|
||||
|
||||
|
@ -662,27 +662,27 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GCPtr<PromiseCa
|
|||
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] SourceTextModule::execute_module({}, PromiseCapability @ {})", filename(), capability.ptr());
|
||||
|
||||
// 1. Let moduleContext be a new ECMAScript code execution context.
|
||||
ExecutionContext module_context { vm.heap() };
|
||||
auto module_context = ExecutionContext::create(vm.heap());
|
||||
|
||||
// Note: This is not in the spec but we require it.
|
||||
module_context.is_strict_mode = true;
|
||||
module_context->is_strict_mode = true;
|
||||
|
||||
// 2. Set the Function of moduleContext to null.
|
||||
|
||||
// 3. Set the Realm of moduleContext to module.[[Realm]].
|
||||
module_context.realm = &realm();
|
||||
module_context->realm = &realm();
|
||||
|
||||
// 4. Set the ScriptOrModule of moduleContext to module.
|
||||
module_context.script_or_module = NonnullGCPtr<Module>(*this);
|
||||
module_context->script_or_module = NonnullGCPtr<Module>(*this);
|
||||
|
||||
// 5. Assert: module has been linked and declarations in its module environment have been instantiated.
|
||||
VERIFY(m_status != ModuleStatus::Unlinked && m_status != ModuleStatus::Linking && environment());
|
||||
|
||||
// 6. Set the VariableEnvironment of moduleContext to module.[[Environment]].
|
||||
module_context.variable_environment = environment();
|
||||
module_context->variable_environment = environment();
|
||||
|
||||
// 7. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
|
||||
module_context.lexical_environment = environment();
|
||||
module_context->lexical_environment = environment();
|
||||
|
||||
// 8. Suspend the currently running execution context.
|
||||
// FIXME: We don't have suspend yet
|
||||
|
@ -692,7 +692,7 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GCPtr<PromiseCa
|
|||
// a. Assert: capability is not present.
|
||||
VERIFY(capability == nullptr);
|
||||
// b. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(module_context, {}));
|
||||
TRY(vm.push_execution_context(*module_context, {}));
|
||||
|
||||
// c. Let result be the result of evaluating module.[[ECMAScriptCode]].
|
||||
Completion result;
|
||||
|
@ -713,7 +713,7 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GCPtr<PromiseCa
|
|||
}
|
||||
|
||||
// d. Let env be moduleContext's LexicalEnvironment.
|
||||
auto env = module_context.lexical_environment;
|
||||
auto env = module_context->lexical_environment;
|
||||
VERIFY(is<DeclarativeEnvironment>(*env));
|
||||
|
||||
// e. Set result to DisposeResources(env, result).
|
||||
|
@ -737,7 +737,7 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GCPtr<PromiseCa
|
|||
VERIFY(capability != nullptr);
|
||||
|
||||
// b. Perform AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext).
|
||||
async_block_start<NonnullRefPtr<Statement const>>(vm, m_ecmascript_code, *capability, module_context);
|
||||
async_block_start<NonnullRefPtr<Statement const>>(vm, m_ecmascript_code, *capability, *module_context);
|
||||
}
|
||||
|
||||
// 11. Return unused.
|
||||
|
|
|
@ -41,13 +41,13 @@ private:
|
|||
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
NonnullRefPtr<Program> m_ecmascript_code; // [[ECMAScriptCode]]
|
||||
ExecutionContext m_execution_context; // [[Context]]
|
||||
GCPtr<Object> m_import_meta; // [[ImportMeta]]
|
||||
Vector<ImportEntry> m_import_entries; // [[ImportEntries]]
|
||||
Vector<ExportEntry> m_local_export_entries; // [[LocalExportEntries]]
|
||||
Vector<ExportEntry> m_indirect_export_entries; // [[IndirectExportEntries]]
|
||||
Vector<ExportEntry> m_star_export_entries; // [[StarExportEntries]]
|
||||
NonnullRefPtr<Program> m_ecmascript_code; // [[ECMAScriptCode]]
|
||||
NonnullOwnPtr<ExecutionContext> m_execution_context; // [[Context]]
|
||||
GCPtr<Object> m_import_meta; // [[ImportMeta]]
|
||||
Vector<ImportEntry> m_import_entries; // [[ImportEntries]]
|
||||
Vector<ExportEntry> m_local_export_entries; // [[LocalExportEntries]]
|
||||
Vector<ExportEntry> m_indirect_export_entries; // [[IndirectExportEntries]]
|
||||
Vector<ExportEntry> m_star_export_entries; // [[StarExportEntries]]
|
||||
|
||||
RefPtr<ExportStatement const> m_default_export; // Note: Not from the spec
|
||||
};
|
||||
|
|
|
@ -79,25 +79,25 @@ ThrowCompletionOr<Promise*> SyntheticModule::evaluate(VM& vm)
|
|||
// FIXME: We don't have suspend yet.
|
||||
|
||||
// 2. Let moduleContext be a new ECMAScript code execution context.
|
||||
ExecutionContext module_context { vm.heap() };
|
||||
auto module_context = ExecutionContext::create(vm.heap());
|
||||
|
||||
// 3. Set the Function of moduleContext to null.
|
||||
// Note: This is the default value.
|
||||
|
||||
// 4. Set the Realm of moduleContext to module.[[Realm]].
|
||||
module_context.realm = &realm();
|
||||
module_context->realm = &realm();
|
||||
|
||||
// 5. Set the ScriptOrModule of moduleContext to module.
|
||||
module_context.script_or_module = NonnullGCPtr<Module>(*this);
|
||||
module_context->script_or_module = NonnullGCPtr<Module>(*this);
|
||||
|
||||
// 6. Set the VariableEnvironment of moduleContext to module.[[Environment]].
|
||||
module_context.variable_environment = environment();
|
||||
module_context->variable_environment = environment();
|
||||
|
||||
// 7. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
|
||||
module_context.lexical_environment = environment();
|
||||
module_context->lexical_environment = environment();
|
||||
|
||||
// 8. Push moduleContext on to the execution context stack; moduleContext is now the running execution context.
|
||||
TRY(vm.push_execution_context(module_context, {}));
|
||||
TRY(vm.push_execution_context(*module_context, {}));
|
||||
|
||||
// 9. Let result be the result of performing module.[[EvaluationSteps]](module).
|
||||
auto result = m_evaluation_steps(*this);
|
||||
|
|
|
@ -189,7 +189,7 @@ ErrorOr<void> initialize_main_thread_vm()
|
|||
};
|
||||
|
||||
// 8.1.5.4.1 HostCallJobCallback(callback, V, argumentsList), https://html.spec.whatwg.org/multipage/webappapis.html#hostcalljobcallback
|
||||
s_main_thread_vm->host_call_job_callback = [](JS::JobCallback& callback, JS::Value this_value, JS::MarkedVector<JS::Value> arguments_list) {
|
||||
s_main_thread_vm->host_call_job_callback = [](JS::JobCallback& callback, JS::Value this_value, ReadonlySpan<JS::Value> arguments_list) {
|
||||
auto& callback_host_defined = verify_cast<WebEngineCustomJobCallbackData>(*callback.custom_data);
|
||||
|
||||
// 1. Let incumbent settings be callback.[[HostDefined]].[[IncumbentSettings]]. (NOTE: Not necessary)
|
||||
|
@ -203,7 +203,7 @@ ErrorOr<void> initialize_main_thread_vm()
|
|||
s_main_thread_vm->push_execution_context(*callback_host_defined.active_script_context);
|
||||
|
||||
// 5. Let result be Call(callback.[[Callback]], V, argumentsList).
|
||||
auto result = JS::call(*s_main_thread_vm, *callback.callback.cell(), this_value, move(arguments_list));
|
||||
auto result = JS::call(*s_main_thread_vm, *callback.callback.cell(), this_value, arguments_list);
|
||||
|
||||
// 6. If script execution context is not null, then pop script execution context from the JavaScript execution context stack.
|
||||
if (callback_host_defined.active_script_context) {
|
||||
|
@ -267,7 +267,7 @@ ErrorOr<void> initialize_main_thread_vm()
|
|||
// NOTE: This keeps job_settings alive by keeping realm alive, which is holding onto job_settings.
|
||||
HTML::queue_a_microtask(script ? script->settings_object().responsible_document().ptr() : nullptr, [job_settings, job = move(job), script_or_module = move(script_or_module)] {
|
||||
// The dummy execution context has to be kept up here to keep it alive for the duration of the function.
|
||||
Optional<JS::ExecutionContext> dummy_execution_context;
|
||||
OwnPtr<JS::ExecutionContext> dummy_execution_context;
|
||||
|
||||
if (job_settings) {
|
||||
// 1. If job settings is not null, then check if we can run script with job settings. If this returns "do not run" then return.
|
||||
|
@ -289,9 +289,9 @@ ErrorOr<void> initialize_main_thread_vm()
|
|||
// FIXME: We need to setup a dummy execution context in case a JS::NativeFunction is called when processing the job.
|
||||
// This is because JS::NativeFunction::call excepts something to be on the execution context stack to be able to get the caller context to initialize the environment.
|
||||
// Do note that the JS spec gives _no_ guarantee that the execution context stack has something on it if HostEnqueuePromiseJob was called with a null realm: https://tc39.es/ecma262/#job-preparedtoevaluatecode
|
||||
dummy_execution_context = JS::ExecutionContext { s_main_thread_vm->heap() };
|
||||
dummy_execution_context = JS::ExecutionContext::create(s_main_thread_vm->heap());
|
||||
dummy_execution_context->script_or_module = script_or_module;
|
||||
s_main_thread_vm->push_execution_context(dummy_execution_context.value());
|
||||
s_main_thread_vm->push_execution_context(*dummy_execution_context);
|
||||
}
|
||||
|
||||
// 3. Let result be job().
|
||||
|
@ -331,7 +331,7 @@ ErrorOr<void> initialize_main_thread_vm()
|
|||
// 4. If active script is not null, set script execution context to a new JavaScript execution context, with its Function field set to null,
|
||||
// its Realm field set to active script's settings object's Realm, and its ScriptOrModule set to active script's record.
|
||||
if (script) {
|
||||
script_execution_context = adopt_own(*new JS::ExecutionContext(s_main_thread_vm->heap()));
|
||||
script_execution_context = JS::ExecutionContext::create(s_main_thread_vm->heap());
|
||||
script_execution_context->function = nullptr;
|
||||
script_execution_context->realm = &script->settings_object().realm();
|
||||
if (is<HTML::ClassicScript>(script)) {
|
||||
|
|
|
@ -193,7 +193,7 @@ JS::ThrowCompletionOr<size_t> instantiate_module(JS::VM& vm, Wasm::Module const&
|
|||
for (auto& entry : arguments)
|
||||
argument_values.append(to_js_value(vm, entry));
|
||||
|
||||
auto result = TRY(JS::call(vm, function, JS::js_undefined(), move(argument_values)));
|
||||
auto result = TRY(JS::call(vm, function, JS::js_undefined(), argument_values.span()));
|
||||
if (type.results().is_empty())
|
||||
return Wasm::Result { Vector<Wasm::Value> {} };
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ JS::Completion call_user_object_operation(WebIDL::CallbackType& callback, Deprec
|
|||
// 12. Let callResult be Call(X, thisArg, esArgs).
|
||||
VERIFY(actual_function_object);
|
||||
auto& vm = object->vm();
|
||||
auto call_result = JS::call(vm, verify_cast<JS::FunctionObject>(*actual_function_object), this_argument.value(), move(args));
|
||||
auto call_result = JS::call(vm, verify_cast<JS::FunctionObject>(*actual_function_object), this_argument.value(), args.span());
|
||||
|
||||
// 13. If callResult is an abrupt completion, set completion to callResult and jump to the step labeled return.
|
||||
if (call_result.is_throw_completion()) {
|
||||
|
@ -233,7 +233,7 @@ JS::Completion invoke_callback(WebIDL::CallbackType& callback, Optional<JS::Valu
|
|||
|
||||
// 11. Let callResult be Call(F, thisArg, esArgs).
|
||||
auto& vm = function_object->vm();
|
||||
auto call_result = JS::call(vm, verify_cast<JS::FunctionObject>(*function_object), this_argument.value(), move(args));
|
||||
auto call_result = JS::call(vm, verify_cast<JS::FunctionObject>(*function_object), this_argument.value(), args.span());
|
||||
|
||||
// 12. If callResult is an abrupt completion, set completion to callResult and jump to the step labeled return.
|
||||
if (call_result.is_throw_completion()) {
|
||||
|
@ -280,7 +280,7 @@ JS::Completion construct(WebIDL::CallbackType& callback, JS::MarkedVector<JS::Va
|
|||
|
||||
// 10. Let callResult be Completion(Construct(F, esArgs)).
|
||||
auto& vm = function_object->vm();
|
||||
auto call_result = JS::construct(vm, verify_cast<JS::FunctionObject>(*function_object), move(args));
|
||||
auto call_result = JS::construct(vm, verify_cast<JS::FunctionObject>(*function_object), args.span());
|
||||
|
||||
// 11. If callResult is an abrupt completion, set completion to callResult and jump to the step labeled return.
|
||||
if (call_result.is_throw_completion()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue