JavaScript 生态长期面临一个根本性问题:各引擎和工具链各自维护独立的中间表示(IR),导致分析、转换和跨平台编译的重复建设。V8 有自己的字节码和编译管道,SpiderMonkey 同样如此,而社区中的 lint 工具、混淆器、静态分析框架更是各持一套 AST 规范。JSIR(JavaScript Intermediate Representation)的出现,正是为了在语言层面建立一个统一且足够高层次的 IR,从根本上缓解这种碎片化。

JSIR 的设计定位

JSIR 是一个构建在 MLIR 之上的高级 JavaScript 中间表示,由 Google 推动并已在内部生产环境部署。与传统 LLVM IR 专注于低层次代码生成不同,JSIR 的核心目标是保留足够多的源代码信息,实现从 JavaScript 源码到 IR 再到等效源码的无损往返(lossless round-trip)。这意味着开发者可以将一段 JavaScript 代码解析为 JSIR,进行各种分析或转换后,还能还原回与原文件在语义和结构上完全一致的代码。

该设计使得 JSIR 位于传统 AST 与低层次 IR 之间的理想位置:它保留了 AST 的结构化信息(语法树节点、作用域、词法环境),同时引入了 IR 特有的数据流和控制流建模能力。JSIR 并不替代 V8 或 SpiderMonkey 等 JavaScript 引擎的执行管道,而是为外部工具链提供一个统一的目标格式 —— 安全分析、代码混淆检测、源码到源码的转换、污点追踪等场景均可受益。

两大 dialect:JSHIR 与 JSLIR

JSIR 规范中定义了两个层级化的 dialect,用于满足不同阶段的需求。JSHIR(JavaScript Source-level High-level IR)是高层 dialect,保持接近源码的结构化表示,使用 MLIR 的区域(region)来自然地建模 ifwhilefor 等结构化控制流。这种设计使得控制流层次一目了然,便于执行源码重构、代码美化、模式匹配等 source-to-source 变换。

JSLIR(JavaScript Low-level IR)则是低层 dialect,呈现为经典的 CFG(控制流图)形式,每条指令都有明确的前驱和后继块。JSLIR 适合执行数据流分析、常量传播、活跃变量分析等基于 CFG 的优化或安全检查。两者之间可以相互转换:JSHIR 可以 lower 为 JSLIR 进行深入分析,而 JSLIR 也可以在需要时提升回 JSHIR 进行源码还原。这种双向转换能力是实现无损往返的关键技术保障。

解决碎片化的工程路径

JavaScript 工具链碎片化的根源在于缺乏统一的 IR 标准。各大公司维护的静态分析工具往往需要针对不同 AST 格式(如 ESTree、Babel AST、Acorn AST)编写适配层,安全研究中的漏洞检测工具也常因引擎差异而需要多套实现。JSIR 通过提供公开、稳定的 IR 定义,直接对标 ESTree 规范,使得大多数 AST 节点到 JSIR 操作的映射接近一对一。

在工程实践中,引入 JSIR 可以显著降低工具开发的适配成本。一个典型的部署路径如下:首先通过前端解析器(支持 ESTree 兼容输出)将 JavaScript 源码转换为 JSHIR;随后根据需要选择在不同 dialect 上工作 —— 若需源码级别的转换或重写,留在 JSHIR 层;若需进行污点分析、控制流敏感的安全检查,则 lower 到 JSLIR 完成分析后,可选择将结果映射回源码层面。整个过程无需针对特定引擎或前端框架编写额外适配代码。

面向未来的 MLIR 融合价值

JSIR 的另一个重要价值在于它验证了 MLIR 在非传统编译器场景中的适用性。MLIR 最初为构建领域特定编译器而设计,其区域嵌套、dialect 分层、渐进式 lowering 等特性在高级语言表示中同样发挥出色。Google 将 JSIR 描述为 MLIR 的「实战检验」,表明同一套基础设施既可以承载像 CUDA、HLSL 这样的领域特定语言,也可以处理 JavaScript 这种通用运行时语言。

对于希望在 JavaScript 工具链中引入更系统化 IR 能力的团队,建议关注以下实践参数:解析阶段优先选用 ESTree 兼容的 parser 以减少映射损耗;转换 pipeline 中保持 JSHIR ↔ JSLIR 的双向通道畅通,避免单向 lower 后丢失源码结构信息;安全分析场景可利用 MLIR 内置的数据流分析框架快速构建污点追踪 pass。

JSIR 的出现代表了一种思路转变:从围绕特定引擎或工具构建专用 IR,转向构建一个社区共建的、足够高层次的共享表示。当这种统一的 IR 成为生态基础设施后,JavaScript 工具链的碎片化问题将迎来实质性的改善。

资料来源:本文技术细节参考 LLVM Discourse 上关于 JSIR 的 RFC 讨论以及 Google jsir GitHub 仓库的设计文档。