diff --git a/src/jsx/dom/jsx-dev-runtime.ts b/src/jsx/dom/jsx-dev-runtime.ts index a4c439b16..d7a6ff29e 100644 --- a/src/jsx/dom/jsx-dev-runtime.ts +++ b/src/jsx/dom/jsx-dev-runtime.ts @@ -1,31 +1,16 @@ import type { Props, JSXNode } from '../base' import { normalizeIntrinsicElementProps } from '../utils' - -const JSXNodeCompatPrototype = { - type: { - get(this: { tag: string | Function }): string | Function { - return this.tag - }, - }, - ref: { - get(this: { props?: { ref: unknown } }): unknown { - return this.props?.ref - }, - }, -} +import { newJSXNode } from './utils' export const jsxDEV = (tag: string | Function, props: Props, key?: string): JSXNode => { if (typeof tag === 'string') { normalizeIntrinsicElementProps(props) } - return Object.defineProperties( - { - tag, - props, - key, - }, - JSXNodeCompatPrototype - ) as JSXNode + return newJSXNode({ + tag, + props, + key, + }) } export const Fragment = (props: Record): JSXNode => jsxDEV('', props, undefined) diff --git a/src/jsx/dom/render.ts b/src/jsx/dom/render.ts index 083f755d7..ba3fffe15 100644 --- a/src/jsx/dom/render.ts +++ b/src/jsx/dom/render.ts @@ -8,6 +8,7 @@ import type { EffectData } from '../hooks' import { STASH_EFFECT } from '../hooks' import { styleObjectForEach } from '../utils' import { createContext } from './context' // import dom-specific versions +import { newJSXNode } from './utils' const HONO_PORTAL_ELEMENT = '_hp' @@ -391,7 +392,7 @@ export const build = ( } const oldVChildren: Node[] = node.vC ? [...node.vC] : [] const vChildren: Node[] = [] - const vChildrenToRemove: Node[] = [] + node.vR = [] let prevNode: Node | undefined try { children.flat().forEach((c: Child) => { @@ -432,7 +433,7 @@ export const build = ( } child = oldChild } else if (oldChild.tag !== child.tag) { - vChildrenToRemove.push(oldChild) + node.vR.push(oldChild) } else { oldChild.pP = oldChild.props oldChild.props = child.props @@ -455,8 +456,7 @@ export const build = ( } }) node.vC = vChildren - vChildrenToRemove.push(...oldVChildren) - node.vR = vChildrenToRemove + node.vR.push(...oldVChildren) } catch (e) { if (errorHandler) { const fallbackUpdateFn = () => @@ -494,10 +494,14 @@ const buildNode = (node: Child): Node | undefined => { } else if (typeof node === 'string' || typeof node === 'number') { return { t: node.toString(), d: true } as NodeString } else { + if ('vR' in node) { + node = newJSXNode({ + tag: (node as NodeObject).tag, + props: (node as NodeObject).props, + key: (node as NodeObject).key, + }) + } if (typeof (node as JSXNode).tag === 'function') { - if ((node as NodeObject)[DOM_STASH]) { - node = { ...node } as NodeObject - } ;(node as NodeObject)[DOM_STASH] = [0, []] } else { const ns = nameSpaceMap[(node as JSXNode).tag as string] diff --git a/src/jsx/dom/utils.ts b/src/jsx/dom/utils.ts index fef0c3c05..77c6b5676 100644 --- a/src/jsx/dom/utils.ts +++ b/src/jsx/dom/utils.ts @@ -1,3 +1,4 @@ +import type { Props, JSXNode } from '../base' import { DOM_INTERNAL_TAG } from '../constants' export const setInternalTagFlag = (fn: Function): Function => { @@ -5,3 +6,19 @@ export const setInternalTagFlag = (fn: Function): Function => { ;(fn as any)[DOM_INTERNAL_TAG] = true return fn } + +const JSXNodeCompatPrototype = { + type: { + get(this: { tag: string | Function }): string | Function { + return this.tag + }, + }, + ref: { + get(this: { props?: { ref: unknown } }): unknown { + return this.props?.ref + }, + }, +} + +export const newJSXNode = (obj: { tag: string | Function; props?: Props; key?: string }): JSXNode => + Object.defineProperties(obj, JSXNodeCompatPrototype) as JSXNode