bippy 0.6.1-dev.3a24abf → 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 +7 -1
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +22 -24
- package/dist/core.d.ts +22 -24
- 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/{types.d.cts → errors.d.cts} +174 -29
- package/dist/{types.d.ts → errors.d.ts} +174 -29
- 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.iife.js +1 -1
- package/dist/rdt-hook.cjs +1 -1
- package/dist/rdt-hook.js +1 -1
- package/dist/source.cjs +13 -13
- package/dist/source.d.cts +18 -9
- package/dist/source.d.ts +18 -9
- package/dist/source.js +13 -13
- package/package.json +9 -5
- package/src/core.ts +195 -156
- 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 +144 -96
- package/src/react-internals.ts +43 -45
- package/src/semver.ts +78 -0
- package/src/source/error-stack.ts +11 -0
- package/src/source/index.ts +9 -1
- package/src/source/inspect-hooks.ts +199 -164
- package/src/source/owner-stack.ts +21 -38
- package/src/source/parse-debug-stack.ts +4 -4
- package/src/source/symbolication.ts +358 -103
- package/src/types.ts +12 -2
- package/src/generated/react-work-tags.ts +0 -169
package/src/core.ts
CHANGED
|
@@ -12,76 +12,41 @@ import type {
|
|
|
12
12
|
ReactRenderer,
|
|
13
13
|
} from "./types.js";
|
|
14
14
|
|
|
15
|
+
import { BippyInstrumentationError, BippyReactDevToolsError, runWithBippyError } from "./errors.js";
|
|
16
|
+
|
|
15
17
|
import {
|
|
16
18
|
_onActiveListeners,
|
|
17
19
|
BIPPY_INSTRUMENTATION_STRING,
|
|
18
20
|
getRDTHook,
|
|
19
21
|
hasRDTHook,
|
|
20
22
|
isRealReactDevtools,
|
|
23
|
+
onRDTHookReplace,
|
|
21
24
|
onRendererInject,
|
|
22
25
|
} from "./rdt-hook.js";
|
|
23
26
|
import {
|
|
24
|
-
|
|
25
|
-
CONCURRENT_MODE_NUMBER,
|
|
26
|
-
CONCURRENT_MODE_SYMBOL_DESCRIPTION,
|
|
27
|
-
CONCURRENT_MODE_SYMBOL_STRING,
|
|
28
|
-
ContextConsumerTag,
|
|
29
|
-
DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION,
|
|
30
|
-
DEPRECATED_ASYNC_MODE_SYMBOL_STRING,
|
|
31
|
-
DehydratedSuspenseComponentTag,
|
|
32
|
-
ELEMENT_TYPE_SYMBOL_STRING,
|
|
33
|
-
ForwardRefTag,
|
|
34
|
-
FragmentTag,
|
|
35
|
-
FunctionComponentTag,
|
|
36
|
-
HostComponentTag,
|
|
37
|
-
HostHoistableTag,
|
|
38
|
-
HostRootTag,
|
|
39
|
-
HostSingletonTag,
|
|
40
|
-
HostTextTag,
|
|
41
|
-
LegacyHiddenComponentTag,
|
|
42
|
-
MemoComponentTag,
|
|
27
|
+
getReactWorkTagsForFiber,
|
|
43
28
|
MutationMask,
|
|
44
|
-
OffscreenComponentTag,
|
|
45
29
|
ReactBuildType,
|
|
46
30
|
ReactFiberFlags,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
TRANSITIONAL_ELEMENT_TYPE_SYMBOL_STRING,
|
|
31
|
+
ReactSymbols,
|
|
32
|
+
setReactWorkTagsForFiber,
|
|
50
33
|
} from "./react-internals.js";
|
|
51
34
|
import { toUnsubscribe, type Unsubscribe } from "./unsubscribe.js";
|
|
52
35
|
|
|
36
|
+
export { getReactWorkTags, ReactSymbols } from "./react-internals.js";
|
|
37
|
+
export type { ReactWorkTagMap, ReactWorkTagVersion } from "./react-internals.js";
|
|
53
38
|
export {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
FragmentTag,
|
|
66
|
-
FunctionComponentTag,
|
|
67
|
-
HostComponentTag,
|
|
68
|
-
HostHoistableTag,
|
|
69
|
-
HostPortalTag,
|
|
70
|
-
HostRootTag,
|
|
71
|
-
HostSingletonTag,
|
|
72
|
-
HostTextTag,
|
|
73
|
-
LazyComponentTag,
|
|
74
|
-
LegacyHiddenComponentTag,
|
|
75
|
-
MemoComponentTag,
|
|
76
|
-
OffscreenComponentTag,
|
|
77
|
-
SimpleMemoComponentTag,
|
|
78
|
-
SuspenseComponentTag,
|
|
79
|
-
SuspenseListComponentTag,
|
|
80
|
-
TRANSITIONAL_ELEMENT_TYPE_SYMBOL_STRING,
|
|
81
|
-
ViewTransitionComponentTag,
|
|
82
|
-
} from "./react-internals.js";
|
|
83
|
-
|
|
84
|
-
const { Cloned, PerformedWork } = ReactFiberFlags;
|
|
39
|
+
BippyError,
|
|
40
|
+
BippyHookInstallationError,
|
|
41
|
+
BippyHookInspectionError,
|
|
42
|
+
BippyHookListenerError,
|
|
43
|
+
BippyHookRenderError,
|
|
44
|
+
BippyInstrumentationError,
|
|
45
|
+
BippyReactBuildError,
|
|
46
|
+
BippyReactDevToolsError,
|
|
47
|
+
BippySourceMapError,
|
|
48
|
+
BippyUnsupportedHookError,
|
|
49
|
+
} from "./errors.js";
|
|
85
50
|
|
|
86
51
|
const isObjectRecord = (value: unknown): value is Record<string, unknown> =>
|
|
87
52
|
typeof value === "object" && value !== null;
|
|
@@ -113,6 +78,20 @@ interface FiberSelector {
|
|
|
113
78
|
(node: Fiber): boolean | Promise<boolean | void> | void;
|
|
114
79
|
}
|
|
115
80
|
|
|
81
|
+
export interface FiberTimings {
|
|
82
|
+
selfTime: number;
|
|
83
|
+
totalTime: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface RenderHandler {
|
|
87
|
+
<State>(fiber: Fiber, phase: RenderPhase, state?: State): unknown;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface ValueWrite {
|
|
91
|
+
path: string[];
|
|
92
|
+
value: unknown;
|
|
93
|
+
}
|
|
94
|
+
|
|
116
95
|
/**
|
|
117
96
|
* Returns `true` if object is a React Element.
|
|
118
97
|
*
|
|
@@ -122,7 +101,7 @@ export const isValidElement = (element: unknown): element is React.ReactElement
|
|
|
122
101
|
typeof element === "object" &&
|
|
123
102
|
element !== null &&
|
|
124
103
|
"$$typeof" in element &&
|
|
125
|
-
[
|
|
104
|
+
[ReactSymbols.LEGACY_ELEMENT_SYMBOL_STRING, ReactSymbols.ELEMENT_SYMBOL_STRING].includes(
|
|
126
105
|
String(element.$$typeof),
|
|
127
106
|
);
|
|
128
107
|
|
|
@@ -145,11 +124,12 @@ export const isValidFiber = (fiber: unknown): fiber is Fiber =>
|
|
|
145
124
|
* @see https://reactnative.dev/architecture/glossary#host-view-tree-and-host-view
|
|
146
125
|
*/
|
|
147
126
|
export const isHostFiber = (fiber: Fiber): fiber is HostFiber => {
|
|
127
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
148
128
|
switch (fiber.tag) {
|
|
149
|
-
case
|
|
150
|
-
case
|
|
151
|
-
case
|
|
152
|
-
case
|
|
129
|
+
case workTags.HostComponent:
|
|
130
|
+
case workTags.HostText:
|
|
131
|
+
case workTags.HostHoistable:
|
|
132
|
+
case workTags.HostSingleton:
|
|
153
133
|
return true;
|
|
154
134
|
default:
|
|
155
135
|
return false;
|
|
@@ -162,12 +142,13 @@ export const isHostFiber = (fiber: Fiber): fiber is HostFiber => {
|
|
|
162
142
|
* @see https://reactnative.dev/architecture/glossary#react-composite-components
|
|
163
143
|
*/
|
|
164
144
|
export const isCompositeFiber = (fiber: Fiber): boolean => {
|
|
145
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
165
146
|
switch (fiber.tag) {
|
|
166
|
-
case
|
|
167
|
-
case
|
|
168
|
-
case
|
|
169
|
-
case
|
|
170
|
-
case
|
|
147
|
+
case workTags.ClassComponent:
|
|
148
|
+
case workTags.ForwardRef:
|
|
149
|
+
case workTags.FunctionComponent:
|
|
150
|
+
case workTags.MemoComponent:
|
|
151
|
+
case workTags.SimpleMemoComponent:
|
|
171
152
|
return true;
|
|
172
153
|
default:
|
|
173
154
|
return false;
|
|
@@ -275,15 +256,16 @@ export const didFiberRender = (fiber: Fiber): boolean => {
|
|
|
275
256
|
const nextProps = fiber.memoizedProps;
|
|
276
257
|
const prevProps = fiber.alternate?.memoizedProps || {};
|
|
277
258
|
const flags = fiber.flags ?? fiber.effectTag ?? 0;
|
|
259
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
278
260
|
|
|
279
261
|
switch (fiber.tag) {
|
|
280
|
-
case
|
|
281
|
-
case
|
|
282
|
-
case
|
|
283
|
-
case
|
|
284
|
-
case
|
|
285
|
-
case
|
|
286
|
-
return (flags & PerformedWork) === PerformedWork;
|
|
262
|
+
case workTags.ClassComponent:
|
|
263
|
+
case workTags.ContextConsumer:
|
|
264
|
+
case workTags.ForwardRef:
|
|
265
|
+
case workTags.FunctionComponent:
|
|
266
|
+
case workTags.MemoComponent:
|
|
267
|
+
case workTags.SimpleMemoComponent: {
|
|
268
|
+
return (flags & ReactFiberFlags.PerformedWork) === ReactFiberFlags.PerformedWork;
|
|
287
269
|
}
|
|
288
270
|
default:
|
|
289
271
|
// Host nodes (DOM, root, etc.)
|
|
@@ -301,8 +283,8 @@ export const didFiberRender = (fiber: Fiber): boolean => {
|
|
|
301
283
|
*/
|
|
302
284
|
export const didFiberCommit = (fiber: Fiber): boolean => {
|
|
303
285
|
return Boolean(
|
|
304
|
-
(fiber.flags & (MutationMask | Cloned)) !== 0 ||
|
|
305
|
-
(fiber.subtreeFlags & (MutationMask | Cloned)) !== 0,
|
|
286
|
+
(fiber.flags & (MutationMask | ReactFiberFlags.Cloned)) !== 0 ||
|
|
287
|
+
(fiber.subtreeFlags & (MutationMask | ReactFiberFlags.Cloned)) !== 0,
|
|
306
288
|
);
|
|
307
289
|
};
|
|
308
290
|
|
|
@@ -351,8 +333,9 @@ export const getFiberStack = (fiber: Fiber): Fiber[] => {
|
|
|
351
333
|
* Returns `true` if the {@link Fiber} should be filtered out during reconciliation.
|
|
352
334
|
*/
|
|
353
335
|
const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
336
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
354
337
|
switch (fiber.tag) {
|
|
355
|
-
case
|
|
338
|
+
case workTags.DehydratedSuspenseComponent:
|
|
356
339
|
// TODO: ideally we would show dehydrated Suspense immediately.
|
|
357
340
|
// However, it has some special behavior (like disconnecting
|
|
358
341
|
// an alternate and turning into real Suspense) which breaks DevTools.
|
|
@@ -360,13 +343,13 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
360
343
|
// https://github.com/bvaughn/react-devtools-experimental/issues/197
|
|
361
344
|
return true;
|
|
362
345
|
|
|
363
|
-
case
|
|
364
|
-
case
|
|
365
|
-
case
|
|
366
|
-
case
|
|
346
|
+
case workTags.Fragment:
|
|
347
|
+
case workTags.HostText:
|
|
348
|
+
case workTags.LegacyHiddenComponent:
|
|
349
|
+
case workTags.OffscreenComponent:
|
|
367
350
|
return true;
|
|
368
351
|
|
|
369
|
-
case
|
|
352
|
+
case workTags.HostRoot:
|
|
370
353
|
// It is never valid to filter the root element.
|
|
371
354
|
return false;
|
|
372
355
|
|
|
@@ -376,15 +359,15 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
376
359
|
|
|
377
360
|
if (typeof symbolOrNumber === "symbol") {
|
|
378
361
|
return (
|
|
379
|
-
symbolOrNumber.description === CONCURRENT_MODE_SYMBOL_DESCRIPTION ||
|
|
380
|
-
symbolOrNumber.description === DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION
|
|
362
|
+
symbolOrNumber.description === ReactSymbols.CONCURRENT_MODE_SYMBOL_DESCRIPTION ||
|
|
363
|
+
symbolOrNumber.description === ReactSymbols.DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION
|
|
381
364
|
);
|
|
382
365
|
}
|
|
383
366
|
|
|
384
367
|
switch (symbolOrNumber) {
|
|
385
|
-
case CONCURRENT_MODE_NUMBER:
|
|
386
|
-
case CONCURRENT_MODE_SYMBOL_STRING:
|
|
387
|
-
case DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
|
|
368
|
+
case ReactSymbols.CONCURRENT_MODE_NUMBER:
|
|
369
|
+
case ReactSymbols.CONCURRENT_MODE_SYMBOL_STRING:
|
|
370
|
+
case ReactSymbols.DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
|
|
388
371
|
return true;
|
|
389
372
|
|
|
390
373
|
default:
|
|
@@ -528,7 +511,7 @@ const traverseFiberAsync = async (
|
|
|
528
511
|
* console.log(selfTime, totalTime);
|
|
529
512
|
* ```
|
|
530
513
|
*/
|
|
531
|
-
export const getTimings = (fiber?: Fiber | null):
|
|
514
|
+
export const getTimings = (fiber?: Fiber | null): FiberTimings => {
|
|
532
515
|
const totalTime = fiber?.actualDuration ?? 0;
|
|
533
516
|
let selfTime = totalTime;
|
|
534
517
|
// TODO: calculate a DOM time, which is just host component summed up
|
|
@@ -612,28 +595,25 @@ export const getLatestFiber = (fiber: Fiber): Fiber => {
|
|
|
612
595
|
return fiber;
|
|
613
596
|
};
|
|
614
597
|
|
|
615
|
-
export type RenderHandler = <S>(fiber: Fiber, phase: RenderPhase, state?: S) => unknown;
|
|
616
|
-
|
|
617
598
|
export type RenderPhase = "mount" | "unmount" | "update";
|
|
618
599
|
|
|
619
|
-
let
|
|
600
|
+
let nextFiberId = 0;
|
|
620
601
|
const fiberIdMap = new WeakMap<Fiber, number>();
|
|
621
602
|
|
|
622
|
-
export const setFiberId = (fiber: Fiber,
|
|
623
|
-
fiberIdMap.set(fiber,
|
|
603
|
+
export const setFiberId = (fiber: Fiber, fiberId: number = nextFiberId++): void => {
|
|
604
|
+
fiberIdMap.set(fiber, fiberId);
|
|
624
605
|
};
|
|
625
606
|
|
|
626
|
-
// Fiber alternates share an identity across double-buffered commits.
|
|
627
607
|
export const getFiberId = (fiber: Fiber): number => {
|
|
628
|
-
let
|
|
629
|
-
if (
|
|
630
|
-
|
|
608
|
+
let currentFiberId = fiberIdMap.get(fiber);
|
|
609
|
+
if (currentFiberId === undefined && fiber.alternate) {
|
|
610
|
+
currentFiberId = fiberIdMap.get(fiber.alternate);
|
|
631
611
|
}
|
|
632
|
-
if (
|
|
633
|
-
|
|
634
|
-
setFiberId(fiber,
|
|
612
|
+
if (currentFiberId === undefined) {
|
|
613
|
+
currentFiberId = nextFiberId++;
|
|
614
|
+
setFiberId(fiber, currentFiberId);
|
|
635
615
|
}
|
|
636
|
-
return
|
|
616
|
+
return currentFiberId;
|
|
637
617
|
};
|
|
638
618
|
|
|
639
619
|
const mountFiberRecursively = (
|
|
@@ -652,7 +632,7 @@ const mountFiberRecursively = (
|
|
|
652
632
|
onRender(fiber, "mount");
|
|
653
633
|
}
|
|
654
634
|
|
|
655
|
-
if (fiber.tag ===
|
|
635
|
+
if (fiber.tag === getReactWorkTagsForFiber(fiber).SuspenseComponent) {
|
|
656
636
|
const isTimedOut = fiber.memoizedState !== null;
|
|
657
637
|
if (isTimedOut) {
|
|
658
638
|
// Special case: if Suspense mounts in a timed-out state,
|
|
@@ -693,7 +673,7 @@ const updateFiberRecursively = (
|
|
|
693
673
|
getFiberId(prevFiber);
|
|
694
674
|
}
|
|
695
675
|
|
|
696
|
-
const isSuspense = nextFiber.tag ===
|
|
676
|
+
const isSuspense = nextFiber.tag === getReactWorkTagsForFiber(nextFiber).SuspenseComponent;
|
|
697
677
|
|
|
698
678
|
const shouldIncludeInTree = !shouldFilterFiber(nextFiber);
|
|
699
679
|
if (shouldIncludeInTree && didFiberRender(nextFiber)) {
|
|
@@ -780,7 +760,7 @@ const updateFiberRecursively = (
|
|
|
780
760
|
};
|
|
781
761
|
|
|
782
762
|
const unmountFiber = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
783
|
-
const isRoot = fiber.tag ===
|
|
763
|
+
const isRoot = fiber.tag === getReactWorkTagsForFiber(fiber).HostRoot;
|
|
784
764
|
|
|
785
765
|
if (isRoot || !shouldFilterFiber(fiber)) {
|
|
786
766
|
onRender(fiber, "unmount");
|
|
@@ -789,7 +769,8 @@ const unmountFiber = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
|
789
769
|
|
|
790
770
|
const unmountFiberChildrenRecursively = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
791
771
|
// We might meet a nested Suspense on our way.
|
|
792
|
-
const isTimedOutSuspense =
|
|
772
|
+
const isTimedOutSuspense =
|
|
773
|
+
fiber.tag === getReactWorkTagsForFiber(fiber).SuspenseComponent && fiber.memoizedState !== null;
|
|
793
774
|
let child = fiber.child;
|
|
794
775
|
|
|
795
776
|
if (isTimedOutSuspense) {
|
|
@@ -878,9 +859,8 @@ let areOverrideRenderersWired = false;
|
|
|
878
859
|
const wireOverrideRenderers = (): void => {
|
|
879
860
|
if (!hasRDTHook()) return;
|
|
880
861
|
const rdtHook = getRDTHook();
|
|
881
|
-
if (!rdtHook?.renderers) return;
|
|
882
862
|
|
|
883
|
-
|
|
863
|
+
setHookEventDispatchers(rdtHook);
|
|
884
864
|
for (const renderer of rdtHook.renderers.values()) {
|
|
885
865
|
overrideRenderers.add(renderer);
|
|
886
866
|
}
|
|
@@ -899,12 +879,9 @@ const getRootRenderer = (fiber: Fiber): ReactRenderer | null => {
|
|
|
899
879
|
}
|
|
900
880
|
const rendererId = rootRendererIds.get(hostRootFiber.stateNode);
|
|
901
881
|
if (rendererId === undefined) return null;
|
|
902
|
-
return getRDTHook().renderers
|
|
882
|
+
return getRDTHook().renderers.get(rendererId) ?? null;
|
|
903
883
|
};
|
|
904
884
|
|
|
905
|
-
// dispatch to the renderer that owns the fiber's root when known; renderers
|
|
906
|
-
// that never committed through bippy's hook patch fall back to "try all",
|
|
907
|
-
// which matches the pre-ownership behavior for single-renderer apps
|
|
908
885
|
const resolveOverrideRenderers = (fiber: Fiber): ReactRenderer[] => {
|
|
909
886
|
wireOverrideRenderers();
|
|
910
887
|
const rootRenderer = getRootRenderer(fiber);
|
|
@@ -930,7 +907,7 @@ const getHookStateDispatch = (
|
|
|
930
907
|
hookIndex: number,
|
|
931
908
|
): ((value: unknown) => void) | null => {
|
|
932
909
|
let hookState = fiber.memoizedState;
|
|
933
|
-
for (let
|
|
910
|
+
for (let currentHookIndex = 0; currentHookIndex < hookIndex; currentHookIndex++) {
|
|
934
911
|
if (!hookState?.next) return null;
|
|
935
912
|
hookState = hookState.next;
|
|
936
913
|
}
|
|
@@ -963,12 +940,12 @@ const isPOJO = (maybePOJO: unknown): maybePOJO is Record<string, unknown> => {
|
|
|
963
940
|
const buildPathsFromValue = (
|
|
964
941
|
maybePOJO: Record<string, unknown>,
|
|
965
942
|
basePath: string[] = [],
|
|
966
|
-
):
|
|
943
|
+
): ValueWrite[] => {
|
|
967
944
|
if (!isPOJO(maybePOJO)) {
|
|
968
945
|
return [{ path: basePath, value: maybePOJO }];
|
|
969
946
|
}
|
|
970
947
|
|
|
971
|
-
const paths:
|
|
948
|
+
const paths: ValueWrite[] = [];
|
|
972
949
|
|
|
973
950
|
for (const key in maybePOJO) {
|
|
974
951
|
const value = maybePOJO[key];
|
|
@@ -984,7 +961,7 @@ const buildPathsFromValue = (
|
|
|
984
961
|
return paths;
|
|
985
962
|
};
|
|
986
963
|
|
|
987
|
-
const buildValueWrites = (partialValue: unknown):
|
|
964
|
+
const buildValueWrites = (partialValue: unknown): ValueWrite[] =>
|
|
988
965
|
isPOJO(partialValue) ? buildPathsFromValue(partialValue) : [{ path: [], value: partialValue }];
|
|
989
966
|
|
|
990
967
|
export const overrideProps = (fiber: Fiber, partialValue: Record<string, unknown>) => {
|
|
@@ -1048,18 +1025,24 @@ export interface InstrumentationOptions {
|
|
|
1048
1025
|
onScheduleFiberRoot?: (rendererID: number, root: FiberRoot, children: React.ReactNode) => unknown;
|
|
1049
1026
|
}
|
|
1050
1027
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
const
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1028
|
+
interface InstrumentationSubscription {
|
|
1029
|
+
options: InstrumentationOptions;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
const instrumentationSubscriptions = new Set<InstrumentationSubscription>();
|
|
1033
|
+
|
|
1034
|
+
const runInstrumentationCallback = (
|
|
1035
|
+
instrumentationName: string,
|
|
1036
|
+
callbackName: string,
|
|
1037
|
+
callback: () => unknown,
|
|
1038
|
+
): void =>
|
|
1039
|
+
runWithBippyError(
|
|
1040
|
+
callback,
|
|
1041
|
+
(cause) => new BippyInstrumentationError(instrumentationName, callbackName, cause),
|
|
1042
|
+
);
|
|
1043
|
+
|
|
1044
|
+
const runReactDevToolsCallback = (callbackName: string, callback: () => unknown): void =>
|
|
1045
|
+
runWithBippyError(callback, (cause) => new BippyReactDevToolsError(callbackName, cause));
|
|
1063
1046
|
|
|
1064
1047
|
interface HookDispatchers {
|
|
1065
1048
|
onCommitFiberRoot: ReactDevToolsGlobalHook["onCommitFiberRoot"];
|
|
@@ -1069,6 +1052,7 @@ interface HookDispatchers {
|
|
|
1069
1052
|
}
|
|
1070
1053
|
|
|
1071
1054
|
const hookDispatchers = new WeakMap<ReactDevToolsGlobalHook, Partial<HookDispatchers>>();
|
|
1055
|
+
let didSubscribeToHookReplacements = false;
|
|
1072
1056
|
|
|
1073
1057
|
const rootRendererIds = new WeakMap<FiberRoot, number>();
|
|
1074
1058
|
|
|
@@ -1077,7 +1061,7 @@ const rootRendererIds = new WeakMap<FiberRoot, number>();
|
|
|
1077
1061
|
// next instrument() call installs a fresh wrapper over it; a superseded
|
|
1078
1062
|
// wrapper still forwards the previous chain but skips the listeners so
|
|
1079
1063
|
// they never fire twice.
|
|
1080
|
-
const
|
|
1064
|
+
const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
1081
1065
|
const dispatchers = hookDispatchers.get(rdtHook) ?? {};
|
|
1082
1066
|
hookDispatchers.set(rdtHook, dispatchers);
|
|
1083
1067
|
|
|
@@ -1092,8 +1076,13 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1092
1076
|
priority,
|
|
1093
1077
|
didError,
|
|
1094
1078
|
) => {
|
|
1095
|
-
prevOnCommitFiberRoot
|
|
1079
|
+
if (prevOnCommitFiberRoot) {
|
|
1080
|
+
runReactDevToolsCallback("onCommitFiberRoot", () =>
|
|
1081
|
+
prevOnCommitFiberRoot(rendererID, root, priority, didError),
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1096
1084
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberRoot !== dispatchCommitFiberRoot) return;
|
|
1085
|
+
setReactWorkTagsForFiber(root.current, rdtHook.renderers.get(rendererID));
|
|
1097
1086
|
const rootMemoizedState = root.current.memoizedState;
|
|
1098
1087
|
const isUnmounting =
|
|
1099
1088
|
rootMemoizedState === null ||
|
|
@@ -1106,8 +1095,14 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1106
1095
|
_fiberRoots.add(root);
|
|
1107
1096
|
rootRendererIds.set(root, rendererID);
|
|
1108
1097
|
}
|
|
1109
|
-
for (const
|
|
1110
|
-
|
|
1098
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
1099
|
+
if (options.onCommitFiberRoot) {
|
|
1100
|
+
runInstrumentationCallback(
|
|
1101
|
+
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1102
|
+
"onCommitFiberRoot",
|
|
1103
|
+
() => options.onCommitFiberRoot?.(rendererID, root, priority, didError),
|
|
1104
|
+
);
|
|
1105
|
+
}
|
|
1111
1106
|
}
|
|
1112
1107
|
};
|
|
1113
1108
|
dispatchers.onCommitFiberRoot = dispatchCommitFiberRoot;
|
|
@@ -1123,12 +1118,23 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1123
1118
|
rendererID,
|
|
1124
1119
|
fiber,
|
|
1125
1120
|
) => {
|
|
1126
|
-
|
|
1121
|
+
setReactWorkTagsForFiber(fiber, rdtHook.renderers.get(rendererID));
|
|
1122
|
+
if (prevOnCommitFiberUnmount) {
|
|
1123
|
+
runReactDevToolsCallback("onCommitFiberUnmount", () =>
|
|
1124
|
+
prevOnCommitFiberUnmount(rendererID, fiber),
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1127
1127
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberUnmount !== dispatchCommitFiberUnmount) {
|
|
1128
1128
|
return;
|
|
1129
1129
|
}
|
|
1130
|
-
for (const
|
|
1131
|
-
|
|
1130
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
1131
|
+
if (options.onCommitFiberUnmount) {
|
|
1132
|
+
runInstrumentationCallback(
|
|
1133
|
+
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1134
|
+
"onCommitFiberUnmount",
|
|
1135
|
+
() => options.onCommitFiberUnmount?.(rendererID, fiber),
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1132
1138
|
}
|
|
1133
1139
|
};
|
|
1134
1140
|
dispatchers.onCommitFiberUnmount = dispatchCommitFiberUnmount;
|
|
@@ -1144,12 +1150,22 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1144
1150
|
rendererID,
|
|
1145
1151
|
root,
|
|
1146
1152
|
) => {
|
|
1147
|
-
prevOnPostCommitFiberRoot
|
|
1153
|
+
if (prevOnPostCommitFiberRoot) {
|
|
1154
|
+
runReactDevToolsCallback("onPostCommitFiberRoot", () =>
|
|
1155
|
+
prevOnPostCommitFiberRoot(rendererID, root),
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1148
1158
|
if (hookDispatchers.get(rdtHook)?.onPostCommitFiberRoot !== dispatchPostCommitFiberRoot) {
|
|
1149
1159
|
return;
|
|
1150
1160
|
}
|
|
1151
|
-
for (const
|
|
1152
|
-
|
|
1161
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
1162
|
+
if (options.onPostCommitFiberRoot) {
|
|
1163
|
+
runInstrumentationCallback(
|
|
1164
|
+
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1165
|
+
"onPostCommitFiberRoot",
|
|
1166
|
+
() => options.onPostCommitFiberRoot?.(rendererID, root),
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1153
1169
|
}
|
|
1154
1170
|
};
|
|
1155
1171
|
dispatchers.onPostCommitFiberRoot = dispatchPostCommitFiberRoot;
|
|
@@ -1166,10 +1182,20 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1166
1182
|
root,
|
|
1167
1183
|
children,
|
|
1168
1184
|
) => {
|
|
1169
|
-
prevOnScheduleFiberRoot
|
|
1185
|
+
if (prevOnScheduleFiberRoot) {
|
|
1186
|
+
runReactDevToolsCallback("onScheduleFiberRoot", () =>
|
|
1187
|
+
prevOnScheduleFiberRoot(rendererID, root, children),
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1170
1190
|
if (hookDispatchers.get(rdtHook)?.onScheduleFiberRoot !== dispatchScheduleFiberRoot) return;
|
|
1171
|
-
for (const
|
|
1172
|
-
|
|
1191
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
1192
|
+
if (options.onScheduleFiberRoot) {
|
|
1193
|
+
runInstrumentationCallback(
|
|
1194
|
+
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1195
|
+
"onScheduleFiberRoot",
|
|
1196
|
+
() => options.onScheduleFiberRoot?.(rendererID, root, children),
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1173
1199
|
}
|
|
1174
1200
|
};
|
|
1175
1201
|
dispatchers.onScheduleFiberRoot = dispatchScheduleFiberRoot;
|
|
@@ -1196,30 +1222,31 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1196
1222
|
* unsubscribe();
|
|
1197
1223
|
*/
|
|
1198
1224
|
export const instrument = (options: InstrumentationOptions): Unsubscribe => {
|
|
1199
|
-
const
|
|
1225
|
+
const onActiveListener = options.onActive;
|
|
1226
|
+
const onActive = onActiveListener
|
|
1227
|
+
? () =>
|
|
1228
|
+
runInstrumentationCallback(
|
|
1229
|
+
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1230
|
+
"onActive",
|
|
1231
|
+
onActiveListener,
|
|
1232
|
+
)
|
|
1233
|
+
: undefined;
|
|
1234
|
+
const rdtHook = getRDTHook(onActive);
|
|
1235
|
+
|
|
1236
|
+
if (!didSubscribeToHookReplacements) {
|
|
1237
|
+
onRDTHookReplace(setHookEventDispatchers);
|
|
1238
|
+
didSubscribeToHookReplacements = true;
|
|
1239
|
+
}
|
|
1200
1240
|
|
|
1201
1241
|
rdtHook._instrumentationSource = options.name ?? BIPPY_INSTRUMENTATION_STRING;
|
|
1202
1242
|
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
onActive,
|
|
1207
|
-
onCommitFiberRoot,
|
|
1208
|
-
onCommitFiberUnmount,
|
|
1209
|
-
onPostCommitFiberRoot,
|
|
1210
|
-
onScheduleFiberRoot,
|
|
1211
|
-
} = options;
|
|
1212
|
-
if (onCommitFiberRoot) commitFiberRootListeners.add(onCommitFiberRoot);
|
|
1213
|
-
if (onCommitFiberUnmount) commitFiberUnmountListeners.add(onCommitFiberUnmount);
|
|
1214
|
-
if (onPostCommitFiberRoot) postCommitFiberRootListeners.add(onPostCommitFiberRoot);
|
|
1215
|
-
if (onScheduleFiberRoot) scheduleFiberRootListeners.add(onScheduleFiberRoot);
|
|
1243
|
+
setHookEventDispatchers(rdtHook);
|
|
1244
|
+
const subscription: InstrumentationSubscription = { options };
|
|
1245
|
+
instrumentationSubscriptions.add(subscription);
|
|
1216
1246
|
|
|
1217
1247
|
return toUnsubscribe(() => {
|
|
1218
1248
|
if (onActive) _onActiveListeners.delete(onActive);
|
|
1219
|
-
|
|
1220
|
-
if (onCommitFiberUnmount) commitFiberUnmountListeners.delete(onCommitFiberUnmount);
|
|
1221
|
-
if (onPostCommitFiberRoot) postCommitFiberRootListeners.delete(onPostCommitFiberRoot);
|
|
1222
|
-
if (onScheduleFiberRoot) scheduleFiberRootListeners.delete(onScheduleFiberRoot);
|
|
1249
|
+
instrumentationSubscriptions.delete(subscription);
|
|
1223
1250
|
});
|
|
1224
1251
|
};
|
|
1225
1252
|
|
|
@@ -1307,6 +1334,18 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1307
1334
|
return null;
|
|
1308
1335
|
};
|
|
1309
1336
|
|
|
1310
|
-
export
|
|
1337
|
+
export {
|
|
1338
|
+
BIPPY_INSTRUMENTATION_STRING,
|
|
1339
|
+
_onActiveListeners,
|
|
1340
|
+
_renderers,
|
|
1341
|
+
getRDTHook,
|
|
1342
|
+
hasRDTHook,
|
|
1343
|
+
installRDTHook,
|
|
1344
|
+
isRealReactDevtools,
|
|
1345
|
+
onRendererInject,
|
|
1346
|
+
patchRDTHook,
|
|
1347
|
+
safelyInstallRDTHook,
|
|
1348
|
+
version,
|
|
1349
|
+
} from "./rdt-hook.js";
|
|
1311
1350
|
export * from "./unsubscribe.js";
|
|
1312
1351
|
export type * from "./types.js";
|