Skip to content

πŸš€ Announcing Version 2.0 ​

After months of hard work, QuickJS Version 2.0 is finally here! πŸŽ‰

This release brings major improvements, including a complete rewrite of the data exchange layer between the guest and host. The API has been simplified, making it easier than ever to work with JavaScript sandboxes while providing even more control.

Along with bug fixes, TypeScript support, async execution, and enhanced configurability, we've also revamped the official website to provide better documentation and examples.

Let’s dive into what’s new! πŸ”₯


✨ What’s New in QuickJS 2.0? ​

πŸ” Re-Use of Context ​

With QuickJS v2, you can now reuse the same sandboxed context multiple times, making execution more efficient.

βœ… Example ​

ts
import { type SandboxOptions, loadQuickJs } from '../../src/index.js'

const options: SandboxOptions = {
  // [...]
}

const { runSandboxed } = await loadQuickJs()

const finalResult = await runSandboxed(async ({ evalCode }) => {
  const firstResult = await evalCode('// [...code 1]', undefined, options)
  console.log('Step 1:', firstResult)

  // Run second call
  return evalCode('// [...code 2]', undefined, options)
}, options)

console.log(finalResult)

Now, you can execute multiple pieces of code inside the same sandboxed context without needing to create a new instance each time.


🟦 TypeScript Support ​

TypeScript execution is now supported natively! πŸŽ‰

To enable it, just install the typescript package and set transformTypescript: true in the sandbox options.

πŸ”Ή Note: This does not perform type checking. It simply transpiles TypeScript to JavaScript, allowing TypeScript code to be executed in the sandbox.


⏳ Full Async Support ​

With QuickJS v2, you can now use asynchronous execution via the Emscripten async variant. This means:

βœ… Dynamic imports at runtime
βœ… Fetching dependencies from sources like esm.sh

πŸ› οΈ How to Use the Async Version ​

Simply replace:

ts
import { loadQuickJs } from '@sebastianwessel/quickjs'

with:

ts
import { loadAsyncQuickJs } from '@sebastianwessel/quickjs'

Now, your sandbox can dynamically load modules and dependencies at runtime! πŸš€


βš™οΈ Enhanced Configuration ​

The sandbox is now more customizable than ever!

βœ… Customizable module path resolver
βœ… Custom module loader
βœ… Fine-grained control over execution behavior

These improvements allow developers to configure precisely how modules are loaded and how the sandbox interacts with the environment.


πŸ“Œ Use Cases ​

To help users get started, three new use cases have been added to the website, with source code available in the GitHub repository.

πŸ€– 1. Execute AI-Generated Code ​

A Large Language Model (LLM) generates JavaScript code to solve a given task. The QuickJS sandbox executes the AI-generated code, and the result is passed back to the LLM for further processing.

πŸ”— Try it here: Execute AI-Generated Code


πŸ›‘οΈ 2. Secure Execution of User-Generated Code ​

Running user-created code safely is a challenge. With QuickJS, sandboxing JavaScript execution takes just a few lines of code!

πŸ”— Check it out: User Generated Code


🌍 3. Server-Side Rendering (SSR) ​

QuickJS can also be used for server-side rendering (SSR) in a secure, isolated environment.

πŸ”— See the example: Serverside Rendering


πŸš€ Migration Guide: QuickJS v1 β†’ v2 ​

QuickJS v2 introduces changes to improve the developer experience and expand capabilities. If you're upgrading from v1, here’s what you need to know:

πŸ“¦ New Dependency Management ​

Previously, QuickJS was shipped with:
@jitl/quickjs-ng-wasmfile-release-sync

Now, you must install your preferred QuickJS WebAssembly variant separately.

πŸ“₯ Install the New Package ​

Use the package manager of your choice:

sh
# npm
npm install @jitl/quickjs-ng-wasmfile-release-sync

# bun
bun add @jitl/quickjs-ng-wasmfile-release-sync

# yarn
yarn add @jitl/quickjs-ng-wasmfile-release-sync

This separates QuickJS from the runtime, allowing more flexibility in choosing the variant that best fits your needs.


πŸ”„ Updated API Usage ​

​

Before (QuickJS v1)

ts
import { quickJS } from '@sebastianwessel/quickjs'

const { createRuntime } = await quickJS()
const { evalCode } = await createRuntime(options)

const result = await evalCode(code)
console.log(result)

After (QuickJS v2) ​

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

const { runSandboxed } = await loadQuickJs()

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

const fn = async () => {
  console.log(join('src', 'dist')) // Logs "src/dist" on the host system
  console.log(env.MY_ENV_VAR) // Logs "env var value" on the host system

  const url = new URL('https://example.com')
  const f = await fetch(url)
  return f.text()
}

export default await fn()
`

const options: SandboxOptions = {
  allowFetch: true, // Allow network requests
  allowFs: true, // Enable virtual file system
  env: { MY_ENV_VAR: 'env var value' },
}

const result = await runSandboxed(async ({ evalCode }) => evalCode(code))
console.log(result)

πŸ’‘ Key Differences:

  • loadQuickJs() replaces quickJS()
  • runSandboxed() simplifies execution
  • Modular approach for better control & flexibility

πŸŽ‰ Final Thoughts ​

QuickJS Version 2.0 is a huge step forward, making it faster, safer, and more configurable.

πŸ”₯ Why Upgrade? ​

βœ… More powerful API
βœ… Async execution
βœ… Dynamic imports & TypeScript support
βœ… Better configuration & modularity
βœ… Improved security

πŸš€ Upgrade today and experience the next generation of JavaScript sandboxing!

πŸ‘‰ Check out the QuickJS repository