-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve place child #4172
Improve place child #4172
Conversation
📊 Tachometer Benchmark ResultsSummaryduration
usedJSHeapSize
Results02_replace1k
duration
usedJSHeapSize
run-warmup-0
run-warmup-1
run-warmup-2
run-warmup-3
run-warmup-4
run-final
03_update10th1k_x16
duration
usedJSHeapSize
07_create10k
duration
usedJSHeapSize
filter_list
duration
usedJSHeapSize
hydrate1k
duration
usedJSHeapSize
many_updates
duration
usedJSHeapSize
text_update
duration
usedJSHeapSize
todo
duration
usedJSHeapSize
|
Size Change: -66 B (0%) Total Size: 57.2 kB
ℹ️ View Unchanged
|
@@ -304,10 +310,8 @@ export function toChildArray(children, out) { | |||
} | |||
|
|||
function placeChild(parentDom, newDom, oldDom) { | |||
if (oldDom == null || oldDom.parentNode !== parentDom) { | |||
parentDom.insertBefore(newDom, null); | |||
} else if (newDom != oldDom || newDom.parentNode == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The newDom.parentNode == null
condition can also be removed cuz it would never happen, or if did would result in a DOMException.
For this condition to be hit, newDom
would have to be equal to oldDom
cuz of the check prior to this one. So in that scenario, if newDom.parentNode == null
, then oldDom.parentNode == null
. If oldDom is unmounted (since it has no parentNode), then calling parentDom.insertBefore(newDom, oldDom)
would error cuz oldDom is unmounted and you can't insert a node before another node that is unmounted.
For some additional context, the new Fragment tests I added are actually from our Suspense test suite. The suspense tests started failing, so I pulled out a simplified repro from those tests into its own test so it was easier to debug and see what's going on. |
@marvinhagemeister This PR removes usages of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yooo this is fantastic!!! From quickly trying it out it looks like it resolves the issue I was running into with Fresh 👍
Also good call on making Fragment tests out of some Suspense tests.
e3378e0
to
137da3c
Compare
NOTE: Might be easier to review by adding
?w=1
to the URLWhen unmounting DOM, we need to move
oldDom
/_nextDom
past the unmounted DOM so the diff can continue by comparing the next VNodes to DOM nodes that are mounted. We did this in the unmount loop but we missed a couple other places where this needs to happen as well.Let's say we have the following components:
Here, Conditional will switch from a group of DOM nodes and
null
. When doing this, diffChildren would hit our null placeholder code which does update oldDom past the unmounted DOM, but it doesn't update_nextDom
, soApp
wouldn't see this move and try to continue diffing from an unmounted DOM node.Further, even if we set
_nextDOM
, diffChildren on App wouldn't see it becauseConditional
returnednull
. Since Conditional returnednull
, it would returnnull
fornewDom
, meaning diffChildren on App would skip over all the code that was previously under aif (newDom)
check, including the code that reads_nextDom
. This PR also fixes that issue so even if a component returnsnull
, we update the skewed index, and will read_nextDom
if necessary.Also, the test "should efficiently unmount & mount components that conditionally return null with null first child" contains an additional edge case where Conditional switching to null, matches it's previous null first child. We need to ensure we detect we still need to move oldDom and update
_nextDom
.Previously we attempted to handle all of these cases by checking
oldDom.parentNode !== parentDom
inplaceChild
. However, in our entire test case, this was only occurred when oldDom was unmounted. So this update prevents unmounted oldDom from ever reachingplaceChild
removing the need for that condition entirely, dramatically simplifyingplaceChild
.