bippy 0.6.1-dev.b88fcb4 → 0.6.1-dev.f9a65c0
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 +211 -445
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +9 -59
- package/dist/core.d.ts +9 -59
- package/dist/core.js +1 -1
- package/dist/core2.cjs +1 -1
- package/dist/core2.d.cts +3 -3
- package/dist/core2.d.ts +3 -3
- package/dist/core2.js +1 -1
- package/dist/errors.d.cts +2 -57
- package/dist/errors.d.ts +2 -57
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +1 -1
- package/dist/install-hook-only.cjs +1 -1
- package/dist/install-hook-only.js +1 -1
- package/dist/rdt-hook.cjs +1 -1
- package/dist/rdt-hook.js +1 -1
- package/dist/source.cjs +12 -13
- package/dist/source.d.cts +77 -78
- package/dist/source.d.ts +77 -78
- package/dist/source.js +12 -13
- package/package.json +6 -3
- package/src/core.ts +106 -545
- package/src/errors.ts +0 -65
- package/src/index.ts +1 -0
- package/src/install-hook-only.ts +2 -2
- package/src/rdt-hook.ts +30 -43
- package/src/react-internals/generated/react-work-tags.ts +6 -2
- package/src/react-internals/index.ts +4 -4
- package/src/react-internals/semver.ts +2 -0
- package/src/react-internals/types.ts +0 -83
- package/src/react.ts +76 -0
- package/src/source/get-display-name-from-source.ts +44 -40
- package/src/source/get-source.ts +40 -24
- package/src/source/index.ts +2 -0
- package/src/source/inspect-hooks.ts +70 -91
- package/src/source/owner-stack.ts +60 -89
- package/src/source/parse-hook-names.ts +14 -53
- package/src/source/parse-stack.ts +14 -31
- package/src/source/renderer-dispatchers.ts +30 -0
- package/src/source/symbolication.ts +312 -111
- package/dist/index.iife.js +0 -9
- package/dist/install-hook-only.iife.js +0 -9
package/src/source/get-source.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Fiber } from "../react-internals/index.js";
|
|
2
|
+
import { getDisplayName } from "../core.js";
|
|
2
3
|
|
|
3
4
|
import type { FiberSource } from "./types.js";
|
|
4
5
|
import {
|
|
@@ -12,8 +13,13 @@ import {
|
|
|
12
13
|
} from "./constants.js";
|
|
13
14
|
import { getDefinitionFrameFromOwnedChild, getParentStack, hasDebugStack } from "./owner-stack.js";
|
|
14
15
|
import { parseDebugStack } from "./parse-debug-stack.js";
|
|
15
|
-
import { StackFrame } from "./parse-stack.js";
|
|
16
|
-
import {
|
|
16
|
+
import { parseStack, type StackFrame } from "./parse-stack.js";
|
|
17
|
+
import {
|
|
18
|
+
getSourceFromSourceMapByFunctionName,
|
|
19
|
+
getSourceMap,
|
|
20
|
+
symbolicateStack,
|
|
21
|
+
type SourceFetch,
|
|
22
|
+
} from "./symbolication.js";
|
|
17
23
|
|
|
18
24
|
export const hasDebugSource = (
|
|
19
25
|
fiber: Fiber,
|
|
@@ -26,10 +32,8 @@ export const hasDebugSource = (
|
|
|
26
32
|
}
|
|
27
33
|
return (
|
|
28
34
|
typeof debugSource === "object" &&
|
|
29
|
-
debugSource !== null &&
|
|
30
|
-
"fileName" in debugSource &&
|
|
31
35
|
typeof debugSource.fileName === "string" &&
|
|
32
|
-
"
|
|
36
|
+
debugSource.fileName !== "(native)" &&
|
|
33
37
|
typeof debugSource.lineNumber === "number"
|
|
34
38
|
);
|
|
35
39
|
};
|
|
@@ -63,6 +67,30 @@ const getUsageFrameFromDebugStack = (fiber: Fiber): StackFrame | null => {
|
|
|
63
67
|
return null;
|
|
64
68
|
};
|
|
65
69
|
|
|
70
|
+
const getSourceByComponentName = async (
|
|
71
|
+
fiber: Fiber,
|
|
72
|
+
cache: boolean,
|
|
73
|
+
fetchFn: SourceFetch | undefined,
|
|
74
|
+
): Promise<FiberSource | null> => {
|
|
75
|
+
const functionName = getDisplayName(fiber.type);
|
|
76
|
+
if (!functionName) return null;
|
|
77
|
+
|
|
78
|
+
const runtimeStackFrames = parseStack(new Error().stack ?? "");
|
|
79
|
+
const visitedFileNames = new Set<string>();
|
|
80
|
+
for (const stackFrame of runtimeStackFrames) {
|
|
81
|
+
const fileName = stackFrame.fileName;
|
|
82
|
+
if (!fileName || visitedFileNames.has(fileName)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
visitedFileNames.add(fileName);
|
|
86
|
+
const sourceMap = await getSourceMap(fileName, cache, fetchFn);
|
|
87
|
+
if (!sourceMap) continue;
|
|
88
|
+
const source = getSourceFromSourceMapByFunctionName(sourceMap, functionName);
|
|
89
|
+
if (source && !source.isIgnoreListed) return toFiberSource(source);
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
};
|
|
93
|
+
|
|
66
94
|
/**
|
|
67
95
|
* Returns the source of where the component is used. Available only in dev, for composite {@link Fiber}s.
|
|
68
96
|
*
|
|
@@ -92,11 +120,10 @@ const getUsageFrameFromDebugStack = (fiber: Fiber): StackFrame | null => {
|
|
|
92
120
|
export const getSource = async (
|
|
93
121
|
fiber: Fiber,
|
|
94
122
|
cache = true,
|
|
95
|
-
fetchFn?:
|
|
123
|
+
fetchFn?: SourceFetch,
|
|
96
124
|
): Promise<FiberSource | null> => {
|
|
97
125
|
if (hasDebugSource(fiber)) {
|
|
98
|
-
|
|
99
|
-
return debugSource || null;
|
|
126
|
+
return fiber._debugSource;
|
|
100
127
|
}
|
|
101
128
|
|
|
102
129
|
const debugStackFrame =
|
|
@@ -115,16 +142,11 @@ export const getSource = async (
|
|
|
115
142
|
return toFiberSource(stackFrame);
|
|
116
143
|
}
|
|
117
144
|
}
|
|
118
|
-
return
|
|
145
|
+
return getSourceByComponentName(fiber, cache, fetchFn);
|
|
119
146
|
};
|
|
120
147
|
|
|
121
148
|
const getPathSegmentCount = (path: string): number => path.split("/").filter(Boolean).length;
|
|
122
149
|
|
|
123
|
-
const getFirstPathSegment = (path: string): string | null => {
|
|
124
|
-
const segments = path.split("/").filter(Boolean);
|
|
125
|
-
return segments[0] ?? null;
|
|
126
|
-
};
|
|
127
|
-
|
|
128
150
|
const stripSingleBasePathPrefix = (path: string): string => {
|
|
129
151
|
const firstSlashIndex = path.indexOf("/", 1);
|
|
130
152
|
if (firstSlashIndex === -1) {
|
|
@@ -141,15 +163,12 @@ const stripSingleBasePathPrefix = (path: string): string => {
|
|
|
141
163
|
return path;
|
|
142
164
|
}
|
|
143
165
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const firstRemainderSegment = getFirstPathSegment(remainderPath);
|
|
149
|
-
if (!firstRemainderSegment) {
|
|
166
|
+
const remainderSegments = remainderPath.split("/").filter(Boolean);
|
|
167
|
+
if (remainderSegments.length < 2) {
|
|
150
168
|
return path;
|
|
151
169
|
}
|
|
152
170
|
|
|
171
|
+
const firstRemainderSegment = remainderSegments[0];
|
|
153
172
|
if (firstRemainderSegment.startsWith("@")) {
|
|
154
173
|
return path;
|
|
155
174
|
}
|
|
@@ -180,9 +199,6 @@ export const normalizeFileName = (fileName: string): string => {
|
|
|
180
199
|
const parsedUrl = new URL(normalizedFileName);
|
|
181
200
|
normalizedFileName = parsedUrl.pathname;
|
|
182
201
|
} catch {}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (isHttpUrl) {
|
|
186
202
|
normalizedFileName = stripSingleBasePathPrefix(normalizedFileName);
|
|
187
203
|
}
|
|
188
204
|
|
|
@@ -215,7 +231,7 @@ export const normalizeFileName = (fileName: string): string => {
|
|
|
215
231
|
}
|
|
216
232
|
}
|
|
217
233
|
|
|
218
|
-
if (!isWindowsDrivePath
|
|
234
|
+
if (!isWindowsDrivePath) {
|
|
219
235
|
const schemeMatch = normalizedFileName.match(SCHEME_REGEX);
|
|
220
236
|
if (schemeMatch) {
|
|
221
237
|
normalizedFileName = normalizedFileName.slice(schemeMatch[0].length);
|
package/src/source/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { formatOwnerStack, getOwnerStack, getParentStack, hasDebugStack } from "./owner-stack.js";
|
|
2
2
|
export { getSource, isSourceFile, normalizeFileName } from "./get-source.js";
|
|
3
3
|
export {
|
|
4
|
+
getSourceContentFromSourceMap,
|
|
4
5
|
getSourceFromSourceMap,
|
|
6
|
+
getSourceFromSourceMapByFunctionName,
|
|
5
7
|
getSourceMap,
|
|
6
8
|
symbolicateStack,
|
|
7
9
|
type DecodedSourceMapSection,
|
|
@@ -12,7 +12,11 @@ import {
|
|
|
12
12
|
} from "../errors.js";
|
|
13
13
|
import { getReactWorkTagsForFiber } from "../react-internals/index.js";
|
|
14
14
|
import { parseStack, type StackFrame } from "./parse-stack.js";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
getRendererDispatcherRefs,
|
|
17
|
+
readDispatcher,
|
|
18
|
+
writeDispatcher,
|
|
19
|
+
} from "./renderer-dispatchers.js";
|
|
16
20
|
|
|
17
21
|
const REACT_CONTEXT_TYPE = Symbol.for("react.context");
|
|
18
22
|
const REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
|
|
@@ -77,7 +81,7 @@ let currentThenableIndex = 0;
|
|
|
77
81
|
let currentThenableState: unknown[] | null = null;
|
|
78
82
|
|
|
79
83
|
const SuspenseException: unknown = new Error(
|
|
80
|
-
"Suspense
|
|
84
|
+
"Suspense interrupted this render. This error is an internal implementation detail of `use`.",
|
|
81
85
|
);
|
|
82
86
|
|
|
83
87
|
const parseErrorStack = (error: Error): StackFrame[] =>
|
|
@@ -89,28 +93,31 @@ const nextHook = (): MemoizedState | null => {
|
|
|
89
93
|
return hook;
|
|
90
94
|
};
|
|
91
95
|
|
|
92
|
-
const isObjectRecord = (value: unknown): value is Record<string, unknown> =>
|
|
93
|
-
typeof value === "object" && value !== null;
|
|
94
|
-
|
|
95
96
|
const isInspectableThenable = (value: unknown): value is InspectableThenable =>
|
|
96
|
-
|
|
97
|
+
typeof value === "object" &&
|
|
98
|
+
value !== null &&
|
|
99
|
+
"then" in value &&
|
|
100
|
+
typeof value.then === "function";
|
|
97
101
|
|
|
98
102
|
const isInspectableRef = (value: unknown): value is InspectableRef =>
|
|
99
|
-
|
|
103
|
+
typeof value === "object" && value !== null && "current" in value;
|
|
100
104
|
|
|
101
105
|
const isReactContext = (value: unknown): value is ReactContext<unknown> =>
|
|
102
|
-
|
|
106
|
+
typeof value === "object" && value !== null && "_currentValue" in value;
|
|
103
107
|
|
|
104
108
|
const isContextDependency = (value: unknown): value is ContextDependency<unknown> =>
|
|
105
|
-
|
|
109
|
+
typeof value === "object" && value !== null && "context" in value && "next" in value;
|
|
106
110
|
|
|
107
111
|
const isForwardRefRenderType = (value: unknown): value is ForwardRefRenderType =>
|
|
108
|
-
|
|
112
|
+
typeof value === "object" &&
|
|
113
|
+
value !== null &&
|
|
114
|
+
"render" in value &&
|
|
115
|
+
typeof value.render === "function";
|
|
109
116
|
|
|
110
117
|
const readContext = (context: InspectableReactContext): unknown => {
|
|
111
118
|
if (currentFiber === null) return context._currentValue;
|
|
112
119
|
if (currentContextDependency === null) {
|
|
113
|
-
throw new BippyHookInspectionError("Context reads
|
|
120
|
+
throw new BippyHookInspectionError("Context reads don’t match context dependencies.");
|
|
114
121
|
}
|
|
115
122
|
if (Object.hasOwn(currentContextDependency, "memoizedValue")) {
|
|
116
123
|
const value = currentContextDependency.memoizedValue;
|
|
@@ -120,27 +127,6 @@ const readContext = (context: InspectableReactContext): unknown => {
|
|
|
120
127
|
return context._currentValue;
|
|
121
128
|
};
|
|
122
129
|
|
|
123
|
-
const getDispatcherRef = (): RendererDispatcherRef | null => {
|
|
124
|
-
const rdtHook = getRDTHook();
|
|
125
|
-
const allRenderers = [..._renderers, ...rdtHook.renderers.values()];
|
|
126
|
-
for (const renderer of allRenderers) {
|
|
127
|
-
const ref = renderer.currentDispatcherRef;
|
|
128
|
-
if (ref) return ref;
|
|
129
|
-
}
|
|
130
|
-
return null;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const getDispatcherFromRef = (ref: RendererDispatcherRef): unknown =>
|
|
134
|
-
"H" in ref ? ref.H : ref.current;
|
|
135
|
-
|
|
136
|
-
const setDispatcherOnRef = (ref: RendererDispatcherRef, dispatcher: unknown): void => {
|
|
137
|
-
if ("H" in ref) {
|
|
138
|
-
ref.H = dispatcher;
|
|
139
|
-
} else {
|
|
140
|
-
ref.current = dispatcher;
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
|
|
144
130
|
const pushHookLogEntry = (
|
|
145
131
|
primitive: string,
|
|
146
132
|
value: unknown,
|
|
@@ -157,7 +143,7 @@ const pushHookLogEntry = (
|
|
|
157
143
|
};
|
|
158
144
|
|
|
159
145
|
const dispatcherUse = (usable: unknown): unknown => {
|
|
160
|
-
if (
|
|
146
|
+
if (typeof usable === "object" && usable !== null) {
|
|
161
147
|
if (isInspectableThenable(usable)) {
|
|
162
148
|
const cachedThenable =
|
|
163
149
|
currentThenableState !== null && currentThenableIndex < currentThenableState.length
|
|
@@ -176,7 +162,7 @@ const dispatcherUse = (usable: unknown): unknown => {
|
|
|
176
162
|
pushHookLogEntry("Unresolved", thenable, "Use");
|
|
177
163
|
throw SuspenseException;
|
|
178
164
|
}
|
|
179
|
-
if (usable.$$typeof === REACT_CONTEXT_TYPE &&
|
|
165
|
+
if ("$$typeof" in usable && usable.$$typeof === REACT_CONTEXT_TYPE && isReactContext(usable)) {
|
|
180
166
|
const context: InspectableReactContext = {
|
|
181
167
|
_currentValue: usable._currentValue,
|
|
182
168
|
displayName: typeof usable.displayName === "string" ? usable.displayName : undefined,
|
|
@@ -186,7 +172,7 @@ const dispatcherUse = (usable: unknown): unknown => {
|
|
|
186
172
|
return value;
|
|
187
173
|
}
|
|
188
174
|
}
|
|
189
|
-
throw new BippyHookInspectionError("
|
|
175
|
+
throw new BippyHookInspectionError("use() received an unsupported value: " + String(usable));
|
|
190
176
|
};
|
|
191
177
|
|
|
192
178
|
const dispatcherUseContext = (context: InspectableReactContext): unknown => {
|
|
@@ -251,10 +237,7 @@ const dispatcherUseEffect = (create: () => void): void => {
|
|
|
251
237
|
|
|
252
238
|
const dispatcherUseImperativeHandle = (ref: unknown): void => {
|
|
253
239
|
nextHook();
|
|
254
|
-
|
|
255
|
-
if (ref !== null && typeof ref === "object" && "current" in ref) {
|
|
256
|
-
instance = ref.current;
|
|
257
|
-
}
|
|
240
|
+
const instance = isInspectableRef(ref) ? ref.current : undefined;
|
|
258
241
|
pushHookLogEntry("ImperativeHandle", instance, "ImperativeHandle");
|
|
259
242
|
};
|
|
260
243
|
|
|
@@ -380,15 +363,8 @@ const createActionStateDispatcher =
|
|
|
380
363
|
const hook = nextHook();
|
|
381
364
|
nextHook();
|
|
382
365
|
nextHook();
|
|
383
|
-
const stackError = new Error();
|
|
384
366
|
const { value, error } = inspectActionStateHook(hook, initialState);
|
|
385
|
-
|
|
386
|
-
displayName: null,
|
|
387
|
-
primitive,
|
|
388
|
-
stackError,
|
|
389
|
-
value,
|
|
390
|
-
dispatcherHookName: primitive,
|
|
391
|
-
});
|
|
367
|
+
pushHookLogEntry(primitive, value, primitive);
|
|
392
368
|
if (error !== null) throw error;
|
|
393
369
|
return [value, () => {}, false];
|
|
394
370
|
};
|
|
@@ -436,15 +412,12 @@ const dispatcher = {
|
|
|
436
412
|
useEffectEvent: dispatcherUseEffectEvent,
|
|
437
413
|
};
|
|
438
414
|
|
|
439
|
-
const dispatcherProxy =
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
throw new BippyUnsupportedHookError("Missing method in Dispatcher: " + propertyName);
|
|
446
|
-
},
|
|
447
|
-
});
|
|
415
|
+
const dispatcherProxy = new Proxy(dispatcher, {
|
|
416
|
+
get(target, propertyName: string) {
|
|
417
|
+
if (Object.hasOwn(target, propertyName)) return Reflect.get(target, propertyName);
|
|
418
|
+
throw new BippyUnsupportedHookError("The React dispatcher is missing method " + propertyName);
|
|
419
|
+
},
|
|
420
|
+
});
|
|
448
421
|
|
|
449
422
|
const getPrimitiveStackCache = (): Map<string, StackFrame[]> => {
|
|
450
423
|
if (primitiveStackCache !== null) return primitiveStackCache;
|
|
@@ -457,7 +430,7 @@ const getPrimitiveStackCache = (): Map<string, StackFrame[]> => {
|
|
|
457
430
|
dispatcher.useState(null);
|
|
458
431
|
dispatcher.useReducer((state: unknown) => state, null);
|
|
459
432
|
dispatcher.useRef(null);
|
|
460
|
-
|
|
433
|
+
dispatcher.useCacheRefresh();
|
|
461
434
|
dispatcher.useLayoutEffect(() => {});
|
|
462
435
|
dispatcher.useInsertionEffect(() => {});
|
|
463
436
|
dispatcher.useEffect(() => {});
|
|
@@ -475,19 +448,16 @@ const getPrimitiveStackCache = (): Map<string, StackFrame[]> => {
|
|
|
475
448
|
dispatcher.useFormState((state: unknown) => state, null);
|
|
476
449
|
dispatcher.useActionState((state: unknown) => state, null);
|
|
477
450
|
dispatcher.useHostTransitionStatus();
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
dispatcher.use(
|
|
485
|
-
|
|
486
|
-
dispatcher.use(new Promise<never>(() => {}));
|
|
487
|
-
} catch {}
|
|
488
|
-
}
|
|
451
|
+
dispatcher.use({ $$typeof: REACT_CONTEXT_TYPE, _currentValue: null });
|
|
452
|
+
const fulfilledPromise = Promise.resolve(null);
|
|
453
|
+
Reflect.set(fulfilledPromise, "status", "fulfilled");
|
|
454
|
+
Reflect.set(fulfilledPromise, "value", null);
|
|
455
|
+
dispatcher.use(fulfilledPromise);
|
|
456
|
+
try {
|
|
457
|
+
dispatcher.use(new Promise<never>(() => {}));
|
|
458
|
+
} catch {}
|
|
489
459
|
dispatcher.useId();
|
|
490
|
-
|
|
460
|
+
dispatcher.useEffectEvent(() => {});
|
|
491
461
|
} finally {
|
|
492
462
|
capturedHookLog = hookLog;
|
|
493
463
|
hookLog = [];
|
|
@@ -718,7 +688,10 @@ const setupContexts = (contextMap: Map<ReactContext<unknown>, unknown>, fiber: F
|
|
|
718
688
|
while (current) {
|
|
719
689
|
if (current.tag === getReactWorkTagsForFiber(current).ContextProvider) {
|
|
720
690
|
const providerType = current.type;
|
|
721
|
-
const nestedContext =
|
|
691
|
+
const nestedContext =
|
|
692
|
+
typeof providerType === "object" && providerType !== null && "_context" in providerType
|
|
693
|
+
? providerType._context
|
|
694
|
+
: undefined;
|
|
722
695
|
const context = isReactContext(nestedContext)
|
|
723
696
|
? nestedContext
|
|
724
697
|
: isReactContext(providerType)
|
|
@@ -742,7 +715,7 @@ const restoreContexts = (contextMap: Map<ReactContext<unknown>, unknown>): void
|
|
|
742
715
|
const handleRenderFunctionError = (error: unknown): void => {
|
|
743
716
|
if (error === SuspenseException) return;
|
|
744
717
|
if (error instanceof BippyUnsupportedHookError) throw error;
|
|
745
|
-
throw new BippyHookRenderError("
|
|
718
|
+
throw new BippyHookRenderError("Bippy couldn’t render the inspected component", error);
|
|
746
719
|
};
|
|
747
720
|
|
|
748
721
|
const resolveDefaultProps = (
|
|
@@ -753,13 +726,14 @@ const resolveDefaultProps = (
|
|
|
753
726
|
component &&
|
|
754
727
|
typeof component === "object" &&
|
|
755
728
|
"defaultProps" in component &&
|
|
756
|
-
|
|
729
|
+
typeof component.defaultProps === "object" &&
|
|
730
|
+
component.defaultProps !== null
|
|
757
731
|
) {
|
|
758
732
|
const props = { ...baseProps };
|
|
759
733
|
const defaultProps = component.defaultProps;
|
|
760
|
-
for (const propName
|
|
734
|
+
for (const [propName, value] of Object.entries(defaultProps)) {
|
|
761
735
|
if (props[propName] === undefined) {
|
|
762
|
-
props[propName] =
|
|
736
|
+
props[propName] = value;
|
|
763
737
|
}
|
|
764
738
|
}
|
|
765
739
|
return props;
|
|
@@ -790,8 +764,8 @@ const performDispatcherInspection = (
|
|
|
790
764
|
dispatcherRef: RendererDispatcherRef,
|
|
791
765
|
renderFn: () => void,
|
|
792
766
|
): HooksTree => {
|
|
793
|
-
const previousDispatcher =
|
|
794
|
-
|
|
767
|
+
const previousDispatcher = readDispatcher(dispatcherRef);
|
|
768
|
+
writeDispatcher(dispatcherRef, dispatcherProxy);
|
|
795
769
|
|
|
796
770
|
let capturedHookLog: HookLogEntry[] = [];
|
|
797
771
|
let ancestorStackError: Error | undefined;
|
|
@@ -804,7 +778,7 @@ const performDispatcherInspection = (
|
|
|
804
778
|
} finally {
|
|
805
779
|
capturedHookLog = hookLog;
|
|
806
780
|
hookLog = [];
|
|
807
|
-
|
|
781
|
+
writeDispatcher(dispatcherRef, previousDispatcher);
|
|
808
782
|
}
|
|
809
783
|
|
|
810
784
|
const rootStack = ancestorStackError !== undefined ? parseErrorStack(ancestorStackError) : [];
|
|
@@ -812,33 +786,40 @@ const performDispatcherInspection = (
|
|
|
812
786
|
};
|
|
813
787
|
|
|
814
788
|
const requireDispatcherRef = (): RendererDispatcherRef => {
|
|
815
|
-
const dispatcherRef =
|
|
789
|
+
const dispatcherRef = getRendererDispatcherRefs()[0];
|
|
816
790
|
if (!dispatcherRef) {
|
|
817
791
|
throw new BippyHookInspectionError(
|
|
818
|
-
"
|
|
792
|
+
"Bippy couldn’t find a React renderer. Load React and install Bippy’s hook.",
|
|
819
793
|
);
|
|
820
794
|
}
|
|
821
795
|
return dispatcherRef;
|
|
822
796
|
};
|
|
823
797
|
|
|
824
798
|
const resolveContextDependency = (fiber: Fiber): void => {
|
|
799
|
+
const legacyDependenciesKey = ["dependencies_old", "dependencies_new"].find((key) =>
|
|
800
|
+
Object.hasOwn(fiber, key),
|
|
801
|
+
);
|
|
825
802
|
if (Object.hasOwn(fiber, "dependencies")) {
|
|
826
803
|
const dependencies = fiber.dependencies;
|
|
827
804
|
currentContextDependency = dependencies !== null ? dependencies.firstContext : null;
|
|
828
|
-
} else if (
|
|
829
|
-
const dependencies: unknown = Reflect.get(fiber,
|
|
830
|
-
const firstContext =
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
const firstContext = isObjectRecord(dependencies) ? dependencies.firstContext : null;
|
|
805
|
+
} else if (legacyDependenciesKey) {
|
|
806
|
+
const dependencies: unknown = Reflect.get(fiber, legacyDependenciesKey);
|
|
807
|
+
const firstContext =
|
|
808
|
+
typeof dependencies === "object" && dependencies !== null && "firstContext" in dependencies
|
|
809
|
+
? dependencies.firstContext
|
|
810
|
+
: null;
|
|
835
811
|
currentContextDependency = isContextDependency(firstContext) ? firstContext : null;
|
|
836
812
|
} else if (Object.hasOwn(fiber, "contextDependencies")) {
|
|
837
813
|
const contextDependencies: unknown = Reflect.get(fiber, "contextDependencies");
|
|
838
|
-
const firstContext =
|
|
814
|
+
const firstContext =
|
|
815
|
+
typeof contextDependencies === "object" &&
|
|
816
|
+
contextDependencies !== null &&
|
|
817
|
+
"first" in contextDependencies
|
|
818
|
+
? contextDependencies.first
|
|
819
|
+
: null;
|
|
839
820
|
currentContextDependency = isContextDependency(firstContext) ? firstContext : null;
|
|
840
821
|
} else {
|
|
841
|
-
throw new BippyHookInspectionError("
|
|
822
|
+
throw new BippyHookInspectionError("Bippy doesn’t support this React version.");
|
|
842
823
|
}
|
|
843
824
|
};
|
|
844
825
|
|
|
@@ -851,9 +832,7 @@ export const getFiberHooks = (fiber: Fiber): HooksTree => {
|
|
|
851
832
|
fiber.tag !== workTags.SimpleMemoComponent &&
|
|
852
833
|
fiber.tag !== workTags.ForwardRef
|
|
853
834
|
) {
|
|
854
|
-
throw new BippyHookInspectionError(
|
|
855
|
-
"Unknown Fiber. Needs to be a function component to inspect hooks.",
|
|
856
|
-
);
|
|
835
|
+
throw new BippyHookInspectionError("Hook inspection requires a function component Fiber.");
|
|
857
836
|
}
|
|
858
837
|
|
|
859
838
|
getPrimitiveStackCache();
|