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');
}