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

forge-runtime

v0.1.7

Published

Experimental browser runtime built on top of WebAssembly, Workers, SharedArrayBuffer, Atomics, and IndexedDB.

Readme

forge-runtime

Environment Support

Forge Runtime is currently focused on modern browsers and browser runtime experimentation. | Feature | Browser | Node.js | |---------------------------------|---------|---------| | Memory APIs | ✅ | ⚠️ Experimental | | Worker Pool | ✅ | ❌ | | Virtual Filesystem (IndexedDB) | ✅ | ❌ | | Shared Memory | ✅ | ❌ | | Atomics | ✅ | ❌ | | Channels | ✅ | ❌ |

A systems toolkit for building advanced web applications with runtime-inspired primitives.

forge-runtime provides a collection of low-level APIs built on top of modern browser technologies such as WebAssembly, Web Workers, SharedArrayBuffer, Atomics, MessageChannel, and IndexedDB.

The goal is to make runtime, concurrency, storage, and systems-programming concepts accessible directly inside the browser.


Features

  • WebAssembly-backed memory management
  • Virtual filesystem powered by IndexedDB
  • Worker-based task execution
  • Shared memory support
  • Atomic operations
  • Message channels
  • Queue primitives
  • TypeScript support
  • Modern ESM package

Installation

npm install forge-runtime

forge-runtime

Manual memory management for JavaScript powered by WebAssembly.

forge-runtime brings a familiar C-style memory model to JavaScript. Allocate raw memory blocks, work directly with bytes through TypedArrays, and explicitly free memory when you're done.

Why?

JavaScript normally relies on garbage collection.

Sometimes, especially when working with:

  • WebAssembly
  • Large binary files
  • Video processing
  • Audio processing
  • Custom runtimes
  • Binary protocols
  • Low-level systems experiments

it can be useful to manage memory manually.

forge-runtime provides a simple API inspired by C's malloc() and free() while remaining fully usable from JavaScript.

Basic Usage

import { allocMemory, freeMemory } from "forge-runtime";

const block = allocMemory(100);

block.memory[0] = 65;
block.memory[1] = 66;
block.memory[2] = 67;

freeMemory(block);

Memory Block

Calling:

const block = allocMemory(100);

returns:

{
  ptr: 1024,
  size: 100,
  memory: Uint8Array(...)
}

Properties

| Property | Description | | -------- | ----------------------------------------- | | ptr | Pointer/address inside WebAssembly memory | | size | Allocated size in bytes | | memory | Uint8Array view over the allocated memory |


Large Memory Allocations

forge-runtime is configured with 1 GB of WebAssembly memory, allowing applications to work with large binary datasets and memory-intensive workloads.

Examples:

const block = allocMemory(1024 * 1024 * 100); // 100 MB
const block = allocMemory(1024 * 1024 * 1024); // 1 GB

Check the current WebAssembly memory size:

console.log(block.memory.buffer.byteLength);

Typical use cases:

  • Large file processing
  • Video and audio pipelines
  • WebAssembly runtimes
  • Binary protocols
  • Custom allocators
  • Systems programming experiments

Notes

  • Actual usable memory depends on available system resources.
  • WebAssembly memory is backed by virtual memory and may not immediately consume physical RAM.
  • Extremely large allocations may still fail if insufficient memory is available.
  • Always free memory when finished.

Writing Data

const block = allocMemory(4);

block.memory[0] = 10;
block.memory[1] = 20;
block.memory[2] = 30;
block.memory[3] = 40;

Reading Data

console.log(block.memory[0]);
console.log(block.memory[1]);

Working With Strings

const block = allocMemory(100);

const bytes = new TextEncoder().encode("hello");

block.memory.set(bytes);

const text = new TextDecoder().decode(block.memory.subarray(0, bytes.length));

console.log(text);

Output:

hello

Freeing Memory

freeMemory(block);

After freeing:

block.ptr === null;
block.memory === null;
block.size === 0;

This helps prevent accidental use-after-free bugs.


Important Notes

Memory Is Not Erased

Calling:

freeMemory(block);

does not immediately erase bytes.

It marks the memory as available for future allocations.

Do Not Use Freed Blocks

Bad:

freeMemory(block);

block.memory[0] = 123;

Good:

block.memory[0] = 123;

freeMemory(block);

Ownership vs Data

When memory is freed:

freeMemory(block);

ownership of the memory is released, but the old bytes may still remain in memory until they are overwritten by a future allocation.

This behavior is similar to C's:

free(ptr);

and is one of the most important concepts in manual memory management.


TypeScript Support

forge-runtime ships with built-in TypeScript definitions.

import { allocMemory, freeMemory } from "forge-runtime";

const block = allocMemory(100);

block.memory[0] = 123;

freeMemory(block);

Inspiration

forge-runtime is inspired by:

void* ptr = malloc(size);

/* use memory */

free(ptr);

and brings a similar workflow to JavaScript through WebAssembly.


Educational Purpose

This project was created to help JavaScript developers better understand:

  • Memory allocation
  • Pointers
  • Heaps
  • WebAssembly memory
  • Manual memory management
  • Systems programming concepts

through a simple JavaScript API.



Quick Start

import {
  allocMemory,
  freeMemory,
  writeText,
  readText,
  spawn,
} from "forge-runtime";

const block = allocMemory(1024);

block.memory[0] = 65;

console.log(block.memory[0]);

freeMemory(block);

await writeText("/hello.txt", "Hello Forge");

console.log(await readText("/hello.txt"));

const result = await spawn((x) => x * 2, 10);

console.log(result);

Forge Pool

A lightweight Worker Pool for running CPU-intensive JavaScript tasks in parallel using Web Workers.

Features

  • Worker Pool
  • Task Queue
  • Automatic Scheduling
  • Promise-based API
  • Async Function Support
  • Error Handling
  • Worker Reuse
  • Automatic Load Distribution
  • Pool Cleanup

Installation

Copy createPool.js into your project.

import { createPool } from "forge-runtime";

const pool = createPool(4);

Create a Pool

import { createPool } from "forge-runtime";

const pool = createPool(4);

Creates a pool with 4 workers.


Run a Task

const result = await pool.run((n) => n * 2, 10);

console.log(result);

Output:

20

Run Multiple Tasks

const p1 = pool.run((n) => n * 2, 10);

const p2 = pool.run((n) => n * 3, 20);

const p3 = pool.run((n) => n * 4, 30);

const results = await Promise.all([p1, p2, p3]);

console.log(results);

Output:

[20, 60, 120]

Async Functions

const result = await pool.run(
  async (n) => {
    await new Promise((resolve) => setTimeout(resolve, 1000));

    return n * 2;
  },

  10,
);

Output:

20

Array Processing

const result = await pool.run(
  (arr) => arr.reduce((a, b) => a + b, 0),

  [1, 2, 3, 4, 5],
);

console.log(result);

Output:

15

Error Handling

try {
  await pool.run(() => {
    throw new Error("Boom");
  });
} catch (error) {
  console.error(error.message);
}

Output:

Boom

Pool Information

Pool Size

console.log(pool.size);

Pending Tasks

console.log(pool.pendingTasks);

Destroy Pool

Terminate all workers and clean resources.

pool.destroy();

How It Works

User
  │
  ▼
pool.run()
  │
  ▼
Task Queue
  │
  ▼
Scheduler
  │
  ▼
Available Worker
  │
  ▼
Worker Executes Task
  │
  ▼
Result Returned
  │
  ▼
Promise Resolved

Notes

Functions passed to run() must be self-contained.

✅ Works:

await pool.run((n) => n * 2, 10);

❌ Does not work:

const multiplier = 5;

await pool.run((n) => n * multiplier, 10);

Reason:

Workers execute the function in an isolated context and do not have access to variables from the main thread.


Use Cases

  • Large Calculations
  • Data Processing
  • Sorting
  • Searching
  • Hashing
  • Simulations
  • Image Processing
  • CPU-intensive Tasks

Example

import { createPool } from "forge-runtime";

const pool = createPool(4);

const result = await pool.run((n) => n * n, 12);

console.log(result);

pool.destroy();

Output:

144

Built for learning browser concurrency, worker pools, scheduling, and runtime architecture.


Philosophy

Modern browsers expose powerful low-level primitives:

  • WebAssembly
  • Web Workers
  • SharedArrayBuffer
  • Atomics
  • IndexedDB
  • MessageChannel

forge-runtime provides a unified API layer on top of these primitives, making it easier to experiment with runtime architecture, concurrency, memory management, storage systems, and browser systems programming.


Memory

Allocate and free memory manually through WebAssembly-backed memory.

import { allocMemory, freeMemory } from "forge-runtime";

const block = allocMemory(1024);

block.memory[0] = 65;

freeMemory(block);

Memory block:

{
  ptr: 1024,
  size: 1024,
  memory: Uint8Array(...)
}

Shared WebAssembly Pool

Run CPU-intensive JavaScript and WebAssembly memory operations across a pool of Web Workers using a shared WebAssembly.Memory.

Features

  • Shared WebAssembly.Memory
  • Zero-copy memory access
  • Worker pool execution
  • Pointer-based memory blocks
  • Parallel processing
  • WebAssembly-backed allocator
  • String ↔ memory helpers
  • No message-passing of large buffers

Installation

import { createHeap, memory, createPoolWasm } from  "forge-runtime";

Creating a Heap

const heap = await createHeap();

The heap provides:

heap.alloc(size);
heap.free(block);
heap.fromString(text);
heap.toString(block);

Allocating Memory

const block = heap.alloc(1);

block.memory[0] = 77;

console.log(block.ptr);

console.log(block.memory[0]);

Example:

73360
77

Creating a Worker Pool

const pool = await createPoolWasm(memory, 4);

Creates four workers sharing the same WebAssembly memory.


Running Tasks

const result = await pool.run(
  (x) => x * 2,

  5,
);

console.log(result);

Output:

10

Working with Shared Memory

Allocate memory:

const block = heap.alloc(1);

block.memory[0] = 77;

Read it from a worker:

const result = await pool.runHeap(
  ({ ptr, HEAP }) => {
    return HEAP[ptr];
  },

  block,
);

console.log(result);

Output:

77

No memory is copied between threads.

Workers access the same underlying shared memory.


Processing Large Buffers

const size = 100_000_000;

const block = heap.alloc(size);

block.memory.fill(1);

Parallel update:

await Promise.all([
  pool.runHeap(
    ({ ptr, size, HEAP }) => {
      const end = ptr + size / 4;

      for (let i = ptr; i < end; i++) {
        HEAP[i] *= 2;
      }
    },

    block,
  ),
]);

This pattern allows large memory regions to be processed in parallel.


String Utilities

Store a string:

const block = heap.fromString("Hello World");

Read it back:

const text = heap.toString(block);

console.log(text);

Output:

Hello World

API

createHeap()

Creates a WebAssembly-backed heap.

const heap = await createHeap();

Returns:

{
  (memory, HEAP, alloc, free, fromString, toString);
}

createPoolWasm(memory, size)

Creates a pool of workers sharing the same WebAssembly memory.

const pool = await createPoolWasm(memory, 4);

pool.run(handler, data)

Runs a task in a worker.

const result = await pool.run(
  (x) => x * 2,

  5,
);

pool.runHeap(handler, block)

Runs a task against a shared memory block.

await pool.runHeap(
  ({ ptr, size, HEAP }) => {
    // access shared memory
  },

  block,
);

pool.destroy()

Stops all workers.

pool.destroy();

Architecture

Main Thread
      │
      ▼
Shared WebAssembly.Memory
      │
 ┌────┼────┐
 ▼    ▼    ▼
W1   W2   W3 ...
      │
      ▼
Shared HEAPU8

Workers operate directly on the same memory buffer, allowing high-performance parallel processing without copying large arrays between threads.


Use Cases

  • Image processing
  • Video processing
  • Audio processing
  • Compression
  • Parsing large files
  • Scientific computing
  • Data transformation
  • Game engines
  • WebAssembly runtimes
  • Custom memory-managed applications

ArrayBuffer Utilities

Store an ArrayBuffer directly in shared WebAssembly memory:

const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");

const buffer = await response.arrayBuffer();

const block = heap.fromArrayBuffer(buffer);

This is equivalent to:

const block = heap.alloc(buffer.byteLength);

block.memory.set(new Uint8Array(buffer));

but removes the boilerplate.


Response Utilities

Store a Fetch Response directly in shared WebAssembly memory:

const block = await heap.fromResponse(
  await fetch("https://jsonplaceholder.typicode.com/todos/1"),
);

Internally:

Response
    ↓
ArrayBuffer
    ↓
Shared WebAssembly Memory

This allows large responses to be processed by workers without repeatedly transferring data between threads.


Real World Example

Process a JSON response inside a worker without blocking the main thread.

const heap = await createHeap();

const pool = await createPoolWasm(memory, 4);

const block = await heap.fromResponse(
  await fetch("https://jsonplaceholder.typicode.com/todos/1"),
);

const title = await pool.runHeap(
  ({ ptr, size, HEAP }) => {
    const text = new TextDecoder().decode(
      Uint8Array.from(HEAP.subarray(ptr, ptr + size)),
    );

    const json = JSON.parse(text);

    return json.title;
  },

  block,
);

console.log(title);

Output:

delectus aut autem

Why use this?

Traditional processing:

Fetch
 ↓
Main Thread
 ↓
JSON.parse
 ↓
UI may freeze

Shared WebAssembly Pool:

Fetch
 ↓
Shared WebAssembly Memory
 ↓
Worker Pool
 ↓
JSON.parse
 ↓
Result

Benefits:

  • Keeps the main thread responsive
  • Avoids repeatedly copying large payloads
  • Works with large JSON files, CSV files, logs, binary files, images, and other datasets
  • Enables parallel processing across multiple workers

Virtual Filesystem

Store files using browser storage.

Write Text

import { writeText } from "forge-runtime";

await writeText("/hello.txt", "Hello Forge");

Read Text

import { readText } from "forge-runtime";

const text = await readText("/hello.txt");

console.log(text);

Write Binary Data

import { writeFile } from "forge-runtime";

await writeFile("/image.bin", new Uint8Array([1, 2, 3]));

Read Binary Data

import { readFile } from "forge-runtime";

const file = await readFile("/image.bin");

Check Existence

import { exists } from "forge-runtime";

const found = await exists("/hello.txt");

Delete File

import { deleteFile } from "forge-runtime";

await deleteFile("/hello.txt");

List Files

import { listFiles } from "forge-runtime";

const files = await listFiles();

console.log(files);

Tasks

Execute work inside isolated workers.

import { spawn } from "forge-runtime";

const result = await spawn((x) => x * 2, 10);

console.log(result);

Output:

20

Channels

Create communication channels.

import { createChannel } from "forge-runtime";

const channel = createChannel();

channel.port1.postMessage("hello");

channel.port2.onmessage = (event) => {
  console.log(event.data);
};

SharedArrayBuffer Requirements

Some Forge Runtime features such as:

  • Shared Memory
  • Atomics
  • Shared Queues
  • Advanced Worker Communication

rely on SharedArrayBuffer.

For security reasons, modern browsers only expose SharedArrayBuffer in cross-origin isolated environments.

If you see an error such as:

ReferenceError: SharedArrayBuffer is not defined

your application is likely not running in a cross-origin isolated context.

Required Headers

Your server must send:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Vite Example

export default {
  server: {
    headers: {
      "Cross-Origin-Opener-Policy": "same-origin",

      "Cross-Origin-Embedder-Policy": "require-corp",
    },
  },
};

Verify Support

console.log(typeof SharedArrayBuffer);

console.log(crossOriginIsolated);

Expected output:

function
true

If SharedArrayBuffer is undefined or crossOriginIsolated is false, browser security restrictions are preventing access to shared memory APIs.

Shared Memory

Create memory accessible from multiple workers.

import { createSharedMemory, createInt32View } from "forge-runtime";

const memory = createSharedMemory(1024);

const view = createInt32View(memory);

view[0] = 123;

Atomic Operations

Safe concurrent access to shared memory.

import { load, store, add } from "forge-runtime";

store(view, 0, 10);

add(view, 0, 5);

console.log(load(view, 0));

Output:

15

Queues

Experimental shared-memory queue implementation.

import { createQueue, push, pop } from "forge-runtime";

const queue = createQueue();

push(queue, 10);

push(queue, 20);

console.log(pop(queue));

console.log(pop(queue));

Output:

10
20

TypeScript

Forge Runtime ships with TypeScript definitions.

import { allocMemory, createQueue, spawn } from "forge-runtime";

Autocomplete and type checking work out of the box.


What forge-runtime Is

  • Browser systems toolkit
  • Runtime experimentation platform
  • Collection of low-level browser primitives
  • Educational systems-programming project
  • Foundation for exploring runtime architecture

What forge-runtime Is Not

  • Node.js replacement
  • Bun replacement
  • Server runtime
  • Production operating system

Browser Support

Requires modern browsers with support for:

  • ES Modules
  • WebAssembly
  • Web Workers
  • SharedArrayBuffer
  • Atomics
  • IndexedDB
  • MessageChannel

Roadmap

v0.1

  • Memory
  • Filesystem
  • Tasks

v0.2

  • Channels
  • Shared Memory
  • Atomics

v0.3

  • Worker Pools
  • Scheduler
  • Job Queues

v0.4

  • Streams

v0.5

  • Database Layer

v1.0

  • Browser Runtime Platform

License

MIT