尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

结构化克隆算法深度解析:HTML Standard中安全传递对象与可转移对象的完整规则

结构化克隆算法深度解析:HTML Standard中安全传递对象与可转移对象的完整规则 结构化克隆算法深度解析HTML Standard中安全传递对象与可转移对象的完整规则【免费下载链接】htmlHTML Standard项目地址: https://gitcode.com/gh_mirrors/ht/html结构化克隆Structured Clone是 HTML Standard 中用于在不同执行环境之间安全传递 JavaScript 对象的核心机制。当你调用structuredClone()、postMessage()等 API 时浏览器内部执行的就是这套序列化 → 反序列化流程它能深拷贝对象图、保留循环引用还能通过可转移对象Transferable Objects实现零拷贝的高性能传输。本文带你逐条拆解 HTML Standard 对「可序列化对象」与「可转移对象」的完整规则以及DataCloneError的触发条件。什么是结构化克隆跨边界传数据的底层原理HTML Standard 在Safe passing of structured data结构化数据的安全传递一节中定义了整套序列化/反序列化基础设施用于把 JavaScript 对象包括平台对象从一个realm边界传递到另一个 realm甚至跨越 agent如主线程与 Web Worker乃至 agent cluster如同一站点的所有浏览上下文。整个过程分为两步阶段抽象操作作用序列化StructuredSerialize把值转成与 realm 无关的 Record 形式反序列化StructuredDeserialize在目标 realm 重建出一个全新的对象副本 规范原文指出大多数 API 是分两步独立执行的序列化与反序列化唯一的例外就是structuredClone()方法它在同一 realm 内一次完成克隆。相关定义见 source。这意味着克隆得到的对象是独立的副本修改副本不会影响原对象而函数、闭包、DOM 节点等与 realm 强绑定的东西则无法克隆——这正是安全传递的含义。可序列化对象规则哪些值能通过结构化克隆只有被规范称为serializable objects可序列化对象的值才支持结构化克隆且并非对象的所有方面都会在序列化中保留见 source。✅默认可克隆的值由StructuredSerializeInternal直接处理原始值undefined、null、Boolean、Number、BigInt、StringMap/Set保留插入顺序Date、RegExp含源码与 flagsArrayBuffer及其变体Resizable / SharedArrayBuffer全部 TypedArray 与DataViewError及其子类name、message、stack数组与普通对象无特殊内部槽的纯对象标记了[Serializable]扩展属性的平台对象如FormData、Blob、File、MessagePort等❌会抛出DataCloneError的值见 sourceSymbol函数IsCallable为真Proxy 等特殊对象、带[[PromiseState]]等内部槽的对象未标记[Serializable]的普通平台对象已 detached 的ArrayBuffer非跨源隔离cross-origin isolated环境下传递SharedArrayBuffer平台对象如何申请可序列化接口上标注[Serializable]扩展属性并实现一对称的serialization steps与deserialization steps算法规范中还给出了完整的Person示例定义见 source。可转移对象详解传输而非复制的高性能方案Transferable objects可转移对象解决的是另一个问题大对象尤其是内存缓冲区复制代价很高。HTML Standard 的策略是传输——把底层数据的所有权移交给接收方同时让发送方的原对象脱钩detach失效见 source。⚠️ 关键特性不可逆一旦对象被传输它既不能被再次传输也不能再被使用。每个可转移的平台对象都带有一个[[Detached]]内部槽用于阻止重复传输见 source。接口需标注[Transferable]并实现对称的transfer steps/transfer-receiving steps见 source。典型的 Web 可转移对象包括ArrayBuffer、MessagePort、ImageBitmap、AudioNode、VideoFrame等。StructuredSerializeWithTransfer对 transfer 列表有严格校验违反任何一条都抛DataCloneError见 source列表项既无[[ArrayBufferData]]槽也无[[Detached]]槽 → 不是可转移对象报错SharedArrayBuffer禁止作为 transfer 列表项同一个对象在列表中重复出现→ 报错ArrayBuffer已处于 detached 状态 → 报错。上图中的MediaStream及其轨道正是与结构化克隆密切相关的类型——MediaStreamTrack是可转移对象MediaStream同时支持序列化与传输让媒体流可以在 Worker、浏览上下文之间高效流转。循环引用怎么办memory 记忆表的工作原理对象图里经常存在循环引用a.b a。StructuredSerializeInternal用一个memory映射表解决每处理一个对象前先查memory[value]已存在则直接返回避免二次序列化新对象序列化前先登记进memory再递归处理其成员Map/Set/Array/Object 均如此见 source 与 source。结果就是循环被保留图中重复引用的对象在克隆后仍指向同一个副本——对象图的拓扑结构完整还原。反序列化侧的StructuredDeserialize同样维护这张表见 source。谁在调用结构化克隆常见 API 对照HTML Standard 专门有一节 Performing serialization and transferring from other specifications 说明各 API 使用哪套抽象操作见 sourceAPI使用的操作特点messagePort.postMessage()StructuredSerializeWithTransfer目标 realm 未知先序列化缓存window.postMessage()StructuredSerializeWithTransfer支持 transfer 列表跨文档传消息broadcastChannel.postMessage()StructuredSerialize/StructuredDeserialize广播给同源其他浏览上下文存储类 API如sessionStorageStructuredSerializeForStorage持久化存储SharedArrayBuffer不可用上图标出了文档内焦点树的层级关系——每一个浏览上下文都是一个独立 realm而结构化克隆正是跨越这些边界传递结构化数据的桥梁。structuredClone() 使用指南与 DataCloneError 排查structuredClone()是唯一一步到位的克隆 API定义在 sourceresult self.structuredClone(value[, { transfer }])对value执行完整结构化克隆返回深拷贝transfer数组中的可转移对象会被传输而非克隆传输后在value中不可再使用输入中任何部分不可序列化时抛出DataCloneError的DOMException。DataCloneError 快速排查清单是否在对象里混入了函数或 Symbol最常见是否包含Proxy、Promise、WeakMap 等非克隆对象ArrayBuffer是否已 detachtransfer 列表是否有重复项或误放了SharedArrayBuffer是否在非 COOP/COEP 页面传递SharedArrayBuffer延伸阅读结构化克隆完整规范章节含全部算法步骤sourceHTML Standard 历次评审稿可观察该章节的演进review-drafts/项目常见问题集FAQ.md掌握结构化克隆的完整规则后你就能准确预判postMessage与structuredClone的行为边界什么值能安全穿越 realm什么资源该走 transfer 零拷贝通道什么会直接触发DataCloneError。【免费下载链接】htmlHTML Standard项目地址: https://gitcode.com/gh_mirrors/ht/html创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表