菜单

Node.js 兼容性

相关源文件

本文档描述了 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文件操作
HTTPop_node_http_request_with_connHTTP 客户端功能
进程op_node_process_kill, op_process_abort进程管理
Requireop_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 定时器函数
  • 具有 Node.js 语义的定时器函数

来源:ext/node/global.rs66-80 ext/node/global.rs267-300 ext/node/global.rs123-228

CommonJS 模块系统

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

HTTP 兼容性层

Deno 通过 polyfills 提供全面的 HTTP 兼容性,这些 polyfills 将 Node.js HTTP API 桥接到 Deno 的原生 HTTP 实现。该系统包含客户端和服务器功能,支持 HTTP/1.1、HTTP/2 和 HTTPS。

HTTP 客户端实现

HTTP 客户端架构

ClientRequest 类实现了完整的 Node.js HTTP 客户端接口

功能实现文件引用
请求创建ClientRequest 构造函数ext/node/polyfills/http.ts184-459
Header 管理_writeHeader() 方法ext/node/polyfills/http.ts461-717
Response 处理IncomingMessageForClientext/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 集成

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 APIDeno 操作
文件存在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 兼容性

DNS 解析系统

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 多个内置模块,包括

模块类别示例实现
核心 APIhttphttpsfscrypto完整的 polyfill 实现
Stream APIstream_stream_*Stream 兼容层
内部 APIinternal/*Node.js 内部模块支持
实用工具 APIutilpathos跨平台实现

来源: ext/node/polyfills/01_require.js171-284 ext/node/polyfills/01_require.js70-165

初始化和引导

Node.js 兼容层需要仔细初始化,以设置全局环境、配置模块解析并建立正确的执行上下文。

Node.js 初始化流程

初始化过程配置了

  1. 全局对象:设置 Node.js 特定的全局对象,如 Bufferprocessglobal
  2. 模块系统:初始化 CommonJS 的 require 系统和模块缓存
  3. 权限集成:为 Node.js 兼容性配置 Deno 的权限系统
  4. Worker 线程:为多线程 Node.js 应用程序设置 worker 线程支持

来源: 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