-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Avoid leaking internal vnodes #3106
Conversation
We started calling `options.vnode()` for internal "text" VNodes and copied VNodes at some point, as best as I can tell it was unintentional. We don't officially support the Text VNode shape, and copied VNodes shouldn't be passed through `options.vnode` again because they've already been processed. This should be good for performance, though it likely won't show up in benchmarks because it primarily affects `preact/compat`.
📊 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
|
Size Change: -3 B (0%) Total Size: 42 kB
ℹ️ View Unchanged
|
@@ -78,7 +78,8 @@ export function createVNode(type, props, key, ref, original) { | |||
_original: original == null ? ++options._vnodeId : original | |||
}; | |||
|
|||
if (options.vnode != null) options.vnode(vnode); | |||
// Only invoke the vnode hook if this was *not* a direct copy: | |||
if (original == null && options.vnode != null) options.vnode(vnode); |
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.
My concern here becomes a bit prefresh-related, we'd break prefresh for ESM-runtimes like wmr, vite & snowpack. Consider the following VDOM-tree:
const Parent = () => <Child />
When we upate Child internally we assign a new type and call forceUpdate, now if we update Parent the reference will still contain a stale version of .type
in _children[0] which means that it'll render the previous version of said functional node.
We'd have to change from this to something that gets all parent vnodes and updates their own child.type
Had a bit more thought about this and this would generally completely break it I think as we can't track vnodes anymore, so if a few setStates occur we would not have the right references possibly
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.
When Parent is invoked, it will call h(Child) and run options.vnode on that VNode - wouldn't that keep prefresh working?
We started calling
options.vnode()
for internal "text" VNodes and copied VNodes at some point, as best as I can tell it was unintentional. We don't officially support the Text VNode shape, and copied VNodes shouldn't be passed throughoptions.vnode
again because they've already been processed.This should be good for performance, though it likely won't show up in benchmarks because it primarily affects
preact/compat
.