diff --git a/TODO.md b/TODO.md deleted file mode 100644 index b358efbbc9..0000000000 --- a/TODO.md +++ /dev/null @@ -1,5 +0,0 @@ -- https://github.com/preactjs/preact/pull/4358 -- https://github.com/preactjs/preact/pull/4361 -- Remove deprecated lifecycle methods -- Put createPortal into core -- Implement hydration 2.0 diff --git a/src/diff/index.js b/src/diff/index.js index e6b22b810d..f82dd392f0 100644 --- a/src/diff/index.js +++ b/src/diff/index.js @@ -248,7 +248,7 @@ export function diff( c.state = c._nextState; if (c.getChildContext != null) { - globalContext = assign({}, globalContext, c.getChildContext()); + globalContext = assign(assign({}, globalContext), c.getChildContext()); } if (isClassComponent && !isNew && c.getSnapshotBeforeUpdate != null) { @@ -300,9 +300,8 @@ export function diff( newVNode._dom = oldDom; } else { for (let i = excessDomChildren.length; i--; ) { - if (excessDomChildren[i]) { - excessDomChildren[i].remove(); - } + const child = excessDomChildren[i]; + if (child) child.remove(); } } } else { @@ -544,7 +543,8 @@ function diffElementNodes( // Remove children that are not part of any vnode. if (excessDomChildren != null) { for (i = excessDomChildren.length; i--; ) { - if (excessDomChildren[i]) excessDomChildren[i].remove(); + const child = excessDomChildren[i]; + if (child) child.remove(); } } } @@ -643,7 +643,7 @@ export function unmount(vnode, parentVNode, skipRemove) { } } - if (!skipRemove && vnode._dom != null && typeof vnode.type != 'function') { + if (!skipRemove && vnode._dom != null && vnode._dom.parentNode) { vnode._dom.remove(); } diff --git a/src/index.d.ts b/src/index.d.ts index 08bc00fd25..92b5d49d27 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -299,16 +299,6 @@ interface ContainerNode { } export function render(vnode: ComponentChild, parent: ContainerNode): void; -/** - * @deprecated Will be removed in v11. - * - * Replacement Preact 10+ implementation can be found here: https://gist.github.com/developit/f4c67a2ede71dc2fab7f357f39cff28c - */ -export function render( - vnode: ComponentChild, - parent: ContainerNode, - replaceNode?: Element | Text -): void; export function hydrate(vnode: ComponentChild, parent: ContainerNode): void; export function cloneElement( vnode: VNode, diff --git a/src/render.js b/src/render.js index 97206fc043..e87f81a988 100644 --- a/src/render.js +++ b/src/render.js @@ -1,4 +1,4 @@ -import { EMPTY_OBJ } from './constants'; +import { EMPTY_OBJ, MODE_HYDRATE } from './constants'; import { commitRoot, diff } from './diff/index'; import { createElement, Fragment } from './create-element'; import options from './options'; @@ -8,10 +8,8 @@ import { slice } from './util'; * Render a Preact virtual node into a DOM element * @param {import('./internal').ComponentChild} vnode The virtual node to render * @param {import('./internal').PreactElement} parentDom The DOM element to render into - * @param {import('./internal').PreactElement | object} [replaceNode] Optional: Attempt to re-use an - * existing DOM tree rooted at `replaceNode` */ -export function render(vnode, parentDom, replaceNode) { +export function render(vnode, parentDom) { // https://github.com/preactjs/preact/issues/3794 if (parentDom == document) { parentDom = document.documentElement; @@ -19,10 +17,8 @@ export function render(vnode, parentDom, replaceNode) { if (options._root) options._root(vnode, parentDom); - // We abuse the `replaceNode` parameter in `hydrate()` to signal if we are in - // hydration mode or not by passing the `hydrate` function instead of a DOM - // element.. - let isHydrating = replaceNode === hydrate; + // @ts-expect-error + let isHydrating = !!(vnode && vnode._flags & MODE_HYDRATE); // To be able to support calling `render()` multiple times on the same // DOM node, we need to obtain a reference to the previous tree. We do @@ -65,5 +61,7 @@ export function render(vnode, parentDom, replaceNode) { * @param {import('./internal').PreactElement} parentDom The DOM element to update */ export function hydrate(vnode, parentDom) { - render(vnode, parentDom, hydrate); + // @ts-expect-error + vnode._flags |= MODE_HYDRATE; + render(vnode, parentDom); } diff --git a/src/util.js b/src/util.js index 8b112f69a2..282ab898d0 100644 --- a/src/util.js +++ b/src/util.js @@ -1,5 +1,17 @@ import { EMPTY_ARR } from './constants'; export const isArray = Array.isArray; -export const assign = Object.assign; export const slice = EMPTY_ARR.slice; + +/** + * Assign properties from `props` to `obj` + * @template O, P The obj and props types + * @param {O} obj The object to copy properties to + * @param {P} props The object to copy properties from + * @returns {O & P} + */ +export function assign(obj, props) { + // @ts-expect-error We change the type of `obj` to be `O & P` + for (let i in props) obj[i] = props[i]; + return /** @type {O & P} */ (obj); +}