用纯 Node.js 写了一个 JS 解释器 — kernel-js-lite

4 阅读3分钟

用纯 Node.js 写了一个 JS 解释器 — kernel-js-lite

为什么会有这个东西

有时候我们需要在 Node.js 里安全地执行用户提交的 JavaScript 代码。Node 自带的 vm 模块并不安全,eval 更不用提。QuickJS 很强大但需要原生编译。safe-evalvm2 等方案要么依赖繁杂要么维护停滞。

如果有一个纯 Node.js 实现、零依赖、可以安全运行不可信代码的 JS 解释器呢?

这就是 kernel-js-lite.

架构一览

传统 JS 引擎的经典三阶段 pipeline,全部手写,零依赖:

源代码 → 词法分析器 → Token 流 → 递归下降解析器 → AST → 树遍历解释器

所有代码都在 src/ 目录下,结构清晰:

文件职责
tokenizer.js词法分析,将源码拆成 Token 流
parser.js递归下降解析,生成 AST
ast.jsAST 节点定义
environment.js作用域链管理
objects.js所有内置对象(Array / Object / String / Number / Boolean / Math / console)
interpreter.jsAST 树遍历执行器,含闭包、资源限制
index.js对外 API 入口

能做什么

const { run, Kernel } = require('kernel-js-lite')

// 一秒上手
run('1 + 2 * 3') // 7

// 完整的 JS 语法支持:函数、闭包、数组、对象
run(`
  function makeCounter() {
    var count = 0
    return function() { return count = count + 1 }
  }
  var c = makeCounter()
  c() + c()  // 3
`)

// 绑定宿主函数(Node.js 能力安全暴露给沙箱)
const k = new Kernel()
k.hostFunction('fetchUser', (id) => ({ id, name: 'Alice' }))
k.run('fetchUser(1).name') // 'Alice'

// 资源限制,防止恶意脚本
run('while(true) {}', { maxInstructions: 10000 })
// → Error: Script execution timeout: max instructions exceeded

内置对象进展

经过 55 个版本的迭代,目前已经实现了大量 ES 特性的内置方法:

  • Array: push, pop, map, filter, reduce, find, findLast, findIndex, sort, includes, indexOf, join, slice, splice, forEach, flat, reverse, at, fill, keys, values, entries, toReversed, toSorted, toSpliced, with, of, from, toString, toLocaleString
  • String: length, charAt, indexOf, includes, slice, split, toUpperCase, toLowerCase, toLocaleUpperCase, toLocaleLowerCase, trim, replace, replaceAll, concat, match, search, padStart, padEnd, trimStart, trimEnd, at, codePointAt, localeCompare, normalize, isWellFormed, valueOf
  • Object: keys, values, entries, assign, fromEntries, create, is, freeze, seal, getPrototypeOf, setPrototypeOf
  • Number: toFixed, toExponential, toPrecision, toLocaleString, valueOf, parseInt, parseFloat, isNaN, isFinite, EPSILON, MAX_SAFE_INTEGER
  • Math: abs, ceil, floor, round, max, min, pow, sqrt, random, PI, E, sign, trunc, cbrt, hypot, exp, log, sin, cos, tan, asin, acos, atan, atan2
  • console: log, warn, error, info, debug, trace, time, timeEnd, count, countReset, group, groupEnd, table, assert
  • JSON: stringify, parse
  • Set: 基本实现
  • 其他: Date.now, encodeURI, decodeURI, escape, unescape, typeof

CLI 工具

除了作为库使用,它还带了一个命令行工具 kjs,可以直接跑 .kjs 文件:

# 安装
npm install -g kernel-js-lite

# 运行脚本
kjs hello.kjs

# 或直接执行代码
kjs -e "print(Math.PI)"

# 资源限制
kjs --max-instructions 5000 myscript.kjs

.kjs 扩展名是强制的,出错会有友好的提示。

适用场景

  • 在线代码编辑器 — 安全执行用户提交的代码片段
  • 游戏脚本引擎 — 给游戏提供可编程的能力(类似 Minecraft 里的 ComputerCraft)
  • 配置即代码 — 运行用户自定义逻辑但又不想暴露完整 Node.js 能力
  • CI/CD 流程 — 安全执行用户定义的 pipeline 脚本
  • 教学工具 — 理解 JS 引擎工作原理的绝佳参考(完整、自包含、代码量适中)

一些数据

指标
版本v1.55.0
依赖0
测试数225+
许可MIT
安装npm install kernel-js-lite

结尾

kernel-js-lite 是一个小而美的纯 JS 解释器,适合需要对不可信代码做沙箱执行的场景。它的设计哲学是:零依赖、可嵌入、够用就好。没有 V8 那么快,但对于控制台命令式的小脚本来说足够。

项目地址:www.npmjs.com/package/ker…

如果你在 Node.js 里需要安全地执行 JS 代码,不妨试试看。