Skip to content

feat(node): connect the client to the combined sysml-wasm module - #872

Merged
HuiJun merged 6 commits into
developfrom
feature/node-wasm-transport
Oct 4, 2026
Merged

HuiJun merged 6 commits into
developfrom
feature/node-wasm-transport

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Lets @openmbee/opensysml run against the combined sysml-wasm WebAssembly module (#870, now on develop) instead of a native sysml-grpc, in Node and in the browser. The existing Connection, Model, values and errors are unchanged; only the transport is different.

  • src/core/wasm.ts:
    • createWasmTransport(host, options) is a Connect Transport. For each unary call it encodes the request with protobuf-es toJson and calls the module's call(method, json). A JSON-RPC error envelope becomes a ConnectError with the same code, and a result is decoded with fromJson (ignoreUnknownFields). It runs through runUnaryCall, so interceptors, onResponse taps, deadlines and abort signals all apply. Streaming calls answer Unimplemented.
    • connectWasmHost opens a Connection with JSON encoding and the usual GetServerInfo handshake, so version and capability checks behave as they do against a service. A call the module doesn't serve fails with MissingCapabilityError, or with UNIMPLEMENTED if the call isn't capability-gated.
    • instantiateInline starts Go in the current realm. It captures and removes globalThis.sysmlWasm so that a second instance can't overwrite the first.
    • loadGoConstructor(wasmExec) loads each wasm_exec.js once per specifier and caches its Go constructor. Loads are serialized, so modules built with different Go toolchains can run side by side.
      • A constructor is accepted only if that script freshly installed it. A script the realm already evaluated, or one that installs nothing, is rejected with an error that says to omit wasmExec and use the installed Go.
      • Afterwards a previous globalThis.Go is restored. A failed load leaves the global exactly as it found it.
      • With no wasmExec, the loader waits for in-flight loads and then uses the installed Go.
    • WorkerWasmHost and serveWasmPort share an init/call protocol for workers. Each call carries the request's AbortSignal. A cancelled or timed-out call is dropped from the pending table, and its late answer is ignored.
  • Node: connectWasm({ wasm, wasmExec, thread }) runs in a worker_threads worker by default (src/node/wasm-worker.ts); thread: "inline" runs it on the calling thread.
  • Browser: connectWasm({ wasm, wasmExec, worker }) runs inline, or in a module worker the caller creates from the new @openmbee/opensysml/browser/wasm-worker export. A page that loads wasm_exec.js itself omits wasmExec.
  • In this PR the caller supplies wasm and the matching wasm_exec.js. feat(release): publish sysml-wasm as release assets and an npm package #875 (stacked on this one) publishes them and resolves them automatically in Node.
  • CI: the build job also builds bin/wasm/sysml-wasm.wasm and copies the toolchain's wasm_exec.js. node-test points the tests at them with OPENSYSML_REQUIRE_WASM=1, so the WASM tests can't silently skip there.
  • Docs: a "WebAssembly, without a service" section in the client README, plus pointers in docs/reference/node-api.md, clients.md and wasm.md.

How it was verified

  • test/wasm.test.ts runs with both the worker and inline threads and compares results against the native connect() client:
    • loads + eval (integers, big integers, quantities, sequences)
    • symbol/children
    • diagnostics on an invalid model
    • instantiate, executeAction and executeState
    • multi-document parseSources
    • a second inline connection that reuses the cached runtime
  • It also covers capability-gated and ungated unserved calls, onResponse taps, close(), and a stale-version refusal that terminates the worker.
  • The browser entry point runs inline under Node.
  • Unit tests cover:
    • the transport: error envelope codes, unknown fields, aborts
    • the worker port protocol: init, call, failed init
    • Go runtime loading:
      • A → B → A identity and restore
      • a preloaded script rejected when wasmExec is passed but used when it's omitted
      • an empty script rejected and not cached
      • a throwing script that leaves no global
      • a lookup without wasmExec that waits for a concurrent load
    • 100 cancelled calls on a worker that never answers, which leave no pending entries
  • npm run build, typecheck, lint and npm test all pass (385 passed, 0 skipped), as does python3 scripts/changelog.py check.

Checklist

  • make test and make lint pass locally (client suite, lint and typecheck; the Go side is feat(wasm): add combined sysml-wasm command #870's, already on develop)
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (see CONTRIBUTING.md)
  • Changelog entry added as changes/unreleased/<slug>.<section>.md, not as an edit to CHANGELOG.md
  • baselines regenerated and make docs-counts run if a gate count moved (compliance rows need nothing: the census is counted at docs build)
  • No internal work-item labels (waves, slices, F4, K5) in the body, docs, or changelog

devin-ai-integration Bot and others added 3 commits October 4, 2026 00:24
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review October 4, 2026 01:16
devin-ai-integration[bot]

This comment was marked as resolved.

…e once

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Base automatically changed from feature/sysml-wasm to develop October 4, 2026 01:40
devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@HuiJun
HuiJun merged commit e6b62d1 into develop Oct 4, 2026
24 checks passed
@HuiJun
HuiJun deleted the feature/node-wasm-transport branch October 4, 2026 03:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant