@@ -373,6 +373,7 @@ var Idiomorph = (function () {
373373 /**
374374 * Scans forward from the startPoint to the endPoint looking for a match
375375 * for the node. It looks for an id set match first, then a soft match.
376+ * We abort softmatching if we find two future soft matches, to reduce churn.
376377 * @param {Node } node
377378 * @param {MorphContext } ctx
378379 * @param {Node | null } startPoint
@@ -381,6 +382,8 @@ var Idiomorph = (function () {
381382 */
382383 function findBestMatch ( ctx , node , startPoint , endPoint ) {
383384 let softMatch = null ;
385+ let nextSibling = node . nextSibling ;
386+ let siblingSoftMatchCount = 0 ;
384387
385388 let cursor = startPoint ;
386389 while ( cursor && cursor != endPoint ) {
@@ -391,23 +394,36 @@ var Idiomorph = (function () {
391394 }
392395
393396 // we haven't yet saved a soft match fallback
394- if ( ! softMatch ) {
397+ if ( softMatch === null ) {
395398 // the current soft match will hard match something else in the future, leave it
396399 if ( ! ctx . idMap . has ( cursor ) ) {
397- // optimization: if node can't id set match, we can just return the soft match immediately
398- if ( ! ctx . idMap . has ( node ) ) {
399- return cursor ;
400- } else {
401- // save this as the fallback if we get through the loop without finding a hard match
402- softMatch = cursor ;
403- }
400+ // save this as the fallback if we get through the loop without finding a hard match
401+ softMatch = cursor ;
404402 }
405403 }
406404 }
405+ if (
406+ softMatch === null &&
407+ nextSibling &&
408+ isSoftMatch ( cursor , nextSibling )
409+ ) {
410+ // The next new node has a soft match with this node, so
411+ // increment the count of future soft matches
412+ siblingSoftMatchCount ++ ;
413+ nextSibling = nextSibling . nextSibling ;
414+
415+ // If there are two future soft matches, block soft matching for this node to allow
416+ // future siblings to soft match. This is to reduce churn in the DOM when an element
417+ // is prepended.
418+ if ( siblingSoftMatchCount >= 2 ) {
419+ softMatch = undefined ;
420+ }
421+ }
422+
407423 cursor = cursor . nextSibling ;
408424 }
409425
410- return softMatch ;
426+ return softMatch || null ;
411427 }
412428
413429 /**
0 commit comments