@assistant-ui/tap 0.6.1 → 0.7.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/README.md +9 -6
- package/dist/core/ResourceFiber.d.ts +5 -5
- package/dist/core/ResourceFiber.d.ts.map +1 -1
- package/dist/core/ResourceFiber.js +26 -18
- package/dist/core/ResourceFiber.js.map +1 -1
- package/dist/core/createTapRoot.d.ts +9 -0
- package/dist/core/createTapRoot.d.ts.map +1 -0
- package/dist/core/createTapRoot.js +27 -0
- package/dist/core/createTapRoot.js.map +1 -0
- package/dist/core/helpers/commit.d.ts +1 -1
- package/dist/core/helpers/commit.d.ts.map +1 -1
- package/dist/core/helpers/commit.js +6 -1
- package/dist/core/helpers/commit.js.map +1 -1
- package/dist/core/helpers/execution-context.d.ts +4 -5
- package/dist/core/helpers/execution-context.d.ts.map +1 -1
- package/dist/core/helpers/execution-context.js +1 -7
- package/dist/core/helpers/execution-context.js.map +1 -1
- package/dist/core/helpers/root.d.ts +3 -2
- package/dist/core/helpers/root.d.ts.map +1 -1
- package/dist/core/helpers/root.js +19 -15
- package/dist/core/helpers/root.js.map +1 -1
- package/dist/core/react-dispatcher.d.ts.map +1 -1
- package/dist/core/react-dispatcher.js +14 -14
- package/dist/core/react-dispatcher.js.map +1 -1
- package/dist/core/resource.d.ts +2 -4
- package/dist/core/resource.d.ts.map +1 -1
- package/dist/core/resource.js +5 -10
- package/dist/core/resource.js.map +1 -1
- package/dist/core/scheduler.d.ts +2 -2
- package/dist/core/scheduler.d.ts.map +1 -1
- package/dist/core/scheduler.js +2 -2
- package/dist/core/scheduler.js.map +1 -1
- package/dist/core/types.d.ts +27 -25
- package/dist/core/types.d.ts.map +1 -1
- package/dist/hooks/useResource.d.ts +2 -2
- package/dist/hooks/useResource.d.ts.map +1 -1
- package/dist/hooks/useResource.js +14 -20
- package/dist/hooks/useResource.js.map +1 -1
- package/dist/hooks/useResources.d.ts +1 -1
- package/dist/hooks/useResources.d.ts.map +1 -1
- package/dist/hooks/useResources.js +18 -27
- package/dist/hooks/useResources.js.map +1 -1
- package/dist/hooks/useTapHost.d.ts +21 -0
- package/dist/hooks/useTapHost.d.ts.map +1 -0
- package/dist/hooks/useTapHost.js +30 -0
- package/dist/hooks/useTapHost.js.map +1 -0
- package/dist/hooks/useTapRoot.d.ts +18 -0
- package/dist/hooks/useTapRoot.d.ts.map +1 -0
- package/dist/hooks/useTapRoot.js +77 -0
- package/dist/hooks/useTapRoot.js.map +1 -0
- package/dist/hooks/utils/depsShallowEqual.d.ts.map +1 -1
- package/dist/hooks/utils/depsShallowEqual.js +5 -2
- package/dist/hooks/utils/depsShallowEqual.js.map +1 -1
- package/dist/hooks/utils/useCell.d.ts +2 -2
- package/dist/hooks/utils/useCell.d.ts.map +1 -1
- package/dist/hooks/utils/useCell.js.map +1 -1
- package/dist/hooks/utils/useDevStrictMode.d.ts +5 -0
- package/dist/hooks/utils/useDevStrictMode.d.ts.map +1 -0
- package/dist/hooks/utils/useDevStrictMode.js +25 -0
- package/dist/hooks/utils/useDevStrictMode.js.map +1 -0
- package/dist/hooks/utils/useRenderMemo.d.ts +5 -0
- package/dist/hooks/utils/useRenderMemo.d.ts.map +1 -0
- package/dist/hooks/utils/useRenderMemo.js +25 -0
- package/dist/hooks/utils/useRenderMemo.js.map +1 -0
- package/dist/hooks/utils/useResourceFiberHostUtils.d.ts +10 -0
- package/dist/hooks/utils/useResourceFiberHostUtils.d.ts.map +1 -0
- package/dist/hooks/utils/useResourceFiberHostUtils.js +46 -0
- package/dist/hooks/utils/useResourceFiberHostUtils.js.map +1 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +7 -4
- package/dist/{hooks → react-hooks}/index.d.ts +6 -6
- package/dist/{hooks → react-hooks}/index.js +5 -5
- package/dist/{hooks → react-hooks}/use.d.ts +1 -1
- package/dist/{hooks → react-hooks}/use.d.ts.map +1 -1
- package/dist/{hooks → react-hooks}/use.js +1 -1
- package/dist/react-hooks/use.js.map +1 -0
- package/dist/{hooks → react-hooks}/useCallback.d.ts +1 -1
- package/dist/react-hooks/useCallback.d.ts.map +1 -0
- package/dist/{hooks → react-hooks}/useCallback.js +1 -1
- package/dist/react-hooks/useCallback.js.map +1 -0
- package/dist/{hooks → react-hooks}/useEffect.d.ts +1 -1
- package/dist/react-hooks/useEffect.d.ts.map +1 -0
- package/dist/react-hooks/useEffect.js +35 -0
- package/dist/react-hooks/useEffect.js.map +1 -0
- package/dist/{hooks → react-hooks}/useEffectEvent.d.ts +1 -1
- package/dist/react-hooks/useEffectEvent.d.ts.map +1 -0
- package/dist/{hooks → react-hooks}/useEffectEvent.js +2 -2
- package/dist/react-hooks/useEffectEvent.js.map +1 -0
- package/dist/{hooks → react-hooks}/useMemo.d.ts +1 -1
- package/dist/react-hooks/useMemo.d.ts.map +1 -0
- package/dist/{hooks → react-hooks}/useMemo.js +3 -3
- package/dist/react-hooks/useMemo.js.map +1 -0
- package/dist/{hooks → react-hooks}/useMemoCache.d.ts +1 -1
- package/dist/react-hooks/useMemoCache.d.ts.map +1 -0
- package/dist/{hooks → react-hooks}/useMemoCache.js +1 -1
- package/dist/react-hooks/useMemoCache.js.map +1 -0
- package/dist/react-hooks/useReducer.d.ts +9 -0
- package/dist/react-hooks/useReducer.d.ts.map +1 -0
- package/dist/react-hooks/useReducer.js +120 -0
- package/dist/react-hooks/useReducer.js.map +1 -0
- package/dist/{hooks → react-hooks}/useRef.d.ts +1 -1
- package/dist/react-hooks/useRef.d.ts.map +1 -0
- package/dist/{hooks → react-hooks}/useRef.js +1 -1
- package/dist/react-hooks/useRef.js.map +1 -0
- package/dist/{hooks → react-hooks}/useState.d.ts +1 -1
- package/dist/react-hooks/useState.d.ts.map +1 -0
- package/dist/{hooks → react-hooks}/useState.js +3 -3
- package/dist/react-hooks/useState.js.map +1 -0
- package/dist/react-shim/index.js +11 -11
- package/dist/react-shim/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/basic/resourceHandle.test.ts +32 -22
- package/src/__tests__/basic/tapEffect.basic.test.ts +8 -8
- package/src/__tests__/basic/tapReducer.basic.test.ts +16 -14
- package/src/__tests__/basic/tapResources.basic.test.ts +19 -16
- package/src/__tests__/basic/tapState.basic.test.ts +11 -11
- package/src/__tests__/bench/hosts.bench.tsx +124 -0
- package/src/__tests__/bench/tree.bench.tsx +166 -0
- package/src/__tests__/errors/errors.effect-errors.test.ts +12 -13
- package/src/__tests__/errors/errors.render-errors.test.ts +65 -22
- package/src/__tests__/lifecycle/lifecycle.dependencies.test.ts +19 -19
- package/src/__tests__/lifecycle/lifecycle.mount-unmount.test.ts +14 -14
- package/src/__tests__/parity/describeParity.tsx +217 -0
- package/src/__tests__/parity/parity.adversarial.test.tsx +375 -0
- package/src/__tests__/parity/parity.basics.test.tsx +281 -0
- package/src/__tests__/parity/parity.divergences.test.tsx +208 -0
- package/src/__tests__/parity/parity.smoke.test.tsx +43 -0
- package/src/__tests__/react/concurrent-mode.test.tsx +10 -6
- package/src/__tests__/react/concurrent-pending-updates.test.tsx +351 -0
- package/src/__tests__/react/concurrent-render-phase.test.tsx +350 -0
- package/src/__tests__/react/react-shim.test.tsx +1 -1
- package/src/__tests__/react/useResource.test.tsx +41 -26
- package/src/__tests__/react/useTapHost.test.tsx +233 -0
- package/src/__tests__/react-dispatcher.test.ts +4 -4
- package/src/__tests__/rules/rules.hook-count.test.ts +21 -21
- package/src/__tests__/rules/rules.hook-order.test.ts +17 -17
- package/src/__tests__/strictmode/strictmode-parity.test.tsx +420 -0
- package/src/__tests__/strictmode/strictmode.test.ts +39 -209
- package/src/__tests__/test-utils.ts +33 -23
- package/src/core/ResourceFiber.ts +43 -35
- package/src/core/createTapRoot.ts +45 -0
- package/src/core/helpers/commit.ts +12 -2
- package/src/core/helpers/execution-context.ts +4 -13
- package/src/core/helpers/root.ts +24 -12
- package/src/core/react-dispatcher.ts +10 -9
- package/src/core/resource.ts +5 -20
- package/src/core/scheduler.ts +1 -1
- package/src/core/types.ts +27 -21
- package/src/hooks/useResource.ts +18 -27
- package/src/hooks/useResources.ts +18 -42
- package/src/hooks/useTapHost.ts +60 -0
- package/src/hooks/useTapRoot.ts +135 -0
- package/src/hooks/utils/depsShallowEqual.ts +12 -2
- package/src/hooks/utils/useCell.ts +2 -2
- package/src/hooks/utils/useDevStrictMode.ts +34 -0
- package/src/hooks/utils/useRenderMemo.ts +27 -0
- package/src/hooks/utils/useResourceFiberHostUtils.ts +61 -0
- package/src/index.ts +6 -3
- package/src/{hooks → react-hooks}/index.ts +4 -4
- package/src/react-hooks/useEffect.ts +58 -0
- package/src/{hooks → react-hooks}/useMemo.ts +1 -1
- package/src/react-hooks/useReducer.ts +254 -0
- package/src/{hooks → react-hooks}/useState.ts +2 -2
- package/src/react-shim/index.ts +1 -1
- package/dist/core/createResourceRoot.d.ts +0 -11
- package/dist/core/createResourceRoot.d.ts.map +0 -1
- package/dist/core/createResourceRoot.js +0 -31
- package/dist/core/createResourceRoot.js.map +0 -1
- package/dist/core/helpers/callResourceFn.d.ts +0 -1
- package/dist/core/helpers/callResourceFn.js +0 -19
- package/dist/core/helpers/callResourceFn.js.map +0 -1
- package/dist/hooks/use.js.map +0 -1
- package/dist/hooks/useCallback.d.ts.map +0 -1
- package/dist/hooks/useCallback.js.map +0 -1
- package/dist/hooks/useEffect.d.ts.map +0 -1
- package/dist/hooks/useEffect.js +0 -40
- package/dist/hooks/useEffect.js.map +0 -1
- package/dist/hooks/useEffectEvent.d.ts.map +0 -1
- package/dist/hooks/useEffectEvent.js.map +0 -1
- package/dist/hooks/useMemo.d.ts.map +0 -1
- package/dist/hooks/useMemo.js.map +0 -1
- package/dist/hooks/useMemoCache.d.ts.map +0 -1
- package/dist/hooks/useMemoCache.js.map +0 -1
- package/dist/hooks/useReducer.d.ts +0 -21
- package/dist/hooks/useReducer.d.ts.map +0 -1
- package/dist/hooks/useReducer.js +0 -81
- package/dist/hooks/useReducer.js.map +0 -1
- package/dist/hooks/useRef.d.ts.map +0 -1
- package/dist/hooks/useRef.js.map +0 -1
- package/dist/hooks/useResourceRoot.d.ts +0 -20
- package/dist/hooks/useResourceRoot.d.ts.map +0 -1
- package/dist/hooks/useResourceRoot.js +0 -77
- package/dist/hooks/useResourceRoot.js.map +0 -1
- package/dist/hooks/useState.d.ts.map +0 -1
- package/dist/hooks/useState.js.map +0 -1
- package/dist/react/hooks.d.ts +0 -25
- package/dist/react/hooks.d.ts.map +0 -1
- package/dist/react/hooks.js +0 -69
- package/dist/react/hooks.js.map +0 -1
- package/src/__tests__/strictmode/react-strictmode-behavior.test.tsx +0 -920
- package/src/__tests__/strictmode/react-strictmode-rerender-sources.test.tsx +0 -488
- package/src/__tests__/strictmode/tap-strictmode-rerender-sources.test.ts +0 -687
- package/src/core/createResourceRoot.ts +0 -53
- package/src/core/helpers/callResourceFn.ts +0 -21
- package/src/hooks/useEffect.ts +0 -72
- package/src/hooks/useReducer.ts +0 -160
- package/src/hooks/useResourceRoot.ts +0 -130
- package/src/react/hooks.ts +0 -112
- /package/src/{hooks → react-hooks}/use.ts +0 -0
- /package/src/{hooks → react-hooks}/useCallback.ts +0 -0
- /package/src/{hooks → react-hooks}/useEffectEvent.ts +0 -0
- /package/src/{hooks → react-hooks}/useMemoCache.ts +0 -0
- /package/src/{hooks → react-hooks}/useRef.ts +0 -0
package/README.md
CHANGED
|
@@ -18,10 +18,10 @@ npm install @assistant-ui/tap
|
|
|
18
18
|
## Usage
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
|
-
import { resource,
|
|
21
|
+
import { resource, createTapRoot, useResource } from "@assistant-ui/tap";
|
|
22
22
|
import { useState, useEffect } from "react";
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const useCounter = ({ incrementBy = 1 }: { incrementBy?: number }) => {
|
|
25
25
|
const [count, setCount] = useState(0);
|
|
26
26
|
|
|
27
27
|
useEffect(() => {
|
|
@@ -32,10 +32,13 @@ const Counter = resource(function Counter({ incrementBy = 1 }: { incrementBy?: n
|
|
|
32
32
|
count,
|
|
33
33
|
increment: () => setCount((c) => c + incrementBy),
|
|
34
34
|
};
|
|
35
|
-
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const Counter = resource(useCounter);
|
|
36
38
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
+
const counter = createTapRoot(function CounterRoot() {
|
|
40
|
+
return useResource(Counter({ incrementBy: 2 }));
|
|
41
|
+
});
|
|
39
42
|
|
|
40
43
|
const unsubscribe = counter.subscribe(() => {
|
|
41
44
|
console.log("counter updated:", counter.getValue().count);
|
|
@@ -57,7 +60,7 @@ function CounterButton() {
|
|
|
57
60
|
|
|
58
61
|
## Hooks
|
|
59
62
|
|
|
60
|
-
Inside a resource you use React's hooks (`useState`, `useEffect`, `useMemo`, `useCallback`, `useRef`, `use`, ...) imported from `"react"`. tap adds `useResource` / `useResources` / `
|
|
63
|
+
Inside a resource you use React's hooks (`useState`, `useEffect`, `useMemo`, `useCallback`, `useRef`, `use`, ...) imported from `"react"`. tap adds `useResource` / `useResources` / `useTapRoot` for composition and `createResourceContext` / `withContextProvider` for context.
|
|
61
64
|
|
|
62
65
|
Full API reference at [assistant-ui.com/tap/docs](https://www.assistant-ui.com/tap/docs).
|
|
63
66
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { RenderResult,
|
|
1
|
+
import { RenderResult, ResourceFiber, ResourceFiberRoot } from "./types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/core/ResourceFiber.d.ts
|
|
4
|
-
declare function createResourceFiber<R,
|
|
5
|
-
declare function unmountResourceFiber<R,
|
|
6
|
-
declare function renderResourceFiber<R,
|
|
7
|
-
declare function commitResourceFiber<R,
|
|
4
|
+
declare function createResourceFiber<R, A extends readonly unknown[]>(hook: (...args: A) => R, root: ResourceFiberRoot, markDirty: (() => void) | undefined, strictMode: "root" | "child" | null): ResourceFiber<R, A>;
|
|
5
|
+
declare function unmountResourceFiber<R, A extends readonly unknown[]>(fiber: ResourceFiber<R, A>): void;
|
|
6
|
+
declare function renderResourceFiber<R, A extends readonly unknown[]>(fiber: ResourceFiber<R, A>, args: Readonly<A>): RenderResult;
|
|
7
|
+
declare function commitResourceFiber<R, A extends readonly unknown[]>(fiber: ResourceFiber<R, A>, result: RenderResult): void;
|
|
8
8
|
//#endregion
|
|
9
9
|
export { commitResourceFiber, createResourceFiber, renderResourceFiber, unmountResourceFiber };
|
|
10
10
|
//# sourceMappingURL=ResourceFiber.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceFiber.d.ts","names":[],"sources":["../../src/core/ResourceFiber.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ResourceFiber.d.ts","names":[],"sources":["../../src/core/ResourceFiber.ts"],"mappings":";;;iBAMgB,mBAAA,kCACd,IAAA,MAAU,IAAA,EAAM,CAAA,KAAM,CAAA,EACtB,IAAA,EAAM,iBAAA,EACN,SAAA,4BACA,UAAA,4BACC,aAAA,CAAc,CAAA,EAAG,CAAA;AAAA,iBAgBJ,oBAAA,kCACd,KAAA,EAAO,aAAA,CAAc,CAAA,EAAG,CAAA;AAAA,iBASV,mBAAA,kCACd,KAAA,EAAO,aAAA,CAAc,CAAA,EAAG,CAAA,GACxB,IAAA,EAAM,QAAA,CAAS,CAAA,IACd,YAAA;AAAA,iBAmCa,mBAAA,kCACd,KAAA,EAAO,aAAA,CAAc,CAAA,EAAG,CAAA,GACxB,MAAA,EAAQ,YAAA"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { callResourceFn } from "./helpers/callResourceFn.js";
|
|
2
1
|
import { cleanupAllEffects, commitAllEffects } from "./helpers/commit.js";
|
|
2
|
+
import { withResourceFiber } from "./helpers/execution-context.js";
|
|
3
3
|
import { isDevelopment } from "./helpers/env.js";
|
|
4
|
-
import { getDevStrictMode, withResourceFiber } from "./helpers/execution-context.js";
|
|
5
4
|
import { withReactDispatcher } from "./react-dispatcher.js";
|
|
6
5
|
//#region src/core/ResourceFiber.ts
|
|
7
|
-
function createResourceFiber(
|
|
6
|
+
function createResourceFiber(hook, root, markDirty = void 0, strictMode) {
|
|
8
7
|
return {
|
|
9
|
-
|
|
8
|
+
hook,
|
|
10
9
|
root,
|
|
11
10
|
markDirty,
|
|
12
11
|
devStrictMode: strictMode,
|
|
13
12
|
cells: [],
|
|
13
|
+
renderPendingCells: null,
|
|
14
14
|
currentIndex: 0,
|
|
15
15
|
renderContext: void 0,
|
|
16
16
|
isFirstRender: true,
|
|
@@ -23,20 +23,28 @@ function unmountResourceFiber(fiber) {
|
|
|
23
23
|
fiber.isMounted = false;
|
|
24
24
|
cleanupAllEffects(fiber);
|
|
25
25
|
}
|
|
26
|
-
function renderResourceFiber(fiber,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
26
|
+
function renderResourceFiber(fiber, args) {
|
|
27
|
+
if (fiber.renderPendingCells !== null) {
|
|
28
|
+
for (const cell of fiber.renderPendingCells) cell.renderQueue = null;
|
|
29
|
+
fiber.renderPendingCells.clear();
|
|
30
|
+
}
|
|
31
|
+
let passes = 0;
|
|
32
|
+
let result;
|
|
33
|
+
do {
|
|
34
|
+
if (++passes > 25) throw new Error("Too many re-renders. tap limits the number of renders to prevent an infinite loop.");
|
|
35
|
+
result = {
|
|
36
|
+
effectTasks: [],
|
|
37
|
+
value: void 0
|
|
38
|
+
};
|
|
39
|
+
withResourceFiber(fiber, () => {
|
|
40
|
+
fiber.renderContext = result;
|
|
41
|
+
try {
|
|
42
|
+
result.value = withReactDispatcher(() => fiber.hook(...args));
|
|
43
|
+
} finally {
|
|
44
|
+
fiber.renderContext = void 0;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
} while ((fiber.renderPendingCells?.size ?? 0) > 0);
|
|
40
48
|
return result;
|
|
41
49
|
}
|
|
42
50
|
function commitResourceFiber(fiber, result) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceFiber.js","names":[],"sources":["../../src/core/ResourceFiber.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"ResourceFiber.js","names":[],"sources":["../../src/core/ResourceFiber.ts"],"sourcesContent":["import type { ResourceFiber, RenderResult, ResourceFiberRoot } from \"./types\";\nimport { commitAllEffects, cleanupAllEffects } from \"./helpers/commit\";\nimport { withResourceFiber } from \"./helpers/execution-context\";\nimport { withReactDispatcher } from \"./react-dispatcher\";\nimport { isDevelopment } from \"./helpers/env\";\n\nexport function createResourceFiber<R, A extends readonly unknown[]>(\n hook: (...args: A) => R,\n root: ResourceFiberRoot,\n markDirty: (() => void) | undefined = undefined,\n strictMode: \"root\" | \"child\" | null,\n): ResourceFiber<R, A> {\n return {\n hook,\n root,\n markDirty,\n devStrictMode: strictMode,\n cells: [],\n renderPendingCells: null,\n currentIndex: 0,\n renderContext: undefined,\n isFirstRender: true,\n isMounted: false,\n isNeverMounted: true,\n };\n}\n\nexport function unmountResourceFiber<R, A extends readonly unknown[]>(\n fiber: ResourceFiber<R, A>,\n): void {\n if (!fiber.isMounted)\n throw new Error(\"Tried to unmount a fiber that is already unmounted\");\n\n fiber.isMounted = false;\n cleanupAllEffects(fiber);\n}\n\nexport function renderResourceFiber<R, A extends readonly unknown[]>(\n fiber: ResourceFiber<R, A>,\n args: Readonly<A>,\n): RenderResult {\n // Discard render-phase actions left by a previous render\n if (fiber.renderPendingCells !== null) {\n for (const cell of fiber.renderPendingCells) cell.renderQueue = null;\n fiber.renderPendingCells.clear();\n }\n\n let passes = 0;\n let result: RenderResult;\n do {\n if (++passes > 25) {\n throw new Error(\n \"Too many re-renders. tap limits the number of renders to prevent \" +\n \"an infinite loop.\",\n );\n }\n\n result = {\n effectTasks: [],\n value: undefined as R | undefined,\n };\n\n withResourceFiber(fiber, () => {\n fiber.renderContext = result;\n try {\n result.value = withReactDispatcher(() => fiber.hook(...args));\n } finally {\n fiber.renderContext = undefined;\n }\n });\n } while ((fiber.renderPendingCells?.size ?? 0) > 0);\n\n return result;\n}\n\nexport function commitResourceFiber<R, A extends readonly unknown[]>(\n fiber: ResourceFiber<R, A>,\n result: RenderResult,\n): void {\n fiber.isMounted = true;\n\n if (isDevelopment && fiber.isNeverMounted && fiber.devStrictMode === \"root\") {\n fiber.isNeverMounted = false;\n\n commitAllEffects(result);\n cleanupAllEffects(fiber);\n }\n\n fiber.isNeverMounted = false;\n commitAllEffects(result);\n}\n"],"mappings":";;;;;AAMA,SAAgB,oBACd,MACA,MACA,YAAsC,KAAA,GACtC,YACqB;CACrB,OAAO;EACL;EACA;EACA;EACA,eAAe;EACf,OAAO,CAAC;EACR,oBAAoB;EACpB,cAAc;EACd,eAAe,KAAA;EACf,eAAe;EACf,WAAW;EACX,gBAAgB;CAClB;AACF;AAEA,SAAgB,qBACd,OACM;CACN,IAAI,CAAC,MAAM,WACT,MAAM,IAAI,MAAM,oDAAoD;CAEtE,MAAM,YAAY;CAClB,kBAAkB,KAAK;AACzB;AAEA,SAAgB,oBACd,OACA,MACc;CAEd,IAAI,MAAM,uBAAuB,MAAM;EACrC,KAAK,MAAM,QAAQ,MAAM,oBAAoB,KAAK,cAAc;EAChE,MAAM,mBAAmB,MAAM;CACjC;CAEA,IAAI,SAAS;CACb,IAAI;CACJ,GAAG;EACD,IAAI,EAAE,SAAS,IACb,MAAM,IAAI,MACR,oFAEF;EAGF,SAAS;GACP,aAAa,CAAC;GACd,OAAO,KAAA;EACT;EAEA,kBAAkB,aAAa;GAC7B,MAAM,gBAAgB;GACtB,IAAI;IACF,OAAO,QAAQ,0BAA0B,MAAM,KAAK,GAAG,IAAI,CAAC;GAC9D,UAAU;IACR,MAAM,gBAAgB,KAAA;GACxB;EACF,CAAC;CACH,UAAU,MAAM,oBAAoB,QAAQ,KAAK;CAEjD,OAAO;AACT;AAEA,SAAgB,oBACd,OACA,QACM;CACN,MAAM,YAAY;CAElB,IAAI,iBAAiB,MAAM,kBAAkB,MAAM,kBAAkB,QAAQ;EAC3E,MAAM,iBAAiB;EAEvB,iBAAiB,MAAM;EACvB,kBAAkB,KAAK;CACzB;CAEA,MAAM,iBAAiB;CACvB,iBAAiB,MAAM;AACzB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useTapRoot } from "../hooks/useTapRoot.js";
|
|
2
|
+
|
|
3
|
+
//#region src/core/createTapRoot.d.ts
|
|
4
|
+
declare const createTapRoot: <R>(render: () => R) => useTapRoot.Root<R> & {
|
|
5
|
+
unmount: () => void;
|
|
6
|
+
};
|
|
7
|
+
//#endregion
|
|
8
|
+
export { createTapRoot };
|
|
9
|
+
//# sourceMappingURL=createTapRoot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTapRoot.d.ts","names":[],"sources":["../../src/core/createTapRoot.ts"],"mappings":";;;cAWa,aAAA,MACX,MAAA,QAAc,CAAA,KACb,UAAA,CAAW,IAAA,CAAK,CAAA;EAAO,OAAA;AAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { isDevelopment } from "./helpers/env.js";
|
|
2
|
+
import { createResourceFiberRoot } from "./helpers/root.js";
|
|
3
|
+
import { commitResourceFiber, createResourceFiber, renderResourceFiber, unmountResourceFiber } from "./ResourceFiber.js";
|
|
4
|
+
import { UpdateScheduler, flushTapSync } from "./scheduler.js";
|
|
5
|
+
import { useTapRoot } from "../hooks/useTapRoot.js";
|
|
6
|
+
//#region src/core/createTapRoot.ts
|
|
7
|
+
const createTapRoot = (render) => {
|
|
8
|
+
const fiber = createResourceFiber(useTapRoot, createResourceFiberRoot((callback) => {
|
|
9
|
+
new UpdateScheduler(() => {
|
|
10
|
+
if (callback()) throw new Error("Unexpected rerender of createTapRoot outer fiber");
|
|
11
|
+
return false;
|
|
12
|
+
}).markDirty();
|
|
13
|
+
}), void 0, isDevelopment ? "root" : null);
|
|
14
|
+
if (isDevelopment && fiber.devStrictMode === "root") renderResourceFiber(fiber, [render]);
|
|
15
|
+
const rendered = renderResourceFiber(fiber, [render]);
|
|
16
|
+
flushTapSync(() => commitResourceFiber(fiber, rendered));
|
|
17
|
+
return {
|
|
18
|
+
...rendered.value,
|
|
19
|
+
unmount: () => {
|
|
20
|
+
unmountResourceFiber(fiber);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { createTapRoot };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=createTapRoot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTapRoot.js","names":[],"sources":["../../src/core/createTapRoot.ts"],"sourcesContent":["import {\n createResourceFiber,\n unmountResourceFiber,\n renderResourceFiber,\n commitResourceFiber,\n} from \"./ResourceFiber\";\nimport { useTapRoot } from \"../hooks/useTapRoot\";\nimport { isDevelopment } from \"./helpers/env\";\nimport { flushTapSync, UpdateScheduler } from \"./scheduler\";\nimport { createResourceFiberRoot } from \"./helpers/root\";\n\nexport const createTapRoot = <R>(\n render: () => R,\n): useTapRoot.Root<R> & { unmount: () => void } => {\n const fiber = createResourceFiber(\n useTapRoot,\n createResourceFiberRoot((callback) => {\n new UpdateScheduler(() => {\n if (callback()) {\n throw new Error(\"Unexpected rerender of createTapRoot outer fiber\");\n }\n return false;\n }).markDirty();\n }),\n undefined,\n isDevelopment ? \"root\" : null,\n );\n\n // In strict mode, render twice to detect side effects\n if (isDevelopment && fiber.devStrictMode === \"root\") {\n void renderResourceFiber(fiber, [render]);\n }\n\n const rendered = renderResourceFiber(fiber, [render]);\n flushTapSync(() => commitResourceFiber(fiber, rendered));\n\n const root = rendered.value as useTapRoot.Root<R>;\n\n return {\n ...root,\n unmount: () => {\n unmountResourceFiber(fiber);\n },\n };\n};\n"],"mappings":";;;;;;AAWA,MAAa,iBACX,WACiD;CACjD,MAAM,QAAQ,oBACZ,YACA,yBAAyB,aAAa;EACpC,IAAI,sBAAsB;GACxB,IAAI,SAAS,GACX,MAAM,IAAI,MAAM,kDAAkD;GAEpE,OAAO;EACT,CAAC,CAAC,CAAC,UAAU;CACf,CAAC,GACD,KAAA,GACA,gBAAgB,SAAS,IAC3B;CAGA,IAAI,iBAAiB,MAAM,kBAAkB,QAC3C,oBAAyB,OAAO,CAAC,MAAM,CAAC;CAG1C,MAAM,WAAW,oBAAoB,OAAO,CAAC,MAAM,CAAC;CACpD,mBAAmB,oBAAoB,OAAO,QAAQ,CAAC;CAIvD,OAAO;EACL,GAHW,SAAS;EAIpB,eAAe;GACb,qBAAqB,KAAK;EAC5B;CACF;AACF"}
|
|
@@ -2,7 +2,7 @@ import { RenderResult, ResourceFiber } from "../types.js";
|
|
|
2
2
|
|
|
3
3
|
//#region src/core/helpers/commit.d.ts
|
|
4
4
|
declare function commitAllEffects(renderResult: RenderResult): void;
|
|
5
|
-
declare function cleanupAllEffects<R,
|
|
5
|
+
declare function cleanupAllEffects<R, A extends readonly unknown[]>(executionContext: ResourceFiber<R, A>): void;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { cleanupAllEffects, commitAllEffects };
|
|
8
8
|
//# sourceMappingURL=commit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.d.ts","names":[],"sources":["../../../src/core/helpers/commit.ts"],"mappings":";;;iBAEgB,gBAAA,CAAiB,YAA0B,EAAZ,YAAY;AAAA,
|
|
1
|
+
{"version":3,"file":"commit.d.ts","names":[],"sources":["../../../src/core/helpers/commit.ts"],"mappings":";;;iBAEgB,gBAAA,CAAiB,YAA0B,EAAZ,YAAY;AAAA,iBA+B3C,iBAAA,kCACd,gBAAA,EAAkB,aAAA,CAAc,CAAA,EAAG,CAAA"}
|
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
function commitAllEffects(renderResult) {
|
|
3
3
|
const errors = [];
|
|
4
4
|
for (const task of renderResult.effectTasks) try {
|
|
5
|
-
task();
|
|
5
|
+
task.cleanup();
|
|
6
|
+
} catch (error) {
|
|
7
|
+
errors.push(error);
|
|
8
|
+
}
|
|
9
|
+
for (const task of renderResult.effectTasks) try {
|
|
10
|
+
task.setup();
|
|
6
11
|
} catch (error) {
|
|
7
12
|
errors.push(error);
|
|
8
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.js","names":[],"sources":["../../../src/core/helpers/commit.ts"],"sourcesContent":["import type { ResourceFiber, RenderResult } from \"../types\";\n\nexport function commitAllEffects(renderResult: RenderResult): void {\n const errors: unknown[] = [];\n\n for (const task of renderResult.effectTasks) {\n try {\n task();\n } catch (error) {\n errors.push(error);\n }\n }\n\n if (errors.length > 0) {\n if (errors.length === 1) {\n throw errors[0];\n } else {\n for (const error of errors) {\n console.error(error);\n }\n throw new AggregateError(errors, \"Errors during commit\");\n }\n }\n}\n\nexport function cleanupAllEffects<R,
|
|
1
|
+
{"version":3,"file":"commit.js","names":[],"sources":["../../../src/core/helpers/commit.ts"],"sourcesContent":["import type { ResourceFiber, RenderResult } from \"../types\";\n\nexport function commitAllEffects(renderResult: RenderResult): void {\n const errors: unknown[] = [];\n\n for (const task of renderResult.effectTasks) {\n try {\n task.cleanup();\n } catch (error) {\n errors.push(error);\n }\n }\n\n for (const task of renderResult.effectTasks) {\n try {\n task.setup();\n } catch (error) {\n errors.push(error);\n }\n }\n\n if (errors.length > 0) {\n if (errors.length === 1) {\n throw errors[0];\n } else {\n for (const error of errors) {\n console.error(error);\n }\n throw new AggregateError(errors, \"Errors during commit\");\n }\n }\n}\n\nexport function cleanupAllEffects<R, A extends readonly unknown[]>(\n executionContext: ResourceFiber<R, A>,\n) {\n const errors: unknown[] = [];\n for (const cell of executionContext.cells) {\n if (cell?.type === \"effect\") {\n cell.deps = null; // Reset deps so effect runs again on next mount\n\n if (cell.cleanup) {\n try {\n cell.cleanup?.();\n } catch (e) {\n errors.push(e);\n } finally {\n cell.cleanup = undefined;\n }\n }\n }\n }\n if (errors.length > 0) {\n if (errors.length === 1) {\n throw errors[0];\n } else {\n for (const error of errors) {\n console.error(error);\n }\n throw new AggregateError(errors, \"Errors during cleanup\");\n }\n }\n}\n"],"mappings":";AAEA,SAAgB,iBAAiB,cAAkC;CACjE,MAAM,SAAoB,CAAC;CAE3B,KAAK,MAAM,QAAQ,aAAa,aAC9B,IAAI;EACF,KAAK,QAAQ;CACf,SAAS,OAAO;EACd,OAAO,KAAK,KAAK;CACnB;CAGF,KAAK,MAAM,QAAQ,aAAa,aAC9B,IAAI;EACF,KAAK,MAAM;CACb,SAAS,OAAO;EACd,OAAO,KAAK,KAAK;CACnB;CAGF,IAAI,OAAO,SAAS,GAClB,IAAI,OAAO,WAAW,GACpB,MAAM,OAAO;MACR;EACL,KAAK,MAAM,SAAS,QAClB,QAAQ,MAAM,KAAK;EAErB,MAAM,IAAI,eAAe,QAAQ,sBAAsB;CACzD;AAEJ;AAEA,SAAgB,kBACd,kBACA;CACA,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,QAAQ,iBAAiB,OAClC,IAAI,MAAM,SAAS,UAAU;EAC3B,KAAK,OAAO;EAEZ,IAAI,KAAK,SACP,IAAI;GACF,KAAK,UAAU;EACjB,SAAS,GAAG;GACV,OAAO,KAAK,CAAC;EACf,UAAU;GACR,KAAK,UAAU,KAAA;EACjB;CAEJ;CAEF,IAAI,OAAO,SAAS,GAClB,IAAI,OAAO,WAAW,GACpB,MAAM,OAAO;MACR;EACL,KAAK,MAAM,SAAS,QAClB,QAAQ,MAAM,KAAK;EAErB,MAAM,IAAI,eAAe,QAAQ,uBAAuB;CAC1D;AAEJ"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { ResourceFiber } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/core/helpers/execution-context.d.ts
|
|
4
|
-
declare function withResourceFiber<R,
|
|
5
|
-
declare function getCurrentResourceFiber(): ResourceFiber<unknown
|
|
6
|
-
declare function peekResourceFiber(): ResourceFiber<unknown
|
|
7
|
-
declare function getDevStrictMode(enable: boolean): "root" | "child" | null;
|
|
4
|
+
declare function withResourceFiber<R, A extends readonly unknown[]>(fiber: ResourceFiber<R, A>, fn: () => void): void;
|
|
5
|
+
declare function getCurrentResourceFiber(): ResourceFiber<unknown>;
|
|
6
|
+
declare function peekResourceFiber(): ResourceFiber<unknown> | null;
|
|
8
7
|
//#endregion
|
|
9
|
-
export { getCurrentResourceFiber,
|
|
8
|
+
export { getCurrentResourceFiber, peekResourceFiber, withResourceFiber };
|
|
10
9
|
//# sourceMappingURL=execution-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context.d.ts","names":[],"sources":["../../../src/core/helpers/execution-context.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"execution-context.d.ts","names":[],"sources":["../../../src/core/helpers/execution-context.ts"],"mappings":";;;iBAIgB,iBAAA,kCACd,KAAA,EAAO,aAAA,CAAc,CAAA,EAAG,CAAA,GACxB,EAAA;AAAA,iBAsBc,uBAAA,IAA2B,aAAa;AAAA,iBAOxC,iBAAA,IAAqB,aAAa"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { isDevelopment } from "./env.js";
|
|
2
1
|
//#region src/core/helpers/execution-context.ts
|
|
3
2
|
let currentResourceFiber = null;
|
|
4
3
|
function withResourceFiber(fiber, fn) {
|
|
@@ -20,12 +19,7 @@ function getCurrentResourceFiber() {
|
|
|
20
19
|
function peekResourceFiber() {
|
|
21
20
|
return currentResourceFiber;
|
|
22
21
|
}
|
|
23
|
-
function getDevStrictMode(enable) {
|
|
24
|
-
if (!isDevelopment) return null;
|
|
25
|
-
if (currentResourceFiber?.devStrictMode) return currentResourceFiber.isFirstRender ? "child" : "root";
|
|
26
|
-
return enable ? "root" : null;
|
|
27
|
-
}
|
|
28
22
|
//#endregion
|
|
29
|
-
export { getCurrentResourceFiber,
|
|
23
|
+
export { getCurrentResourceFiber, peekResourceFiber, withResourceFiber };
|
|
30
24
|
|
|
31
25
|
//# sourceMappingURL=execution-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context.js","names":[],"sources":["../../../src/core/helpers/execution-context.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"execution-context.js","names":[],"sources":["../../../src/core/helpers/execution-context.ts"],"sourcesContent":["import type { ResourceFiber } from \"../types\";\n\nlet currentResourceFiber: ResourceFiber<any, any> | null = null;\n\nexport function withResourceFiber<R, A extends readonly unknown[]>(\n fiber: ResourceFiber<R, A>,\n fn: () => void,\n): void {\n fiber.currentIndex = 0;\n\n const previousContext = currentResourceFiber;\n currentResourceFiber = fiber;\n try {\n fn();\n\n fiber.isFirstRender = false;\n\n // ensure hook count matches\n if (fiber.cells.length !== fiber.currentIndex) {\n throw new Error(\n `Rendered ${fiber.currentIndex} hooks but expected ${fiber.cells.length}. ` +\n \"Hooks must be called in the exact same order in every render.\",\n );\n }\n } finally {\n currentResourceFiber = previousContext;\n }\n}\nexport function getCurrentResourceFiber(): ResourceFiber<unknown> {\n if (!currentResourceFiber) {\n throw new Error(\"No resource fiber available\");\n }\n return currentResourceFiber;\n}\n\nexport function peekResourceFiber(): ResourceFiber<unknown> | null {\n return currentResourceFiber;\n}\n"],"mappings":";AAEA,IAAI,uBAAuD;AAE3D,SAAgB,kBACd,OACA,IACM;CACN,MAAM,eAAe;CAErB,MAAM,kBAAkB;CACxB,uBAAuB;CACvB,IAAI;EACF,GAAG;EAEH,MAAM,gBAAgB;EAGtB,IAAI,MAAM,MAAM,WAAW,MAAM,cAC/B,MAAM,IAAI,MACR,YAAY,MAAM,aAAa,sBAAsB,MAAM,MAAM,OAAO,gEAE1E;CAEJ,UAAU;EACR,uBAAuB;CACzB;AACF;AACA,SAAgB,0BAAkD;CAChE,IAAI,CAAC,sBACH,MAAM,IAAI,MAAM,6BAA6B;CAE/C,OAAO;AACT;AAEA,SAAgB,oBAAmD;CACjE,OAAO;AACT"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { Cell, ResourceFiber, ResourceFiberRoot } from "../types.js";
|
|
1
|
+
import { Cell, ChangelogRecord, ResourceFiber, ResourceFiberRoot } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/core/helpers/root.d.ts
|
|
4
4
|
declare const createResourceFiberRoot: (dispatchUpdate: (cb: () => boolean) => void) => ResourceFiberRoot;
|
|
5
5
|
declare const commitRoot: (root: ResourceFiberRoot) => void;
|
|
6
6
|
declare const setRootVersion: (root: ResourceFiberRoot, version: number) => void;
|
|
7
|
+
declare const applyChangelogRecord: (record: ChangelogRecord) => void;
|
|
7
8
|
declare const markCellDirty: (fiber: ResourceFiber<any, any>, cell: Cell & {
|
|
8
9
|
type: "reducer";
|
|
9
10
|
}) => void;
|
|
10
11
|
//#endregion
|
|
11
|
-
export { commitRoot, createResourceFiberRoot, markCellDirty, setRootVersion };
|
|
12
|
+
export { applyChangelogRecord, commitRoot, createResourceFiberRoot, markCellDirty, setRootVersion };
|
|
12
13
|
//# sourceMappingURL=root.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.d.ts","names":[],"sources":["../../../src/core/helpers/root.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"root.d.ts","names":[],"sources":["../../../src/core/helpers/root.ts"],"mappings":";;;cAOa,uBAAA,GACX,cAAA,GAAiB,EAAA,6BAChB,iBAQF;AAAA,cAEY,UAAA,GAAc,IAAuB,EAAjB,iBAAiB;AAAA,cASrC,cAAA,GACX,IAAA,EAAM,iBAAiB,EACvB,OAAA;AAAA,cAgCW,oBAAA,GAAwB,MAAuB,EAAf,eAAe;AAAA,cAQ/C,aAAA,GACX,KAAA,EAAO,aAAA,YACP,IAAA,EAAM,IAAI;EAAK,IAAA;AAAA"}
|
|
@@ -5,46 +5,50 @@ const createResourceFiberRoot = (dispatchUpdate) => {
|
|
|
5
5
|
committedVersion: 0,
|
|
6
6
|
dispatchUpdate,
|
|
7
7
|
changelog: [],
|
|
8
|
-
dirtyCells:
|
|
8
|
+
dirtyCells: /* @__PURE__ */ new Set()
|
|
9
9
|
};
|
|
10
10
|
};
|
|
11
11
|
const commitRoot = (root) => {
|
|
12
|
-
for (const cell of root.dirtyCells)
|
|
13
|
-
cell.dirty = false;
|
|
14
|
-
cell.queue.clear();
|
|
15
|
-
cell.current = cell.workInProgress;
|
|
16
|
-
}
|
|
12
|
+
for (const cell of root.dirtyCells) cell.current = cell.workInProgress;
|
|
17
13
|
root.committedVersion = root.version;
|
|
18
14
|
root.changelog.length = 0;
|
|
19
|
-
root.dirtyCells.
|
|
15
|
+
root.dirtyCells.clear();
|
|
20
16
|
};
|
|
21
17
|
const setRootVersion = (root, version) => {
|
|
22
18
|
const rollback = root.version > version;
|
|
23
19
|
root.version = version;
|
|
24
20
|
if (rollback) {
|
|
25
21
|
for (const cell of root.dirtyCells) {
|
|
26
|
-
cell.
|
|
27
|
-
|
|
22
|
+
if (cell.queue !== null) {
|
|
23
|
+
for (const record of cell.queue) record.queued = false;
|
|
24
|
+
cell.queue = null;
|
|
25
|
+
}
|
|
28
26
|
cell.workInProgress = cell.current;
|
|
29
27
|
}
|
|
30
|
-
root.dirtyCells.
|
|
28
|
+
root.dirtyCells.clear();
|
|
31
29
|
if (version === root.committedVersion) root.changelog.length = 0;
|
|
32
30
|
else {
|
|
33
31
|
if (root.committedVersion > version) throw new Error("Version is less than committed version");
|
|
34
32
|
while (root.committedVersion + root.changelog.length > version) root.changelog.pop();
|
|
35
|
-
root.changelog.forEach(
|
|
33
|
+
root.changelog.forEach(applyChangelogRecord);
|
|
36
34
|
commitRoot(root);
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
37
|
};
|
|
38
|
+
const applyChangelogRecord = (record) => {
|
|
39
|
+
markCellDirty(record.fiber, record.cell);
|
|
40
|
+
if (!record.queued) {
|
|
41
|
+
record.queued = true;
|
|
42
|
+
(record.cell.queue ??= []).push(record);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
40
45
|
const markCellDirty = (fiber, cell) => {
|
|
41
|
-
if (!cell
|
|
42
|
-
cell.dirty = true;
|
|
46
|
+
if (!fiber.root.dirtyCells.has(cell)) {
|
|
43
47
|
fiber.markDirty?.();
|
|
44
|
-
fiber.root.dirtyCells.
|
|
48
|
+
fiber.root.dirtyCells.add(cell);
|
|
45
49
|
}
|
|
46
50
|
};
|
|
47
51
|
//#endregion
|
|
48
|
-
export { commitRoot, createResourceFiberRoot, markCellDirty, setRootVersion };
|
|
52
|
+
export { applyChangelogRecord, commitRoot, createResourceFiberRoot, markCellDirty, setRootVersion };
|
|
49
53
|
|
|
50
54
|
//# sourceMappingURL=root.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.js","names":[],"sources":["../../../src/core/helpers/root.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"root.js","names":[],"sources":["../../../src/core/helpers/root.ts"],"sourcesContent":["import type {\n Cell,\n ChangelogRecord,\n ResourceFiber,\n ResourceFiberRoot,\n} from \"../types\";\n\nexport const createResourceFiberRoot = (\n dispatchUpdate: (cb: () => boolean) => void,\n): ResourceFiberRoot => {\n return {\n version: 0,\n committedVersion: 0,\n dispatchUpdate,\n changelog: [],\n dirtyCells: new Set(),\n };\n};\n\nexport const commitRoot = (root: ResourceFiberRoot): void => {\n for (const cell of root.dirtyCells) {\n cell.current = cell.workInProgress;\n }\n root.committedVersion = root.version;\n root.changelog.length = 0;\n root.dirtyCells.clear();\n};\n\nexport const setRootVersion = (\n root: ResourceFiberRoot,\n version: number,\n): void => {\n const rollback = root.version > version;\n root.version = version;\n if (rollback) {\n for (const cell of root.dirtyCells) {\n if (cell.queue !== null) {\n for (const record of cell.queue) record.queued = false;\n cell.queue = null;\n }\n cell.workInProgress = cell.current;\n }\n root.dirtyCells.clear();\n\n if (version === root.committedVersion) {\n root.changelog.length = 0;\n } else {\n // commit happened without a useEffect update (offscreen API)\n\n if (root.committedVersion > version)\n throw new Error(\"Version is less than committed version\");\n\n while (root.committedVersion + root.changelog.length > version) {\n root.changelog.pop();\n }\n\n root.changelog.forEach(applyChangelogRecord);\n commitRoot(root);\n }\n }\n};\n\nexport const applyChangelogRecord = (record: ChangelogRecord): void => {\n markCellDirty(record.fiber, record.cell);\n if (!record.queued) {\n record.queued = true;\n (record.cell.queue ??= []).push(record);\n }\n};\n\nexport const markCellDirty = (\n fiber: ResourceFiber<any, any>,\n cell: Cell & { type: \"reducer\" },\n): void => {\n if (!fiber.root.dirtyCells.has(cell)) {\n fiber.markDirty?.();\n fiber.root.dirtyCells.add(cell);\n }\n};\n"],"mappings":";AAOA,MAAa,2BACX,mBACsB;CACtB,OAAO;EACL,SAAS;EACT,kBAAkB;EAClB;EACA,WAAW,CAAC;EACZ,4BAAY,IAAI,IAAI;CACtB;AACF;AAEA,MAAa,cAAc,SAAkC;CAC3D,KAAK,MAAM,QAAQ,KAAK,YACtB,KAAK,UAAU,KAAK;CAEtB,KAAK,mBAAmB,KAAK;CAC7B,KAAK,UAAU,SAAS;CACxB,KAAK,WAAW,MAAM;AACxB;AAEA,MAAa,kBACX,MACA,YACS;CACT,MAAM,WAAW,KAAK,UAAU;CAChC,KAAK,UAAU;CACf,IAAI,UAAU;EACZ,KAAK,MAAM,QAAQ,KAAK,YAAY;GAClC,IAAI,KAAK,UAAU,MAAM;IACvB,KAAK,MAAM,UAAU,KAAK,OAAO,OAAO,SAAS;IACjD,KAAK,QAAQ;GACf;GACA,KAAK,iBAAiB,KAAK;EAC7B;EACA,KAAK,WAAW,MAAM;EAEtB,IAAI,YAAY,KAAK,kBACnB,KAAK,UAAU,SAAS;OACnB;GAGL,IAAI,KAAK,mBAAmB,SAC1B,MAAM,IAAI,MAAM,wCAAwC;GAE1D,OAAO,KAAK,mBAAmB,KAAK,UAAU,SAAS,SACrD,KAAK,UAAU,IAAI;GAGrB,KAAK,UAAU,QAAQ,oBAAoB;GAC3C,WAAW,IAAI;EACjB;CACF;AACF;AAEA,MAAa,wBAAwB,WAAkC;CACrE,cAAc,OAAO,OAAO,OAAO,IAAI;CACvC,IAAI,CAAC,OAAO,QAAQ;EAClB,OAAO,SAAS;EAChB,CAAC,OAAO,KAAK,UAAU,CAAC,EAAA,CAAG,KAAK,MAAM;CACxC;AACF;AAEA,MAAa,iBACX,OACA,SACS;CACT,IAAI,CAAC,MAAM,KAAK,WAAW,IAAI,IAAI,GAAG;EACpC,MAAM,YAAY;EAClB,MAAM,KAAK,WAAW,IAAI,IAAI;CAChC;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-dispatcher.d.ts","names":[],"sources":["../../src/core/react-dispatcher.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"react-dispatcher.d.ts","names":[],"sources":["../../src/core/react-dispatcher.ts"],"mappings":";;AAoEA;;;;;;iBAAgB,mBAAA,IAAuB,MAAA,QAAc,CAAA,GAAI,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { useReducer as useReducer$1 } from "../hooks/useReducer.js";
|
|
2
|
-
import { useState as useState$1 } from "../hooks/useState.js";
|
|
3
|
-
import { useRef as useRef$1 } from "../hooks/useRef.js";
|
|
4
|
-
import { useMemo as useMemo$1 } from "../hooks/useMemo.js";
|
|
5
|
-
import { useCallback } from "../hooks/useCallback.js";
|
|
6
|
-
import { useEffect } from "../hooks/useEffect.js";
|
|
7
|
-
import { useEffectEvent } from "../hooks/useEffectEvent.js";
|
|
8
|
-
import { use } from "../hooks/use.js";
|
|
9
|
-
import { useMemoCache } from "../hooks/useMemoCache.js";
|
|
1
|
+
import { useReducer as useReducer$1 } from "../react-hooks/useReducer.js";
|
|
2
|
+
import { useState as useState$1 } from "../react-hooks/useState.js";
|
|
3
|
+
import { useRef as useRef$1 } from "../react-hooks/useRef.js";
|
|
4
|
+
import { useMemo as useMemo$1 } from "../react-hooks/useMemo.js";
|
|
5
|
+
import { useCallback as useCallback$1 } from "../react-hooks/useCallback.js";
|
|
6
|
+
import { useEffect as useEffect$1 } from "../react-hooks/useEffect.js";
|
|
7
|
+
import { useEffectEvent as useEffectEvent$1 } from "../react-hooks/useEffectEvent.js";
|
|
8
|
+
import { use } from "../react-hooks/use.js";
|
|
9
|
+
import { useMemoCache } from "../react-hooks/useMemoCache.js";
|
|
10
10
|
import React from "react";
|
|
11
11
|
//#region src/core/react-dispatcher.ts
|
|
12
12
|
const tapDispatcher = {
|
|
@@ -14,11 +14,11 @@ const tapDispatcher = {
|
|
|
14
14
|
useReducer: useReducer$1,
|
|
15
15
|
useRef: useRef$1,
|
|
16
16
|
useMemo: useMemo$1,
|
|
17
|
-
useCallback,
|
|
18
|
-
useEffect,
|
|
19
|
-
useLayoutEffect: useEffect,
|
|
20
|
-
useInsertionEffect: useEffect,
|
|
21
|
-
useEffectEvent,
|
|
17
|
+
useCallback: useCallback$1,
|
|
18
|
+
useEffect: useEffect$1,
|
|
19
|
+
useLayoutEffect: useEffect$1,
|
|
20
|
+
useInsertionEffect: useEffect$1,
|
|
21
|
+
useEffectEvent: useEffectEvent$1,
|
|
22
22
|
useContext: use,
|
|
23
23
|
use,
|
|
24
24
|
useMemoCache
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-dispatcher.js","names":[],"sources":["../../src/core/react-dispatcher.ts"],"sourcesContent":["import React from \"react\";\nimport { useState } from \"../hooks/useState\";\nimport { useReducer } from \"../hooks/useReducer\";\nimport { useRef } from \"../hooks/useRef\";\nimport { useMemo } from \"../hooks/useMemo\";\nimport { useCallback } from \"../hooks/useCallback\";\nimport { useEffect } from \"../hooks/useEffect\";\nimport { useEffectEvent } from \"../hooks/useEffectEvent\";\nimport { use } from \"../hooks/use\";\nimport { useMemoCache } from \"../hooks/useMemoCache\";\n\n// The dispatcher React reads while a resource renders, so hooks imported from\n// \"react\" route to tap with no build step. Hooks tap has no equivalent for are\n// intentionally absent: calling one throws, which is the intended \"unsupported\n// in a resource\" signal.\nconst tapDispatcher = {\n useState,\n useReducer,\n useRef,\n useMemo,\n useCallback,\n useEffect,\n useLayoutEffect: useEffect,\n useInsertionEffect: useEffect,\n useEffectEvent,\n useContext: use,\n use,\n useMemoCache,\n};\n\n// React's live dispatcher slot differs by version: React 19 exposes it as `H` on\n// the client internals object; React 18 as `ReactCurrentDispatcher.current`.\nconst ReactRuntime = React as any;\nconst internals =\n ReactRuntime.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ??\n ReactRuntime.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nconst slot: { current: unknown } | null =\n internals == null\n ? null\n : \"H\" in internals\n ? {\n get current() {\n return internals.H;\n },\n set current(d) {\n internals.H = d;\n },\n }\n : \"ReactCurrentDispatcher\" in internals\n ? {\n get current() {\n return internals.ReactCurrentDispatcher.current;\n },\n set current(d) {\n internals.ReactCurrentDispatcher.current = d;\n },\n }\n : null;\n\n/**\n * Runs a resource body with tap's React dispatcher installed, so real React\n * hooks called inside it (`import { useState } from \"react\"`) route to tap, then\n * restores the previous dispatcher. If React's internal dispatcher slot can't be\n * found (an unsupported React version), the body runs unchanged and `react`\n * hooks inside it keep throwing React's \"invalid hook call\".\n */\nexport function withReactDispatcher<T>(render: () => T): T {\n if (!slot) return render();\n\n const previous = slot.current;\n slot.current = tapDispatcher;\n try {\n return render();\n } finally {\n slot.current = previous;\n }\n}\n"],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"react-dispatcher.js","names":["useEffect"],"sources":["../../src/core/react-dispatcher.ts"],"sourcesContent":["import React from \"react\";\n\nimport { useState } from \"../react-hooks/useState\";\nimport { useReducer } from \"../react-hooks/useReducer\";\nimport { useRef } from \"../react-hooks/useRef\";\nimport { useMemo } from \"../react-hooks/useMemo\";\nimport { useCallback } from \"../react-hooks/useCallback\";\nimport { useEffect } from \"../react-hooks/useEffect\";\nimport { useEffectEvent } from \"../react-hooks/useEffectEvent\";\nimport { use } from \"../react-hooks/use\";\nimport { useMemoCache } from \"../react-hooks/useMemoCache\";\n\n// The dispatcher React reads while a resource renders, so hooks imported from\n// \"react\" route to tap with no build step. Hooks tap has no equivalent for are\n// intentionally absent: calling one throws, which is the intended \"unsupported\n// in a resource\" signal.\nconst tapDispatcher = {\n useState,\n useReducer,\n useRef,\n useMemo,\n useCallback,\n useEffect,\n useLayoutEffect: useEffect,\n useInsertionEffect: useEffect,\n useEffectEvent,\n useContext: use,\n use,\n useMemoCache,\n};\n\n// React's live dispatcher slot differs by version: React 19 exposes it as `H` on\n// the client internals object; React 18 as `ReactCurrentDispatcher.current`.\nconst ReactRuntime = React as any;\nconst internals =\n ReactRuntime.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ??\n ReactRuntime.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nconst slot: { current: unknown } | null =\n internals == null\n ? null\n : \"H\" in internals\n ? {\n get current() {\n return internals.H;\n },\n set current(d) {\n internals.H = d;\n },\n }\n : \"ReactCurrentDispatcher\" in internals\n ? {\n get current() {\n return internals.ReactCurrentDispatcher.current;\n },\n set current(d) {\n internals.ReactCurrentDispatcher.current = d;\n },\n }\n : null;\n\n/**\n * Runs a resource body with tap's React dispatcher installed, so real React\n * hooks called inside it (`import { useState } from \"react\"`) route to tap, then\n * restores the previous dispatcher. If React's internal dispatcher slot can't be\n * found (an unsupported React version), the body runs unchanged and `react`\n * hooks inside it keep throwing React's \"invalid hook call\".\n */\nexport function withReactDispatcher<T>(render: () => T): T {\n if (!slot) return render();\n\n const previous = slot.current;\n slot.current = tapDispatcher;\n try {\n return render();\n } finally {\n slot.current = previous;\n }\n}\n"],"mappings":";;;;;;;;;;;AAgBA,MAAM,gBAAgB;CACpB,UAAA;CACA,YAAA;CACA,QAAA;CACA,SAAA;CACA,aAAA;CACA,WAAA;CACA,iBAAiBA;CACjB,oBAAoBA;CACpB,gBAAA;CACA,YAAY;CACZ;CACA;AACF;AAIA,MAAM,eAAe;AACrB,MAAM,YACJ,aAAa,mEACb,aAAa;AAEf,MAAM,OACJ,aAAa,OACT,OACA,OAAO,YACL;CACE,IAAI,UAAU;EACZ,OAAO,UAAU;CACnB;CACA,IAAI,QAAQ,GAAG;EACb,UAAU,IAAI;CAChB;AACF,IACA,4BAA4B,YAC1B;CACE,IAAI,UAAU;EACZ,OAAO,UAAU,uBAAuB;CAC1C;CACA,IAAI,QAAQ,GAAG;EACb,UAAU,uBAAuB,UAAU;CAC7C;AACF,IACA;;;;;;;;AASV,SAAgB,oBAAuB,QAAoB;CACzD,IAAI,CAAC,MAAM,OAAO,OAAO;CAEzB,MAAM,WAAW,KAAK;CACtB,KAAK,UAAU;CACf,IAAI;EACF,OAAO,OAAO;CAChB,UAAU;EACR,KAAK,UAAU;CACjB;AACF"}
|
package/dist/core/resource.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Resource } from "./types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/core/resource.d.ts
|
|
4
|
-
declare function resource<R>(
|
|
5
|
-
declare function resource<R, P>(fn: (props: P) => R): (props: P) => ResourceElement<R, P>;
|
|
6
|
-
declare function resource<R, P>(fn: (props?: P) => R): (props?: P) => ResourceElement<R, P | undefined>;
|
|
4
|
+
declare function resource<R, A extends readonly unknown[]>(hook: (...args: A) => R): Resource<R, A>;
|
|
7
5
|
//#endregion
|
|
8
6
|
export { resource };
|
|
9
7
|
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.d.ts","names":[],"sources":["../../src/core/resource.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"resource.d.ts","names":[],"sources":["../../src/core/resource.ts"],"mappings":";;;iBAEgB,QAAA,kCACd,IAAA,MAAU,IAAA,EAAM,CAAA,KAAM,CAAA,GACrB,QAAA,CAAS,CAAA,EAAG,CAAA"}
|
package/dist/core/resource.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import { fnSymbol } from "./helpers/callResourceFn.js";
|
|
2
1
|
//#region src/core/resource.ts
|
|
3
|
-
function resource(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
type[fnSymbol] = fn;
|
|
11
|
-
return type;
|
|
2
|
+
function resource(hook) {
|
|
3
|
+
return (...args) => ({
|
|
4
|
+
hook,
|
|
5
|
+
args
|
|
6
|
+
});
|
|
12
7
|
}
|
|
13
8
|
//#endregion
|
|
14
9
|
export { resource };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.js","names":[],"sources":["../../src/core/resource.ts"],"sourcesContent":["import type { ResourceElement } from \"./types\";\
|
|
1
|
+
{"version":3,"file":"resource.js","names":[],"sources":["../../src/core/resource.ts"],"sourcesContent":["import type { Resource, ResourceElement } from \"./types\";\n\nexport function resource<R, A extends readonly unknown[]>(\n hook: (...args: A) => R,\n): Resource<R, A> {\n return (...args: A): ResourceElement<R, A> => ({ hook, args });\n}\n"],"mappings":";AAEA,SAAgB,SACd,MACgB;CAChB,QAAQ,GAAG,UAAoC;EAAE;EAAM;CAAK;AAC9D"}
|
package/dist/core/scheduler.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ declare class UpdateScheduler {
|
|
|
8
8
|
markDirty(): void;
|
|
9
9
|
runTask(): void;
|
|
10
10
|
}
|
|
11
|
-
declare const
|
|
11
|
+
declare const flushTapSync: <T>(callback: () => T) => T;
|
|
12
12
|
//#endregion
|
|
13
|
-
export { UpdateScheduler,
|
|
13
|
+
export { UpdateScheduler, flushTapSync };
|
|
14
14
|
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.d.ts","names":[],"sources":["../../src/core/scheduler.ts"],"mappings":";KAAK,IAAA;AAAA,cAaQ,eAAA;EAAA,iBAGkB,KAAA;EAAA,QAFrB,QAAA;cAEqB,KAAA,EAAO,IAAI;EAAA,IAEpC,OAAA;EAIJ,SAAA;EAOA,OAAA;AAAA;AAAA,cAiEW,
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","names":[],"sources":["../../src/core/scheduler.ts"],"mappings":";KAAK,IAAA;AAAA,cAaQ,eAAA;EAAA,iBAGkB,KAAA;EAAA,QAFrB,QAAA;cAEqB,KAAA,EAAO,IAAI;EAAA,IAEpC,OAAA;EAIJ,SAAA;EAOA,OAAA;AAAA;AAAA,cAiEW,YAAA,MAAmB,QAAA,QAAgB,CAAA,KAAI,CAenD"}
|
package/dist/core/scheduler.js
CHANGED
|
@@ -61,7 +61,7 @@ const scheduleMacrotask = (() => {
|
|
|
61
61
|
}
|
|
62
62
|
return () => setTimeout(flushScheduled, 0);
|
|
63
63
|
})();
|
|
64
|
-
const
|
|
64
|
+
const flushTapSync = (callback) => {
|
|
65
65
|
const prev = flushState;
|
|
66
66
|
flushState = {
|
|
67
67
|
schedulers: /* @__PURE__ */ new Set([]),
|
|
@@ -76,6 +76,6 @@ const flushResourcesSync = (callback) => {
|
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
78
|
//#endregion
|
|
79
|
-
export { UpdateScheduler,
|
|
79
|
+
export { UpdateScheduler, flushTapSync };
|
|
80
80
|
|
|
81
81
|
//# sourceMappingURL=scheduler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","names":[],"sources":["../../src/core/scheduler.ts"],"sourcesContent":["type Task = () => void;\n\ntype GlobalFlushState = {\n schedulers: Set<UpdateScheduler>;\n isScheduled: boolean;\n};\n\nconst MAX_FLUSH_LIMIT = 50;\nlet flushState: GlobalFlushState = {\n schedulers: new Set([]),\n isScheduled: false,\n};\n\nexport class UpdateScheduler {\n private _isDirty = false;\n\n constructor(private readonly _task: Task) {}\n\n get isDirty() {\n return this._isDirty;\n }\n\n markDirty() {\n this._isDirty = true;\n\n flushState.schedulers.add(this);\n scheduleFlush();\n }\n\n runTask() {\n this._isDirty = false;\n this._task();\n }\n}\n\nconst scheduleFlush = () => {\n if (flushState.isScheduled) return;\n flushState.isScheduled = true;\n scheduleMacrotask();\n};\n\nconst flushScheduled = () => {\n try {\n const errors = [];\n let flushDepth = 0;\n\n for (const scheduler of flushState.schedulers) {\n flushState.schedulers.delete(scheduler);\n if (!scheduler.isDirty) continue;\n\n flushDepth++;\n\n if (flushDepth > MAX_FLUSH_LIMIT) {\n throw new Error(\n `Maximum update depth exceeded. This can happen when a resource ` +\n `repeatedly calls setState inside useEffect.`,\n );\n }\n\n try {\n scheduler.runTask();\n } catch (error) {\n errors.push(error);\n }\n }\n\n if (errors.length > 0) {\n if (errors.length === 1) {\n throw errors[0];\n } else {\n for (const error of errors) {\n console.error(error);\n }\n throw new AggregateError(errors, \"Errors occurred during flushSync\");\n }\n }\n } finally {\n flushState.schedulers.clear();\n flushState.isScheduled = false;\n }\n};\n\n// Use MessageChannel to schedule flushes as macrotasks (like React's scheduler).\n// This allows more state updates to batch into a single re-render.\nconst scheduleMacrotask = (() => {\n if (typeof MessageChannel !== \"undefined\") {\n const channel = new MessageChannel();\n channel.port1.onmessage = flushScheduled;\n return () => channel.port2.postMessage(null);\n }\n // Fallback for environments without MessageChannel\n return () => setTimeout(flushScheduled, 0);\n})();\n\nexport const
|
|
1
|
+
{"version":3,"file":"scheduler.js","names":[],"sources":["../../src/core/scheduler.ts"],"sourcesContent":["type Task = () => void;\n\ntype GlobalFlushState = {\n schedulers: Set<UpdateScheduler>;\n isScheduled: boolean;\n};\n\nconst MAX_FLUSH_LIMIT = 50;\nlet flushState: GlobalFlushState = {\n schedulers: new Set([]),\n isScheduled: false,\n};\n\nexport class UpdateScheduler {\n private _isDirty = false;\n\n constructor(private readonly _task: Task) {}\n\n get isDirty() {\n return this._isDirty;\n }\n\n markDirty() {\n this._isDirty = true;\n\n flushState.schedulers.add(this);\n scheduleFlush();\n }\n\n runTask() {\n this._isDirty = false;\n this._task();\n }\n}\n\nconst scheduleFlush = () => {\n if (flushState.isScheduled) return;\n flushState.isScheduled = true;\n scheduleMacrotask();\n};\n\nconst flushScheduled = () => {\n try {\n const errors = [];\n let flushDepth = 0;\n\n for (const scheduler of flushState.schedulers) {\n flushState.schedulers.delete(scheduler);\n if (!scheduler.isDirty) continue;\n\n flushDepth++;\n\n if (flushDepth > MAX_FLUSH_LIMIT) {\n throw new Error(\n `Maximum update depth exceeded. This can happen when a resource ` +\n `repeatedly calls setState inside useEffect.`,\n );\n }\n\n try {\n scheduler.runTask();\n } catch (error) {\n errors.push(error);\n }\n }\n\n if (errors.length > 0) {\n if (errors.length === 1) {\n throw errors[0];\n } else {\n for (const error of errors) {\n console.error(error);\n }\n throw new AggregateError(errors, \"Errors occurred during flushSync\");\n }\n }\n } finally {\n flushState.schedulers.clear();\n flushState.isScheduled = false;\n }\n};\n\n// Use MessageChannel to schedule flushes as macrotasks (like React's scheduler).\n// This allows more state updates to batch into a single re-render.\nconst scheduleMacrotask = (() => {\n if (typeof MessageChannel !== \"undefined\") {\n const channel = new MessageChannel();\n channel.port1.onmessage = flushScheduled;\n return () => channel.port2.postMessage(null);\n }\n // Fallback for environments without MessageChannel\n return () => setTimeout(flushScheduled, 0);\n})();\n\nexport const flushTapSync = <T>(callback: () => T): T => {\n const prev = flushState;\n flushState = {\n schedulers: new Set([]),\n isScheduled: true,\n };\n\n try {\n const result = callback();\n flushScheduled();\n\n return result;\n } finally {\n flushState = prev;\n }\n};\n"],"mappings":";AAOA,MAAM,kBAAkB;AACxB,IAAI,aAA+B;CACjC,4BAAY,IAAI,IAAI,CAAC,CAAC;CACtB,aAAa;AACf;AAEA,IAAa,kBAAb,MAA6B;CAGE;CAF7B,WAAmB;CAEnB,YAAY,OAA8B;EAAb,KAAA,QAAA;CAAc;CAE3C,IAAI,UAAU;EACZ,OAAO,KAAK;CACd;CAEA,YAAY;EACV,KAAK,WAAW;EAEhB,WAAW,WAAW,IAAI,IAAI;EAC9B,cAAc;CAChB;CAEA,UAAU;EACR,KAAK,WAAW;EAChB,KAAK,MAAM;CACb;AACF;AAEA,MAAM,sBAAsB;CAC1B,IAAI,WAAW,aAAa;CAC5B,WAAW,cAAc;CACzB,kBAAkB;AACpB;AAEA,MAAM,uBAAuB;CAC3B,IAAI;EACF,MAAM,SAAS,CAAC;EAChB,IAAI,aAAa;EAEjB,KAAK,MAAM,aAAa,WAAW,YAAY;GAC7C,WAAW,WAAW,OAAO,SAAS;GACtC,IAAI,CAAC,UAAU,SAAS;GAExB;GAEA,IAAI,aAAa,iBACf,MAAM,IAAI,MACR,4GAEF;GAGF,IAAI;IACF,UAAU,QAAQ;GACpB,SAAS,OAAO;IACd,OAAO,KAAK,KAAK;GACnB;EACF;EAEA,IAAI,OAAO,SAAS,GAClB,IAAI,OAAO,WAAW,GACpB,MAAM,OAAO;OACR;GACL,KAAK,MAAM,SAAS,QAClB,QAAQ,MAAM,KAAK;GAErB,MAAM,IAAI,eAAe,QAAQ,kCAAkC;EACrE;CAEJ,UAAU;EACR,WAAW,WAAW,MAAM;EAC5B,WAAW,cAAc;CAC3B;AACF;AAIA,MAAM,2BAA2B;CAC/B,IAAI,OAAO,mBAAmB,aAAa;EACzC,MAAM,UAAU,IAAI,eAAe;EACnC,QAAQ,MAAM,YAAY;EAC1B,aAAa,QAAQ,MAAM,YAAY,IAAI;CAC7C;CAEA,aAAa,WAAW,gBAAgB,CAAC;AAC3C,EAAA,CAAG;AAEH,MAAa,gBAAmB,aAAyB;CACvD,MAAM,OAAO;CACb,aAAa;EACX,4BAAY,IAAI,IAAI,CAAC,CAAC;EACtB,aAAa;CACf;CAEA,IAAI;EACF,MAAM,SAAS,SAAS;EACxB,eAAe;EAEf,OAAO;CACT,UAAU;EACR,aAAa;CACf;AACF"}
|