Skip to content

Commit 9c44db8

Browse files
authored
Save bytes by inlining ref unmount checks (#4896)
* Save bytes by inlining ref unmount checks * Inline unmount check * Hoist excessDomChildren check * Reduce var alloc * Remove need for clearProcessingException * Remove need for isNew * Save bytes by making shouldPlace a number * Use else to save some bytees * Save some render bytes
1 parent 665126a commit 9c44db8

File tree

4 files changed

+28
-30
lines changed

4 files changed

+28
-30
lines changed

src/component.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,10 @@ BaseComponent.prototype.setState = function (update, callback) {
4848

4949
if (update) {
5050
assign(s, update);
51+
} else {
52+
return;
5153
}
5254

53-
// Skip update if updater function returned null
54-
if (update == NULL) return;
55-
5655
if (this._vnode) {
5756
if (callback) {
5857
this._stateCallbacks.push(callback);

src/diff/children.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export function diffChildren(
128128
firstChildDom = newDom;
129129
}
130130

131-
let shouldPlace = !!(childVNode._flags & INSERT_VNODE);
131+
let shouldPlace = childVNode._flags & INSERT_VNODE;
132132
if (shouldPlace || oldVNode._children === childVNode._children) {
133133
oldDom = insert(childVNode, oldDom, parentDom, shouldPlace);
134134
} else if (typeof childVNode.type == 'function' && result !== UNDEFINED) {
@@ -251,9 +251,7 @@ function constructNewChildrenArray(
251251
// Here, we define isMounting for the purposes of the skew diffing
252252
// algorithm. Nodes that are unsuspending are considered mounting and we detect
253253
// this by checking if oldVNode._original == null
254-
const isMounting = oldVNode == NULL || oldVNode._original == NULL;
255-
256-
if (isMounting) {
254+
if (oldVNode == NULL || oldVNode._original == NULL) {
257255
if (matchingIndex == -1) {
258256
// When the array of children is growing we need to decrease the skew
259257
// as we are adding a new element to the array.
@@ -340,7 +338,7 @@ function constructNewChildrenArray(
340338
* @param {VNode} parentVNode
341339
* @param {PreactElement} oldDom
342340
* @param {PreactElement} parentDom
343-
* @param {boolean} shouldPlace
341+
* @param {number} shouldPlace
344342
* @returns {PreactElement}
345343
*/
346344
function insert(parentVNode, oldDom, parentDom, shouldPlace) {

src/diff/index.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,11 @@ export function diff(
8989

9090
outer: if (typeof newType == 'function') {
9191
try {
92-
let c, isNew, oldProps, oldState, snapshot, clearProcessingException;
93-
let newProps = newVNode.props;
92+
let c,
93+
oldProps,
94+
oldState,
95+
snapshot,
96+
newProps = newVNode.props;
9497
const isClassComponent =
9598
'prototype' in newType && newType.prototype.render;
9699

@@ -109,7 +112,6 @@ export function diff(
109112
c = newVNode._component = oldVNode._component;
110113
if (c._bits & COMPONENT_PENDING_ERROR) {
111114
c._bits |= COMPONENT_PROCESSING_EXCEPTION;
112-
clearProcessingException = true;
113115
}
114116
} else {
115117
// Instantiate the new component
@@ -132,7 +134,6 @@ export function diff(
132134
if (!c.state) c.state = {};
133135
c.context = componentContext;
134136
c._globalContext = globalContext;
135-
isNew = true;
136137
c._bits |= COMPONENT_DIRTY;
137138
c._renderCallbacks = [];
138139
c._stateCallbacks = [];
@@ -159,7 +160,7 @@ export function diff(
159160
c._vnode = newVNode;
160161

161162
// Invoke pre-render lifecycle methods
162-
if (isNew) {
163+
if (!oldVNode._component) {
163164
if (
164165
isClassComponent &&
165166
newType.getDerivedStateFromProps == NULL &&
@@ -269,21 +270,24 @@ export function diff(
269270
globalContext = assign({}, globalContext, c.getChildContext());
270271
}
271272

272-
if (isClassComponent && !isNew && c.getSnapshotBeforeUpdate != NULL) {
273+
if (
274+
isClassComponent &&
275+
oldVNode._component &&
276+
c.getSnapshotBeforeUpdate != NULL
277+
) {
273278
snapshot = c.getSnapshotBeforeUpdate(oldProps, oldState);
274279
}
275280

276281
let isTopLevelFragment =
277282
tmp != NULL && tmp.type === Fragment && tmp.key == NULL;
278-
let renderResult = tmp;
279283

280284
if (isTopLevelFragment) {
281-
renderResult = cloneNode(tmp.props.children);
285+
tmp = cloneNode(tmp.props.children);
282286
}
283287

284288
oldDom = diffChildren(
285289
parentDom,
286-
isArray(renderResult) ? renderResult : [renderResult],
290+
isArray(tmp) ? tmp : [tmp],
287291
newVNode,
288292
oldVNode,
289293
globalContext,
@@ -303,7 +307,7 @@ export function diff(
303307
commitQueue.push(c);
304308
}
305309

306-
if (clearProcessingException) {
310+
if (c._bits & COMPONENT_PENDING_ERROR) {
307311
c._bits &= ~(COMPONENT_PROCESSING_EXCEPTION | COMPONENT_PENDING_ERROR);
308312
}
309313
} catch (e) {
@@ -664,13 +668,11 @@ function diffElementNodes(
664668
export function applyRef(ref, value, vnode) {
665669
try {
666670
if (typeof ref == 'function') {
667-
let hasRefUnmount = typeof ref._unmount == 'function';
668-
if (hasRefUnmount) {
669-
// @ts-ignore TS doesn't like moving narrowing checks into variables
671+
if (typeof ref._unmount == 'function') {
670672
ref._unmount();
671673
}
672674

673-
if (!hasRefUnmount || value != NULL) {
675+
if (typeof ref._unmount != 'function' || value != NULL) {
674676
// Store the cleanup function on the function
675677
// instance object itself to avoid shape
676678
// transitioning vnode
@@ -693,10 +695,8 @@ export function unmount(vnode, parentVNode, skipRemove) {
693695
let r;
694696
if (options.unmount) options.unmount(vnode);
695697

696-
if ((r = vnode.ref)) {
697-
if (!r.current || r.current == vnode._dom) {
698-
applyRef(r, NULL, parentVNode);
699-
}
698+
if ((r = vnode.ref) && (!r.current || r.current == vnode._dom)) {
699+
applyRef(r, NULL, parentVNode);
700700
}
701701

702702
if ((r = vnode._component) != NULL) {

src/render.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export function render(vnode, parentDom) {
1818
if (options._root) options._root(vnode, parentDom);
1919

2020
// @ts-expect-error
21-
let isHydrating = !!(vnode && vnode._flags & MODE_HYDRATE);
21+
let isHydrating = vnode && vnode._flags & MODE_HYDRATE;
2222

2323
// To be able to support calling `render()` multiple times on the same
2424
// DOM node, we need to obtain a reference to the previous tree. We do
@@ -27,7 +27,7 @@ export function render(vnode, parentDom) {
2727
// means that we are mounting a new tree for the first time.
2828
let oldVNode = isHydrating ? NULL : parentDom._children;
2929

30-
vnode = parentDom._children = createElement(Fragment, NULL, [vnode]);
30+
parentDom._children = createElement(Fragment, NULL, [vnode]);
3131

3232
// List of effects that need to be called after diffing.
3333
let commitQueue = [],
@@ -37,7 +37,7 @@ export function render(vnode, parentDom) {
3737
parentDom,
3838
// Determine the new vnode tree and store it on the DOM element on
3939
// our custom `_children` property.
40-
vnode,
40+
parentDom._children,
4141
oldVNode || EMPTY_OBJ,
4242
EMPTY_OBJ,
4343
parentDom.namespaceURI,
@@ -48,13 +48,14 @@ export function render(vnode, parentDom) {
4848
: NULL,
4949
commitQueue,
5050
oldVNode ? oldVNode._dom : parentDom.firstChild,
51+
// @ts-expect-error we are doing a bit-wise operation so it's either 0 or true
5152
isHydrating,
5253
refQueue,
5354
parentDom.ownerDocument
5455
);
5556

5657
// Flush all queued effects
57-
commitRoot(commitQueue, vnode, refQueue);
58+
commitRoot(commitQueue, parentDom._children, refQueue);
5859
}
5960

6061
/**

0 commit comments

Comments
 (0)