bippy 0.6.1-dev.3a24abf → 0.6.1-dev.a3b3942
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/LICENSE +1 -1
- package/README.md +7 -1
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +39 -42
- package/dist/core.d.ts +39 -42
- package/dist/core.js +1 -1
- package/dist/core2.cjs +1 -1
- package/dist/core2.d.cts +11 -3
- package/dist/core2.d.ts +11 -3
- package/dist/core2.js +1 -1
- package/dist/{types.d.cts → errors.d.cts} +187 -58
- package/dist/{types.d.ts → errors.d.ts} +187 -58
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -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 +8 -0
- package/dist/install-hook-only.d.ts +8 -0
- 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 +13 -14
- package/dist/source.d.cts +27 -11
- package/dist/source.d.ts +27 -11
- package/dist/source.js +13 -14
- package/package.json +10 -6
- package/src/core.ts +244 -274
- package/src/errors.ts +34 -0
- package/src/install-hook-only.ts +2 -2
- package/src/rdt-hook.ts +152 -110
- package/src/react-internals/generated/react-work-tags.ts +318 -0
- package/src/react-internals/index.ts +67 -0
- package/src/react-internals/semver.ts +80 -0
- package/src/{types.ts → react-internals/types.ts} +13 -75
- package/src/source/error-stack.ts +11 -0
- package/src/source/get-display-name-from-source.ts +32 -25
- package/src/source/get-source.ts +3 -4
- package/src/source/index.ts +9 -1
- package/src/source/inspect-hooks.ts +215 -182
- package/src/source/owner-stack.ts +70 -96
- package/src/source/parse-debug-stack.ts +4 -4
- package/src/source/parse-hook-names.ts +1 -1
- package/src/source/parse-stack.ts +0 -2
- package/src/source/symbolication.ts +483 -104
- package/src/generated/react-work-tags.ts +0 -169
- package/src/react-internals.ts +0 -67
- package/src/unsubscribe.ts +0 -17
package/src/core.ts
CHANGED
|
@@ -10,102 +10,45 @@ import type {
|
|
|
10
10
|
MemoizedState,
|
|
11
11
|
ReactDevToolsGlobalHook,
|
|
12
12
|
ReactRenderer,
|
|
13
|
-
} from "./
|
|
13
|
+
} from "./react-internals/index.js";
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
16
|
_onActiveListeners,
|
|
17
17
|
BIPPY_INSTRUMENTATION_STRING,
|
|
18
|
+
createUnsubscribe,
|
|
18
19
|
getRDTHook,
|
|
19
20
|
hasRDTHook,
|
|
20
21
|
isRealReactDevtools,
|
|
22
|
+
onRDTHookReplace,
|
|
21
23
|
onRendererInject,
|
|
22
24
|
} from "./rdt-hook.js";
|
|
25
|
+
import type { Unsubscribe } 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
|
-
|
|
50
|
-
} from "./react-internals.js";
|
|
51
|
-
import { toUnsubscribe, type Unsubscribe } from "./unsubscribe.js";
|
|
31
|
+
ReactSymbols,
|
|
32
|
+
setReactWorkTagsForFiber,
|
|
33
|
+
} from "./react-internals/index.js";
|
|
52
34
|
|
|
35
|
+
export { getReactWorkTags, ReactSymbols } from "./react-internals/index.js";
|
|
36
|
+
export type { ReactWorkTagMap, ReactWorkTagVersion } from "./react-internals/index.js";
|
|
53
37
|
export {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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;
|
|
38
|
+
BippyError,
|
|
39
|
+
BippyHookInspectionError,
|
|
40
|
+
BippyHookRenderError,
|
|
41
|
+
BippySourceMapError,
|
|
42
|
+
BippyUnsupportedHookError,
|
|
43
|
+
} from "./errors.js";
|
|
88
44
|
|
|
89
45
|
const isComponentType = (value: unknown): value is React.ComponentType<unknown> =>
|
|
90
46
|
typeof value === "function";
|
|
91
47
|
|
|
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
48
|
const getTypeName = (value: object): string | null => {
|
|
106
|
-
const displayName =
|
|
49
|
+
const displayName = "displayName" in value ? value.displayName : null;
|
|
107
50
|
if (typeof displayName === "string" && displayName) return displayName;
|
|
108
|
-
const name =
|
|
51
|
+
const name = "name" in value ? value.name : null;
|
|
109
52
|
return typeof name === "string" && name ? name : null;
|
|
110
53
|
};
|
|
111
54
|
|
|
@@ -113,6 +56,20 @@ interface FiberSelector {
|
|
|
113
56
|
(node: Fiber): boolean | Promise<boolean | void> | void;
|
|
114
57
|
}
|
|
115
58
|
|
|
59
|
+
export interface FiberTimings {
|
|
60
|
+
selfTime: number;
|
|
61
|
+
totalTime: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface RenderHandler {
|
|
65
|
+
(fiber: Fiber, phase: RenderPhase): unknown;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface ValueWrite {
|
|
69
|
+
path: string[];
|
|
70
|
+
value: unknown;
|
|
71
|
+
}
|
|
72
|
+
|
|
116
73
|
/**
|
|
117
74
|
* Returns `true` if object is a React Element.
|
|
118
75
|
*
|
|
@@ -122,9 +79,8 @@ export const isValidElement = (element: unknown): element is React.ReactElement
|
|
|
122
79
|
typeof element === "object" &&
|
|
123
80
|
element !== null &&
|
|
124
81
|
"$$typeof" in element &&
|
|
125
|
-
|
|
126
|
-
String(element.$$typeof)
|
|
127
|
-
);
|
|
82
|
+
(String(element.$$typeof) === ReactSymbols.LEGACY_ELEMENT_SYMBOL_STRING ||
|
|
83
|
+
String(element.$$typeof) === ReactSymbols.ELEMENT_SYMBOL_STRING);
|
|
128
84
|
|
|
129
85
|
/**
|
|
130
86
|
* Returns `true` if object is a React Fiber.
|
|
@@ -139,17 +95,24 @@ export const isValidFiber = (fiber: unknown): fiber is Fiber =>
|
|
|
139
95
|
"sibling" in fiber &&
|
|
140
96
|
"flags" in fiber;
|
|
141
97
|
|
|
98
|
+
const isFiberRoot = (fiberRoot: unknown): fiberRoot is FiberRoot =>
|
|
99
|
+
typeof fiberRoot === "object" &&
|
|
100
|
+
fiberRoot !== null &&
|
|
101
|
+
"current" in fiberRoot &&
|
|
102
|
+
isValidFiber(fiberRoot.current);
|
|
103
|
+
|
|
142
104
|
/**
|
|
143
105
|
* Returns `true` if fiber is a host fiber. Host fibers are DOM nodes in react-dom, `View` in react-native, etc.
|
|
144
106
|
*
|
|
145
107
|
* @see https://reactnative.dev/architecture/glossary#host-view-tree-and-host-view
|
|
146
108
|
*/
|
|
147
109
|
export const isHostFiber = (fiber: Fiber): fiber is HostFiber => {
|
|
110
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
148
111
|
switch (fiber.tag) {
|
|
149
|
-
case
|
|
150
|
-
case
|
|
151
|
-
case
|
|
152
|
-
case
|
|
112
|
+
case workTags.HostComponent:
|
|
113
|
+
case workTags.HostText:
|
|
114
|
+
case workTags.HostHoistable:
|
|
115
|
+
case workTags.HostSingleton:
|
|
153
116
|
return true;
|
|
154
117
|
default:
|
|
155
118
|
return false;
|
|
@@ -162,12 +125,13 @@ export const isHostFiber = (fiber: Fiber): fiber is HostFiber => {
|
|
|
162
125
|
* @see https://reactnative.dev/architecture/glossary#react-composite-components
|
|
163
126
|
*/
|
|
164
127
|
export const isCompositeFiber = (fiber: Fiber): boolean => {
|
|
128
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
165
129
|
switch (fiber.tag) {
|
|
166
|
-
case
|
|
167
|
-
case
|
|
168
|
-
case
|
|
169
|
-
case
|
|
170
|
-
case
|
|
130
|
+
case workTags.ClassComponent:
|
|
131
|
+
case workTags.ForwardRef:
|
|
132
|
+
case workTags.FunctionComponent:
|
|
133
|
+
case workTags.MemoComponent:
|
|
134
|
+
case workTags.SimpleMemoComponent:
|
|
171
135
|
return true;
|
|
172
136
|
default:
|
|
173
137
|
return false;
|
|
@@ -275,15 +239,16 @@ export const didFiberRender = (fiber: Fiber): boolean => {
|
|
|
275
239
|
const nextProps = fiber.memoizedProps;
|
|
276
240
|
const prevProps = fiber.alternate?.memoizedProps || {};
|
|
277
241
|
const flags = fiber.flags ?? fiber.effectTag ?? 0;
|
|
242
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
278
243
|
|
|
279
244
|
switch (fiber.tag) {
|
|
280
|
-
case
|
|
281
|
-
case
|
|
282
|
-
case
|
|
283
|
-
case
|
|
284
|
-
case
|
|
285
|
-
case
|
|
286
|
-
return (flags & PerformedWork) === PerformedWork;
|
|
245
|
+
case workTags.ClassComponent:
|
|
246
|
+
case workTags.ContextConsumer:
|
|
247
|
+
case workTags.ForwardRef:
|
|
248
|
+
case workTags.FunctionComponent:
|
|
249
|
+
case workTags.MemoComponent:
|
|
250
|
+
case workTags.SimpleMemoComponent: {
|
|
251
|
+
return (flags & ReactFiberFlags.PerformedWork) === ReactFiberFlags.PerformedWork;
|
|
287
252
|
}
|
|
288
253
|
default:
|
|
289
254
|
// Host nodes (DOM, root, etc.)
|
|
@@ -301,8 +266,8 @@ export const didFiberRender = (fiber: Fiber): boolean => {
|
|
|
301
266
|
*/
|
|
302
267
|
export const didFiberCommit = (fiber: Fiber): boolean => {
|
|
303
268
|
return Boolean(
|
|
304
|
-
(fiber.flags & (MutationMask | Cloned)) !== 0 ||
|
|
305
|
-
(fiber.subtreeFlags & (MutationMask | Cloned)) !== 0,
|
|
269
|
+
(fiber.flags & (MutationMask | ReactFiberFlags.Cloned)) !== 0 ||
|
|
270
|
+
(fiber.subtreeFlags & (MutationMask | ReactFiberFlags.Cloned)) !== 0,
|
|
306
271
|
);
|
|
307
272
|
};
|
|
308
273
|
|
|
@@ -351,8 +316,9 @@ export const getFiberStack = (fiber: Fiber): Fiber[] => {
|
|
|
351
316
|
* Returns `true` if the {@link Fiber} should be filtered out during reconciliation.
|
|
352
317
|
*/
|
|
353
318
|
const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
319
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
354
320
|
switch (fiber.tag) {
|
|
355
|
-
case
|
|
321
|
+
case workTags.DehydratedSuspenseComponent:
|
|
356
322
|
// TODO: ideally we would show dehydrated Suspense immediately.
|
|
357
323
|
// However, it has some special behavior (like disconnecting
|
|
358
324
|
// an alternate and turning into real Suspense) which breaks DevTools.
|
|
@@ -360,13 +326,13 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
360
326
|
// https://github.com/bvaughn/react-devtools-experimental/issues/197
|
|
361
327
|
return true;
|
|
362
328
|
|
|
363
|
-
case
|
|
364
|
-
case
|
|
365
|
-
case
|
|
366
|
-
case
|
|
329
|
+
case workTags.Fragment:
|
|
330
|
+
case workTags.HostText:
|
|
331
|
+
case workTags.LegacyHiddenComponent:
|
|
332
|
+
case workTags.OffscreenComponent:
|
|
367
333
|
return true;
|
|
368
334
|
|
|
369
|
-
case
|
|
335
|
+
case workTags.HostRoot:
|
|
370
336
|
// It is never valid to filter the root element.
|
|
371
337
|
return false;
|
|
372
338
|
|
|
@@ -376,15 +342,15 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
376
342
|
|
|
377
343
|
if (typeof symbolOrNumber === "symbol") {
|
|
378
344
|
return (
|
|
379
|
-
symbolOrNumber.description === CONCURRENT_MODE_SYMBOL_DESCRIPTION ||
|
|
380
|
-
symbolOrNumber.description === DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION
|
|
345
|
+
symbolOrNumber.description === ReactSymbols.CONCURRENT_MODE_SYMBOL_DESCRIPTION ||
|
|
346
|
+
symbolOrNumber.description === ReactSymbols.DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION
|
|
381
347
|
);
|
|
382
348
|
}
|
|
383
349
|
|
|
384
350
|
switch (symbolOrNumber) {
|
|
385
|
-
case CONCURRENT_MODE_NUMBER:
|
|
386
|
-
case CONCURRENT_MODE_SYMBOL_STRING:
|
|
387
|
-
case DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
|
|
351
|
+
case ReactSymbols.CONCURRENT_MODE_NUMBER:
|
|
352
|
+
case ReactSymbols.CONCURRENT_MODE_SYMBOL_STRING:
|
|
353
|
+
case ReactSymbols.DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
|
|
388
354
|
return true;
|
|
389
355
|
|
|
390
356
|
default:
|
|
@@ -448,75 +414,67 @@ export function traverseFiber(
|
|
|
448
414
|
selector: (node: Fiber) => Promise<boolean | void>,
|
|
449
415
|
ascending?: boolean,
|
|
450
416
|
): Promise<Fiber | null>;
|
|
417
|
+
export function traverseFiber(
|
|
418
|
+
fiber: Fiber | null,
|
|
419
|
+
selector: FiberSelector,
|
|
420
|
+
ascending?: boolean,
|
|
421
|
+
): Fiber | null | Promise<Fiber | null>;
|
|
451
422
|
export function traverseFiber(
|
|
452
423
|
fiber: Fiber | null,
|
|
453
424
|
selector: FiberSelector,
|
|
454
425
|
ascending = false,
|
|
455
426
|
): Fiber | null | Promise<Fiber | null> {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
const firstResult = selector(fiber);
|
|
459
|
-
if (firstResult instanceof Promise) {
|
|
460
|
-
return (async () => {
|
|
461
|
-
if ((await firstResult) === true) return fiber;
|
|
462
|
-
|
|
463
|
-
let child = ascending ? fiber.return : fiber.child;
|
|
464
|
-
while (child) {
|
|
465
|
-
const match = await traverseFiberAsync(child, selector, ascending);
|
|
466
|
-
if (match) return match;
|
|
467
|
-
child = ascending ? null : child.sibling;
|
|
468
|
-
}
|
|
469
|
-
return null;
|
|
470
|
-
})();
|
|
471
|
-
}
|
|
427
|
+
return traverseFiberInternal(fiber, selector, ascending);
|
|
428
|
+
}
|
|
472
429
|
|
|
473
|
-
|
|
430
|
+
const isPromiseLike = <Result>(value: unknown): value is PromiseLike<Result> =>
|
|
431
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
432
|
+
value !== null &&
|
|
433
|
+
"then" in value &&
|
|
434
|
+
typeof value.then === "function";
|
|
474
435
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
return
|
|
482
|
-
}
|
|
436
|
+
const traverseFiberChildren = (
|
|
437
|
+
fiber: Fiber,
|
|
438
|
+
selector: FiberSelector,
|
|
439
|
+
ascending: boolean,
|
|
440
|
+
): Fiber | null | Promise<Fiber | null> => {
|
|
441
|
+
const firstChild = ascending ? fiber.return : fiber.child;
|
|
442
|
+
return traverseFiberSiblings(firstChild, selector, ascending);
|
|
443
|
+
};
|
|
483
444
|
|
|
484
|
-
const
|
|
445
|
+
const traverseFiberSiblings = (
|
|
485
446
|
fiber: Fiber | null,
|
|
486
447
|
selector: FiberSelector,
|
|
487
|
-
ascending
|
|
488
|
-
): Fiber | null => {
|
|
448
|
+
ascending: boolean,
|
|
449
|
+
): Fiber | null | Promise<Fiber | null> => {
|
|
489
450
|
if (!fiber) return null;
|
|
490
|
-
const selection = selector(fiber);
|
|
491
|
-
if (selection instanceof Promise) return null;
|
|
492
|
-
if (selection === true) return fiber;
|
|
493
451
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
452
|
+
const nextSibling = ascending ? null : fiber.sibling;
|
|
453
|
+
const match = traverseFiberInternal(fiber, selector, ascending);
|
|
454
|
+
if (isPromiseLike<Fiber | null>(match)) {
|
|
455
|
+
return Promise.resolve(match).then(
|
|
456
|
+
(resolvedMatch) => resolvedMatch ?? traverseFiberSiblings(nextSibling, selector, ascending),
|
|
457
|
+
);
|
|
500
458
|
}
|
|
501
|
-
return
|
|
459
|
+
return match ?? traverseFiberSiblings(nextSibling, selector, ascending);
|
|
502
460
|
};
|
|
503
461
|
|
|
504
|
-
const
|
|
462
|
+
const traverseFiberInternal = (
|
|
505
463
|
fiber: Fiber | null,
|
|
506
464
|
selector: FiberSelector,
|
|
507
|
-
ascending
|
|
508
|
-
): Promise<Fiber | null> => {
|
|
465
|
+
ascending: boolean,
|
|
466
|
+
): Fiber | null | Promise<Fiber | null> => {
|
|
509
467
|
if (!fiber) return null;
|
|
510
|
-
if ((await selector(fiber)) === true) return fiber;
|
|
511
|
-
|
|
512
|
-
let child = ascending ? fiber.return : fiber.child;
|
|
513
|
-
while (child) {
|
|
514
|
-
const match = await traverseFiberAsync(child, selector, ascending);
|
|
515
|
-
if (match) return match;
|
|
516
468
|
|
|
517
|
-
|
|
469
|
+
const selection = selector(fiber);
|
|
470
|
+
if (isPromiseLike<boolean | void>(selection)) {
|
|
471
|
+
return Promise.resolve(selection).then((didSelectFiber) =>
|
|
472
|
+
didSelectFiber === true ? fiber : traverseFiberChildren(fiber, selector, ascending),
|
|
473
|
+
);
|
|
518
474
|
}
|
|
519
|
-
return
|
|
475
|
+
if (selection === true) return fiber;
|
|
476
|
+
|
|
477
|
+
return traverseFiberChildren(fiber, selector, ascending);
|
|
520
478
|
};
|
|
521
479
|
|
|
522
480
|
/**
|
|
@@ -528,7 +486,7 @@ const traverseFiberAsync = async (
|
|
|
528
486
|
* console.log(selfTime, totalTime);
|
|
529
487
|
* ```
|
|
530
488
|
*/
|
|
531
|
-
export const getTimings = (fiber?: Fiber | null):
|
|
489
|
+
export const getTimings = (fiber?: Fiber | null): FiberTimings => {
|
|
532
490
|
const totalTime = fiber?.actualDuration ?? 0;
|
|
533
491
|
let selfTime = totalTime;
|
|
534
492
|
// TODO: calculate a DOM time, which is just host component summed up
|
|
@@ -552,8 +510,8 @@ export const hasMemoCache = (fiber: Fiber): boolean => {
|
|
|
552
510
|
*/
|
|
553
511
|
export const getType = (type: unknown): null | React.ComponentType<unknown> => {
|
|
554
512
|
if (isComponentType(type)) return type;
|
|
555
|
-
if (
|
|
556
|
-
return getType(
|
|
513
|
+
if (typeof type !== "object" || type === null) return null;
|
|
514
|
+
return getType(Reflect.get(type, "type") ?? Reflect.get(type, "render"));
|
|
557
515
|
};
|
|
558
516
|
|
|
559
517
|
/**
|
|
@@ -605,35 +563,35 @@ export const getLatestFiber = (fiber: Fiber): Fiber => {
|
|
|
605
563
|
}
|
|
606
564
|
for (const root of _fiberRoots) {
|
|
607
565
|
const latestFiber = traverseFiber(root.current, (innerFiber) => {
|
|
608
|
-
if (innerFiber === fiber) return true;
|
|
566
|
+
if (innerFiber === fiber || innerFiber === alternate) return true;
|
|
609
567
|
});
|
|
610
568
|
if (latestFiber) return latestFiber;
|
|
611
569
|
}
|
|
612
570
|
return fiber;
|
|
613
571
|
};
|
|
614
572
|
|
|
615
|
-
export type RenderHandler = <S>(fiber: Fiber, phase: RenderPhase, state?: S) => unknown;
|
|
616
|
-
|
|
617
573
|
export type RenderPhase = "mount" | "unmount" | "update";
|
|
618
574
|
|
|
619
|
-
let
|
|
575
|
+
let nextFiberId = 0;
|
|
620
576
|
const fiberIdMap = new WeakMap<Fiber, number>();
|
|
621
577
|
|
|
622
|
-
export const setFiberId = (fiber: Fiber,
|
|
623
|
-
fiberIdMap.set(fiber,
|
|
578
|
+
export const setFiberId = (fiber: Fiber, fiberId: number = nextFiberId++): void => {
|
|
579
|
+
fiberIdMap.set(fiber, fiberId);
|
|
580
|
+
if (Number.isSafeInteger(fiberId) && fiberId >= nextFiberId) {
|
|
581
|
+
nextFiberId = fiberId + 1;
|
|
582
|
+
}
|
|
624
583
|
};
|
|
625
584
|
|
|
626
|
-
// Fiber alternates share an identity across double-buffered commits.
|
|
627
585
|
export const getFiberId = (fiber: Fiber): number => {
|
|
628
|
-
let
|
|
629
|
-
if (
|
|
630
|
-
|
|
586
|
+
let currentFiberId = fiberIdMap.get(fiber);
|
|
587
|
+
if (currentFiberId === undefined && fiber.alternate) {
|
|
588
|
+
currentFiberId = fiberIdMap.get(fiber.alternate);
|
|
631
589
|
}
|
|
632
|
-
if (
|
|
633
|
-
|
|
634
|
-
setFiberId(fiber,
|
|
590
|
+
if (currentFiberId === undefined) {
|
|
591
|
+
currentFiberId = nextFiberId++;
|
|
592
|
+
setFiberId(fiber, currentFiberId);
|
|
635
593
|
}
|
|
636
|
-
return
|
|
594
|
+
return currentFiberId;
|
|
637
595
|
};
|
|
638
596
|
|
|
639
597
|
const mountFiberRecursively = (
|
|
@@ -652,7 +610,7 @@ const mountFiberRecursively = (
|
|
|
652
610
|
onRender(fiber, "mount");
|
|
653
611
|
}
|
|
654
612
|
|
|
655
|
-
if (fiber.tag ===
|
|
613
|
+
if (fiber.tag === getReactWorkTagsForFiber(fiber).SuspenseComponent) {
|
|
656
614
|
const isTimedOut = fiber.memoizedState !== null;
|
|
657
615
|
if (isTimedOut) {
|
|
658
616
|
// Special case: if Suspense mounts in a timed-out state,
|
|
@@ -682,8 +640,7 @@ const mountFiberRecursively = (
|
|
|
682
640
|
const updateFiberRecursively = (
|
|
683
641
|
onRender: RenderHandler,
|
|
684
642
|
nextFiber: Fiber,
|
|
685
|
-
prevFiber: Fiber,
|
|
686
|
-
parentFiber: Fiber | null,
|
|
643
|
+
prevFiber: Fiber | null,
|
|
687
644
|
): void => {
|
|
688
645
|
if (!fiberIdMap.has(nextFiber)) {
|
|
689
646
|
getFiberId(nextFiber);
|
|
@@ -693,7 +650,7 @@ const updateFiberRecursively = (
|
|
|
693
650
|
getFiberId(prevFiber);
|
|
694
651
|
}
|
|
695
652
|
|
|
696
|
-
const isSuspense = nextFiber.tag ===
|
|
653
|
+
const isSuspense = nextFiber.tag === getReactWorkTagsForFiber(nextFiber).SuspenseComponent;
|
|
697
654
|
|
|
698
655
|
const shouldIncludeInTree = !shouldFilterFiber(nextFiber);
|
|
699
656
|
if (shouldIncludeInTree && didFiberRender(nextFiber)) {
|
|
@@ -722,7 +679,7 @@ const updateFiberRecursively = (
|
|
|
722
679
|
const prevFallbackChildSet = prevFiber.child?.sibling ?? null;
|
|
723
680
|
|
|
724
681
|
if (nextFallbackChildSet !== null && prevFallbackChildSet !== null) {
|
|
725
|
-
updateFiberRecursively(onRender, nextFallbackChildSet, prevFallbackChildSet
|
|
682
|
+
updateFiberRecursively(onRender, nextFallbackChildSet, prevFallbackChildSet);
|
|
726
683
|
}
|
|
727
684
|
} else if (prevDidTimeout && !nextDidTimeOut) {
|
|
728
685
|
// Fallback -> Primary:
|
|
@@ -761,14 +718,7 @@ const updateFiberRecursively = (
|
|
|
761
718
|
// Schedule updates and mounts depending on whether alternates exist.
|
|
762
719
|
// We don't track deletions here because they are reported separately.
|
|
763
720
|
if (nextChild.alternate) {
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
updateFiberRecursively(
|
|
767
|
-
onRender,
|
|
768
|
-
nextChild,
|
|
769
|
-
prevChild,
|
|
770
|
-
shouldIncludeInTree ? nextFiber : parentFiber,
|
|
771
|
-
);
|
|
721
|
+
updateFiberRecursively(onRender, nextChild, nextChild.alternate);
|
|
772
722
|
} else {
|
|
773
723
|
mountFiberRecursively(onRender, nextChild, false);
|
|
774
724
|
}
|
|
@@ -780,7 +730,7 @@ const updateFiberRecursively = (
|
|
|
780
730
|
};
|
|
781
731
|
|
|
782
732
|
const unmountFiber = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
783
|
-
const isRoot = fiber.tag ===
|
|
733
|
+
const isRoot = fiber.tag === getReactWorkTagsForFiber(fiber).HostRoot;
|
|
784
734
|
|
|
785
735
|
if (isRoot || !shouldFilterFiber(fiber)) {
|
|
786
736
|
onRender(fiber, "unmount");
|
|
@@ -789,7 +739,8 @@ const unmountFiber = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
|
789
739
|
|
|
790
740
|
const unmountFiberChildrenRecursively = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
791
741
|
// We might meet a nested Suspense on our way.
|
|
792
|
-
const isTimedOutSuspense =
|
|
742
|
+
const isTimedOutSuspense =
|
|
743
|
+
fiber.tag === getReactWorkTagsForFiber(fiber).SuspenseComponent && fiber.memoizedState !== null;
|
|
793
744
|
let child = fiber.child;
|
|
794
745
|
|
|
795
746
|
if (isTimedOutSuspense) {
|
|
@@ -815,7 +766,7 @@ const unmountFiberChildrenRecursively = (onRender: RenderHandler, fiber: Fiber):
|
|
|
815
766
|
|
|
816
767
|
let commitId = 0;
|
|
817
768
|
const rootInstanceMap = new WeakMap<
|
|
818
|
-
FiberRoot,
|
|
769
|
+
Fiber | FiberRoot,
|
|
819
770
|
{
|
|
820
771
|
id: number;
|
|
821
772
|
prevFiber: Fiber | null;
|
|
@@ -829,7 +780,7 @@ const rootInstanceMap = new WeakMap<
|
|
|
829
780
|
* console.log(phase)
|
|
830
781
|
* })
|
|
831
782
|
*/
|
|
832
|
-
export const traverseRenderedFibers = (root: FiberRoot, onRender: RenderHandler): void => {
|
|
783
|
+
export const traverseRenderedFibers = (root: Fiber | FiberRoot, onRender: RenderHandler): void => {
|
|
833
784
|
const fiber = "current" in root ? root.current : root;
|
|
834
785
|
|
|
835
786
|
let rootInstance = rootInstanceMap.get(root);
|
|
@@ -861,7 +812,7 @@ export const traverseRenderedFibers = (root: FiberRoot, onRender: RenderHandler)
|
|
|
861
812
|
if (!wasMounted && isMounted) {
|
|
862
813
|
mountFiberRecursively(onRender, fiber, false);
|
|
863
814
|
} else if (wasMounted && isMounted) {
|
|
864
|
-
updateFiberRecursively(onRender, fiber, fiber.alternate
|
|
815
|
+
updateFiberRecursively(onRender, fiber, fiber.alternate);
|
|
865
816
|
} else if (wasMounted && !isMounted) {
|
|
866
817
|
unmountFiber(onRender, fiber);
|
|
867
818
|
}
|
|
@@ -878,9 +829,8 @@ let areOverrideRenderersWired = false;
|
|
|
878
829
|
const wireOverrideRenderers = (): void => {
|
|
879
830
|
if (!hasRDTHook()) return;
|
|
880
831
|
const rdtHook = getRDTHook();
|
|
881
|
-
if (!rdtHook?.renderers) return;
|
|
882
832
|
|
|
883
|
-
|
|
833
|
+
setHookEventDispatchers(rdtHook);
|
|
884
834
|
for (const renderer of rdtHook.renderers.values()) {
|
|
885
835
|
overrideRenderers.add(renderer);
|
|
886
836
|
}
|
|
@@ -897,14 +847,13 @@ const getRootRenderer = (fiber: Fiber): ReactRenderer | null => {
|
|
|
897
847
|
while (hostRootFiber.return) {
|
|
898
848
|
hostRootFiber = hostRootFiber.return;
|
|
899
849
|
}
|
|
900
|
-
const
|
|
850
|
+
const fiberRoot = hostRootFiber.stateNode;
|
|
851
|
+
if (!isFiberRoot(fiberRoot)) return null;
|
|
852
|
+
const rendererId = rootRendererIds.get(fiberRoot);
|
|
901
853
|
if (rendererId === undefined) return null;
|
|
902
|
-
return getRDTHook().renderers
|
|
854
|
+
return getRDTHook().renderers.get(rendererId) ?? null;
|
|
903
855
|
};
|
|
904
856
|
|
|
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
857
|
const resolveOverrideRenderers = (fiber: Fiber): ReactRenderer[] => {
|
|
909
858
|
wireOverrideRenderers();
|
|
910
859
|
const rootRenderer = getRootRenderer(fiber);
|
|
@@ -930,7 +879,7 @@ const getHookStateDispatch = (
|
|
|
930
879
|
hookIndex: number,
|
|
931
880
|
): ((value: unknown) => void) | null => {
|
|
932
881
|
let hookState = fiber.memoizedState;
|
|
933
|
-
for (let
|
|
882
|
+
for (let currentHookIndex = 0; currentHookIndex < hookIndex; currentHookIndex++) {
|
|
934
883
|
if (!hookState?.next) return null;
|
|
935
884
|
hookState = hookState.next;
|
|
936
885
|
}
|
|
@@ -963,28 +912,30 @@ const isPOJO = (maybePOJO: unknown): maybePOJO is Record<string, unknown> => {
|
|
|
963
912
|
const buildPathsFromValue = (
|
|
964
913
|
maybePOJO: Record<string, unknown>,
|
|
965
914
|
basePath: string[] = [],
|
|
966
|
-
|
|
967
|
-
|
|
915
|
+
ancestors = new WeakSet<object>(),
|
|
916
|
+
): ValueWrite[] => {
|
|
917
|
+
if (ancestors.has(maybePOJO)) {
|
|
968
918
|
return [{ path: basePath, value: maybePOJO }];
|
|
969
919
|
}
|
|
970
920
|
|
|
971
|
-
|
|
921
|
+
ancestors.add(maybePOJO);
|
|
922
|
+
const paths: ValueWrite[] = [];
|
|
972
923
|
|
|
973
|
-
for (const key
|
|
974
|
-
const value = maybePOJO[key];
|
|
924
|
+
for (const [key, value] of Object.entries(maybePOJO)) {
|
|
975
925
|
const path = basePath.concat(key);
|
|
976
926
|
|
|
977
927
|
if (isPOJO(value)) {
|
|
978
|
-
paths.push(...buildPathsFromValue(value, path));
|
|
928
|
+
paths.push(...buildPathsFromValue(value, path, ancestors));
|
|
979
929
|
} else {
|
|
980
930
|
paths.push({ path, value });
|
|
981
931
|
}
|
|
982
932
|
}
|
|
983
933
|
|
|
934
|
+
ancestors.delete(maybePOJO);
|
|
984
935
|
return paths;
|
|
985
936
|
};
|
|
986
937
|
|
|
987
|
-
const buildValueWrites = (partialValue: unknown):
|
|
938
|
+
const buildValueWrites = (partialValue: unknown): ValueWrite[] =>
|
|
988
939
|
isPOJO(partialValue) ? buildPathsFromValue(partialValue) : [{ path: [], value: partialValue }];
|
|
989
940
|
|
|
990
941
|
export const overrideProps = (fiber: Fiber, partialValue: Record<string, unknown>) => {
|
|
@@ -1048,18 +999,11 @@ export interface InstrumentationOptions {
|
|
|
1048
999
|
onScheduleFiberRoot?: (rendererID: number, root: FiberRoot, children: React.ReactNode) => unknown;
|
|
1049
1000
|
}
|
|
1050
1001
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
>();
|
|
1057
|
-
const postCommitFiberRootListeners = new Set<
|
|
1058
|
-
NonNullable<InstrumentationOptions["onPostCommitFiberRoot"]>
|
|
1059
|
-
>();
|
|
1060
|
-
const scheduleFiberRootListeners = new Set<
|
|
1061
|
-
NonNullable<InstrumentationOptions["onScheduleFiberRoot"]>
|
|
1062
|
-
>();
|
|
1002
|
+
interface InstrumentationSubscription {
|
|
1003
|
+
options: InstrumentationOptions;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
const instrumentationSubscriptions = new Set<InstrumentationSubscription>();
|
|
1063
1007
|
|
|
1064
1008
|
interface HookDispatchers {
|
|
1065
1009
|
onCommitFiberRoot: ReactDevToolsGlobalHook["onCommitFiberRoot"];
|
|
@@ -1069,6 +1013,7 @@ interface HookDispatchers {
|
|
|
1069
1013
|
}
|
|
1070
1014
|
|
|
1071
1015
|
const hookDispatchers = new WeakMap<ReactDevToolsGlobalHook, Partial<HookDispatchers>>();
|
|
1016
|
+
let didSubscribeToHookReplacements = false;
|
|
1072
1017
|
|
|
1073
1018
|
const rootRendererIds = new WeakMap<FiberRoot, number>();
|
|
1074
1019
|
|
|
@@ -1077,7 +1022,7 @@ const rootRendererIds = new WeakMap<FiberRoot, number>();
|
|
|
1077
1022
|
// next instrument() call installs a fresh wrapper over it; a superseded
|
|
1078
1023
|
// wrapper still forwards the previous chain but skips the listeners so
|
|
1079
1024
|
// they never fire twice.
|
|
1080
|
-
const
|
|
1025
|
+
const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
1081
1026
|
const dispatchers = hookDispatchers.get(rdtHook) ?? {};
|
|
1082
1027
|
hookDispatchers.set(rdtHook, dispatchers);
|
|
1083
1028
|
|
|
@@ -1092,8 +1037,11 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1092
1037
|
priority,
|
|
1093
1038
|
didError,
|
|
1094
1039
|
) => {
|
|
1095
|
-
prevOnCommitFiberRoot
|
|
1040
|
+
if (prevOnCommitFiberRoot) {
|
|
1041
|
+
prevOnCommitFiberRoot.call(rdtHook, rendererID, root, priority, didError);
|
|
1042
|
+
}
|
|
1096
1043
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberRoot !== dispatchCommitFiberRoot) return;
|
|
1044
|
+
setReactWorkTagsForFiber(root.current, rdtHook.renderers.get(rendererID));
|
|
1097
1045
|
const rootMemoizedState = root.current.memoizedState;
|
|
1098
1046
|
const isUnmounting =
|
|
1099
1047
|
rootMemoizedState === null ||
|
|
@@ -1106,8 +1054,10 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1106
1054
|
_fiberRoots.add(root);
|
|
1107
1055
|
rootRendererIds.set(root, rendererID);
|
|
1108
1056
|
}
|
|
1109
|
-
for (const
|
|
1110
|
-
|
|
1057
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
1058
|
+
if (options.onCommitFiberRoot) {
|
|
1059
|
+
options.onCommitFiberRoot(rendererID, root, priority, didError);
|
|
1060
|
+
}
|
|
1111
1061
|
}
|
|
1112
1062
|
};
|
|
1113
1063
|
dispatchers.onCommitFiberRoot = dispatchCommitFiberRoot;
|
|
@@ -1123,12 +1073,17 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1123
1073
|
rendererID,
|
|
1124
1074
|
fiber,
|
|
1125
1075
|
) => {
|
|
1126
|
-
|
|
1076
|
+
setReactWorkTagsForFiber(fiber, rdtHook.renderers.get(rendererID));
|
|
1077
|
+
if (prevOnCommitFiberUnmount) {
|
|
1078
|
+
prevOnCommitFiberUnmount.call(rdtHook, rendererID, fiber);
|
|
1079
|
+
}
|
|
1127
1080
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberUnmount !== dispatchCommitFiberUnmount) {
|
|
1128
1081
|
return;
|
|
1129
1082
|
}
|
|
1130
|
-
for (const
|
|
1131
|
-
|
|
1083
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
1084
|
+
if (options.onCommitFiberUnmount) {
|
|
1085
|
+
options.onCommitFiberUnmount(rendererID, fiber);
|
|
1086
|
+
}
|
|
1132
1087
|
}
|
|
1133
1088
|
};
|
|
1134
1089
|
dispatchers.onCommitFiberUnmount = dispatchCommitFiberUnmount;
|
|
@@ -1144,12 +1099,16 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1144
1099
|
rendererID,
|
|
1145
1100
|
root,
|
|
1146
1101
|
) => {
|
|
1147
|
-
prevOnPostCommitFiberRoot
|
|
1102
|
+
if (prevOnPostCommitFiberRoot) {
|
|
1103
|
+
prevOnPostCommitFiberRoot.call(rdtHook, rendererID, root);
|
|
1104
|
+
}
|
|
1148
1105
|
if (hookDispatchers.get(rdtHook)?.onPostCommitFiberRoot !== dispatchPostCommitFiberRoot) {
|
|
1149
1106
|
return;
|
|
1150
1107
|
}
|
|
1151
|
-
for (const
|
|
1152
|
-
|
|
1108
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
1109
|
+
if (options.onPostCommitFiberRoot) {
|
|
1110
|
+
options.onPostCommitFiberRoot(rendererID, root);
|
|
1111
|
+
}
|
|
1153
1112
|
}
|
|
1154
1113
|
};
|
|
1155
1114
|
dispatchers.onPostCommitFiberRoot = dispatchPostCommitFiberRoot;
|
|
@@ -1166,10 +1125,14 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1166
1125
|
root,
|
|
1167
1126
|
children,
|
|
1168
1127
|
) => {
|
|
1169
|
-
prevOnScheduleFiberRoot
|
|
1128
|
+
if (prevOnScheduleFiberRoot) {
|
|
1129
|
+
prevOnScheduleFiberRoot.call(rdtHook, rendererID, root, children);
|
|
1130
|
+
}
|
|
1170
1131
|
if (hookDispatchers.get(rdtHook)?.onScheduleFiberRoot !== dispatchScheduleFiberRoot) return;
|
|
1171
|
-
for (const
|
|
1172
|
-
|
|
1132
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
1133
|
+
if (options.onScheduleFiberRoot) {
|
|
1134
|
+
options.onScheduleFiberRoot(rendererID, root, children);
|
|
1135
|
+
}
|
|
1173
1136
|
}
|
|
1174
1137
|
};
|
|
1175
1138
|
dispatchers.onScheduleFiberRoot = dispatchScheduleFiberRoot;
|
|
@@ -1182,8 +1145,7 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1182
1145
|
* dispatches to a set of listeners, so multiple `instrument` calls compose
|
|
1183
1146
|
* without stacking patches. Returns an unsubscribe function that removes
|
|
1184
1147
|
* exactly the handlers this call registered.
|
|
1185
|
-
* The
|
|
1186
|
-
* bippy subscriptions through `using`.
|
|
1148
|
+
* The unsubscribe function can also be disposed through `using`.
|
|
1187
1149
|
* @example
|
|
1188
1150
|
* const unsubscribe = instrument({
|
|
1189
1151
|
* onActive() {
|
|
@@ -1198,28 +1160,20 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1198
1160
|
export const instrument = (options: InstrumentationOptions): Unsubscribe => {
|
|
1199
1161
|
const rdtHook = getRDTHook(options.onActive);
|
|
1200
1162
|
|
|
1163
|
+
if (!didSubscribeToHookReplacements) {
|
|
1164
|
+
onRDTHookReplace(setHookEventDispatchers);
|
|
1165
|
+
didSubscribeToHookReplacements = true;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1201
1168
|
rdtHook._instrumentationSource = options.name ?? BIPPY_INSTRUMENTATION_STRING;
|
|
1202
1169
|
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
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);
|
|
1216
|
-
|
|
1217
|
-
return toUnsubscribe(() => {
|
|
1218
|
-
if (onActive) _onActiveListeners.delete(onActive);
|
|
1219
|
-
if (onCommitFiberRoot) commitFiberRootListeners.delete(onCommitFiberRoot);
|
|
1220
|
-
if (onCommitFiberUnmount) commitFiberUnmountListeners.delete(onCommitFiberUnmount);
|
|
1221
|
-
if (onPostCommitFiberRoot) postCommitFiberRootListeners.delete(onPostCommitFiberRoot);
|
|
1222
|
-
if (onScheduleFiberRoot) scheduleFiberRootListeners.delete(onScheduleFiberRoot);
|
|
1170
|
+
setHookEventDispatchers(rdtHook);
|
|
1171
|
+
const subscription: InstrumentationSubscription = { options };
|
|
1172
|
+
instrumentationSubscriptions.add(subscription);
|
|
1173
|
+
|
|
1174
|
+
return createUnsubscribe(() => {
|
|
1175
|
+
if (options.onActive) _onActiveListeners.delete(options.onActive);
|
|
1176
|
+
instrumentationSubscriptions.delete(subscription);
|
|
1223
1177
|
});
|
|
1224
1178
|
};
|
|
1225
1179
|
|
|
@@ -1231,30 +1185,35 @@ const isFiberPropertyKey = (key: string): boolean =>
|
|
|
1231
1185
|
key.startsWith("__reactInternalInstance$") ||
|
|
1232
1186
|
key.startsWith("__reactFiber");
|
|
1233
1187
|
|
|
1234
|
-
const getLegacyRootFiber = (hostInstance:
|
|
1235
|
-
const reactRootContainer = hostInstance
|
|
1236
|
-
if (
|
|
1237
|
-
const internalRoot = reactRootContainer
|
|
1238
|
-
if (
|
|
1239
|
-
const current = internalRoot
|
|
1240
|
-
if (
|
|
1241
|
-
const child = current
|
|
1188
|
+
const getLegacyRootFiber = (hostInstance: object): Fiber | null => {
|
|
1189
|
+
const reactRootContainer = Reflect.get(hostInstance, "_reactRootContainer");
|
|
1190
|
+
if (typeof reactRootContainer !== "object" || reactRootContainer === null) return null;
|
|
1191
|
+
const internalRoot = Reflect.get(reactRootContainer, "_internalRoot");
|
|
1192
|
+
if (typeof internalRoot !== "object" || internalRoot === null) return null;
|
|
1193
|
+
const current = Reflect.get(internalRoot, "current");
|
|
1194
|
+
if (typeof current !== "object" || current === null) return null;
|
|
1195
|
+
const child = Reflect.get(current, "child");
|
|
1242
1196
|
return isValidFiber(child) ? child : null;
|
|
1243
1197
|
};
|
|
1244
1198
|
|
|
1245
|
-
const getInternalInstanceHandle = (hostInstance:
|
|
1199
|
+
const getInternalInstanceHandle = (hostInstance: object): Fiber | null => {
|
|
1246
1200
|
const internalInstanceHandle =
|
|
1247
|
-
hostInstance
|
|
1201
|
+
Reflect.get(hostInstance, "__internalInstanceHandle") ??
|
|
1202
|
+
Reflect.get(hostInstance, "_internalInstanceHandle");
|
|
1248
1203
|
return isValidFiber(internalInstanceHandle) ? internalInstanceHandle : null;
|
|
1249
1204
|
};
|
|
1250
1205
|
|
|
1251
1206
|
const getPublicHostInstance = (stateNode: unknown): unknown => {
|
|
1252
|
-
if (
|
|
1253
|
-
const canonical = stateNode
|
|
1254
|
-
if (
|
|
1255
|
-
|
|
1207
|
+
if (typeof stateNode !== "object" || stateNode === null) return stateNode;
|
|
1208
|
+
const canonical = Reflect.get(stateNode, "canonical");
|
|
1209
|
+
if (typeof canonical === "object" && canonical !== null) {
|
|
1210
|
+
const publicInstance = Reflect.get(canonical, "publicInstance");
|
|
1211
|
+
if (typeof publicInstance === "object" && publicInstance !== null) {
|
|
1212
|
+
return publicInstance;
|
|
1213
|
+
}
|
|
1256
1214
|
}
|
|
1257
|
-
|
|
1215
|
+
const nativeTag = Reflect.get(stateNode, "_nativeTag");
|
|
1216
|
+
return typeof nativeTag === "number" ? nativeTag : stateNode;
|
|
1258
1217
|
};
|
|
1259
1218
|
|
|
1260
1219
|
export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
@@ -1268,7 +1227,7 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1268
1227
|
}
|
|
1269
1228
|
}
|
|
1270
1229
|
|
|
1271
|
-
if (
|
|
1230
|
+
if (typeof hostInstance === "object" && hostInstance !== null) {
|
|
1272
1231
|
const legacyRootFiber = getLegacyRootFiber(hostInstance);
|
|
1273
1232
|
if (legacyRootFiber) return legacyRootFiber;
|
|
1274
1233
|
|
|
@@ -1276,14 +1235,14 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1276
1235
|
if (internalInstanceHandle) return internalInstanceHandle;
|
|
1277
1236
|
|
|
1278
1237
|
for (const knownKey of knownFiberPropertyKeys) {
|
|
1279
|
-
const fiber = hostInstance
|
|
1238
|
+
const fiber = Reflect.get(hostInstance, knownKey);
|
|
1280
1239
|
if (isValidFiber(fiber)) return fiber;
|
|
1281
1240
|
}
|
|
1282
1241
|
|
|
1283
1242
|
for (const key of Object.keys(hostInstance)) {
|
|
1284
1243
|
if (isFiberPropertyKey(key)) {
|
|
1285
1244
|
knownFiberPropertyKeys.add(key);
|
|
1286
|
-
const fiber = hostInstance
|
|
1245
|
+
const fiber = Reflect.get(hostInstance, key);
|
|
1287
1246
|
if (isValidFiber(fiber)) return fiber;
|
|
1288
1247
|
}
|
|
1289
1248
|
}
|
|
@@ -1307,6 +1266,17 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1307
1266
|
return null;
|
|
1308
1267
|
};
|
|
1309
1268
|
|
|
1310
|
-
export
|
|
1311
|
-
|
|
1312
|
-
|
|
1269
|
+
export {
|
|
1270
|
+
BIPPY_INSTRUMENTATION_STRING,
|
|
1271
|
+
_onActiveListeners,
|
|
1272
|
+
_renderers,
|
|
1273
|
+
getRDTHook,
|
|
1274
|
+
hasRDTHook,
|
|
1275
|
+
installRDTHook,
|
|
1276
|
+
isRealReactDevtools,
|
|
1277
|
+
onRendererInject,
|
|
1278
|
+
patchRDTHook,
|
|
1279
|
+
version,
|
|
1280
|
+
} from "./rdt-hook.js";
|
|
1281
|
+
export type { Unsubscribe } from "./rdt-hook.js";
|
|
1282
|
+
export type * from "./react-internals/index.js";
|