liveBook · Manning

Pipeline

As explained in Build a Frontend Web Framework (From Scratch)

An operation sequence is an ordered collection of array-editing operations that describes a transformation from one array state to another.

When a virtual node’s children change, the DOM needs a plan for turning the old children array into the new one. An operation sequence is that plan: ordered add, remove, move, and noop records. Applying them in order produces the new arrangement. section 7.6 section 7.6.4

Why order and indices matter

To turn [A, B, C] into [C, B, D], remove A at index 0, move C from its *current* index 1 to index 0, then add D at index 2. After the removal, C is no longer at its original index 2. Other sequences could reach the same result, but avoiding unnecessary DOM changes is useful. section 7.6

Build the sequence by walking the new array from left to right while editing a copy of the old array. At each index, make the copied array match the new one there; earlier positions then stay settled. Keep a parallel record of each surviving item’s original index, because a move or noop may need both its current position and its starting position. section 7.6.2 section 7.6.4

At each index, choose one action:

  • Remove the current old item if it appears nowhere in the new array; check the same index again. section 7.6.2
  • Record a noop if the current items match; otherwise add the new item if it cannot be found later in the working array. section 7.6.2
  • Otherwise move the matching item forward to this index. After the walk, remove any old items left beyond the new array’s length. section 7.6.2
Listing 7.18 Removing outstanding items (utils/arrays.js)
export function arraysDiffSequence(
  oldArray,
  newArray,
  equalsFn = (a, b) => a === b
) {
  const sequence = []
  const array = new ArrayWithOriginalIndices(oldArray, equalsFn)

  for (let index = 0; index < newArray.length; index++) {
    if (array.isRemoval(index, newArray)) {
      sequence.push(array.removeItem(index))
      index--
      continue
    }

    if (array.isNoop(index, newArray)) {
      sequence.push(array.noopItem(index))
      continue
    }

    const item = newArray[index]

    if (array.isAddition(item, index)) {
      sequence.push(array.addItem(item, index))
      continue
    }

    sequence.push(array.moveItem(item, index))
  }

  sequence.push(...array.removeItemsAfter(newArray.length))

  return sequence
}

The JavaScript implementation collects each operation as it updates the working array, then appends removals for leftover items. A supplied equality function can replace the default strict comparison. section 7.6.4

To check a sequence, apply its operations to the old array and compare the result with the new array. Try the duplicate-containing input ['A', 'A', 'B', 'C'] and target ['C', 'K', 'A', 'B']: it tests more than a simple swap. section 7.6.4

How Build a Frontend Web Framework (From Scratch) covers it

How deep it goes
Works through a left-to-right algorithm and incremental JavaScript implementation, including current and original indices; leaves applying sequences as an exercise.
Examples
Uses [A, B, C] becoming [C, B, D] and a duplicate-containing array exercise to test generated operations.
What it assumes
Assumes basic JavaScript arrays, functions, and loops while explicitly building the original-index tracking helper.
What you can do after
Build it from scratch with arraysDiffSequence(), then verify its operations by applying them to an old array.
How it connects
Connects array diffing with virtual DOM reconciliation, child nodes, and DOM patching.

Also explained in

Compare how 48 books explain pipeline →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Build a Frontend Web Framework (From Scratch). The section links point to the parts of the book it draws on.