JavaScript Runtime
If you are building a JavaScript application, you can run compiled Devlish programs inside that application instead of starting the CLI for each call. The devlish-runtime package loads the WebAssembly version of the Devlish virtual machine and accepts a compiled bytecode package plus input values.
This page is for developers embedding Devlish in a browser, Node.js, or another compatible JavaScript host. Compile a .dvl program to .dvlc.json first. The examples explain loading, execution, returned results, and the restrictions of this runtime.
Installation
Section titled “Installation”Install the package in the JavaScript project that will load and run your bytecode.
npm install devlish-runtimeQuick Start
Section titled “Quick Start”This example assumes a compiled program is available at /rules/pricing.dvlc.json and accepts customer_tier and deal_size. It loads the package, runs it with those inputs, and reads the returned result.
import { runTool } from "devlish-runtime";
const bytecode = await fetch("/rules/pricing.dvlc.json").then(r => r.json());
const result = await runTool(bytecode, { customer_tier: "enterprise", deal_size: 500000});
if (result.success) { console.log("Result:", result.response);}loadTool API
Section titled “loadTool API”For repeated execution, load a tool once and call it multiple times:
import { loadTool } from "devlish-runtime";
const tool = await loadTool({ bytecode: compiledBytecodeJson, mainThread: false, instructionLimit: 5000000});
const result1 = await tool.run({ project_id: "A" });const result2 = await tool.run({ project_id: "B" });
tool.dispose(); // clean up the WorkerOptions
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
bytecode |
object or string | required | Compiled .dvlc.json bytecode |
mainThread |
boolean | false |
Skip Web Worker, run synchronously |
instructionLimit |
number | 10000000 |
Max instructions before termination |
runTool API
Section titled “runTool API”One-shot convenience function. Loads, runs, and disposes in one call:
import { runTool } from "devlish-runtime";
const result = await runTool(bytecode, { amount: 1200 });Always runs on the main thread.
RunResult
Section titled “RunResult”{ "success": true, "responded": true, "response": {"status": "approved", "score": 85}, "context": {"amount": 1200, "score": 85}, "results": {}}| Field | Type | Description |
|---|---|---|
success |
boolean | Whether execution completed without error |
error |
string | Error message if success is false |
responded |
boolean | Whether the program used Respond with |
response |
any | The value passed to Respond with |
context |
object | All variables at end of execution |
results |
object | Validation and assertion results |
Web Worker Execution
Section titled “Web Worker Execution”By default, loadTool runs bytecode in a Web Worker, keeping the main thread free for UI. The WASM binary is inlined as base64 in the package for zero-config bundler compatibility.
// Worker execution (default)const tool = await loadTool({ bytecode });const result = await tool.run(input);tool.dispose();
// Main thread executionconst tool = await loadTool({ bytecode, mainThread: true });Permission Checking
Section titled “Permission Checking”The runtime enforces a strict sandbox. Tools that declare certain permissions in their manifest are rejected at load time:
- HTTP requests: Rejected (WASM sandbox has no network access)
- Filesystem operations: Rejected (WASM sandbox has no filesystem)
- Instruction limit: Enforced (prevents infinite loops)
- Memory isolation: Each tool runs in its own WASM linear memory
Browser Embed
Section titled “Browser Embed”<script type="module"> import { runTool } from "https://esm.sh/devlish-runtime";
const bytecode = await fetch("/rules/check.dvlc.json").then(r => r.json()); const result = await runTool(bytecode, { amount: 500 }); document.getElementById("output").textContent = JSON.stringify(result.response);</script>Node.js and Edge
Section titled “Node.js and Edge”The same API works in Node.js and edge runtimes (Cloudflare Workers, Deno, Bun). Import and use identically.