bippy 0.6.1-dev.051a9b2 → 0.6.1-dev.3a24abf
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 +26 -48
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +32 -44
- package/dist/core.d.ts +32 -44
- 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/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 +1 -1
- package/dist/source.d.ts +1 -1
- package/dist/source.js +14 -4
- package/dist/types.d.cts +291 -0
- package/dist/types.d.ts +291 -0
- package/package.json +14 -12
- package/src/core.ts +206 -155
- package/src/generated/react-work-tags.ts +169 -0
- package/src/rdt-hook.ts +24 -67
- package/src/react-internals.ts +67 -0
- package/src/source/constants.ts +1 -1
- package/src/source/get-source.ts +2 -1
- package/src/source/owner-stack.ts +64 -77
- package/src/source/parse-stack.ts +1 -1
- package/src/source/symbolication.ts +25 -4
- package/src/types.ts +154 -333
- 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
package/src/core.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
//
|
|
2
|
-
// since it will be executed before the react devtools hook is created
|
|
1
|
+
// React must remain a type-only import because this module loads immediately after the DevTools hook.
|
|
3
2
|
|
|
4
3
|
import type * as React from "react";
|
|
5
4
|
|
|
@@ -7,6 +6,7 @@ import type {
|
|
|
7
6
|
ContextDependency,
|
|
8
7
|
Fiber,
|
|
9
8
|
FiberRoot,
|
|
9
|
+
HostFiber,
|
|
10
10
|
MemoizedState,
|
|
11
11
|
ReactDevToolsGlobalHook,
|
|
12
12
|
ReactRenderer,
|
|
@@ -17,55 +17,101 @@ import {
|
|
|
17
17
|
BIPPY_INSTRUMENTATION_STRING,
|
|
18
18
|
getRDTHook,
|
|
19
19
|
hasRDTHook,
|
|
20
|
-
isReactRefresh,
|
|
21
20
|
isRealReactDevtools,
|
|
22
21
|
onRendererInject,
|
|
23
22
|
} from "./rdt-hook.js";
|
|
23
|
+
import {
|
|
24
|
+
ClassComponentTag,
|
|
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,
|
|
43
|
+
MutationMask,
|
|
44
|
+
OffscreenComponentTag,
|
|
45
|
+
ReactBuildType,
|
|
46
|
+
ReactFiberFlags,
|
|
47
|
+
SimpleMemoComponentTag,
|
|
48
|
+
SuspenseComponentTag,
|
|
49
|
+
TRANSITIONAL_ELEMENT_TYPE_SYMBOL_STRING,
|
|
50
|
+
} from "./react-internals.js";
|
|
24
51
|
import { toUnsubscribe, type Unsubscribe } from "./unsubscribe.js";
|
|
25
52
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
53
|
+
export {
|
|
54
|
+
ActivityComponentTag,
|
|
55
|
+
ClassComponentTag,
|
|
56
|
+
CONCURRENT_MODE_NUMBER,
|
|
57
|
+
CONCURRENT_MODE_SYMBOL_DESCRIPTION,
|
|
58
|
+
CONCURRENT_MODE_SYMBOL_STRING,
|
|
59
|
+
ContextConsumerTag,
|
|
60
|
+
DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION,
|
|
61
|
+
DEPRECATED_ASYNC_MODE_SYMBOL_STRING,
|
|
62
|
+
DehydratedSuspenseComponentTag,
|
|
63
|
+
ELEMENT_TYPE_SYMBOL_STRING,
|
|
64
|
+
ForwardRefTag,
|
|
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;
|
|
85
|
+
|
|
86
|
+
const isObjectRecord = (value: unknown): value is Record<string, unknown> =>
|
|
87
|
+
typeof value === "object" && value !== null;
|
|
88
|
+
|
|
89
|
+
const isComponentType = (value: unknown): value is React.ComponentType<unknown> =>
|
|
90
|
+
typeof value === "function";
|
|
91
|
+
|
|
92
|
+
const getPropertyValue = (value: object, key: PropertyKey): unknown => {
|
|
93
|
+
let currentValue: object | null = value;
|
|
94
|
+
while (currentValue) {
|
|
95
|
+
const descriptor = Object.getOwnPropertyDescriptor(currentValue, key);
|
|
96
|
+
if (descriptor) {
|
|
97
|
+
if ("value" in descriptor) return descriptor.value;
|
|
98
|
+
return descriptor.get?.call(value);
|
|
99
|
+
}
|
|
100
|
+
currentValue = Object.getPrototypeOf(currentValue);
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const getTypeName = (value: object): string | null => {
|
|
106
|
+
const displayName = getPropertyValue(value, "displayName");
|
|
107
|
+
if (typeof displayName === "string" && displayName) return displayName;
|
|
108
|
+
const name = getPropertyValue(value, "name");
|
|
109
|
+
return typeof name === "string" && name ? name : null;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
interface FiberSelector {
|
|
113
|
+
(node: Fiber): boolean | Promise<boolean | void> | void;
|
|
114
|
+
}
|
|
69
115
|
|
|
70
116
|
/**
|
|
71
117
|
* Returns `true` if object is a React Element.
|
|
@@ -74,9 +120,8 @@ const MutationMask =
|
|
|
74
120
|
*/
|
|
75
121
|
export const isValidElement = (element: unknown): element is React.ReactElement =>
|
|
76
122
|
typeof element === "object" &&
|
|
77
|
-
element
|
|
123
|
+
element !== null &&
|
|
78
124
|
"$$typeof" in element &&
|
|
79
|
-
// react 18 uses Symbol.for('react.element'), react 19 uses Symbol.for('react.transitional.element')
|
|
80
125
|
[ELEMENT_TYPE_SYMBOL_STRING, TRANSITIONAL_ELEMENT_TYPE_SYMBOL_STRING].includes(
|
|
81
126
|
String(element.$$typeof),
|
|
82
127
|
);
|
|
@@ -86,7 +131,7 @@ export const isValidElement = (element: unknown): element is React.ReactElement
|
|
|
86
131
|
*/
|
|
87
132
|
export const isValidFiber = (fiber: unknown): fiber is Fiber =>
|
|
88
133
|
typeof fiber === "object" &&
|
|
89
|
-
fiber
|
|
134
|
+
fiber !== null &&
|
|
90
135
|
"tag" in fiber &&
|
|
91
136
|
"stateNode" in fiber &&
|
|
92
137
|
"return" in fiber &&
|
|
@@ -99,16 +144,15 @@ export const isValidFiber = (fiber: unknown): fiber is Fiber =>
|
|
|
99
144
|
*
|
|
100
145
|
* @see https://reactnative.dev/architecture/glossary#host-view-tree-and-host-view
|
|
101
146
|
*/
|
|
102
|
-
export const isHostFiber = (fiber: Fiber):
|
|
147
|
+
export const isHostFiber = (fiber: Fiber): fiber is HostFiber => {
|
|
103
148
|
switch (fiber.tag) {
|
|
104
149
|
case HostComponentTag:
|
|
105
|
-
|
|
150
|
+
case HostTextTag:
|
|
106
151
|
case HostHoistableTag:
|
|
107
|
-
// @ts-expect-error: it exists
|
|
108
152
|
case HostSingletonTag:
|
|
109
153
|
return true;
|
|
110
154
|
default:
|
|
111
|
-
return
|
|
155
|
+
return false;
|
|
112
156
|
}
|
|
113
157
|
};
|
|
114
158
|
|
|
@@ -230,7 +274,7 @@ export const traverseProps = (
|
|
|
230
274
|
export const didFiberRender = (fiber: Fiber): boolean => {
|
|
231
275
|
const nextProps = fiber.memoizedProps;
|
|
232
276
|
const prevProps = fiber.alternate?.memoizedProps || {};
|
|
233
|
-
const flags = fiber.flags ??
|
|
277
|
+
const flags = fiber.flags ?? fiber.effectTag ?? 0;
|
|
234
278
|
|
|
235
279
|
switch (fiber.tag) {
|
|
236
280
|
case ClassComponentTag:
|
|
@@ -297,7 +341,8 @@ export const getFiberStack = (fiber: Fiber): Fiber[] => {
|
|
|
297
341
|
let currentFiber = fiber;
|
|
298
342
|
while (currentFiber.return) {
|
|
299
343
|
stack.push(currentFiber);
|
|
300
|
-
|
|
344
|
+
const parentFiber = currentFiber.return;
|
|
345
|
+
currentFiber = parentFiber;
|
|
301
346
|
}
|
|
302
347
|
return stack;
|
|
303
348
|
};
|
|
@@ -405,7 +450,7 @@ export function traverseFiber(
|
|
|
405
450
|
): Promise<Fiber | null>;
|
|
406
451
|
export function traverseFiber(
|
|
407
452
|
fiber: Fiber | null,
|
|
408
|
-
selector:
|
|
453
|
+
selector: FiberSelector,
|
|
409
454
|
ascending = false,
|
|
410
455
|
): Fiber | null | Promise<Fiber | null> {
|
|
411
456
|
if (!fiber) return null;
|
|
@@ -417,11 +462,7 @@ export function traverseFiber(
|
|
|
417
462
|
|
|
418
463
|
let child = ascending ? fiber.return : fiber.child;
|
|
419
464
|
while (child) {
|
|
420
|
-
const match = await traverseFiberAsync(
|
|
421
|
-
child,
|
|
422
|
-
selector as (node: Fiber) => Promise<boolean | void>,
|
|
423
|
-
ascending,
|
|
424
|
-
);
|
|
465
|
+
const match = await traverseFiberAsync(child, selector, ascending);
|
|
425
466
|
if (match) return match;
|
|
426
467
|
child = ascending ? null : child.sibling;
|
|
427
468
|
}
|
|
@@ -433,7 +474,7 @@ export function traverseFiber(
|
|
|
433
474
|
|
|
434
475
|
let child = ascending ? fiber.return : fiber.child;
|
|
435
476
|
while (child) {
|
|
436
|
-
const match = traverseFiberSync(child, selector
|
|
477
|
+
const match = traverseFiberSync(child, selector, ascending);
|
|
437
478
|
if (match) return match;
|
|
438
479
|
child = ascending ? null : child.sibling;
|
|
439
480
|
}
|
|
@@ -442,11 +483,13 @@ export function traverseFiber(
|
|
|
442
483
|
|
|
443
484
|
const traverseFiberSync = (
|
|
444
485
|
fiber: Fiber | null,
|
|
445
|
-
selector:
|
|
486
|
+
selector: FiberSelector,
|
|
446
487
|
ascending = false,
|
|
447
488
|
): Fiber | null => {
|
|
448
489
|
if (!fiber) return null;
|
|
449
|
-
|
|
490
|
+
const selection = selector(fiber);
|
|
491
|
+
if (selection instanceof Promise) return null;
|
|
492
|
+
if (selection === true) return fiber;
|
|
450
493
|
|
|
451
494
|
let child = ascending ? fiber.return : fiber.child;
|
|
452
495
|
while (child) {
|
|
@@ -460,7 +503,7 @@ const traverseFiberSync = (
|
|
|
460
503
|
|
|
461
504
|
const traverseFiberAsync = async (
|
|
462
505
|
fiber: Fiber | null,
|
|
463
|
-
selector:
|
|
506
|
+
selector: FiberSelector,
|
|
464
507
|
ascending = false,
|
|
465
508
|
): Promise<Fiber | null> => {
|
|
466
509
|
if (!fiber) return null;
|
|
@@ -490,7 +533,7 @@ export const getTimings = (fiber?: Fiber | null): { selfTime: number; totalTime:
|
|
|
490
533
|
let selfTime = totalTime;
|
|
491
534
|
// TODO: calculate a DOM time, which is just host component summed up
|
|
492
535
|
let child = fiber?.child ?? null;
|
|
493
|
-
while (totalTime > 0 && child
|
|
536
|
+
while (totalTime > 0 && child !== null) {
|
|
494
537
|
selfTime -= child.actualDuration ?? 0;
|
|
495
538
|
child = child.sibling;
|
|
496
539
|
}
|
|
@@ -501,48 +544,29 @@ export const getTimings = (fiber?: Fiber | null): { selfTime: number; totalTime:
|
|
|
501
544
|
* Returns `true` if the {@link Fiber} uses React Compiler's memo cache.
|
|
502
545
|
*/
|
|
503
546
|
export const hasMemoCache = (fiber: Fiber): boolean => {
|
|
504
|
-
return Boolean(
|
|
547
|
+
return Boolean(fiber.updateQueue?.memoCache);
|
|
505
548
|
};
|
|
506
549
|
|
|
507
|
-
type FiberType =
|
|
508
|
-
| React.ComponentType<unknown>
|
|
509
|
-
| React.ForwardRefExoticComponent<unknown>
|
|
510
|
-
| React.MemoExoticComponent<React.ComponentType<unknown>>;
|
|
511
|
-
|
|
512
550
|
/**
|
|
513
551
|
* Returns the type (e.g. component definition) of the {@link Fiber}
|
|
514
552
|
*/
|
|
515
553
|
export const getType = (type: unknown): null | React.ComponentType<unknown> => {
|
|
516
|
-
|
|
517
|
-
if (
|
|
518
|
-
|
|
519
|
-
}
|
|
520
|
-
if (typeof currentType === "object" && currentType) {
|
|
521
|
-
// memo / forwardRef case
|
|
522
|
-
return getType(
|
|
523
|
-
(currentType as React.MemoExoticComponent<React.ComponentType<unknown>>).type ||
|
|
524
|
-
(currentType as { render: React.ComponentType<unknown> }).render,
|
|
525
|
-
);
|
|
526
|
-
}
|
|
527
|
-
return null;
|
|
554
|
+
if (isComponentType(type)) return type;
|
|
555
|
+
if (!isObjectRecord(type)) return null;
|
|
556
|
+
return getType(type.type ?? type.render);
|
|
528
557
|
};
|
|
529
558
|
|
|
530
559
|
/**
|
|
531
560
|
* Returns the display name of the {@link Fiber} type.
|
|
532
561
|
*/
|
|
533
562
|
export const getDisplayName = (type: unknown): null | string => {
|
|
534
|
-
|
|
535
|
-
if (typeof
|
|
536
|
-
|
|
537
|
-
}
|
|
538
|
-
if (typeof currentType !== "function" && !(typeof currentType === "object" && currentType)) {
|
|
539
|
-
return null;
|
|
540
|
-
}
|
|
541
|
-
const name = currentType.displayName || currentType.name || null;
|
|
563
|
+
if (typeof type === "string") return type;
|
|
564
|
+
if ((typeof type !== "function" && typeof type !== "object") || type === null) return null;
|
|
565
|
+
const name = getTypeName(type);
|
|
542
566
|
if (name) return name;
|
|
543
|
-
const unwrappedType = getType(
|
|
567
|
+
const unwrappedType = getType(type);
|
|
544
568
|
if (!unwrappedType) return null;
|
|
545
|
-
return unwrappedType
|
|
569
|
+
return getTypeName(unwrappedType);
|
|
546
570
|
};
|
|
547
571
|
|
|
548
572
|
/**
|
|
@@ -550,7 +574,10 @@ export const getDisplayName = (type: unknown): null | string => {
|
|
|
550
574
|
*/
|
|
551
575
|
export const detectReactBuildType = (renderer: ReactRenderer): "development" | "production" => {
|
|
552
576
|
try {
|
|
553
|
-
if (
|
|
577
|
+
if (
|
|
578
|
+
typeof renderer.version === "string" &&
|
|
579
|
+
renderer.bundleType === ReactBuildType.Development
|
|
580
|
+
) {
|
|
554
581
|
return "development";
|
|
555
582
|
}
|
|
556
583
|
} catch {}
|
|
@@ -562,11 +589,7 @@ export const detectReactBuildType = (renderer: ReactRenderer): "development" | "
|
|
|
562
589
|
*/
|
|
563
590
|
export const isInstrumentationActive = (): boolean => {
|
|
564
591
|
const rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
565
|
-
return (
|
|
566
|
-
Boolean(rdtHook?._instrumentationIsActive) ||
|
|
567
|
-
isRealReactDevtools(rdtHook) ||
|
|
568
|
-
isReactRefresh(rdtHook)
|
|
569
|
-
);
|
|
592
|
+
return Boolean(rdtHook?._instrumentationIsActive) || isRealReactDevtools(rdtHook);
|
|
570
593
|
};
|
|
571
594
|
|
|
572
595
|
export const _fiberRoots = new Set<FiberRoot>();
|
|
@@ -600,9 +623,7 @@ export const setFiberId = (fiber: Fiber, id: number = fiberId++): void => {
|
|
|
600
623
|
fiberIdMap.set(fiber, id);
|
|
601
624
|
};
|
|
602
625
|
|
|
603
|
-
//
|
|
604
|
-
// be switched to the current fiber and vice versa.
|
|
605
|
-
// fiber === fiber.alternate.alternate
|
|
626
|
+
// Fiber alternates share an identity across double-buffered commits.
|
|
606
627
|
export const getFiberId = (fiber: Fiber): number => {
|
|
607
628
|
let id = fiberIdMap.get(fiber);
|
|
608
629
|
if (id === undefined && fiber.alternate) {
|
|
@@ -622,7 +643,7 @@ const mountFiberRecursively = (
|
|
|
622
643
|
): void => {
|
|
623
644
|
let fiber: Fiber | null = firstChild;
|
|
624
645
|
|
|
625
|
-
while (fiber
|
|
646
|
+
while (fiber !== null) {
|
|
626
647
|
if (!fiberIdMap.has(fiber)) {
|
|
627
648
|
getFiberId(fiber);
|
|
628
649
|
}
|
|
@@ -646,18 +667,12 @@ const mountFiberRecursively = (
|
|
|
646
667
|
}
|
|
647
668
|
}
|
|
648
669
|
} else {
|
|
649
|
-
|
|
650
|
-
const areSuspenseChildrenConditionallyWrapped = (OffscreenComponentTag as number) === -1;
|
|
651
|
-
if (areSuspenseChildrenConditionallyWrapped) {
|
|
652
|
-
primaryChild = fiber.child;
|
|
653
|
-
} else if (fiber.child !== null) {
|
|
654
|
-
primaryChild = fiber.child.child;
|
|
655
|
-
}
|
|
670
|
+
const primaryChild = fiber.child?.child ?? null;
|
|
656
671
|
if (primaryChild !== null) {
|
|
657
672
|
mountFiberRecursively(onRender, primaryChild, false);
|
|
658
673
|
}
|
|
659
674
|
}
|
|
660
|
-
} else if (fiber.child
|
|
675
|
+
} else if (fiber.child !== null) {
|
|
661
676
|
mountFiberRecursively(onRender, fiber.child, true);
|
|
662
677
|
}
|
|
663
678
|
fiber = traverseSiblings ? fiber.sibling : null;
|
|
@@ -831,13 +846,15 @@ export const traverseRenderedFibers = (root: FiberRoot, onRender: RenderHandler)
|
|
|
831
846
|
} else if (prevFiber !== null) {
|
|
832
847
|
const wasMounted =
|
|
833
848
|
prevFiber &&
|
|
834
|
-
prevFiber.memoizedState
|
|
835
|
-
prevFiber.memoizedState.element
|
|
849
|
+
prevFiber.memoizedState !== null &&
|
|
850
|
+
prevFiber.memoizedState.element !== null &&
|
|
851
|
+
prevFiber.memoizedState.element !== undefined &&
|
|
836
852
|
// A dehydrated root is not considered mounted
|
|
837
853
|
prevFiber.memoizedState.isDehydrated !== true;
|
|
838
854
|
const isMounted =
|
|
839
|
-
fiber.memoizedState
|
|
840
|
-
fiber.memoizedState.element
|
|
855
|
+
fiber.memoizedState !== null &&
|
|
856
|
+
fiber.memoizedState.element !== null &&
|
|
857
|
+
fiber.memoizedState.element !== undefined &&
|
|
841
858
|
// A dehydrated root is not considered mounted
|
|
842
859
|
fiber.memoizedState.isDehydrated !== true;
|
|
843
860
|
|
|
@@ -859,16 +876,16 @@ const overrideRenderers = new Set<ReactRenderer>();
|
|
|
859
876
|
let areOverrideRenderersWired = false;
|
|
860
877
|
|
|
861
878
|
const wireOverrideRenderers = (): void => {
|
|
862
|
-
if (areOverrideRenderersWired) return;
|
|
863
879
|
if (!hasRDTHook()) return;
|
|
864
880
|
const rdtHook = getRDTHook();
|
|
865
881
|
if (!rdtHook?.renderers) return;
|
|
866
|
-
areOverrideRenderersWired = true;
|
|
867
882
|
|
|
868
883
|
ensureHookDispatchesToListeners(rdtHook);
|
|
869
884
|
for (const renderer of rdtHook.renderers.values()) {
|
|
870
885
|
overrideRenderers.add(renderer);
|
|
871
886
|
}
|
|
887
|
+
if (areOverrideRenderersWired) return;
|
|
888
|
+
areOverrideRenderersWired = true;
|
|
872
889
|
onRendererInject((renderer) => {
|
|
873
890
|
overrideRenderers.add(renderer);
|
|
874
891
|
});
|
|
@@ -918,10 +935,9 @@ const getHookStateDispatch = (
|
|
|
918
935
|
hookState = hookState.next;
|
|
919
936
|
}
|
|
920
937
|
const queue = hookState?.queue;
|
|
921
|
-
if (isPOJO(queue)
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
return null;
|
|
938
|
+
if (!isPOJO(queue)) return null;
|
|
939
|
+
const dispatch = queue.dispatch;
|
|
940
|
+
return typeof dispatch === "function" ? (value) => dispatch(value) : null;
|
|
925
941
|
};
|
|
926
942
|
|
|
927
943
|
const findContextProviderFiber = (fiber: Fiber, contextType: unknown): Fiber | null => {
|
|
@@ -985,11 +1001,10 @@ export const overrideHookState = (fiber: Fiber, id: number, partialValue: unknow
|
|
|
985
1001
|
const writes = buildValueWrites(partialValue);
|
|
986
1002
|
|
|
987
1003
|
if (renderers.length > 0) {
|
|
988
|
-
const hookId = String(id);
|
|
989
1004
|
for (const renderer of renderers) {
|
|
990
1005
|
for (const { path, value } of writes) {
|
|
991
1006
|
try {
|
|
992
|
-
renderer.overrideHookState?.(fiber,
|
|
1007
|
+
renderer.overrideHookState?.(fiber, id, path, value);
|
|
993
1008
|
} catch {}
|
|
994
1009
|
}
|
|
995
1010
|
}
|
|
@@ -1022,7 +1037,12 @@ export const overrideContext = (fiber: Fiber, contextType: unknown, partialValue
|
|
|
1022
1037
|
export interface InstrumentationOptions {
|
|
1023
1038
|
name?: string;
|
|
1024
1039
|
onActive?: () => unknown;
|
|
1025
|
-
onCommitFiberRoot?: (
|
|
1040
|
+
onCommitFiberRoot?: (
|
|
1041
|
+
rendererID: number,
|
|
1042
|
+
root: FiberRoot,
|
|
1043
|
+
priority: number | void,
|
|
1044
|
+
didError?: boolean,
|
|
1045
|
+
) => unknown;
|
|
1026
1046
|
onCommitFiberUnmount?: (rendererID: number, fiber: Fiber) => unknown;
|
|
1027
1047
|
onPostCommitFiberRoot?: (rendererID: number, root: FiberRoot) => unknown;
|
|
1028
1048
|
onScheduleFiberRoot?: (rendererID: number, root: FiberRoot, children: React.ReactNode) => unknown;
|
|
@@ -1070,13 +1090,24 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1070
1090
|
rendererID,
|
|
1071
1091
|
root,
|
|
1072
1092
|
priority,
|
|
1093
|
+
didError,
|
|
1073
1094
|
) => {
|
|
1074
|
-
prevOnCommitFiberRoot?.(rendererID, root, priority);
|
|
1095
|
+
prevOnCommitFiberRoot?.(rendererID, root, priority, didError);
|
|
1075
1096
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberRoot !== dispatchCommitFiberRoot) return;
|
|
1076
|
-
|
|
1077
|
-
|
|
1097
|
+
const rootMemoizedState = root.current.memoizedState;
|
|
1098
|
+
const isUnmounting =
|
|
1099
|
+
rootMemoizedState === null ||
|
|
1100
|
+
rootMemoizedState.element === null ||
|
|
1101
|
+
rootMemoizedState.element === undefined;
|
|
1102
|
+
if (isUnmounting) {
|
|
1103
|
+
_fiberRoots.delete(root);
|
|
1104
|
+
rootRendererIds.delete(root);
|
|
1105
|
+
} else {
|
|
1106
|
+
_fiberRoots.add(root);
|
|
1107
|
+
rootRendererIds.set(root, rendererID);
|
|
1108
|
+
}
|
|
1078
1109
|
for (const listener of commitFiberRootListeners) {
|
|
1079
|
-
listener(rendererID, root, priority);
|
|
1110
|
+
listener(rendererID, root, priority, didError);
|
|
1080
1111
|
}
|
|
1081
1112
|
};
|
|
1082
1113
|
dispatchers.onCommitFiberRoot = dispatchCommitFiberRoot;
|
|
@@ -1192,9 +1223,7 @@ export const instrument = (options: InstrumentationOptions): Unsubscribe => {
|
|
|
1192
1223
|
});
|
|
1193
1224
|
};
|
|
1194
1225
|
|
|
1195
|
-
// React
|
|
1196
|
-
// caching discovered keys makes repeat lookups a single property read instead of a
|
|
1197
|
-
// scan over every own key of the element.
|
|
1226
|
+
// React uses per-renderer suffixes for host-instance Fiber keys, so discovered keys are cached.
|
|
1198
1227
|
const knownFiberPropertyKeys = new Set<string>();
|
|
1199
1228
|
|
|
1200
1229
|
const isFiberPropertyKey = (key: string): boolean =>
|
|
@@ -1202,6 +1231,32 @@ const isFiberPropertyKey = (key: string): boolean =>
|
|
|
1202
1231
|
key.startsWith("__reactInternalInstance$") ||
|
|
1203
1232
|
key.startsWith("__reactFiber");
|
|
1204
1233
|
|
|
1234
|
+
const getLegacyRootFiber = (hostInstance: Record<string, unknown>): Fiber | null => {
|
|
1235
|
+
const reactRootContainer = hostInstance._reactRootContainer;
|
|
1236
|
+
if (!isObjectRecord(reactRootContainer)) return null;
|
|
1237
|
+
const internalRoot = reactRootContainer._internalRoot;
|
|
1238
|
+
if (!isObjectRecord(internalRoot)) return null;
|
|
1239
|
+
const current = internalRoot.current;
|
|
1240
|
+
if (!isObjectRecord(current)) return null;
|
|
1241
|
+
const child = current.child;
|
|
1242
|
+
return isValidFiber(child) ? child : null;
|
|
1243
|
+
};
|
|
1244
|
+
|
|
1245
|
+
const getInternalInstanceHandle = (hostInstance: Record<string, unknown>): Fiber | null => {
|
|
1246
|
+
const internalInstanceHandle =
|
|
1247
|
+
hostInstance.__internalInstanceHandle ?? hostInstance._internalInstanceHandle;
|
|
1248
|
+
return isValidFiber(internalInstanceHandle) ? internalInstanceHandle : null;
|
|
1249
|
+
};
|
|
1250
|
+
|
|
1251
|
+
const getPublicHostInstance = (stateNode: unknown): unknown => {
|
|
1252
|
+
if (!isObjectRecord(stateNode)) return stateNode;
|
|
1253
|
+
const canonical = stateNode.canonical;
|
|
1254
|
+
if (isObjectRecord(canonical) && isObjectRecord(canonical.publicInstance)) {
|
|
1255
|
+
return canonical.publicInstance;
|
|
1256
|
+
}
|
|
1257
|
+
return typeof stateNode._nativeTag === "number" ? stateNode._nativeTag : stateNode;
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1205
1260
|
export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
1206
1261
|
const rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
1207
1262
|
if (rdtHook?.renderers) {
|
|
@@ -1213,42 +1268,38 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1213
1268
|
}
|
|
1214
1269
|
}
|
|
1215
1270
|
|
|
1216
|
-
if (
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
return (hostInstance._reactRootContainer as any)?._internalRoot?.current?.child;
|
|
1220
|
-
}
|
|
1271
|
+
if (isObjectRecord(hostInstance)) {
|
|
1272
|
+
const legacyRootFiber = getLegacyRootFiber(hostInstance);
|
|
1273
|
+
if (legacyRootFiber) return legacyRootFiber;
|
|
1221
1274
|
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
// handle" instead of a __reactFiber$-prefixed key
|
|
1225
|
-
const fabricInstanceHandle =
|
|
1226
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1227
|
-
(hostInstance as any).__internalInstanceHandle ??
|
|
1228
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1229
|
-
(hostInstance as any)._internalInstanceHandle;
|
|
1230
|
-
if (isFiber(fabricInstanceHandle)) {
|
|
1231
|
-
return fabricInstanceHandle;
|
|
1232
|
-
}
|
|
1275
|
+
const internalInstanceHandle = getInternalInstanceHandle(hostInstance);
|
|
1276
|
+
if (internalInstanceHandle) return internalInstanceHandle;
|
|
1233
1277
|
|
|
1234
|
-
const hostInstanceRecord = hostInstance as Record<string, unknown>;
|
|
1235
1278
|
for (const knownKey of knownFiberPropertyKeys) {
|
|
1236
|
-
const fiber =
|
|
1237
|
-
if (fiber) return fiber
|
|
1279
|
+
const fiber = hostInstance[knownKey];
|
|
1280
|
+
if (isValidFiber(fiber)) return fiber;
|
|
1238
1281
|
}
|
|
1239
1282
|
|
|
1240
|
-
for (const key of Object.keys(
|
|
1283
|
+
for (const key of Object.keys(hostInstance)) {
|
|
1241
1284
|
if (isFiberPropertyKey(key)) {
|
|
1242
1285
|
knownFiberPropertyKeys.add(key);
|
|
1243
|
-
|
|
1286
|
+
const fiber = hostInstance[key];
|
|
1287
|
+
if (isValidFiber(fiber)) return fiber;
|
|
1244
1288
|
}
|
|
1245
1289
|
}
|
|
1290
|
+
}
|
|
1246
1291
|
|
|
1292
|
+
if (
|
|
1293
|
+
hostInstance !== null &&
|
|
1294
|
+
hostInstance !== undefined &&
|
|
1295
|
+
(typeof hostInstance === "object" || typeof hostInstance === "number")
|
|
1296
|
+
) {
|
|
1247
1297
|
for (const fiberRoot of _fiberRoots) {
|
|
1248
|
-
if (getRootRenderer(fiberRoot.current)?.findFiberByHostInstance) continue;
|
|
1249
1298
|
const fiber = traverseFiber(
|
|
1250
1299
|
fiberRoot.current,
|
|
1251
|
-
(candidateFiber) =>
|
|
1300
|
+
(candidateFiber) =>
|
|
1301
|
+
isHostFiber(candidateFiber) &&
|
|
1302
|
+
getPublicHostInstance(candidateFiber.stateNode) === hostInstance,
|
|
1252
1303
|
);
|
|
1253
1304
|
if (fiber) return fiber;
|
|
1254
1305
|
}
|