/* * Copyright (c) 2026, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Opaque parsed program handle from the Rust pipeline. namespace JS::FFI { struct ParsedProgram; struct CompiledProgram; struct CompiledFunction; struct DecodedBytecodeCacheBlob; } namespace JS::RustIntegration { // Result type for compile_script(). // NB: Uses GC::Root to prevent collection while the result is in transit // between compile_script() and the Script constructor. struct ScriptResult { GC::Root executable; Vector> shared_function_data; bool is_strict_mode { false }; Vector lexical_names; Vector var_names; struct FunctionToInitialize { GC::Root shared_data; Utf16FlyString name; }; Vector functions_to_initialize; HashTable declared_function_names; Vector var_scoped_names; Vector annex_b_candidate_names; Vector lexical_bindings; }; // Result type for compile_eval(). // NB: Uses GC::Root to prevent collection while the result is in transit. struct EvalResult { GC::Root executable; bool is_strict_mode { false }; EvalDeclarationData declaration_data; }; // Result type for compile_module(). // NB: Uses GC::Root to prevent collection while the result is in transit. struct ModuleResult { bool has_top_level_await { false }; Vector requested_modules; Vector import_entries; Vector local_export_entries; Vector indirect_export_entries; Vector star_export_entries; Optional default_export_binding_name; Vector var_declared_names; Vector lexical_bindings; struct FunctionToInitialize { GC::Root shared_data; Utf16FlyString name; }; Vector functions_to_initialize; GC::Root executable; Vector> shared_function_data; GC::Root tla_shared_data; }; // Parse a program (script or module) without GC interaction. Thread-safe. JS_API FFI::ParsedProgram* parse_program(u16 const* utf16_data, size_t length_in_code_units, ProgramType type, size_t line_number_offset = 0); // Compile a parsed program to bytecode without touching the VM or GC. Thread-safe. JS_API FFI::CompiledProgram* compile_parsed_program_off_thread(FFI::ParsedProgram* parsed, size_t length_in_code_units); // Fully compile a parsed program to bytecode without touching the VM or GC. Thread-safe. JS_API FFI::CompiledProgram* compile_parsed_program_fully_off_thread(FFI::ParsedProgram* parsed, size_t length_in_code_units); // Check if a parsed program has errors. Does not consume the program. JS_API bool parsed_program_has_errors(FFI::ParsedProgram const*); // Free a parsed program without compiling it. JS_API void free_parsed_program(FFI::ParsedProgram*); // Free a compiled program without materializing it. JS_API void free_compiled_program(FFI::CompiledProgram*); // Serialize a fully compiled program into a versioned bytecode cache blob. JS_API ByteBuffer serialize_compiled_program_for_bytecode_cache(FFI::CompiledProgram const&, ProgramType, ReadonlyBytes source_hash); // Decode an ImmutableBytes-backed bytecode cache blob into a parser-free cache handle. // The returned blob can be validated off-thread before main-thread materialization. JS_API FFI::DecodedBytecodeCacheBlob* decode_bytecode_cache_blob(Core::ImmutableBytes, ProgramType, ReadonlyBytes source_hash, Core::EventLoop&); // Validate a decoded bytecode cache blob before materialization. Thread-safe. JS_API bool validate_decoded_bytecode_cache_blob(FFI::DecodedBytecodeCacheBlob*, size_t source_length); // Free a decoded bytecode cache blob. JS_API void free_decoded_bytecode_cache_blob(FFI::DecodedBytecodeCacheBlob*); // Materialize a decoded script bytecode cache. Must be called on the main thread. JS_API Optional>> materialize_bytecode_cache_script(DecodedBytecodeCache&, NonnullRefPtr source_code, Realm&); // Materialize a decoded module bytecode cache. Must be called on the main thread. JS_API Optional>> materialize_bytecode_cache_module(DecodedBytecodeCache&, NonnullRefPtr source_code, Realm&); struct ModuleBytecodeCacheInstallResult { GC::Root executable; GC::Root top_level_await_executable; }; // Try to install a decoded script bytecode cache into an existing script executable tree. // Must be called on the main thread. JS_API GC::Ptr try_install_bytecode_cache_script(DecodedBytecodeCache&, NonnullRefPtr source_code, Realm&, Bytecode::Executable& existing_executable, ReadonlySpan existing_shared_function_data); // Install a decoded script bytecode cache produced by the current process. // Must be called on the main thread. JS_API GC::Ref install_generated_bytecode_cache_script(DecodedBytecodeCache&, NonnullRefPtr source_code, Realm&, Bytecode::Executable& existing_executable, ReadonlySpan existing_shared_function_data); // Try to install a decoded module bytecode cache into an existing module executable tree. // Must be called on the main thread. JS_API Optional try_install_bytecode_cache_module(DecodedBytecodeCache&, NonnullRefPtr source_code, Realm&, Bytecode::Executable* existing_executable, ReadonlySpan existing_shared_function_data, SharedFunctionInstanceData* existing_top_level_await_shared_data); // Install a decoded module bytecode cache produced by the current process. // Must be called on the main thread. JS_API ModuleBytecodeCacheInstallResult install_generated_bytecode_cache_module(DecodedBytecodeCache&, NonnullRefPtr source_code, Realm&, Bytecode::Executable* existing_executable, ReadonlySpan existing_shared_function_data, SharedFunctionInstanceData* existing_top_level_await_shared_data); // Compile a previously parsed script. Must be called on the main thread. // Consumes and frees the Rust ParsedProgram. // Returns nullopt if Rust is not available. Optional>> compile_parsed_script(FFI::ParsedProgram* parsed, NonnullRefPtr source_code, Realm& realm); // Materialize a previously compiled script. Must be called on the main thread. // Consumes and frees the Rust CompiledProgram. Optional>> materialize_compiled_script(FFI::CompiledProgram* compiled, NonnullRefPtr source_code, Realm& realm); // Compile a script. Returns nullopt if Rust is not available. Optional>> compile_script(Utf16View source_text, Realm& realm, Utf16View display_filename, size_t line_number_offset); // Compile eval code. Returns nullopt if Rust is not available. // On success, the executable's name is set to "eval". Optional> compile_eval( PrimitiveString& code_string, VM& vm, CallerMode strict_caller, bool in_function, bool in_method, bool in_derived_constructor, bool in_class_field_initializer); // Compile a previously parsed module. Must be called on the main thread. // Consumes and frees the Rust ParsedProgram. // Returns nullopt if Rust is not available. Optional>> compile_parsed_module(FFI::ParsedProgram* parsed, NonnullRefPtr source_code, Realm& realm); // Materialize a previously compiled module. Must be called on the main thread. // Consumes and frees the Rust CompiledProgram. Optional>> materialize_compiled_module(FFI::CompiledProgram* compiled, NonnullRefPtr source_code, Realm& realm); // Compile a module. Returns nullopt if Rust is not available. Optional>> compile_module(Utf16View source_text, Realm& realm, Utf16View display_filename); Optional>> compile_module(NonnullRefPtr, Realm& realm); // Compile a dynamic function (new Function()). // On success, returns a SharedFunctionInstanceData with source_text set. JS_API Optional, Utf16String>> compile_dynamic_function( VM& vm, Utf16View source_text, Utf16View parameters_string, Utf16View body_parse_string, FunctionKind kind); // Compile a builtin JS file. Returns nullopt if Rust is not available. Optional>> compile_builtin_file( Utf16View script_text, VM& vm); // Compile a function body for lazy compilation. // Returns nullptr if Rust is not available or the SFD doesn't use Rust compilation. GC::Ptr compile_function(VM& vm, SharedFunctionInstanceData& shared_data, bool builtin_abstract_operations_enabled); JS_API void dump_bytecode(StringBuilder&, Bytecode::Executable const&); JS_API size_t count_bytecode_basic_blocks(Bytecode::Executable const&); JS_API void* clone_function_ast(void const*); JS_API FFI::CompiledFunction* compile_function_off_thread(void* function_ast, size_t length_in_code_units, bool builtin_abstract_operations_enabled); // Attach a previously compiled function for lazy materialization. JS_API void materialize_compiled_function(FFI::CompiledFunction*, VM&, SourceCode const&, SharedFunctionInstanceData&); JS_API void free_compiled_function(FFI::CompiledFunction*); // Free a Rust decoded bytecode cache executable pointer. No-op if null. void free_cached_bytecode_executable(void*); // Free a Rust precompiled bytecode executable pointer. No-op if null. void free_precompiled_bytecode_executable(void*); // Free a Rust function AST pointer. No-op if Rust is not available. void free_function_ast(void* ast); }