New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

wasmfuncplatform

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

wasmfuncplatform

An opinionated WebAssembly function platform with Component Model, WIT, and async stepper execution

latest
npmnpm
Version
0.1.0
Version published
Maintainers
1
Created
Source

wasm-func-platform-node (Component Model + WIT + async stepper)

This repo is an opinionated function platform:

  • A user program is a set of functions with a fixed main signature.
  • We compile to a WebAssembly Component defined by WIT.
  • Execution is always asynchronous via a stepper interface: the component returns pending(effect, state) and the Node host performs the effect (DB, messages, timers, ctx) and resumes.
  • Nested/inline functions are compiled into separate, referencable functions (stable IDs) via lambda lifting (foundation for "DB query + callback" fan-out).
  • Object-oriented abstractions via WIT resources for natural method/property access.

Quick start

npm install
npm test

# Compile example into a component
node packages/cli/dist/main.js compile examples/program.simple.json --out /tmp/f.component.wasm

# Run it (will auto-transpile using jco if available)
node packages/cli/dist/main.js run /tmp/f.component.wasm --ctx n=41 --ctx k=1

Note: component building/transpiling uses @bytecodealliance/jco and @bytecodealliance/componentize-js. Some environments require installing a JS engine for componentize-js. See docs.

Layout

  • wit/function.wit — Component interface
  • packages/core-ir — canonical IR + stable IDs + lambda lifting
  • packages/compiler-component — IR -> guest JS -> jco componentize -> component wasm
  • packages/runtime — Node host async stepper loop + effect handlers
  • packages/clifuncctl CLI
  • examples/ — example programs
  • docs/ — design notes and future directions

Library Usage

The platform can be embedded as a library for programmatic compilation and execution.

Programmatic Compilation

Use @wfp/compiler-component to compile programs directly from JavaScript:

import { compileProgram, compileProgramJson } from '@wfp/compiler-component';

// Option 1: Compile from a file path
await compileProgramJson('./examples/program.simple.json', {
  outWasm: './dist/func.wasm',
  entry: 'main'  // optional, defaults to 'main'
});

// Option 2: Compile a Program object directly
const program = {
  version: 1,
  functions: [{
    id: '',  // auto-generated stable ID
    name: 'main',
    parent: null,
    params: [],
    body: [
      { op: 'let', name: 'n', expr: { op: 'ctx_get_i64', key: 'n' } },
      { op: 'let', name: 'one', expr: { op: 'lit_i64', value: 1 } },
      { op: 'let', name: 'result', expr: { op: 'add', a: { op: 'var', name: 'n' }, b: { op: 'var', name: 'one' } } },
      { op: 'return', expr: { op: 'json', value: { result: { op: 'var', name: 'result' } } } }
    ]
  }]
};

await compileProgram(program, {
  outWasm: './dist/func.wasm',
  outIrJson: './dist/ir.json'  // optional: save processed IR
});

Programmatic Execution

Use @wfp/runtime to execute compiled components:

import { makeEnv, runComponent } from '@wfp/runtime';

// Create a host environment
const env = makeEnv();

// Set context values (accessible via ctx_get_i64 in the program)
env.ctx.set('n', 41);
env.ctx.set('k', 1);

// Run the component
const { output, env: finalEnv } = await runComponent('./dist/func.wasm', env);

console.log(output);  // '{"result":42}'
console.log(finalEnv.messages);  // Messages sent via msg_send
console.log(finalEnv.ctx.get('n'));  // Updated context values

Working with Resources

Resources provide object-oriented abstractions with properties and methods:

import { makeEnv, runComponent, createResourceInstance, getResourceInstance } from '@wfp/runtime';

// Create environment and resource instance
const env = makeEnv();
const handle = createResourceInstance(env, 'Counter', { value: 0 });

// Run a method on the resource
const { output } = await runComponent('./dist/counter.wasm', env, {
  resourceHandle: handle,
  maxSteps: 1000  // optional step limit
});

// Access updated resource properties
const instance = getResourceInstance(env, handle);
console.log(instance.properties.get('value'));  // Updated counter value

Core IR Transformations

Use @wfp/core-ir for IR manipulation:

import { assignMissingIds, lambdaLift, hashObject } from '@wfp/core-ir';

// Assign stable content-hash IDs to functions
const withIds = assignMissingIds(program);
console.log(withIds.functions[0].id);  // e.g., 'a1b2c3d4e5f67890'

// Lift nested functions to top-level with explicit captures
const lifted = lambdaLift(withIds);

// Compute deterministic hash of any object
const hash = hashObject({ name: 'test', value: 42 });

Async Stepper Model

The platform uses an async stepper execution model where components yield effects and the host resumes them:

  • run-step is called with context ID, input JSON, state bytes, and optional resume JSON
  • Component returns one of:
    • done(output) — execution complete, return output JSON
    • pending(effect, state) — yield effect, save state for resumption
    • trap(message) — execution error
  • Host handles the effect (ctx access, messaging, sleep, db query)
  • Host resumes component with effect result
  • Repeat until done or trap

This model enables:

  • Deterministic replay — state can be persisted and resumed
  • Effect isolation — all I/O happens in the host
  • Step limiting — prevent infinite loops with max step count

Supported Effects

EffectDescriptionResume Data
ctx-get-i64Read i64 from context map{ i64: number }
ctx-set-i64Write i64 to context mapnone
msg-sendSend message to topicnone
sleep-msWait for durationnone
db-queryDatabase query (MVP placeholder){ rows: [] }

Examples

The examples/ directory contains several example programs with run scripts:

ExampleDescriptionRun Script
program.simple.jsonBasic: reads context, computes sum, sends messagerun-simple.sh
program.nested.jsonLambda lifting: nested function captures parent variablerun-nested.sh
program.converter.jsonUnit conversion: reads Celsius, outputs Fahrenheitrun-converter.sh
program.accumulator.jsonMulti-input: reads 3 values, stores sum and doubledrun-accumulator.sh
program.resource.jsonCounter resource with increment/getValue methodsrun-resource-demo.mjs
program.bank-account.jsonComplex resource: balance, transactions, transfersrun-resource-demo.mjs
program.state-machine.jsonState machine with transitions and error trackingrun-resource-demo.mjs

Run all CLI examples:

./examples/run-all.sh

Run the programmatic resource demo:

node examples/run-resource-demo.mjs

Example: Counter Resource

The examples/program.resource.json demonstrates resource usage with a Counter object:

{
  "version": 1,
  "functions": [
    {
      "id": "",
      "name": "getValue",
      "resource": "Counter",
      "params": [],
      "body": [
        {"op": "return", "expr": {"op": "self_get", "property": "value"}}
      ]
    },
    {
      "id": "",
      "name": "increment",
      "resource": "Counter",
      "params": [],
      "body": [
        {"op": "let", "name": "current", "expr": {"op": "self_get", "property": "value"}},
        {"op": "let", "name": "one", "expr": {"op": "lit_i64", "value": 1}},
        {"op": "let", "name": "newValue", "expr": {"op": "add", "a": {"op": "var", "name": "current"}, "b": {"op": "var", "name": "one"}}},
        {"op": "expr", "expr": {"op": "self_set", "property": "value", "value": {"op": "var", "name": "newValue"}}},
        {"op": "return", "expr": {"op": "self_get", "property": "value"}}
      ]
    }
  ],
  "resources": [
    {
      "name": "Counter",
      "properties": [{"name": "value", "type": "i64"}],
      "methods": ["getValue", "increment", "add"]
    }
  ]
}

Expected behavior:

  • getValue() returns the current counter value
  • increment() adds 1 to the counter and returns the new value
  • add(amount) adds the specified amount and returns the new value

Running with the library:

import { makeEnv, runComponent, createResourceInstance } from '@wfp/runtime';

const env = makeEnv();
const handle = createResourceInstance(env, 'Counter', { value: 10 });

// After running increment method:
// output: '{"result":11}'
// instance.properties.get('value') === 11

Philosophy

Wasm is the execution artifact. The canonical IR (and metadata like stable IDs and nesting) is the source of truth for pretty-printing in different languages.

Keywords

wasm

FAQs

Package last updated on 21 Jan 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts