Consuming from the Browser
Status: live.
@gdscript-analyzer/wasmis published and this is its real, shipped surface — try it in the playground (plans/ROADMAP.mdtracks what's still ahead on the road to1.0).
For in-page analysis — web playgrounds, browser-based editors (Monaco / CodeMirror), or any client that can't load a native addon — there is a WebAssembly build:
npm i @gdscript-analyzer/wasm
How the wasm build is produced
The shipped route is a dedicated bindings/wasm crate built with
wasm-bindgen (wasm-pack build --target web), sharing the engine-neutral
gdscript-session core with the Node binding — not the napi-rs
wasm32-wasip1-threads target originally sketched in
ADR-0003 (see that ADR's amendment
note). This keeps the artifact small with no SharedArrayBuffer/COOP-COEP
requirement — the approach Biome and Ruff take. See
plans/01-ARCHITECTURE.md §4.
The shape across the boundary
As in Node, the wasm module holds a stateful, URI-keyed Analyzer session and
returns results as native JS values (via serde-wasm-bindgen, JSON-compatible
mode) per query. Strings and structs cross the boundary by copy, so a query
returns only its feature result — never a full AST per call.
import init, { Analyzer } from "@gdscript-analyzer/wasm";
await init(); // load + instantiate the .wasm module
const az = new Analyzer();
az.openDocument("inmemory://main.gd", "extends Node\nfunc f(): pass\n", null);
const diagnostics = az.diagnostics("inmemory://main.gd"); // byte offsets in, native JS out
Analyzer also exposes changeDocument/closeDocument,
setProjectConfig/setWorkspaceComplete/setWarningOverride,
loadEngineApi(bytes) (to enable engine-class completion/hover — see below),
and one method per IDE feature (completions, hover, signatureHelp,
codeActions, gotoDefinition, findReferences, rename,
workspaceSymbols, semanticTokens, foldingRanges, inlayHints, format,
formatRange, syntaxTree) — see the
wasm package README
for the full, current list.
Engine data is shipped separately
The Godot engine model (extension_api.json) is several megabytes, so it is
not include_bytes!'d into the wasm module. Fetch the bundled binary blob
and hand it to loadEngineApi(bytes) to enable engine-class
completion/hover — see the wasm package README for where to source it.
Portability is enforced from day one
The core crates must compile to wasm32 — no std::fs, no
Instant::now()/SystemTime::now(), no threads in the hot path, and
getrandom's JS backend only in the wasm binding. CI runs
cargo check -p gdscript-ide --target wasm32-unknown-unknown on every PR. The
full rules are in plans/01-ARCHITECTURE.md §7.