From 57a034ecaf7e05a3331efc53b9d956b26e5727cf Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Fri, 2 Sep 2022 16:33:08 -0400 Subject: [PATCH 1/4] Always clone VNodes before using them --- src/diff/children.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/diff/children.js b/src/diff/children.js index e55fc97017..71b1872822 100644 --- a/src/diff/children.js +++ b/src/diff/children.js @@ -48,7 +48,7 @@ export function diffChildren( childVNode = renderResult[i]; if (childVNode == null || typeof childVNode == 'boolean') { - childVNode = newParentVNode._children[i] = null; + childVNode = null; } // If this newVNode is being reused (e.g.
{reuse}{reuse}
) in the same diff, // or we are rendering a component (e.g. setState) copy the oldVNodes so it can have @@ -59,7 +59,7 @@ export function diffChildren( // eslint-disable-next-line valid-typeof typeof childVNode == 'bigint' ) { - childVNode = newParentVNode._children[i] = createVNode( + childVNode = createVNode( null, childVNode, null, @@ -67,28 +67,28 @@ export function diffChildren( childVNode ); } else if (Array.isArray(childVNode)) { - childVNode = newParentVNode._children[i] = createVNode( + childVNode = createVNode( Fragment, { children: childVNode }, null, null, null ); - } else if (childVNode._depth > 0) { - // VNode is already in use, clone it. This can happen in the following - // scenario: + } else { + // Always clone VNodes to ensure our own copy within the tree. + // This avoids clobbering VNodes used in multiple places: // const reuse =
//
{reuse}{reuse}
- childVNode = newParentVNode._children[i] = createVNode( + childVNode = createVNode( childVNode.type, childVNode.props, childVNode.key, childVNode.ref ? childVNode.ref : null, childVNode._original ); - } else { - childVNode = newParentVNode._children[i] = childVNode; } + + newParentVNode._children[i] = childVNode; // Terser removes the `continue` here and wraps the loop body // in a `if (childVNode) { ... } condition From dfa941d446888e127fec299a582413598934a5dc Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Fri, 2 Sep 2022 16:53:11 -0400 Subject: [PATCH 2/4] don't add internal props to public vnodes --- src/create-element.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/create-element.js b/src/create-element.js index 892389054a..f70d2afe71 100644 --- a/src/create-element.js +++ b/src/create-element.js @@ -37,7 +37,7 @@ export function createElement(type, props, children) { } } - return createVNode(type, normalizedProps, key, ref, null); + return { type, props: normalizedProps, key, ref, constructor: undefined }; } /** From 773c34123831cb664981e5c23bf31f69449cd610 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Fri, 2 Sep 2022 16:54:15 -0400 Subject: [PATCH 3/4] don't add internal props to public vnodes --- jsx-runtime/src/index.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/jsx-runtime/src/index.js b/jsx-runtime/src/index.js index 260d68703e..a3b5278c89 100644 --- a/jsx-runtime/src/index.js +++ b/jsx-runtime/src/index.js @@ -43,17 +43,9 @@ function createVNode(type, props, key, __self, __source) { props: normalizedProps, key, ref, - _children: null, - _parent: null, - _depth: 0, - _dom: null, - _nextDom: undefined, - _component: null, - _hydrating: null, - constructor: undefined, - _original: --vnodeId, __source, - __self + __self, + constructor: undefined }; // If a Component VNode, check for and apply defaultProps. From daca89de5cba58ce11acafba418d1fde3fed81d0 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Fri, 2 Sep 2022 16:55:22 -0400 Subject: [PATCH 4/4] invoke vnode hook in createElement --- src/create-element.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/create-element.js b/src/create-element.js index f70d2afe71..9088e737b1 100644 --- a/src/create-element.js +++ b/src/create-element.js @@ -37,7 +37,15 @@ export function createElement(type, props, children) { } } - return { type, props: normalizedProps, key, ref, constructor: undefined }; + const vnode = { + type, + props: normalizedProps, + key, + ref, + constructor: undefined + }; + if (options.vnode) options.vnode(vnode); + return vnode; } /** @@ -75,9 +83,6 @@ export function createVNode(type, props, key, ref, original) { _original: original == null ? ++vnodeId : original }; - // Only invoke the vnode hook if this was *not* a direct copy: - if (original == null && options.vnode != null) options.vnode(vnode); - return vnode; }