/* * Copyright (c) 2020-2024, Andreas Kling * Copyright (c) 2020-2021, Linus Groh * Copyright (c) 2022, Luke Wilde * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include namespace JS { using ScriptOrModule = Variant, GC::Ref>; struct CachedSourceRange : public RefCounted { CachedSourceRange(size_t program_counter, Variant source_range) : program_counter(program_counter) , source_range(move(source_range)) { } size_t program_counter { 0 }; Variant source_range; }; // 9.4 Execution Contexts, https://tc39.es/ecma262/#sec-execution-contexts struct ExecutionContext { static NonnullOwnPtr create(u32 registers_and_constants_and_locals_count, u32 arguments_count); [[nodiscard]] NonnullOwnPtr copy() const; ~ExecutionContext(); void visit_edges(Cell::Visitor&); private: friend class ExecutionContextAllocator; ExecutionContext(); public: void operator delete(void* ptr); GC::Ptr function; // [[Function]] GC::Ptr realm; // [[Realm]] ScriptOrModule script_or_module; // [[ScriptOrModule]] GC::Ptr lexical_environment; // [[LexicalEnvironment]] GC::Ptr variable_environment; // [[VariableEnvironment]] GC::Ptr private_environment; // [[PrivateEnvironment]] // Non-standard: This points at something that owns this ExecutionContext, in case it needs to be protected from GC. GC::Ptr context_owner; Optional program_counter; mutable RefPtr cached_source_range; GC::Ptr function_name; Optional this_value; GC::Ptr executable; // 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 { auto arguments_size = registers_and_constants_and_locals_and_arguments.size() - arguments_offset; if (index >= arguments_size) [[unlikely]] return js_undefined(); return registers_and_constants_and_locals_and_arguments[arguments_offset + index]; } Value& local(size_t index) { return registers_and_constants_and_locals_and_arguments[index]; } u32 arguments_offset { 0 }; u32 passed_argument_count { 0 }; bool is_strict_mode { false }; Span arguments() { return registers_and_constants_and_locals_and_arguments.span().slice(arguments_offset); } ReadonlySpan arguments() const { return registers_and_constants_and_locals_and_arguments.span().slice(arguments_offset); } private: friend class Bytecode::Interpreter; Vector registers_and_constants_and_locals_and_arguments; public: Vector unwind_contexts; Vector> previously_scheduled_jumps; Vector> saved_lexical_environments; }; struct StackTraceElement { ExecutionContext* execution_context; RefPtr source_range; }; }