π 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 β
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:
import { loadQuickJs } from '@sebastianwessel/quickjs'
with:
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:
# 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)
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) β
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()
replacesquickJS()
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!