Skip to content

Commit

Permalink
fix(hdom): fix #72, update __skip diff handling & HDOMImplementation
Browse files Browse the repository at this point in the history
- when a previously skipped element is re-enabled, replace entire sub-tree,
  but do NOT call lifecycle `init()` methods
- add init arg/flag to HDOMImplementation.createTree() / replaceChild()
- update DEFAULT_IMPL
- update normalizeElement()
  • Loading branch information
postspectacular committed Oct 6, 2019
1 parent 21ff930 commit 0071df3
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 14 deletions.
4 changes: 4 additions & 0 deletions packages/hdom/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,10 @@ ignored during diffing. Therefore, if this attribute is enabled the
element should either have no children OR the children are the same
(type) as when the attribute is disabled (i.e. when `__skip` is falsy).

Furthermore, once a previously skipped element is re-enabled (i.e. its
`__skip` attrib is now falsy again), the element's entire sub-tree is
re-created, but any lifecycle `init()` methods will not be re-executed.

### Benchmarks

Some stress test benchmarks are here:
Expand Down
7 changes: 5 additions & 2 deletions packages/hdom/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,14 @@ export interface HDOMImplementation<T> {
* @param parent
* @param tree
* @param child
* @param init
*/
createTree(
opts: Partial<HDOMOpts>,
parent: T,
tree: any,
child?: number
child?: number,
init?: boolean
): T | T[];

/**
Expand Down Expand Up @@ -400,7 +402,8 @@ export interface HDOMImplementation<T> {
opts: Partial<HDOMOpts>,
parent: T,
child: number,
newTree: any
newTree: any,
init?: boolean
): T | T[];

/**
Expand Down
8 changes: 4 additions & 4 deletions packages/hdom/src/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import { normalizeTree } from "./normalize";
* Default target implementation to manipulate browser DOM.
*/
export const DEFAULT_IMPL: HDOMImplementation<any> = {
createTree(opts, parent, tree, child?) {
return createTree(opts, this, parent, tree, child);
createTree(opts, parent, tree, child?, init?) {
return createTree(opts, this, parent, tree, child, init);
},

hydrateTree(opts, parent, tree, child?) {
Expand All @@ -42,8 +42,8 @@ export const DEFAULT_IMPL: HDOMImplementation<any> = {

createTextElement,

replaceChild(opts, parent, child, tree) {
replaceChild(opts, this, parent, child, tree);
replaceChild(opts, parent, child, tree, init?) {
replaceChild(opts, this, parent, child, tree, init);
},

removeChild,
Expand Down
5 changes: 5 additions & 0 deletions packages/hdom/src/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ export const diffTree = <T>(
impl.replaceChild(opts, parent, child, curr);
return;
}
const pattribs = prev[1];
if (pattribs && pattribs.__skip) {
impl.replaceChild(opts, parent, child, curr, false);
return;
}
// delegate to branch-local implementation
let _impl = attribs.__impl;
if (_impl && _impl !== impl) {
Expand Down
18 changes: 11 additions & 7 deletions packages/hdom/src/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ export const createTree = <T>(
impl: HDOMImplementation<T>,
parent: T,
tree: any,
insert?: number
insert?: number,
init = true
): any => {
if (isArray(tree)) {
const tag = tree[0];
Expand All @@ -41,23 +42,24 @@ export const createTree = <T>(
opts,
parent,
tree,
insert
insert,
init
);
}
const el = impl.createElement(parent, tag, attribs, insert);
if (tree.length > 2) {
const n = tree.length;
for (let i = 2; i < n; i++) {
createTree(opts, impl, el, tree[i]);
createTree(opts, impl, el, tree[i], undefined, init);
}
}
maybeInitElement<T>(el, tree);
init && maybeInitElement<T>(el, tree);
return el;
}
if (isNotStringAndIterable(tree)) {
const res = [];
for (let t of tree) {
res.push(createTree(opts, impl, parent, t));
res.push(createTree(opts, impl, parent, t, insert, init));
}
return res;
}
Expand Down Expand Up @@ -165,9 +167,11 @@ export const replaceChild = (
impl: HDOMImplementation<any>,
parent: Element,
child: number,
tree: any
tree: any,
init = true
) => (
impl.removeChild(parent, child), impl.createTree(opts, parent, tree, child)
impl.removeChild(parent, child),
impl.createTree(opts, parent, tree, child, init)
);

export const cloneWithNewAttribs = (el: Element, attribs: any) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/hdom/src/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const normalizeElement = (spec: any[], keys: boolean) => {
}
}
return attribs.__skip && spec.length < 3
? [mtag, attribs, ""]
? [mtag, attribs]
: [mtag, attribs, ...spec.slice(hasAttribs ? 2 : 1)];
};

Expand Down

0 comments on commit 0071df3

Please sign in to comment.