Skip to content

Fork with kernel 41.2, ESM + Bun/Deno support, and ~2x faster async runtime — interest in upstreaming? #46

Description

@pyrex41

Hi Robert — first off, thank you for ShenScript. The async-transparent design has held up remarkably well, and I've been building on it heavily.

I've been maintaining a fork at pyrex41/ShenScript and wanted to surface the work in case any of it is useful upstream. Summary of what's there:

Modernization

  • Migrated to ES modules; runs on Node 20+, Bun, and Deno 2 (CI runs the kernel suite on all three)
  • Targets ShenOSKernel 41.2 (vendored from Shen-Language/shen-sources with checksums/provenance)

Performance — the kernel certification suite went from 19.0s (Node) / 50.1s (Bun) to ~10s / ~19.5s on the same machine, via three changes that preserve semantics (all 134 kernel tests + extensions pass on all three runtimes, REPL/trap-error/Prolog/eval-redefinition verified):

  1. Arity-specialized function wrappers (7841d8b) — funSync/funAsync emit fixed-parameter wrappers for arities 0–4 instead of variadic (...args) wrappers; rest/spread on every call was a dominant cost on JavaScriptCore and a measurable one on V8.
  2. No double promise layer (0bc94ed) — async wrappers became plain functions returning the callee's promise directly, with an async: true own-property marker replacing instanceof AsyncFunction checks where wrappers are observed.
  3. Compile sync where provable (ef36617) — call sites in async contexts compile to a conditional await ((w$ = $.t(f(...))) instanceof Promise ? await w$ : w$), any compiled lambda whose body contains no await is emitted as a plain function (66% of kernel lambdas), and let flattens to scoped assignments instead of awaited async IIFEs (2330 → 41 in the rendered kernel). Because callers test the result dynamically, runtime redefinition via eval — including redefining a sync-compiled function to an async one — keeps working with no restrictions.

While profiling this I also filed oven-sh/bun#32208; Bun's team confirmed the remaining Bun-vs-Node gap is JSC engine-level async-frame/promise-allocation throughput, not anything in ShenScript's design.

New capability — the fork is also a stage-2 target for Ratatoskr (a tree-shaker for Shen descended from Mark Tarver's Yggdrasil): a shaken, eval-stripped Shen program compiles ahead of time into one self-contained ~140 KB ES module with ~50 ms startup on Bun/Deno.

I realize this repo has been quiet for a while and the fork has diverged a fair bit (ESM + kernel bump underneath everything), so rather than open a large unsolicited PR I wanted to ask: is there interest in any of this landing upstream? The three performance changes are the most self-contained pieces — I'd be happy to discuss backporting them to the current codebase, or whatever form is most useful to you. And of course feel free to cherry-pick anything directly; it's all under the same BSD-3 license with your copyright intact.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions