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

@gasm-compiler/core

v0.9.0

Published

Rust/Wasm Gasm compiler for WebAssembly to WGSL (WebGPU Shading Language)

Downloads

677

Readme

@gasm-compiler/core

Compile WebAssembly to WGSL for GPU Execution

Transform WebAssembly binaries into WGSL (WebGPU Shading Language) compute shaders. Write your GPU kernels in any language that compiles to WebAssembly (C, C++, Rust, Go, AssemblyScript, or hand-written WAT), then run them on the GPU via WebGPU.

Gasm v0.2 is the default through the Rust/Wasm compiler backend. Archived Gasm v0.1 behavior remains available through an explicit compatibility option.


Installation

npm install @gasm-compiler/core

The compiler core is distributed as a Rust-generated WebAssembly artifact. No TypeScript runtime dependency is required by consumers.


Quick Start

import { compile } from "@gasm-compiler/core";

// Load a WebAssembly binary (.wasm file)
const wasmBytes = new Uint8Array(await fetch("shader.wasm").then(r => r.arrayBuffer()));

// Compile to WGSL
const wgslCode = compile(wasmBytes);

// Use with WebGPU
const shaderModule = device.createShaderModule({ code: wgslCode });

Features

  • 120+ WebAssembly instructions mapped to WGSL equivalents
  • Full L0 conformance (i32, i64, f32, f64 scalar operations)
  • Control flow restructuring — WebAssembly's unstructured branches become WGSL loops/blocks
  • Sub-word memory access — i8/i16 loads/stores lowered to word-aligned operations
  • Gasm built-in globals for GPU thread identification
  • Optional math extension for direct WGSL built-in math calls
  • Works in Node.js, Deno, and browsers

Usage

Specification Versions

Gasm v0.2 is the default:

const wgsl = compile(wasmBytes);

The default enables strict v0.2 validation and lowering. Existing consumers can keep the archived v0.1 compiler behavior explicitly:

const wgsl = compile(wasmBytes, { specVersion: "0.1" });

Compile a v0.2 artifact and metadata sidecar through the Rust/Wasm compiler:

import {
  compileToArtifact,
  validateGasmMetadataSchema,
} from "@gasm-compiler/core";

const result = compileToArtifact(wasmBytes);
if (!result.ok) {
  throw new Error(
    `${result.diagnostics.errors[0]?.code}: ` +
      `${result.diagnostics.errors[0]?.message}`,
  );
}

const schema = validateGasmMetadataSchema(result.metadata);
if (!schema.valid) throw new Error(schema.errors.join(", "));

All Gasm compiler semantics, including explicit v0.1 compatibility mode, are implemented in packages/core-rs and distributed through its Wasm artifact. The TypeScript package code is limited to host integration, artifact metadata, source-map comments, preparation helpers, and execution APIs. Deno remains the runtime for the CLI and the live core/CLI test suites, including headless WebGPU execution.

The CLI also defaults to v0.2:

gasm-compiler compile input.wasm \
  --output output.wgsl \
  --metadata output.gasm.json

Use --spec-version 0.1 when compiling archived v0.1 inputs.

Migrating from 0.5.x

  • The Rust/Wasm compiler is now the only compiler backend. The GASM_CORE_BACKEND environment variable no longer changes compilation.
  • Browser backend selection APIs have been removed: setBrowserCompilerBackend(), getBrowserCompilerBackend(), and BrowserCompilerBackend.
  • TypeScript/Rust comparison APIs and their result types have been removed: compileWithBackendComparison(), compileWithBackendComparisonAsync(), BackendComparisonResult, and BackendMismatchDetails.
  • Remove backend-selection and comparison UI from integrator applications and call compile(), compileWithDiagnostics(), or compileWithDiagnosticsAsync() directly.
  • Consumers no longer need to install TypeScript as a peer dependency of @gasm-compiler/core.

Migrating from 0.3.x

  • Compilation now defaults to strict Gasm v0.2 validation.
  • Pass { specVersion: "0.1" } to retain archived v0.1 behavior.
  • Gasm v0.2 extensions must be declared in the module's gasm.extensions custom section.
  • Math extension scalar imports use explicit type suffixes such as sin_f32. Legacy unsuffixed imports remain accepted for compatibility.

Required extensions are declared by the module's gasm.extensions custom section. The CLI does not inject extensions, so validation reflects the exact module that will be distributed.

Integrator Workflow

Playgrounds, compiler backends, and other embedders can prepare transient Wasm without modifying their producer toolchain:

import {
  compileWithRuntimeInfo,
  prepareModule,
} from "@gasm-compiler/core/browser";

const prepared = prepareModule(wasmBytes, {
  demotionPolicy: { f64: "allow", i64: "allow-lossy" },
});
if (prepared.errors.length > 0) {
  throw new Error(prepared.errors[0].message);
}

const result = compileWithRuntimeInfo(prepared.wasmBytes, {
  ...prepared.compileOptions,
  mode: "strict",
});
if (!result.ok) throw new Error(result.diagnostics.errors[0].message);

prepareModule() defaults to integrator mode. It infers required extensions, merges a stable gasm.extensions section, and returns binding and mutable-global initialization data. Modules with undeclared mutable defined globals use the v0.1 private-global compatibility path to avoid shared-storage races.

Use { mode: "strict" } to analyze a distribution artifact without changing its bytes. Strict compilation through compile() and compileWithDiagnostics() remains unchanged and never injects extensions.

compileWithRuntimeInfo() is also available from the main and browser entry points. It combines preparation, compilation, binding metadata, dispatch information, and mutable-global initialization into one result.

Basic Compilation

import { compile } from "@gasm-compiler/core";

const wgslCode = compile(wasmBytes);

Compilation Options

import { compile } from "@gasm-compiler/core";

const wgslCode = compile(wasmBytes, {
  workgroupSize: [128, 1, 1],  // Default: [64, 1, 1]
  minify: true,                 // Optimize and emit compact, single-line WGSL
  mathExtension: true,          // Enable gasm:math built-ins
});

minify: true enables optimization, shortens internal identifiers and literals, removes comments and formatting, and emits a single-line shader. Exported entry-point names and metadata-visible resource names are preserved. Minification cannot be combined with optimize: false, source mapping, or compiler metadata.

Math Extension

Enable direct mapping of WebAssembly imports to WGSL built-in math functions:

const wgslCode = compile(wasmBytes, {
  mathExtension: true,    // Enable all levels (M0, M1, M2)
  // or: mathExtension: "M0"   // Core scalar functions only
  // or: mathExtension: "M1"   // Core + vector functions
  // or: mathExtension: "M2"   // All functions
});

When enabled, WebAssembly imports like (import "gasm" "sin_f32" (func ...)) compile to direct WGSL built-in calls (sin(...)) with zero overhead. Unsuffixed scalar names such as sin remain accepted as legacy aliases.

Math Levels:

  • M0 (Core): sin, cos, sqrt, abs, min, max, clamp, floor, ceil, etc.
  • M1 (Vector): length, dot, cross, normalize, reflect, refract, etc.
  • M2 (Advanced): modf, frexp, ldexp, degrees, radians, bit manipulation

See also: @gasm-compiler/math-reference for CPU-side reference implementations of these math functions.

Error Handling

import { compile, isCompileError } from "@gasm-compiler/core";

try {
  const wgslCode = compile(wasmBytes);
} catch (error) {
  if (isCompileError(error)) {
    console.error("Compile Error:", error.message);
    if (error.location) {
      console.error(`  at line ${error.location.line}, column ${error.location.column}`);
    }
  } else {
    throw error;
  }
}

Browser Usage

import { compile } from "@gasm-compiler/core/browser";

const wgslCode = compile(wasmBytes);

The compiler has no required browser initialization step. For applications that want to fetch and cache the Wasm compiler ahead of time, the browser entry point also exposes an optional async path:

import { compileAsync, preloadCompiler } from "@gasm-compiler/core/browser";

await preloadCompiler();
const wgslCode = await compileAsync(wasmBytes);

Using with WebGPU

import { compile } from "@gasm-compiler/core";

// 1. Compile Wasm → WGSL
const wgslCode = compile(wasmBytes, { workgroupSize: [256, 1, 1] });

// 2. Create shader module
const shaderModule = device.createShaderModule({ code: wgslCode });

// 3. Create compute pipeline
const pipeline = device.createComputePipeline({
  layout: "auto",
  compute: { module: shaderModule, entryPoint: "main" },
});

// 4. Dispatch
const commandEncoder = device.createCommandEncoder();
const pass = commandEncoder.beginComputePass();
pass.setPipeline(pipeline);
pass.setBindGroup(0, bindGroup);
pass.dispatchWorkgroups(numWorkgroups);
pass.end();
device.queue.submit([commandEncoder.finish()]);

How It Works

The compiler transforms WebAssembly into WGSL through a multi-phase pipeline:

WebAssembly Binary (.wasm)
        ↓
   Parse & Validate (Gasm restrictions)
        ↓
   Convert to SSA form
        ↓
   Restructure control flow (Relooper)
        ↓
   Lower memory operations
        ↓
   WGSL Code Generation
        ↓
WGSL Compute Shader (.wgsl)

Gasm Restrictions

Your WebAssembly module must conform to the Gasm subset:

  • Single memory — max 1 linear memory, exported as "memory"
  • Single table — max 1 table (for indirect calls)
  • Global imports only — no function or memory imports (except Gasm built-in globals)
  • Structured control flow — all branches must be restructurable

Gasm Built-in Globals

Import GPU thread identifiers as WebAssembly globals from the "gasm" module:

| Import Name | Maps to WGSL | Type | |-------------|--------------|------| | global_invocation_id_x/y/z | @builtin(global_invocation_id) | u32 | | local_invocation_id_x/y/z | @builtin(local_invocation_id) | u32 | | workgroup_id_x/y/z | @builtin(workgroup_id) | u32 | | num_workgroups_x/y/z | @builtin(num_workgroups) | u32 |

Example (WAT):

(module
  (import "gasm" "global_invocation_id_x" (global $gid_x i32))
  (memory (export "memory") 1)
  (func (export "main")
    ;; Use $gid_x to index into memory per-thread
  ))

Instruction Support

| Category | Examples | WGSL Output | |----------|---------|-------------| | Arithmetic | i32.add, f32.mul | a + b, a * b | | Bitwise | i32.and, i32.shl | a & b, a << (b & 31u) | | Comparisons | i32.lt_s, f32.eq | a < b, a == b | | Memory | i32.load, i32.store8 | memory[addr/4u], bit-masking | | Conversions | i32.trunc_f32_s | i32(trunc(a)) | | Control Flow | block, loop, br_if | loop { ... }, if (c) { break; } | | Variables | local.get, global.set | var_N, global_N = val |


API Reference

compile(source, options?)

function compile(source: Uint8Array, options?: CompileOptions): string

Compiles a WebAssembly binary to WGSL.

Parameters:

  • source — WebAssembly binary as Uint8Array
  • options — Optional CompileOptions

Returns: WGSL shader code as a string

Throws: CompileError on validation or compilation failure

compileAsync(source, options?)

function compileAsync(source: Uint8Array, options?: CompileOptions): Promise<string>

Async equivalent of compile. In browsers this can be paired with preloadCompiler() to fetch and instantiate the compiler artifact before the first compilation.

compileWithDiagnostics(source, options?)

function compileWithDiagnostics(
  source: Uint8Array,
  options?: CompileOptions,
): CompileWithDiagnosticsResult

Compiles a WebAssembly binary and returns diagnostics instead of throwing.

compileWithDiagnosticsAsync(source, options?)

function compileWithDiagnosticsAsync(
  source: Uint8Array,
  options?: CompileOptions,
): Promise<CompileWithDiagnosticsResult>

Async equivalent of compileWithDiagnostics.

preloadCompiler(options?)

function preloadCompiler(options?: { wasmUrl?: string | URL }): Promise<void>

Optional performance hook for browser applications that want to load the compiler before the first call to compileAsync.

CompileOptions

interface CompileOptions {
  workgroupSize?: [number, number, number];  // Default: [64, 1, 1]
  debug?: boolean;                           // Emit debug comments (default: false)
  mathExtension?: boolean | "M0" | "M1" | "M2";  // Enable math built-ins
}

CompileError

interface CompileError {
  type: "CompileError";
  message: string;
  location?: { line: number; column: number };
  context?: string;
}

isCompileError(error)

function isCompileError(error: unknown): error is CompileError

Type guard for CompileError.


Related Packages


License

See LICENSE for details.