Skip to content

QuickJS Sandbox Options

The QuickJS Sandbox provides a secure, configurable environment for executing JavaScript and TypeScript code. The sandbox supports both synchronous and asynchronous WebAssembly execution, with various options for resource limits, virtual file systems, networking, logging, and more.

⚙️ Base Options

These options apply to both synchronous and asynchronous sandbox instances.

⏳ Execution Limits

OptionTypeDescription
executionTimeoutnumberMaximum script execution time (in seconds). Set to 0 for unlimited.
maxStackSizenumberMaximum stack size (in bytes). Set to 0 to disable the limit.
memoryLimitnumberMaximum memory allocation. Set to -1 to remove the limit.

📂 Virtual File System

OptionTypeDescription
mountFs`NestedDirectoryJSONIFs`
nodeModulesNestedDirectoryJSONMounts custom node_modules in the virtual file system.

📄 File System Access

OptionTypeDescription
allowFsbooleanEnables file system access (node:fs).

🌐 Networking

OptionTypeDescription
allowFetchbooleanEnables fetch for making HTTP(S) calls.
fetchAdaptertypeof fetchCustom fetch adapter provided as a host function.

🛠️ Testing Utilities

OptionTypeDescription
enableTestUtilsbooleanEnables test frameworks (chai & mocha).

📢 Console Customization

You can override console methods for custom logging behavior.

ts
console: {
  log?: (message?: unknown, ...params: unknown[]) => void;
  error?: (message?: unknown, ...params: unknown[]) => void;
  warn?: (message?: unknown, ...params: unknown[]) => void;
  info?: (message?: unknown, ...params: unknown[]) => void;
  debug?: (message?: unknown, ...params: unknown[]) => void;
}

🛑 Environment & Syncing

OptionTypeDescription
envRecord<string, unknown>Defines environment variables available inside QuickJS.
dangerousSyncRecord<string, unknown>Syncs data between host & guest (⚠️ can be modified by guest).

📝 TypeScript Support

OptionTypeDescription
typescriptImportFilestringTypeScript library to import (default: typescript).
transformTypescriptbooleanTranspiles TypeScript files to JavaScript in mountFs.
transformCompilerOptionsTS.CompilerOptionsTypeScript compiler options.

⏲️ Timer Limits

To prevent abuse, the number of running setTimeout and setInterval calls is restricted.

OptionTypeDescription
maxTimeoutCountnumberMax concurrent timeouts (default: 100).
maxIntervalCountnumberMax concurrent intervals (default: 100).

🏗️ Module Handling

Both synchronous and asynchronous QuickJS sandboxes allow customizing module loading.

📦 Synchronous Module Options (SandboxOptions)

OptionTypeDescription
getModuleLoader(fs: IFs, options: RuntimeOptions) => JSModuleLoaderCustom module loader.
modulePathNormalizerJSModuleNormalizerTransforms module paths before loading.

🌍 Asynchronous Module Options (SandboxAsyncOptions)

OptionTypeDescription
getModuleLoader(fs: IFs, options: RuntimeOptions) => JSModuleLoaderAsyncCustom module loader.
modulePathNormalizerJSModuleNormalizerAsyncTransforms module paths before loading.

🔗 More info: See github.com/justjake/quickjs-emscripten for details on asynchronous execution.

Example Usage

The options are passed to the createRuntime method. Here is a basic example:

typescript
import { type SandboxOptions, loadQuickJs } from '@sebastianwessel/quickjs'

const { runSandboxed } = await loadQuickJs()

// Create a runtime instance each time a JS code should be executed
const options:SandboxOptions = {
  allowFetch: true, // inject fetch and allow the code to fetch data
  allowFs: true,    // mount a virtual file system and provide node:fs module
  env: {
    MY_ENV_VAR: 'env var value'
  },
  console: {
    log: (message, ...optionalParams) => {
      console.log(`[QuickJS Log]: ${message}`, ...optionalParams);
    },
    error: (message, ...optionalParams) => {
      console.error(`[QuickJS Error]: ${message}`, ...optionalParams);
    }
    // Customize other console methods as needed
  }
};

const code = `
import { join } as path from 'path';

const fn = async () => {
  console.log(join('src', 'dist')); // logs "src/dist" on host system

  console.log(env.MY_ENV_VAR); // logs "env var value" on host system

  const url = new URL('https://example.com');

  const f = await fetch(url);

  return f.text();
}

export default await fn();
`

const result = await runSandboxed(async ({ evalCode }) => evalCode(code, undefined, options), options)

console.log(result); // { ok: true, data: '<!doctype html>\n<html>\n[....]</html>\n' }