Structured Clone S0
中文标题:结构化克隆
- 阶段: Stage 0
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案定义了结构化克隆算法,用于在领域间复制ECMAScript对象的子集,允许主机扩展和可选资源转移。它引入了StructuredClone运算符,并规定了[[Transfer]]和[[OnSuccessfulTransfer]]等内部方法,以及用于失败的DataCloneError。该提案处于早期阶段,指出目前尚不可由用户插拔,并侧重于将现有语义移入ECMAScript本身。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
结构化克隆和转移
概述
结构化克隆算法定义了在代码领域之间复制ECMAScript对象的明确定义子集的语义。该算法可由宿主环境扩展以支持克隆宿主对象。
可选地,某些类型的对象可能支持“转移”操作,其效果是将与对象关联的某些资源的“所有权”转移到不同的代码领域。然后该对象在源代码领域中变得不可用。
本规范合并并涵盖了 http://www.whatwg.org/specs/web-apps/current-work/#dom-messageport-postmessage 和 http://www.whatwg.org/specs/web-apps/current-work/#structured-clone,因为它们确实属于一起。
HTML规范将更新以引用此_StructuredClone_算法的规范。
我们引入一个StructuredClone运算符。
可转移对象携带一个[[Transfer]]内部数据属性,其值要么是一个转移运算符,要么是“被中和的”,以及一个[[OnSuccessfulTransfer]]内部方法。
在ECMAScript之外定义的对象需要定义一个[[Clone]]内部方法,该方法返回对象的副本。
注意:第一次迭代不是用户可插拔的。这是关于将语义移入ECMAScript本身并加以确定。
StructuredClone(input, transferList, targetRealm)
运算符StructuredClone要么返回_input_的_结构化克隆_,要么抛出异常。对象_input_的_结构化克隆_是代码领域_targetRealm_中的一个对象。_transferList_是应该在克隆_input_期间被转移的对象列表。
- 让_memory_是一个源到目标对象映射的映射表。
- 对于_transferList_中的每个对象_transferable_:
- 如果_transferable_没有其值为运算符的[[Transfer]]内部数据属性, 则抛出DataCloneError异常。
- 让_transferResult_是调用_transferable_的内部方法[[Transfer]]的结果,参数为_targetRealm_。
- ReturnIfAbrupt( transferResult )
- 将从_transferable_到_transferResult_的映射添加到_memory_。
- 让_clone_是InternalStructuredClone( input, memory, targetRealm )的结果。
- ReturnIfAbrupt( clone )。
- 对于_transferList_中的每个对象_transferable_:
- 让_transferResult_是_memory_中从_transferable_映射的目标。
- 运行_transferable_的内部方法[[OnSuccessfulTransfer]](transferResult, targetRealm)。
- 返回_clone_。
InternalStructuredClone(input, memory, targetRealm)
运算符InternalStructuredClone要么返回代码领域_targetRealm_中_input_的_结构化克隆_,要么抛出异常。
- 如果_input_是_memory_中一对对象中的源对象,则返回该对对象中的目标对象。
- 如果_input_的[[Transfer]]是“被中和的”,则抛出DataCloneError异常。
- 如果_input_是原始值,则返回_input_。
- 让_deepClone_为false。
- 如果_input_具有[[BooleanData]]内部数据属性:
- 让_output_是_targetRealm_中的一个新Boolean对象,其[[BooleanData]]是_input_的[[BooleanData]]。
- 如果_input_具有[[NumberData]]内部数据属性:
- 让_output_是_targetRealm_中的一个新Number对象,其[[NumberData]]是_input_的[[NumberData]]。
- 如果_input_具有[[StringData]]内部数据属性:
- 让_output_是_targetRealm_中的一个新String对象,其[[StringData]]是_input_的[[StringData]]。
- 如果_input_具有[[DateValue]]内部数据属性:
- 让_output_是_targetRealm_中的一个新Date对象,其[[DateValue]]是_input_的[[DateValue]]。
- 如果_input_.[[RegExpMatcher]]存在:
- 让_output_是_targetRealm_中的一个新RegExp对象_r_,使得:
- _r_的[[RegExpMatcher]]是_input_的[[RegExpMatcher]]。
- _r_的[[OriginalSource]]是_input_的[[OriginalSource]]。
- _r_的[[OriginalFlags]]是_input_的[[OriginalFlags]]。
- 让_output_是_targetRealm_中的一个新RegExp对象_r_,使得:
- 如果_input_具有[[ArrayBufferData]]内部数据属性:
- 设置_output_为CopyArrayBufferToRealm(input, targetRealm)。
- 如果_input_具有[[ViewedArrayBuffer]]内部数据属性,那么:
- 让_arrayBuffer_是_input_的[[ViewedArrayBuffer]]内部数据属性的值。
- 让_arrayBufferClone_是InternalStructuredClone(arrayBuffer, memory, targetRealm)的结果
- ReturnIfAbrupt(arrayBufferClone)
- 如果_input_ instanceof 当前领域中的%DataView%内置对象:
- 让_output_是_targetRealm_中%DataView%内置对象的一个实例。
- 设置_output_的[[ViewedArrayBuffer]]为_arrayBufferClone_。
- 设置_output_的[[ByteOffset]]为_input_的[[ByteOffset]]。
- 设置_output_的[[ByteLength]]为_input_的[[ByteLength]]。
- 否则,如果_input_ instanceof %TypedArray% 对于当前代码领域中类型化数组的内置对象_TypedArray_之一:
- 让_output_是_targetRealm_中%TypedArray%内置对象的一个实例。
- 设置_output_的[[ByteOffset]]为_input_的[[ByteOffset]]。
- 设置_output_的[[ByteLength]]为_input_的[[ByteLength]]。
- 设置_output_的[[ArrayLength]]为_input_的[[ArrayLength]]。
- 如果_input_具有[[MapData]]内部数据属性,...
- 如果_input_具有[[SetData]]内部数据属性,...
- 如果_input_是一个异质Array对象:
- 让_output_是_targetRealm_中的一个新Array。
- 设置_output_.length为_input_.length。
- 设置_deepClone_为true。
- 否则,如果IsCallable( input),则抛出DataCloneError异常。
- 否则,如果_input_具有[[ErrorData]]属性,则抛出DataCloneError异常。
- 否则,如果_input_具有[[Clone]]内部方法:
- 设置_output_为_input_.[[Clone]]( targetRealm )的结果
- 否则,如果_input_是一个异质对象,则抛出DataCloneError异常。
- 否则:
- 让_object_是_targetRealm_中的一个新Object。
- 设置_deepClone_为true。
- 将从_input_(源对象)到_output_(目标对象)的映射添加到_memory_。
- 如果_deepClone_为true:
- 让_keys_是_input_.[[OwnPropertyKeys]]().
- 对于_keys_中的每个_key_:
- 如果_key_是原始String值,则设置_outputKey_为_key_。
- TODO:符号
- 让_sourceValue_是调用_input_的内部方法[[Get]]( key, input)的结果。
- ReturnIfAbrupt( sourceValue)。
- 让_clonedValue_是InternalStructuredClone( sourceValue, memory )。
- ReturnIfAbrupt( clonedValue)。
- 让_outputSet_是调用_output_的内部方法[[Set]]( outputKey, clonedValue, output)的结果。
- ReturnIfAbrupt( outputSet )
- 返回_output_。
ECMAScript异质对象上[[Transfer]](targetRealm)的定义。
定义_object_.[[Transfer]]( targetRealm ):
- 如果_object_具有[[ArrayBufferData]]内部数据属性,那么:
- 返回CopyArrayBufferToRealm(object, targetRealm)。
CopyArrayBufferToRealm(arrayBuffer, targetRealm)的定义
- 让_result_是_targetRealm_中的一个新ArrayBuffer arrayBuffer。
- 让_length_是_arrayBuffer_的[[ArrayBufferByteLength]]内部槽的值。
- 让_srcBlock_是_arrayBuffer_的[[ArrayBufferData]]内部槽的值。
- 让_setStatus_是SetArrayBufferData(result,length)的结果。
- ReturnIfAbrupt(setStatus)。
- 让_targetBlock_是_result_的[[ArrayBufferData]]内部槽的值。
- 执行CopyDataBlock(targetBlock, 0, srcBlock, 0, length)。
- 返回_result_。
ECMAScript异质对象上[[OnSuccessfulTransfer]]()的定义。
定义内部方法_object_.[[OnSuccessfulTransfer]]( transferResult, targetRealm ):
- 如果_object_具有[[ArrayBufferData]]内部数据属性,那么:
- 让_neuteringResult_是SetArrayBufferData( object, 0 )。
- ReturnIfAbrupt( neuteringResult )。
- 设置_object_的[[Transfer]]内部数据属性的值为“被中和的”。
DataCloneError错误对象
表示结构化克隆算法的失败。
{理由:通常,ECMAScript操作对类似的失败抛出RangeError,但我们需要保持DOM兼容性}