Skip to content

Begin diff with next DOM sibling in forceUpdate#1689

Merged
marvinhagemeister merged 13 commits into
masterfrom
forceupdate-diffChildren3
Jun 10, 2019
Merged

Begin diff with next DOM sibling in forceUpdate#1689
marvinhagemeister merged 13 commits into
masterfrom
forceupdate-diffChildren3

Conversation

@andrewiggins

Copy link
Copy Markdown
Member

When a Component isn't currently associated with a DOM node, we need to begin the diff from it's next DOM sibling so that if this render of the Component adds DOM, it will be correctly inserted into it's parent (instead of always appended like before).

I stole this idea from @marvinhagemeister's #1605, but re-implemented it so it no longer needs a _sibling pointer which should make this a little smaller.

I tried exploring other ideas (like two loops in diffChildren) but they didn't pan out like I had hoped (would be just as big a change and couldn't get Fragments working after a while 😞). I figured it would be better to just get something working in master first.

With #1658, I think this solution works out pretty elegantly anyway (diffChildren is still the only place where DOM is added or removed).

Total change: +75 B 😬

NOTE: depends on #1688 (+5 B) so don't merge until after #1688 is in master. I'll rebase this PR on master once that happens.

Comment thread test/browser/fragments.test.js

/** @jsx h */

describe('getDomSibling', () => {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marvinhagemeister FYI, I copied your tests from #1605 and added a bunch. I couldn't get the implementation of getDomSibling in #1605 to pass all the new tests which is why I re-built it from scratch.

@marvinhagemeister marvinhagemeister Jun 8, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad you did that as my version was a bit hacked together to get a good sense of the problem space. I didn't have time to clean it up. The variant in this PR is much cleaner and the childIndex handling is ace 💯

it('should find sibling with nested placeholder', () => {
render((
<div key="0">
<Fragment key="0.0">

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added keys to some of the tests here just cuz they made it easier to debug getDomSibling with a couple of well-placed console.log(vnode.key)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh that's a very neat way to debug ordering. I'll use that on my next PR 👍

Comment thread src/component.js
* @param {import('./internal').VNode} vnode
* @param {number | null} [childIndex]
*/
export function getDomSibling(vnode, childIndex) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forget - does JS support optimized tail recursion? I think this function could be re-written to be tail-recursive if it isn't already (I forget what exactly qualifies as tail recursive).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

V8 had it for a while but not anymore, tracking bug: https://bugs.chromium.org/p/v8/issues/detail?id=4698

@JoviDeCroock JoviDeCroock left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Andre, super nice work! I think this solves the following issue as well: https://github.com/preactjs/preact/pull/1687/files#diff-d5abae78db533876550fd82502fe7000R186

Comment thread src/component.js
* @param {import('./internal').VNode} vnode
* @param {number | null} [childIndex]
*/
export function getDomSibling(vnode, childIndex) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

V8 had it for a while but not anymore, tracking bug: https://bugs.chromium.org/p/v8/issues/detail?id=4698

@marvinhagemeister marvinhagemeister left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wohoo! This PR makes me really excited!! It is way better than my initial draft in #1605 👍 👍 Especially the getDomSibling function is a thing of beauty 🙌

Hopefully we've caught all remaining issues with Fragment ordering with this PR. The approach is a lot more sound compared to what's in master. Really amazing things happening here 💯 🍀

@andrewiggins andrewiggins force-pushed the forceupdate-diffChildren3 branch from 97b8726 to ab51a14 Compare June 9, 2019 10:28
@andrewiggins andrewiggins changed the base branch from parent-pointer to master June 9, 2019 10:29
@andrewiggins andrewiggins force-pushed the forceupdate-diffChildren3 branch from 9dcbd6d to cb4e6e7 Compare June 10, 2019 01:18
@andrewiggins andrewiggins marked this pull request as ready for review June 10, 2019 01:26
@coveralls

coveralls commented Jun 10, 2019

Copy link
Copy Markdown

Coverage Status

Coverage increased (+1.3%) to 99.778% when pulling 3688977 on forceupdate-diffChildren3 into c37cfee on master.

@marvinhagemeister marvinhagemeister left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is so good 🙌💯 Let's do it!

@marvinhagemeister marvinhagemeister merged commit 93c626e into master Jun 10, 2019
@JoviDeCroock JoviDeCroock deleted the forceupdate-diffChildren3 branch June 10, 2019 08:34
@JoviDeCroock JoviDeCroock restored the forceupdate-diffChildren3 branch June 10, 2019 08:34
@andrewiggins andrewiggins deleted the forceupdate-diffChildren3 branch June 10, 2019 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants