npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

maiac

v1.2.13

Published

MaiaC (WebC): C89-subset to WebAssembly compiler in JavaScript.

Readme

MaiaC (WebC)

MaiaC is a C-to-WebAssembly compiler focused on a practical C89 subset and a browser/Node execution workflow.

Process Documentation

Mandatory cross-repository synchronization workflow:

Overview

MaiaC currently provides:

  • C source parsing from EBNF-generated parser artifacts.
  • Semantic lowering to a WAT module model.
  • WAT emission through template-based backend code.
  • Validation/assembly through MaiaWASM.
  • Runtime execution support in Node and browser wrappers.

The project uses two local submodules:

  • MaiaCC: grammar-to-parser generation.
  • MaiaWASM: WAT assembler and validation pipeline.

Repository Structure

  • compiler/: parser integration, semantic analysis, lowering, WAT generation, tests.
  • grammar/: C grammar source files.
  • tools/: parser generation scripts, runtime helpers, browser runner.
  • bin/: convenience wrappers (webc.sh, run-test-node.sh, run-wasm-browser.sh).
  • docs/: project documentation.
  • maiacc/: MaiaCC submodule.
  • maiawasm/: MaiaWASM submodule.

Quick Start

1) Build the C parser from EBNF

bash tools/build-c-parser.sh

2) Compile a C file to WAT and validate

bash bin/webc.sh --file ./compiler/examples/test.c --wat-out ./out/test.wat

3) Run a compiled program in Node

bash bin/run-test-node.sh compiler/examples/test.c

4) Run in browser (development runner)

bash bin/run-wasm-browser.sh

Then open:

  • http://127.0.0.1:8080/tools/browser/run-wasm.html

Runtime Tooling (Consistent Flow)

tools/webc.js (compile + wrapper + optional run + dist)

webc compiles a C source and emits:

  • <out>.wasm
  • <out>.js wrapper (createImports() + run())
  • optional <out>.wat

It can also package a complete distributable folder (--dist) containing browser and Node runners.

Example:

node tools/webc.js compiler/examples/test.c -o out/test --wat

Run immediately:

node tools/webc.js compiler/examples/test.c -o out/test --run

Optional (experimental include expansion):

node tools/webc.js compiler/examples/test.c -o out/test --run --resolve-system-includes

Create distribution package (browser + node):

node tools/webc.js compiler/examples/test.c --dist --out-dir dist --name test --wat

Create dist and run generated Node runner in one step:

node tools/webc.js compiler/examples/test.c --dist-run --out-dir dist --name test

Dist outputs include:

  • dist/test.wasm
  • dist/test.js
  • dist/test.wat (when --wat is used)
  • dist/manifest.json
  • dist/browser-runner.html
  • dist/browser-memory-file-store.js
  • dist/node-runner.js
  • dist/node-runner.sh

Run from dist in Node:

node dist/node-runner.js
# or
bash dist/node-runner.sh

Run from dist in browser: serve the repo root and open dist/browser-runner.html.

tools/create-dist.js (compatibility wrapper)

create-dist.js remains available for backward compatibility and delegates to webc --dist internally:

node tools/create-dist.js compiler/examples/test.c -o dist --name test --wat

tools/host-env-builder.js (extern __host__path bridge)

host-env-builder converts compiler hostImports metadata into imports.env functions.

C example:

extern void __console__log(char *msg);
extern double __Math__sin(double x);

At runtime this maps to console.log(...) and Math.sin(...), with automatic C string dereference for char * parameters.

Recommended Validation Flow

Use this sequence to validate compiler/runtime behavior quickly and consistently.

1) Core large example (compiler/examples/test.c)

node tools/webc.js compiler/examples/test.c -o out/test --run
node tools/run-test-node.js compiler/examples/test.c
node tools/webc.js compiler/examples/test.c --dist --out-dir dist --name test
node dist/node-runner.js

Expected result: all commands complete and return 0.

2) Host extern bridge (compiler/examples/test-extern.c)

node tools/webc.js compiler/examples/test-extern.c -o out/test-extern --run
node tools/run-test-node.js compiler/examples/test-extern.c

Expected result: host calls such as __console__log and __Math__sqrt execute correctly and return 0.

3) About --resolve-system-includes

  • This flag is optional and currently experimental for complex sources.
  • It is useful when you explicitly want inline expansion of system headers.
  • The default validation path for test.c and test-extern.c should run without this flag.

setjmp/longjmp Runtime Semantics (Current)

  • Current implementation is host-assisted and emulated resume.
  • longjmp restores __stack_ptr/__frame_ptr, signals unwind, and runtime re-enters the program entrypoint.
  • The next setjmp capture for the same jmp_buf returns the pending value (longjmp(..., 0) normalizes to 1).
  • This is now handled consistently in:
    • tools/run-test-node.js
    • tools/webc.js --run
    • generated wrapper run()
    • webc --dist browser runner page
    • webc --dist node runner scripts

Compiler CLI

Main CLI entrypoint:

  • compiler/c-compiler.js

Typical options:

  • --code <c-code>: compile inline source.
  • --file <path>: compile source from file.
  • --ast: print parse tree.
  • --print-json, --print-xml: print parse outputs.
  • --json-out, --xml-out: write parse outputs.
  • --wat-out: write generated WAT.
  • --wasm-out: write assembled WASM.
  • --no-wat: suppress WAT stdout.
  • --no-validate: skip validation/assembly.

Example:

node compiler/c-compiler.js --file ./compiler/examples/test.c --wat-out ./out/test.wat --wasm-out ./out/test.wasm

Test Strategy

Run the full bundle:

node compiler/tests/test-all.js

Run full regression (bundle + additional focused diagnostics):

bash tools/run-full-tests.sh
# or
npm run test:full

Includes:

  • Preprocessor tests.
  • C89 mini-suite runtime validation.
  • Rich C89 example-suite dist/runtime validation (compiler/examples/suite/).
  • Large end-to-end example test.
  • stdarg end-to-end tests.
  • setjmp/longjmp bootstrap + emulated-resume tests.

The full-regression script also executes focused tests that are intentionally kept outside test-all.js (debug/diagnostic pointer and WAT checks) to provide a broader post-change safety net.

Optional JSON report:

node compiler/tests/test-all.js --json-out compiler/tests/outputs/test-report.json

For mini-suite artifacts (disabled by default):

MAIAC_WRITE_TEST_OUTPUTS=1 node compiler/tests/test-c89-mini-suite.js

For the rich example suite directly:

bash compiler/examples/suite/build_all.sh
bash compiler/examples/suite/run_all.sh

Examples (Large + Small)

Large Example (test.c) in Node

node tools/examples/run-test-node-example.js

Large Example (test.c) in Browser

  1. Build wasm:
node tools/examples/build-test-wasm.js
  1. Serve the repository root:
bash bin/run-wasm-browser.sh
  1. Open:
  • http://127.0.0.1:8080/tools/browser/test-large.html

Small Example (simple_add.c) in Node

node tools/examples/build-simple-add-wasm.js
node tools/examples/run-simple-add-node.js

Small Example (simple_add.c) in Browser

After starting the same browser server (bin/run-wasm-browser.sh), open:

  • http://127.0.0.1:8080/tools/browser/simple-add.html

Architecture Documentation

For system design, data flow, and diagrams, see:

Bootstrap details:

Consistency Rules for Submodules

  • maiacc in MaiaC and MaiaWASM should reference the same canonical MaiaCC commit.
  • Parser changes should be made in grammar sources and regenerated, not edited directly in generated parser files.
  • When MaiaWASM parser changes are required, update grammar/WAT.ebnf, regenerate assembler/wat-parser.js, and then update MaiaC submodule pointer.

Current Scope and Notes

  • Current target is a practical C89 subset with strong runtime validation.
  • Some advanced C/library features remain intentionally out of scope.
  • Keep generated test artifacts out of version control unless explicitly needed.