From 7fb54b6c03f23bc853e18f1c66ff1348a7326e3a Mon Sep 17 00:00:00 2001 From: jdecroock Date: Sat, 27 Jul 2024 16:38:45 +0200 Subject: [PATCH] Prune some more --- compat/src/index.js | 16 ----- compat/src/suspense-list.d.ts | 14 ---- compat/src/suspense-list.js | 127 ---------------------------------- 3 files changed, 157 deletions(-) delete mode 100644 compat/src/suspense-list.d.ts delete mode 100644 compat/src/suspense-list.js diff --git a/compat/src/index.js b/compat/src/index.js index 85f21e2419..9e8a38da39 100644 --- a/compat/src/index.js +++ b/compat/src/index.js @@ -25,7 +25,6 @@ import { memo } from './memo'; import { forwardRef } from './forwardRef'; import { Children } from './Children'; import { Suspense, lazy } from './suspense'; -import { SuspenseList } from './suspense-list'; import { createPortal } from './portals'; import { is } from './util'; import { hydrate, render, REACT_ELEMENT_TYPE } from './render'; @@ -112,16 +111,6 @@ function findDOMNode(component) { ); } -/** - * Deprecated way to control batched rendering inside the reconciler, but we - * already schedule in batches inside our rendering code - * @template Arg - * @param {(arg: Arg) => void} callback function that triggers the updated - * @param {Arg} [arg] Optional argument that can be passed to the callback - */ -// eslint-disable-next-line camelcase -const unstable_batchedUpdates = (callback, arg) => callback(arg); - /** * In React, `flushSync` flushes the entire tree and forces a rerender. It's * implmented here as a no-op. @@ -233,11 +222,8 @@ export { memo, forwardRef, flushSync, - // eslint-disable-next-line camelcase - unstable_batchedUpdates, StrictMode, Suspense, - SuspenseList, lazy }; @@ -281,9 +267,7 @@ export default { memo, forwardRef, flushSync, - unstable_batchedUpdates, StrictMode, Suspense, - SuspenseList, lazy }; diff --git a/compat/src/suspense-list.d.ts b/compat/src/suspense-list.d.ts deleted file mode 100644 index caa1eb6bff..0000000000 --- a/compat/src/suspense-list.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Component, ComponentChild, ComponentChildren } from '../../src'; - -// -// SuspenseList -// ----------------------------------- - -export interface SuspenseListProps { - children?: ComponentChildren; - revealOrder?: 'forwards' | 'backwards' | 'together'; -} - -export class SuspenseList extends Component { - render(): ComponentChild; -} diff --git a/compat/src/suspense-list.js b/compat/src/suspense-list.js deleted file mode 100644 index 5e5d750a08..0000000000 --- a/compat/src/suspense-list.js +++ /dev/null @@ -1,127 +0,0 @@ -import { Component, toChildArray } from 'preact'; -import { suspended } from './suspense.js'; - -// Indexes to linked list nodes (nodes are stored as arrays to save bytes). -const SUSPENDED_COUNT = 0; -const RESOLVED_COUNT = 1; -const NEXT_NODE = 2; - -// Having custom inheritance instead of a class here saves a lot of bytes. -export function SuspenseList() { - this._next = null; - this._map = null; -} - -// Mark one of child's earlier suspensions as resolved. -// Some pending callbacks may become callable due to this -// (e.g. the last suspended descendant gets resolved when -// revealOrder === 'together'). Process those callbacks as well. -const resolve = (list, child, node) => { - if (++node[RESOLVED_COUNT] === node[SUSPENDED_COUNT]) { - // The number a child (or any of its descendants) has been suspended - // matches the number of times it's been resolved. Therefore we - // mark the child as completely resolved by deleting it from ._map. - // This is used to figure out when *all* children have been completely - // resolved when revealOrder is 'together'. - list._map.delete(child); - } - - // If revealOrder is falsy then we can do an early exit, as the - // callbacks won't get queued in the node anyway. - // If revealOrder is 'together' then also do an early exit - // if all suspended descendants have not yet been resolved. - if ( - !list.props.revealOrder || - (list.props.revealOrder[0] === 't' && list._map.size) - ) { - return; - } - - // Walk the currently suspended children in order, calling their - // stored callbacks on the way. Stop if we encounter a child that - // has not been completely resolved yet. - node = list._next; - while (node) { - while (node.length > 3) { - node.pop()(); - } - if (node[RESOLVED_COUNT] < node[SUSPENDED_COUNT]) { - break; - } - list._next = node = node[NEXT_NODE]; - } -}; - -// Things we do here to save some bytes but are not proper JS inheritance: -// - call `new Component()` as the prototype -// - do not set `Suspense.prototype.constructor` to `Suspense` -SuspenseList.prototype = new Component(); - -SuspenseList.prototype._suspended = function (child) { - const list = this; - const delegated = suspended(list._vnode); - - let node = list._map.get(child); - node[SUSPENDED_COUNT]++; - - return unsuspend => { - const wrappedUnsuspend = () => { - if (!list.props.revealOrder) { - // Special case the undefined (falsy) revealOrder, as there - // is no need to coordinate a specific order or unsuspends. - unsuspend(); - } else { - node.push(unsuspend); - resolve(list, child, node); - } - }; - if (delegated) { - delegated(wrappedUnsuspend); - } else { - wrappedUnsuspend(); - } - }; -}; - -SuspenseList.prototype.render = function (props) { - this._next = null; - this._map = new Map(); - - const children = toChildArray(props.children); - if (props.revealOrder && props.revealOrder[0] === 'b') { - // If order === 'backwards' (or, well, anything starting with a 'b') - // then flip the child list around so that the last child will be - // the first in the linked list. - children.reverse(); - } - // Build the linked list. Iterate through the children in reverse order - // so that `_next` points to the first linked list node to be resolved. - for (let i = children.length; i--; ) { - // Create a new linked list node as an array of form: - // [suspended_count, resolved_count, next_node] - // where suspended_count and resolved_count are numeric counters for - // keeping track how many times a node has been suspended and resolved. - // - // Note that suspended_count starts from 1 instead of 0, so we can block - // processing callbacks until componentDidMount has been called. In a sense - // node is suspended at least until componentDidMount gets called! - // - // Pending callbacks are added to the end of the node: - // [suspended_count, resolved_count, next_node, callback_0, callback_1, ...] - this._map.set(children[i], (this._next = [1, 0, this._next])); - } - return props.children; -}; - -SuspenseList.prototype.componentDidUpdate = - SuspenseList.prototype.componentDidMount = function () { - // Iterate through all children after mounting for two reasons: - // 1. As each node[SUSPENDED_COUNT] starts from 1, this iteration increases - // each node[RELEASED_COUNT] by 1, therefore balancing the counters. - // The nodes can now be completely consumed from the linked list. - // 2. Handle nodes that might have gotten resolved between render and - // componentDidMount. - this._map.forEach((node, child) => { - resolve(this, child, node); - }); - };