test('nthChild', () => {
const t = template('<div><span><b>nested</b></span><p></p></div>')
- const root = t()
- const span = nthChild(root, 0)
+ const root = t() as ParentNode
+ const span = nthChild(root, 0) as ParentNode
const b = nthChild(span, 0)
const p = nthChild(root, 1)
expect(span).toBe(root.firstChild)
test('next', () => {
const t = template('<div><span></span><b></b><p></p></div>')
- const root = t()
+ const root = t() as ParentNode
const span = child(root as ParentNode)
const b = next(span)
// optimize anchor cache lookup
;(Comment.prototype as any).$fe = undefined
;(Node.prototype as any).$idx = undefined
+ ;(Node.prototype as any).$children = undefined
isOptimized = true
}
enableHydrationNodeLookup()
import {
type ChildItem,
+ type InsertionParent,
getHydrationState,
- getTemplateChildren,
} from '../insertionState'
export function createElement(tagName: string): HTMLElement {
}
/* @__NO_SIDE_EFFECTS__ */
-export function _child(node: ParentNode): Node {
- const templateChildren = getTemplateChildren(node)
- return templateChildren ? templateChildren[0] : node.firstChild!
+export function _child(node: InsertionParent): Node {
+ const children = node.$children
+ return children ? children[0] : node.firstChild!
}
/**
* Hydration-specific version of `child`.
*/
/* @__NO_SIDE_EFFECTS__ */
-export function __child(node: ParentNode & { $lpn?: Node }): Node {
+export function __child(node: ParentNode): Node {
return __nthChild(node, 0)!
}
/* @__NO_SIDE_EFFECTS__ */
-export function _nthChild(node: Node, i: number): Node {
- const templateChildren = getTemplateChildren(node as ParentNode)
- return templateChildren ? templateChildren[i] : node.childNodes[i]
+export function _nthChild(node: InsertionParent, i: number): Node {
+ const children = node.$children
+ return children ? children[i] : node.childNodes[i]
}
/**
/* @__NO_SIDE_EFFECTS__ */
export function _next(node: Node): Node {
- const templateChildren = getTemplateChildren(node.parentNode!)
- return templateChildren
- ? templateChildren[(node as ChildItem).$idx + 1]
- : node.nextSibling!
+ const children = (node.parentNode! as InsertionParent).$children
+ return children ? children[(node as ChildItem).$idx + 1] : node.nextSibling!
}
/**
import { isHydrating } from './dom/hydration'
-export interface ChildItem extends ChildNode {
- $idx: number
-}
+export type ChildItem = ChildNode & { $idx: number }
+export type InsertionParent = ParentNode & { $children?: ChildItem[] }
+
type HydrationState = {
logicalChildren: ChildItem[]
prevDynamicCount: number
insertionAnchors: Map<Node, number> | null
appendAnchor: Node | null
}
-export let insertionParent: ParentNode | undefined
+export let insertionParent: InsertionParent | undefined
export let insertionAnchor: Node | 0 | undefined | null
-const templateChildrenCache = new WeakMap<ParentNode, ChildItem[]>()
-
const hydrationStateCache = new WeakMap<ParentNode, HydrationState>()
/**
function cacheTemplateChildren(
anchor: number | Node | null | undefined,
- parent: ParentNode,
+ parent: InsertionParent,
) {
// special handling append anchor value to null
insertionAnchor =
typeof anchor === 'number' && anchor > 0 ? null : (anchor as Node)
- if (!templateChildrenCache.has(parent)) {
+ if (!parent.$children) {
const nodes = parent.childNodes
const len = nodes.length
- const children = new Array(len)
+ const children = new Array(len) as ChildItem[]
for (let i = 0; i < len; i++) {
const node = nodes[i] as ChildItem
node.$idx = i
children[i] = node
}
- templateChildrenCache.set(parent, children)
+ parent.$children = children
}
}
insertionParent = insertionAnchor = undefined
}
-export function getTemplateChildren(
- parent: ParentNode,
-): ChildItem[] | undefined {
- return templateChildrenCache.get(parent)
-}
-
export function getHydrationState(
parent: ParentNode,
): HydrationState | undefined {