@tanstack/redact 0.0.5 → 0.0.7

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.
package/README.md ADDED
@@ -0,0 +1,481 @@
1
+ # redact
2
+
3
+ **React, redacted.** A minimal React-19-API-compatible drop-in replacement, **~4× smaller** than canonical React. Shipped as a single `@tanstack/redact` package with subpath exports for the `react` / `react-dom` / `react-dom/server` / `scheduler` / `react/jsx-runtime` shapes. User code keeps its canonical `import { useState } from 'react'` — the swap happens at the bundler level.
4
+
5
+ - **9.07 KB** gzip at full drop-in parity (vs ~45 KB for React 19)
6
+ - **6.75 KB** gzip with every opt-in feature stubbed (`nano` preset)
7
+ - **707/707** unit + integration tests passing, SSR + streaming Suspense + hydration included
8
+ - Running in production on [tanstack.com](https://tanstack.com) as of 2026-04-20
9
+
10
+ ---
11
+
12
+ ## Quick start
13
+
14
+ ```bash
15
+ pnpm add @tanstack/redact@next
16
+ ```
17
+
18
+ ```ts
19
+ // vite.config.ts
20
+ import { defineConfig } from 'vite'
21
+ import { redact } from '@tanstack/redact/vite'
22
+
23
+ export default defineConfig({
24
+ plugins: [redact()],
25
+ })
26
+ ```
27
+
28
+ That's it. The plugin aliases `react` / `react-dom` / `scheduler` across Vite's client + ssr environments. The RSC environment is skipped so `@vitejs/plugin-rsc` keeps using real React for Flight serialization. User-facing imports are unchanged:
29
+
30
+ ```ts
31
+ import { useState, Suspense } from 'react'
32
+ import { createRoot, hydrateRoot } from 'react-dom/client'
33
+ ```
34
+
35
+ ### Shrink further with feature flags
36
+
37
+ Two presets — pick a starting point, flip flags from there:
38
+
39
+ ```ts
40
+ redact({ preset: 'full' }) // 9.07 KB — everything on, opt OUT individual features
41
+ redact({ preset: 'nano' }) // 6.75 KB — everything off, opt IN what you need
42
+ ```
43
+
44
+ Opt out from `full`:
45
+
46
+ ```ts
47
+ redact({
48
+ preset: 'full',
49
+ features: {
50
+ hydration: false, // SPA only — no SSR
51
+ classComponents: false, // function components only
52
+ },
53
+ })
54
+ ```
55
+
56
+ Opt in from `nano`:
57
+
58
+ ```ts
59
+ redact({
60
+ preset: 'nano',
61
+ features: {
62
+ context: true, // bring back just what you need
63
+ suspense: true,
64
+ },
65
+ })
66
+ ```
67
+
68
+ Full feature matrix and alternative configuration paths below.
69
+
70
+ ---
71
+
72
+ ## How it works in 30 seconds
73
+
74
+ `@tanstack/redact/dom` is built as an irreducible core (fiber reconciler, host DOM, core hooks, elements) plus **8 opt-in features** layered on top. Each feature has a `full.ts` (real implementation) and a `stub.ts` (graceful degradation). Features self-register with the reconciler at module load — renderers, type matchers, capability hooks.
75
+
76
+ Feature selection is a bundler-level concern. The `@tanstack/redact/vite` plugin's `resolveId` hook swaps `features/<name>/index.js` → `features/<name>/stub.js` for features you've flagged off. Stubbed features' full code never enters the module graph, so tree-shaking strips it. No user-code changes. No runtime branching.
77
+
78
+ ---
79
+
80
+ ## Feature flags
81
+
82
+ ### Feature matrix
83
+
84
+ | Flag | Full behavior | Stub behavior (when `false`) | Savings (gzip) |
85
+ |---|---|---|---:|
86
+ | `portal` | `createPortal` into alt container | Children render in place, `container` ignored | ~30 B |
87
+ | `context` | Provider push/pop + consumer walk | Provider → Fragment; `useContext` returns default | ~80 B |
88
+ | `suspense` | Boundary + fallback + streaming hydration | Suspense → Fragment; thenables retry on settle | **~640 B** |
89
+ | `memo` | `shallowEqual` prop-equality gate | Passes through every parent render | ~80 B |
90
+ | `forwardRef` | Ref forwarded to inner fn | Ref dropped (React 19 "refs as props" still works) | ~70 B |
91
+ | `lazy` | Full hydration coordination | Sync-resolvable payloads work; async retries on settle | ~20 B |
92
+ | `classComponents` | Full lifecycle + `contextType` + error boundaries | `constructor` + `render` + `setState` only | ~200 B |
93
+ | `hydration` | SSR DOM adoption, streaming boundaries, scroll guard, event replay | `hydrateRoot` throws; use `createRoot` for SPA | **~1270 B** |
94
+
95
+ **Always on** (irreducible core, ~6.7 KB gzip): fiber reconciler with keyed child diffing, host DOM mount/update, `useState` / `useReducer` / `useEffect` / `useLayoutEffect` / `useInsertionEffect` / `useRef` / `useMemo` / `useCallback` / `useId` / `useSyncExternalStore` / `use` (for thenables), native event binding, Fragments, StrictMode/Profiler (aliased to Fragment), element creation + JSX runtime.
96
+
97
+ ### Presets
98
+
99
+ | Preset | What's on | `react-dom/client` gzip | Intent |
100
+ |---|---|---:|---|
101
+ | `full` (default) | all 8 features | **9.07 KB** | Drop-in React — opt OUT individual features you don't need |
102
+ | **`nano`** | none | **6.75 KB** | Start minimal — opt IN individual features you need |
103
+
104
+ Two presets, not a spectrum: every app either wants most of React (start from `full`, opt out) or a tight bundle (start from `nano`, opt in). Per-feature overrides merge on top of preset defaults either way.
105
+
106
+ ---
107
+
108
+ ## Configuration
109
+
110
+ Four ways to configure, depending on your bundler and ergonomics preference.
111
+
112
+ ### 1. Vite plugin (recommended)
113
+
114
+ `@tanstack/redact/vite`'s `redact()` plugin. Covered in [Quick start](#quick-start) above. Full options:
115
+
116
+ ```ts
117
+ interface RedactOptions {
118
+ preset?: 'nano' | 'full' // default: 'full'
119
+ features?: {
120
+ portal?: boolean
121
+ context?: boolean
122
+ suspense?: boolean
123
+ memo?: boolean
124
+ forwardRef?: boolean
125
+ lazy?: boolean
126
+ classComponents?: boolean
127
+ hydration?: boolean
128
+ }
129
+ skip?: ReadonlyArray<string> // don't alias these specifiers
130
+ resolveFrom?: string // override package resolution root
131
+ packageRoots?: Record<string, string> // explicit package paths
132
+ }
133
+ ```
134
+
135
+ The plugin also handles Vite-specific wiring: `optimizeDeps.exclude` for the shim packages, `ssr.noExternal` so SSR bundles inline them, and an `enforce: 'pre'` hook ordering so the alias wins over other resolvers.
136
+
137
+ ### 2. Bundler aliases (Webpack / Rollup / esbuild / …)
138
+
139
+ The package exposes every feature module as a `./features/*` subpath export. Any bundler with a path-alias feature can redirect a feature's `index` to its `stub` to opt the feature out of the bundle.
140
+
141
+ **Subpath layout:**
142
+
143
+ ```
144
+ @tanstack/redact/features/
145
+ portal/ context/ suspense/ memo/ forward-ref/ lazy/ class/ hydration/
146
+ index ← re-exports from ./full by default
147
+ full ← real implementation
148
+ stub ← graceful degradation
149
+ ```
150
+
151
+ **Webpack example (stubs hydration + suspense):**
152
+
153
+ ```js
154
+ // webpack.config.js
155
+ module.exports = {
156
+ resolve: {
157
+ alias: {
158
+ '@tanstack/redact/features/hydration/index':
159
+ '@tanstack/redact/features/hydration/stub',
160
+ '@tanstack/redact/features/suspense/index':
161
+ '@tanstack/redact/features/suspense/stub',
162
+ },
163
+ },
164
+ }
165
+ ```
166
+
167
+ **Rollup:**
168
+
169
+ ```js
170
+ import alias from '@rollup/plugin-alias'
171
+
172
+ export default {
173
+ plugins: [
174
+ alias({
175
+ entries: [
176
+ {
177
+ find: '@tanstack/redact/features/hydration/index',
178
+ replacement: '@tanstack/redact/features/hydration/stub',
179
+ },
180
+ ],
181
+ }),
182
+ ],
183
+ }
184
+ ```
185
+
186
+ **esbuild:**
187
+
188
+ ```js
189
+ import { build } from 'esbuild'
190
+
191
+ await build({
192
+ entryPoints: ['src/app.tsx'],
193
+ bundle: true,
194
+ alias: {
195
+ '@tanstack/redact/features/hydration/index':
196
+ '@tanstack/redact/features/hydration/stub',
197
+ },
198
+ })
199
+ ```
200
+
201
+ **Gotchas:**
202
+
203
+ - **On-disk folder names vs. config keys**: `forward-ref/` ↔ `forwardRef`, `class/` ↔ `classComponents`. When configuring aliases manually, match the on-disk folder.
204
+ - **Single-instance requirement**: `@tanstack/redact` (and any subpath of it) must resolve to **one** installed copy in your app. Mixing source + dist, or two different tarballs, duplicates `ReactSharedInternals` and breaks hooks. The package's `ReactSharedInternals` is stashed on `globalThis` under a registered symbol as a defense-in-depth, but you should still aim for a single copy.
205
+ - **Feature interdependencies**: Suspense's full implementation imports hydration helpers. If hydration is stubbed but Suspense is full, the Suspense feature uses hydration's no-op stubs (fine — you're not hydrating). Suspense stubbed + hydration full is also fine (streaming boundaries just won't render fallback UI because `Suspense` maps to Fragment).
206
+
207
+ ### 3. Prebuilt bundle presets (planned)
208
+
209
+ Not yet shipped. The planned shape:
210
+
211
+ ```ts
212
+ import { createRoot } from '@tanstack/redact/dom/nano/client'
213
+ ```
214
+
215
+ Zero bundler configuration; useful for script-tag usage, non-bundler Node tools, or users who just want the smallest install without thinking about it.
216
+
217
+ **Why not yet:** the preset bundle would need its own self-contained `_all.js` built with the right stubs compiled in — stubs can't reliably overlay a module that registers full variants first (registration order matters, last-write-wins). We want to gather real Vite-plugin usage data before deciding which prebuilt configurations are worth publishing. Open an issue with your use case if this unblocks you.
218
+
219
+ ### 4. npm aliases (limited)
220
+
221
+ `npm:` package aliases in `package.json` work for the top-level `react` mapping but **not** for subpaths — there's no spec-level way to point `react-dom` at a subpath like `@tanstack/redact/dom` purely via `package.json`. So this path only gets you partway:
222
+
223
+ ```jsonc
224
+ // package.json — works, but only swaps `react` itself
225
+ {
226
+ "dependencies": {
227
+ "react": "npm:@tanstack/redact@next"
228
+ }
229
+ }
230
+ ```
231
+
232
+ Anything that imports `react-dom`, `react-dom/client`, `react-dom/server`, or `scheduler` will still resolve to the real React in `node_modules` unless your bundler can rewrite those specifiers — at which point you may as well use Path 1 (Vite plugin) or Path 2 (bundler aliases). This is a real trade-off of the single-package layout: the install side is simpler but the no-bundler workflow loses some flexibility versus a multi-package shim. If you need a no-bundler full swap, open an issue with your toolchain and we can publish individual `@tanstack/redact-dom`, `@tanstack/redact-server`, etc. compatibility re-export packages.
233
+
234
+ ---
235
+
236
+ ## Advanced: authoring custom features & bundler plugins
237
+
238
+ If you're extending the system, writing a bundler plugin for a tool without one, or just curious how the swap works — the internal API surface is exported from `@tanstack/redact/_all`.
239
+
240
+ ### Registration primitives
241
+
242
+ Feature modules self-register by calling these at module load:
243
+
244
+ ```ts
245
+ import {
246
+ registerRenderer,
247
+ registerTypeMatcher,
248
+ registerElementMarker,
249
+ type RenderFn,
250
+ type TypeMatcher,
251
+ } from '@tanstack/redact/_all'
252
+
253
+ // Install a renderer for a FiberTag. Later calls overwrite earlier ones —
254
+ // stubs exploit this order-dependence.
255
+ function registerRenderer(tag: FiberTag, fn: RenderFn): void
256
+
257
+ // Add a type matcher. Iterated in registration order during fiber creation,
258
+ // after core checks (string → Host, REACT_FRAGMENT_TYPE → Fragment) and
259
+ // before the function-vs-class fallback.
260
+ type TypeMatcher = (type: any, marker: any) => FiberTag | null
261
+ function registerTypeMatcher(m: TypeMatcher): void
262
+
263
+ // Extend the accepted $$typeof set for child normalization. Default:
264
+ // REACT_ELEMENT_TYPE, REACT_LEGACY_ELEMENT_TYPE. Portal adds REACT_PORTAL_TYPE.
265
+ function registerElementMarker(sym: symbol): void
266
+ ```
267
+
268
+ ### Capability hooks
269
+
270
+ Cross-cutting concerns (thrown-thenable handling, context reads) install via `installCapability`:
271
+
272
+ ```ts
273
+ import { installCapability, type Capabilities } from '@tanstack/redact/_all'
274
+
275
+ interface Capabilities {
276
+ handleSuspended: (fiber: Fiber, thenable: Promise<any>) => void
277
+ readContext: (fiber: Fiber, ctx: any) => any
278
+ }
279
+
280
+ function installCapability<K extends keyof Capabilities>(
281
+ name: K,
282
+ fn: Capabilities[K],
283
+ ): void
284
+ ```
285
+
286
+ Defaults when no feature installs an override:
287
+ - `handleSuspended`: retry-on-settle (no boundary stack, no fallback)
288
+ - `readContext`: returns `ctx._currentValue` with no provider-tree walk
289
+
290
+ The full Suspense feature installs a boundary-stack-based `handleSuspended`. The full Context feature installs a walking `readContext`.
291
+
292
+ ### Authoring a custom feature
293
+
294
+ ```ts
295
+ // my-feature/full.ts
296
+ import {
297
+ FiberTag,
298
+ registerRenderer,
299
+ registerTypeMatcher,
300
+ reconcileChildren,
301
+ childrenToArray,
302
+ type Fiber,
303
+ } from '@tanstack/redact/_all'
304
+ import { SOME_SYMBOL } from '@tanstack/redact'
305
+
306
+ function renderMyThing(fiber: Fiber, domParent: Node, anchor: Node | null): void {
307
+ // your render logic
308
+ }
309
+
310
+ registerTypeMatcher((_type, marker) =>
311
+ marker === SOME_SYMBOL ? FiberTag.SomeTag : null,
312
+ )
313
+ registerRenderer(FiberTag.SomeTag, renderMyThing)
314
+ ```
315
+
316
+ ```ts
317
+ // my-feature/stub.ts
318
+ import { FiberTag, registerTypeMatcher } from '@tanstack/redact/_all'
319
+ import { SOME_SYMBOL } from '@tanstack/redact'
320
+
321
+ // Stub: treat my-thing elements as Fragments (children render normally).
322
+ registerTypeMatcher((_type, marker) =>
323
+ marker === SOME_SYMBOL ? FiberTag.Fragment : null,
324
+ )
325
+ ```
326
+
327
+ Pair with an `index.ts` (`export * from './full'`) and let your bundler pick which to import.
328
+
329
+ ### Authoring a bundler plugin
330
+
331
+ The Vite plugin's core is two `resolveId` cases. Port this pattern to any bundler's resolve hook:
332
+
333
+ ```ts
334
+ // Case 1: short specifier from features/index.ts
335
+ // Matches `./portal`, `./context`, etc.
336
+ if (importer matches /features[/\\]index\.(ts|js)$/) {
337
+ const name = id.match(/^\.\/([a-z-]+)$/)?.[1]
338
+ if (name && flags[name] === false) {
339
+ return resolveFrom(`./${name}/stub`, importer)
340
+ }
341
+ }
342
+
343
+ // Case 2: resolved-path match for hydration
344
+ // (imported from reconcile, root, suspense/full, lazy/full)
345
+ if (flags.hydration === false && /\/hydration$/.test(id)) {
346
+ const resolved = await resolve(id, importer)
347
+ if (/features[/\\]hydration[/\\]index\.(ts|js)$/.test(resolved)) {
348
+ return resolved.replace(/index\.(ts|js)$/, 'stub.$1')
349
+ }
350
+ }
351
+ ```
352
+
353
+ Real implementation: [packages/redact/src/vite/index.ts](packages/redact/src/vite/index.ts).
354
+
355
+ ### Verifying your setup
356
+
357
+ Whichever path you choose, check that stubbed features' full code isn't in your output. Use your bundler's analyzer (rollup-plugin-visualizer, Webpack's bundle-analyzer, etc.) and search for `features/<name>/full.js`. With `hydration: false`, you should NOT see `features/hydration/full.js` or its imports (cursor machinery, event-replay, scroll-guard).
358
+
359
+ ---
360
+
361
+ ## Scope
362
+
363
+ ### Supported
364
+
365
+ - React 19 element model, JSX (classic + automatic), Fragment, Suspense, Portal, Error boundaries, forwardRef, memo, lazy
366
+ - Full hook surface: `useState`, `useReducer`, `useEffect`, `useLayoutEffect`, `useInsertionEffect`, `useMemo`, `useCallback`, `useRef`, `useContext`, `useSyncExternalStore`, `useId`, `useDeferredValue`, `useTransition`, `use` (Context + Promise), `useEffectEvent`
367
+ - Class components with full lifecycle (`componentDidMount`/`componentDidUpdate`/`componentWillUnmount`, `contextType`, `shouldComponentUpdate`, `getDerivedStateFromError`, `componentDidCatch`, legacy lifecycles as no-ops)
368
+ - SSR via `renderToString` / `renderToReadableStream` / `renderToPipeableStream` — including Suspense boundary streaming with `$RC` reveal + event replay
369
+ - Hydration: SSR DOM adoption, deferred hydration for `use(promise)` / lazy, cursor preservation across the synchronous `endHydration`
370
+ - Cohabitation with `@vitejs/plugin-rsc`: the Vite plugin deliberately skips the RSC environment so Flight serialization stays on real `react-server-dom`
371
+
372
+ ### Best-effort / subset behavior
373
+
374
+ - `useTransition` / `useDeferredValue` run synchronously — no priority scheduling
375
+ - Scheduler shim is a no-op wrapper around microtasks
376
+ - No time slicing, no lane-based work interruption
377
+
378
+ ### Out of scope
379
+
380
+ - `react-server-dom-*/client` Flight deserializer (TanStack Start uses its own seroval-based codec + `@vitejs/plugin-rsc`)
381
+ - React DevTools protocol
382
+ - Behavioral 1:1 parity with React under concurrent-mode stress
383
+
384
+ See [docs/SURFACE.md](./docs/SURFACE.md) for the full React-19 export-by-export audit.
385
+
386
+ ---
387
+
388
+ ## Performance
389
+
390
+ Measured against TanStack Router + TanStack Start benchmarks (`pnpm nx run @benchmarks/client-nav:test:perf:react`, `@benchmarks/ssr:test:perf:react`):
391
+
392
+ | Bench | Real React | This shim | Ratio |
393
+ |---|---:|---:|---:|
394
+ | `client-nav` (router-driven navigation loop) | 34.9 hz | **78.1 hz** | **2.24× faster** |
395
+ | `ssr` (request loop) | ~48 hz | **168 hz** | **~3× faster**[^1] |
396
+
397
+ [^1]: SSR speedup requires a latent `stringifyValue` bug in `@tanstack/router-core` to be patched (exception-throwing in a hot loop was eating 34% of request time regardless of renderer — see `scripts/repro-router-hang.mjs`).
398
+
399
+ On tanstack.com (full site, not just renderer): Lighthouse perf scores at parity with stock React, consistent FCP wins across desktop/mobile, mild LCP regression on RSC-heavy pages (tied to the shim's Flight-deserialize suspend/resume), CLS/TBT ≈ 0. Full 30-run median breakdown: [tanstack.com/docs/perf/lighthouse-shim-vs-react-2026-04-20.md](https://github.com/TanStack/tanstack.com/blob/main/docs/perf/lighthouse-shim-vs-react-2026-04-20.md).
400
+
401
+ ---
402
+
403
+ ## Development
404
+
405
+ ### Layout
406
+
407
+ One package, one tree, internal subdirectories per concern:
408
+
409
+ ```
410
+ packages/redact/src/
411
+ core/ VDOM types + symbols (FiberTag, Hook, ReactNode, …)
412
+ react/ 'react' entry: createElement, hooks, context, class,
413
+ memo, suspense, jsx-runtime, ReactSharedInternals
414
+ dom/ 'react-dom' entry: reconciler, host DOM, root,
415
+ createPortal, flushSync
416
+ features/ opt-in features (each is an index/full/stub triple)
417
+ portal/ context/ suspense/ memo/
418
+ forward-ref/ lazy/ class/ hydration/
419
+ server/ 'react-dom/server' entry: renderToString,
420
+ renderToReadableStream, renderToPipeableStream
421
+ scheduler/ 'scheduler' shim (no-op microtask wrapper)
422
+ vite/ redact() Vite plugin: aliases + feature-flag swaps
423
+ tests/ vitest suite — 707 tests
424
+ examples/
425
+ ssr-demo/ full SSR + Suspense streaming smoke app
426
+ docs/
427
+ SURFACE.md React 19 export audit
428
+ SAVINGS_ANALYSIS.md per-export size savings vs React 19
429
+ scripts/
430
+ build.mjs per-entry esbuild build (every TS module emitted)
431
+ size.mjs per-preset / per-flag gzip report
432
+ size-check.mjs CI size-budget assertions
433
+ size-analyze.mjs per-module byte breakdown for a given preset
434
+ ```
435
+
436
+ Cross-subdir imports inside `packages/redact/src/` use relative paths
437
+ (`../core`, `../react`, etc.). The build emits each TS module as its own
438
+ dist file with all relative imports kept literal — that's what preserves the
439
+ import-graph boundaries the Vite plugin needs to swap features at consumer
440
+ build time.
441
+
442
+ ### Commands
443
+
444
+ ```bash
445
+ pnpm install
446
+ pnpm build # esbuild dist/ + tsc declaration emit
447
+ pnpm test # vitest suite (707 tests)
448
+ pnpm test:types # tsc --noEmit
449
+ pnpm size # gzip/brotli per entry + per feature-stub
450
+ pnpm size:check # CI budget assertions (fails on regression)
451
+ pnpm --filter ssr-demo dev # serve http://localhost:5173
452
+ ```
453
+
454
+ ### Current sizes
455
+
456
+ Subpath sizes from `pnpm size`. The `react` / `react-dom/client` / `react-dom/server` column names are the user-facing aliases the Vite plugin sets up; under the hood they all resolve into `@tanstack/redact/*`.
457
+
458
+ | Entry | min | gzip | brotli |
459
+ |---|---:|---:|---:|
460
+ | `react` (= `@tanstack/redact`) | 6.59 KB | 2.65 KB | 2.41 KB |
461
+ | `react/jsx-runtime` (= `@tanstack/redact/jsx-runtime`) | 247 B | 189 B | 178 B |
462
+ | `react-dom/client` (= `@tanstack/redact/dom-client`, `full`) | 26.56 KB | **9.07 KB** | 8.21 KB |
463
+ | `react-dom/client` (= `@tanstack/redact/dom-client`, `nano`) | 18.75 KB | **6.75 KB** | 6.10 KB |
464
+ | `react-dom/server` (= `@tanstack/redact/server`) | 11.48 KB | 4.59 KB | 4.16 KB |
465
+ | **Client total** (`full`: react + react-dom/client + jsx-runtime) | 32.63 KB | **11.18 KB** | 10.14 KB |
466
+
467
+ Regenerate with `pnpm size`.
468
+
469
+ ---
470
+
471
+ ## Changelog
472
+
473
+ The project's first 9 alpha versions shipped as separate `@tanstack/react`, `@tanstack/react-dom`, `@tanstack/react-dom-server`, `@tanstack/dom-core`, `@tanstack/scheduler`, and `@tanstack/dom-vite` packages (`0.1.0-alpha.0` … `0.1.0-alpha.9`). Those packages are now deprecated. The project starts fresh as a single `@tanstack/redact` (`0.0.1`+) with subpath exports — the fixes below predate the rename and the package names refer to the previous multi-package layout.
474
+
475
+ - `@tanstack/redact@0.0.1` — **first release of `@tanstack/redact`**. Consolidates the 6 previously-separate alpha packages into a single package with subpath exports (`./jsx-runtime`, `./dom`, `./dom-client`, `./dom-test-utils`, `./server`, `./scheduler`, `./vite`, `./features/*`, `./_all`). Vite plugin renamed `tanstackDom()` → `redact()`, types `TanStackDom*` → `Redact*`. `ReactSharedInternals` made a `globalThis`-stashed singleton via `Symbol.for` to defend against duplicate package copies under bundlers like Cloudflare's `vite-plugin` that mix `noExternal: true` worker bundling with separate pre-bundled dep copies. New `tests/public-exports.test.ts` snapshot guards every subpath's named-export set against silent link-time drift.
476
+ - `react@0.1.0-alpha.8` — added `useEffectEvent` hook (stable callback over a `useInsertionEffect`-refreshed ref). Fixes missing-export errors in consumers using React 19 event handlers.
477
+ - `react-dom@0.1.0-alpha.8` — **feature-flag system landed**: 8 opt-in features with stub/full pairs, typed Vite plugin config, `pnpm size:check` CI budget enforcement. `nano` preset ships **6.75 KB gzip** — a 26% reduction from `full`.
478
+ - `react-dom@0.1.0-alpha.5` — `useEffect` / `useLayoutEffect` cleanup now runs at effect-run time (in the passive drain) instead of dispatch time. Coalesced renders landing back-to-back before the drain (common with router/store state updates triggered by one user action) no longer leak side-effects into the DOM.
479
+ - `react-dom@0.1.0-alpha.4` — `renderFunction`'s deferred-hydration branch now matches `renderLazy`'s ancestor-Suspense guard (`_awaitingLazyHydration`). Fixes duplicate markup on RSC-hydrated subtrees.
480
+ - `react-dom-server@0.1.0-alpha.4` — shell + bootstrap emits are buffered into one `TextEncoder.encode` + `ReadableStream.enqueue` instead of per-chunk, cutting Node stream overhead in the SSR CPU profile.
481
+ </content>
@@ -287,7 +287,20 @@ function reconcileChildren(parent, newChildren, domParent, anchor) {
287
287
  if (prevNewFiber) prevNewFiber.sibling = fiber;
288
288
  else parent.child = fiber;
289
289
  prevNewFiber = fiber;
290
- renderFiber(fiber, domParent, anchor);
290
+ }
291
+ const hydrating = !!currentRoot?.hydrating;
292
+ for (let f = parent.child; f; f = f.sibling) {
293
+ let a = anchor;
294
+ if (!hydrating) {
295
+ for (let s = f.sibling; s; s = s.sibling) {
296
+ const d = firstDomNode(s);
297
+ if (d && d.parentNode === domParent) {
298
+ a = d;
299
+ break;
300
+ }
301
+ }
302
+ }
303
+ renderFiber(f, domParent, a);
291
304
  }
292
305
  if (!prevNewFiber) parent.child = null;
293
306
  else prevNewFiber.sibling = null;
@@ -328,6 +341,13 @@ function placeChildrenInOrder(parent, domParent, anchor) {
328
341
  }
329
342
  if (current !== doms[i]) inOrder = false;
330
343
  }
344
+ if (inOrder) {
345
+ let last = doms[doms.length - 1].nextSibling;
346
+ while (last && !doms.includes(last) && last !== anchor) {
347
+ last = last.nextSibling;
348
+ }
349
+ if (last !== anchor) inOrder = false;
350
+ }
331
351
  if (inOrder) return;
332
352
  }
333
353
  for (let i = doms.length - 1; i >= 0; i--) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/dom/reconcile.ts"],
4
- "sourcesContent": ["import {\n FiberTag,\n FiberFlag,\n createFiber,\n REACT_ELEMENT_TYPE,\n REACT_LEGACY_ELEMENT_TYPE,\n REACT_FRAGMENT_TYPE,\n type Fiber,\n type FiberRoot,\n type ReactElement,\n type ReactNode,\n type Hook,\n type Effect,\n} from '../core'\nimport {\n ReactSharedInternals,\n REACT_LAZY_TYPE,\n REACT_STRICT_MODE_TYPE,\n REACT_PROFILER_TYPE,\n} from '../react'\nimport { createHostNode, setProp } from './dom'\nimport { makeDispatcher } from './dispatcher'\nimport {\n adoptHostDom,\n adoptTextDom,\n tryConsumeBoundary,\n advanceCursorPast,\n setHydrationCursor,\n getHydrationCursor,\n clearHydrationCursor,\n HydrationCursor,\n findHostParent as findHydrationHost,\n} from './features/hydration'\n\n// ---------------------------------------------------------------------------\n// Render scheduling\n// ---------------------------------------------------------------------------\n\nlet currentRoot: FiberRoot | null = null\nlet flushing = false\nlet isBatching = false\nconst pendingRoots = new Set<FiberRoot>()\n\n// Set by rerenderFiber to identify the exact memo-tagged fiber whose INTERNAL\n// state (hook update, useSyncExternalStore notification) triggered this render\n// pass. renderMemo checks this to bypass its prop-equality gate for that fiber.\n// Without the bypass, a memo bail would swallow state changes: React's memo is\n// only a parent-triggered gate \u2014 state-driven rerenders must always run the\n// inner function. Router-adjacent components (Outlet, Match, MatchInner) are\n// all memo-wrapped and subscribe to stores; missing this bypass breaks nav\n// content updates even though the URL changes.\nlet forceRerenderingFiber: Fiber | null = null\n\nexport function scheduleUpdate(fiber: Fiber): void {\n // Drop updates scheduled on already-unmounted fibers. Subscribers (router,\n // query, any external store) can fire after unmount if their cleanup was\n // missed, and letting those reach rerenderFiber mounts zombie DOM into the\n // old .parent's DOM (which stays reachable via the stale pointer).\n if (fiber.unmounted) return\n const root = findRoot(fiber)\n if (!root) return\n root.pending.add(fiber)\n fiber.dirty = true\n pendingRoots.add(root)\n if (isBatching) return\n if (!root.scheduled) {\n root.scheduled = true\n queueMicrotask(flushPending)\n }\n}\n\nexport function flushSyncWork(fn: () => void): void {\n const wasBatching = isBatching\n isBatching = true\n try {\n fn()\n } finally {\n isBatching = wasBatching\n }\n flushPending()\n}\n\nexport function batchedUpdates<T>(fn: () => T): T {\n const wasBatching = isBatching\n isBatching = true\n try {\n return fn()\n } finally {\n isBatching = wasBatching\n if (!wasBatching) flushPending()\n }\n}\n\nfunction flushPending(): void {\n if (flushing) return\n flushing = true\n try {\n let guard = 0\n while (pendingRoots.size > 0) {\n if (++guard > 50) {\n throw new Error('flushPending exceeded 50 iterations \u2014 suspected infinite update loop.')\n }\n const roots = [...pendingRoots]\n pendingRoots.clear()\n for (const root of roots) {\n root.scheduled = false\n // Render each pending fiber from shallowest first so an ancestor's\n // cascade reaches descendants before we try to render them directly.\n // Descendants rendered via cascade still have `dirty=true` (only\n // rerenderFiber clears it); when we later reach them in this loop,\n // rerenderFiber's own `if (!dirty) return` is our short-circuit. We\n // previously filtered descendants of dirty ancestors here, but that\n // loses updates whenever an ancestor's render doesn't actually reach\n // the descendant \u2014 e.g. React.memo bailing on equal props. Keep all\n // dirty fibers and let rerenderFiber de-dupe via its dirty check.\n const pending = [...root.pending]\n root.pending.clear()\n pending.sort((a, b) => fiberDepth(a) - fiberDepth(b))\n for (const fiber of pending) {\n rerenderFiber(fiber, root)\n }\n runEffects(root)\n }\n }\n } finally {\n flushing = false\n }\n}\n\nfunction fiberDepth(fiber: Fiber): number {\n let d = 0\n let p: Fiber | null = fiber.parent\n while (p) {\n d++\n p = p.parent\n }\n return d\n}\n\nexport function findRoot(fiber: Fiber): FiberRoot | null {\n let f: Fiber | null = fiber\n while (f) {\n if (f.root) return f.root\n f = f.parent\n }\n return null\n}\n\n// ---------------------------------------------------------------------------\n// Entry points (called by createRoot)\n// ---------------------------------------------------------------------------\n\nexport function renderRoot(root: FiberRoot, children: ReactNode): void {\n const rootFiber = root.current\n rootFiber.pendingProps = { children }\n currentRoot = root\n try {\n reconcileChildren(rootFiber, childrenToArray(children), root.container as Node, null)\n rootFiber.memoizedProps = rootFiber.pendingProps\n rootFiber.dirty = false\n } finally {\n currentRoot = null\n }\n runEffects(root)\n}\n\nfunction rerenderFiber(fiber: Fiber, root: FiberRoot): void {\n if (!fiber.dirty) return\n // Skip fibers that were unmounted between scheduling and flush. Without this,\n // the flush loop re-enters a zombie fiber whose .parent is still set; its\n // render mounts fresh DOM into the old parent's still-attached DOM (since\n // unmountFiber only clears fiber.child, not fiber.parent). Visible as route\n // content from a previous location staying on screen after nav, because a\n // pending rerender on the old route's LibraryLandingPage (unmounted during\n // Outlet's shallow-first render) still fires from root.pending.\n if (fiber.unmounted) return\n // Clear BEFORE rendering so a scheduleUpdate() triggered mid-render (e.g.\n // error boundary catching a descendant throw) marks us dirty for the next\n // flush iteration instead of being wiped out when render() completes.\n fiber.dirty = false\n currentRoot = root\n // If this rerender is resuming a hydration that was deferred by a suspension,\n // re-activate hydration mode for its duration so descendants adopt DOM\n // instead of re-creating it.\n const resumeHydration =\n fiber.memoizedState && (fiber.memoizedState as any)._pendingHydration === true\n const prevHydrating = root.hydrating\n if (resumeHydration) {\n delete (fiber.memoizedState as any)._pendingHydration\n root.hydrating = true\n }\n const prevForcing = forceRerenderingFiber\n forceRerenderingFiber = fiber\n try {\n renderFiber(fiber, getHostParent(fiber), getAnchor(fiber))\n } finally {\n forceRerenderingFiber = prevForcing\n if (resumeHydration) {\n root.hydrating = prevHydrating\n // Deferred hydration completed \u2014 detach the preserved cursor so future\n // updates (post-hydration state changes) don't try to adopt stale DOM.\n clearHydrationCursor(fiber)\n }\n currentRoot = null\n }\n}\n\n// ---------------------------------------------------------------------------\n// Element \u2192 children normalization\n// ---------------------------------------------------------------------------\n\ntype TextChild = { _text: string }\ntype NormalizedChild = ReactElement | TextChild | null\n\n// NEVER use `'_text' in child` to distinguish text wrappers from elements.\n// TanStack's RSC renderable proxies (createRscProxy with renderable: true) are\n// Proxy wrappers around real React elements whose `has` trap returns `true`\n// for ANY string key \u2014 so `'_text' in rscProxy` is TRUE even though the proxy\n// is an element. That misidentification set a Text fiber's `pendingProps` to\n// `child._text` (another chained RSC proxy), which then rendered as\n// `[object Object]` when createTextNode stringified the element. React\n// elements always carry `$$typeof`; our text wrapper never does \u2014 so the\n// presence of `$$typeof` is the invariant we rely on.\nfunction isTextChild(child: Exclude<NormalizedChild, null>): child is TextChild {\n return (child as any).$$typeof === undefined\n}\n\nexport function childrenToArray(children: ReactNode): NormalizedChild[] {\n const out: NormalizedChild[] = []\n pushChildren(children, out)\n return out\n}\n\nfunction pushChildren(node: ReactNode, out: NormalizedChild[]): void {\n if (node == null || typeof node === 'boolean') return\n if (typeof node === 'string' || typeof node === 'number') {\n // Empty strings render no text node (matches React + the `<!-- -->`\n // separator elision on the SSR side so server/client agree).\n if (node === '') return\n out.push({ _text: '' + node })\n return\n }\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) pushChildren(node[i], out)\n return\n }\n if (isIterable(node)) {\n for (const item of node as Iterable<ReactNode>) pushChildren(item, out)\n return\n }\n if (typeof node === 'object') {\n const t = (node as any).$$typeof\n if (ACCEPTED_ELEMENT_MARKERS.has(t)) {\n out.push(node as ReactElement)\n return\n }\n // Raw React.lazy as a child. RSC Flight encodes 'use client' components\n // (CodeBlock, CodeExplorer, etc.) as bare Lazy objects in the tree, not\n // wrapped in REACT_ELEMENT_TYPE. Dropping them made code snippets\n // disappear from docs pages. The RSC decoder pre-awaits payloads via\n // `awaitLazyElements`, so by render time the status is 'fulfilled' and\n // `_init()` returns the resolved element synchronously.\n if (t === REACT_LAZY_TYPE) {\n const lazy = node as any\n const resolved = lazy._init(lazy._payload)\n pushChildren(resolved, out)\n return\n }\n }\n}\n\nfunction isIterable(obj: any): boolean {\n return obj != null && typeof obj !== 'string' && typeof obj[Symbol.iterator] === 'function'\n}\n\nfunction getKeyOf(child: NormalizedChild, index: number): string {\n if (!child) return 'n' + index\n if (isTextChild(child)) return '$t' + index\n if (child.key != null) return 'k' + child.key\n return 'i' + index\n}\n\nfunction sameType(fiber: Fiber, child: NormalizedChild): boolean {\n if (!child) return false\n if (isTextChild(child)) return fiber.tag === FiberTag.Text\n return fiber.type === child.type && sameKey(fiber.key, child.key)\n}\n\nfunction sameKey(a: string | null, b: string | null | undefined): boolean {\n return (a ?? null) === (b ?? null)\n}\n\n// ---------------------------------------------------------------------------\n// Fiber creation\n// ---------------------------------------------------------------------------\n\nfunction fiberFromChild(child: NormalizedChild, parent: Fiber): Fiber {\n if (!child) return createFiber(FiberTag.Fragment, null, null)\n if (isTextChild(child)) {\n const f = createFiber(FiberTag.Text, null, null)\n f.pendingProps = child._text\n f.parent = parent\n return f\n }\n const type = child.type\n let tag: FiberTag = FiberTag.Host\n const marker = type && (type as any).$$typeof\n if (typeof type === 'string') tag = FiberTag.Host\n else if (type === REACT_FRAGMENT_TYPE) tag = FiberTag.Fragment\n else if (type === REACT_STRICT_MODE_TYPE || type === REACT_PROFILER_TYPE) tag = FiberTag.Fragment\n else {\n // Feature-registered type matchers (Portal, future extractions). Features\n // that carry the symbol as element.type directly (rather than wrapping in\n // REACT_ELEMENT_TYPE) match here by type identity.\n let matched: FiberTag | null = null\n for (const m of TYPE_MATCHERS) {\n matched = m(type, marker)\n if (matched !== null) break\n }\n if (matched !== null) tag = matched\n else if (typeof type === 'function') {\n tag = type.prototype && type.prototype.isReactComponent ? FiberTag.Class : FiberTag.Function\n }\n }\n const f = createFiber(tag, type, child.key ?? null)\n f.ref = (child as any).ref ?? null\n f.pendingProps = child.props\n f.parent = parent\n return f\n}\n\n// ---------------------------------------------------------------------------\n// Reconciliation\n// ---------------------------------------------------------------------------\n\n/**\n * Reconcile a parent fiber's child list against new normalized children.\n * Mutates parent.child and the sibling chain.\n * Mounts new host DOM into `domParent` before `anchor` (or appends if anchor === null).\n */\nexport function reconcileChildren(\n parent: Fiber,\n newChildren: NormalizedChild[],\n domParent: Node,\n anchor: Node | null,\n): void {\n const existing = collectChildren(parent)\n const keyed = new Map<string, Fiber>()\n for (const f of existing) {\n if (f.key != null) keyed.set('k' + f.key, f)\n }\n\n let prevNewFiber: Fiber | null = null\n const claimed = new Set<Fiber>()\n let structurallyChanged = false\n // Budget-guided positional matching. We walk `existing` (unkeyed only) with a\n // single cursor `existingIdx` and, on a type mismatch, choose insert vs delete\n // based on the remaining length delta (`budget`):\n // budget > 0: more new than old remain \u2192 treat slot as an INSERTION: keep\n // the old cursor and create a fresh fiber for new[i].\n // budget < 0: more old than new remain \u2192 treat slot as a DELETION: advance\n // the old cursor past the mismatched fiber (it'll be unmounted\n // in the unclaimed pass) and retry.\n // budget == 0: equal remaining \u2192 treat as REPLACE by preferring delete\n // until budget flips positive or we hit a match.\n // This avoids greedy forward scans that steal a later same-type fiber for a\n // newly inserted leading sibling (e.g. smallMenu flipping null \u2192 <div>\n // stealing the content <div>'s fiber and tearing down the drawer fragment).\n let existingIdx = 0\n let unkeyedOld = 0\n for (const f of existing) if (f.key == null) unkeyedOld++\n let unkeyedNew = 0\n for (const c of newChildren) if (c != null) unkeyedNew++\n let budget = unkeyedNew - unkeyedOld\n\n for (let i = 0; i < newChildren.length; i++) {\n const child = newChildren[i]\n if (child == null) continue\n\n let match: Fiber | null = null\n\n // key-based match\n if (child && typeof child === 'object' && !isTextChild(child) && (child as ReactElement).key != null) {\n const k = 'k' + (child as ReactElement).key\n const m = keyed.get(k)\n if (m && m.type === (child as ReactElement).type) {\n match = m\n keyed.delete(k)\n }\n }\n\n if (!match) {\n while (existingIdx < existing.length) {\n const cand = existing[existingIdx]!\n if (claimed.has(cand) || cand.key != null) {\n existingIdx++\n continue\n }\n if (sameType(cand, child)) {\n match = cand\n existingIdx++\n break\n }\n // Type mismatch at the cursor. Resolve via budget.\n if (budget > 0) {\n // Insertion: leave cand in place, create new for child.\n break\n }\n // Deletion (or replace-as-delete-first): advance past cand. It remains\n // unclaimed and will be unmounted at the end.\n existingIdx++\n budget++\n }\n }\n\n // Detect reorder: matched fiber is not at its original position\n if (match && existing[i] !== match) structurallyChanged = true\n\n let fiber: Fiber\n if (match) {\n claimed.add(match)\n fiber = match\n if (isTextChild(child!)) {\n fiber.pendingProps = child._text\n } else {\n fiber.type = (child as ReactElement).type\n fiber.pendingProps = (child as ReactElement).props\n fiber.ref = (child as any).ref ?? null\n }\n } else {\n fiber = fiberFromChild(child, parent)\n structurallyChanged = true\n if (budget > 0) budget--\n }\n\n fiber.parent = parent\n fiber.sibling = null\n if (prevNewFiber) prevNewFiber.sibling = fiber\n else parent.child = fiber\n prevNewFiber = fiber\n\n // Render this fiber (mount or update)\n renderFiber(fiber, domParent, anchor)\n }\n\n if (!prevNewFiber) parent.child = null\n else prevNewFiber.sibling = null\n\n // Head content is additive \u2014 server may inject metadata/stylesheets (Vite\n // dev styles, Sentry, analytics) that aren't in the React tree. Unmounting\n // them on every reconcile thrashes styles and causes flash of unstyled\n // content. Keep existing head children that weren't matched this pass.\n const parentIsHeadHost =\n parent.tag === FiberTag.Host &&\n typeof parent.type === 'string' &&\n (parent.type as string).toLowerCase() === 'head'\n\n if (!parentIsHeadHost) {\n // Unmount unclaimed\n for (const f of existing) {\n if (!claimed.has(f)) {\n unmountFiber(f, domParent)\n structurallyChanged = true\n }\n }\n // Leftover keyed\n for (const f of keyed.values()) {\n if (!claimed.has(f)) {\n unmountFiber(f, domParent)\n structurallyChanged = true\n }\n }\n }\n\n // During hydration, DOM is already in document order from the cursor-driven\n // adoption walk. Running placeChildrenInOrder here would reappend nodes to\n // the end of domParent when the true anchor (often an end marker comment)\n // isn't reflected in `anchor`. Skip it in hydration mode.\n //\n // For <head>, skip always \u2014 HeadContent re-renders routinely (route match\n // changes, providers updating), and reordering every <link>/<style>/<meta>\n // on each re-render causes stylesheet flash and re-download. Head element\n // ordering is semantically fluid; the browser doesn't care about exact\n // order within <head>.\n const parentIsHead =\n (domParent as Element).nodeType === 1 &&\n (domParent as Element).tagName.toLowerCase() === 'head'\n if (structurallyChanged && !currentRoot?.hydrating && !parentIsHead) {\n placeChildrenInOrder(parent, domParent, anchor)\n }\n}\n\nfunction placeChildrenInOrder(parent: Fiber, domParent: Node, anchor: Node | null): void {\n const doms: Node[] = []\n let c = parent.child\n while (c) {\n collectHostDoms(c, doms)\n c = c.sibling\n }\n\n // Pre-check: if our fiber-owned DOM is already in document order within\n // domParent AND the end anchor matches, no reorder is needed. This is the\n // common case on stable re-renders, and avoids detaching/re-attaching\n // subtrees (which cancels CSS animations and triggers layout).\n if (doms.length > 0) {\n let current: Node | null = doms[0]!\n let inOrder = current.parentNode === domParent\n for (let i = 1; inOrder && i < doms.length; i++) {\n current = current!.nextSibling\n // Skip foreign nodes (SSR-injected scripts, dev-styles) between owned\n // fiber DOMs \u2014 they should stay where they are.\n while (current && !doms.includes(current as Node)) {\n current = current.nextSibling\n }\n if (current !== doms[i]) inOrder = false\n }\n if (inOrder) return\n }\n\n // Reverse-iterate, anchoring each node before the one that should follow it.\n // This works because by the time we're placing doms[i], doms[i+1] is already\n // in its final slot. Forward iteration is buggy: insertBefore(doms[i],\n // doms[i+1]) pulls doms[i] forward past any nodes that SHOULD move behind\n // it, leaving those nodes mis-anchored (app-starter Analyze/Lucky swap, npm\n // stats library dropdown reorder \u2014 both reported by users).\n //\n // Concrete example: start=[A, R, L], target=[A, L, R]. Forward pass gives\n // [L, A, R] (wrong). Reverse pass moves R to end, then L and A are already\n // correct \u2014 1 move, matches target.\n //\n // Skip nodes already in their target position so CSS transitions on stable\n // siblings aren't cancelled (e.g. drawer slide animation).\n for (let i = doms.length - 1; i >= 0; i--) {\n const d = doms[i]!\n const targetNext: Node | null = i + 1 < doms.length ? doms[i + 1]! : anchor\n if (d.parentNode !== domParent || d.nextSibling !== targetNext) {\n domParent.insertBefore(d, targetNext)\n }\n }\n}\n\nfunction collectHostDoms(fiber: Fiber, out: Node[]): void {\n if (fiber.tag === FiberTag.Host || fiber.tag === FiberTag.Text) {\n if (fiber.dom) out.push(fiber.dom)\n return\n }\n if (fiber.tag === FiberTag.Portal) return\n let c = fiber.child\n while (c) {\n collectHostDoms(c, out)\n c = c.sibling\n }\n}\n\nfunction collectChildren(parent: Fiber): Fiber[] {\n const out: Fiber[] = []\n let c = parent.child\n while (c) {\n out.push(c)\n c = c.sibling\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Rendering per fiber tag\n// ---------------------------------------------------------------------------\n\nexport type RenderFn = (fiber: Fiber, domParent: Node, anchor: Node | null) => void\nexport type TypeMatcher = (type: any, marker: any) => FiberTag | null\n\n// Mutable renderer registry indexed by FiberTag. Feature modules install their\n// renderer via registerRenderer(); unregistered features render as no-ops. The\n// initial registrations below rely on function-declaration hoisting \u2014 every\n// render* function is declared with `function` later in this file.\nconst RENDERERS: Array<RenderFn | undefined> = new Array(13)\n\n// Element-marker allowlist for child normalization (pushChildren). Core-always\n// markers are seeded here; features add their own via registerElementMarker.\nconst ACCEPTED_ELEMENT_MARKERS = new Set<symbol>([\n REACT_ELEMENT_TYPE as symbol,\n REACT_LEGACY_ELEMENT_TYPE as symbol,\n])\n\n// Type-to-tag matchers tried in registration order from fiberFromChild's\n// fallback branch. Features register here for element types that aren't\n// marker-based (e.g. Portal, where element.type IS the symbol).\nconst TYPE_MATCHERS: TypeMatcher[] = []\n\nexport function registerRenderer(tag: FiberTag, fn: RenderFn): void {\n RENDERERS[tag] = fn\n}\n\nexport function registerTypeMatcher(m: TypeMatcher): void {\n TYPE_MATCHERS.push(m)\n}\n\nexport function registerElementMarker(sym: symbol): void {\n ACCEPTED_ELEMENT_MARKERS.add(sym)\n}\n\n// Accessor + scoped setter for the module-level `currentRoot`. Feature modules\n// need these to participate in the render loop (e.g. Suspense re-hydration\n// must temporarily set the root while rebuilding a boundary subtree).\nexport function getCurrentRoot(): FiberRoot | null {\n return currentRoot\n}\n\nexport function withCurrentRoot<T>(root: FiberRoot | null, fn: () => T): T {\n const prev = currentRoot\n currentRoot = root\n try {\n return fn()\n } finally {\n currentRoot = prev\n }\n}\n\n// The memo feature uses this to bypass its prop-equality gate on state-driven\n// rerenders of the memoized fiber itself (hook update / subscribed store),\n// where props haven't changed by definition.\nexport function getForceRerenderingFiber(): Fiber | null {\n return forceRerenderingFiber\n}\n\nregisterRenderer(FiberTag.Text, renderText)\nregisterRenderer(FiberTag.Host, renderHost)\nregisterRenderer(FiberTag.Function, renderFunction)\nregisterRenderer(FiberTag.Fragment, renderFragment)\n\nexport function renderFiber(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const fn = RENDERERS[fiber.tag]\n if (fn) fn(fiber, domParent, anchor)\n}\n\nfunction renderText(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const text = fiber.pendingProps as string\n if (!fiber.dom) {\n const hydrated = currentRoot?.hydrating ? adoptTextDom(fiber, fiber.parent!, text) : false\n if (!hydrated) {\n fiber.dom = document.createTextNode(text)\n insertInto(domParent, fiber.dom, anchor)\n }\n } else if ((fiber.dom as Text).data !== text) {\n ;(fiber.dom as Text).data = text\n }\n fiber.memoizedProps = text\n // dirty cleared at rerender start; leaving true lets mid-render schedule persist\n}\n\nfunction renderHost(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const props = fiber.pendingProps ?? {}\n const prev = fiber.memoizedProps ?? {}\n const type = fiber.type as string\n const isSvg = type === 'svg' || (domParent as Element).namespaceURI === 'http://www.w3.org/2000/svg'\n\n // <select value> must be applied AFTER children mount \u2014 setting `.value`\n // on a `<select>` with no matching `<option>` yet resets it to empty. Same\n // for `defaultValue` on first mount. Stash and replay.\n const isSelect = type === 'select'\n const deferredSelectValue =\n isSelect && (props.value !== undefined || props.defaultValue !== undefined)\n ? props.value !== undefined ? props.value : props.defaultValue\n : undefined\n\n if (!fiber.dom) {\n const hydrated = currentRoot?.hydrating ? adoptHostDom(fiber, fiber.parent!) : false\n if (!hydrated) {\n fiber.dom = createHostNode(type, isSvg)\n // Two passes so form-control attributes (notably <input type>) are in\n // place before event handlers attach. setEventHandler reads the\n // element's runtime state to decide the DOM event name (e.g. onChange\n // \u2192 `input` vs `change`); binding before `type` is applied would\n // attach to the wrong event for checkbox/radio/file inputs.\n for (const k in props) {\n if (isSelect && (k === 'value' || k === 'defaultValue')) continue\n if (isEventProp(k)) continue\n setProp(fiber.dom as Element, k, props[k], undefined, isSvg)\n }\n for (const k in props) {\n if (!isEventProp(k)) continue\n setProp(fiber.dom as Element, k, props[k], undefined, isSvg)\n }\n insertInto(domParent, fiber.dom, anchor)\n }\n attachRef(fiber, fiber.dom)\n } else {\n const el = fiber.dom as Element\n for (const k in prev) {\n if (!(k in props)) setProp(el, k, undefined, prev[k], isSvg)\n }\n // Non-event props first for the same reason as above: a `type` change\n // must land before we ask setEventHandler to resolve the DOM event for\n // `onChange`.\n for (const k in props) {\n if (isSelect && (k === 'value' || k === 'defaultValue')) continue\n if (isEventProp(k)) continue\n if (prev[k] !== props[k]) setProp(el, k, props[k], prev[k], isSvg)\n }\n for (const k in props) {\n if (!isEventProp(k)) continue\n if (prev[k] !== props[k]) setProp(el, k, props[k], prev[k], isSvg)\n }\n if (prev !== props) syncRefIfChanged(fiber, fiber.dom)\n }\n\n // Children go into this DOM node\n reconcileChildren(fiber, childrenToArray(props.children), fiber.dom!, null)\n\n // During hydration, if after reconciling all client-expected children we\n // still have server DOM left in the cursor for this host, that's a\n // structural mismatch (server produced more than client wants). Report.\n // <head>/<html> are position-insensitive \u2014 leftover here is normal\n // (Vite dev-style injections, SSR-only scripts, etc.).\n if (currentRoot?.hydrating) {\n const parentTag = (fiber.type as string).toLowerCase()\n if (parentTag !== 'head' && parentTag !== 'html') {\n const cursor = getHydrationCursor(fiber)\n if (cursor) {\n const leftover = cursor.remaining().filter(\n (n) => n.nodeType === 1 || n.nodeType === 3,\n )\n if (leftover.length > 0 && currentRoot.onRecoverableError) {\n currentRoot.onRecoverableError(\n new Error(\n `Hydration mismatch: server rendered ${leftover.length} extra ` +\n `${leftover.length === 1 ? 'node' : 'nodes'} inside <${parentTag}> ` +\n `that the client tree did not.`,\n ),\n )\n for (const n of leftover) n.parentNode?.removeChild(n)\n }\n }\n }\n }\n\n // Apply <select> value after options are mounted.\n if (isSelect && deferredSelectValue !== undefined) {\n const select = fiber.dom as HTMLSelectElement\n if (Array.isArray(deferredSelectValue)) {\n const asStrings = deferredSelectValue.map((v) => '' + v)\n for (const opt of Array.from(select.options)) {\n opt.selected = asStrings.includes(opt.value)\n }\n } else {\n select.value = '' + deferredSelectValue\n }\n }\n\n fiber.memoizedProps = props\n // dirty cleared at rerender start; leaving true lets mid-render schedule persist\n}\n\nfunction renderFunction(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const prevDispatcher = ReactSharedInternals.H\n const prevFiber = ReactSharedInternals.currentFiber\n const prevHook = ReactSharedInternals.currentHook\n const prevIndex = ReactSharedInternals.hookIndex\n\n ReactSharedInternals.H = makeDispatcher()\n ReactSharedInternals.currentFiber = fiber\n ReactSharedInternals.currentHook = null\n ReactSharedInternals.hookIndex = 0\n\n let rendered: ReactNode\n let deferredForHydration = false\n try {\n rendered = (fiber.type as Function)(fiber.pendingProps ?? {})\n } catch (e: any) {\n if (isThenable(e)) {\n if (currentRoot?.hydrating) {\n // Suspension during initial hydration. Leave the existing DOM alone\n // and preserve the in-scope hydration cursor on THIS fiber so it\n // survives the synchronous endHydration() that fires when the initial\n // hydrateRoot() call returns. When the promise settles, the fiber\n // re-renders (see rerenderFiber) with hydration re-activated and its\n // descendants adopt DOM instead of creating new nodes.\n const hostParent = findHydrationHost(fiber)\n const inheritedCursor = getHydrationCursor(hostParent)\n if (inheritedCursor) {\n setHydrationCursor(fiber, inheritedCursor)\n }\n fiber.memoizedState = {\n ...(fiber.memoizedState ?? {}),\n _pendingHydration: true,\n }\n // Mirror renderLazy's guard: mark the nearest Suspense ancestor as\n // awaiting hydration-resume, so any re-render of that Suspense (e.g.\n // rehydrateBoundary fired by $RC, or an unrelated state update from a\n // sibling) doesn't re-enter `tryChildren`, re-throw, and flip Suspense\n // into its suspended+pending path \u2014 which would unmount our deferred\n // subtree and remount a fallback on top of the SSR content. By\n // pinning the Suspense to a \"hydration-suspended\" no-op until our\n // resume fires, the deferred re-render owns the adoption pass.\n let sus: Fiber | null = fiber.parent\n while (sus && sus.tag !== FiberTag.Suspense) sus = sus.parent\n if (sus && sus.memoizedState) {\n ;(sus.memoizedState as any)._awaitingLazyHydration = true\n }\n const clearAwait = () => {\n if (sus && sus.memoizedState) {\n ;(sus.memoizedState as any)._awaitingLazyHydration = false\n }\n scheduleUpdate(fiber)\n }\n e.then(clearAwait, clearAwait)\n deferredForHydration = true\n } else {\n CAPABILITIES.handleSuspended(fiber, e)\n rendered = null\n }\n } else {\n handleErrorInRender(fiber, e)\n return\n }\n } finally {\n ReactSharedInternals.H = prevDispatcher\n ReactSharedInternals.currentFiber = prevFiber\n ReactSharedInternals.currentHook = prevHook\n ReactSharedInternals.hookIndex = prevIndex\n }\n\n if (deferredForHydration) return\n\n reconcileChildren(fiber, childrenToArray(rendered), domParent, anchor)\n fiber.memoizedProps = fiber.pendingProps\n // dirty cleared at rerender start; leaving true lets mid-render schedule persist\n}\n\nfunction hasAncestorHydrationCursor(_fiber: Fiber): boolean {\n // Reserved for future per-Suspense-boundary hydration deferral. For now the\n // top-level hydration path is all we need to special-case.\n return false\n}\n\nfunction renderFragment(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const props = fiber.pendingProps ?? {}\n reconcileChildren(fiber, childrenToArray(props.children), domParent, anchor)\n fiber.memoizedProps = props\n // dirty cleared at rerender start; leaving true lets mid-render schedule persist\n}\n\n// ---------------------------------------------------------------------------\n// Error handling + default Suspense capability\n// ---------------------------------------------------------------------------\n\n// Default handler when the Suspense feature isn't installed: just schedule\n// a re-render when the thrown thenable settles. No boundary walk, no\n// fallback swap \u2014 children render empty during the pending window.\nfunction defaultHandleSuspended(fiber: Fiber, thenable: Promise<any>): void {\n thenable.then(\n () => scheduleUpdate(fiber),\n () => scheduleUpdate(fiber),\n )\n}\n\n// ---------------------------------------------------------------------------\n// Capability hooks \u2014 cross-cutting behaviors that features override.\n// Defaults here preserve today's behavior so the indirection is transparent\n// when all features are loaded. A feature's full-module can install its own\n// implementation via installCapability(); stubs leave the default in place,\n// where the default may intentionally degrade (e.g. a no-Context build's\n// readContext never walks the tree because no Provider fibers exist).\n// ---------------------------------------------------------------------------\n\nexport interface Capabilities {\n handleSuspended: (fiber: Fiber, thenable: Promise<any>) => void\n readContext: (fiber: Fiber, ctx: any) => any\n}\n\nconst CAPABILITIES: Capabilities = {\n handleSuspended: defaultHandleSuspended,\n readContext: defaultReadContext,\n}\n\nexport function installCapability<K extends keyof Capabilities>(\n name: K,\n fn: Capabilities[K],\n): void {\n CAPABILITIES[name] = fn\n}\n\n// Wrapper for features that catch thrown thenables inside their render\n// functions. Delegates to the installed Suspense capability.\nexport function handleSuspended(fiber: Fiber, thenable: Promise<any>): void {\n CAPABILITIES.handleSuspended(fiber, thenable)\n}\n\nexport function handleErrorInRender(fiber: Fiber, err: any): void {\n // Bubble to nearest class boundary with getDerivedStateFromError / componentDidCatch\n let f: Fiber | null = fiber.parent\n while (f) {\n if (f.tag === FiberTag.Class) {\n const Ctor = f.type as any\n const instance = f.stateNode\n if (Ctor.getDerivedStateFromError) {\n const update = Ctor.getDerivedStateFromError(err)\n instance.state = { ...instance.state, ...update }\n }\n if (instance.componentDidCatch) {\n try {\n instance.componentDidCatch(err, { componentStack: '' })\n } catch {}\n }\n scheduleUpdate(f)\n return\n }\n f = f.parent\n }\n // No boundary \u2014 report to root\n if (currentRoot?.onUncaughtError) currentRoot.onUncaughtError(err)\n else throw err\n}\n\nexport function isThenable(x: any): x is Promise<any> {\n return x != null && typeof x.then === 'function'\n}\n\n// ---------------------------------------------------------------------------\n// Unmount\n// ---------------------------------------------------------------------------\n\nfunction unmountFiber(fiber: Fiber, domParent: Node): void {\n fiber.unmounted = true\n // Recurse first\n let c = fiber.child\n while (c) {\n const next = c.sibling\n unmountFiber(c, fiber.tag === FiberTag.Host ? fiber.dom! : domParent)\n c = next\n }\n fiber.child = null\n\n // Run cleanups (effects + layout effects)\n if (fiber.cleanups) {\n for (const cleanup of fiber.cleanups) {\n try {\n cleanup()\n } catch (e) {\n if (currentRoot?.onRecoverableError) currentRoot.onRecoverableError(e)\n }\n }\n fiber.cleanups = null\n }\n\n if (fiber.tag === FiberTag.Class && fiber.stateNode?.componentWillUnmount) {\n try {\n fiber.stateNode.componentWillUnmount()\n } catch (e) {\n if (currentRoot?.onRecoverableError) currentRoot.onRecoverableError(e)\n }\n fiber.stateNode._fiber = null\n fiber.stateNode._enqueueUpdate = null\n fiber.stateNode._forceUpdate = null\n }\n\n // Detach ref\n if (fiber.ref) detachRef(fiber.ref)\n\n // Remove DOM if host\n if (fiber.tag === FiberTag.Host && fiber.dom && fiber.dom.parentNode) {\n fiber.dom.parentNode.removeChild(fiber.dom)\n } else if (fiber.tag === FiberTag.Text && fiber.dom && fiber.dom.parentNode) {\n fiber.dom.parentNode.removeChild(fiber.dom)\n }\n}\n\nexport function unmountAllChildren(parent: Fiber, domParent: Node): void {\n let c = parent.child\n while (c) {\n const next = c.sibling\n unmountFiber(c, domParent)\n c = next\n }\n parent.child = null\n}\n\n// ---------------------------------------------------------------------------\n// DOM navigation helpers\n// ---------------------------------------------------------------------------\n\nfunction insertInto(parent: Node, node: Node, anchor: Node | null): void {\n // Anchor may have been removed or moved since it was computed (mutations\n // from unmount, boundary reveal, user code, HMR). If it's no longer a child\n // of `parent`, fall back to append \u2014 trying to insertBefore a non-child\n // throws NotFoundError and dev-loops the reconciler.\n if (anchor && anchor.parentNode === parent) {\n parent.insertBefore(node, anchor)\n } else {\n parent.appendChild(node)\n }\n}\n\nfunction getHostParent(fiber: Fiber): Node {\n let p = fiber.parent\n while (p) {\n if (p.tag === FiberTag.Host) return p.dom!\n if (p.tag === FiberTag.Root)\n return (p.stateNode as Node) || (p.dom as Node) || (p.root?.container as Node)\n if (p.tag === FiberTag.Portal) {\n // Portal renders its children into the `container` prop, not into any\n // DOM element the portal fiber \"owns\". Read the container from the\n // portal's own props so a rerenderFiber triggered on a descendant\n // (e.g. a Floating-UI-positioned popper in a Radix Portal) finds its\n // host parent \u2014 otherwise getHostParent returns undefined and the\n // next renderHost crashes reading `.namespaceURI` on undefined.\n const props = (p.pendingProps ?? p.memoizedProps) as { container?: Element } | null\n return (props?.container as Node) || (p.stateNode as Node) || (p.dom as Node) || (p.root?.container as Node)\n }\n p = p.parent\n }\n throw new Error('No host parent found.')\n}\n\nfunction getAnchor(fiber: Fiber): Node | null {\n // Return the first DOM node that comes after this fiber within the host parent\n let f: Fiber | null = fiber.sibling\n while (f) {\n const d = firstDomNode(f)\n if (d) return d\n f = f.sibling\n }\n // Ascend\n let p = fiber.parent\n while (p && p.tag !== FiberTag.Host && p.tag !== FiberTag.Root && p.tag !== FiberTag.Portal) {\n if (p.sibling) {\n const d = firstDomNode(p.sibling)\n if (d) return d\n }\n p = p.parent\n }\n return null\n}\n\nfunction firstDomNode(fiber: Fiber): Node | null {\n if (fiber.tag === FiberTag.Host || fiber.tag === FiberTag.Text) return fiber.dom\n let c = fiber.child\n while (c) {\n const d = firstDomNode(c)\n if (d) return d\n c = c.sibling\n }\n return null\n}\n\n// ---------------------------------------------------------------------------\n// Context read \u2014 exported for dispatcher.ts (useContext, use()). Delegates to\n// the installed capability so the Context feature can override with a walking\n// implementation that finds the nearest Provider fiber. When the feature is\n// stubbed, the default here returns ctx._currentValue \u2014 correct because no\n// Provider fibers exist in the tree (Provider element \u2192 Fragment via the\n// stub's type matcher).\n// ---------------------------------------------------------------------------\n\nexport function readContext(fiber: Fiber, ctx: any): any {\n return CAPABILITIES.readContext(fiber, ctx)\n}\n\nfunction defaultReadContext(_fiber: Fiber, ctx: any): any {\n return ctx._currentValue\n}\n\n// ---------------------------------------------------------------------------\n// Refs\n// ---------------------------------------------------------------------------\n\nfunction attachRef(fiber: Fiber, value: any): void {\n const ref = fiber.ref ?? (fiber.pendingProps?.ref ?? null)\n if (!ref) return\n if (typeof ref === 'function') {\n // Match React's commit-phase semantics: callback refs run after render\n // (during the layout/commit phase), not during render. Calling them\n // synchronously here breaks libraries that assert no event handlers run\n // during render (e.g. base-ui's useStableCallback trampoline).\n scheduleLifecycle(fiber, () => {\n const cleanup = ref(value)\n fiber.cleanups ||= []\n fiber.cleanups.push(typeof cleanup === 'function' ? cleanup : () => ref(null))\n })\n } else {\n ref.current = value\n }\n}\n\nfunction syncRefIfChanged(fiber: Fiber, value: any): void {\n const ref = fiber.ref ?? (fiber.pendingProps?.ref ?? null)\n if (!ref) return\n if (typeof ref === 'object' && ref.current !== value) ref.current = value\n}\n\nfunction detachRef(ref: any): void {\n // Function refs are handled via fiber.cleanups (queued in attachRef during\n // the commit phase): the cleanup either invokes the user-returned cleanup\n // fn or calls ref(null). Calling ref(null) here would double-fire it.\n if (ref && typeof ref === 'object') {\n ref.current = null\n }\n}\n\n// ---------------------------------------------------------------------------\n// Effects\n// ---------------------------------------------------------------------------\n\nconst pendingEffects: Array<{ fiber: Fiber; effect: Effect }> = []\nconst pendingLayoutEffects: Array<{ fiber: Fiber; effect: Effect }> = []\nconst pendingLifecycles: Array<{ fiber: Fiber; fn: () => void }> = []\n\nexport function enqueueEffect(fiber: Fiber, effect: Effect): void {\n if (effect.tag === 'layout' || effect.tag === 'insertion') {\n pendingLayoutEffects.push({ fiber, effect })\n } else {\n pendingEffects.push({ fiber, effect })\n }\n}\n\nexport function scheduleLifecycle(fiber: Fiber, fn: () => void): void {\n pendingLifecycles.push({ fiber, fn })\n}\n\nexport function runEffects(root: FiberRoot): void {\n // Layout effects synchronously\n while (pendingLayoutEffects.length) {\n const { fiber, effect } = pendingLayoutEffects.shift()!\n runEffect(fiber, effect, root)\n }\n // Then lifecycles\n while (pendingLifecycles.length) {\n const { fn } = pendingLifecycles.shift()!\n try {\n fn()\n } catch (e) {\n if (root.onCaughtError) root.onCaughtError(e)\n }\n }\n // Passive effects on microtask\n if (pendingEffects.length) {\n const batch = pendingEffects.splice(0)\n queueMicrotask(() => {\n for (const { fiber, effect } of batch) runEffect(fiber, effect, root)\n })\n }\n}\n\nfunction runEffect(fiber: Fiber, effect: Effect, root: FiberRoot): void {\n try {\n const cleanup = effect.create()\n effect.destroy = typeof cleanup === 'function' ? cleanup : undefined\n if (effect.destroy) {\n fiber.cleanups ||= []\n fiber.cleanups.push(effect.destroy)\n }\n } catch (e) {\n if (root.onCaughtError) root.onCaughtError(e)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nfunction isEventProp(name: string): boolean {\n return (\n name.length > 2 &&\n name.charCodeAt(0) === 111 /* o */ &&\n name.charCodeAt(1) === 110 /* n */ &&\n name.charCodeAt(2) >= 65 /* 'A'-ish: any uppercase start (onClick, onChange, \u2026) */\n )\n}\n\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n FiberTag,\n FiberFlag,\n createFiber,\n REACT_ELEMENT_TYPE,\n REACT_LEGACY_ELEMENT_TYPE,\n REACT_FRAGMENT_TYPE,\n type Fiber,\n type FiberRoot,\n type ReactElement,\n type ReactNode,\n type Hook,\n type Effect,\n} from '../core'\nimport {\n ReactSharedInternals,\n REACT_LAZY_TYPE,\n REACT_STRICT_MODE_TYPE,\n REACT_PROFILER_TYPE,\n} from '../react'\nimport { createHostNode, setProp } from './dom'\nimport { makeDispatcher } from './dispatcher'\nimport {\n adoptHostDom,\n adoptTextDom,\n tryConsumeBoundary,\n advanceCursorPast,\n setHydrationCursor,\n getHydrationCursor,\n clearHydrationCursor,\n HydrationCursor,\n findHostParent as findHydrationHost,\n} from './features/hydration'\n\n// ---------------------------------------------------------------------------\n// Render scheduling\n// ---------------------------------------------------------------------------\n\nlet currentRoot: FiberRoot | null = null\nlet flushing = false\nlet isBatching = false\nconst pendingRoots = new Set<FiberRoot>()\n\n// Set by rerenderFiber to identify the exact memo-tagged fiber whose INTERNAL\n// state (hook update, useSyncExternalStore notification) triggered this render\n// pass. renderMemo checks this to bypass its prop-equality gate for that fiber.\n// Without the bypass, a memo bail would swallow state changes: React's memo is\n// only a parent-triggered gate \u2014 state-driven rerenders must always run the\n// inner function. Router-adjacent components (Outlet, Match, MatchInner) are\n// all memo-wrapped and subscribe to stores; missing this bypass breaks nav\n// content updates even though the URL changes.\nlet forceRerenderingFiber: Fiber | null = null\n\nexport function scheduleUpdate(fiber: Fiber): void {\n // Drop updates scheduled on already-unmounted fibers. Subscribers (router,\n // query, any external store) can fire after unmount if their cleanup was\n // missed, and letting those reach rerenderFiber mounts zombie DOM into the\n // old .parent's DOM (which stays reachable via the stale pointer).\n if (fiber.unmounted) return\n const root = findRoot(fiber)\n if (!root) return\n root.pending.add(fiber)\n fiber.dirty = true\n pendingRoots.add(root)\n if (isBatching) return\n if (!root.scheduled) {\n root.scheduled = true\n queueMicrotask(flushPending)\n }\n}\n\nexport function flushSyncWork(fn: () => void): void {\n const wasBatching = isBatching\n isBatching = true\n try {\n fn()\n } finally {\n isBatching = wasBatching\n }\n flushPending()\n}\n\nexport function batchedUpdates<T>(fn: () => T): T {\n const wasBatching = isBatching\n isBatching = true\n try {\n return fn()\n } finally {\n isBatching = wasBatching\n if (!wasBatching) flushPending()\n }\n}\n\nfunction flushPending(): void {\n if (flushing) return\n flushing = true\n try {\n let guard = 0\n while (pendingRoots.size > 0) {\n if (++guard > 50) {\n throw new Error('flushPending exceeded 50 iterations \u2014 suspected infinite update loop.')\n }\n const roots = [...pendingRoots]\n pendingRoots.clear()\n for (const root of roots) {\n root.scheduled = false\n // Render each pending fiber from shallowest first so an ancestor's\n // cascade reaches descendants before we try to render them directly.\n // Descendants rendered via cascade still have `dirty=true` (only\n // rerenderFiber clears it); when we later reach them in this loop,\n // rerenderFiber's own `if (!dirty) return` is our short-circuit. We\n // previously filtered descendants of dirty ancestors here, but that\n // loses updates whenever an ancestor's render doesn't actually reach\n // the descendant \u2014 e.g. React.memo bailing on equal props. Keep all\n // dirty fibers and let rerenderFiber de-dupe via its dirty check.\n const pending = [...root.pending]\n root.pending.clear()\n pending.sort((a, b) => fiberDepth(a) - fiberDepth(b))\n for (const fiber of pending) {\n rerenderFiber(fiber, root)\n }\n runEffects(root)\n }\n }\n } finally {\n flushing = false\n }\n}\n\nfunction fiberDepth(fiber: Fiber): number {\n let d = 0\n let p: Fiber | null = fiber.parent\n while (p) {\n d++\n p = p.parent\n }\n return d\n}\n\nexport function findRoot(fiber: Fiber): FiberRoot | null {\n let f: Fiber | null = fiber\n while (f) {\n if (f.root) return f.root\n f = f.parent\n }\n return null\n}\n\n// ---------------------------------------------------------------------------\n// Entry points (called by createRoot)\n// ---------------------------------------------------------------------------\n\nexport function renderRoot(root: FiberRoot, children: ReactNode): void {\n const rootFiber = root.current\n rootFiber.pendingProps = { children }\n currentRoot = root\n try {\n reconcileChildren(rootFiber, childrenToArray(children), root.container as Node, null)\n rootFiber.memoizedProps = rootFiber.pendingProps\n rootFiber.dirty = false\n } finally {\n currentRoot = null\n }\n runEffects(root)\n}\n\nfunction rerenderFiber(fiber: Fiber, root: FiberRoot): void {\n if (!fiber.dirty) return\n // Skip fibers that were unmounted between scheduling and flush. Without this,\n // the flush loop re-enters a zombie fiber whose .parent is still set; its\n // render mounts fresh DOM into the old parent's still-attached DOM (since\n // unmountFiber only clears fiber.child, not fiber.parent). Visible as route\n // content from a previous location staying on screen after nav, because a\n // pending rerender on the old route's LibraryLandingPage (unmounted during\n // Outlet's shallow-first render) still fires from root.pending.\n if (fiber.unmounted) return\n // Clear BEFORE rendering so a scheduleUpdate() triggered mid-render (e.g.\n // error boundary catching a descendant throw) marks us dirty for the next\n // flush iteration instead of being wiped out when render() completes.\n fiber.dirty = false\n currentRoot = root\n // If this rerender is resuming a hydration that was deferred by a suspension,\n // re-activate hydration mode for its duration so descendants adopt DOM\n // instead of re-creating it.\n const resumeHydration =\n fiber.memoizedState && (fiber.memoizedState as any)._pendingHydration === true\n const prevHydrating = root.hydrating\n if (resumeHydration) {\n delete (fiber.memoizedState as any)._pendingHydration\n root.hydrating = true\n }\n const prevForcing = forceRerenderingFiber\n forceRerenderingFiber = fiber\n try {\n renderFiber(fiber, getHostParent(fiber), getAnchor(fiber))\n } finally {\n forceRerenderingFiber = prevForcing\n if (resumeHydration) {\n root.hydrating = prevHydrating\n // Deferred hydration completed \u2014 detach the preserved cursor so future\n // updates (post-hydration state changes) don't try to adopt stale DOM.\n clearHydrationCursor(fiber)\n }\n currentRoot = null\n }\n}\n\n// ---------------------------------------------------------------------------\n// Element \u2192 children normalization\n// ---------------------------------------------------------------------------\n\ntype TextChild = { _text: string }\ntype NormalizedChild = ReactElement | TextChild | null\n\n// NEVER use `'_text' in child` to distinguish text wrappers from elements.\n// TanStack's RSC renderable proxies (createRscProxy with renderable: true) are\n// Proxy wrappers around real React elements whose `has` trap returns `true`\n// for ANY string key \u2014 so `'_text' in rscProxy` is TRUE even though the proxy\n// is an element. That misidentification set a Text fiber's `pendingProps` to\n// `child._text` (another chained RSC proxy), which then rendered as\n// `[object Object]` when createTextNode stringified the element. React\n// elements always carry `$$typeof`; our text wrapper never does \u2014 so the\n// presence of `$$typeof` is the invariant we rely on.\nfunction isTextChild(child: Exclude<NormalizedChild, null>): child is TextChild {\n return (child as any).$$typeof === undefined\n}\n\nexport function childrenToArray(children: ReactNode): NormalizedChild[] {\n const out: NormalizedChild[] = []\n pushChildren(children, out)\n return out\n}\n\nfunction pushChildren(node: ReactNode, out: NormalizedChild[]): void {\n if (node == null || typeof node === 'boolean') return\n if (typeof node === 'string' || typeof node === 'number') {\n // Empty strings render no text node (matches React + the `<!-- -->`\n // separator elision on the SSR side so server/client agree).\n if (node === '') return\n out.push({ _text: '' + node })\n return\n }\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) pushChildren(node[i], out)\n return\n }\n if (isIterable(node)) {\n for (const item of node as Iterable<ReactNode>) pushChildren(item, out)\n return\n }\n if (typeof node === 'object') {\n const t = (node as any).$$typeof\n if (ACCEPTED_ELEMENT_MARKERS.has(t)) {\n out.push(node as ReactElement)\n return\n }\n // Raw React.lazy as a child. RSC Flight encodes 'use client' components\n // (CodeBlock, CodeExplorer, etc.) as bare Lazy objects in the tree, not\n // wrapped in REACT_ELEMENT_TYPE. Dropping them made code snippets\n // disappear from docs pages. The RSC decoder pre-awaits payloads via\n // `awaitLazyElements`, so by render time the status is 'fulfilled' and\n // `_init()` returns the resolved element synchronously.\n if (t === REACT_LAZY_TYPE) {\n const lazy = node as any\n const resolved = lazy._init(lazy._payload)\n pushChildren(resolved, out)\n return\n }\n }\n}\n\nfunction isIterable(obj: any): boolean {\n return obj != null && typeof obj !== 'string' && typeof obj[Symbol.iterator] === 'function'\n}\n\nfunction getKeyOf(child: NormalizedChild, index: number): string {\n if (!child) return 'n' + index\n if (isTextChild(child)) return '$t' + index\n if (child.key != null) return 'k' + child.key\n return 'i' + index\n}\n\nfunction sameType(fiber: Fiber, child: NormalizedChild): boolean {\n if (!child) return false\n if (isTextChild(child)) return fiber.tag === FiberTag.Text\n return fiber.type === child.type && sameKey(fiber.key, child.key)\n}\n\nfunction sameKey(a: string | null, b: string | null | undefined): boolean {\n return (a ?? null) === (b ?? null)\n}\n\n// ---------------------------------------------------------------------------\n// Fiber creation\n// ---------------------------------------------------------------------------\n\nfunction fiberFromChild(child: NormalizedChild, parent: Fiber): Fiber {\n if (!child) return createFiber(FiberTag.Fragment, null, null)\n if (isTextChild(child)) {\n const f = createFiber(FiberTag.Text, null, null)\n f.pendingProps = child._text\n f.parent = parent\n return f\n }\n const type = child.type\n let tag: FiberTag = FiberTag.Host\n const marker = type && (type as any).$$typeof\n if (typeof type === 'string') tag = FiberTag.Host\n else if (type === REACT_FRAGMENT_TYPE) tag = FiberTag.Fragment\n else if (type === REACT_STRICT_MODE_TYPE || type === REACT_PROFILER_TYPE) tag = FiberTag.Fragment\n else {\n // Feature-registered type matchers (Portal, future extractions). Features\n // that carry the symbol as element.type directly (rather than wrapping in\n // REACT_ELEMENT_TYPE) match here by type identity.\n let matched: FiberTag | null = null\n for (const m of TYPE_MATCHERS) {\n matched = m(type, marker)\n if (matched !== null) break\n }\n if (matched !== null) tag = matched\n else if (typeof type === 'function') {\n tag = type.prototype && type.prototype.isReactComponent ? FiberTag.Class : FiberTag.Function\n }\n }\n const f = createFiber(tag, type, child.key ?? null)\n f.ref = (child as any).ref ?? null\n f.pendingProps = child.props\n f.parent = parent\n return f\n}\n\n// ---------------------------------------------------------------------------\n// Reconciliation\n// ---------------------------------------------------------------------------\n\n/**\n * Reconcile a parent fiber's child list against new normalized children.\n * Mutates parent.child and the sibling chain.\n * Mounts new host DOM into `domParent` before `anchor` (or appends if anchor === null).\n */\nexport function reconcileChildren(\n parent: Fiber,\n newChildren: NormalizedChild[],\n domParent: Node,\n anchor: Node | null,\n): void {\n const existing = collectChildren(parent)\n const keyed = new Map<string, Fiber>()\n for (const f of existing) {\n if (f.key != null) keyed.set('k' + f.key, f)\n }\n\n let prevNewFiber: Fiber | null = null\n const claimed = new Set<Fiber>()\n let structurallyChanged = false\n // Budget-guided positional matching. We walk `existing` (unkeyed only) with a\n // single cursor `existingIdx` and, on a type mismatch, choose insert vs delete\n // based on the remaining length delta (`budget`):\n // budget > 0: more new than old remain \u2192 treat slot as an INSERTION: keep\n // the old cursor and create a fresh fiber for new[i].\n // budget < 0: more old than new remain \u2192 treat slot as a DELETION: advance\n // the old cursor past the mismatched fiber (it'll be unmounted\n // in the unclaimed pass) and retry.\n // budget == 0: equal remaining \u2192 treat as REPLACE by preferring delete\n // until budget flips positive or we hit a match.\n // This avoids greedy forward scans that steal a later same-type fiber for a\n // newly inserted leading sibling (e.g. smallMenu flipping null \u2192 <div>\n // stealing the content <div>'s fiber and tearing down the drawer fragment).\n let existingIdx = 0\n let unkeyedOld = 0\n for (const f of existing) if (f.key == null) unkeyedOld++\n let unkeyedNew = 0\n for (const c of newChildren) if (c != null) unkeyedNew++\n let budget = unkeyedNew - unkeyedOld\n\n // Pass 1 (this loop): match against existing fibers and build the sibling\n // chain. Pass 2 (after the loop) renders each fiber with the correct\n // per-child anchor \u2014 the firstDomNode of its next still-mounted sibling,\n // or the parent's own anchor for the rightmost. Without per-child anchors\n // a child whose render output type changes from no-DOM (Portal, null) to\n // an in-flow host gets appended to the end of domParent (every child\n // would otherwise share the parent's anchor) and never moves before its\n // later siblings. Hit by the t3code Sidebar swap from a portal-rendering\n // <Sheet> to a <div data-slot=sidebar> when isMobile flips during a\n // Provider re-render.\n for (let i = 0; i < newChildren.length; i++) {\n const child = newChildren[i]\n if (child == null) continue\n\n let match: Fiber | null = null\n\n // key-based match\n if (child && typeof child === 'object' && !isTextChild(child) && (child as ReactElement).key != null) {\n const k = 'k' + (child as ReactElement).key\n const m = keyed.get(k)\n if (m && m.type === (child as ReactElement).type) {\n match = m\n keyed.delete(k)\n }\n }\n\n if (!match) {\n while (existingIdx < existing.length) {\n const cand = existing[existingIdx]!\n if (claimed.has(cand) || cand.key != null) {\n existingIdx++\n continue\n }\n if (sameType(cand, child)) {\n match = cand\n existingIdx++\n break\n }\n // Type mismatch at the cursor. Resolve via budget.\n if (budget > 0) {\n // Insertion: leave cand in place, create new for child.\n break\n }\n // Deletion (or replace-as-delete-first): advance past cand. It remains\n // unclaimed and will be unmounted at the end.\n existingIdx++\n budget++\n }\n }\n\n // Detect reorder: matched fiber is not at its original position\n if (match && existing[i] !== match) structurallyChanged = true\n\n let fiber: Fiber\n if (match) {\n claimed.add(match)\n fiber = match\n if (isTextChild(child!)) {\n fiber.pendingProps = child._text\n } else {\n fiber.type = (child as ReactElement).type\n fiber.pendingProps = (child as ReactElement).props\n fiber.ref = (child as any).ref ?? null\n }\n } else {\n fiber = fiberFromChild(child, parent)\n structurallyChanged = true\n if (budget > 0) budget--\n }\n\n fiber.parent = parent\n fiber.sibling = null\n if (prevNewFiber) prevNewFiber.sibling = fiber\n else parent.child = fiber\n prevNewFiber = fiber\n }\n\n // Pass 2: walk the sibling chain we just built and render each fiber\n // forward with the correct per-child anchor. During hydration the cursor\n // walks DOM forward and each renderFiber adopts the next existing node,\n // so per-child anchors are moot \u2014 fall back to the parent's anchor.\n const hydrating = !!currentRoot?.hydrating\n for (let f: Fiber | null = parent.child; f; f = f.sibling) {\n let a = anchor\n if (!hydrating) {\n // Find the firstDomNode of the next still-mounted sibling, if any.\n for (let s: Fiber | null = f.sibling; s; s = s.sibling) {\n const d = firstDomNode(s)\n if (d && d.parentNode === domParent) { a = d; break }\n }\n }\n renderFiber(f, domParent, a)\n }\n\n if (!prevNewFiber) parent.child = null\n else prevNewFiber.sibling = null\n\n // Head content is additive \u2014 server may inject metadata/stylesheets (Vite\n // dev styles, Sentry, analytics) that aren't in the React tree. Unmounting\n // them on every reconcile thrashes styles and causes flash of unstyled\n // content. Keep existing head children that weren't matched this pass.\n const parentIsHeadHost =\n parent.tag === FiberTag.Host &&\n typeof parent.type === 'string' &&\n (parent.type as string).toLowerCase() === 'head'\n\n if (!parentIsHeadHost) {\n // Unmount unclaimed\n for (const f of existing) {\n if (!claimed.has(f)) {\n unmountFiber(f, domParent)\n structurallyChanged = true\n }\n }\n // Leftover keyed\n for (const f of keyed.values()) {\n if (!claimed.has(f)) {\n unmountFiber(f, domParent)\n structurallyChanged = true\n }\n }\n }\n\n // During hydration, DOM is already in document order from the cursor-driven\n // adoption walk. Running placeChildrenInOrder here would reappend nodes to\n // the end of domParent when the true anchor (often an end marker comment)\n // isn't reflected in `anchor`. Skip it in hydration mode.\n //\n // For <head>, skip always \u2014 HeadContent re-renders routinely (route match\n // changes, providers updating), and reordering every <link>/<style>/<meta>\n // on each re-render causes stylesheet flash and re-download. Head element\n // ordering is semantically fluid; the browser doesn't care about exact\n // order within <head>.\n const parentIsHead =\n (domParent as Element).nodeType === 1 &&\n (domParent as Element).tagName.toLowerCase() === 'head'\n if (structurallyChanged && !currentRoot?.hydrating && !parentIsHead) {\n placeChildrenInOrder(parent, domParent, anchor)\n }\n}\n\nfunction placeChildrenInOrder(parent: Fiber, domParent: Node, anchor: Node | null): void {\n const doms: Node[] = []\n let c = parent.child\n while (c) {\n collectHostDoms(c, doms)\n c = c.sibling\n }\n\n // Pre-check: if our fiber-owned DOM is already in document order within\n // domParent AND the trailing anchor matches, no reorder is needed. This is\n // the common case on stable re-renders, and avoids detaching/re-attaching\n // subtrees (which cancels CSS animations and triggers layout).\n if (doms.length > 0) {\n let current: Node | null = doms[0]!\n let inOrder = current.parentNode === domParent\n for (let i = 1; inOrder && i < doms.length; i++) {\n current = current!.nextSibling\n // Skip foreign nodes (SSR-injected scripts, dev-styles) between owned\n // fiber DOMs \u2014 they should stay where they are.\n while (current && !doms.includes(current as Node)) {\n current = current.nextSibling\n }\n if (current !== doms[i]) inOrder = false\n }\n // Also verify the LAST dom's next sibling lines up with `anchor`. A\n // single-dom collection (or correctly-internally-ordered doms) can sit\n // at the WRONG absolute position in domParent and still pass the\n // relative-order check above. This happens when a fiber's render output\n // changes from no-DOM (e.g. a Portal-using <Sheet>, or null) to an\n // in-flow host element: the new host is appended to the end of\n // domParent (because the parent reconcileChildren loop hands every\n // child the same anchor \u2014 typically null), and without this trailing\n // check it would never get moved before its later siblings.\n if (inOrder) {\n let last: Node | null = doms[doms.length - 1]!.nextSibling\n while (last && !doms.includes(last as Node) && last !== anchor) {\n last = last.nextSibling\n }\n if (last !== anchor) inOrder = false\n }\n if (inOrder) return\n }\n\n // Reverse-iterate, anchoring each node before the one that should follow it.\n // This works because by the time we're placing doms[i], doms[i+1] is already\n // in its final slot. Forward iteration is buggy: insertBefore(doms[i],\n // doms[i+1]) pulls doms[i] forward past any nodes that SHOULD move behind\n // it, leaving those nodes mis-anchored (app-starter Analyze/Lucky swap, npm\n // stats library dropdown reorder \u2014 both reported by users).\n //\n // Concrete example: start=[A, R, L], target=[A, L, R]. Forward pass gives\n // [L, A, R] (wrong). Reverse pass moves R to end, then L and A are already\n // correct \u2014 1 move, matches target.\n //\n // Skip nodes already in their target position so CSS transitions on stable\n // siblings aren't cancelled (e.g. drawer slide animation).\n for (let i = doms.length - 1; i >= 0; i--) {\n const d = doms[i]!\n const targetNext: Node | null = i + 1 < doms.length ? doms[i + 1]! : anchor\n if (d.parentNode !== domParent || d.nextSibling !== targetNext) {\n domParent.insertBefore(d, targetNext)\n }\n }\n}\n\nfunction collectHostDoms(fiber: Fiber, out: Node[]): void {\n if (fiber.tag === FiberTag.Host || fiber.tag === FiberTag.Text) {\n if (fiber.dom) out.push(fiber.dom)\n return\n }\n if (fiber.tag === FiberTag.Portal) return\n let c = fiber.child\n while (c) {\n collectHostDoms(c, out)\n c = c.sibling\n }\n}\n\nfunction collectChildren(parent: Fiber): Fiber[] {\n const out: Fiber[] = []\n let c = parent.child\n while (c) {\n out.push(c)\n c = c.sibling\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Rendering per fiber tag\n// ---------------------------------------------------------------------------\n\nexport type RenderFn = (fiber: Fiber, domParent: Node, anchor: Node | null) => void\nexport type TypeMatcher = (type: any, marker: any) => FiberTag | null\n\n// Mutable renderer registry indexed by FiberTag. Feature modules install their\n// renderer via registerRenderer(); unregistered features render as no-ops. The\n// initial registrations below rely on function-declaration hoisting \u2014 every\n// render* function is declared with `function` later in this file.\nconst RENDERERS: Array<RenderFn | undefined> = new Array(13)\n\n// Element-marker allowlist for child normalization (pushChildren). Core-always\n// markers are seeded here; features add their own via registerElementMarker.\nconst ACCEPTED_ELEMENT_MARKERS = new Set<symbol>([\n REACT_ELEMENT_TYPE as symbol,\n REACT_LEGACY_ELEMENT_TYPE as symbol,\n])\n\n// Type-to-tag matchers tried in registration order from fiberFromChild's\n// fallback branch. Features register here for element types that aren't\n// marker-based (e.g. Portal, where element.type IS the symbol).\nconst TYPE_MATCHERS: TypeMatcher[] = []\n\nexport function registerRenderer(tag: FiberTag, fn: RenderFn): void {\n RENDERERS[tag] = fn\n}\n\nexport function registerTypeMatcher(m: TypeMatcher): void {\n TYPE_MATCHERS.push(m)\n}\n\nexport function registerElementMarker(sym: symbol): void {\n ACCEPTED_ELEMENT_MARKERS.add(sym)\n}\n\n// Accessor + scoped setter for the module-level `currentRoot`. Feature modules\n// need these to participate in the render loop (e.g. Suspense re-hydration\n// must temporarily set the root while rebuilding a boundary subtree).\nexport function getCurrentRoot(): FiberRoot | null {\n return currentRoot\n}\n\nexport function withCurrentRoot<T>(root: FiberRoot | null, fn: () => T): T {\n const prev = currentRoot\n currentRoot = root\n try {\n return fn()\n } finally {\n currentRoot = prev\n }\n}\n\n// The memo feature uses this to bypass its prop-equality gate on state-driven\n// rerenders of the memoized fiber itself (hook update / subscribed store),\n// where props haven't changed by definition.\nexport function getForceRerenderingFiber(): Fiber | null {\n return forceRerenderingFiber\n}\n\nregisterRenderer(FiberTag.Text, renderText)\nregisterRenderer(FiberTag.Host, renderHost)\nregisterRenderer(FiberTag.Function, renderFunction)\nregisterRenderer(FiberTag.Fragment, renderFragment)\n\nexport function renderFiber(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const fn = RENDERERS[fiber.tag]\n if (fn) fn(fiber, domParent, anchor)\n}\n\nfunction renderText(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const text = fiber.pendingProps as string\n if (!fiber.dom) {\n const hydrated = currentRoot?.hydrating ? adoptTextDom(fiber, fiber.parent!, text) : false\n if (!hydrated) {\n fiber.dom = document.createTextNode(text)\n insertInto(domParent, fiber.dom, anchor)\n }\n } else if ((fiber.dom as Text).data !== text) {\n ;(fiber.dom as Text).data = text\n }\n fiber.memoizedProps = text\n // dirty cleared at rerender start; leaving true lets mid-render schedule persist\n}\n\nfunction renderHost(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const props = fiber.pendingProps ?? {}\n const prev = fiber.memoizedProps ?? {}\n const type = fiber.type as string\n const isSvg = type === 'svg' || (domParent as Element).namespaceURI === 'http://www.w3.org/2000/svg'\n\n // <select value> must be applied AFTER children mount \u2014 setting `.value`\n // on a `<select>` with no matching `<option>` yet resets it to empty. Same\n // for `defaultValue` on first mount. Stash and replay.\n const isSelect = type === 'select'\n const deferredSelectValue =\n isSelect && (props.value !== undefined || props.defaultValue !== undefined)\n ? props.value !== undefined ? props.value : props.defaultValue\n : undefined\n\n if (!fiber.dom) {\n const hydrated = currentRoot?.hydrating ? adoptHostDom(fiber, fiber.parent!) : false\n if (!hydrated) {\n fiber.dom = createHostNode(type, isSvg)\n // Two passes so form-control attributes (notably <input type>) are in\n // place before event handlers attach. setEventHandler reads the\n // element's runtime state to decide the DOM event name (e.g. onChange\n // \u2192 `input` vs `change`); binding before `type` is applied would\n // attach to the wrong event for checkbox/radio/file inputs.\n for (const k in props) {\n if (isSelect && (k === 'value' || k === 'defaultValue')) continue\n if (isEventProp(k)) continue\n setProp(fiber.dom as Element, k, props[k], undefined, isSvg)\n }\n for (const k in props) {\n if (!isEventProp(k)) continue\n setProp(fiber.dom as Element, k, props[k], undefined, isSvg)\n }\n insertInto(domParent, fiber.dom, anchor)\n }\n attachRef(fiber, fiber.dom)\n } else {\n const el = fiber.dom as Element\n for (const k in prev) {\n if (!(k in props)) setProp(el, k, undefined, prev[k], isSvg)\n }\n // Non-event props first for the same reason as above: a `type` change\n // must land before we ask setEventHandler to resolve the DOM event for\n // `onChange`.\n for (const k in props) {\n if (isSelect && (k === 'value' || k === 'defaultValue')) continue\n if (isEventProp(k)) continue\n if (prev[k] !== props[k]) setProp(el, k, props[k], prev[k], isSvg)\n }\n for (const k in props) {\n if (!isEventProp(k)) continue\n if (prev[k] !== props[k]) setProp(el, k, props[k], prev[k], isSvg)\n }\n if (prev !== props) syncRefIfChanged(fiber, fiber.dom)\n }\n\n // Children go into this DOM node\n reconcileChildren(fiber, childrenToArray(props.children), fiber.dom!, null)\n\n // During hydration, if after reconciling all client-expected children we\n // still have server DOM left in the cursor for this host, that's a\n // structural mismatch (server produced more than client wants). Report.\n // <head>/<html> are position-insensitive \u2014 leftover here is normal\n // (Vite dev-style injections, SSR-only scripts, etc.).\n if (currentRoot?.hydrating) {\n const parentTag = (fiber.type as string).toLowerCase()\n if (parentTag !== 'head' && parentTag !== 'html') {\n const cursor = getHydrationCursor(fiber)\n if (cursor) {\n const leftover = cursor.remaining().filter(\n (n) => n.nodeType === 1 || n.nodeType === 3,\n )\n if (leftover.length > 0 && currentRoot.onRecoverableError) {\n currentRoot.onRecoverableError(\n new Error(\n `Hydration mismatch: server rendered ${leftover.length} extra ` +\n `${leftover.length === 1 ? 'node' : 'nodes'} inside <${parentTag}> ` +\n `that the client tree did not.`,\n ),\n )\n for (const n of leftover) n.parentNode?.removeChild(n)\n }\n }\n }\n }\n\n // Apply <select> value after options are mounted.\n if (isSelect && deferredSelectValue !== undefined) {\n const select = fiber.dom as HTMLSelectElement\n if (Array.isArray(deferredSelectValue)) {\n const asStrings = deferredSelectValue.map((v) => '' + v)\n for (const opt of Array.from(select.options)) {\n opt.selected = asStrings.includes(opt.value)\n }\n } else {\n select.value = '' + deferredSelectValue\n }\n }\n\n fiber.memoizedProps = props\n // dirty cleared at rerender start; leaving true lets mid-render schedule persist\n}\n\nfunction renderFunction(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const prevDispatcher = ReactSharedInternals.H\n const prevFiber = ReactSharedInternals.currentFiber\n const prevHook = ReactSharedInternals.currentHook\n const prevIndex = ReactSharedInternals.hookIndex\n\n ReactSharedInternals.H = makeDispatcher()\n ReactSharedInternals.currentFiber = fiber\n ReactSharedInternals.currentHook = null\n ReactSharedInternals.hookIndex = 0\n\n let rendered: ReactNode\n let deferredForHydration = false\n try {\n rendered = (fiber.type as Function)(fiber.pendingProps ?? {})\n } catch (e: any) {\n if (isThenable(e)) {\n if (currentRoot?.hydrating) {\n // Suspension during initial hydration. Leave the existing DOM alone\n // and preserve the in-scope hydration cursor on THIS fiber so it\n // survives the synchronous endHydration() that fires when the initial\n // hydrateRoot() call returns. When the promise settles, the fiber\n // re-renders (see rerenderFiber) with hydration re-activated and its\n // descendants adopt DOM instead of creating new nodes.\n const hostParent = findHydrationHost(fiber)\n const inheritedCursor = getHydrationCursor(hostParent)\n if (inheritedCursor) {\n setHydrationCursor(fiber, inheritedCursor)\n }\n fiber.memoizedState = {\n ...(fiber.memoizedState ?? {}),\n _pendingHydration: true,\n }\n // Mirror renderLazy's guard: mark the nearest Suspense ancestor as\n // awaiting hydration-resume, so any re-render of that Suspense (e.g.\n // rehydrateBoundary fired by $RC, or an unrelated state update from a\n // sibling) doesn't re-enter `tryChildren`, re-throw, and flip Suspense\n // into its suspended+pending path \u2014 which would unmount our deferred\n // subtree and remount a fallback on top of the SSR content. By\n // pinning the Suspense to a \"hydration-suspended\" no-op until our\n // resume fires, the deferred re-render owns the adoption pass.\n let sus: Fiber | null = fiber.parent\n while (sus && sus.tag !== FiberTag.Suspense) sus = sus.parent\n if (sus && sus.memoizedState) {\n ;(sus.memoizedState as any)._awaitingLazyHydration = true\n }\n const clearAwait = () => {\n if (sus && sus.memoizedState) {\n ;(sus.memoizedState as any)._awaitingLazyHydration = false\n }\n scheduleUpdate(fiber)\n }\n e.then(clearAwait, clearAwait)\n deferredForHydration = true\n } else {\n CAPABILITIES.handleSuspended(fiber, e)\n rendered = null\n }\n } else {\n handleErrorInRender(fiber, e)\n return\n }\n } finally {\n ReactSharedInternals.H = prevDispatcher\n ReactSharedInternals.currentFiber = prevFiber\n ReactSharedInternals.currentHook = prevHook\n ReactSharedInternals.hookIndex = prevIndex\n }\n\n if (deferredForHydration) return\n\n reconcileChildren(fiber, childrenToArray(rendered), domParent, anchor)\n fiber.memoizedProps = fiber.pendingProps\n // dirty cleared at rerender start; leaving true lets mid-render schedule persist\n}\n\nfunction hasAncestorHydrationCursor(_fiber: Fiber): boolean {\n // Reserved for future per-Suspense-boundary hydration deferral. For now the\n // top-level hydration path is all we need to special-case.\n return false\n}\n\nfunction renderFragment(fiber: Fiber, domParent: Node, anchor: Node | null): void {\n const props = fiber.pendingProps ?? {}\n reconcileChildren(fiber, childrenToArray(props.children), domParent, anchor)\n fiber.memoizedProps = props\n // dirty cleared at rerender start; leaving true lets mid-render schedule persist\n}\n\n// ---------------------------------------------------------------------------\n// Error handling + default Suspense capability\n// ---------------------------------------------------------------------------\n\n// Default handler when the Suspense feature isn't installed: just schedule\n// a re-render when the thrown thenable settles. No boundary walk, no\n// fallback swap \u2014 children render empty during the pending window.\nfunction defaultHandleSuspended(fiber: Fiber, thenable: Promise<any>): void {\n thenable.then(\n () => scheduleUpdate(fiber),\n () => scheduleUpdate(fiber),\n )\n}\n\n// ---------------------------------------------------------------------------\n// Capability hooks \u2014 cross-cutting behaviors that features override.\n// Defaults here preserve today's behavior so the indirection is transparent\n// when all features are loaded. A feature's full-module can install its own\n// implementation via installCapability(); stubs leave the default in place,\n// where the default may intentionally degrade (e.g. a no-Context build's\n// readContext never walks the tree because no Provider fibers exist).\n// ---------------------------------------------------------------------------\n\nexport interface Capabilities {\n handleSuspended: (fiber: Fiber, thenable: Promise<any>) => void\n readContext: (fiber: Fiber, ctx: any) => any\n}\n\nconst CAPABILITIES: Capabilities = {\n handleSuspended: defaultHandleSuspended,\n readContext: defaultReadContext,\n}\n\nexport function installCapability<K extends keyof Capabilities>(\n name: K,\n fn: Capabilities[K],\n): void {\n CAPABILITIES[name] = fn\n}\n\n// Wrapper for features that catch thrown thenables inside their render\n// functions. Delegates to the installed Suspense capability.\nexport function handleSuspended(fiber: Fiber, thenable: Promise<any>): void {\n CAPABILITIES.handleSuspended(fiber, thenable)\n}\n\nexport function handleErrorInRender(fiber: Fiber, err: any): void {\n // Bubble to nearest class boundary with getDerivedStateFromError / componentDidCatch\n let f: Fiber | null = fiber.parent\n while (f) {\n if (f.tag === FiberTag.Class) {\n const Ctor = f.type as any\n const instance = f.stateNode\n if (Ctor.getDerivedStateFromError) {\n const update = Ctor.getDerivedStateFromError(err)\n instance.state = { ...instance.state, ...update }\n }\n if (instance.componentDidCatch) {\n try {\n instance.componentDidCatch(err, { componentStack: '' })\n } catch {}\n }\n scheduleUpdate(f)\n return\n }\n f = f.parent\n }\n // No boundary \u2014 report to root\n if (currentRoot?.onUncaughtError) currentRoot.onUncaughtError(err)\n else throw err\n}\n\nexport function isThenable(x: any): x is Promise<any> {\n return x != null && typeof x.then === 'function'\n}\n\n// ---------------------------------------------------------------------------\n// Unmount\n// ---------------------------------------------------------------------------\n\nfunction unmountFiber(fiber: Fiber, domParent: Node): void {\n fiber.unmounted = true\n // Recurse first\n let c = fiber.child\n while (c) {\n const next = c.sibling\n unmountFiber(c, fiber.tag === FiberTag.Host ? fiber.dom! : domParent)\n c = next\n }\n fiber.child = null\n\n // Run cleanups (effects + layout effects)\n if (fiber.cleanups) {\n for (const cleanup of fiber.cleanups) {\n try {\n cleanup()\n } catch (e) {\n if (currentRoot?.onRecoverableError) currentRoot.onRecoverableError(e)\n }\n }\n fiber.cleanups = null\n }\n\n if (fiber.tag === FiberTag.Class && fiber.stateNode?.componentWillUnmount) {\n try {\n fiber.stateNode.componentWillUnmount()\n } catch (e) {\n if (currentRoot?.onRecoverableError) currentRoot.onRecoverableError(e)\n }\n fiber.stateNode._fiber = null\n fiber.stateNode._enqueueUpdate = null\n fiber.stateNode._forceUpdate = null\n }\n\n // Detach ref\n if (fiber.ref) detachRef(fiber.ref)\n\n // Remove DOM if host\n if (fiber.tag === FiberTag.Host && fiber.dom && fiber.dom.parentNode) {\n fiber.dom.parentNode.removeChild(fiber.dom)\n } else if (fiber.tag === FiberTag.Text && fiber.dom && fiber.dom.parentNode) {\n fiber.dom.parentNode.removeChild(fiber.dom)\n }\n}\n\nexport function unmountAllChildren(parent: Fiber, domParent: Node): void {\n let c = parent.child\n while (c) {\n const next = c.sibling\n unmountFiber(c, domParent)\n c = next\n }\n parent.child = null\n}\n\n// ---------------------------------------------------------------------------\n// DOM navigation helpers\n// ---------------------------------------------------------------------------\n\nfunction insertInto(parent: Node, node: Node, anchor: Node | null): void {\n // Anchor may have been removed or moved since it was computed (mutations\n // from unmount, boundary reveal, user code, HMR). If it's no longer a child\n // of `parent`, fall back to append \u2014 trying to insertBefore a non-child\n // throws NotFoundError and dev-loops the reconciler.\n if (anchor && anchor.parentNode === parent) {\n parent.insertBefore(node, anchor)\n } else {\n parent.appendChild(node)\n }\n}\n\nfunction getHostParent(fiber: Fiber): Node {\n let p = fiber.parent\n while (p) {\n if (p.tag === FiberTag.Host) return p.dom!\n if (p.tag === FiberTag.Root)\n return (p.stateNode as Node) || (p.dom as Node) || (p.root?.container as Node)\n if (p.tag === FiberTag.Portal) {\n // Portal renders its children into the `container` prop, not into any\n // DOM element the portal fiber \"owns\". Read the container from the\n // portal's own props so a rerenderFiber triggered on a descendant\n // (e.g. a Floating-UI-positioned popper in a Radix Portal) finds its\n // host parent \u2014 otherwise getHostParent returns undefined and the\n // next renderHost crashes reading `.namespaceURI` on undefined.\n const props = (p.pendingProps ?? p.memoizedProps) as { container?: Element } | null\n return (props?.container as Node) || (p.stateNode as Node) || (p.dom as Node) || (p.root?.container as Node)\n }\n p = p.parent\n }\n throw new Error('No host parent found.')\n}\n\nfunction getAnchor(fiber: Fiber): Node | null {\n // Return the first DOM node that comes after this fiber within the host parent\n let f: Fiber | null = fiber.sibling\n while (f) {\n const d = firstDomNode(f)\n if (d) return d\n f = f.sibling\n }\n // Ascend\n let p = fiber.parent\n while (p && p.tag !== FiberTag.Host && p.tag !== FiberTag.Root && p.tag !== FiberTag.Portal) {\n if (p.sibling) {\n const d = firstDomNode(p.sibling)\n if (d) return d\n }\n p = p.parent\n }\n return null\n}\n\nfunction firstDomNode(fiber: Fiber): Node | null {\n if (fiber.tag === FiberTag.Host || fiber.tag === FiberTag.Text) return fiber.dom\n let c = fiber.child\n while (c) {\n const d = firstDomNode(c)\n if (d) return d\n c = c.sibling\n }\n return null\n}\n\n// ---------------------------------------------------------------------------\n// Context read \u2014 exported for dispatcher.ts (useContext, use()). Delegates to\n// the installed capability so the Context feature can override with a walking\n// implementation that finds the nearest Provider fiber. When the feature is\n// stubbed, the default here returns ctx._currentValue \u2014 correct because no\n// Provider fibers exist in the tree (Provider element \u2192 Fragment via the\n// stub's type matcher).\n// ---------------------------------------------------------------------------\n\nexport function readContext(fiber: Fiber, ctx: any): any {\n return CAPABILITIES.readContext(fiber, ctx)\n}\n\nfunction defaultReadContext(_fiber: Fiber, ctx: any): any {\n return ctx._currentValue\n}\n\n// ---------------------------------------------------------------------------\n// Refs\n// ---------------------------------------------------------------------------\n\nfunction attachRef(fiber: Fiber, value: any): void {\n const ref = fiber.ref ?? (fiber.pendingProps?.ref ?? null)\n if (!ref) return\n if (typeof ref === 'function') {\n // Match React's commit-phase semantics: callback refs run after render\n // (during the layout/commit phase), not during render. Calling them\n // synchronously here breaks libraries that assert no event handlers run\n // during render (e.g. base-ui's useStableCallback trampoline).\n scheduleLifecycle(fiber, () => {\n const cleanup = ref(value)\n fiber.cleanups ||= []\n fiber.cleanups.push(typeof cleanup === 'function' ? cleanup : () => ref(null))\n })\n } else {\n ref.current = value\n }\n}\n\nfunction syncRefIfChanged(fiber: Fiber, value: any): void {\n const ref = fiber.ref ?? (fiber.pendingProps?.ref ?? null)\n if (!ref) return\n if (typeof ref === 'object' && ref.current !== value) ref.current = value\n}\n\nfunction detachRef(ref: any): void {\n // Function refs are handled via fiber.cleanups (queued in attachRef during\n // the commit phase): the cleanup either invokes the user-returned cleanup\n // fn or calls ref(null). Calling ref(null) here would double-fire it.\n if (ref && typeof ref === 'object') {\n ref.current = null\n }\n}\n\n// ---------------------------------------------------------------------------\n// Effects\n// ---------------------------------------------------------------------------\n\nconst pendingEffects: Array<{ fiber: Fiber; effect: Effect }> = []\nconst pendingLayoutEffects: Array<{ fiber: Fiber; effect: Effect }> = []\nconst pendingLifecycles: Array<{ fiber: Fiber; fn: () => void }> = []\n\nexport function enqueueEffect(fiber: Fiber, effect: Effect): void {\n if (effect.tag === 'layout' || effect.tag === 'insertion') {\n pendingLayoutEffects.push({ fiber, effect })\n } else {\n pendingEffects.push({ fiber, effect })\n }\n}\n\nexport function scheduleLifecycle(fiber: Fiber, fn: () => void): void {\n pendingLifecycles.push({ fiber, fn })\n}\n\nexport function runEffects(root: FiberRoot): void {\n // Layout effects synchronously\n while (pendingLayoutEffects.length) {\n const { fiber, effect } = pendingLayoutEffects.shift()!\n runEffect(fiber, effect, root)\n }\n // Then lifecycles\n while (pendingLifecycles.length) {\n const { fn } = pendingLifecycles.shift()!\n try {\n fn()\n } catch (e) {\n if (root.onCaughtError) root.onCaughtError(e)\n }\n }\n // Passive effects on microtask\n if (pendingEffects.length) {\n const batch = pendingEffects.splice(0)\n queueMicrotask(() => {\n for (const { fiber, effect } of batch) runEffect(fiber, effect, root)\n })\n }\n}\n\nfunction runEffect(fiber: Fiber, effect: Effect, root: FiberRoot): void {\n try {\n const cleanup = effect.create()\n effect.destroy = typeof cleanup === 'function' ? cleanup : undefined\n if (effect.destroy) {\n fiber.cleanups ||= []\n fiber.cleanups.push(effect.destroy)\n }\n } catch (e) {\n if (root.onCaughtError) root.onCaughtError(e)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nfunction isEventProp(name: string): boolean {\n return (\n name.length > 2 &&\n name.charCodeAt(0) === 111 /* o */ &&\n name.charCodeAt(1) === 110 /* n */ &&\n name.charCodeAt(2) >= 65 /* 'A'-ish: any uppercase start (onClick, onChange, \u2026) */\n )\n}\n\n"],
5
+ "mappings": "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",
6
6
  "names": ["f"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/redact",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "React, redacted. A minimal React-API-compatible drop-in replacement.",
5
5
  "type": "module",
6
6
  "main": "./dist/react/index.js",
@@ -78,10 +78,10 @@
78
78
  "optional": true
79
79
  }
80
80
  },
81
- "scripts": {
82
- "build": "echo done-by-root-build"
83
- },
84
81
  "publishConfig": {
85
82
  "access": "public"
83
+ },
84
+ "scripts": {
85
+ "build": "echo done-by-root-build"
86
86
  }
87
- }
87
+ }
@@ -373,6 +373,16 @@ export function reconcileChildren(
373
373
  for (const c of newChildren) if (c != null) unkeyedNew++
374
374
  let budget = unkeyedNew - unkeyedOld
375
375
 
376
+ // Pass 1 (this loop): match against existing fibers and build the sibling
377
+ // chain. Pass 2 (after the loop) renders each fiber with the correct
378
+ // per-child anchor — the firstDomNode of its next still-mounted sibling,
379
+ // or the parent's own anchor for the rightmost. Without per-child anchors
380
+ // a child whose render output type changes from no-DOM (Portal, null) to
381
+ // an in-flow host gets appended to the end of domParent (every child
382
+ // would otherwise share the parent's anchor) and never moves before its
383
+ // later siblings. Hit by the t3code Sidebar swap from a portal-rendering
384
+ // <Sheet> to a <div data-slot=sidebar> when isMobile flips during a
385
+ // Provider re-render.
376
386
  for (let i = 0; i < newChildren.length; i++) {
377
387
  const child = newChildren[i]
378
388
  if (child == null) continue
@@ -438,9 +448,23 @@ export function reconcileChildren(
438
448
  if (prevNewFiber) prevNewFiber.sibling = fiber
439
449
  else parent.child = fiber
440
450
  prevNewFiber = fiber
451
+ }
441
452
 
442
- // Render this fiber (mount or update)
443
- renderFiber(fiber, domParent, anchor)
453
+ // Pass 2: walk the sibling chain we just built and render each fiber
454
+ // forward with the correct per-child anchor. During hydration the cursor
455
+ // walks DOM forward and each renderFiber adopts the next existing node,
456
+ // so per-child anchors are moot — fall back to the parent's anchor.
457
+ const hydrating = !!currentRoot?.hydrating
458
+ for (let f: Fiber | null = parent.child; f; f = f.sibling) {
459
+ let a = anchor
460
+ if (!hydrating) {
461
+ // Find the firstDomNode of the next still-mounted sibling, if any.
462
+ for (let s: Fiber | null = f.sibling; s; s = s.sibling) {
463
+ const d = firstDomNode(s)
464
+ if (d && d.parentNode === domParent) { a = d; break }
465
+ }
466
+ }
467
+ renderFiber(f, domParent, a)
444
468
  }
445
469
 
446
470
  if (!prevNewFiber) parent.child = null
@@ -499,8 +523,8 @@ function placeChildrenInOrder(parent: Fiber, domParent: Node, anchor: Node | nul
499
523
  }
500
524
 
501
525
  // Pre-check: if our fiber-owned DOM is already in document order within
502
- // domParent AND the end anchor matches, no reorder is needed. This is the
503
- // common case on stable re-renders, and avoids detaching/re-attaching
526
+ // domParent AND the trailing anchor matches, no reorder is needed. This is
527
+ // the common case on stable re-renders, and avoids detaching/re-attaching
504
528
  // subtrees (which cancels CSS animations and triggers layout).
505
529
  if (doms.length > 0) {
506
530
  let current: Node | null = doms[0]!
@@ -514,6 +538,22 @@ function placeChildrenInOrder(parent: Fiber, domParent: Node, anchor: Node | nul
514
538
  }
515
539
  if (current !== doms[i]) inOrder = false
516
540
  }
541
+ // Also verify the LAST dom's next sibling lines up with `anchor`. A
542
+ // single-dom collection (or correctly-internally-ordered doms) can sit
543
+ // at the WRONG absolute position in domParent and still pass the
544
+ // relative-order check above. This happens when a fiber's render output
545
+ // changes from no-DOM (e.g. a Portal-using <Sheet>, or null) to an
546
+ // in-flow host element: the new host is appended to the end of
547
+ // domParent (because the parent reconcileChildren loop hands every
548
+ // child the same anchor — typically null), and without this trailing
549
+ // check it would never get moved before its later siblings.
550
+ if (inOrder) {
551
+ let last: Node | null = doms[doms.length - 1]!.nextSibling
552
+ while (last && !doms.includes(last as Node) && last !== anchor) {
553
+ last = last.nextSibling
554
+ }
555
+ if (last !== anchor) inOrder = false
556
+ }
517
557
  if (inOrder) return
518
558
  }
519
559