首页
/ Deno 的 deno_web 扩展全解:Web API 如何从 Rust ops 到 JS 全局对象落地

Deno 的 deno_web 扩展全解:Web API 如何从 Rust ops 到 JS 全局对象落地

2026-09-04 09:22:08作者:温玫谨Lighthearted

本文基于 Deno 仓库中 ext/web 目录的官方文档(ext/web/README.md)及其配套源码展开,系统讲解 deno_web 扩展的职责边界、deno_core::extension! 宏注册机制、JS 脚本加载与全局对象装配流程、Rust 侧初始化参数,并深入剖析 timers、Base64、TextEncoding、Blob 等核心 API 的底层 ops 实现。读完后,你能够完整理解一个 Web 平台 API 从 V8 桥接到用户可用全局对象的全链路,并具备在此基础上定制或扩展 deno_core 运行时能力的思路。

1. deno_web 是什么:Deno 的 Web 平台 API 集合

deno_web 是 Deno 运行时中负责实现浏览器平台级 Web API 的扩展 crate,位于 ext/web/ 目录,crate 名称为 deno_web(见 ext/web/Cargo.toml,描述为 "Collection of Web APIs")。

ext/web/README.md 开宗明义地概括了它的核心职责:

Implements timers, as well as the following APIs:

  • Event
  • TextEncoder
  • TextDecoder
  • File (Spec: https://w3c.github.io/FileAPI)

Note: Testing for text encoding is done via WPT in cli/.

也就是说,它首先提供**定时器(timers)**与 **Event 事件模型、文本编解码(TextEncoder/TextDecoder)、文件(File/Blob/FileReader)**这几组最基础的平台能力。但从实际文件清单和源码来看,它承载的远不止这些——目录中按编号组织的一批 JS 实现文件覆盖了完整的 Web 平台 API 面:

文件 提供的能力
00_infra.js HTTP 解析等基础设施辅助函数
00_url.js URL / URLSearchParams
01_broadcast_channel.js BroadcastChannel
01_console.js console
01_dom_exception.js DOMException
01_mimesniff.js MIME 类型嗅探辅助
01_urlpattern.js URLPattern
02_event.js Event / EventTarget 及事件族
02_structured_clone.js structuredClone 核心算法
02_timers.js setTimeout / setInterval 等
03_abort_signal.js AbortController / AbortSignal
04_global_interfaces.js 全局接口辅助(toStringTag 等)
05_base64.js atob / btoa
06_streams.js Web Streams(Readable/Writable/Transform)
08_text_encoding.js TextEncoder / TextDecoder
09_file.js Blob / File
10_filereader.js FileReader
12_location.js Location
13_message_port.js MessageChannel / MessagePort / structuredClone
14_compression.js CompressionStream / DecompressionStream
15_performance.js performance / PerformanceMark / Measure
16_image_data.js ImageData
17_geometry.js DOMPoint / DOMRect / DOMMatrix 等几何类型
18_css_stylesheet.js CSSStyleSheet
locks.js Web Locks API
webtransport.js WebTransport

这些编号前缀不是随意的:deno_core 的扩展加载机制要求脚本按依赖顺序加载(00_* 是最底层基础设施,01_* 依赖它,依此类推),README 中的加载示例(下文详述)也严格遵循这一顺序。

Rust 侧的实现模块与这些 JS 一一对应,见 ext/web/lib.rs 中的模块声明:blobbroadcast_channelcompressionconsolegeometrymessage_portstream_resourcetimersurlurlpattern 等。

2. 扩展注册机制:deno_core::extension!

deno_web 与 deno_core 的集成完全由一个宏调用描述,位于 ext/web/lib.rsdeno_core::extension!(deno_web, ...) 中。这段宏是理解"Deno 扩展如何工作"的关键,它的每个字段都有明确职责:

deno_core::extension!(deno_web,
  deps = [ deno_webidl ],
  ops = [ op_base64_decode, op_encoding_new_decoder, /* ... */ ],
  objects = [ geometry::DOMMatrix, image_data::ImageData, /* ... */ ],
  lazy_loaded_esm = [ "locks.js", "webtransport.js" ],
  lazy_loaded_js = [ "00_infra.js", "00_url.js", /* ... */ ],
  options = {
    blob_store: Arc<dyn BlobStoreTrait>,
    maybe_location: Option<Url>,
    enable_css_parser_features: bool,
    bc: InMemoryBroadcastChannel,
  },
  state = |state, options| {
    state.put(options.blob_store);
    if let Some(location) = options.maybe_location {
      state.put(Location(location));
    }
    state.put(StartTime::default());
    state.put(geometry::State::new(options.enable_css_parser_features));
    state.put(options.bc);
    state.put(broadcast_channel::BroadcastSabStash::default());
  }
);

各字段的含义:

  • deps = [deno_webidl]:声明本扩展依赖 deno_webidl 扩展(WebIDL 类型转换工具,JS 侧表现为 ext:deno_webidl/00_webidl.js),与 README 中 "Dependencies" 一节一致——deno_webidldeno_webidl crate 提供。
  • ops:注册全部 Rust ops(下文按子系统逐一讲解),它们是 JS 通过 core.ops 可访问的原生函数。
  • objects:注册以"对象资源"形式持有的 Rust 类型(如 DOMMatrixImageDataCSSStyleSheetConsole),这类对象在 V8 中是长生命周期对象,由 GC 追踪。
  • lazy_loaded_js / lazy_loaded_esm:声明本扩展携带的 JS 脚本清单。普通脚本(lazy_loaded_js)按需加载;locks.jswebtransport.js 走 ESM 懒加载路径,对应 README 示例中的 core.createLazyLoader
  • options + state:定义运行时初始化时宿主必须提供的参数,并展示它们如何注入 OpState(ops 共享状态容器)——Blob 存储、可选的 Location URL、定时器起点 StartTime、几何状态与 BroadcastChannel 内存通道都在这里入栈。

3. 使用方式:JS 侧加载脚本并装配全局对象

ext/web/README.md 给出了在 JS 中装配整个 deno_web 扩展的标准做法:先用 core.loadExtScript 按序加载全部脚本,再把导出物挂到全局作用域。

3.1 按序加载扩展脚本

import { core } from "ext:core/mod.js";

const infra = core.loadExtScript("ext:deno_web/00_infra.js");
const url = core.loadExtScript("ext:deno_web/00_url.js");
const broadcastChannel = core.loadExtScript(
  "ext:deno_web/01_broadcast_channel.js",
);
const console = core.loadExtScript("ext:deno_web/01_console.js");
const DOMException = core.loadExtScript("ext:deno_web/01_dom_exception.js");
const mimesniff = core.loadExtScript("ext:deno_web/01_mimesniff.js");
const urlPattern = core.loadExtScript("ext:deno_web/01_urlpattern.js");
const event = core.loadExtScript("ext:deno_web/02_event.js");
const structuredClone = core.loadExtScript(
  "ext:deno_web/02_structured_clone.js",
);
const timers = core.loadExtScript("ext:deno_web/02_timers.js");
const abortSignal = core.loadExtScript("ext:deno_web/03_abort_signal.js");
const globalInterfaces = core.loadExtScript(
  "ext:deno_web/04_global_interfaces.js",
);
const base64 = core.loadExtScript("ext:deno_web/05_base64.js");
const streams = core.loadExtScript("ext:deno_web/06_streams.js");
const encoding = core.loadExtScript("ext:deno_web/08_text_encoding.js");
const file = core.loadExtScript("ext:deno_web/09_file.js");
const fileReader = core.loadExtScript("ext:deno_web/10_filereader.js");
const location = core.loadExtScript("ext:deno_web/12_location.js");
const messagePort = core.loadExtScript("ext:deno_web/13_message_port.js");
const compression = core.loadExtScript("ext:deno_web/14_compression.js");
const performance = core.loadExtScript("ext:deno_web/15_performance.js");
const imageData = core.loadExtScript("ext:deno_web/16_image_data.js");
const loadGeometry = core.createLazyLoader("ext:deno_web/geometry.js");
const loadWebTransport = core.createLazyLoader("ext:deno_web/webtransport.js");
const geometry = loadGeometry();
const webTransport = loadWebTransport();

两个细节值得注意:

  1. ext: 协议ext:deno_web/... 是 deno_core 的扩展资源协议,脚本内容在快照(snapshot)构建期被内嵌进二进制的 V8 快照,运行时按资源 ID 取用,而不是从磁盘读取。
  2. 懒加载器core.createLazyLoader 用于 geometrywebtransport 两个脚本——首次调用时才会真正求值,避免冷启动成本。对照 ext/web/lib.rslazy_loaded_esm / lazy_loaded_js 清单,当前源码中几何脚本的实际文件是 ext/web/17_geometry.js(README 示例写作 geometry.js,属于文档相对当前源码的轻微滞后)。

3.2 装配全局对象

加载完成后,README 给出了一段挂载示例与完整的属性表:

Object.defineProperty(globalThis, "AbortController", {
  value: abortSignal.AbortController,
  enumerable: false,
  configurable: true,
  writable: true,
});

完整的装配表如下(enumerable=false 保证这些平台对象不出现在 for...in 枚举中,与浏览器行为一致):

Name Value enumerable configurable writeable
AbortController abortSignal.AbortController false true true
AbortSignal abortSignal.AbortSignal false true true
Blob file.Blob false true true
BroadcastChannel broadcastChannel.BroadcastChannel false true true
ByteLengthQueuingStrategy streams.ByteLengthQueuingStrategy
CloseEvent event.CloseEvent false true true
CompressionStream compression.CompressionStream false true true
CountQueuingStrategy streams.CountQueuingStrategy
CustomEvent event.CustomEvent false true true
DecompressionStream compression.DecompressionStream false true true
DOMException DOMException false true true
ErrorEvent event.ErrorEvent false true true
Event event.Event false true true
EventTarget event.EventTarget false true true
File file.File false true true
FileReader fileReader.FileReader false true true
MessageEvent event.MessageEvent false true true
Performance performance.Performance false true true
PerformanceEntry performance.PerformanceEntry false true true
PerformanceMark performance.PerformanceMark false true true
PerformanceMeasure performance.PerformanceMeasure false true true
PromiseRejectionEvent event.PromiseRejectionEvent false true true
ProgressEvent event.ProgressEvent false true true
ReadableStream streams.ReadableStream false true true
ReadableStreamDefaultReader streams.ReadableStreamDefaultReader
TextDecoder encoding.TextDecoder false true true
TextEncoder encoding.TextEncoder false true true
TextDecoderStream encoding.TextDecoderStream false true true
TextEncoderStream encoding.TextEncoderStream false true true
TransformStream streams.TransformStream false true true
URL url.URL false true true
URLPattern urlPattern.URLPattern false true true
URLSearchParams url.URLSearchParams false true true
MessageChannel messagePort.MessageChannel false true true
MessagePort messagePort.MessagePort false true true
WritableStream streams.WritableStream false true true
WritableStreamDefaultWriter streams.WritableStreamDefaultWriter
WritableStreamDefaultController streams.WritableStreamDefaultController
ReadableByteStreamController streams.ReadableByteStreamController
ReadableStreamBYOBReader streams.ReadableStreamBYOBReader
ReadableStreamBYOBRequest streams.ReadableStreamBYOBRequest
ReadableStreamDefaultController streams.ReadableStreamDefaultController
TransformStreamDefaultController streams.TransformStreamDefaultController
ImageData imageData.ImageData false true true
atob base64.atob true true true
btoa base64.btoa true true true
clearInterval timers.clearInterval true true true
clearTimeout timers.clearTimeout true true true
console new console.Console(printer) false true true
performance performance.performance true true true
reportError event.reportError true true true
setInterval timers.setInterval true true true
setTimeout timers.setTimeout true true true
structuredClone messagePort.structuredClone true true true

一个值得玩味的规律:构造函数(EventBlob…)以 enumerable: false 挂载,而函数(setTimeoutatob)与 performance 单例是 enumerable: true——这正是浏览器全局对象的实际属性描述符特征,deno_web 在这一点上刻意复刻了浏览器语义。

4. Rust 侧初始化参数

README 同时规定了宿主(如 Deno CLI 或嵌入 deno_core 的自定义运行时)在 Rust 侧必须做的事:

Then from rust, provide: deno_web::deno_web::init(Arc<dyn BlobStoreTrait>, Option<Url>, bool, InMemoryBroadcastChannel) in the extensions field of your RuntimeOptions

Where:

  • Arc<dyn BlobStoreTrait> can be provided by BlobStore::default_arc()
  • Option<Url> provides an optional base URL for certain ops
  • bool indicates whether window features are enabled at initialization
  • InMemoryBroadcastChannel can be provided by Default::default()

对照 ext/web/lib.rsoptions 定义,四个参数与当前源码一一对应:

  1. Arc<dyn BlobStoreTrait>:Blob 数据存储。BlobStoreTrait 定义于 ext/web/blob.rs,抽象了"按 UUID 存取 Blob part、管理 blob: Object URL"的职责;默认实现 BlobStore 提供 default_arc() 工厂。由于是 trait 对象,嵌入方可以替换成带内存限制或持久化的自定义存储。
  2. Option<Url>maybe_location:可选基准 URL,用于 Location 以及 Blob Object URL 生成(insert_object_url 需要 maybe_location)。Some 时会被封装为 Location(Url) 放入 OpState
  3. boolenable_css_parser_features:当前源码中该布尔位控制是否启用 CSS 解析特性(见 geometry::State::new(options.enable_css_parser_features)),影响 cssparser 相关能力是否开启。
  4. InMemoryBroadcastChannelbc):进程内 BroadcastChannel 消息通道的内存实现,可用 Default::default() 构造。

state 闭包展示了这些参数如何落地:blob_storeLocationStartTime(timers 的时间原点)、几何状态、bc 以及 BroadcastSabStash 全部注入 OpState,随后 ops 通过 state.borrow::<T>() / state.put 读写它们。

5. 定时器:从 op_nowsetTimeout 的全链路

README 把 timers 列为 deno_web 的头号职责。这条链路横跨 Rust 与 JS 两层。

5.1 Rust 层:时间原语

ext/web/timers.rs 只有约 57 行,却包含全部时间原语:

pub struct StartTime(Instant);

#[op2(fast)]
pub fn op_now(state: &mut OpState, #[buffer] buf: &mut [u8]) {
  let start_time = state.borrow::<StartTime>();
  let elapsed = start_time.elapsed();
  expose_time(elapsed, buf);
}

#[op2(fast)]
pub fn op_time_origin(state: &mut OpState, #[buffer] buf: &mut [u8]) {
  // https://w3c.github.io/hr-time/#dfn-estimated-monotonic-time-of-the-unix-epoch
  let wall_time = SystemTime::now();
  let monotonic_time = state.borrow::<StartTime>().elapsed();
  let epoch = wall_time.duration_since(UNIX_EPOCH).unwrap() - monotonic_time;
  expose_time(epoch, buf);
}

三个要点:

  • StartTime 在扩展初始化时写入 OpState(见第 4 节的 state.put(StartTime::default())),作为单调时钟原点;op_now 返回相对原点的流逝时间。
  • op_time_origin 实现了 W3C HR-Time 规范中的 "estimated monotonic time of the UNIX epoch":用当前墙钟时间减去单调流逝时间,反推出"epoch 对应的单调估计值",从而让 performance.timeOriginDate.now() 在同一时间轴上自洽。
  • expose_time 直接把秒(u32)与纳秒余数(u32)以原机字节序写入 8 字节 buffer,JS 侧用 Uint32Array 视图一次读出,避免跨边界的浮点舍入问题。
  • 第三个 op op_deferasync(lazy) 空函数)用于让 JS 侧获得一个可延后的异步 tick,服务于定时器回调的调度。

5.2 JS 层:WHATWG 语义补全

ext/web/02_timers.js 在核心 core.createTimer 之上补齐浏览器语义,文件头注释概括得很清楚:

// Web timers (setTimeout/setInterval) built directly on core.createTimer.
// Adds WHATWG-specific behavior on top:
// - webidl type coercion
// - string callback eval (WHATWG spec)
// - timer nesting depth tracking (WHATWG spec)
// - numeric timer IDs
// AsyncContext propagation across the callback boundary

setTimeout 为例(ext/web/02_timers.js):

  • this 检查checkThis 要求 thisnull/undefined/globalThis,否则抛 TypeError: Illegal invocation——保证 window.setTimeout.call({}, ...) 这类误用会按规范报错。
  • 字符串回调:若传入的不是函数,则经 WebIDL 转为字符串后用 indirectEval 执行,符合 WHATWG "evaluate a string as a script" 的要求。
  • AsyncContext 传播:注册时捕获 getAsyncContext(),回调执行时 setAsyncContext 恢复——这使 await 链路中的资源追踪(如 Deno 的 async locals)能跨定时器边界保持连续。
  • 嵌套深度追踪:模块级 timerDepth 在回调内 +1、结束后恢复,对应规范中"嵌套定时器最小延迟递增"的条款。
  • 数字 IDcreateTimer 返回的内部对象被存入 activeTimers Map,对外暴露 timer._timerId 数字句柄,clearTimeout/clearInterval 按 ID 查找并 cancelTimer

6. Base64:simdutf 加速的 atob / btoa

atob/btoa 看起来平凡,却是 ext/web/lib.rs 中性能工程最集中的部分。

6.1 JS 层:规范的错误语义

ext/web/05_base64.js 中,两个函数都是"webidl 参数校验 → 调 op → 错误翻译"的薄封装:

function atob(data) {
  const prefix = "Failed to execute 'atob'";
  webidl.requiredArguments(arguments.length, 1, prefix);
  data = webidl.converters.DOMString(data, prefix, "Argument 1");
  try {
    return op_base64_atob(data);
  } catch (e) {
    if (ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e)) {
      throw new DOMException(
        "Failed to decode base64: invalid character",
        "InvalidCharacterError",
      );
    }
    throw e;
  }
}

Rust op 抛出的 TypeError 会被翻译为浏览器的 DOMException(InvalidCharacterError)btoa 同理("string contains characters outside of the Latin1 range")。Rust 侧的错误分类定义在 ext/web/lib.rsWebError 枚举,#[class("DOMExceptionInvalidCharacterError")] 等注解让 op 抛出的错误直接呈现为正确的 JS 异常类型。

6.2 Rust 层:零拷贝与 SIMD

核心 op 包括 op_base64_decodeop_base64_decode_intoop_base64_encode_from_bufferop_base64_atobop_base64_btoa,底层全部走 simdutf(经由 V8 暴露的 v8::simdutf):

  • op_base64_atobext/web/lib.rs):小于 8KB 的输出走栈上 8KB 缓冲解码后截断回填;大输出则直接返回解码后的新 buffer,注释明确说明这是"省掉每次大 atob 调用输出全量 memcpy"的优化。
  • op_base64_encode_from_buffer:接受 offset/length 子区间参数,"avoiding a JS-side slice copy"——JS 不必先 ArrayBuffer.slice() 再编码。
  • base64_encode_to_v8_string:输出小于 8KB 时栈上编码并 new_from_one_byte 构造 V8 单字节串;更大时编码进 Box<[u8]> 后用 new_external_onebyte 把所有权交给 V8(GC 时由 V8 释放),同样避免拷贝。
  • base64url 家族:从源码结构看,当前源码还注册了 op_base64url_decodeop_base64url_decode_intoop_base64url_encode_from_buffer(见 ext/web/lib.rsext/web/lib.rs),使用 Base64Options::Url 字母表(-_ 替代 +/、无填充),README 的 ops 清单尚未列出这批新 op。
  • 截断写入哨兵base64_decode_into_slice 在输入非法时返回 -1 而非抛异常,注释解释这是为了让 JS 清洗回退路径"不用为脏输入付出抛异常的成本"。

正确性由 ext/web/lib.rs 中的单元测试锁定:RFC 4648 测试向量、64KiB 往返、Strict/Loose 末块处理差异(base64url_strict_rejects_unpadded_final_chunk 直接固化了"为什么 base64url 直解必须用 Loose"这一设计决策)、8192 字节栈/堆缓冲边界(base64url_decode_into_slice_scratch_boundary)等,覆盖面相当完整。

7. TextEncoding:encoding_rs + ASCII 快速路径

README 特别注明"Text encoding 的测试通过 cli/ 下的 WPT 用例完成"。Rust 侧 ops(ext/web/lib.rs)分为"一次性解码"和"流式解码器"两条路:

  • op_encoding_normalize_label:用 encoding_rs::Encoding::for_label_no_replacement 规范化编码标签(如 UNICODE-1-1-UTF-8utf-8),非法标签抛 InvalidEncodingLabelWebError 中为 range 类错误)。
  • op_encoding_decode_utf8:纯 ASCII 输入直接 new_from_one_byte 返回 V8 串——注释称这是"HTTP/JSON 正文、文件读取等现实主导场景",simdutf::validate_ascii 的高位扫描使该检查近乎免费;非 ASCII 才走 BOM 剥离 + UTF-8 校验。解码结果超长于 V8 容量时返回 BufferTooLongRangeError),并链接到 WHATWG 编码规范与 deno 历史 issue。
  • 流式解码器op_encoding_new_decoder 创建一个 #[cppgc] 资源 TextDecoderResource(内含 RefCell<Decoder>fatal 标志),op_encoding_decode 携带 stream 参数对其增量解码——!stream 时 flushing 掉解码器内部状态,这正是 TextDecoder 规范中 stream: falsetrue 的语义差别。
  • ASCII-only 流式快速路径op_encoding_decode_utf8_ascii_only 在输入为纯 ASCII 时直接返回 V8 串,否则返回 null;JS 侧据此跳过 Vec<u16> 分配与 UTF-16 转换,同时保持解码器状态空闲。
  • 编码(encode_into)op_encoding_encode_into 把字符串直接写进目标 buffer 并返回打包的 (read, written) 结果,还配有 V8 fast-api 变体 op_encoding_encode_into_fast(输入已是 UTF-8 时按字符边界回退找截断点,纯内存拷贝)与 op_encoding_encode_into_fallback(结果写入 u32 输出 buffer 的慢路径),三级路径兼顾了吞吐与超大量级安全。

8. Blob / File:可插拔的 BlobStore

File API(README 列名的核心能力之一,规范即 W3C FileAPI)由 ext/web/09_file.js(JS)与 ext/web/blob.rs(Rust)协作实现。Rust 侧的核心抽象:

/// Trait abstracting the blob store, allowing custom implementations
/// (e.g. with memory limits or persistence).
pub trait BlobStoreTrait: Debug + Send + Sync {
  fn insert_part(&self, part: Arc<dyn BlobPart + Send + Sync>) -> Uuid;
  fn get_part(&self, id: &Uuid) -> Option<Arc<dyn BlobPart + Send + Sync>>;
  fn remove_part(&self, id: &Uuid) -> Option<Arc<dyn BlobPart + Send + Sync>>;
  fn get_object_url(&self, url: Url) -> Option<Arc<Blob>>;
  fn insert_object_url(&self, blob: Blob, maybe_location: Option<Url>) -> Url;
  fn remove_object_url(&self, url: &Url);
  fn clear(&self);
}
  • Blob 的每个数据片段(part)以 UUID 索引存入 PartMapHashMap<Uuid, Arc<dyn BlobPart>>),op_blob_create_part 写入、op_blob_read_part/op_blob_slice_part/op_blob_clone_part 读写、op_blob_remove_part 清理——大文件因此可以按需分片读取而不必整体驻留。
  • Object URL 生命周期op_blob_create_object_url 生成 blob:<base>/<uuid> 形式的 URL(依赖第 4 节的 maybe_location),op_blob_revoke_object_url 释放,op_blob_from_object_url 反查 Blob。
  • 错误类型 BlobErrorext/web/blob.rs)区分 BlobPartNotFoundSizeLargerThanBlobPartBlobURLsNotSupported(未提供 base URL 时 URL.createObjectURL 不可用),均标注 type 错误类。

9. 其余 ops 分组速览

除上文重点剖析的子系统外,README "Provided ops" 一节列出的完整 ops 清单可按子系统归类如下(均经 Deno.ops / core.ops 访问):

  • Base64op_base64_decodeop_base64_decode_intoop_base64_encode_from_bufferop_base64_atobop_base64_btoa
  • 编码op_encoding_normalize_labelop_encoding_decode_singleop_encoding_decode_utf8op_encoding_new_decoderop_encoding_decodeop_encoding_encode_intoop_encoding_encode_into_fallback
  • Blobop_blob_create_partop_blob_slice_partop_blob_read_partop_blob_remove_partop_blob_clone_partop_blob_create_object_urlop_blob_revoke_object_urlop_blob_from_object_url
  • MessagePortop_message_port_create_entangled(创建纠缠的一对 MessagePort)、op_message_port_post_messageop_message_port_post_message_rawop_message_port_recv_message(异步收包)、op_message_port_recv_message_sync
  • 压缩op_compression_newop_compression_writeop_compression_finish(支撑 14_compression.js 的 CompressionStream/DecompressionStream;Rust 依赖 ext/web/Cargo.toml 中的 brotliflate2 提供 gzip/deflate/brotli 编解码)
  • 时间op_nowop_time_originop_defer
  • 几何op_geometry_get_enable_css_parser_featuresop_geometry_matrix_set_matrix_valueop_geometry_matrix_to_string,以及作为注册对象的 DOMPointReadOnlyDOMPointDOMRectReadOnlyDOMRectDOMQuadDOMMatrixReadOnlyDOMMatrixImageData
  • 可读流资源op_readable_stream_resource_allocateop_readable_stream_resource_allocate_sizedop_readable_stream_resource_get_sinkop_readable_stream_resource_write_errorop_readable_stream_resource_write_bufop_readable_stream_resource_write_syncop_readable_stream_resource_closeop_readable_stream_resource_await_close(把 Rust 侧资源包装成 ReadableStream 的基础设施)
  • URL / URLPatternop_url_reparseop_url_parseop_url_get_serializationop_url_parse_with_baseop_url_parse_search_paramsop_url_stringify_search_paramsop_urlpattern_parseop_urlpattern_process_match_input(URLPattern 由 urlpattern crate 提供)
  • 控制台op_preview_entries(源码中还注册了 op_console_inspectop_console_format_value 等一批 console 格式化 ops,见 ext/web/lib.rs
  • BroadcastChannelop_broadcast_subscribeop_broadcast_unsubscribeop_broadcast_serializeop_broadcast_deserializeop_broadcast_freeop_broadcast_sendop_broadcast_recv

ext/web/lib.rs 的宏注册清单还可以看到,当前源码比 README 清单多出一组 op_lock_manager_*(request/await_lock/await_steal/is_stolen/cancel/release/query),支撑 ext/web/locks.js 的 Web Locks API——README 尚未同步这一批 op。

10. 测试与基准

deno_web 的质量验证分布在三个层面,可在仓库内直接查证:

  1. Rust 单元测试ext/web/lib.rs 起约 360 行 #[cfg(test)] 代码,覆盖 Base64/URL 编解码的正确性向量、边界与安全断言(如 base64_decode_into_asserts_output_capacity 验证"输出容量不足会在内存不安全之前 panic")。
  2. 基准测试ext/web/Cargo.toml 声明了四个 bench——encodingtimers_opsurl_opstext_decoder_stream(对应 ext/web/benches/ 目录),可单独验证高频 op 的吞吐。
  3. WPT 与集成测试:README 明确 TextEncoding 的规范符合性测试放在 cli/ 下的 WPT 用例中(仓库根下 tests/ 目录亦含大量 Web API 集成与 WPT 适配,见 tests/wpt/tests/README.md)。

11. 小结

deno_web 展示了 Deno "Rust 提供不可信输入下的原生能力、JS 提供规范语义"的扩展分层范式:

  • 注册:一个 deno_core::extension! 宏声明 deps、ops、objects、JS 清单与初始化选项,ext/web/lib.rs 是该扩展的"单一事实来源";
  • 加载:JS 侧 core.loadExtScript 按编号顺序装配,createLazyLoader 延迟非关键脚本;
  • 装配:50 余个全局属性以浏览器一致的属性描述符挂到 globalThis
  • 实现:timers、Base64、encoding、Blob 等每条 API 都有 ops 层(含 fast-api、SIMD、零拷贝等性能路径)与 JS 层(WebIDL 校验、规范错误语义)的明确分工;
  • 宿主集成:只需在 RuntimeOptions.extensions 中提供 BlobStoreTrait、可选 Url、CSS 特性开关与 InMemoryBroadcastChannel 四个参数即可启用。

如果你要在自定义 deno_core 运行时上扩展 Web 能力,ext/web 是最值得逐行研读的范本;若只想查阅 API 清单与装配表,ext/web/README.md 依然是入口文档,配合 ext/web/lib.rs 的 ops 注册宏即可获得最新、最完整的能力边界。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.79 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
988
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384