# All files / lib/tasks sync-trees.js

94.44% Statements 68/72
66.66% Branches 8/12
100% Functions 1/1
94.44% Lines 68/72

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    732x
    2x
    2x
    2x
    2x
    2x
    2x
    227x
    227x
    227x
    227x
    227x
    225x

    225x
    225x

    225x
    225x
    225x
    225x
    225x
    225x
    225x
    227x
    227x
    5x
    227x
    3x
    3x
    3x
    3x
    1x
    1x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    1x
    1x
    3x
    227x
    227x
    227x
    227x
    227x
    227x
    227x
    227x
    227x
    227x
    227x
    227x
     import syncTree from '../tree/sync';
    import createNode from '../node/create';
    import { StateCache, NODE_TYPE, PATCH_TYPE, EMPTY, Mount } from '../util/types';
    import process from '../util/process';
    import Transaction from '../transaction';

    export default function syncTrees(/** @type {Transaction} */ transaction) {
      const { state, state: { measure }, oldTree, newTree, mount } = transaction;

      measure('sync trees');

      if (process.env.NODE_ENV !== 'production') {
        if (!oldTree) {
          throw new Error('Missing old tree during synchronization');
        }

        if (!newTree) {
          throw new Error('Missing new tree during synchronization');
        }
      }

      // Do a global replace of the element, unable to do this at a lower level.
      // Ignore this for document fragments, they don't appear in the DOM and we
      // treat them as transparent containers.
      if (
        oldTree &&
        newTree &&
        oldTree.nodeName !== newTree.nodeName &&
        newTree.nodeType !== NODE_TYPE.FRAGMENT
      ) {
        // If there is no `parentNode` for the replace operation, we will need to
        // throw an error and prevent the `StateCache` from being updated.
        if (process.env.NODE_ENV !== 'production') {
          if (!/** @type {HTMLElement} */ (mount).parentNode) {
            throw new Error('Unable to replace top level node without a parent');
          }
        }

        // Replace the top level elements.
        transaction.patches = [
          PATCH_TYPE.REPLACE_CHILD,
          newTree,
          oldTree,
        ];

        // Clean up the existing old tree, and mount the new tree.
        transaction.oldTree = state.oldTree = newTree;

        const newNode = createNode(newTree);

        // Update the StateCache since we are changing the top level element.
        StateCache.delete(mount);
        StateCache.set(/** @type {Mount} */ (newNode), state);

        transaction.mount = /** @type {HTMLElement} */ (newNode);

        if (newTree.nodeName === 'script') {
          state.scriptsToExecute.set(newTree, newTree.attributes.type || EMPTY.STR);
        }
      }
      // Synchronize the top level elements.
      else {
        transaction.patches = syncTree(
          oldTree || null,
          newTree || null,
          [],
          state,
        );
      }

      measure('sync trees');
    }