@tanstack/redact 0.0.1
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/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +7 -0
- package/dist/core/internal.d.ts +76 -0
- package/dist/core/internal.js +59 -0
- package/dist/core/internal.js.map +7 -0
- package/dist/core/types.d.ts +21 -0
- package/dist/core/types.js +10 -0
- package/dist/core/types.js.map +7 -0
- package/dist/dom/_all.d.ts +17 -0
- package/dist/dom/_all.js +51 -0
- package/dist/dom/_all.js.map +7 -0
- package/dist/dom/client.d.ts +3 -0
- package/dist/dom/client.js +8 -0
- package/dist/dom/client.js.map +7 -0
- package/dist/dom/dispatcher.d.ts +20 -0
- package/dist/dom/dispatcher.js +267 -0
- package/dist/dom/dispatcher.js.map +7 -0
- package/dist/dom/dom.d.ts +10 -0
- package/dist/dom/dom.js +262 -0
- package/dist/dom/dom.js.map +7 -0
- package/dist/dom/event-replay.d.ts +13 -0
- package/dist/dom/event-replay.js +46 -0
- package/dist/dom/event-replay.js.map +7 -0
- package/dist/dom/features/class/full.d.ts +1 -0
- package/dist/dom/features/class/full.js +91 -0
- package/dist/dom/features/class/full.js.map +7 -0
- package/dist/dom/features/class/index.d.ts +1 -0
- package/dist/dom/features/class/index.js +3 -0
- package/dist/dom/features/class/index.js.map +7 -0
- package/dist/dom/features/class/stub.d.ts +1 -0
- package/dist/dom/features/class/stub.js +50 -0
- package/dist/dom/features/class/stub.js.map +7 -0
- package/dist/dom/features/context/full.d.ts +1 -0
- package/dist/dom/features/context/full.js +49 -0
- package/dist/dom/features/context/full.js.map +7 -0
- package/dist/dom/features/context/index.d.ts +1 -0
- package/dist/dom/features/context/index.js +3 -0
- package/dist/dom/features/context/index.js.map +7 -0
- package/dist/dom/features/context/stub.d.ts +1 -0
- package/dist/dom/features/context/stub.js +22 -0
- package/dist/dom/features/context/stub.js.map +7 -0
- package/dist/dom/features/forward-ref/full.d.ts +1 -0
- package/dist/dom/features/forward-ref/full.js +51 -0
- package/dist/dom/features/forward-ref/full.js.map +7 -0
- package/dist/dom/features/forward-ref/index.d.ts +1 -0
- package/dist/dom/features/forward-ref/index.js +3 -0
- package/dist/dom/features/forward-ref/index.js.map +7 -0
- package/dist/dom/features/forward-ref/stub.d.ts +1 -0
- package/dist/dom/features/forward-ref/stub.js +22 -0
- package/dist/dom/features/forward-ref/stub.js.map +7 -0
- package/dist/dom/features/hydration/full.d.ts +61 -0
- package/dist/dom/features/hydration/full.js +264 -0
- package/dist/dom/features/hydration/full.js.map +7 -0
- package/dist/dom/features/hydration/index.d.ts +1 -0
- package/dist/dom/features/hydration/index.js +3 -0
- package/dist/dom/features/hydration/index.js.map +7 -0
- package/dist/dom/features/hydration/stub.d.ts +28 -0
- package/dist/dom/features/hydration/stub.js +66 -0
- package/dist/dom/features/hydration/stub.js.map +7 -0
- package/dist/dom/features/index.d.ts +7 -0
- package/dist/dom/features/index.js +9 -0
- package/dist/dom/features/index.js.map +7 -0
- package/dist/dom/features/lazy/full.d.ts +1 -0
- package/dist/dom/features/lazy/full.js +78 -0
- package/dist/dom/features/lazy/full.js.map +7 -0
- package/dist/dom/features/lazy/index.d.ts +1 -0
- package/dist/dom/features/lazy/index.js +3 -0
- package/dist/dom/features/lazy/index.js.map +7 -0
- package/dist/dom/features/lazy/stub.d.ts +1 -0
- package/dist/dom/features/lazy/stub.js +36 -0
- package/dist/dom/features/lazy/stub.js.map +7 -0
- package/dist/dom/features/memo/full.d.ts +1 -0
- package/dist/dom/features/memo/full.js +59 -0
- package/dist/dom/features/memo/full.js.map +7 -0
- package/dist/dom/features/memo/index.d.ts +1 -0
- package/dist/dom/features/memo/index.js +3 -0
- package/dist/dom/features/memo/index.js.map +7 -0
- package/dist/dom/features/memo/stub.d.ts +1 -0
- package/dist/dom/features/memo/stub.js +36 -0
- package/dist/dom/features/memo/stub.js.map +7 -0
- package/dist/dom/features/portal/full.d.ts +1 -0
- package/dist/dom/features/portal/full.js +19 -0
- package/dist/dom/features/portal/full.js.map +7 -0
- package/dist/dom/features/portal/index.d.ts +1 -0
- package/dist/dom/features/portal/index.js +3 -0
- package/dist/dom/features/portal/index.js.map +7 -0
- package/dist/dom/features/portal/stub.d.ts +1 -0
- package/dist/dom/features/portal/stub.js +7 -0
- package/dist/dom/features/portal/stub.js.map +7 -0
- package/dist/dom/features/suspense/full.d.ts +1 -0
- package/dist/dom/features/suspense/full.js +146 -0
- package/dist/dom/features/suspense/full.js.map +7 -0
- package/dist/dom/features/suspense/index.d.ts +1 -0
- package/dist/dom/features/suspense/index.js +3 -0
- package/dist/dom/features/suspense/index.js.map +7 -0
- package/dist/dom/features/suspense/stub.d.ts +1 -0
- package/dist/dom/features/suspense/stub.js +6 -0
- package/dist/dom/features/suspense/stub.js.map +7 -0
- package/dist/dom/index.d.ts +25 -0
- package/dist/dom/index.js +45 -0
- package/dist/dom/index.js.map +7 -0
- package/dist/dom/portal.d.ts +2 -0
- package/dist/dom/portal.js +15 -0
- package/dist/dom/portal.js.map +7 -0
- package/dist/dom/reconcile.d.ts +40 -0
- package/dist/dom/reconcile.js +795 -0
- package/dist/dom/reconcile.js.map +7 -0
- package/dist/dom/root.d.ts +15 -0
- package/dist/dom/root.js +85 -0
- package/dist/dom/root.js.map +7 -0
- package/dist/dom/test-utils.d.ts +1 -0
- package/dist/dom/test-utils.js +10 -0
- package/dist/dom/test-utils.js.map +7 -0
- package/dist/react/children.d.ts +8 -0
- package/dist/react/children.js +75 -0
- package/dist/react/children.js.map +7 -0
- package/dist/react/class.d.ts +31 -0
- package/dist/react/class.js +40 -0
- package/dist/react/class.js.map +7 -0
- package/dist/react/context.d.ts +27 -0
- package/dist/react/context.js +31 -0
- package/dist/react/context.js.map +7 -0
- package/dist/react/element.d.ts +10 -0
- package/dist/react/element.js +64 -0
- package/dist/react/element.js.map +7 -0
- package/dist/react/hooks.d.ts +37 -0
- package/dist/react/hooks.js +146 -0
- package/dist/react/hooks.js.map +7 -0
- package/dist/react/index.d.ts +76 -0
- package/dist/react/index.js +187 -0
- package/dist/react/index.js.map +7 -0
- package/dist/react/jsx-runtime.d.ts +5 -0
- package/dist/react/jsx-runtime.js +21 -0
- package/dist/react/jsx-runtime.js.map +7 -0
- package/dist/react/memo.d.ts +29 -0
- package/dist/react/memo.js +47 -0
- package/dist/react/memo.js.map +7 -0
- package/dist/react/portal.d.ts +1 -0
- package/dist/react/portal.js +6 -0
- package/dist/react/portal.js.map +7 -0
- package/dist/react/shared-internals.d.ts +33 -0
- package/dist/react/shared-internals.js +29 -0
- package/dist/react/shared-internals.js.map +7 -0
- package/dist/react/suspense.d.ts +15 -0
- package/dist/react/suspense.js +16 -0
- package/dist/react/suspense.js.map +7 -0
- package/dist/scheduler/index.d.ts +44 -0
- package/dist/scheduler/index.js +109 -0
- package/dist/scheduler/index.js.map +7 -0
- package/dist/server/bootstrap-script.d.ts +22 -0
- package/dist/server/bootstrap-script.js +16 -0
- package/dist/server/bootstrap-script.js.map +7 -0
- package/dist/server/dispatcher.d.ts +37 -0
- package/dist/server/dispatcher.js +140 -0
- package/dist/server/dispatcher.js.map +7 -0
- package/dist/server/escape.d.ts +7 -0
- package/dist/server/escape.js +159 -0
- package/dist/server/escape.js.map +7 -0
- package/dist/server/index.d.ts +16 -0
- package/dist/server/index.js +26 -0
- package/dist/server/index.js.map +7 -0
- package/dist/server/renderToString.d.ts +7 -0
- package/dist/server/renderToString.js +29 -0
- package/dist/server/renderToString.js.map +7 -0
- package/dist/server/stream.d.ts +40 -0
- package/dist/server/stream.js +200 -0
- package/dist/server/stream.js.map +7 -0
- package/dist/server/walk.d.ts +33 -0
- package/dist/server/walk.js +298 -0
- package/dist/server/walk.js.map +7 -0
- package/dist/vite/index.d.ts +96 -0
- package/dist/vite/index.js +217 -0
- package/dist/vite/index.js.map +7 -0
- package/package.json +83 -0
- package/src/core/index.ts +2 -0
- package/src/core/internal.ts +107 -0
- package/src/core/types.ts +36 -0
- package/src/dom/_all.ts +54 -0
- package/src/dom/client.ts +4 -0
- package/src/dom/dispatcher.ts +318 -0
- package/src/dom/dom.ts +316 -0
- package/src/dom/event-replay.ts +55 -0
- package/src/dom/features/class/full.ts +104 -0
- package/src/dom/features/class/index.ts +1 -0
- package/src/dom/features/class/stub.ts +65 -0
- package/src/dom/features/context/full.ts +57 -0
- package/src/dom/features/context/index.ts +1 -0
- package/src/dom/features/context/stub.ts +32 -0
- package/src/dom/features/forward-ref/full.ts +54 -0
- package/src/dom/features/forward-ref/index.ts +1 -0
- package/src/dom/features/forward-ref/stub.ts +28 -0
- package/src/dom/features/hydration/full.ts +345 -0
- package/src/dom/features/hydration/index.ts +1 -0
- package/src/dom/features/hydration/stub.ts +72 -0
- package/src/dom/features/index.ts +11 -0
- package/src/dom/features/lazy/full.ts +98 -0
- package/src/dom/features/lazy/index.ts +1 -0
- package/src/dom/features/lazy/stub.ts +45 -0
- package/src/dom/features/memo/full.ts +74 -0
- package/src/dom/features/memo/index.ts +1 -0
- package/src/dom/features/memo/stub.ts +42 -0
- package/src/dom/features/portal/full.ts +22 -0
- package/src/dom/features/portal/index.ts +1 -0
- package/src/dom/features/portal/stub.ts +11 -0
- package/src/dom/features/suspense/full.ts +191 -0
- package/src/dom/features/suspense/index.ts +1 -0
- package/src/dom/features/suspense/stub.ts +12 -0
- package/src/dom/index.ts +33 -0
- package/src/dom/portal.ts +16 -0
- package/src/dom/reconcile.ts +1169 -0
- package/src/dom/root.ts +107 -0
- package/src/dom/test-utils.ts +6 -0
- package/src/react/children.ts +85 -0
- package/src/react/class.ts +56 -0
- package/src/react/context.ts +50 -0
- package/src/react/element.ts +80 -0
- package/src/react/hooks.ts +190 -0
- package/src/react/index.ts +132 -0
- package/src/react/jsx-runtime.ts +16 -0
- package/src/react/memo.ts +45 -0
- package/src/react/portal.ts +1 -0
- package/src/react/shared-internals.ts +79 -0
- package/src/react/suspense.ts +18 -0
- package/src/scheduler/index.ts +124 -0
- package/src/server/bootstrap-script.ts +52 -0
- package/src/server/dispatcher.ts +158 -0
- package/src/server/escape.ts +187 -0
- package/src/server/index.ts +26 -0
- package/src/server/renderToString.ts +33 -0
- package/src/server/stream.ts +302 -0
- package/src/server/walk.ts +448 -0
- package/src/vite/index.ts +401 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/vite/index.ts"],
|
|
4
|
+
"sourcesContent": ["import { existsSync, readFileSync, realpathSync } from 'node:fs'\nimport { dirname, resolve as resolvePath } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport type RedactPreset = 'nano' | 'full'\n\n/**\n * Opt-in feature set. Each flag toggles whether the feature's real\n * implementation ships (`true`) or is swapped with a stub module that\n * degrades gracefully (`false`). Missing keys fall back to the preset's\n * default. Adding a feature to this interface propagates to consumer\n * configs as autocompleted options.\n */\nexport interface RedactFeatures {\n /**\n * `createPortal`. When `false`, portal elements render in place as a\n * Fragment (the `container` prop is ignored). `renderPortal` and its\n * deps are stripped from the bundle.\n */\n portal?: boolean\n /**\n * `createContext` / `useContext` / `<Provider>` / `<Consumer>`. When\n * `false`, Providers render as Fragments (value never propagates),\n * Consumers invoke their function-children with the context's default\n * value, and `useContext` returns the default. Provider-walk logic and\n * `renderProvider` are stripped.\n */\n context?: boolean\n /**\n * `<Suspense>` boundaries + streaming hydration. When `false`, Suspense\n * elements render as Fragments (children mount inline, `fallback` is\n * ignored). Thrown thenables still schedule a re-render on settle, so\n * eventual consistency works \u2014 just no fallback UI during the pending\n * window. Boundary-handler stack and hydration integration are stripped.\n */\n suspense?: boolean\n /**\n * `React.memo`. When `false`, memoized components still render but without\n * the prop-equality gate \u2014 every parent rerender passes through.\n * `shallowEqual` and the force-rerender bypass are stripped.\n */\n memo?: boolean\n /**\n * `React.forwardRef`. When `false`, forwardRef components still render but\n * the ref prop isn't forwarded to the inner function. React 19+ treats\n * refs as normal props on function components anyway, so most apps can\n * drop this. The dispatcher save/restore machinery is stripped.\n */\n forwardRef?: boolean\n /**\n * `React.lazy`. When `false`, lazy elements still resolve if their payload\n * is already available synchronously (e.g. pre-awaited RSC Flight); async\n * resolution throws a clear error. The hydration-deferred-reveal path and\n * Suspense coordination are stripped.\n */\n lazy?: boolean\n /**\n * Class components (`extends Component`). When `false`, class components\n * still render but only honor the core contract: constructor + `render()`\n * + `setState`. Dropped: `contextType`, `getDerivedStateFromProps`,\n * `shouldComponentUpdate`, `componentDidMount`/`Update`/`WillUnmount`,\n * `getDerivedStateFromError`/`componentDidCatch` (error boundaries).\n */\n classComponents?: boolean\n /**\n * SSR hydration (`hydrateRoot`). When `false`, `hydrateRoot` throws\n * (use `createRoot` for SPAs). The HydrationCursor / DOM adoption /\n * streaming-boundary coordination / event-replay / scroll-guard\n * machinery is stripped \u2014 the biggest single chunk of reducible code.\n */\n hydration?: boolean\n}\n\ninterface ResolvedFeatures {\n portal: boolean\n context: boolean\n suspense: boolean\n memo: boolean\n forwardRef: boolean\n lazy: boolean\n classComponents: boolean\n hydration: boolean\n}\n\nconst PRESET_DEFAULTS: Record<RedactPreset, ResolvedFeatures> = {\n // Opt-in: everything off. Turn individual features on via `features`.\n nano: {\n portal: false, context: false, suspense: false, memo: false,\n forwardRef: false, lazy: false, classComponents: false, hydration: false,\n },\n // Opt-out: everything on (drop-in React parity). Turn features off via `features`.\n full: {\n portal: true, context: true, suspense: true, memo: true,\n forwardRef: true, lazy: true, classComponents: true, hydration: true,\n },\n}\n\nfunction resolveFeatures(\n preset: RedactPreset,\n overrides: RedactFeatures,\n): ResolvedFeatures {\n const p = PRESET_DEFAULTS[preset]\n return {\n portal: overrides.portal ?? p.portal,\n context: overrides.context ?? p.context,\n suspense: overrides.suspense ?? p.suspense,\n memo: overrides.memo ?? p.memo,\n forwardRef: overrides.forwardRef ?? p.forwardRef,\n lazy: overrides.lazy ?? p.lazy,\n classComponents: overrides.classComponents ?? p.classComponents,\n hydration: overrides.hydration ?? p.hydration,\n }\n}\n\nexport interface RedactOptions {\n /** Skip aliasing specific specifiers, e.g. if a consumer wants real React somewhere. */\n skip?: ReadonlyArray<string>\n /**\n * Override package resolution root. Defaults to the Vite config root. Useful\n * for monorepos where the plugin lives in a different workspace than the\n * consumer app.\n */\n resolveFrom?: string\n /**\n * Explicit package roots, bypassing node_modules lookup. Keys are package\n * names (e.g. `@tanstack/redact`), values are absolute paths to the package\n * directory. Handy for cross-workspace testing / bring-your-own-build setups.\n */\n packageRoots?: Record<string, string>\n /**\n * Starting point for feature selection. `'full'` (default) turns every\n * feature on \u2014 drop-in React parity, opt-out individual features via\n * `features`. `'nano'` turns everything off \u2014 opt in to what you need.\n */\n preset?: RedactPreset\n /**\n * Per-feature overrides merged on top of the preset's defaults. Enables\n * fine-grained \"preset minus X\" or \"preset plus Y\" configurations.\n */\n features?: RedactFeatures\n}\n\n// Alias map. ORDER MATTERS \u2014 Vite's alias matcher uses first-match against\n// prefix, so more-specific specifiers MUST come before less-specific ones.\n// Without this, `react-dom/server` would prefix-match `react-dom` first and\n// resolve to `@tanstack/redact/dom/server` (wrong) instead of\n// `@tanstack/redact/server`.\n//\n// `use-sync-external-store` aliases are here because its CJS-only React 17\n// compat shim does `var React = require('react')`. That survives Vite's\n// pre-bundling intact and explodes in Cloudflare Workers (no `require`).\n// Modern React has `useSyncExternalStore` built-in, and `@tanstack/redact`\n// additionally exports `useSyncExternalStoreWithSelector` so this alias\n// is safe everywhere.\nconst ALIASES: Record<string, string> = {\n // ---- most-specific first ----\n 'use-sync-external-store/shim/with-selector': '@tanstack/redact',\n 'use-sync-external-store/shim/with-selector.js': '@tanstack/redact',\n 'use-sync-external-store/with-selector': '@tanstack/redact',\n 'use-sync-external-store/with-selector.js': '@tanstack/redact',\n 'use-sync-external-store/shim': '@tanstack/redact',\n 'use-sync-external-store': '@tanstack/redact',\n\n // React drop-in shim targets. Subpaths first.\n 'react/jsx-runtime': '@tanstack/redact/jsx-runtime',\n 'react/jsx-dev-runtime': '@tanstack/redact/jsx-dev-runtime',\n 'react-dom/client': '@tanstack/redact/dom-client',\n 'react-dom/server': '@tanstack/redact/server',\n 'react-dom/test-utils': '@tanstack/redact/dom-test-utils',\n 'react-dom': '@tanstack/redact/dom',\n react: '@tanstack/redact',\n scheduler: '@tanstack/redact/scheduler',\n\n // Self-aliases so Vite resolves `@tanstack/redact/*` imports to the same\n // canonical file path no matter where they originate (worker bundle vs\n // deps_ssr pre-bundle vs source). Without these, Cloudflare's\n // `noExternal: true` worker config inlines one copy while Vite's\n // optimizeDeps pre-bundles another, ending up with two separate\n // ReactSharedInternals instances and a null dispatcher in user hooks.\n // Subpaths first here too.\n '@tanstack/redact/jsx-runtime': '@tanstack/redact/jsx-runtime',\n '@tanstack/redact/jsx-dev-runtime': '@tanstack/redact/jsx-dev-runtime',\n '@tanstack/redact/dom-client': '@tanstack/redact/dom-client',\n '@tanstack/redact/dom-test-utils': '@tanstack/redact/dom-test-utils',\n '@tanstack/redact/server': '@tanstack/redact/server',\n '@tanstack/redact/scheduler': '@tanstack/redact/scheduler',\n '@tanstack/redact/dom': '@tanstack/redact/dom',\n '@tanstack/redact': '@tanstack/redact',\n}\n\nfunction splitSpecifier(specifier: string): { pkg: string; sub: string } {\n if (specifier.startsWith('@')) {\n const slash1 = specifier.indexOf('/')\n const slash2 = specifier.indexOf('/', slash1 + 1)\n if (slash2 < 0) return { pkg: specifier, sub: '' }\n return { pkg: specifier.slice(0, slash2), sub: specifier.slice(slash2 + 1) }\n }\n const slash = specifier.indexOf('/')\n if (slash < 0) return { pkg: specifier, sub: '' }\n return { pkg: specifier.slice(0, slash), sub: specifier.slice(slash + 1) }\n}\n\nfunction findPackageDir(pkg: string, fromDir: string): string | null {\n let dir = fromDir\n while (true) {\n const candidate = resolvePath(dir, 'node_modules', pkg)\n if (existsSync(resolvePath(candidate, 'package.json'))) return candidate\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\nfunction resolveExport(packageDir: string, sub: string): string | null {\n const pkgJsonPath = resolvePath(packageDir, 'package.json')\n let pkg: any\n try {\n pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))\n } catch {\n return null\n }\n const key = sub ? './' + sub : '.'\n const exp = pkg.exports?.[key]\n // Prefer published `import` (dist/.js) over `source` \u2014 dist is a single\n // transformed bundle so Vite's dep optimizer doesn't thrash on dozens of\n // individual source files. The package keeps cross-subpath imports\n // external, so there's still only one runtime instance.\n const pick = (v: any): string | null => {\n if (typeof v === 'string') return v\n if (v && typeof v === 'object') {\n return pick(v.import ?? v.module ?? v.source ?? v.default ?? null)\n }\n return null\n }\n const target = pick(exp)\n if (target) return resolvePath(packageDir, target)\n if (!sub) {\n const main = pkg.module ?? pkg.main\n if (typeof main === 'string') return resolvePath(packageDir, main)\n }\n return null\n}\n\n// When installed from npm, `@tanstack/redact` is declared as a `dependency`\n// of consumer apps. Under pnpm's strict mode it ends up nested under the\n// plugin's own `.pnpm/@tanstack+redact@.../node_modules/` rather than\n// hoisted to the consumer's root, so a `findPackageDir` walk starting at\n// the Vite project root won't always find it. Search from the plugin's own\n// directory first (which walks into its nested node_modules), then fall\n// back to the consumer root for hoisted installs.\nconst pluginDir = dirname(fileURLToPath(import.meta.url))\n\nfunction resolveSpecifier(\n specifier: string,\n fromDir: string,\n packageRoots: Record<string, string>,\n): string | null {\n const { pkg, sub } = splitSpecifier(specifier)\n const packageDir =\n packageRoots[pkg] ??\n findPackageDir(pkg, pluginDir) ??\n findPackageDir(pkg, fromDir)\n if (!packageDir) return null\n const target = resolveExport(packageDir, sub)\n if (!target) return null\n // Canonicalize through pnpm symlinks. Under strict pnpm, the package may\n // live nested under `.pnpm/@tanstack+redact@.../node_modules/*`, but each\n // of those is itself a symlink to the flat `.pnpm/@tanstack+redact@.../`\n // entry. Vite's `fetchModule` (used by TanStack Start's server-fn\n // compiler) follows the realpath, so the id seen by the capture-transform\n // differs from the nested id we'd return. That leaves the compiler's\n // moduleCache keyed on the realpath while `getModuleInfo` looks up the\n // nested path \u2192 miss \u2192 \"could not load module info\". Returning the\n // canonical realpath here keeps the two sides in agreement.\n try {\n return realpathSync(target)\n } catch {\n return target\n }\n}\n\nexport function redact(options: RedactOptions = {}): any {\n const skip = new Set(options.skip ?? [])\n const entries = Object.entries(ALIASES).filter(([k]) => !skip.has(k))\n const features = resolveFeatures(options.preset ?? 'full', options.features ?? {})\n\n const resolvedMap: Record<string, string> = {}\n let done = false\n\n function resolveAll(root: string): void {\n if (done) return\n const fromDir = options.resolveFrom ?? root\n const packageRoots = options.packageRoots ?? {}\n for (const [from, to] of entries) {\n const resolved = resolveSpecifier(to, fromDir, packageRoots)\n if (resolved) resolvedMap[from] = resolved\n }\n done = true\n }\n\n return {\n name: 'redact',\n enforce: 'pre',\n\n config() {\n const excludeList = entries.map(([k]) => k)\n // Single package \u2014 only one name to dedupe / no-external.\n const noExt = ['@tanstack/redact']\n // Top-level resolve.alias so `react` \u2192 `@tanstack/redact` happens\n // BEFORE any plugin-based resolveId hook fires. The Cloudflare\n // vite-plugin's rolldown worker-runner pre-scans the worker entry's\n // exports and resolves bare specifiers via Vite's alias map directly\n // (not via plugin hooks), so without this it would resolve `react` to\n // the real npm package and try to `require()` it in a Worker (no CJS\n // support). Object form is required \u2014 array form is silently ignored\n // by rolldown's worker-runner.\n const aliasMap = Object.fromEntries(entries.filter(([from, to]) => from !== to))\n // Scope optimizeDeps to client + ssr environments ONLY. Do NOT set a\n // top-level optimizeDeps \u2014 in Vite 6+ that's effectively the client\n // env's default but also seeps into the rsc env's `'use client'`\n // analysis, causing flood warnings like \"inconsistently optimized\".\n // Dedupe `@tanstack/redact` so Vite resolves it to a single instance\n // even when multiple packages (e.g. @tanstack/react-router and user\n // code) drag it into different parts of the module graph.\n const dedupe = noExt\n return {\n resolve: {\n alias: aliasMap,\n dedupe,\n },\n environments: {\n client: {\n optimizeDeps: { exclude: excludeList },\n },\n ssr: {\n optimizeDeps: { exclude: excludeList },\n resolve: { noExternal: noExt },\n },\n },\n ssr: { noExternal: noExt },\n }\n },\n\n configResolved(config: any) {\n resolveAll(config.root)\n // With `packageRoots`, package sources live outside the consumer's Vite\n // project root, so the default server.fs.allow list blocks them. Append\n // to the resolved allow list rather than replacing via `config()`, so we\n // keep Vite's defaults (root + node_modules + client runtime).\n const fsAllow = Object.values(options.packageRoots ?? {})\n if (fsAllow.length && config.server?.fs?.allow) {\n for (const p of fsAllow) {\n if (!config.server.fs.allow.includes(p)) {\n config.server.fs.allow.push(p)\n }\n }\n }\n },\n\n async resolveId(this: any, id: string, importer?: string, opts?: any) {\n // Skip the RSC environment \u2014 it relies on real React internals via\n // @vitejs/plugin-rsc's vendored react-server-dom. Substituting our\n // shim there breaks Flight serialization. Client + SSR envs still swap.\n const envName = this?.environment?.name\n if (envName === 'rsc') return null\n\n // Feature-flag swap: when the reconciler's `features/index` module\n // imports a feature by relative path, redirect to that feature's stub\n // if the flag is off. The stub registers a graceful-degradation\n // matcher (e.g. Portal \u2192 Fragment) so user code keeps working.\n if (importer && /[\\\\/]features[\\\\/]index\\.[jt]sx?$/.test(importer)) {\n const m = id.match(/^\\.\\/([a-z-]+)$/)\n if (m) {\n const name = m[1] as keyof ResolvedFeatures\n if (name in features && !features[name]) {\n const r = await this.resolve(`./${name}/stub`, importer, {\n ...opts,\n skipSelf: true,\n })\n if (r) return r.id\n }\n }\n }\n\n // Hydration swap: hydration isn't self-registering, so it's imported\n // from reconcile.ts, root.ts, and the Suspense/Lazy feature modules.\n // Any specifier ending in `/hydration` that resolves to our feature\n // module gets redirected to the stub when the flag is off.\n if (!features.hydration && importer && /[\\\\/]hydration$/.test(id)) {\n const r = await this.resolve(id, importer, { ...opts, skipSelf: true })\n if (r && /features[\\\\/]hydration[\\\\/]index\\.(ts|js)$/.test(r.id)) {\n return r.id.replace(/index\\.(ts|js)$/, 'stub.$1')\n }\n }\n\n return resolvedMap[id] ?? null\n },\n }\n}\n\nexport default redact\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tanstack/redact",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "React, redacted. A minimal React-API-compatible drop-in replacement.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/react/index.js",
|
|
7
|
+
"module": "./dist/react/index.js",
|
|
8
|
+
"types": "./dist/react/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/react/index.d.ts",
|
|
12
|
+
"import": "./dist/react/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./jsx-runtime": {
|
|
15
|
+
"types": "./dist/react/jsx-runtime.d.ts",
|
|
16
|
+
"import": "./dist/react/jsx-runtime.js"
|
|
17
|
+
},
|
|
18
|
+
"./jsx-dev-runtime": {
|
|
19
|
+
"types": "./dist/react/jsx-runtime.d.ts",
|
|
20
|
+
"import": "./dist/react/jsx-runtime.js"
|
|
21
|
+
},
|
|
22
|
+
"./dom": {
|
|
23
|
+
"types": "./dist/dom/index.d.ts",
|
|
24
|
+
"import": "./dist/dom/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./dom-client": {
|
|
27
|
+
"types": "./dist/dom/client.d.ts",
|
|
28
|
+
"import": "./dist/dom/client.js"
|
|
29
|
+
},
|
|
30
|
+
"./dom-test-utils": {
|
|
31
|
+
"types": "./dist/dom/test-utils.d.ts",
|
|
32
|
+
"import": "./dist/dom/test-utils.js"
|
|
33
|
+
},
|
|
34
|
+
"./server": {
|
|
35
|
+
"types": "./dist/server/index.d.ts",
|
|
36
|
+
"import": "./dist/server/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./scheduler": {
|
|
39
|
+
"types": "./dist/scheduler/index.d.ts",
|
|
40
|
+
"import": "./dist/scheduler/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./vite": {
|
|
43
|
+
"types": "./dist/vite/index.d.ts",
|
|
44
|
+
"import": "./dist/vite/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./features/*": {
|
|
47
|
+
"types": "./dist/dom/features/*.d.ts",
|
|
48
|
+
"import": "./dist/dom/features/*.js"
|
|
49
|
+
},
|
|
50
|
+
"./_all": {
|
|
51
|
+
"types": "./dist/dom/_all.d.ts",
|
|
52
|
+
"import": "./dist/dom/_all.js"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"files": [
|
|
56
|
+
"dist",
|
|
57
|
+
"src"
|
|
58
|
+
],
|
|
59
|
+
"sideEffects": [
|
|
60
|
+
"./src/dom/features/**",
|
|
61
|
+
"./dist/dom/features/**",
|
|
62
|
+
"./src/dom/index.ts",
|
|
63
|
+
"./src/dom/client.ts",
|
|
64
|
+
"./src/dom/_all.ts",
|
|
65
|
+
"./dist/dom/index.js",
|
|
66
|
+
"./dist/dom/client.js",
|
|
67
|
+
"./dist/dom/_all.js"
|
|
68
|
+
],
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"vite": ">=5"
|
|
71
|
+
},
|
|
72
|
+
"peerDependenciesMeta": {
|
|
73
|
+
"vite": {
|
|
74
|
+
"optional": true
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"scripts": {
|
|
78
|
+
"build": "echo done-by-root-build"
|
|
79
|
+
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode, Ref } from './types'
|
|
2
|
+
|
|
3
|
+
export const enum FiberTag {
|
|
4
|
+
Host = 0,
|
|
5
|
+
Text = 1,
|
|
6
|
+
Function = 2,
|
|
7
|
+
Class = 3,
|
|
8
|
+
Fragment = 4,
|
|
9
|
+
Portal = 5,
|
|
10
|
+
Provider = 6,
|
|
11
|
+
Consumer = 7,
|
|
12
|
+
ForwardRef = 8,
|
|
13
|
+
Memo = 9,
|
|
14
|
+
Lazy = 10,
|
|
15
|
+
Suspense = 11,
|
|
16
|
+
Root = 12,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const enum FiberFlag {
|
|
20
|
+
None = 0,
|
|
21
|
+
Placement = 1 << 0,
|
|
22
|
+
Update = 1 << 1,
|
|
23
|
+
Deletion = 1 << 2,
|
|
24
|
+
Ref = 1 << 3,
|
|
25
|
+
Effect = 1 << 4,
|
|
26
|
+
LayoutEffect = 1 << 5,
|
|
27
|
+
ContentReset = 1 << 6,
|
|
28
|
+
DidCapture = 1 << 7,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface Hook {
|
|
32
|
+
state: any
|
|
33
|
+
queue: any
|
|
34
|
+
deps: any
|
|
35
|
+
cleanup: any
|
|
36
|
+
next: Hook | null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface Effect {
|
|
40
|
+
tag: 'effect' | 'layout' | 'insertion'
|
|
41
|
+
create: () => any
|
|
42
|
+
destroy: (() => void) | void
|
|
43
|
+
deps: ReadonlyArray<unknown> | undefined
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface Fiber {
|
|
47
|
+
tag: FiberTag
|
|
48
|
+
type: any
|
|
49
|
+
key: string | null
|
|
50
|
+
ref: Ref<any> | null
|
|
51
|
+
pendingProps: any
|
|
52
|
+
memoizedProps: any
|
|
53
|
+
memoizedState: any
|
|
54
|
+
stateNode: any
|
|
55
|
+
dom: Node | null
|
|
56
|
+
parent: Fiber | null
|
|
57
|
+
child: Fiber | null
|
|
58
|
+
sibling: Fiber | null
|
|
59
|
+
hooks: Hook | null
|
|
60
|
+
effects: Effect[] | null
|
|
61
|
+
layoutEffects: Effect[] | null
|
|
62
|
+
cleanups: Array<() => void> | null
|
|
63
|
+
flags: FiberFlag
|
|
64
|
+
dirty: boolean
|
|
65
|
+
unmounted: boolean
|
|
66
|
+
root: FiberRoot | null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface FiberRoot {
|
|
70
|
+
container: Element | DocumentFragment
|
|
71
|
+
current: Fiber
|
|
72
|
+
pending: Set<Fiber>
|
|
73
|
+
scheduled: boolean
|
|
74
|
+
onRecoverableError?: (err: unknown) => void
|
|
75
|
+
onCaughtError?: (err: unknown) => void
|
|
76
|
+
onUncaughtError?: (err: unknown) => void
|
|
77
|
+
identifierPrefix: string
|
|
78
|
+
hydrating: boolean
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function createFiber(tag: FiberTag, type: any, key: string | null): Fiber {
|
|
82
|
+
return {
|
|
83
|
+
tag,
|
|
84
|
+
type,
|
|
85
|
+
key,
|
|
86
|
+
ref: null,
|
|
87
|
+
pendingProps: null,
|
|
88
|
+
memoizedProps: null,
|
|
89
|
+
memoizedState: null,
|
|
90
|
+
stateNode: null,
|
|
91
|
+
dom: null,
|
|
92
|
+
parent: null,
|
|
93
|
+
child: null,
|
|
94
|
+
sibling: null,
|
|
95
|
+
hooks: null,
|
|
96
|
+
effects: null,
|
|
97
|
+
layoutEffects: null,
|
|
98
|
+
cleanups: null,
|
|
99
|
+
flags: FiberFlag.None,
|
|
100
|
+
dirty: false,
|
|
101
|
+
unmounted: false,
|
|
102
|
+
root: null,
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export type ChildNode = ReactElement | string | number | boolean | null | undefined | ChildNode[]
|
|
107
|
+
export type { ReactElement, ReactNode }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// React 19+ uses the transitional element symbol. When our shim's elements
|
|
2
|
+
// are passed to react-dom (e.g. Start routing through real react-dom/server
|
|
3
|
+
// somewhere), they must carry the symbol that React's isValidElement checks.
|
|
4
|
+
export const REACT_ELEMENT_TYPE = Symbol.for('react.transitional.element')
|
|
5
|
+
export const REACT_LEGACY_ELEMENT_TYPE = Symbol.for('react.element')
|
|
6
|
+
export const REACT_FRAGMENT_TYPE = Symbol.for('react.fragment')
|
|
7
|
+
|
|
8
|
+
export type Key = string | number | null | undefined
|
|
9
|
+
|
|
10
|
+
export interface ReactElement<P = any, T = any> {
|
|
11
|
+
$$typeof: typeof REACT_ELEMENT_TYPE
|
|
12
|
+
type: T
|
|
13
|
+
key: string | null
|
|
14
|
+
ref: any
|
|
15
|
+
props: P
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type ReactNode =
|
|
19
|
+
| ReactElement
|
|
20
|
+
| string
|
|
21
|
+
| number
|
|
22
|
+
| boolean
|
|
23
|
+
| null
|
|
24
|
+
| undefined
|
|
25
|
+
| Iterable<ReactNode>
|
|
26
|
+
|
|
27
|
+
export type RefObject<T> = { current: T | null }
|
|
28
|
+
export type RefCallback<T> = (instance: T | null) => void | (() => void)
|
|
29
|
+
export type Ref<T> = RefObject<T> | RefCallback<T> | null
|
|
30
|
+
|
|
31
|
+
export type Dispatch<A> = (value: A) => void
|
|
32
|
+
export type SetStateAction<S> = S | ((prev: S) => S)
|
|
33
|
+
|
|
34
|
+
export type EffectCallback = () => void | (() => void)
|
|
35
|
+
export type DependencyList = ReadonlyArray<unknown>
|
|
36
|
+
|
package/src/dom/_all.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Unified entry exposing both top-level public API (createRoot, hydrateRoot,
|
|
2
|
+
// createPortal, …) and the registration primitives that custom features and
|
|
3
|
+
// custom bundler plugins need to hook into the reconciler. Reachable as
|
|
4
|
+
// `@tanstack/redact/_all` via the package's subpath exports. Single-instance
|
|
5
|
+
// state for things like the hydration CLAIMED WeakSet, scheduler queue,
|
|
6
|
+
// dispatcher H slot, etc. is preserved because every public entry funnels
|
|
7
|
+
// through this module.
|
|
8
|
+
|
|
9
|
+
// Side-effect import: registers all opt-in features (renderers, type matchers,
|
|
10
|
+
// element markers) with the reconciler. A vite plugin may alias individual
|
|
11
|
+
// feature modules to ./features/<name>/stub to strip them from the bundle.
|
|
12
|
+
import './features'
|
|
13
|
+
|
|
14
|
+
// Top-level public API (mirrors the surface of /, /dom, /dom-client).
|
|
15
|
+
export { flushSync, batchedUpdates as unstable_batchedUpdates } from './root'
|
|
16
|
+
export { createRoot, hydrateRoot } from './root'
|
|
17
|
+
export type { Root, RootOptions } from './root'
|
|
18
|
+
export { createPortal } from './portal'
|
|
19
|
+
export { act } from './test-utils'
|
|
20
|
+
|
|
21
|
+
// Resource hints — stubs
|
|
22
|
+
export function preconnect(_href: string, _opts?: any): void {}
|
|
23
|
+
export function prefetchDNS(_href: string): void {}
|
|
24
|
+
export function preload(_href: string, _opts?: any): void {}
|
|
25
|
+
export function preinit(_href: string, _opts?: any): void {}
|
|
26
|
+
export function preloadModule(_href: string, _opts?: any): void {}
|
|
27
|
+
export function preinitModule(_href: string, _opts?: any): void {}
|
|
28
|
+
|
|
29
|
+
export const version = '19.2.3'
|
|
30
|
+
|
|
31
|
+
// Registration primitives — needed by custom features
|
|
32
|
+
// (`registerRenderer`, `registerTypeMatcher`, `registerElementMarker`) and by
|
|
33
|
+
// anything that wants to override a cross-cutting concern like Suspense's
|
|
34
|
+
// `handleSuspended` or Context's `readContext` (`installCapability`). The
|
|
35
|
+
// built-in features in `./features/*/{full,stub}.ts` use these via relative
|
|
36
|
+
// imports; external authors reach them through this entry. Order-of-
|
|
37
|
+
// registration matters: later calls overwrite earlier ones.
|
|
38
|
+
export {
|
|
39
|
+
registerRenderer,
|
|
40
|
+
registerTypeMatcher,
|
|
41
|
+
registerElementMarker,
|
|
42
|
+
installCapability,
|
|
43
|
+
reconcileChildren,
|
|
44
|
+
childrenToArray,
|
|
45
|
+
} from './reconcile'
|
|
46
|
+
export type {
|
|
47
|
+
RenderFn,
|
|
48
|
+
TypeMatcher,
|
|
49
|
+
Capabilities,
|
|
50
|
+
} from './reconcile'
|
|
51
|
+
|
|
52
|
+
// Core types most custom features need.
|
|
53
|
+
export { FiberTag } from '../core'
|
|
54
|
+
export type { Fiber, FiberRoot, ReactNode, ReactElement } from '../core'
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import type { Hook, Fiber, FiberRoot, Effect } from '../core'
|
|
2
|
+
import { ReactSharedInternals, REACT_CONTEXT_TYPE } from '../react'
|
|
3
|
+
import { scheduleUpdate, enqueueEffect, readContext } from './reconcile'
|
|
4
|
+
|
|
5
|
+
function getCurrentFiber(): Fiber {
|
|
6
|
+
const f = ReactSharedInternals.currentFiber
|
|
7
|
+
if (!f) throw new Error('Hook called outside a function component render.')
|
|
8
|
+
return f
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function nextHook(): Hook {
|
|
12
|
+
const fiber = getCurrentFiber()
|
|
13
|
+
const idx = ReactSharedInternals.hookIndex++
|
|
14
|
+
|
|
15
|
+
let prev = ReactSharedInternals.currentHook
|
|
16
|
+
|
|
17
|
+
if (idx === 0) {
|
|
18
|
+
if (fiber.hooks) {
|
|
19
|
+
ReactSharedInternals.currentHook = fiber.hooks
|
|
20
|
+
return fiber.hooks
|
|
21
|
+
}
|
|
22
|
+
const h: Hook = { state: undefined, queue: undefined, deps: undefined, cleanup: undefined, next: null }
|
|
23
|
+
fiber.hooks = h
|
|
24
|
+
ReactSharedInternals.currentHook = h
|
|
25
|
+
return h
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (prev && prev.next) {
|
|
29
|
+
ReactSharedInternals.currentHook = prev.next
|
|
30
|
+
return prev.next
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const h: Hook = { state: undefined, queue: undefined, deps: undefined, cleanup: undefined, next: null }
|
|
34
|
+
if (prev) prev.next = h
|
|
35
|
+
else fiber.hooks = h
|
|
36
|
+
ReactSharedInternals.currentHook = h
|
|
37
|
+
return h
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function depsEqual(
|
|
41
|
+
a: ReadonlyArray<unknown> | undefined,
|
|
42
|
+
b: ReadonlyArray<unknown> | undefined,
|
|
43
|
+
): boolean {
|
|
44
|
+
if (a === b) return true
|
|
45
|
+
if (!a || !b) return false
|
|
46
|
+
if (a.length !== b.length) return false
|
|
47
|
+
for (let i = 0; i < a.length; i++) {
|
|
48
|
+
if (!Object.is(a[i], b[i])) return false
|
|
49
|
+
}
|
|
50
|
+
return true
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function makeDispatcher() {
|
|
54
|
+
return {
|
|
55
|
+
useState<S>(initial: S | (() => S)) {
|
|
56
|
+
return this.useReducer<S, S | ((p: S) => S)>(
|
|
57
|
+
basicReducer as any,
|
|
58
|
+
typeof initial === 'function' ? (initial as () => S)() : initial,
|
|
59
|
+
)
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
useReducer<S, A>(reducer: (s: S, a: A) => S, initialArg: any, init?: (a: any) => S) {
|
|
63
|
+
const hook = nextHook()
|
|
64
|
+
const fiber = getCurrentFiber()
|
|
65
|
+
if (hook.queue === undefined) {
|
|
66
|
+
hook.state = init ? init(initialArg) : initialArg
|
|
67
|
+
const queue: any = { reducer }
|
|
68
|
+
const dispatch = (action: A) => {
|
|
69
|
+
const currentState = hook.state as S
|
|
70
|
+
const next = queue.reducer(currentState, action)
|
|
71
|
+
if (!Object.is(next, currentState)) {
|
|
72
|
+
hook.state = next
|
|
73
|
+
scheduleUpdate(fiber)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
queue.dispatch = dispatch
|
|
77
|
+
hook.queue = queue
|
|
78
|
+
} else {
|
|
79
|
+
hook.queue.reducer = reducer
|
|
80
|
+
}
|
|
81
|
+
return [hook.state, hook.queue.dispatch] as [S, (a: A) => void]
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
useEffect(create: () => any, deps?: ReadonlyArray<unknown>) {
|
|
85
|
+
const hook = nextHook()
|
|
86
|
+
const fiber = getCurrentFiber()
|
|
87
|
+
const prevDeps = hook.deps
|
|
88
|
+
if (prevDeps !== undefined && depsEqual(prevDeps, deps)) return
|
|
89
|
+
hook.deps = deps
|
|
90
|
+
const effect: Effect = {
|
|
91
|
+
tag: 'effect',
|
|
92
|
+
create: () => {
|
|
93
|
+
// Run the prior cleanup INSIDE the effect run, not during the
|
|
94
|
+
// dispatch/render phase. If render A → B → C all happen back-to-
|
|
95
|
+
// back before the passive microtask drains, dispatch-time cleanup
|
|
96
|
+
// only fires once (between A→B) and effects B + C both run fresh,
|
|
97
|
+
// leaving two side-effects (e.g. two plot SVGs) in the DOM. Doing
|
|
98
|
+
// it here, at effect-run time, means every new create first tears
|
|
99
|
+
// down whatever cleanup is currently live on the hook.
|
|
100
|
+
if (hook.cleanup) {
|
|
101
|
+
try { hook.cleanup() } catch {}
|
|
102
|
+
// The prior cleanup was also pushed onto fiber.cleanups; remove
|
|
103
|
+
// it so unmount doesn't double-call it.
|
|
104
|
+
if (fiber.cleanups) {
|
|
105
|
+
const i = fiber.cleanups.indexOf(hook.cleanup)
|
|
106
|
+
if (i >= 0) fiber.cleanups.splice(i, 1)
|
|
107
|
+
}
|
|
108
|
+
hook.cleanup = null
|
|
109
|
+
}
|
|
110
|
+
const c = create()
|
|
111
|
+
hook.cleanup = typeof c === 'function' ? c : null
|
|
112
|
+
return hook.cleanup
|
|
113
|
+
},
|
|
114
|
+
destroy: undefined,
|
|
115
|
+
deps,
|
|
116
|
+
}
|
|
117
|
+
enqueueEffect(fiber, effect)
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
useLayoutEffect(create: () => any, deps?: ReadonlyArray<unknown>) {
|
|
121
|
+
const hook = nextHook()
|
|
122
|
+
const fiber = getCurrentFiber()
|
|
123
|
+
const prevDeps = hook.deps
|
|
124
|
+
if (prevDeps !== undefined && depsEqual(prevDeps, deps)) return
|
|
125
|
+
hook.deps = deps
|
|
126
|
+
const effect: Effect = {
|
|
127
|
+
tag: 'layout',
|
|
128
|
+
create: () => {
|
|
129
|
+
// Mirror useEffect: tear down the prior cleanup at run time so
|
|
130
|
+
// coalesced renders don't leak side-effects.
|
|
131
|
+
if (hook.cleanup) {
|
|
132
|
+
try { hook.cleanup() } catch {}
|
|
133
|
+
if (fiber.cleanups) {
|
|
134
|
+
const i = fiber.cleanups.indexOf(hook.cleanup)
|
|
135
|
+
if (i >= 0) fiber.cleanups.splice(i, 1)
|
|
136
|
+
}
|
|
137
|
+
hook.cleanup = null
|
|
138
|
+
}
|
|
139
|
+
const c = create()
|
|
140
|
+
hook.cleanup = typeof c === 'function' ? c : null
|
|
141
|
+
return hook.cleanup
|
|
142
|
+
},
|
|
143
|
+
destroy: undefined,
|
|
144
|
+
deps,
|
|
145
|
+
}
|
|
146
|
+
enqueueEffect(fiber, effect)
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
useInsertionEffect(create: () => any, deps?: ReadonlyArray<unknown>) {
|
|
150
|
+
return this.useLayoutEffect(create, deps)
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
useRef<T>(initial: T) {
|
|
154
|
+
const hook = nextHook()
|
|
155
|
+
if (hook.state === undefined) hook.state = { current: initial }
|
|
156
|
+
return hook.state as { current: T }
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
useMemo<T>(factory: () => T, deps?: ReadonlyArray<unknown>) {
|
|
160
|
+
const hook = nextHook()
|
|
161
|
+
if (hook.deps !== undefined && depsEqual(hook.deps, deps)) {
|
|
162
|
+
return hook.state as T
|
|
163
|
+
}
|
|
164
|
+
const value = factory()
|
|
165
|
+
hook.state = value
|
|
166
|
+
hook.deps = deps
|
|
167
|
+
return value
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
useCallback<T extends Function>(fn: T, deps?: ReadonlyArray<unknown>): T {
|
|
171
|
+
return this.useMemo(() => fn, deps) as T
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
useContext<T>(ctx: any): T {
|
|
175
|
+
const fiber = getCurrentFiber()
|
|
176
|
+
return readContext(fiber, ctx)
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
useImperativeHandle<T>(ref: any, factory: () => T, deps?: ReadonlyArray<unknown>) {
|
|
180
|
+
const hook = nextHook()
|
|
181
|
+
if (hook.deps !== undefined && depsEqual(hook.deps, deps)) return
|
|
182
|
+
hook.deps = deps
|
|
183
|
+
const value = factory()
|
|
184
|
+
if (ref) {
|
|
185
|
+
if (typeof ref === 'function') ref(value)
|
|
186
|
+
else ref.current = value
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
useDebugValue<T>(_value: T, _formatter?: (v: T) => any): void {
|
|
191
|
+
// noop
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
useId(): string {
|
|
195
|
+
const hook = nextHook()
|
|
196
|
+
if (hook.state === undefined) {
|
|
197
|
+
const fiber = getCurrentFiber()
|
|
198
|
+
const root = findRootFromFiber(fiber)
|
|
199
|
+
hook.state = (root?.identifierPrefix ?? ':r') + (idCounter++).toString(36)
|
|
200
|
+
}
|
|
201
|
+
return hook.state as string
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
useTransition(): [boolean, (fn: () => void) => void] {
|
|
205
|
+
return [false, (fn: () => void) => fn()]
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
useDeferredValue<T>(v: T): T {
|
|
209
|
+
return v
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
useSyncExternalStore<T>(
|
|
213
|
+
subscribe: (cb: () => void) => () => void,
|
|
214
|
+
getSnapshot: () => T,
|
|
215
|
+
getServerSnapshot?: () => T,
|
|
216
|
+
): T {
|
|
217
|
+
const fiber = getCurrentFiber()
|
|
218
|
+
const hook = nextHook()
|
|
219
|
+
|
|
220
|
+
// During hydration, use the server snapshot (if provided) so the tree
|
|
221
|
+
// matches the SSR output. Components like TanStack Router's ClientOnly
|
|
222
|
+
// rely on this: they render `false` on server, `true` on client — and
|
|
223
|
+
// if we return `true` during hydration, client and server diverge and
|
|
224
|
+
// the tree mounts fresh next to the SSR fallback DOM.
|
|
225
|
+
const root = fiber.root ?? findRootFromFiber(fiber)
|
|
226
|
+
const isHydrating = Boolean(root?.hydrating)
|
|
227
|
+
const value =
|
|
228
|
+
isHydrating && getServerSnapshot ? getServerSnapshot() : getSnapshot()
|
|
229
|
+
hook.state = value
|
|
230
|
+
|
|
231
|
+
if (hook.cleanup == null) {
|
|
232
|
+
const forceUpdate = () => {
|
|
233
|
+
let next: T
|
|
234
|
+
try {
|
|
235
|
+
next = getSnapshot()
|
|
236
|
+
} catch {
|
|
237
|
+
scheduleUpdate(fiber)
|
|
238
|
+
return
|
|
239
|
+
}
|
|
240
|
+
if (!Object.is(hook.state, next)) {
|
|
241
|
+
hook.state = next
|
|
242
|
+
scheduleUpdate(fiber)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const unsubscribe = subscribe(forceUpdate)
|
|
246
|
+
hook.cleanup = unsubscribe
|
|
247
|
+
// Register with fiber so unmountFiber runs it. Without this, the store
|
|
248
|
+
// keeps holding forceUpdate and every store update schedules an already-
|
|
249
|
+
// unmounted fiber — its rerender walks stale .parent pointers and mounts
|
|
250
|
+
// zombie DOM into the old parent.
|
|
251
|
+
if (typeof unsubscribe === 'function') {
|
|
252
|
+
fiber.cleanups ||= []
|
|
253
|
+
fiber.cleanups.push(unsubscribe)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// If we served the server snapshot, run a post-hydration check so
|
|
257
|
+
// components like `useHydrated()` flip from false → true after the
|
|
258
|
+
// initial render commits. Queued late so hydration finishes first.
|
|
259
|
+
if (isHydrating && getServerSnapshot) {
|
|
260
|
+
queueMicrotask(() => queueMicrotask(forceUpdate))
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return value
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
use<T>(resource: any): T {
|
|
267
|
+
if (resource == null) throw new Error('use() received null or undefined')
|
|
268
|
+
if (resource.$$typeof === REACT_CONTEXT_TYPE) {
|
|
269
|
+
return readContext(getCurrentFiber(), resource)
|
|
270
|
+
}
|
|
271
|
+
if (typeof resource.then === 'function') {
|
|
272
|
+
const thenable = resource
|
|
273
|
+
switch (thenable.status) {
|
|
274
|
+
case 'fulfilled':
|
|
275
|
+
return thenable.value
|
|
276
|
+
case 'rejected':
|
|
277
|
+
throw thenable.reason
|
|
278
|
+
default: {
|
|
279
|
+
if (thenable.status === undefined) {
|
|
280
|
+
thenable.status = 'pending'
|
|
281
|
+
thenable.then(
|
|
282
|
+
(v: any) => {
|
|
283
|
+
if (thenable.status === 'pending') {
|
|
284
|
+
thenable.status = 'fulfilled'
|
|
285
|
+
thenable.value = v
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
(e: any) => {
|
|
289
|
+
if (thenable.status === 'pending') {
|
|
290
|
+
thenable.status = 'rejected'
|
|
291
|
+
thenable.reason = e
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
)
|
|
295
|
+
}
|
|
296
|
+
throw thenable
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
throw new Error('use() expected a Promise or Context')
|
|
301
|
+
},
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function basicReducer<S>(state: S, action: S | ((p: S) => S)): S {
|
|
306
|
+
return typeof action === 'function' ? (action as (p: S) => S)(state) : action
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
let idCounter = 0
|
|
310
|
+
|
|
311
|
+
function findRootFromFiber(fiber: Fiber): FiberRoot | null {
|
|
312
|
+
let f: Fiber | null = fiber
|
|
313
|
+
while (f) {
|
|
314
|
+
if (f.root) return f.root
|
|
315
|
+
f = f.parent
|
|
316
|
+
}
|
|
317
|
+
return null
|
|
318
|
+
}
|