
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
wasmfuncplatform
Advanced tools
An opinionated WebAssembly function platform with Component Model, WIT, and async stepper execution
This repo is an opinionated function platform:
pending(effect, state) and the Node host performs the effect (DB, messages, timers, ctx) and resumes.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/jcoand@bytecodealliance/componentize-js. Some environments require installing a JS engine for componentize-js. See docs.
wit/function.wit — Component interfacepackages/core-ir — canonical IR + stable IDs + lambda liftingpackages/compiler-component — IR -> guest JS -> jco componentize -> component wasmpackages/runtime — Node host async stepper loop + effect handlerspackages/cli — funcctl CLIexamples/ — example programsdocs/ — design notes and future directionsThe platform can be embedded as a library for programmatic compilation and execution.
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
});
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
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
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 });
The platform uses an async stepper execution model where components yield effects and the host resumes them:
done(output) — execution complete, return output JSONpending(effect, state) — yield effect, save state for resumptiontrap(message) — execution errordone or trapThis model enables:
| Effect | Description | Resume Data |
|---|---|---|
ctx-get-i64 | Read i64 from context map | { i64: number } |
ctx-set-i64 | Write i64 to context map | none |
msg-send | Send message to topic | none |
sleep-ms | Wait for duration | none |
db-query | Database query (MVP placeholder) | { rows: [] } |
The examples/ directory contains several example programs with run scripts:
| Example | Description | Run Script |
|---|---|---|
program.simple.json | Basic: reads context, computes sum, sends message | run-simple.sh |
program.nested.json | Lambda lifting: nested function captures parent variable | run-nested.sh |
program.converter.json | Unit conversion: reads Celsius, outputs Fahrenheit | run-converter.sh |
program.accumulator.json | Multi-input: reads 3 values, stores sum and doubled | run-accumulator.sh |
program.resource.json | Counter resource with increment/getValue methods | run-resource-demo.mjs |
program.bank-account.json | Complex resource: balance, transactions, transfers | run-resource-demo.mjs |
program.state-machine.json | State machine with transitions and error tracking | run-resource-demo.mjs |
Run all CLI examples:
./examples/run-all.sh
Run the programmatic resource demo:
node examples/run-resource-demo.mjs
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 valueincrement() adds 1 to the counter and returns the new valueadd(amount) adds the specified amount and returns the new valueRunning 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
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.
FAQs
An opinionated WebAssembly function platform with Component Model, WIT, and async stepper execution
We found that wasmfuncplatform demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

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.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.