'use strict'; /*! (c) 2018 Andrea Giammarchi (ISC) */ const { eqeq, identity, indexOf, isReversed, next, append, remove, smartDiff } = require('./utils.js'); const domdiff = ( parentNode, // where changes happen currentNodes, // Array of current items/nodes futureNodes, // Array of future items/nodes options // optional object with one of the following properties // before: domNode // compare(generic, generic) => true if same generic // node(generic) => Node ) => { if (!options) options = {}; const compare = options.compare || eqeq; const get = options.node || identity; const before = options.before == null ? null : get(options.before, 0); const currentLength = currentNodes.length; let currentEnd = currentLength; let currentStart = 0; let futureEnd = futureNodes.length; let futureStart = 0; // common prefix while ( currentStart < currentEnd && futureStart < futureEnd && compare(currentNodes[currentStart], futureNodes[futureStart]) ) { currentStart++; futureStart++; } // common suffix while ( currentStart < currentEnd && futureStart < futureEnd && compare(currentNodes[currentEnd - 1], futureNodes[futureEnd - 1]) ) { currentEnd--; futureEnd--; } const currentSame = currentStart === currentEnd; const futureSame = futureStart === futureEnd; // same list if (currentSame && futureSame) return futureNodes; // only stuff to add if (currentSame && futureStart < futureEnd) { append( get, parentNode, futureNodes, futureStart, futureEnd, next(get, currentNodes, currentStart, currentLength, before) ); return futureNodes; } // only stuff to remove if (futureSame && currentStart < currentEnd) { remove( get, parentNode, currentNodes, currentStart, currentEnd ); return futureNodes; } const currentChanges = currentEnd - currentStart; const futureChanges = futureEnd - futureStart; let i = -1; // 2 simple indels: the shortest sequence is a subsequence of the longest if (currentChanges < futureChanges) { i = indexOf( futureNodes, futureStart, futureEnd, currentNodes, currentStart, currentEnd, compare ); // inner diff if (-1 < i) { append( get, parentNode, futureNodes, futureStart, i, get(currentNodes[currentStart], 0) ); append( get, parentNode, futureNodes, i + currentChanges, futureEnd, next(get, currentNodes, currentEnd, currentLength, before) ); return futureNodes; } } /* istanbul ignore else */ else if (futureChanges < currentChanges) { i = indexOf( currentNodes, currentStart, currentEnd, futureNodes, futureStart, futureEnd, compare ); // outer diff if (-1 < i) { remove( get, parentNode, currentNodes, currentStart, i ); remove( get, parentNode, currentNodes, i + futureChanges, currentEnd ); return futureNodes; } } // common case with one replacement for many nodes // or many nodes replaced for a single one /* istanbul ignore else */ if ((currentChanges < 2 || futureChanges < 2)) { append( get, parentNode, futureNodes, futureStart, futureEnd, get(currentNodes[currentStart], 0) ); remove( get, parentNode, currentNodes, currentStart, currentEnd ); return futureNodes; } // the half match diff part has been skipped in petit-dom // https://github.com/yelouafi/petit-dom/blob/bd6f5c919b5ae5297be01612c524c40be45f14a7/src/vdom.js#L391-L397 // accordingly, I think it's safe to skip in here too // if one day it'll come out like the speediest thing ever to do // then I might add it in here too // Extra: before going too fancy, what about reversed lists ? // This should bail out pretty quickly if that's not the case. if ( currentChanges === futureChanges && isReversed( futureNodes, futureEnd, currentNodes, currentStart, currentEnd, compare ) ) { append( get, parentNode, futureNodes, futureStart, futureEnd, next(get, currentNodes, currentEnd, currentLength, before) ); return futureNodes; } // last resort through a smart diff smartDiff( get, parentNode, futureNodes, futureStart, futureEnd, futureChanges, currentNodes, currentStart, currentEnd, currentChanges, currentLength, compare, before ); return futureNodes; }; Object.defineProperty(exports, '__esModule', {value: true}).default = domdiff;