@reckona/mreact-compat 0.0.185 → 0.0.187

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,8 +12,10 @@ import { isThenable } from "./thenable.js";
12
12
  import { hasDirtyClassUpdate, isClassComponentType, recoverClassComponentError, renderClassComponentWithRuntime, } from "./class-component.js";
13
13
  import { areMemoPropsEqual, getPendingProps, shallowEqual } from "./prop-comparison.js";
14
14
  import { reportElementTextMismatch, reportExtraHydrationNodes, reportHydrationNodeTypeMismatch, reportMissingHydrationNode, reportReactSuspenseServerError, reportRecoverable, withHydrationComponentStack, } from "./hydration.js";
15
+ import { withBatchedDelegatedRootReleases } from "@reckona/mreact-reactive-dom";
15
16
  const committedPortalContainers = new Set();
16
17
  const pendingHostRefUpdates = [];
18
+ const pendingReactiveDomBlockAfterCommits = [];
17
19
  const emptyInstanceKeys = [];
18
20
  const SKIP_COMMIT_PATH = "\0";
19
21
  const hasOwnProperty = Object.prototype.hasOwnProperty;
@@ -106,25 +108,30 @@ export function commitHostFiberRoot(root, finishedWork, options = {}) {
106
108
  try {
107
109
  committedPortalContainers.clear();
108
110
  pendingHostRefUpdates.length = 0;
111
+ pendingReactiveDomBlockAfterCommits.length = 0;
109
112
  const commitPath = getRootCommitPath(options);
110
113
  if (!hasChildListMutation(finishedWork)) {
111
114
  commitHostDirtyChildrenOf(finishedWork, finishedWork.child, root.container, root.container, commitPath, options);
115
+ flushPendingReactiveDomBlockAfterCommits();
112
116
  committed = true;
113
117
  return;
114
118
  }
115
119
  if (finishedWork.childListChanged &&
116
120
  commitHostKeyedChildListMutationFiber(finishedWork, root.container, root.container, commitPath, options)) {
121
+ flushPendingReactiveDomBlockAfterCommits();
117
122
  committed = true;
118
123
  return;
119
124
  }
120
125
  if (!finishedWork.childListChanged &&
121
126
  finishedWork.subtreeChildListChanged &&
122
127
  commitHostKeyedChildListMutation(finishedWork.child, root.container, root.container, commitPath, options)) {
128
+ flushPendingReactiveDomBlockAfterCommits();
123
129
  committed = true;
124
130
  return;
125
131
  }
126
132
  const nodes = commitHostChildren(finishedWork.child, root.container, root.container, commitPath, options);
127
133
  syncChildNodes(root.container, nodes);
134
+ flushPendingReactiveDomBlockAfterCommits();
128
135
  committed = true;
129
136
  }
130
137
  finally {
@@ -144,9 +151,11 @@ export function commitHydratingHostFiberRoot(root, finishedWork, scope, options
144
151
  try {
145
152
  committedPortalContainers.clear();
146
153
  pendingHostRefUpdates.length = 0;
154
+ pendingReactiveDomBlockAfterCommits.length = 0;
147
155
  const eventRoot = root.container;
148
156
  const nodes = commitHostChildren(finishedWork.child, scope.parent, eventRoot, "", options);
149
157
  syncScopedChildNodes(scope.parent, scope.before, scope.after, nodes);
158
+ flushPendingReactiveDomBlockAfterCommits();
150
159
  committed = true;
151
160
  }
152
161
  finally {
@@ -155,6 +164,7 @@ export function commitHydratingHostFiberRoot(root, finishedWork, scope, options
155
164
  }
156
165
  else {
157
166
  pendingHostRefUpdates.length = 0;
167
+ pendingReactiveDomBlockAfterCommits.length = 0;
158
168
  }
159
169
  committedPortalContainers.clear();
160
170
  }
@@ -168,23 +178,27 @@ export function disposeHostFiberResources(fiber) {
168
178
  if (fiber === undefined || fiber.hasDisposableResources !== true) {
169
179
  return;
170
180
  }
171
- // Dispose this fiber and its SUBTREE only — not its siblings. This is called
172
- // once per deleted fiber, and deleted siblings are disposed by their own
173
- // calls; walking siblings here re-walked the whole deleted list per deletion
174
- // (O(n^2) on a cleared 1k-row reactive list). The dedupe set is allocated
175
- // once for the subtree walk.
176
- const seen = new Set();
177
- if (fiber.tag === "reactive-dom-block") {
178
- disposeReactiveDomBlockState(fiber.stateNode, seen);
179
- }
180
- disposeHostFiberChildResources(fiber.child, seen);
181
+ withBatchedDelegatedRootReleases(() => {
182
+ // Dispose this fiber and its SUBTREE only not its siblings. This is called
183
+ // once per deleted fiber, and deleted siblings are disposed by their own
184
+ // calls; walking siblings here re-walked the whole deleted list per deletion
185
+ // (O(n^2) on a cleared 1k-row reactive list). The dedupe set is allocated
186
+ // once for the subtree walk.
187
+ const seen = new Set();
188
+ if (fiber.tag === "reactive-dom-block") {
189
+ disposeReactiveDomBlockState(fiber.stateNode, seen);
190
+ }
191
+ disposeHostFiberChildResources(fiber.child, seen);
192
+ });
181
193
  }
182
194
  export function disposeUnretainedHostFiberResources(fiber, retained) {
183
195
  if (fiber === undefined || fiber.hasDisposableResources !== true || retained.has(fiber)) {
184
196
  return;
185
197
  }
186
- const seen = new Set();
187
- disposeUnretainedHostFiberSubtreeResources(fiber, seen, retained);
198
+ withBatchedDelegatedRootReleases(() => {
199
+ const seen = new Set();
200
+ disposeUnretainedHostFiberSubtreeResources(fiber, seen, retained);
201
+ });
188
202
  }
189
203
  function disposeHostFiberChildResources(fiber, seen) {
190
204
  let cursor = fiber;
@@ -496,6 +510,9 @@ function isStaticReactiveBlockComponent(type) {
496
510
  return (typeof type === "function" &&
497
511
  type[STATIC_REACTIVE_BLOCK_MARKER] === true);
498
512
  }
513
+ function consumeReactiveDomBlockHydrationNode(previousNodes) {
514
+ return previousNodes === undefined || previousNodes.length === 0 ? 0 : 1;
515
+ }
499
516
  function areCompilerMemoComparePropsEqual(memoType, previousProps, nextProps) {
500
517
  const keys = memoType[MEMO_COMPARE_PROPS_MARKER];
501
518
  if (keys === undefined) {
@@ -1322,7 +1339,7 @@ function createHostFiberImpl(parent, current, node, key, runtime, path, options
1322
1339
  setReactivePropCell(previousState.propCell, blockProps);
1323
1340
  }
1324
1341
  fiber.stateNode = previousState;
1325
- return { fiber, consumed: options.previousNodes?.length ?? 0 };
1342
+ return { fiber, consumed: consumeReactiveDomBlockHydrationNode(options.previousNodes) };
1326
1343
  }
1327
1344
  const fiber = createFiber("reactive-dom-block", node.props, key);
1328
1345
  fiber.type = node.type;
@@ -1336,7 +1353,7 @@ function createHostFiberImpl(parent, current, node, key, runtime, path, options
1336
1353
  else {
1337
1354
  fiber.stateNode = render();
1338
1355
  }
1339
- return { fiber, consumed: options.previousNodes?.length ?? 0 };
1356
+ return { fiber, consumed: consumeReactiveDomBlockHydrationNode(options.previousNodes) };
1340
1357
  }
1341
1358
  if (isReactCompatProvider(node.type)) {
1342
1359
  const fiber = current?.tag === "context-provider" && current.type === node.type
@@ -1865,6 +1882,7 @@ function commitHostDirtyFiber(fiber, parent, eventRoot, path, options = {}) {
1865
1882
  if (!(isDomElement && childNodes.length === 0 && committedPortalContainers.has(element)) &&
1866
1883
  !(isDomElement && shouldPreserveContentEditableChildren(element, props, childNodes))) {
1867
1884
  syncChildNodes(element, childNodes);
1885
+ flushPendingReactiveDomBlockAfterCommits();
1868
1886
  }
1869
1887
  }
1870
1888
  else if (fiber.subtreeFlags !== NoFlags) {
@@ -2155,6 +2173,7 @@ function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
2155
2173
  }
2156
2174
  if (fiber.tag === "reactive-dom-block") {
2157
2175
  const node = getReactiveDomBlockNode(fiber.stateNode);
2176
+ enqueueReactiveDomBlockAfterCommit(fiber.stateNode);
2158
2177
  fiber.memoizedProps = fiber.pendingProps;
2159
2178
  finishCommittedFiber(fiber);
2160
2179
  return node === undefined ? [] : [node];
@@ -2214,6 +2233,7 @@ function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
2214
2233
  if (!(isDomElement && childNodes.length === 0 && committedPortalContainers.has(element)) &&
2215
2234
  !(isDomElement && shouldPreserveContentEditableChildren(element, props, childNodes))) {
2216
2235
  syncChildNodes(element, childNodes);
2236
+ flushPendingReactiveDomBlockAfterCommits();
2217
2237
  }
2218
2238
  }
2219
2239
  else if (fiber.subtreeFlags !== NoFlags) {
@@ -2341,6 +2361,18 @@ function getReactiveDomBlockNode(state) {
2341
2361
  }
2342
2362
  return undefined;
2343
2363
  }
2364
+ function enqueueReactiveDomBlockAfterCommit(state) {
2365
+ const afterCommit = state?.afterCommit;
2366
+ if (typeof afterCommit === "function") {
2367
+ pendingReactiveDomBlockAfterCommits.push(afterCommit);
2368
+ }
2369
+ }
2370
+ function flushPendingReactiveDomBlockAfterCommits() {
2371
+ const pending = pendingReactiveDomBlockAfterCommits.splice(0);
2372
+ for (const afterCommit of pending) {
2373
+ afterCommit();
2374
+ }
2375
+ }
2344
2376
  function disposeReactiveDomBlockState(state, seen) {
2345
2377
  if (typeof state !== "object" || state === null || seen.has(state)) {
2346
2378
  return;