-
Notifications
You must be signed in to change notification settings - Fork 382
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
fix(engine-core): add abstraction for moving vfragments #3405
Conversation
Downstream repo at salesforce-experience-platform-emu/lds-lightning-platform currently has a broken build. |
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.
Requested to add or verify we have tests for a specific use case.
packages/@lwc/integration-karma/test/rendering/issue-3377/index.spec.js
Outdated
Show resolved
Hide resolved
packages/@lwc/integration-karma/test/rendering/issue-3396/x/test/test.html
Show resolved
Hide resolved
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.
It seems strange to me that the diffing algo would have knowledge of fragment start and end text positions. My understanding is that the goal of fragments was to insert the text nodes and just let the diffing algo act accordingly.
Looking at how Vue does it, they seem to insert both the leading and trailing text nodes and then patch the content in before the trailing one. Can we use a similar technique?
@nolanlawson Patching the content in before the trailing anchor already works fine, and we're doing it the way you're suggesting (the way Vue does it). The problem here is not with patching/mounting the internal content of the fragment itself, it's with how the diffing algo deals with the VFragment node along with its sibling nodes. It's the difference between Thanks for linking how Vue does vdom. From what I can see, Vue's diffing algo actually does have knowledge of fragment start and end node positions:
This hits a good middle ground and I agree we should use a similar technique: fragment-specific start/end nodes are abstracted away into the base VNode definition itself (vnode.elm always leading, vnode.anchor for fragment tails, helper function to grab the next node element) and then the diffing algo just does its thing with minimal fragment-specific logic. I think we're being misguided trying to stick to a cc - @ekashida What do either of you think? |
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.
@jye-sf Nice research! Yeah that makes sense to me. If VFragment can't just be "any old VNode," then let's go whole-hog and keep a reference to its start and end anchors explicitly. |
packages/@lwc/integration-karma/test/rendering/sequential-reordering/index.spec.js
Show resolved
Hide resolved
packages/@lwc/integration-karma/test/rendering/sequential-reordering/index.spec.js
Show resolved
Hide resolved
That should be ‘Node | VFragment’
…On Mon, Mar 27, 2023 at 12:21 Nolan Lawson ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In ***@***.***/engine-core/src/framework/rendering.ts
<#3405 (comment)>:
> + if (isVFragment(elmToMove)) {
+ insertFragment(elmToMove, parent, oldStartVnode.elm!, renderer);
+ } else {
+ insertNode(elmToMove.elm!, parent, oldStartVnode.elm!, renderer);
+ }
I took a stab at it, and I think it's possible with just an isVFragment()
check? Unless I'm missing the issue with this approach:
0a18c80
<0a18c80>
—
Reply to this email directly, view it on GitHub
<#3405 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AABAW6O6XGCQRBUXOLIMXI3W6HSCVANCNFSM6AAAAAAWBJALDA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
I tested 0a18c80, and it compiles with TypeScript and passes the Karma tests. It looks like |
@nolanlawson Ah, I see what you mean. |
906fb87
to
3160c74
Compare
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.
One small nitpick, otherwise LGTM!
@jye-sf another review please! |
// trailing anchor as the argument to nextSibling(): | ||
// [..., [leading, ...content, trailing], nextSibling, ...] | ||
let anchor: Node | null; | ||
if (isVFragment(oldEndVnode)) { |
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.
Minor nit: we could save a check here if trailing
was on VNode rather than Vfragment because we can do
anchor = renderer.nextSibling(oldEndVnode.trailing ? oldEndVnode.trailing.elm : oldEndVnode.elm)
but I don't think we need to hold up this PR for that change. We can consider that when refactoring.
Details
Implements an abstraction for moving vfragment-based nodes around and fixes both reported issues around insertion when the vfragment-based nodes are the reference node. Note that we already had logic for mounting/patching/removing.
Fixes #3396
Fixes #3377
Does this pull request introduce a breaking change?
No
Does this pull request introduce an observable change?
Yes
GUS work item
W-12630370