From fefea7ec51248d418316423d42f4eb6d5610df12 Mon Sep 17 00:00:00 2001 From: jdecroock Date: Tue, 18 Jun 2024 16:54:15 +0200 Subject: [PATCH 1/4] graciously handle array shuffling --- src/diff/children.js | 24 +++++++++++++++++++----- test/browser/render.test.js | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/diff/children.js b/src/diff/children.js index 912cc72d7c..eb86799efc 100644 --- a/src/diff/children.js +++ b/src/diff/children.js @@ -302,20 +302,34 @@ function constructNewChildrenArray(newParentVNode, renderResult, oldChildren) { childVNode._flags |= INSERT_VNODE; } } else if (matchingIndex !== skewedIndex) { - if (matchingIndex === skewedIndex + 1) { + if (matchingIndex == skewedIndex - 1) { + skew = matchingIndex - skewedIndex; + } else if (matchingIndex == skewedIndex + 1) { skew++; } else if (matchingIndex > skewedIndex) { + // Our matched DOM-node is further in the list of children than + // where it's at now. + + // When the remaining old children is bigger than the new-children + // minus our skewed index we know we are dealing with a shrinking list + // we have to increase our skew with the matchedIndex - the skewed index if (remainingOldChildren > newChildrenLength - skewedIndex) { skew += matchingIndex - skewedIndex; } else { + // If we have matched all the children just decrease the skew skew--; } } else if (matchingIndex < skewedIndex) { - if (matchingIndex == skewedIndex - 1) { - skew = matchingIndex - skewedIndex; + // Our matched DOM-node is further in the negative way in the list of children + // than where it's at now. + + // When the remaining old chiildren is less than the new children + // plus our skewed index we know we are dealing with a growing list + if (remainingOldChildren < newChildrenLength + skewedIndex) { + skew += matchingIndex + skewedIndex; + } else { + skew = 0; } - } else { - skew = 0; } // Move this VNode's DOM if the original index (matchingIndex) doesn't diff --git a/test/browser/render.test.js b/test/browser/render.test.js index f440962f70..5241cfaf29 100644 --- a/test/browser/render.test.js +++ b/test/browser/render.test.js @@ -474,17 +474,17 @@ describe('render()', () => { it('should support popover auto', () => { render(
, scratch); - expect(scratch.innerHTML).to.equal("
"); + expect(scratch.innerHTML).to.equal('
'); }); it('should support popover true boolean', () => { render(
, scratch); - expect(scratch.innerHTML).to.equal("
"); + expect(scratch.innerHTML).to.equal('
'); }); it('should support popover false boolean', () => { render(
, scratch); - expect(scratch.innerHTML).to.equal("
"); + expect(scratch.innerHTML).to.equal('
'); }); // Test for preactjs/preact#4340 @@ -1625,4 +1625,31 @@ describe('render()', () => { '
One
Six
Seven
' ); }); + + it('shuffle', function () { + const App = ({ items }) => ( +
+ {items.map(key => ( +
{key}
+ ))} +
+ ); + const a = ['0', '1', '2', '3', '4', '5', '6']; + const b = ['1', '3', '5', '2', '6', '4', '0']; + render(, scratch); + expect(scratch.innerHTML).to.equal( + `
${a.map(n => `
${n}
`).join('')}
` + ); + + render(, scratch); + + expect(scratch.innerHTML).to.equal( + `
${b.map(n => `
${n}
`).join('')}
` + ); + + render(, scratch); + expect(scratch.innerHTML).to.equal( + `
${a.map(n => `
${n}
`).join('')}
` + ); + }); }); From 6515610d8429c6574ce4acc6dc4dbcd5fb94201a Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Tue, 18 Jun 2024 17:51:53 +0200 Subject: [PATCH 2/4] Update test/browser/render.test.js --- test/browser/render.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/browser/render.test.js b/test/browser/render.test.js index 5241cfaf29..d779ca4edb 100644 --- a/test/browser/render.test.js +++ b/test/browser/render.test.js @@ -1626,7 +1626,7 @@ describe('render()', () => { ); }); - it('shuffle', function () { + it('handles shuffled child-ordering', function () { const App = ({ items }) => (
{items.map(key => ( From c189ade0f04bbd8af0980ab7b8ff395dd5cb6180 Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Tue, 18 Jun 2024 17:52:05 +0200 Subject: [PATCH 3/4] Update test/browser/render.test.js --- test/browser/render.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/browser/render.test.js b/test/browser/render.test.js index d779ca4edb..e6caf3adb9 100644 --- a/test/browser/render.test.js +++ b/test/browser/render.test.js @@ -1642,7 +1642,6 @@ describe('render()', () => { ); render(, scratch); - expect(scratch.innerHTML).to.equal( `
${b.map(n => `
${n}
`).join('')}
` ); From c739eae5c9711f0f4d00842a454cde1c9d7824e9 Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Wed, 19 Jun 2024 10:28:27 +0200 Subject: [PATCH 4/4] easier to read --- src/diff/children.js | 12 ++---------- test/browser/render.test.js | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/diff/children.js b/src/diff/children.js index eb86799efc..fb31e7b15c 100644 --- a/src/diff/children.js +++ b/src/diff/children.js @@ -320,16 +320,8 @@ function constructNewChildrenArray(newParentVNode, renderResult, oldChildren) { skew--; } } else if (matchingIndex < skewedIndex) { - // Our matched DOM-node is further in the negative way in the list of children - // than where it's at now. - - // When the remaining old chiildren is less than the new children - // plus our skewed index we know we are dealing with a growing list - if (remainingOldChildren < newChildrenLength + skewedIndex) { - skew += matchingIndex + skewedIndex; - } else { - skew = 0; - } + // When our new position is in front of our old position than we increase the skew + skew++; } // Move this VNode's DOM if the original index (matchingIndex) doesn't diff --git a/test/browser/render.test.js b/test/browser/render.test.js index e6caf3adb9..4755607c12 100644 --- a/test/browser/render.test.js +++ b/test/browser/render.test.js @@ -1636,7 +1636,9 @@ describe('render()', () => { ); const a = ['0', '1', '2', '3', '4', '5', '6']; const b = ['1', '3', '5', '2', '6', '4', '0']; + const c = ['11', '3', '1', '4', '6', '2', '5', '0', '9', '10']; render(, scratch); + clearLog(); expect(scratch.innerHTML).to.equal( `
${a.map(n => `
${n}
`).join('')}
` ); @@ -1645,10 +1647,46 @@ describe('render()', () => { expect(scratch.innerHTML).to.equal( `
${b.map(n => `
${n}
`).join('')}
` ); + expect(getLog()).to.deep.equal([ + '
0123456.insertBefore(
2,
6)', + '
0134526.appendChild(
4)', + '
0135264.appendChild(
0)' + ]); + clearLog(); + + render(, scratch); + expect(scratch.innerHTML).to.equal( + `
${c.map(n => `
${n}
`).join('')}
` + ); + expect(getLog()).to.deep.equal([ + '
.appendChild(#text)', + '
1352640.insertBefore(
11,
1)', + '
111352640.insertBefore(
1,
5)', + '
113152640.insertBefore(
6,
0)', + '
113152460.insertBefore(
2,
0)', + '
113154620.insertBefore(
5,
0)', + '
.appendChild(#text)', + '
113146250.appendChild(
9)', + '
.appendChild(#text)', + '
1131462509.appendChild(
10)' + ]); + clearLog(); render(, scratch); expect(scratch.innerHTML).to.equal( `
${a.map(n => `
${n}
`).join('')}
` ); + expect(getLog()).to.deep.equal([ + '
11.remove()', + '
9.remove()', + '
10.remove()', + '
3146250.appendChild(
1)', + '
3462501.appendChild(
2)', + '
3465012.appendChild(
3)', + '
4650123.appendChild(
4)', + '
6501234.appendChild(
5)', + '
6012345.appendChild(
6)' + ]); + clearLog(); }); });