feat: embed SWC TypeScript transpiler and load .ts modules directly#226
Open
benpalevsky wants to merge 1 commit into
Open
feat: embed SWC TypeScript transpiler and load .ts modules directly#226benpalevsky wants to merge 1 commit into
benpalevsky wants to merge 1 commit into
Conversation
Compiles a Rust staticlib (transpiler-ffi/) built around SWC and exposed through a minimal two-function/one-struct C FFI, wired into the engine via SCsub. jsb_module_resolver loads .ts sources directly by transpiling them in-process into the CommonJS module wrapper, so TypeScript no longer needs a separate tsc emit step to run. Opt-in via a new use_typescript_transpiler build flag, off by default. With the flag off (the default) no Rust toolchain enters the build graph and every .ts code path is compiled out behind JSB_WITH_TYPESCRIPT_TRANSPILER: script loading keeps using the tsc-emitted .js (convert_typescript_path), the resolver does not probe .ts, and the build behaves as before this change. The FFI is panic-safe (catch_unwind at the boundary) and hands buffers to C through Box<[u8]> so the C-side free is sound. Build flags in SCsub allow the staticlib's libstd symbols to coexist with Godot's prebuilt accesskit staticlib on Linux/Windows.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part 1 of 3 — the SWC stack. Foundation; PRs 227 and 228 build on this one.
Problem
Today, a
.tsfile has to be compiled to.jsbytscbefore GodotJS can run it. That means a separate build step and a dependency on having TypeScript installed.What this adds
An embedded TypeScript transpiler, so the engine can load
.tsmodules directly. A small Rust library (SWC, a fast TypeScript-to-JavaScript compiler) is built into the engine and called through a tiny interface — two C functions and one struct. When a.tsmodule loads, it's transpiled in-process and run, with no separatetscstep.It is opt-in and off by default: the transpiler only builds with
scons use_typescript_transpiler=yes. With the flag off (the default), no Rust toolchain is needed and the build is unchanged from today.The pieces:
transpiler-ffi/— the Rust staticlib and its C header (the two-function/one-struct boundary).SCsub/config.py— theuse_typescript_transpilerbuild flag (default off), and building/linking the staticlib when it's on.bridge/jsb_module_resolver.cpp— transpile.tson load, and probe for.tsduring resolution. Both are behind#if JSB_WITH_TYPESCRIPT_TRANSPILER, so with the flag off the resolver behaves exactly as today (no.tsprobe, no transpile path).weaver/jsb_script.cpp— with the flag on, attach a.tsscript by loading the.tssource directly (transpiled in-process); with the flag off it keeps loading thetsc-emitted.jsviaconvert_typescript_path, as before this change.What it costs (please weigh this)
With the flag on, building the engine needs a Rust toolchain (
cargoonPATH), and the first build downloads and compiles the SWC dependency tree (pinned inCargo.lock). With the flag off — the default — there is no new prerequisite: no Rust, no cargo build, and the engine builds exactly as it does today.Robustness
The Rust FFI is panic-safe: a panic inside the transpiler (for example SWC choking on malformed input) is caught at the C boundary and returned as an error result, never unwinding into the engine.
How to verify
use_typescript_transpiler=yes: build on Linux, Windows, and macOS — the static-link fix (allowing duplicaterust_eh_personalitysymbols against Godot's prebuilt static libs) specifically needs cross-platform confirmation. Then load a.tsmodule and confirm it runs without a separatetscstep.A changeset is included.