Skip to content

feat(deno): Deno runtime support#1060

Draft
lu-zero wants to merge 12 commits into
anomalyco:mainfrom
lu-zero:deno-support
Draft

feat(deno): Deno runtime support#1060
lu-zero wants to merge 12 commits into
anomalyco:mainfrom
lu-zero:deno-support

Conversation

@lu-zero

@lu-zero lu-zero commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Deno runtime support to opentui, building on top of the debun-urls branch (PR #1027). With this, opentui core runs under Deno with native FFI, tree-sitter highlighting, and test infrastructure.

What's included

  • Root deno.json with sloppy-imports and deno task test:core / test:solid
  • Core deno.json import map: bun:ffibun-compat@0.4.2, bun:test@std/testing shim, @opentui/core → src, node: builtins
  • bun-test.ts shim delegating to @std/testing/bdd, @std/expect, @std/expect/fn with spyOn/mockImplementation compatibility and auto-installing bun-compat for globalThis.Bun
  • Solid deno.json with npm:solid-js specifiers and jsx-runtime mapping
  • jsx-runtime.ts for Deno-compatible JSX transformation
  • Module workers ({ type: "module" }) for Deno compat
  • WASM fallback from with { type: "wasm" } to import.meta.resolve + URL
  • FFI bun:ffi fallback when node:ffi is unavailable (bun-compat)
  • Timer/worker cleanup for Deno's strict leak detection
  • isBunRuntime check in resolveBundledFilePath to distinguish real Bun from bun-compat shim
  • Platform shim for native binary path resolution using import.meta.url

Test results

Deno: 225 passed (1349 steps), 3 failed

  • 2 failures are Deno leak detection strictness (signal handlers, FFI resources)
  • 1 failure uses Bun.serve (Bun-only test)

Bun: 58/58 pass (no regressions)

How to test

# Run core lib tests under Deno
deno test --allow-all --no-check --config packages/core/deno.json packages/core/src/lib/

# Run a demo under Deno
deno run --allow-all --config packages/core/deno.json packages/examples/src/console-demo.ts

Dependencies

Known limitations

  • --no-check needed (type errors from Deno stdlib mismatches)
  • 3 test failures due to Deno's stricter resource leak detection
  • Solid tests need further reconciler/renderer lifecycle work under Deno

simonklee and others added 12 commits May 10, 2026 12:11
Bare `import ... with { type: "file" }` and direct Worker
construction are Bun-specific. Route asset path resolution through
resolveBundledFilePath() and worker creation through PlatformWorker
so tree-sitter operates correctly across runtimes.
The native package loader, FFI backend, and tree-sitter parser
initialization all used top-level await with Bun-specific import
patterns. Replace with synchronous require for FFI, conditional
exports for native packages, and deferred async loading for parsers
so the package works under Node.js and Deno in addition to Bun.

Issue anomalyco#2
The tree-sitter WASM still loaded via a direct import that only
Bun's bundler resolves; route it through resolveBundledFilePath
alongside the other bundled assets so Node and Deno builds work.

Tighten toBigIntPointer to reject negative bigints and out-of-range
numeric values. Bad pointers now throw at the conversion boundary
instead of reaching the FFI backend as invalid addresses. The Zig
render lib uses the validated toPointer helper for buffer reads.
The encodeUnicode result pointer was non-nullable, so empty input
had no clean representation. Make the output pointer nullable,
short-circuit zero-length input to a null result, and accept the
null/zero pair in freeUnicode so callers can encode and free
unconditionally.
Root deno.json with sloppy-imports and test tasks. Core deno.json
maps bun:ffi → bun-compat 0.4.2, bun:test → @std/testing bdd shim,
@opentui/core → src, and node: builtins. Bun-test shim delegates
to @std/testing/bdd, @std/expect, @std/expect/fn with spyOn compat
and auto-installs bun-compat for globalThis.Bun. Solid deno.json
maps solid-js to npm: specifiers. Add jsx-runtime.ts for
Deno-compatible JSX transformation.
…fallback

Use { type: "module" } in Worker constructor for Deno compat.
Fall back from with { type: "wasm" } to URL-based WASM
resolution. Clear dispose timeout on worker response. Stop
worker before clearing callbacks. Guard handleWorkerMessage
against destroyed state. Call preventDefault on worker error.
Add bun:ffi fallback when node:ffi unavailable (bun-compat).
bun-compat sets globalThis.Bun under Deno, so checking for its
presence alone incorrectly triggers the with { type: "file" }
import path. Use process.versions.bun to distinguish the real
Bun runtime from the compat shim.
Fix @opentui/core/testing path (testing.ts not testing/index.ts).
Add solid-js/jsx-runtime mapping to local jsx-runtime.ts.
@simonklee

Copy link
Copy Markdown
Member

Thanks for this ­— but you're a bit too early. We need to go through refactoring to support node:ffi first, and only then we can consider another platform. Adding multiple platforms at once will just cause too much chaos.

@lu-zero

lu-zero commented May 13, 2026

Copy link
Copy Markdown
Contributor Author

I'll rebase on top of the node:ffi support once it is ready then :)

@simonklee

Copy link
Copy Markdown
Member

I'll rebase on top of the node:ffi support once it is ready then :)

I may cherry pick a couple of the the things you have here, tbh. I think the resolveBundledFilePath may be better than what i have and i haven't gotten around to the solid.js part yet. So i think in the end you'll need way less for Deno support.

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.

2 participants