bippy 0.6.1-dev.61475ed → 0.6.1-dev.d7876ea
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 +32 -48
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +42 -56
- package/dist/core.d.ts +42 -56
- package/dist/core.js +1 -1
- package/dist/core2.cjs +9 -0
- package/dist/core2.d.cts +3 -3
- package/dist/core2.d.ts +3 -3
- package/dist/core2.js +9 -0
- package/dist/errors.d.cts +436 -0
- package/dist/errors.d.ts +436 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.iife.js +1 -1
- package/dist/index.js +1 -1
- package/dist/install-hook-only.cjs +1 -1
- package/dist/install-hook-only.d.cts +1 -1
- package/dist/install-hook-only.d.ts +1 -1
- package/dist/install-hook-only.iife.js +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 +14 -4
- package/dist/source.d.cts +18 -9
- package/dist/source.d.ts +18 -9
- package/dist/source.js +14 -4
- package/package.json +21 -15
- package/src/core.ts +343 -253
- package/src/errors.ts +99 -0
- package/src/generated/react-work-tags.d.ts +261 -0
- package/src/generated/react-work-tags.js +240 -0
- package/src/rdt-hook.ts +154 -149
- package/src/react-internals.ts +65 -0
- package/src/semver.ts +78 -0
- package/src/source/constants.ts +1 -1
- package/src/source/error-stack.ts +11 -0
- package/src/source/get-source.ts +2 -1
- package/src/source/index.ts +9 -1
- package/src/source/inspect-hooks.ts +199 -164
- package/src/source/owner-stack.ts +84 -114
- package/src/source/parse-debug-stack.ts +4 -4
- package/src/source/parse-stack.ts +1 -1
- package/src/source/symbolication.ts +365 -89
- package/src/types.ts +165 -334
- package/src/unsubscribe.ts +2 -2
- package/dist/get-source.cjs +0 -19
- package/dist/get-source.js +0 -19
- package/dist/react-refresh.cjs +0 -9
- package/dist/react-refresh.d.cts +0 -66
- package/dist/react-refresh.d.ts +0 -66
- package/dist/react-refresh.js +0 -9
- package/dist/unsubscribe.d.cts +0 -298
- package/dist/unsubscribe.d.ts +0 -298
- package/src/react-refresh/constants.ts +0 -9
- package/src/react-refresh/detect-hmr-transport.ts +0 -33
- package/src/react-refresh/index.ts +0 -173
- package/src/react-refresh/metro-hmr-transport.ts +0 -188
- package/src/react-refresh/next-webpack-hmr-transport.ts +0 -72
- package/src/react-refresh/normalize-hmr-file-path.ts +0 -24
- package/src/react-refresh/types.ts +0 -7
- package/src/react-refresh/vite-hmr-transport.ts +0 -116
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Fiber,
|
|
3
|
+
ContextDependency,
|
|
4
|
+
MemoizedState,
|
|
5
|
+
ReactContext,
|
|
6
|
+
RendererDispatcherRef,
|
|
7
|
+
} from "../types.js";
|
|
8
|
+
import {
|
|
9
|
+
BippyHookInspectionError,
|
|
10
|
+
BippyHookRenderError,
|
|
11
|
+
BippyUnsupportedHookError,
|
|
12
|
+
} from "../errors.js";
|
|
13
|
+
import { getReactWorkTagsForFiber } from "../react-internals.js";
|
|
2
14
|
import { parseStack, type StackFrame } from "./parse-stack.js";
|
|
3
15
|
import { getRDTHook, _renderers } from "../rdt-hook.js";
|
|
4
16
|
|
|
5
17
|
const REACT_CONTEXT_TYPE = Symbol.for("react.context");
|
|
6
18
|
const REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
|
|
7
19
|
|
|
8
|
-
const FUNCTION_COMPONENT_TAG = 0;
|
|
9
|
-
const CONTEXT_PROVIDER_TAG = 10;
|
|
10
|
-
const FORWARD_REF_TAG = 11;
|
|
11
|
-
const SIMPLE_MEMO_COMPONENT_TAG = 15;
|
|
12
|
-
|
|
13
20
|
export interface HookSource {
|
|
14
21
|
lineNumber: number | null;
|
|
15
22
|
columnNumber: number | null;
|
|
@@ -26,8 +33,7 @@ export interface HooksNode {
|
|
|
26
33
|
hookSource: HookSource | null;
|
|
27
34
|
}
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
export interface HooksTree extends Array<HooksNode> {}
|
|
36
|
+
export type HooksTree = HooksNode[];
|
|
31
37
|
|
|
32
38
|
interface HookLogEntry {
|
|
33
39
|
displayName: string | null;
|
|
@@ -37,10 +43,29 @@ interface HookLogEntry {
|
|
|
37
43
|
dispatcherHookName: string;
|
|
38
44
|
}
|
|
39
45
|
|
|
40
|
-
interface
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
interface InspectableReactContext {
|
|
47
|
+
_currentValue: unknown;
|
|
48
|
+
displayName?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface InspectableRef {
|
|
52
|
+
current: unknown;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface InspectableThenable {
|
|
56
|
+
reason?: unknown;
|
|
57
|
+
status?: unknown;
|
|
58
|
+
then: (...arguments_: unknown[]) => unknown;
|
|
59
|
+
value?: unknown;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface ForwardRefRenderType {
|
|
63
|
+
render: (props: Record<string, unknown>, ref: unknown) => unknown;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface InspectedActionState {
|
|
67
|
+
error: unknown;
|
|
68
|
+
value: unknown;
|
|
44
69
|
}
|
|
45
70
|
|
|
46
71
|
let hookLog: HookLogEntry[] = [];
|
|
@@ -49,8 +74,7 @@ let currentFiber: Fiber | null = null;
|
|
|
49
74
|
let currentHook: MemoizedState | null = null;
|
|
50
75
|
let currentContextDependency: ContextDependency<unknown> | null = null;
|
|
51
76
|
let currentThenableIndex = 0;
|
|
52
|
-
|
|
53
|
-
let currentThenableState: any[] | null = null;
|
|
77
|
+
let currentThenableState: unknown[] | null = null;
|
|
54
78
|
|
|
55
79
|
const SuspenseException: unknown = new Error(
|
|
56
80
|
"Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render.",
|
|
@@ -65,33 +89,51 @@ const nextHook = (): MemoizedState | null => {
|
|
|
65
89
|
return hook;
|
|
66
90
|
};
|
|
67
91
|
|
|
68
|
-
const
|
|
92
|
+
const isObjectRecord = (value: unknown): value is Record<string, unknown> =>
|
|
93
|
+
typeof value === "object" && value !== null;
|
|
94
|
+
|
|
95
|
+
const isInspectableThenable = (value: unknown): value is InspectableThenable =>
|
|
96
|
+
isObjectRecord(value) && typeof value.then === "function";
|
|
97
|
+
|
|
98
|
+
const isInspectableRef = (value: unknown): value is InspectableRef =>
|
|
99
|
+
isObjectRecord(value) && "current" in value;
|
|
100
|
+
|
|
101
|
+
const isReactContext = (value: unknown): value is ReactContext<unknown> =>
|
|
102
|
+
isObjectRecord(value) && "_currentValue" in value;
|
|
103
|
+
|
|
104
|
+
const isContextDependency = (value: unknown): value is ContextDependency<unknown> =>
|
|
105
|
+
isObjectRecord(value) && "context" in value && "next" in value;
|
|
106
|
+
|
|
107
|
+
const isForwardRefRenderType = (value: unknown): value is ForwardRefRenderType =>
|
|
108
|
+
isObjectRecord(value) && typeof value.render === "function";
|
|
109
|
+
|
|
110
|
+
const readContext = (context: InspectableReactContext): unknown => {
|
|
69
111
|
if (currentFiber === null) return context._currentValue;
|
|
70
112
|
if (currentContextDependency === null) {
|
|
71
|
-
throw new
|
|
113
|
+
throw new BippyHookInspectionError("Context reads do not line up with context dependencies.");
|
|
72
114
|
}
|
|
73
|
-
if (Object.
|
|
74
|
-
const value = currentContextDependency.memoizedValue
|
|
115
|
+
if (Object.hasOwn(currentContextDependency, "memoizedValue")) {
|
|
116
|
+
const value = currentContextDependency.memoizedValue;
|
|
75
117
|
currentContextDependency = currentContextDependency.next;
|
|
76
118
|
return value;
|
|
77
119
|
}
|
|
78
120
|
return context._currentValue;
|
|
79
121
|
};
|
|
80
122
|
|
|
81
|
-
const getDispatcherRef = ():
|
|
123
|
+
const getDispatcherRef = (): RendererDispatcherRef | null => {
|
|
82
124
|
const rdtHook = getRDTHook();
|
|
83
125
|
const allRenderers = [..._renderers, ...rdtHook.renderers.values()];
|
|
84
126
|
for (const renderer of allRenderers) {
|
|
85
127
|
const ref = renderer.currentDispatcherRef;
|
|
86
|
-
if (ref
|
|
128
|
+
if (ref) return ref;
|
|
87
129
|
}
|
|
88
130
|
return null;
|
|
89
131
|
};
|
|
90
132
|
|
|
91
|
-
const getDispatcherFromRef = (ref:
|
|
133
|
+
const getDispatcherFromRef = (ref: RendererDispatcherRef): unknown =>
|
|
92
134
|
"H" in ref ? ref.H : ref.current;
|
|
93
135
|
|
|
94
|
-
const setDispatcherOnRef = (ref:
|
|
136
|
+
const setDispatcherOnRef = (ref: RendererDispatcherRef, dispatcher: unknown): void => {
|
|
95
137
|
if ("H" in ref) {
|
|
96
138
|
ref.H = dispatcher;
|
|
97
139
|
} else {
|
|
@@ -115,14 +157,13 @@ const pushHookLogEntry = (
|
|
|
115
157
|
};
|
|
116
158
|
|
|
117
159
|
const dispatcherUse = (usable: unknown): unknown => {
|
|
118
|
-
if (usable
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (typeof asThenable.then === "function") {
|
|
122
|
-
const thenable =
|
|
160
|
+
if (isObjectRecord(usable)) {
|
|
161
|
+
if (isInspectableThenable(usable)) {
|
|
162
|
+
const cachedThenable =
|
|
123
163
|
currentThenableState !== null && currentThenableIndex < currentThenableState.length
|
|
124
164
|
? currentThenableState[currentThenableIndex++]
|
|
125
|
-
:
|
|
165
|
+
: usable;
|
|
166
|
+
const thenable = isInspectableThenable(cachedThenable) ? cachedThenable : usable;
|
|
126
167
|
|
|
127
168
|
switch (thenable.status) {
|
|
128
169
|
case "fulfilled": {
|
|
@@ -135,19 +176,22 @@ const dispatcherUse = (usable: unknown): unknown => {
|
|
|
135
176
|
pushHookLogEntry("Unresolved", thenable, "Use");
|
|
136
177
|
throw SuspenseException;
|
|
137
178
|
}
|
|
138
|
-
if (
|
|
139
|
-
const context:
|
|
179
|
+
if (usable.$$typeof === REACT_CONTEXT_TYPE && "_currentValue" in usable) {
|
|
180
|
+
const context: InspectableReactContext = {
|
|
181
|
+
_currentValue: usable._currentValue,
|
|
182
|
+
displayName: typeof usable.displayName === "string" ? usable.displayName : undefined,
|
|
183
|
+
};
|
|
140
184
|
const value = readContext(context);
|
|
141
|
-
pushHookLogEntry("Context (use)", value, "Use", context.displayName
|
|
185
|
+
pushHookLogEntry("Context (use)", value, "Use", context.displayName ?? "Context");
|
|
142
186
|
return value;
|
|
143
187
|
}
|
|
144
188
|
}
|
|
145
|
-
throw new
|
|
189
|
+
throw new BippyHookInspectionError("An unsupported type was passed to use(): " + String(usable));
|
|
146
190
|
};
|
|
147
191
|
|
|
148
|
-
const dispatcherUseContext = (context:
|
|
192
|
+
const dispatcherUseContext = (context: InspectableReactContext): unknown => {
|
|
149
193
|
const value = readContext(context);
|
|
150
|
-
pushHookLogEntry("Context", value, "Context", context.displayName
|
|
194
|
+
pushHookLogEntry("Context", value, "Context", context.displayName ?? null);
|
|
151
195
|
return value;
|
|
152
196
|
};
|
|
153
197
|
|
|
@@ -157,7 +201,7 @@ const dispatcherUseState = (initialState: unknown): [unknown, () => void] => {
|
|
|
157
201
|
hook !== null
|
|
158
202
|
? hook.memoizedState
|
|
159
203
|
: typeof initialState === "function"
|
|
160
|
-
?
|
|
204
|
+
? initialState()
|
|
161
205
|
: initialState;
|
|
162
206
|
pushHookLogEntry("State", state, "State");
|
|
163
207
|
return [state, () => {}];
|
|
@@ -175,11 +219,13 @@ const dispatcherUseReducer = (
|
|
|
175
219
|
return [state, () => {}];
|
|
176
220
|
};
|
|
177
221
|
|
|
178
|
-
const dispatcherUseRef = (initialValue: unknown):
|
|
222
|
+
const dispatcherUseRef = (initialValue: unknown): InspectableRef => {
|
|
179
223
|
const hook = nextHook();
|
|
180
|
-
const ref = hook
|
|
181
|
-
|
|
182
|
-
|
|
224
|
+
const ref = isInspectableRef(hook?.memoizedState)
|
|
225
|
+
? hook.memoizedState
|
|
226
|
+
: { current: initialValue };
|
|
227
|
+
pushHookLogEntry("Ref", ref.current, "Ref");
|
|
228
|
+
return ref;
|
|
183
229
|
};
|
|
184
230
|
|
|
185
231
|
const dispatcherUseCacheRefresh = (): (() => void) => {
|
|
@@ -227,7 +273,7 @@ const dispatcherUseCallback = (callback: unknown): unknown => {
|
|
|
227
273
|
const hook = nextHook();
|
|
228
274
|
pushHookLogEntry(
|
|
229
275
|
"Callback",
|
|
230
|
-
hook
|
|
276
|
+
Array.isArray(hook?.memoizedState) ? hook.memoizedState[0] : callback,
|
|
231
277
|
"Callback",
|
|
232
278
|
);
|
|
233
279
|
return callback;
|
|
@@ -235,7 +281,7 @@ const dispatcherUseCallback = (callback: unknown): unknown => {
|
|
|
235
281
|
|
|
236
282
|
const dispatcherUseMemo = (nextCreate: () => unknown): unknown => {
|
|
237
283
|
const hook = nextHook();
|
|
238
|
-
const value = hook
|
|
284
|
+
const value = Array.isArray(hook?.memoizedState) ? hook.memoizedState[0] : nextCreate();
|
|
239
285
|
pushHookLogEntry("Memo", value, "Memo");
|
|
240
286
|
return value;
|
|
241
287
|
};
|
|
@@ -254,7 +300,7 @@ const dispatcherUseSyncExternalStore = (
|
|
|
254
300
|
const dispatcherUseTransition = (): [boolean, () => void] => {
|
|
255
301
|
const stateHook = nextHook();
|
|
256
302
|
nextHook();
|
|
257
|
-
const isPending = stateHook
|
|
303
|
+
const isPending = stateHook?.memoizedState === true;
|
|
258
304
|
pushHookLogEntry("Transition", isPending, "Transition");
|
|
259
305
|
return [isPending, () => {}];
|
|
260
306
|
};
|
|
@@ -268,7 +314,7 @@ const dispatcherUseDeferredValue = (value: unknown): unknown => {
|
|
|
268
314
|
|
|
269
315
|
const dispatcherUseId = (): string => {
|
|
270
316
|
const hook = nextHook();
|
|
271
|
-
const identifier = hook
|
|
317
|
+
const identifier = typeof hook?.memoizedState === "string" ? hook.memoizedState : "";
|
|
272
318
|
pushHookLogEntry("Id", identifier, "Id");
|
|
273
319
|
return identifier;
|
|
274
320
|
};
|
|
@@ -277,9 +323,7 @@ const dispatcherUseMemoCache = (size: number): unknown[] => {
|
|
|
277
323
|
const fiber = currentFiber;
|
|
278
324
|
if (fiber === null || fiber === undefined) return [];
|
|
279
325
|
|
|
280
|
-
const memoCache =
|
|
281
|
-
fiber.updateQueue as { memoCache?: { data: unknown[][]; index: number } } | null
|
|
282
|
-
)?.memoCache;
|
|
326
|
+
const memoCache = fiber.updateQueue?.memoCache;
|
|
283
327
|
if (memoCache === null || memoCache === undefined) return [];
|
|
284
328
|
|
|
285
329
|
let memoCacheSlots = memoCache.data[memoCache.index];
|
|
@@ -304,28 +348,22 @@ const dispatcherUseOptimistic = (passthrough: unknown): [unknown, () => void] =>
|
|
|
304
348
|
const inspectActionStateHook = (
|
|
305
349
|
hook: MemoizedState | null,
|
|
306
350
|
initialState: unknown,
|
|
307
|
-
):
|
|
351
|
+
): InspectedActionState => {
|
|
308
352
|
let value: unknown;
|
|
309
353
|
let error: unknown = null;
|
|
310
354
|
if (hook !== null) {
|
|
311
355
|
const actionResult = hook.memoizedState;
|
|
312
|
-
if (
|
|
313
|
-
|
|
314
|
-
actionResult !== null &&
|
|
315
|
-
"then" in actionResult &&
|
|
316
|
-
typeof actionResult.then === "function"
|
|
317
|
-
) {
|
|
318
|
-
const thenable = actionResult as { status?: string; value?: unknown; reason?: unknown };
|
|
319
|
-
switch (thenable.status) {
|
|
356
|
+
if (isInspectableThenable(actionResult)) {
|
|
357
|
+
switch (actionResult.status) {
|
|
320
358
|
case "fulfilled":
|
|
321
|
-
value =
|
|
359
|
+
value = actionResult.value;
|
|
322
360
|
break;
|
|
323
361
|
case "rejected":
|
|
324
|
-
error =
|
|
362
|
+
error = actionResult.reason;
|
|
325
363
|
break;
|
|
326
364
|
default:
|
|
327
365
|
error = SuspenseException;
|
|
328
|
-
value =
|
|
366
|
+
value = actionResult;
|
|
329
367
|
}
|
|
330
368
|
} else {
|
|
331
369
|
value = actionResult;
|
|
@@ -360,7 +398,7 @@ const dispatcherUseFormState = createActionStateDispatcher("FormState");
|
|
|
360
398
|
|
|
361
399
|
const dispatcherUseHostTransitionStatus = (): unknown => {
|
|
362
400
|
// HACK: creating a minimal fake context because useHostTransitionStatus reads from an internal context not available outside React
|
|
363
|
-
const status = readContext({ _currentValue: null }
|
|
401
|
+
const status = readContext({ _currentValue: null });
|
|
364
402
|
pushHookLogEntry("HostTransitionStatus", status, "HostTransitionStatus");
|
|
365
403
|
return status;
|
|
366
404
|
};
|
|
@@ -371,8 +409,7 @@ const dispatcherUseEffectEvent = (callback: (...args: unknown[]) => unknown): ty
|
|
|
371
409
|
return callback;
|
|
372
410
|
};
|
|
373
411
|
|
|
374
|
-
|
|
375
|
-
const Dispatcher: Record<string, (...args: any[]) => any> = {
|
|
412
|
+
const dispatcher = {
|
|
376
413
|
readContext,
|
|
377
414
|
use: dispatcherUse,
|
|
378
415
|
useCallback: dispatcherUseCallback,
|
|
@@ -399,15 +436,13 @@ const Dispatcher: Record<string, (...args: any[]) => any> = {
|
|
|
399
436
|
useEffectEvent: dispatcherUseEffectEvent,
|
|
400
437
|
};
|
|
401
438
|
|
|
402
|
-
const
|
|
439
|
+
const dispatcherProxy =
|
|
403
440
|
typeof Proxy === "undefined"
|
|
404
|
-
?
|
|
405
|
-
: new Proxy(
|
|
406
|
-
get(target,
|
|
407
|
-
if (Object.
|
|
408
|
-
|
|
409
|
-
error.name = "ReactDebugToolsUnsupportedHookError";
|
|
410
|
-
throw error;
|
|
441
|
+
? dispatcher
|
|
442
|
+
: new Proxy(dispatcher, {
|
|
443
|
+
get(target, propertyName: string) {
|
|
444
|
+
if (Object.hasOwn(target, propertyName)) return Reflect.get(target, propertyName);
|
|
445
|
+
throw new BippyUnsupportedHookError("Missing method in Dispatcher: " + propertyName);
|
|
411
446
|
},
|
|
412
447
|
});
|
|
413
448
|
|
|
@@ -418,41 +453,42 @@ const getPrimitiveStackCache = (): Map<string, StackFrame[]> => {
|
|
|
418
453
|
let capturedHookLog: HookLogEntry[];
|
|
419
454
|
|
|
420
455
|
try {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if (typeof
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
456
|
+
dispatcher.useContext({ _currentValue: null });
|
|
457
|
+
dispatcher.useState(null);
|
|
458
|
+
dispatcher.useReducer((state: unknown) => state, null);
|
|
459
|
+
dispatcher.useRef(null);
|
|
460
|
+
if (typeof dispatcher.useCacheRefresh === "function") dispatcher.useCacheRefresh();
|
|
461
|
+
dispatcher.useLayoutEffect(() => {});
|
|
462
|
+
dispatcher.useInsertionEffect(() => {});
|
|
463
|
+
dispatcher.useEffect(() => {});
|
|
464
|
+
dispatcher.useImperativeHandle(undefined, () => null);
|
|
465
|
+
dispatcher.useDebugValue(null);
|
|
466
|
+
dispatcher.useCallback(() => {});
|
|
467
|
+
dispatcher.useTransition();
|
|
468
|
+
dispatcher.useSyncExternalStore(
|
|
434
469
|
() => () => {},
|
|
435
470
|
() => null,
|
|
436
471
|
() => null,
|
|
437
472
|
);
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
if (typeof
|
|
445
|
-
if (typeof
|
|
446
|
-
|
|
447
|
-
|
|
473
|
+
dispatcher.useDeferredValue(null);
|
|
474
|
+
dispatcher.useMemo(() => null);
|
|
475
|
+
dispatcher.useOptimistic(null, (state: unknown) => state);
|
|
476
|
+
dispatcher.useFormState((state: unknown) => state, null);
|
|
477
|
+
dispatcher.useActionState((state: unknown) => state, null);
|
|
478
|
+
dispatcher.useHostTransitionStatus();
|
|
479
|
+
if (typeof dispatcher.useMemoCache === "function") dispatcher.useMemoCache(0);
|
|
480
|
+
if (typeof dispatcher.use === "function") {
|
|
481
|
+
dispatcher.use({ $$typeof: REACT_CONTEXT_TYPE, _currentValue: null });
|
|
482
|
+
const fulfilledPromise = Promise.resolve(null);
|
|
483
|
+
Reflect.set(fulfilledPromise, "status", "fulfilled");
|
|
484
|
+
Reflect.set(fulfilledPromise, "value", null);
|
|
485
|
+
dispatcher.use(fulfilledPromise);
|
|
448
486
|
try {
|
|
449
|
-
|
|
450
|
-
} catch {
|
|
451
|
-
/* noop */
|
|
452
|
-
}
|
|
487
|
+
dispatcher.use(new Promise<never>(() => {}));
|
|
488
|
+
} catch {}
|
|
453
489
|
}
|
|
454
|
-
|
|
455
|
-
if (typeof
|
|
490
|
+
dispatcher.useId();
|
|
491
|
+
if (typeof dispatcher.useEffectEvent === "function") dispatcher.useEffectEvent(() => {});
|
|
456
492
|
} finally {
|
|
457
493
|
capturedHookLog = hookLog;
|
|
458
494
|
hookLog = [];
|
|
@@ -681,14 +717,17 @@ const processDebugValues = (hooksTree: HooksTree, parentHooksNode: HooksNode | n
|
|
|
681
717
|
const setupContexts = (contextMap: Map<ReactContext<unknown>, unknown>, fiber: Fiber): void => {
|
|
682
718
|
let current: Fiber | null = fiber;
|
|
683
719
|
while (current) {
|
|
684
|
-
if (current.tag ===
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
720
|
+
if (current.tag === getReactWorkTagsForFiber(current).ContextProvider) {
|
|
721
|
+
const providerType = current.type;
|
|
722
|
+
const nestedContext = isObjectRecord(providerType) ? providerType._context : undefined;
|
|
723
|
+
const context = isReactContext(nestedContext)
|
|
724
|
+
? nestedContext
|
|
725
|
+
: isReactContext(providerType)
|
|
726
|
+
? providerType
|
|
727
|
+
: null;
|
|
728
|
+
if (context && !contextMap.has(context)) {
|
|
690
729
|
contextMap.set(context, context._currentValue);
|
|
691
|
-
context._currentValue =
|
|
730
|
+
context._currentValue = current.memoizedProps.value;
|
|
692
731
|
}
|
|
693
732
|
}
|
|
694
733
|
current = current.return;
|
|
@@ -703,25 +742,22 @@ const restoreContexts = (contextMap: Map<ReactContext<unknown>, unknown>): void
|
|
|
703
742
|
|
|
704
743
|
const handleRenderFunctionError = (error: unknown): void => {
|
|
705
744
|
if (error === SuspenseException) return;
|
|
706
|
-
if (error instanceof
|
|
707
|
-
|
|
708
|
-
wrapperError.name = "ReactDebugToolsRenderError";
|
|
709
|
-
(wrapperError as { cause: unknown }).cause = error;
|
|
710
|
-
throw wrapperError;
|
|
745
|
+
if (error instanceof BippyUnsupportedHookError) throw error;
|
|
746
|
+
throw new BippyHookRenderError("Error rendering inspected component", error);
|
|
711
747
|
};
|
|
712
748
|
|
|
713
749
|
const resolveDefaultProps = (
|
|
714
|
-
|
|
750
|
+
component: unknown,
|
|
715
751
|
baseProps: Record<string, unknown>,
|
|
716
752
|
): Record<string, unknown> => {
|
|
717
753
|
if (
|
|
718
|
-
|
|
719
|
-
typeof
|
|
720
|
-
"defaultProps" in
|
|
721
|
-
|
|
754
|
+
component &&
|
|
755
|
+
typeof component === "object" &&
|
|
756
|
+
"defaultProps" in component &&
|
|
757
|
+
isObjectRecord(component.defaultProps)
|
|
722
758
|
) {
|
|
723
759
|
const props = { ...baseProps };
|
|
724
|
-
const defaultProps =
|
|
760
|
+
const defaultProps = component.defaultProps;
|
|
725
761
|
for (const propName in defaultProps) {
|
|
726
762
|
if (props[propName] === undefined) {
|
|
727
763
|
props[propName] = defaultProps[propName];
|
|
@@ -736,11 +772,9 @@ const suppressConsole = (): Record<string, unknown> => {
|
|
|
736
772
|
const originalMethods: Record<string, unknown> = {};
|
|
737
773
|
for (const method in console) {
|
|
738
774
|
try {
|
|
739
|
-
originalMethods[method] = (console
|
|
740
|
-
(console
|
|
741
|
-
} catch {
|
|
742
|
-
/* noop */
|
|
743
|
-
}
|
|
775
|
+
originalMethods[method] = Reflect.get(console, method);
|
|
776
|
+
Reflect.set(console, method, () => {});
|
|
777
|
+
} catch {}
|
|
744
778
|
}
|
|
745
779
|
return originalMethods;
|
|
746
780
|
};
|
|
@@ -748,19 +782,17 @@ const suppressConsole = (): Record<string, unknown> => {
|
|
|
748
782
|
const restoreConsole = (originalMethods: Record<string, unknown>): void => {
|
|
749
783
|
for (const method in originalMethods) {
|
|
750
784
|
try {
|
|
751
|
-
(console
|
|
752
|
-
} catch {
|
|
753
|
-
/* noop */
|
|
754
|
-
}
|
|
785
|
+
Reflect.set(console, method, originalMethods[method]);
|
|
786
|
+
} catch {}
|
|
755
787
|
}
|
|
756
788
|
};
|
|
757
789
|
|
|
758
790
|
const performDispatcherInspection = (
|
|
759
|
-
dispatcherRef:
|
|
791
|
+
dispatcherRef: RendererDispatcherRef,
|
|
760
792
|
renderFn: () => void,
|
|
761
793
|
): HooksTree => {
|
|
762
794
|
const previousDispatcher = getDispatcherFromRef(dispatcherRef);
|
|
763
|
-
setDispatcherOnRef(dispatcherRef,
|
|
795
|
+
setDispatcherOnRef(dispatcherRef, dispatcherProxy);
|
|
764
796
|
|
|
765
797
|
let capturedHookLog: HookLogEntry[] = [];
|
|
766
798
|
let ancestorStackError: Error | undefined;
|
|
@@ -780,10 +812,10 @@ const performDispatcherInspection = (
|
|
|
780
812
|
return buildTree(rootStack, capturedHookLog);
|
|
781
813
|
};
|
|
782
814
|
|
|
783
|
-
const requireDispatcherRef = ():
|
|
815
|
+
const requireDispatcherRef = (): RendererDispatcherRef => {
|
|
784
816
|
const dispatcherRef = getDispatcherRef();
|
|
785
817
|
if (!dispatcherRef) {
|
|
786
|
-
throw new
|
|
818
|
+
throw new BippyHookInspectionError(
|
|
787
819
|
"No React renderer found. Make sure React is loaded and bippy's hook is installed.",
|
|
788
820
|
);
|
|
789
821
|
}
|
|
@@ -791,38 +823,38 @@ const requireDispatcherRef = (): DispatcherRefContainer => {
|
|
|
791
823
|
};
|
|
792
824
|
|
|
793
825
|
const resolveContextDependency = (fiber: Fiber): void => {
|
|
794
|
-
if (Object.
|
|
826
|
+
if (Object.hasOwn(fiber, "dependencies")) {
|
|
795
827
|
const dependencies = fiber.dependencies;
|
|
796
828
|
currentContextDependency = dependencies !== null ? dependencies.firstContext : null;
|
|
797
|
-
} else if (Object.
|
|
798
|
-
const dependencies = (fiber
|
|
799
|
-
|
|
800
|
-
currentContextDependency =
|
|
801
|
-
} else if (Object.
|
|
802
|
-
const dependencies = (fiber
|
|
803
|
-
|
|
804
|
-
currentContextDependency =
|
|
805
|
-
} else if (Object.
|
|
806
|
-
const contextDependencies = (
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
}
|
|
810
|
-
).contextDependencies;
|
|
811
|
-
currentContextDependency = contextDependencies !== null ? contextDependencies.first : null;
|
|
829
|
+
} else if (Object.hasOwn(fiber, "dependencies_old")) {
|
|
830
|
+
const dependencies: unknown = Reflect.get(fiber, "dependencies_old");
|
|
831
|
+
const firstContext = isObjectRecord(dependencies) ? dependencies.firstContext : null;
|
|
832
|
+
currentContextDependency = isContextDependency(firstContext) ? firstContext : null;
|
|
833
|
+
} else if (Object.hasOwn(fiber, "dependencies_new")) {
|
|
834
|
+
const dependencies: unknown = Reflect.get(fiber, "dependencies_new");
|
|
835
|
+
const firstContext = isObjectRecord(dependencies) ? dependencies.firstContext : null;
|
|
836
|
+
currentContextDependency = isContextDependency(firstContext) ? firstContext : null;
|
|
837
|
+
} else if (Object.hasOwn(fiber, "contextDependencies")) {
|
|
838
|
+
const contextDependencies: unknown = Reflect.get(fiber, "contextDependencies");
|
|
839
|
+
const firstContext = isObjectRecord(contextDependencies) ? contextDependencies.first : null;
|
|
840
|
+
currentContextDependency = isContextDependency(firstContext) ? firstContext : null;
|
|
812
841
|
} else {
|
|
813
|
-
throw new
|
|
842
|
+
throw new BippyHookInspectionError("Unsupported React version.");
|
|
814
843
|
}
|
|
815
844
|
};
|
|
816
845
|
|
|
817
846
|
export const getFiberHooks = (fiber: Fiber): HooksTree => {
|
|
818
847
|
const dispatcherRef = requireDispatcherRef();
|
|
848
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
819
849
|
|
|
820
850
|
if (
|
|
821
|
-
fiber.tag !==
|
|
822
|
-
fiber.tag !==
|
|
823
|
-
fiber.tag !==
|
|
851
|
+
fiber.tag !== workTags.FunctionComponent &&
|
|
852
|
+
fiber.tag !== workTags.SimpleMemoComponent &&
|
|
853
|
+
fiber.tag !== workTags.ForwardRef
|
|
824
854
|
) {
|
|
825
|
-
throw new
|
|
855
|
+
throw new BippyHookInspectionError(
|
|
856
|
+
"Unknown Fiber. Needs to be a function component to inspect hooks.",
|
|
857
|
+
);
|
|
826
858
|
}
|
|
827
859
|
|
|
828
860
|
getPrimitiveStackCache();
|
|
@@ -830,19 +862,17 @@ export const getFiberHooks = (fiber: Fiber): HooksTree => {
|
|
|
830
862
|
currentHook = fiber.memoizedState;
|
|
831
863
|
currentFiber = fiber;
|
|
832
864
|
|
|
833
|
-
const debugThenableState =
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
? debugThenableState.thenables || debugThenableState
|
|
838
|
-
: null;
|
|
865
|
+
const debugThenableState = fiber.dependencies?._debugThenableState;
|
|
866
|
+
const usedThenables = Array.isArray(debugThenableState)
|
|
867
|
+
? debugThenableState
|
|
868
|
+
: debugThenableState?.thenables;
|
|
839
869
|
currentThenableState = Array.isArray(usedThenables) ? usedThenables : null;
|
|
840
870
|
currentThenableIndex = 0;
|
|
841
871
|
|
|
842
872
|
resolveContextDependency(fiber);
|
|
843
873
|
|
|
844
874
|
const type = fiber.type;
|
|
845
|
-
let props = fiber.memoizedProps
|
|
875
|
+
let props = fiber.memoizedProps;
|
|
846
876
|
if (type !== fiber.elementType) {
|
|
847
877
|
props = resolveDefaultProps(type, props);
|
|
848
878
|
}
|
|
@@ -853,22 +883,27 @@ export const getFiberHooks = (fiber: Fiber): HooksTree => {
|
|
|
853
883
|
try {
|
|
854
884
|
if (
|
|
855
885
|
currentContextDependency !== null &&
|
|
856
|
-
!Object.
|
|
886
|
+
!Object.hasOwn(currentContextDependency, "memoizedValue")
|
|
857
887
|
) {
|
|
858
888
|
setupContexts(contextMap, fiber);
|
|
859
889
|
}
|
|
860
890
|
|
|
861
|
-
if (fiber.tag ===
|
|
891
|
+
if (fiber.tag === workTags.ForwardRef) {
|
|
892
|
+
if (!isForwardRefRenderType(type)) {
|
|
893
|
+
throw new BippyHookInspectionError("ForwardRef fiber is missing its render function.");
|
|
894
|
+
}
|
|
862
895
|
return performDispatcherInspection(dispatcherRef, () => {
|
|
863
|
-
|
|
864
|
-
props,
|
|
865
|
-
fiber.ref,
|
|
866
|
-
);
|
|
896
|
+
type.render(props, fiber.ref);
|
|
867
897
|
});
|
|
868
898
|
}
|
|
869
899
|
|
|
900
|
+
if (typeof type !== "function") {
|
|
901
|
+
throw new BippyHookInspectionError(
|
|
902
|
+
"Function component fiber is missing its component function.",
|
|
903
|
+
);
|
|
904
|
+
}
|
|
870
905
|
return performDispatcherInspection(dispatcherRef, () => {
|
|
871
|
-
|
|
906
|
+
type(props);
|
|
872
907
|
});
|
|
873
908
|
} finally {
|
|
874
909
|
currentFiber = null;
|