For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/structured-clone.md.
  • 简体中文
  • Structured Clone S0

    中文标题:结构化克隆

    提案概览
    提案速览

    该提案定义了结构化克隆算法,用于在领域间复制ECMAScript对象的子集,允许主机扩展和可选资源转移。它引入了StructuredClone运算符,并规定了[[Transfer]]和[[OnSuccessfulTransfer]]等内部方法,以及用于失败的DataCloneError。该提案处于早期阶段,指出目前尚不可由用户插拔,并侧重于将现有语义移入ECMAScript本身。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    结构化克隆和转移

    概述

    结构化克隆算法定义了在代码领域之间复制ECMAScript对象的明确定义子集的语义。该算法可由宿主环境扩展以支持克隆宿主对象。

    可选地,某些类型的对象可能支持“转移”操作,其效果是将与对象关联的某些资源的“所有权”转移到不同的代码领域。然后该对象在源代码领域中变得不可用。


    本规范合并并涵盖了 http://www.whatwg.org/specs/web-apps/current-work/#dom-messageport-postmessagehttp://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_期间被转移的对象列表。

    1. 让_memory_是一个源到目标对象映射的映射表。
    2. 对于_transferList_中的每个对象_transferable_:
      1. 如果_transferable_没有其值为运算符的[[Transfer]]内部数据属性, 则抛出DataCloneError异常。
      2. 让_transferResult_是调用_transferable_的内部方法[[Transfer]]的结果,参数为_targetRealm_。
      3. ReturnIfAbrupt( transferResult )
      4. 将从_transferable_到_transferResult_的映射添加到_memory_。
    3. 让_clone_是InternalStructuredClone( input, memory, targetRealm )的结果。
    4. ReturnIfAbrupt( clone )。
    5. 对于_transferList_中的每个对象_transferable_:
      1. 让_transferResult_是_memory_中从_transferable_映射的目标。
      2. 运行_transferable_的内部方法[[OnSuccessfulTransfer]](transferResult, targetRealm)。
    6. 返回_clone_。

    InternalStructuredClone(input, memory, targetRealm)

    运算符InternalStructuredClone要么返回代码领域_targetRealm_中_input_的_结构化克隆_,要么抛出异常。

    1. 如果_input_是_memory_中一对对象中的源对象,则返回该对对象中的目标对象。
    2. 如果_input_的[[Transfer]]是“被中和的”,则抛出DataCloneError异常。
    3. 如果_input_是原始值,则返回_input_。
    4. 让_deepClone_为false。
    5. 如果_input_具有[[BooleanData]]内部数据属性:
      • 让_output_是_targetRealm_中的一个新Boolean对象,其[[BooleanData]]是_input_的[[BooleanData]]。
    6. 如果_input_具有[[NumberData]]内部数据属性:
      • 让_output_是_targetRealm_中的一个新Number对象,其[[NumberData]]是_input_的[[NumberData]]。
    7. 如果_input_具有[[StringData]]内部数据属性:
      • 让_output_是_targetRealm_中的一个新String对象,其[[StringData]]是_input_的[[StringData]]。
    8. 如果_input_具有[[DateValue]]内部数据属性:
      • 让_output_是_targetRealm_中的一个新Date对象,其[[DateValue]]是_input_的[[DateValue]]。
    9. 如果_input_.[[RegExpMatcher]]存在:
      • 让_output_是_targetRealm_中的一个新RegExp对象_r_,使得:
        • _r_的[[RegExpMatcher]]是_input_的[[RegExpMatcher]]。
        • _r_的[[OriginalSource]]是_input_的[[OriginalSource]]。
        • _r_的[[OriginalFlags]]是_input_的[[OriginalFlags]]。
    10. 如果_input_具有[[ArrayBufferData]]内部数据属性:
      1. 设置_output_为CopyArrayBufferToRealm(input, targetRealm)。
    11. 如果_input_具有[[ViewedArrayBuffer]]内部数据属性,那么:
      1. 让_arrayBuffer_是_input_的[[ViewedArrayBuffer]]内部数据属性的值。
      2. 让_arrayBufferClone_是InternalStructuredClone(arrayBuffer, memory, targetRealm)的结果
      3. ReturnIfAbrupt(arrayBufferClone)
      4. 如果_input_ instanceof 当前领域中的%DataView%内置对象:
        1. 让_output_是_targetRealm_中%DataView%内置对象的一个实例。
        2. 设置_output_的[[ViewedArrayBuffer]]为_arrayBufferClone_。
        3. 设置_output_的[[ByteOffset]]为_input_的[[ByteOffset]]。
        4. 设置_output_的[[ByteLength]]为_input_的[[ByteLength]]。
      5. 否则,如果_input_ instanceof %TypedArray% 对于当前代码领域中类型化数组的内置对象_TypedArray_之一:
        1. 让_output_是_targetRealm_中%TypedArray%内置对象的一个实例。
        2. 设置_output_的[[ByteOffset]]为_input_的[[ByteOffset]]。
        3. 设置_output_的[[ByteLength]]为_input_的[[ByteLength]]。
        4. 设置_output_的[[ArrayLength]]为_input_的[[ArrayLength]]。
    12. 如果_input_具有[[MapData]]内部数据属性,...
    13. 如果_input_具有[[SetData]]内部数据属性,...
    14. 如果_input_是一个异质Array对象:
      1. 让_output_是_targetRealm_中的一个新Array。
      2. 设置_output_.length为_input_.length。
      3. 设置_deepClone_为true。
    15. 否则,如果IsCallable( input),则抛出DataCloneError异常。
    16. 否则,如果_input_具有[[ErrorData]]属性,则抛出DataCloneError异常。
    17. 否则,如果_input_具有[[Clone]]内部方法:
      1. 设置_output_为_input_.[[Clone]]( targetRealm )的结果
    18. 否则,如果_input_是一个异质对象,则抛出DataCloneError异常。
    19. 否则:
      1. 让_object_是_targetRealm_中的一个新Object。
      2. 设置_deepClone_为true。
    20. 将从_input_(源对象)到_output_(目标对象)的映射添加到_memory_。
    21. 如果_deepClone_为true:
      1. 让_keys_是_input_.[[OwnPropertyKeys]]().
      2. 对于_keys_中的每个_key_:
        1. 如果_key_是原始String值,则设置_outputKey_为_key_。
        2. TODO:符号
        3. 让_sourceValue_是调用_input_的内部方法[[Get]]( key, input)的结果。
        4. ReturnIfAbrupt( sourceValue)。
        5. 让_clonedValue_是InternalStructuredClone( sourceValue, memory )。
        6. ReturnIfAbrupt( clonedValue)。
        7. 让_outputSet_是调用_output_的内部方法[[Set]]( outputKey, clonedValue, output)的结果。
        8. ReturnIfAbrupt( outputSet )
    22. 返回_output_。

    ECMAScript异质对象上[[Transfer]](targetRealm)的定义。

    定义_object_.[[Transfer]]( targetRealm ):

    1. 如果_object_具有[[ArrayBufferData]]内部数据属性,那么:
    2. 返回CopyArrayBufferToRealm(object, targetRealm)。

    CopyArrayBufferToRealm(arrayBuffer, targetRealm)的定义

    1. 让_result_是_targetRealm_中的一个新ArrayBuffer arrayBuffer
    2. 让_length_是_arrayBuffer_的[[ArrayBufferByteLength]]内部槽的值。
    3. 让_srcBlock_是_arrayBuffer_的[[ArrayBufferData]]内部槽的值。
    4. 让_setStatus_是SetArrayBufferData(result,length)的结果。
    5. ReturnIfAbrupt(setStatus)。
    6. 让_targetBlock_是_result_的[[ArrayBufferData]]内部槽的值。
    7. 执行CopyDataBlock(targetBlock, 0, srcBlock, 0, length)。
    8. 返回_result_。

    ECMAScript异质对象上[[OnSuccessfulTransfer]]()的定义。

    定义内部方法_object_.[[OnSuccessfulTransfer]]( transferResult, targetRealm ):

    1. 如果_object_具有[[ArrayBufferData]]内部数据属性,那么:
      1. 让_neuteringResult_是SetArrayBufferData( object, 0 )。
      2. ReturnIfAbrupt( neuteringResult )。
      3. 设置_object_的[[Transfer]]内部数据属性的值为“被中和的”。

    DataCloneError错误对象

    表示结构化克隆算法的失败。

    {理由:通常,ECMAScript操作对类似的失败抛出RangeError,但我们需要保持DOM兼容性}