Sandbox
@whisq/sandbox provides a secure execution environment for running untrusted code. It’s designed for interactive playgrounds, code editors, and educational tools where user-submitted code needs to run safely.
npm install @whisq/sandboxBasic Usage
Section titled “Basic Usage”import { createSandbox } from "@whisq/sandbox";
const sandbox = createSandbox();
const result = await sandbox.execute(` const x = 2 + 2; x;`);
console.log(result);// { success: true, value: 4 }
sandbox.dispose();Error Handling
Section titled “Error Handling”When code throws an error, the sandbox catches it:
const result = await sandbox.execute(` throw new Error("something broke");`);
console.log(result);// { success: false, error: "Error: something broke" }Your application doesn’t crash — the error is captured and returned.
Timeouts
Section titled “Timeouts”Set a maximum execution time to prevent infinite loops:
const sandbox = createSandbox({ timeout: 3000 }); // 3 seconds
const result = await sandbox.execute(` while (true) {} // infinite loop`);
console.log(result);// { success: false, error: "Execution timed out" }The default timeout is 5,000ms (5 seconds).
Blocked APIs
Section titled “Blocked APIs”The sandbox blocks access to browser APIs that could be dangerous:
document,window,globalThisfetch,XMLHttpRequest,WebSocketlocalStorage,sessionStorage,indexedDBnavigator,location,historyalert,confirm,prompt
Attempting to access any of these throws an error:
const result = await sandbox.execute(` fetch("/api/data");`);
// { success: false, error: "fetch is not defined" }Communication
Section titled “Communication”Send messages between the sandbox and your application:
const sandbox = createSandbox();
// Listen for messages from sandboxed codesandbox.onMessage((msg) => { console.log("From sandbox:", msg);});
await sandbox.execute(` postMessage({ type: "result", value: 42 });`);Building a Code Playground
Section titled “Building a Code Playground”Combine the sandbox with Whisq UI for an interactive playground:
import { signal, component, div, textarea, button, pre, mount } from "@whisq/core";import { createSandbox } from "@whisq/sandbox";
const Playground = component(() => { const code = signal('const x = 2 + 2;\nx;'); const output = signal(""); const sandbox = createSandbox({ timeout: 3000 });
const run = async () => { const result = await sandbox.execute(code.value); output.value = result.success ? String(result.value) : `Error: ${result.error}`; };
return div({ class: "playground" }, textarea({ value: () => code.value, oninput: (e) => code.value = e.target.value, rows: "8", }), button({ onclick: run }, "Run"), pre({ class: "output" }, () => output.value), );});
mount(Playground({}), document.getElementById("app")!);Cleanup
Section titled “Cleanup”Always dispose the sandbox when you’re done:
const sandbox = createSandbox();
// ... use the sandbox ...
sandbox.dispose(); // clean up resourcesIn a Whisq component, use onCleanup:
import { onMount, onCleanup } from "@whisq/core";import { createSandbox } from "@whisq/sandbox";
const PlaygroundComponent = component(() => { let sandbox: Sandbox;
onMount(() => { sandbox = createSandbox(); onCleanup(() => sandbox.dispose()); });
// ... use sandbox in event handlers});API Reference
Section titled “API Reference”createSandbox(options?)
Section titled “createSandbox(options?)”| Option | Type | Default | Description |
|---|---|---|---|
timeout | number | 5000 | Maximum execution time in ms |
sandbox.execute(code)
Section titled “sandbox.execute(code)”Returns Promise<ExecutionResult>:
interface ExecutionResult { success: boolean; value?: unknown; // result of the last expression error?: string; // error message if failed}sandbox.onMessage(handler)
Section titled “sandbox.onMessage(handler)”Listen for postMessage() calls from sandboxed code.
sandbox.dispose()
Section titled “sandbox.dispose()”Clean up sandbox resources.
Next Steps
Section titled “Next Steps”- Performance — Optimizing Whisq applications
- Testing — Testing components that use sandboxes
- Error Boundaries — Handling errors in UI