A full-static compiling, running method and compiling system of a TypeScript executable file

CN122816644APending Publication Date: 2026-09-25CHENYIN (SHANGHAI) INFORMATION CO LTD
View PDF 0 Cites 0 Cited by

Patent Information

Application Number
CN202611189025.X
Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
Filing Date
2026-08-06
Publication Date
2026-09-25

AI Technical Summary

Technical Problem

[0003]上述现有技术方案存在以下技术缺陷:其一,所有基于JS引擎的方案(包括QuickJS的标记-清扫GC和V8的分代GC)都存在不可预测的GC暂停时间,不适用于医疗设备、工业控制、POS机等对实时性有严格要求的可执行文件场景

Benefits of technology

1、本发明通过跨编译器-运行时边界的统一NaN-tagging值编码,使编译器生成的机器码与运行时DLL之间直接传递64位浮点数值,无需编解码转换层,FFI调用零开销,extern“C”fn(f64)->f64直接对应x86-64的XMM寄存器调用约定。

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN122816644A_ABST
    Figure CN122816644A_ABST
Patent Text Reader

Abstract

The application provides a TypeScript executable file full static compiling, running method and compiling system, realizes complete static compiling and zero GC running of the TypeScript executable file from source code to independent executable file, and comprises the following steps: S1, parsing import / export statements of an entry file and all dependent modules, constructing a module dependency graph and sorting in topological order; S2, traversing all modules in topological order, and sequentially executing the following steps for each module: (1) parsing TypeScript source code into SWCAST; (2) converting SWCAST into a HirExpr expression list; (3) generating a corresponding CraneliftIR instruction sequence for each HirExpr, and generating COFF format binary data; S3, generating an x86-64 machine code format main wrapper function; S4, calling a Rust compiler to independently compile a PE loader, embedding code sections, data sections and read-only data sections of a binary module file into the PE loader, performing symbol analysis and double-type relocation, and generating an executable file.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This invention relates to the field of computer programming language technology, and more specifically, to a fully static compilation and execution method and compilation system for TypeScript executable files. Background Technology

[0002] The deployment and execution of TypeScript / JavaScript executables currently mainly rely on the following technical paths: interpreted execution or JIT (Just-In-Time) compilation based on engines such as V8 / SpiderMonkey; binding Chromium or system WebView based on frameworks such as Electron, Tauri, and NW.js; adding bytecode based on lightweight JS engines such as QuickJS and Hermes; and compiling a subset of TypeScript into WebAssembly based on AssemblyScript.

[0003] The existing technical solutions described above have the following technical drawbacks: First, all JS engine-based solutions (including QuickJS's mark-and-sweep GC and V8's generational GC) suffer from unpredictable GC pause times, making them unsuitable for executable file scenarios with strict real-time requirements, such as medical devices, industrial control systems, and POS machines. Second, bundling a complete JS engine or browser kernel results in excessively large executable file sizes (typically exceeding 100MB), requiring the parsing and compilation of a large amount of code during startup, leading to high startup latency. Third, existing solutions generally require Node.js / npm ecosystem support, resulting in complex deployment processes, difficult version management, and high operating system dependencies. Fourth, the rendering backends differ across platforms (GDI or Direct2D on Windows, X11 or Wayland on Linux, and SurfaceFlinger on Android), and each solution lacks a unified hardware acceleration abstraction layer, leading to high cross-platform portability costs.

[0004] In summary, existing deployment solutions for TypeScript / JavaScript executables suffer from technical problems such as unpredictable GC pauses, bloated executable file sizes, complex runtime dependencies, and fragmented cross-platform rendering. There is an urgent need for a TypeScript static compilation solution that can eliminate GC pauses and achieve runtime-independent execution. Summary of the Invention

[0005] The purpose of this invention is to provide a fully static compilation and execution method and compilation system for TypeScript executable files, enabling complete static compilation and zero-GC execution of TypeScript executable files from source code to standalone executable files.

[0006] To achieve the above objectives, the present invention provides the following technical solution: a fully static compilation method for TypeScript executable files, comprising the following steps: S1. Parse the import / export statements of the entry file and all dependent modules, construct the module dependency graph and sort it by topological order, assign a unique identifier to each module, and construct an export mapping table containing function exports and variable exports. S2. Traverse all modules in topological order and perform the following steps for each module in sequence: (1) Parse the TypeScript source code into SWCAST; (2) Convert SWCAST into a list of HirExpr expressions; (3) Generate a corresponding CraneliftIR instruction sequence for each HirExpr and generate COFF format binary data. The final output is a binary module file; S3. Generate the main wrapper function in x86-64 machine code format, call the initialization functions of all modules in topological order, and then call the entry main function to realize the initialization of modules in the order of dependencies; S4. Call the Rust compiler to independently compile a PE loader, embed the code segment, data segment, and read-only data segment of the binary module file into the PE loader, perform symbol resolution and dual-type relocation, and generate an executable file that can be run directly.

[0007] Step S1 of the present invention specifically includes the following steps: (1) The compiler loads the entry file and the TypeScript source files of all its dependent modules, and calls the SWC parser to parse the import / export statements for each source file; (2) Perform topological sorting through DFS postorder traversal, construct the module dependency graph, and enable TypeScript Barrel mode with circular dependencies; (3) Assign a unique numeric identifier to each module according to the topological order; (4) Construct the export mapping table.

[0008] Step S2 of the present invention specifically includes the following steps: (1) SWC parsing: Call swc_ecma_parser::parse_module() to parse the TypeScript source code into SWCAST; (2) HIR conversion: Convert SWCAST into a flat list of HirExpr expressions, each expression corresponding to one or more CraneliftIR instructions; (3) CraneliftIR code generation: Generate a corresponding CraneliftIR instruction sequence for each HirExpr, and directly generate COFF format binary data; (4) Delayed batch release: At the basic block construction point, the temporary string value references accumulated in the current basic block are batch-called to the js_release release function, and the return value is excluded from the list to be released, ensuring that the value is released in its defined basic block and satisfies Cranelift dominance constraints. (5) COFF target file output: The generated code segment, data segment, read-only data segment, symbol table and relocation table are packaged into a COFF format target file and written to a .tsnobj format binary module file.

[0009] Step S3 of the present invention specifically includes the following steps: (1) The function entry point first executes sub rsp,40 to allocate stack space, then generates call__tsn_module_init_{id} instruction for each module according to topological order to call its initialization function, and finally generates call main instruction to call the main function of the executable file entry point; (2) At the function exit, add rsp,40 and ret are executed to restore the stack and return; (3) Add the wrapper function and its symbol to the code segment and symbol table of the main entry module.

[0010] Step S4 of the present invention specifically includes the following steps: (1) Call the Rust compiler to compile the loader source code with zero third-party dependencies independently and output standalone-loader.exe; each module generates an independent .tsnobj file (containing code segment, data segment, read-only data segment and symbol / relocation table) during compilation. When the loader runs, it reads the manifest and each .tsnobj, loads its code segment, data segment and read-only data segment into the process memory and performs cross-module symbol resolution and relocation before execution.

[0011] (2) The loader performs 5-level priority symbol resolution at runtime: Level 1 searches the global symbol table of loaded modules, with the first registered symbol winning and duplicates not being overwritten; Level 2 searches the function center registered at runtime via js_register_function; Level 3 searches the export table of tsn_runtime.dll via GetProcAddress; Level 4 searches the export tables of all loaded extension DLLs in the order of loading; Level 5 uses the stub function that returns TAG_UNDEFINED. (3) After symbol resolution is completed, relocation corrections of two types, REL32 and ADDR64, are performed. Finally, the module initialization function is called in the topology order, followed by the main function.

[0012] In step S4 of this invention, the PE loading and symbol resolution process specifically includes the following steps: B1. Use the Rust compiler to compile the loader source code into a standalone PE executable file; B2. At runtime, load all binary module files, parse the segment size, symbol count, relocation count and entry module name metadata of each module in its header, allocate executable memory pages and read-write memory pages through VirtualAlloc, and copy the module's code segment, data segment and read-only data segment to the corresponding memory area. B3. Traverse the symbol tables and relocation tables of all modules and parse each symbol in a multi-priority order; B4. For each record in the relocation table, perform the corresponding address correction operation according to the relocation type; B5. Call the initialization functions of all modules in topological order. Each initialization function creates a namespace storage object for the module, executes the module's top-level statement, and sets the module's exported variables.

[0013] A method for running a TypeScript executable file, wherein the executable file is generated according to the above-described fully static compilation method, and the memory management process of the executable file includes the following steps: A1. Using unified NaN-tagging encoding, the encoding space of the IEEE754 double-precision floating-point number with all exponent bits set to 0x7FF and the mantissa being non-zero is divided into multiple type tag regions. The high 4 bits of each type tag store the type information, and the low 48 bits store the data index or pointer. This allows the compiler-generated machine code to directly transfer 64-bit floating-point values ​​with the runtime DLL without the need for encoding / decoding conversion. A2. Create a thread-local generic reference counting pool, each containing a slot vector and a list of free slots. When a value is allocated, a slot is obtained from the free list or a new slot is added and the reference count is initialized to 1. When a value is referenced, the reference count of the corresponding slot is incremented by 1. When a value is released, the reference count of the corresponding slot is decremented by 1. When the reference count drops to 0, the slot is marked as free and recycled to the free list. Sub-values ​​are released recursively. A3. When generating machine code, the compiler does not immediately call the release function for short-term temporary values, but accumulates them in the delayed release vector and releases them in batches at the boundaries of basic blocks; The memory management process of the executable file includes the following steps: C1. Receives style descriptions passed in from the JavaScript layer; C2. Based on the parsed style information, perform the complete Flex layout algorithm on the child nodes of the node; C3. Recursively traverse the virtual node tree starting from the root node. For each node, execute the following steps in sequence: parse style, calculate box model, draw its own style, handle absolute and fixed positioning child nodes, register event handlers, clip overflow content, and recursively render child nodes. C4. Convert all drawing operations into abstract rendering commands and add them to the processing queue. During frame rendering, sort all commands by z-index, traverse and call the corresponding Direct2D drawing primitives for rasterization, and finally submit the rendering results to the window.

[0014] In step C2 of this invention, the Flexbox layout algorithm specifically includes the following steps: Step 1: Determine the main axis and cross axis based on the flex-direction style property. row indicates that the main axis is horizontal and the cross axis is vertical, and column indicates that the main axis is vertical and the cross axis is horizontal. Step 2: For each child node, use the explicit flex-basis value first. When flex-basis is auto, fall back to the explicit width or height value. If there is no explicit value, use the content estimate value. Step 3: Calculate the sum of the base dimensions and spacing of all child nodes, and compare it with the main axis dimension of the container to obtain the remaining space; if the remaining space is positive and the total flex-grow coefficient is greater than zero, proceed to step 4; if the remaining space is negative and the total flex-shrink weighted coefficient is greater than zero, proceed to step 5. Step 4: Allocate the remaining space to the main axis size of each node according to the proportion of the flex-grow coefficient of each node to the total coefficient. For any remaining space caused by floating-point precision, add it to the size of the last node. Step 5: Compress the overflow space according to the proportion of the product of the flex-shrink coefficient and the reference size of each node to the total weighting coefficient. After compression, the main axis size of each node shall not be less than zero. Step 6: Adjust the main axis start position of each node according to the justify-content style property. flex-start arranges nodes from the start position, flex-end arranges nodes near the end position, center arranges nodes in the center, space-between arranges nodes with equal spacing and no spacing at the beginning and end, space-around arranges nodes with half the internal spacing at the beginning and end, and space-evenly arranges all spacings equally. Step 7: Based on the align-items and align-self style properties, adjust the starting position of each node along the cross axis according to the alignment factor to achieve alignment.

[0015] The event handling and dispatching process of the executable file described in this invention includes the following steps: E1. Register event handlers in the JavaScript layer through the event properties of virtual nodes. The event handlers are stored in the event mapping table of the virtual nodes in the form of function references. E2. During the frame rendering process of the Rust rendering layer, scene nodes are created sequentially for each interactive virtual node through the scene graph API, and the node position, size, z-index and event handler references are registered to the scene graph. E3. Capture operating system-level input events through the message pump of the Win32 native window and store the event coordinates in a global atomic variable; E4. After a mouse event is triggered, the dirty flag is set to true. The dirty flag is checked in the next frame's WM_PAINT redraw. The JavaScript frame rendering callback is called only when the dirty flag is true. The dirty flag is cleared after the dirty rendering is complete. E5. After the frame rendering callback is executed, read the coordinates of the click event to be processed from the global atomic variable, traverse the scene graph nodes in reverse z-index to perform a rectangle hit test, and call the handler when the hit node has registered a click event handler; for hover events, read the mouse coordinates after each rendering to perform a hit test, and trigger the hover enter or hover leave callback when the hit state changes. E6. After each rendering, `call_frame_handler` reads the current mouse coordinates from `MOUSE_X` and `MOUSE_Y` and calls the `scene_graph::process_hover` function. `process_hover` traverses the scene graph nodes and performs a hit test. If the mouse hits the currently hovering element and the hit state has not changed, no callback is triggered. When the mouse enters the hit state from a non-hit state, a hover enter callback is triggered with parameters (id, 1.0). When the mouse leaves the hit state, a hover leave callback is triggered with parameters (id, 0.0). The hit state is maintained through the global atomic variable `HOVERED_ELEMENT_ID`.

[0016] A static compilation system for TypeScript executables, used to implement the aforementioned fully static compilation method, includes: (i) Dependency graph construction module, used to parse the import / export statements of the entry file and all dependent modules, construct the module dependency graph and sort it by topological order, assign a unique identifier to each module, and construct an export mapping table containing function exports and variable exports; (ii) Module compilation module, which is used to traverse all modules in topological order, and execute SWC parsing to AST, HIR conversion, CraneliftIR code generation, and COFF format object file generation for each module in sequence, and finally outputs binary module file. During the compilation process, the reference count release of temporary string values ​​is managed through a delayed batch release mechanism at the basic block construction point. (iii) The main wrapper generation module is used to generate the main wrapper function in x86-64 machine code format, call the initialization functions of all modules in topological order, and then call the entry main function; (iv) Loader compilation and linking module: The Rust compiler is used to independently compile a standalone PE loader with zero third-party dependencies. Each module generates an independent binary module file (.tsnobj, containing code segment, data segment, read-only data segment and symbol / relocation table) during compilation. When the loader runs, it reads the manifest file and loads the code segment, data segment and read-only data segment of each module into the process memory. It performs multi-level priority symbol resolution (cross-module symbol table → DLL registry center → runtime DLL export → addon DLL, downgraded to stub if missing) and dual-type relocation (REL32 relative / ABS64 absolute). After deployment together with the runtime DLL and module files, it outputs an executable file that can be run directly.

[0017] Compared with the prior art, the present invention has the following advantages: 1. This invention enables the direct transfer of 64-bit floating-point values ​​between the compiler-generated machine code and the runtime DLL through unified NaN-tagging value encoding across the compiler-runtime boundary. No encoding / decoding conversion layer is required, FFI calls have zero overhead, and extern "C" fn(f64) -> f64 directly corresponds to the x86-64 XMM register calling convention.

[0018] 2. This invention achieves deterministic memory management with zero GC pauses through a thread-local generic reference counting pool. The destruction time of all values ​​is completely determined, and the reference count is released instantly when it reaches zero. There is no stop-the-world pause, and the time taken for each release operation is constant O(1) and does not change with the heap size. There is no need for GC root scanning and object graph traversal. The LIFO strategy of free_list reuses the recently released slots to improve the cache hit rate. The thread-local pool does not require locking operations.

[0019] 3. This invention uses a 5-level priority symbol resolution and stub degradation mechanism to ensure that the final executable file depends only on the runtime DLL, without the operating system's dynamic linker participating in executable file-level symbol resolution. Missing symbols are replaced by stubs to prevent runtime crashes. After removing exported functions from the runtime DLL, symbols are automatically downgraded to stubs, simplifying DLL trimming. The extended DLL mechanism supports function-level hot updates.

[0020] 4. This invention uses a self-contained PE loader to make the compilation output a single executable file plus a single runtime DLL. The executable file size is about 6 to 8 MB, the startup time is less than 100 milliseconds, and no Node.js runtime or npm package dependency is required.

[0021] 5. This invention enables the complete CSS parsing, Flexbox layout, Direct2D hardware-accelerated rendering, and IME input method support to be implemented in a single DLL through integrated DOM rendering, without relying on the system WebView, Skia, or browser kernel. The DrawCommand abstraction layer uses Direct2D as the unified rendering backend.

[0022] 6. This invention utilizes AOT compilation of VueSFC, enabling the compilation of .vue files to be done without node_modules, @vue / compiler-sfc, or any JavaScript toolchain. After compilation, there is no Vue runtime overhead; everything is converted to native machine code, resulting in deterministic performance with full repaint and no Vue asynchronous rendering queue and watcher scheduling overhead.

[0023] 7. This invention integrates event response into the frame rendering pipeline through scene graph event registration, dirty tag-driven click processing, and hover detection mechanism. Mouse clicks are dispatched immediately after the current frame is rendered, without the need for a separate event queue or interrupt. The processing delay of click events does not exceed one frame cycle (approximately 16 milliseconds), and hover state changes are responded to in real time without additional asynchronous tasks. Attached Figure Description

[0024] Figure 1 This is a flowchart of the steps of the static compilation method for TypeScript executable files according to an embodiment of the present invention; Figure 2 This is a schematic diagram of NaN-tagging value encoding according to an embodiment of the present invention; Figure 3 This is a lifecycle state diagram of the reference counting pool according to an embodiment of the present invention; Figure 4 This is a flowchart illustrating the 5-level symbol resolution priority in an embodiment of the present invention; Figure 5 This is a block diagram of the module connection of the zero-GC runtime engine according to an embodiment of the present invention; Figure 6 This is a flowchart of the steps of the Flexbox layout algorithm according to an embodiment of the present invention; Figure 7 This is a flowchart of the rendering pipeline according to an embodiment of the present invention; Figure 8 This is a flowchart of the event processing and dispatching process according to an embodiment of the present invention; Figure 9 This is a preprocessing flowchart of an embodiment of the present invention. Detailed Implementation

[0025] The present invention will now be described in further detail with reference to the accompanying drawings and specific embodiments.

[0026] I. A static compilation method for TypeScript executables, used to compile TypeScript / Vue source code into native x86-64 machine code and link it into a standalone executable file, including the following steps: S1. Dependency Graph Construction Steps: Parse the import / export statements of the entry file and all dependent modules, construct the module dependency graph and sort it by topological order, assign a unique identifier to each module, and construct an export mapping table containing function exports and variable exports. Specifically, this includes the following steps: (1) The compiler loads the entry file and the TypeScript source files of all its dependent modules, and calls the SWC parser to parse the import / export statements for each source file.

[0027] (2) Topological sorting is performed by DFS postorder traversal to construct the module dependency graph, allowing the TypeScript Barrel mode of circular dependencies.

[0028] (3) Assign a unique numeric identifier to each module in topological order, starting from 1 and incrementing.

[0029] (4) Construct an export mapping table. Function exports in the export mapping table are mapped to global symbol names in the form of "mod_{id}_{name}". Variable exports do not generate getter symbols. Cross-module variable reading is performed at runtime by reading the module storage through the path import_binding→js_module_store_get. Constant exports are inlined into the value table at compile time through const_values, without the need for runtime calls.

[0030] S2, Module compilation steps: Traverse all modules in topological order and perform the following steps for each module in sequence: (1) Parse the TypeScript source code into SWCAST; (2) Convert SWCAST into a list of HirExpr expressions; (3) Generate the corresponding CraneliftIR instruction sequence for each HirExpr and generate COFF format binary data. The final output is a self-described binary module file. During compilation, a delayed batch release mechanism is used to manage the reference count release of temporary string values ​​at the basic block construction points. Specifically, the following steps are included: (1) SWC parsing: call swc_ecma_parser::parse_module() to parse the TypeScript source code into SWCAST.

[0031] (2) HIR (High-Level Intermediate Representation) Conversion: SWCAST is converted into a flat list of HirExpr expressions, each corresponding to one or more CraneliftIR instructions. During compilation, cross-module function calls are completed directly through Cranelift function declaration and call instructions, without going through the External Function Interface (FFI) call path. The conversion process handles various syntax structures such as variable declarations, function declarations, class declarations, import / export statements, conditional statements, loop statements, exception handling statements, ternary operator expressions, and logical AND / OR expressions.

[0032] (3) CraneliftIR code generation: Generate a corresponding CraneliftIR instruction sequence for each HirExpr, directly generating COFF format binary data, including code segment, data segment, and read-only data segment. During compilation, cross-module function calls use ctx.function_ids to find the Cranelift function declaration of the target function and call it directly using the call instruction, without going through the external function interface path.

[0033] (4) Delayed Batch Release: At the basic block construction points such as if conditional branches, while loops, for loops, try-catch exception handling, ternary operators, and logical AND / OR expressions, the accumulated temporary string value references within the current basic block are batch-called using the js_release function. Simultaneously, the return value is excluded from the release list, ensuring that the value is released within its defining basic block and satisfies Cranelift dominance constraints. Specifically, all values ​​in the ctx.temp_releases vector are retrieved, and call_import(ctx,builder,js_release,&[v]) is called. For ternary operator expressions, the return value is first excluded from the temp_releases vector before release is performed. When adding a new basic block construction point, this release operation must be performed before the block entry point and before inter-block jumps.

[0034] (5) COFF Object File Output: The generated code segment, data segment, read-only data segment, symbol table, and relocation table are packaged into a COFF format object file and written to a self-describing binary module file in .tsnobj format. The header of the .tsnobj file contains metadata such as the size of each segment, symbol count, relocation count, and entry module name.

[0035] In this embodiment, the format of the self-describing binary module file includes a header and various data segments. The header contains a 4-byte code segment size, a 4-byte data segment size, a 4-byte read-only data segment size, a 4-byte symbol count, a 4-byte relocation count, and a 64-byte entry module name. The data segments include a code segment (x86-64 machine code), a data segment (static variables), and a read-only data segment (string constants). Each record in the symbol table contains a 1-byte segment type (0 for code segment, 1 for data segment, and 2 for read-only data segment), a 4-byte segment offset, and a 64-byte symbol name. Each record in the relocation table contains a 1-byte segment type, a 4-byte segment offset, a 1-byte relocation type (0 for REL32 and 1 for ADDR64), a 1-byte padding byte, and a 64-byte target symbol name.

[0036] S3. Main Wrapper Generation Steps: Generate a main wrapper function in x86-64 machine code format, call the initialization functions of all modules in topological order, and then call the entry main function to achieve module initialization in dependency order. Specifically, this includes the following steps: (1) The function entry point first executes sub rsp,40 to allocate stack space, then generates call__tsn_module_init_{id} instruction for each module according to topological order to call its initialization function, and finally generates call main instruction to call the main function of the executable file.

[0037] (2) The function exits by executing add rsp,40 and ret to restore the stack and return.

[0038] (3) Add the wrapper function and its symbol to the code segment and symbol table of the main entry module.

[0039] S4. Loader Compilation and Linking Steps: The Rust compiler is used to independently compile a PE loader with zero external dependencies. The code segment, data segment, and read-only data segment of the self-describing binary module file are embedded into the PE loader. Symbol resolution and dual-type relocation are performed at five priorities, outputting a directly executable file. Specifically, the following steps are included: (1) Call the Rust compiler to compile the loader source code with zero external dependencies in an independent manner and output standalone-loader.exe; during the compilation process, embed the code segment, data segment and read-only data segment of all modules generated in steps S2 and S3 into the corresponding segment of the PE loader.

[0040] (2) The loader performs 5-level priority symbol resolution at runtime: Level 1 searches the global symbol table of loaded modules, with the first registered symbol winning and duplicates not being overwritten; Level 2 searches the function center registered at runtime via js_register_function; Level 3 searches the export table of tsn_runtime.dll via GetProcAddress; Level 4 searches the export table of all loaded extension DLLs in the order of loading; Level 5 uses the stub function that returns TAG_UNDEFINED.

[0041] (3) After symbol resolution is completed, relocation corrections of two types, REL32 and ADDR64, are performed. Finally, the module initialization function is called in the topology order, followed by the main function.

[0042] II. In step S4 of the static compilation phase, the PE loading and symbol resolution process specifically includes the following steps: B1. Loader independent compilation steps: Call the Rust compiler to compile the loader source code with zero external dependencies into an independent PE executable file. The loader only uses the Rust standard library and Win32FFI functions and does not depend on any third-party libraries.

[0043] B2. Module loading steps: At runtime, all self-describing binary module files are loaded. For each module, the size of each segment, symbol count, relocation count, and entry module name metadata in its header are parsed. Executable memory pages and read-write memory pages are allocated through VirtualAlloc. The module's code segment, data segment, and read-only data segment are copied to the corresponding memory areas.

[0044] B3. Symbol resolution steps: Traverse the symbol tables and relocation tables of all modules, and resolve each symbol in a 5-level priority order: First, search in the global module symbol table, then in the runtime registry, then in the runtime DLL export table using GetProcAddress, then in the extended DLL export table in the order of loading, and finally, if no symbol is found at any level, use the stub function to return an undefined value.

[0045] In this embodiment, the global module symbol table adopts a first-to-file strategy, and symbols with the same name are not overwritten. The exported symbols of each module are isolated by the namespace rule "mod_{id}_{name}", and there is no cross-module symbol overwriting.

[0046] In this embodiment, the stub function returns a NaN-tagging constant value representing type Undefined, allowing the executable to continue running without crashing. When a certain exported function is removed during runtime DLL trimming, calls that depend on that symbol are automatically downgraded to stubs.

[0047] B4. Relocation Steps: For each record in the relocation table, perform the corresponding address correction operation according to the relocation type. The relocation types include 32-bit relative offset relocation for the x86-64 call rel32 instruction, and 64-bit absolute address relocation for function pointer variables and virtual tables.

[0048] B5. Module initialization steps: Call the initialization functions of all modules in topological order. Each initialization function creates a namespace storage object for the module, executes the top-level statement of the module, and sets the module's exported variables.

[0049] III. See Appendix Figure 9 In the static compilation phase, the Vue files need to be preprocessed at the beginning, changing the .vue extension files to .ts extension files. During the Vue file preprocessing, AOT (Ahead-of-Time) compilation is performed. Specifically, this includes the following steps: D0, Project Discovery Steps.

[0050] Locate the entry file (default main.ts), recursively scan the project directory, collect all .ts, .js, and .vue source files, and bucket them by file extension: .ts / .js files → directly enter D5 (bypass D1-D4); .vue file → additional entry into D1; This stage's deliverables: a list of documents.

[0051] D0.5, Steps for constructing the module dependency graph: Based on the recursive parsing of import / export statements in the entry file, a module dependency graph is constructed, and a module_id is assigned to each module, generating an export_map. The function exports foo→mod_{id}_foo; Exporting the variable 'bar' → no getter symbol is generated; cross-module variable reading is done at runtime by reading the module storage via the path 'import_binding' → js_module_store_get. The constant `export const` is inlined into `const_values` at compile time, preventing the generation of runtime getters. The deliverable of this stage: a module dependency graph.

[0052] D1, SFC parsing steps (.vue files only).

[0053] This code analyzes the three-part structure of a Vue single-file component, extracting the template, script, and style sections. The style section is not included in this AOT compilation but is handled as runtime CSS injection.

[0054] D2. Script compilation steps (.vue files only).

[0055] The OptionsAPI definition in the script segment is parsed, and the reactive data declaration returned by the data() function, the method definitions in the methods block, and the computed property definitions in the computed block are extracted. This lightweight compiler does not implement a watch listener; related requirements are met by manually subscribing to data changes using methods.

[0056] The deliverable of this phase: a standardized component option object.

[0057] D3. Template compilation steps (.vue files only).

[0058] The HTML template expressions in the template segment are recursively compiled into an h factory function call chain, with each template element corresponding to an h function call; the attribute bindings in the template (:class, :style, etc.) are compiled into the props parameters of the h function, and the event bindings (@click, @input, etc.) are compiled into the on* event properties of the h function; v-if / v-show are compiled into conditional expressions, and v-for is compiled into an array of child nodes wrapped in Array.map.

[0059] The output of this stage: the h() call expression.

[0060] D4. Steps for generating rendering functions (.vue files only).

[0061] The compiled `h` function call chain is wrapped in the `render()` function. The function body only returns the `h` call result of the root node (i.e., the VNode tree), without inserting any window / event loop startup calls. The generated TypeScript code is fed into the standard compilation pipeline via the SWC memory pipe (without leaving temporary files), and after HIR transformation, it is compiled into object code by Cranelift. The window startup call `js_desktop_show_window()` is initiated uniformly by the `main()` entry point of the compiled artifact after all components are mounted, and is unrelated to this step.

[0062] In this embodiment, the syntax supported by template compilation includes at least text interpolation expressions, event binding, conditional rendering instructions, list rendering instructions, display toggle instructions, two-way binding instructions, attribute binding instructions, and slot instructions.

[0063] The deliverable at this stage: a complete TS module.

[0064] D5, TS source merging steps.

[0065] Merge the .ts / .js source files collected by D0 with the .vue compilation results produced by D4 into a unified TypeScript module stream: .ts / .js files → Enter with original content; .vue files → are accessed as TS modules with the render() function generated by D4 and component options; Cross-module symbols are rewritten according to export_map in D0.5.

[0066] The output of this stage is the merged module flow, ordered by topology.

[0067] D6. SWC analysis and HIR conversion steps.

[0068] The D5 module stream is parsed using the SWC memory pipeline, converting the AST of each TS / JS module into a HIR. The HIR stage completes all semantic rewriting. The module-level `let` function is rewritten as a `var` function within `main()` and marked as `module_store` for writing. The h() factory function is injected into the output module by the Vue front-end compiler. The h call generated by the template compilation directly executes this function to create virtual nodes, without being rewritten as an FFI call. isNaN(x) can be rewritten as js_is_nan(x)FFI; String comparisons >= / <= / should be rewritten as js_string_*FFI; Static method dispatch: Math.PI / Object.keys, etc.; The values ​​of constants exported as const are collected into const_values ​​and inlined at compile time. Cross-module imports are rewritten as mod_{id}_* based on export_map for direct invocation; The deliverable at this stage is HIR (High-Level Intermediate Representation), which no longer contains the original TS syntax.

[0069] D7. Runtime API verification steps (final verification after compilation).

[0070] Scan all FFI references (js_* / ts_native_shim_*) in the HIR, compare them with the exported symbol table of the runtime DLL (parsed via dumpbin / EXPORTS), and generate runtime-requirements.json: Missing symbols are handled by the stub function (which returns undefined), without blocking compilation. The report output in this step records the matching status between the runtime symbols referenced by the compiler and those actually exported by the DLL, used for link integrity verification.

[0071] The output of this stage is runtime-requirements.json (the final verification report after compilation).

[0072] This verification step is performed after the compilation process generates all machine code and completes linking.

[0073] IV. A method for running a TypeScript executable file, wherein the executable file memory management process includes the following steps: A1. Value Encoding Steps: A unified NaN-tagging encoding across the compiler-runtime boundary is adopted. The encoding space of the IEEE754 double-precision floating-point number, where the exponent bits are all 0x7FF and the mantissa is non-zero, is divided into multiple type tag regions. The high 4 bits of the payload of each type tag store the type information, and the low 48 bits store the data index or pointer. This allows the 64-bit floating-point value to be directly transferred between the machine code generated by the compiler and the runtime DLL without the need for encoding and decoding conversion.

[0074] In this embodiment, the value encoding is defined as follows: (1) Numeric type: When the exponent of a 64-bit double-precision floating-point number is not all 0x7FF, it is directly interpreted as an IEEE754 double-precision floating-point number. (2) Non-numeric type: When the exponent is all 0x7FF and the mantissa is not zero, bits 48 to 51 store the type label, and bits 0 to 47 store the data payload.

[0075] In this embodiment, the type tags of NaN-tagging encoding include at least the following: tag 0 represents a numeric type, directly interpreted as an IEEE 754 double-precision floating-point number; tag 1 represents a string type, with the lower 48 bits being the string pool index; tag 2 represents an object type, with the lower 48 bits being the object pool index; tag 3 represents a boolean type, with the lower 1 bit distinguishing between true and false; tag 4 represents the Undefined type; tag 5 represents the Null type; tag 6 represents a function type, with the lower 48 bits being the function pointer address; tag 7 represents an array type, with the lower 48 bits being the array pool index; tag 8 represents a buffer type, with the lower 48 bits being the buffer pool index; tag 9 represents a typed array type, with the lower 48 bits being the typed array pool index; and tag 10 represents the BigInt type, with the lower 48 bits being the heap pointer.

[0076] A2. Reference counting management steps: Create a thread-local generic reference counting pool. Each pool maintains a slot vector and a list of free slots. When allocating a value, a slot is obtained from the free list or a new slot is added, and the reference count is initialized to 1. When a value is referenced, the reference count of the corresponding slot is incremented by 1. When a value is released, the reference count of the corresponding slot is decremented by 1. When the reference count drops to 0, the slot is marked as free and recycled to the free list. Sub-values ​​are released recursively.

[0077] In this embodiment, each pool contains a slot vector and a list of free slots. The slot structure includes a generic value field, a 32-bit unsigned integer reference count field, and a boolean free flag field. The string pool manages dynamic string objects, automatically deduplicating them during allocation by searching for content; strings with the same content reuse the same slot. The object pool manages JavaScript objects; each object maintains a property key-value pair mapping table and a prototype reference. During release, all property values ​​and prototype references are recursively traversed to perform the release. The array pool manages dynamic arrays, recursively traversing all element values ​​to perform the release. The buffer pool manages byte vectors, directly releasing the underlying byte storage during release. Reference counting operations: the `js_retain` function dispatches to the corresponding pool's `retain` method based on the type label in the value encoding, incrementing the slot reference count by 1. The `js_release` function dispatches to the corresponding pool's `release` method based on the type label, decrementing the slot reference count by 1. When the reference count reaches 0, the free flag of the slot is set to true, the slot index is added to the free list, and sub-values ​​are recursively released.

[0078] In this embodiment, the reference counting pool includes at least four independent instances: a string pool, an object pool, an array pool, and a buffer pool. Each pool is independent of the others and is thread-local storage, requiring no locking operations. The string pool automatically de-de-saves during allocation by searching for content. The object pool recursively releases all attribute values ​​and prototype references during release. The array pool recursively releases all element values ​​during release. The buffer pool releases the underlying byte vector during release.

[0079] A3. Batch Delayed Release Steps: When generating machine code, the compiler does not immediately call the release function for short-term temporary values, but accumulates them in the delayed release vector and releases them in batches at the boundaries of basic blocks.

[0080] In this embodiment, the compiler postpones the deallocation of short-lived temporary strings and objects to the boundary of basic blocks during the codegen phase, reducing the frequency of FFI calls through batch calls of the js_release function. Values ​​in the temporary deallocation vector must be released within the defined block and cannot cross basic blocks; otherwise, Cranelift's dominance constraint is violated.

[0081] V. A method for running a TypeScript executable file, the GUI rendering process of which includes the following steps: C1. Style parsing steps: Receive style descriptions from the JavaScript layer, supporting both CSS string format and JavaScript object format inputs, and extract at least 40 CSS property fields, covering box model properties, layout properties, visual properties, positioning properties, and text properties.

[0082] C2. Flexbox layout steps: Based on the parsed style information, perform a complete Flex layout algorithm on the child nodes of the node, including determining the main axis direction, calculating the base size of each child node, allocating the remaining or overflow space of the main axis according to flex-grow and flex-shrink, adjusting the main axis position according to justify-content, and controlling the cross axis alignment according to align-items and align-self.

[0083] In this embodiment, the main axis space allocation of the Flex layout algorithm includes the following sub-steps: First, calculate the sum of the base size and spacing of all child nodes, and compare it with the main axis size of the container to obtain the remaining space; if the remaining space is positive and the total flex-grow coefficient is greater than zero, allocate the remaining space according to the proportion of the flex-grow coefficient of each node to the total coefficient; if the remaining space is negative and the total flex-shrink weighted coefficient is greater than zero, compress the overflow space according to the proportion of the product of the flex-shrink coefficient and the base size of each node to the total weighted coefficient.

[0084] C3, VNode recursive rendering steps: Starting from the root node, recursively traverse the virtual node tree, and for each node, execute the following steps in sequence: parse style, calculate box model, draw its own style (including background color, border, shadow, and text), process absolutely and fixed positioned child nodes, register event handlers, clip overflow content, and recursively render child nodes.

[0085] C4. Command Batch Rendering Steps: Convert all drawing operations into abstract rendering commands and add them to the processing queue. During frame rendering, sort all commands by z-index, traverse and call the corresponding Direct2D drawing primitives for rasterization, and finally submit the rendering results to the window.

[0086] In this embodiment, in step C4, the abstract rendering commands include at least rectangle fill command, rounded rectangle fill command, gradient fill command, text drawing command, clipping region command, and texture drawing command, which are dispatched by the Direct2D graphics interface to the corresponding drawing primitives according to the command type to complete rasterization.

[0087] VI. See Appendix Figure 6 In step C2, the Flexbox layout algorithm specifically includes the following steps: Step 1: Determine the main axis direction: Determine the main axis and cross axis based on the flex-direction style property. row indicates that the main axis is horizontal and the cross axis is vertical, and column indicates that the main axis is vertical and the cross axis is horizontal.

[0088] Step 2: Calculate the baseline size: For each child node, the explicit flex-basis value is used first. When flex-basis is auto, it falls back to the explicit width or height value. If there is no explicit value, the content estimate is used.

[0089] Step 3, Main Axis Space Calculation: Calculate the sum of the base dimensions and spacing of all child nodes, and compare it with the container's main axis dimension to obtain the remaining space. If the remaining space is positive and the total flex-grow coefficient is greater than zero, execute the flex-grow allocation in Step 4; if the remaining space is negative and the total flex-shrink weighted coefficient is greater than zero, execute the flex-shrink allocation in Step 5.

[0090] Step 4, flex-grow allocation: Based on the proportion of each node's flex-grow coefficient to the total coefficient, allocate the remaining space to the main axis size of each node. For any remaining space caused by floating-point precision, add it to the size of the last node.

[0091] Step 5, flex-shrink allocation: Compress the overflow space according to the proportion of the product of the flex-shrink coefficient and the base size of each node to the total weighting coefficient. After compression, the main axis size of each node is not less than zero.

[0092] Step 6, adjust justify-content: Adjust the starting position of each node on the main axis according to the justify-content style property. flex-start arranges nodes from the starting position, flex-end arranges nodes near the ending position, center arranges nodes in the center, space-between arranges nodes with equal spacing and no spacing at the beginning and end, space-around arranges nodes with half the spacing at the beginning and end, and space-evenly arranges all spacings equally.

[0093] Step 7, Cross Axis Alignment: Based on the align-items and align-self style properties, adjust the starting position of each node along the cross axis according to the alignment coefficient to achieve alignment methods such as flex-start, center, flex-end, and stretch.

[0094] VII. A method for running a TypeScript executable file, the event handling and dispatch process of which includes the following steps: E1. Event binding steps: Register event handlers in the JavaScript layer through the event properties of virtual nodes. Event handlers are stored in the event mapping table of virtual nodes in the form of function references. Event types include at least click events and hover events.

[0095] In this embodiment, the event handler is stored on the JavaScript virtual node as follows: the event property of the virtual node is an object, the key name of the object is the event type string, and the key value is the handler function reference.

[0096] Specifically: During the construction of the JavaScript virtual node tree, event handlers are registered for interactive nodes through the fourth parameter of the `h` factory function. Event handlers are stored as function references in the `event` property of the virtual node object. `event` is a mapping object where the key is the string name of the event (e.g., "click" or "hover"), and the value is the corresponding handler function reference.

[0097] E2. Scene Graph Registration Steps: During the frame rendering process of the Rust rendering layer, scene nodes are created sequentially for each interactive virtual node through the scene graph API, and the node position, size, z-index, and event handler references are registered to the scene graph.

[0098] In this embodiment, the scene graph API includes js_scene_create for creating scene nodes and returning node IDs, js_scene_set_on_click for binding click handlers, and js_scene_set_on_hover for binding hover handlers.

[0099] Specifically, the Rust-side `register_scene_nodes` function, when rendering each node, reads the event mapping object on the virtual node using `js_object_get`, reads the `click` and `hover` attributes, and if a valid event handler exists, it sequentially calls `scene_graph::js_scene_create` to create the scene node and returns its node ID, calls `scene_graph::js_scene_set_on_click` to bind the click handler, and calls `scene_graph::js_scene_set_on_hover` to bind the hover handler. Scene nodes record the node's global coordinates, size, and z-index value, and parent-child relationships are constructed using the `parent_id` field to build a tree-like scene graph.

[0100] E3. Window event capture steps: Capture operating system-level input events through the message pump of the Win32 native window, including left mouse button press events, left mouse button release events, mouse movement events, keyboard press events, and keyboard release events, and store the event coordinates in global atomic variables.

[0101] Specifically: The WndProc message handling function in desktop_window.rs captures left mouse button press events via the WM_LBUTTONDOWN message, left mouse button release events via the WM_LBUTTONUP message, mouse movement events via the WM_MOUSEMOVE message, keyboard press events via the WM_KEYDOWN message, and keyboard release events via the WM_KEYUP message. Mouse event coordinates are extracted from the lparam parameter using the lparam_to_coords function and stored in the global atomic variables MOUSE_X and MOUSE_Y. Upon triggering a mouse click event, the dirty flag RENDER_DIRTY is set to true, and a window redraw is immediately requested.

[0102] E4. Dirty flag driven steps: After a mouse event is triggered, the dirty flag is set to true. In the next frame's WM_PAINT redraw, the dirty flag is checked. The JavaScript frame rendering callback is called only when the dirty flag is true. The dirty flag is cleared after the dirty rendering is complete.

[0103] Specifically: After handling mouse events, WndProc calls request_redraw(), triggering the WM_PAINT redraw message. During the redraw, the canvas_ffi::call_frame_handler function is called. call_frame_handler first calls process_pending_click to process the pending click events accumulated from the previous frame, and then checks the RENDER_DIRTY dirty flag. If the dirty flag is false (no data change), it only performs cursor preparation and hover detection and then returns immediately. If the dirty flag is true, it calls the JavaScript frame rendering callback to execute the complete DOM rendering pipeline.

[0104] E5. Event dispatch steps: After the frame rendering callback is executed, the coordinates of the click event to be processed are read from the global atomic variable. The scene graph nodes are traversed in reverse z-index order to perform a rectangle hit test. When a hit node has registered a click event handler, the handler is called. For hover events, the mouse coordinates are read after each rendering to perform a hit test. When the hit state changes, the hover enter or hover leave callback is triggered.

[0105] Specifically, the `process_pending_click` function retrieves pending mouse click events from the `MOUSE_EVENT_QUEUE` event queue and calls the `scene_graph::process_click` function to perform a hit test. `process_click` iterates through all root nodes in the scene graph, recursively performing a bounding box test on each node and its child nodes in descending order of z-index. The test uses the node's global coordinates and size to calculate the bounding box. If the click coordinates fall within the bounding box and the node has a registered click handler, the handler function is called and `true` is returned.

[0106] E6. Hover Event Dispatch: After each rendering, `call_frame_handler` reads the current mouse coordinates from `MOUSE_X` and `MOUSE_Y` and calls the `scene_graph::process_hover` function. `process_hover` iterates through the scene graph nodes, performing a hit test. If the mouse hits the currently hovering element and the hit state hasn't changed, no callback is triggered. When the mouse moves from a non-hit state to a hit state, a hover entry callback is triggered with parameters (id, 1.0). When the mouse leaves the hit state, a hover exit callback is triggered with parameters (id, 0.0). The hit state is maintained through the global atomic variable `HOVERED_ELEMENT_ID`.

[0107] II. This embodiment provides a static compilation and execution system for TypeScript executable files, including: (i) Dependency graph construction module, used to parse the import / export statements of the entry file and all dependent modules, construct the module dependency graph and sort it in topological order, assign a unique identifier to each module, and construct an export mapping table containing function exports and variable exports.

[0108] (ii) Module compilation module, which is used to traverse all modules in topological order, and execute SWC parsing to AST, HIR conversion, CraneliftIR code generation, and COFF format object file generation for each module in sequence, and finally outputs a self-describing binary module file. During the compilation process, the reference count release of temporary string values ​​is managed through a delayed batch release mechanism at the basic block construction point.

[0109] (iii) The main wrapper generation module is used to generate the main wrapper function in x86-64 machine code format, call the initialization functions of all modules in topological order, and then call the entry main function; (iv) Loader compilation and linking module, which calls the Rust compiler to independently compile a PE loader with zero external dependencies, embeds the code segment, data segment and read-only data segment of the self-describing binary module file into the PE loader, performs symbol resolution and dual-type relocation with 5 priority levels, and outputs an executable file that can be run directly.

[0110] (v) Zero-GC runtime engine, which includes: (1) Value encoding unit, used to adopt unified NaN-tagging encoding across compiler-runtime boundaries, divides the encoding space of IEEE754 double-precision floating-point numbers with all exponent bits set to 0x7FF and mantissas to multiple type tag regions. The high 4 bits of each type tag store type information, and the low 48 bits store data index or pointer.

[0111] (2) Reference counting management unit, used to create thread-local generic reference counting pools. Each pool maintains a slot vector and a list of free slots. When a value is allocated, a slot is obtained from the free list or a new slot is added and the reference count is initialized to 1. When a value is referenced, the reference count of the corresponding slot is incremented by 1. When a value is released, the reference count of the corresponding slot is decremented by 1. When the reference count drops to 0, the slot is marked as free and recycled to the free list. Sub-values ​​are released recursively.

[0112] (3) Batch Delayed Release Unit, which is used by the compiler to accumulate short-term temporary values ​​into the delayed release vector when generating machine code, and release them in batches at the boundaries of basic blocks.

[0113] (vi) A self-contained PE loading and symbol resolution engine, which includes: (1) The loader independent compilation unit is used to call the Rust compiler to compile the loader source code with zero external dependencies into an independent PE executable file.

[0114] (2) Module loading unit, used to load all self-describing binary module files at runtime, parse header metadata, allocate memory pages through VirtualAlloc and copy each segment to the corresponding memory area.

[0115] (3) Level 5 symbol resolution unit, used to resolve each symbol in the order of priority of the five levels: global module symbol table, runtime registry center, runtime DLL export table, extended DLL export table, and stub function.

[0116] (4) Dual-type relocation unit, used to perform address correction for two relocation types: relative offset 32 ​​bits and absolute address 64 bits; topology order initialization unit, used to call the initialization function of all modules in topology order.

[0117] (vii) The DOM rendering engine, which includes: (1) Dual-format style parsing unit, which supports both CSS string format and JavaScript object format style input at the same time, and extracts at least 40 CSS property fields.

[0118] (2) Flexbox layout unit, used to perform the complete Flex layout algorithm, including main axis direction determination, baseline size calculation, flex-grow / flex-shrink space allocation, justify-content position adjustment and cross axis alignment.

[0119] (3) VNode recursive rendering unit, used to recursively traverse the virtual node tree starting from the root node, and perform style parsing, box model calculation, style drawing, child node recursive rendering and event registration for each node.

[0120] (4) Command batch rendering unit, which is used to convert all drawing operations into abstract rendering commands, sort them by z-index and rasterize them through Direct2D drawing primitives during frame rendering.

[0121] (viii) An event handling engine, which includes: (1) Scene graph registration unit, used to create scene nodes and register event handlers for each interactive node during the rendering process.

[0122] (2) Window event capture unit, used to capture mouse and keyboard input events through the message pump of Win32 native window and store the event coordinates in global atomic variables.

[0123] (3) Dirty tag driving unit, used to control the triggering of frame rendering callbacks with dirty tags, and only performs rendering after data changes.

[0124] (4) Event dispatch unit, used to perform a hit test of the scene graph after frame rendering and call the event handlers registered on the hit node.

[0125] See appendix Figure 7 This embodiment also proposes a rendering pipeline flow for an integrated DOM rendering engine. This flow is driven by JavaScript frame callbacks, and the specific steps are as follows: Step 1: The JavaScript executable sets a frame callback function through the requestAnimationFrame mechanism. The function uses the h factory function to build a virtual node tree and calls the js_dom_render_window function to pass the virtual node tree to the Rust runtime layer.

[0126] Step 2: The js_dom_render_window function serves as the rendering entry point. First, it clears the scene graph of the previous frame, and then calls the layout_node recursive layout function to recursively lay out the data starting from the root node with the screen width and height as the initial dimensions.

[0127] Step 3: The `layout_node` function executes the following steps for each node: It calls `parse_style_object` or `parse_style_string` to parse the node style into a `ParsedStyle` structure; it calculates the inner margin, outer margin, border, and center offset based on the box model properties to obtain the available space for child nodes; for flex containers, it uses the Flexbox layout algorithm to allocate the position and size of child nodes; for non-flex containers, it arranges child nodes vertically according to block-level flow; it handles absolutely positioned and fixed-position child nodes; it sets the clipping region for `overflow:hidden`; and it recursively calls `layout_node` to lay out all child nodes. After the layout is complete, `register_scene_nodes` registers each interactive node to the scene graph, `flatten_layout` flattens the layout tree into a list of drawable items and sorts them by z-index, and finally, `paint_node` draws the node's own style, including background color filling as a rounded rectangle, borders drawn as four lines, shadows drawn as offset rectangles, and text rendered using DirectWrite.

[0128] Step 4: During the rendering process, all drawing commands are converted into DrawCommand enumerations through the canvas_ffi abstraction layer and submitted to the command queue to be processed. The types of DrawCommand include at least rectangle fill, rounded rectangle fill, gradient fill, text drawing, clipping region, and texture drawing.

[0129] Step 5: The Renderer::render function is called during the frame rendering stage. First, all commands to be processed are sorted by z-index. Then, each command is traversed, and the corresponding Direct2D drawing primitive is called to rasterize according to the command type. The rectangle fill primitive directly outputs the color, the texture drawing primitive samples the texture and mixes it with the color, the rounded rectangle primitive clips pixels that exceed the rounded corner radius, and the gradient fill primitive linearly interpolates between the start color and the end color.

[0130] Step 6: After rasterization is complete, call EndDraw to end the rendering and display the frame buffer to the window. Clear the pending command queue and wait for the rendering request of the next frame.

[0131] In this embodiment, text rendering supports a dual-path scheme. The primary path is DirectWrite text rendering, which uses IDWriteTextLayout to handle text layout and font fallback, supporting Unicode text, automatic line wrapping, horizontal alignment, and vertical centering. The secondary path is GDI off-screen text rendering, which creates an off-screen device context and DIBSection, uses CreateFontIndirectW to create the font, ExtTextOutW to draw the text, GetDIBits to read the pixel bitmap, and finally composites it into the framebuffer.

[0132] In this embodiment, the IME input method is supported through the TSF (TextServicesFramework) built into the Win32 native EDIT control. The `ime_set_focus` function positions and activates the EDIT control when the input box gains focus. IME candidate text updates and text submissions are handled through TSF callbacks. The `IME_PREEDIT_TEXT` atomic string stores the current candidate text for cursor blinking. The IME cursor position is passed from the JavaScript side to the Rust side via the `js_canvas_set_ime_input_pos` function. The Rust side positions the candidate window using the `ime_set_focus` and `ime_refresh_cursor_area` functions.

[0133] The above specific embodiments have described in detail the principles and implementation methods of the present invention. These embodiments are only used to help understand the core technical content of the present invention. Based on the above specific embodiments of the present invention, any improvements and modifications made to the present invention by those skilled in the art without departing from the principles of the present invention should fall within the patent protection scope of the present invention.

Claims

1. A fully static compilation method for TypeScript executables, characterized in that: Includes the following steps: S1. Parse the import / export statements of the entry file and all dependent modules, construct the module dependency graph and sort it by topological order, assign a unique identifier to each module, and construct an export mapping table containing function exports and variable exports. S2. Traverse all modules in topological order and perform the following steps for each module in sequence: (1) Parse the TypeScript source code into SWCAST; (2) Convert SWCAST into a list of HirExpr expressions; (3) Generate a corresponding CraneliftIR instruction sequence for each HirExpr and generate COFF format binary data. The final output is a binary module file; S3. Generate the main wrapper function in x86-64 machine code format, call the initialization functions of all modules in topological order, and then call the entry main function to realize the initialization of modules in the order of dependencies; S4. Call the Rust compiler to independently compile a PE loader, embed the code segment, data segment, and read-only data segment of the binary module file into the PE loader, perform symbol resolution and dual-type relocation, and generate an executable file that can be run directly.

2. The fully static compilation method according to claim 1, characterized in that: Step S1 specifically includes the following steps: (1) The compiler loads the entry file and the TypeScript source files of all its dependent modules, and calls the SWC parser to parse the import / export statements for each source file; (2) Perform topological sorting using DFS postorder traversal and construct a module dependency graph; (3) Assign a unique numeric identifier to each module according to the topological order; (4) Construct the export mapping table.

3. The fully static compilation method according to claim 1, characterized in that: Step S2 specifically includes the following steps: (1) SWC parsing: Call swc_ecma_parser::parse_module() to parse the TypeScript source code into SWCAST; (2) HIR conversion: Convert SWCAST into a flat list of HirExpr expressions, each expression corresponding to one or more CraneliftIR instructions; (3) CraneliftIR code generation: Generate a corresponding CraneliftIR instruction sequence for each HirExpr, and directly generate COFF format binary data; (4) Delayed batch release: At the basic block construction point, the temporary string value references accumulated in the current basic block are batch-called to the js_release release function, and the return value is excluded from the list to be released, ensuring that the value is released in its defined basic block and satisfies Cranelift dominance constraints. (5) COFF target file output: The generated code segment, data segment, read-only data segment, symbol table and relocation table are packaged into a COFF format target file and written to a .tsnobj format binary module file.

4. The fully static compilation method according to claim 1, characterized in that: Step S3 specifically includes the following steps: (1) The function entry point first executes subrsp,40 to allocate stack space, then generates call__tsn_module_init_{id} instructions for each module according to the topological order to call its initialization function, and finally generates callmain instructions to call the main function of the executable file. (2) At the function exit, addrsp,40 and ret are executed to restore the stack and return; (3) Add the wrapper function and its symbol to the code segment and symbol table of the main entry module.

5. The fully static compilation method according to claim 1, characterized in that: Step S4 specifically includes the following steps: (1) Call the Rust compiler to compile the loader source code with zero external dependencies independently and output standalone-loader.exe; each module is generated independently in the form of binary module files in step S2. When the loader runs, it reads all module files from the disk and copies the code segment, data segment and read-only data segment of each module to the executable memory page and read-write memory page of the loader process through VirtualAlloc. (2) The loader performs a 5-level priority symbol resolution at runtime: The first level searches the global symbol table of the loaded modules, and the first registered one wins and the same name is not overwritten; the second level searches the runtime function registry, and the function is registered by js_register_function and searched by js_find_function; the third level searches the export table of tsn_runtime.dll through GetProcAddress; the fourth level searches the export table of all loaded extension DLLs in the order of loading; the fifth level uses the stub function that returns TAG_UNDEFINED. (3) After symbol resolution is completed, relocation corrections of two types, REL32 and ADDR64, are performed. Finally, the main wrapper function is called. The main wrapper calls the module initialization function in topological order and then calls the entry main function.

6. The fully static compilation method according to claim 1 or 5, characterized in that: In step S4, the PE loading and symbol resolution process specifically includes the following steps: B1. Use the Rust compiler to compile the loader source code into a standalone PE executable file; B2. At runtime, load all binary module files, parse the segment size, symbol count, relocation count and entry module name metadata of each module in its header, allocate executable memory pages and read-write memory pages through VirtualAlloc, and copy the module's code segment, data segment and read-only data segment to the corresponding memory area. B3. Traverse the symbol tables and relocation tables of all modules and parse each symbol in a multi-priority order; B4. For each record in the relocation table, perform the corresponding address correction operation according to the relocation type; B5. Call the initialization functions of all modules in topological order. Each initialization function creates a namespace storage object for the module, executes the module's top-level statement, and sets the module's exported variables.

7. A method for running a TypeScript executable file, wherein the executable file is generated by the fully static compilation method according to any one of claims 1-6, characterized in that: The memory management process of the executable file includes the following steps: A1. Using unified NaN-tagging encoding, the encoding space of the IEEE754 double-precision floating-point number with all exponent bits set to 0x7FF and the mantissa being non-zero is divided into multiple type tag regions. The high 4 bits of each type tag store the type information, and the low 48 bits store the data index or pointer, enabling the direct transfer of 64-bit floating-point values ​​between the machine code generated by the compiler and the runtime DLL. A2. Create a thread-local generic reference counting pool. Each pool contains a slot vector and a list of free slots. When a value is allocated, a slot is obtained from the free list or a new slot is added and the reference count is initialized to 1. When a value is referenced, the reference count of the corresponding slot is incremented by 1. When a value is released, the reference count of the corresponding slot is decremented by 1. When the reference count drops to 0, the slot is marked as free and recycled to the free list. Sub-values ​​are released recursively. A3. When generating machine code, the compiler does not immediately call the release function for short-term temporary values, but accumulates them in the delayed release vector and releases them in batches at the boundaries of basic blocks; The memory management process of the executable file includes the following steps: C1. Receives style descriptions passed in from the JavaScript layer; C2. Based on the parsed style information, perform the complete Flex layout algorithm on the child nodes of the node; C3. Recursively traverse the virtual node tree starting from the root node. For each node, execute the following steps in sequence: parse style, calculate box model, draw its own style, handle absolute and fixed positioning child nodes, register event handlers, clip overflow content, and recursively render child nodes. C4. Convert all drawing operations into abstract rendering commands and add them to the processing queue. During frame rendering, sort all commands by z-index, traverse and call the corresponding Direct2D drawing primitives for rasterization, and finally submit the rendering results to the window.

8. The method for running a TypeScript executable file according to claim 7, characterized in that: In step C2, the Flexbox layout algorithm specifically includes the following steps: Step 1: Determine the main axis and cross axis based on the flex-direction style property. row indicates that the main axis is horizontal and the cross axis is vertical, and column indicates that the main axis is vertical and the cross axis is horizontal. Step 2: For each child node, prioritize using explicit width or height values, then use flex-basis values, and if no explicit value is available, use the content estimate. Step 3: Calculate the sum of the base dimensions and spacing of all child nodes, and compare it with the main axis dimension of the container to obtain the remaining space; if the remaining space is positive and the total flex-grow coefficient is greater than zero, proceed to step 4; if the remaining space is negative and the total flex-shrink weighted coefficient is greater than zero, proceed to step 5. Step 4: Allocate the remaining space to the main axis size of each node according to the proportion of the flex-grow coefficient of each node to the total coefficient. For any remaining space caused by floating-point precision, add it to the size of the last node. Step 5: Compress the overflow space according to the proportion of the product of the flex-shrink coefficient and the reference size of each node to the total weighting coefficient. After compression, the main axis size of each node shall not be less than zero. Step 6: Adjust the main axis start position of each node according to the justify-content style property. flex-start arranges nodes from the start position, flex-end arranges nodes near the end position, center arranges nodes in the center, space-between arranges nodes with equal spacing and no spacing at the beginning and end, space-around arranges nodes with half the internal spacing at the beginning and end, and space-evenly arranges all spacings equally. Step 7: Based on the align-items and align-self style properties, adjust the starting position of each node along the cross axis according to the alignment factor to achieve alignment.

9. The method for running a TypeScript executable file according to claim 7, characterized in that: The event handling and dispatch process of the executable file includes the following steps: E1. Register event handlers in the JavaScript layer through the event properties of virtual nodes. The event handlers are stored in the event mapping table of the virtual nodes in the form of function references. E2. During the frame rendering process of the Rust rendering layer, scene nodes are created sequentially for each interactive virtual node through the scene graph API, and the node position, size, z-index and event handler references are registered to the scene graph. E3. Capture operating system-level input events through the WinIT event loop, convert the event coordinates from physical pixels to logical pixels, and store them in global atomic variables; E4. After the mouse event is triggered, the dirty flag is set to true. The dirty flag is checked in the RedrawRequested event of the next frame. The JavaScript frame rendering callback is called only when the dirty flag is true. The dirty flag is cleared after the dirty rendering is completed. E5. After the frame rendering callback is executed, read the coordinates of the click event to be processed from the global atomic variable, traverse the scene graph nodes in reverse z-index to perform rectangle hit test, and call the handler when the hit node has registered a click event handler. For hover events, after each rendering, the mouse coordinates are read to perform a hit test, and a hover entry or hover exit callback is triggered when the hit state changes. E6. After each rendering, `call_frame_handler` reads the current mouse coordinates from `MOUSE_X` and `MOUSE_Y` and calls the `element_registry::process_hover` function. `process_hover` traverses the scene graph nodes and performs a hit test. If the mouse hits the currently hovering element and the hit state has not changed, no callback is triggered. When the mouse enters the hit state from a non-hit state, a hover entry callback is triggered with parameters (id, 1.0). When the mouse leaves the hit state, a hover exit callback is triggered with parameters (id, 0.0). The hit state is maintained through the global atomic variable `HOVERED_ELEMENT_ID`.

10. A static compilation system for TypeScript executable files, used to implement the fully static compilation method according to any one of claims 1-6, characterized in that: include: (i) Dependency graph construction module, used to parse the import / export statements of the entry file and all dependent modules, construct the module dependency graph and sort it by topological order, assign a unique identifier to each module, and construct an export mapping table containing function exports and variable exports; (ii) Module compilation module, which is used to traverse all modules in topological order, and execute SWC parsing to AST, HIR conversion, CraneliftIR code generation, and COFF format object file generation for each module in sequence, and finally outputs binary module file. During the compilation process, the reference count release of temporary string values ​​is managed through a delayed batch release mechanism at the basic block construction point. (iii) The main wrapper generation module is used to generate the main wrapper function in x86-64 machine code format, call the initialization functions of all modules in topological order, and then call the entry main function; (iv) Loader compilation and linking module, which is used to call the Rust compiler to independently compile a PE loader with zero third-party dependencies.