Sval JavaScript Interpreter
Sval is a JavaScript interpreter written entirely in JavaScript, leveraging the Acorn parser to support modern ECMAScript features while maintaining compatibility with ES5 environments. As of version 0.6.12, it provides robust capabilities for executing JavaScript code in either an isolated sandbox or an invasive mode, depending on user requirements. This flexibility makes it particularly useful for environments where native `eval`, `setTimeout`, or `new Function` might be disabled or restricted due to security policies. The package is actively maintained, with frequent updates addressing bug fixes and dependency bumps, ensuring ongoing support for new JavaScript syntax and improved stability. Key differentiators include its ability to run cutting-edge ES features on older runtimes and its explicit support for both script and module source types, alongside TypeScript type definitions for enhanced developer experience.
Common errors
-
ReferenceError: [variable_name] is not defined
cause The interpreted code is attempting to access a variable or function that exists in the host environment but has not been explicitly imported into the `sval` interpreter's scope.fixUse `interpreter.import('variable_name', hostVariable)` or `interpreter.import({ variable_name: hostVariable })` to make the host variable accessible within the interpreter's context. -
SyntaxError: 'import' and 'export' may only appear with 'sourceType: "module"'
cause The interpreted JavaScript code contains ES module syntax (e.g., `import` statements, `export` statements) but the `Sval` instance was initialized with the default `sourceType: 'script'`.fixInitialize the `Sval` interpreter with `new Sval({ sourceType: 'module', ... })` to enable ES module parsing and execution. -
TypeError: Cannot read properties of undefined (reading 'log')
cause This often occurs when trying to access `console.log` (or other host globals) within a module-type script (`sourceType: 'module'`) or when `this` is `undefined` at the top level, and `console` was not explicitly imported.fixWhen using `sourceType: 'module'`, top-level `this` is `undefined`. Explicitly import global objects like `console` or `Math` into the interpreter's scope: `interpreter.import('console', console);`. -
Error: [Parser Error] (e.g., 'Unexpected token', 'Unexpected keyword')
cause The `ecmaVer` option is set to an older ECMAScript version that does not support the syntax used in the interpreted code, or there's a general syntax error.fixEnsure `ecmaVer` is set to `'latest'` or a specific year that supports the syntax in your code (e.g., `ecmaVer: '2024'`). Double-check the interpreted code for any actual syntax errors.
Warnings
- breaking In `sval` versions 0.6.10 and later, the behavior of `sourceType: 'module'` was updated to strictly align with ECMAScript module semantics. This includes treating the top-level `this` as `undefined` and enforcing strict mode by default for module contexts.
- gotcha The `sandBox` option, which defaults to `true`, is crucial for security. When `sandBox: false` (invasive mode), the interpreted code can directly interact with and mutate the host environment's global scope, posing a significant security risk if executing untrusted code.
- gotcha The `import` method's behavior is context-dependent based on the `sourceType`. When `sourceType: 'script'`, `import` makes provided values available as global variables within the script's scope. However, for `sourceType: 'module'`, `import` is intended to pre-populate the module's internal import map, behaving closer to how ES modules resolve dependencies.
- gotcha While `sval` is often used as a safer alternative to `eval` for executing dynamic code, it still executes arbitrary JavaScript. Without proper sandboxing (`sandBox: true`) and input validation, it can still be exploited if fed malicious code.
Install
-
npm install sval -
yarn add sval -
pnpm add sval
Imports
- Sval
import { Sval } from 'sval'import Sval from 'sval'
- Sval (CommonJS)
const { Sval } = require('sval')const Sval = require('sval') - SvalOptions (Type)
import type { SvalOptions } from 'sval'
Quickstart
import Sval from 'sval';
const interpreter = new Sval({
ecmaVer: 'latest', // Support latest ECMAScript features
sourceType: 'script', // Treat code as a standard script
sandBox: true, // Run code in an isolated environment (recommended)
});
// Import host-environment variables or modules into the interpreter's scope
interpreter.import({
log: console.log,
greet: (name: string) => `Hello, ${name} from interpreter!`,
});
try {
// Execute JavaScript code as a string
interpreter.run(`
const message = greet('Sval User');
log(message);
const sum = (a, b) => a + b;
log('2 + 3 =', sum(2, 3));
// Accessing built-in globals like Math
log('Math.PI =', Math.PI);
`);
} catch (error) {
console.error('Interpreter Error:', error);
}