本文档描述了 Deno 的 Node.js 兼容层,它使得 Node.js 代码和 npm 包能在 Deno 运行时中执行。该系统提供了 Node.js 内置模块的 polyfills,实现了 CommonJS 模块系统,并管理 Node.js 和 Deno 环境之间的全局对象差异。
有关 npm 包集成和模块加载的信息,请参阅 NPM 集成。有关兼容性测试流程的详细信息,请参阅 兼容性测试。
Node.js 兼容性系统作为一个 Deno 扩展(deno_node)实现,它将 Node.js API 桥接到 Deno 的底层能力。该系统通过三个主要层运行:JavaScript/TypeScript 中的 polyfill 实现、用于原生功能的 Rust 操作(ops)以及一个动态切换 Deno 和 Node.js 行为的全局管理系统。
Node.js 兼容性架构
来源:ext/node/lib.rs253-899 ext/node/global.rs123-145 ext/node/polyfills/02_init.js13-89
该 deno_node 扩展使用 Deno 的扩展宏系统定义,注册所有 Node.js 操作、对象和模块映射。该扩展支持用于 npm 包检查、文件夹解析和文件系统抽象的参数化类型。
扩展注册系统
扩展注册包括全面的操作映射
| 操作类别 | 示例操作 | 目的 |
|---|---|---|
| 加密 | op_node_hash_digest, op_node_sign | 加密函数 |
| 文件系统 | op_node_fs_exists, op_node_cp | 文件操作 |
| HTTP | op_node_http_request_with_conn | HTTP 客户端功能 |
| 进程 | op_node_process_kill, op_process_abort | 进程管理 |
| Require | op_require_resolve_deno_dir | 模块解析 |
来源:ext/node/lib.rs253-500 ext/node/lib.rs509-767
Deno 实现了一个复杂的全局代理系统,该系统根据代码是在 Node.js 上下文还是 Deno 上下文中执行,动态地提供不同的全局对象。该系统使用 V8 命名属性处理器来拦截全局属性访问,而不会对常见全局变量产生性能开销。
全局属性解析系统
受管理的全局对象包括关键的 Node.js 特有对象
Buffer - Node.js buffer 实现process - 具有 Node.js API 的 Process 对象global - 指向全局对象的引用setImmediate/clearImmediate - Node.js 定时器函数来源:ext/node/global.rs66-80 ext/node/global.rs267-300 ext/node/global.rs123-228
Node.js 兼容性层通过 require() 函数和 Module 类实现了一个完整的 CommonJS 模块系统。该系统支持模块解析、缓存和加载,并完全支持 Node.js 语义。
CommonJS 模块解析算法
解析系统支持多种策略
| 解析类型 | 实现 | 用例 |
|---|---|---|
| 相对路径 | op_require_is_request_relative() | 本地模块导入 |
| Node 模块 | op_require_node_module_paths() | npm 包解析 |
| Deno 目录 | op_require_resolve_deno_dir() | Deno 缓存集成 |
| 包导出 | op_require_resolve_exports() | 现代 package.json 导出 |
来源:ext/node/polyfills/01_require.js669-726 ext/node/polyfills/01_require.js538-625 ext/node/polyfills/01_require.js631-667
模块扩展系统
来源:ext/node/polyfills/01_require.js421-435 ext/node/polyfills/01_require.js502-503
Deno 通过 polyfills 提供全面的 HTTP 兼容性,这些 polyfills 将 Node.js HTTP API 桥接到 Deno 的原生 HTTP 实现。该系统包含客户端和服务器功能,支持 HTTP/1.1、HTTP/2 和 HTTPS。
HTTP 客户端架构
该 ClientRequest 类实现了完整的 Node.js HTTP 客户端接口
| 功能 | 实现 | 文件引用 |
|---|---|---|
| 请求创建 | ClientRequest 构造函数 | ext/node/polyfills/http.ts184-459 |
| Header 管理 | _writeHeader() 方法 | ext/node/polyfills/http.ts461-717 |
| Response 处理 | IncomingMessageForClient | ext/node/polyfills/http.ts996-1588 |
| 连接管理 | Socket 抽象 | ext/node/polyfills/http.ts138-177 |
来源:ext/node/polyfills/http.ts184-974 ext/node/ops/http.rs154-891
HTTPS 和 TLS 支持
来源:ext/node/polyfills/https.ts21-162 ext/node/polyfills/_tls_wrap.ts63-254 ext/node/polyfills/_tls_wrap.ts140-212
Node.js 文件系统兼容性层提供了对 Node.js fs 模块 API 的全面支持,包括同步和异步变体。该实现将 Node.js 语义桥接到 Deno 的基于权限的文件系统。
文件系统架构
关键文件系统操作包括
| 操作类型 | Node.js API | Deno 操作 |
|---|---|---|
| 文件存在 | fs.exists(), fs.existsSync() | op_node_fs_exists |
| 文件复制 | fs.cp(), fs.cpSync() | op_node_cp |
| 文件元数据 | fs.stat(), fs.lstat() | op_require_stat |
| 目录操作 | fs.mkdir(), fs.readdir() | 标准 Deno op |
来源: ext/node/lib.rs52-154 ext/node/lib.rs368-376
DNS 兼容层使用 Deno 的底层网络能力,结合自定义的解析逻辑和缓存,实现了 Node.js 的 DNS API。
DNS 解析架构
来源: ext/node/polyfills/dns.ts400-600 ext/node/polyfills/internal_binding/cares_wrap.ts30-500
网络套接字系统
来源: ext/node/polyfills/net.ts600-1200 ext/node/polyfills/internal_binding/tcp_wrap.ts100-400 ext/node/polyfills/internal_binding/stream_wrap.ts116-400
Node.js 兼容层通过一个全面的映射系统,为所有主要的 Node.js 内置模块提供了 polyfill。每个模块的实现都旨在匹配 Node.js 的语义,同时利用 Deno 的底层能力。
内置模块注册
该系统注册了 70 多个内置模块,包括
| 模块类别 | 示例 | 实现 |
|---|---|---|
| 核心 API | http、https、fs、crypto | 完整的 polyfill 实现 |
| Stream API | stream、_stream_* | Stream 兼容层 |
| 内部 API | internal/* | Node.js 内部模块支持 |
| 实用工具 API | util、path、os | 跨平台实现 |
来源: ext/node/polyfills/01_require.js171-284 ext/node/polyfills/01_require.js70-165
Node.js 兼容层需要仔细初始化,以设置全局环境、配置模块解析并建立正确的执行上下文。
Node.js 初始化流程
初始化过程配置了
Buffer、process、global来源: ext/node/polyfills/02_init.js13-89 ext/node/polyfills/01_require.js500-507
Node.js 兼容层实现了全面的错误处理,匹配 Node.js 的错误语义,包括错误代码、堆栈跟踪和错误继承模式。
错误处理架构
错误系统提供具有正确继承、错误代码和堆栈跟踪保留的 Node.js 兼容错误对象。
来源: ext/node/polyfills/internal/errors.ts1-100 ext/node/ops/http.rs104-152