bippy 0.6.1-dev.b88fcb4 → 0.6.1-dev.f9e6c65
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 +159 -487
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +8 -54
- package/dist/core.d.ts +8 -54
- package/dist/core.js +1 -1
- package/dist/core2.cjs +1 -1
- package/dist/core2.d.cts +3 -3
- package/dist/core2.d.ts +3 -3
- package/dist/core2.js +1 -1
- package/dist/errors.d.cts +2 -57
- package/dist/errors.d.ts +2 -57
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +1 -1
- package/dist/install-hook-only.cjs +1 -1
- package/dist/install-hook-only.js +1 -1
- package/dist/rdt-hook.cjs +1 -1
- package/dist/rdt-hook.js +1 -1
- package/dist/source.cjs +12 -13
- package/dist/source.d.cts +77 -78
- package/dist/source.d.ts +77 -78
- package/dist/source.js +12 -13
- package/package.json +6 -3
- package/src/core.ts +101 -530
- package/src/errors.ts +0 -65
- package/src/index.ts +1 -0
- package/src/install-hook-only.ts +2 -2
- package/src/rdt-hook.ts +30 -43
- package/src/react-internals/generated/react-work-tags.ts +6 -2
- package/src/react-internals/index.ts +4 -4
- package/src/react-internals/semver.ts +2 -0
- package/src/react-internals/types.ts +0 -83
- package/src/react.ts +76 -0
- package/src/source/get-display-name-from-source.ts +44 -40
- package/src/source/get-source.ts +40 -24
- package/src/source/index.ts +2 -0
- package/src/source/inspect-hooks.ts +70 -91
- package/src/source/owner-stack.ts +60 -89
- package/src/source/parse-hook-names.ts +14 -53
- package/src/source/parse-stack.ts +14 -31
- package/src/source/renderer-dispatchers.ts +30 -0
- package/src/source/symbolication.ts +312 -111
- package/dist/index.iife.js +0 -9
- package/dist/install-hook-only.iife.js +0 -9
package/src/core.ts
CHANGED
|
@@ -3,17 +3,13 @@
|
|
|
3
3
|
import type * as React from "react";
|
|
4
4
|
|
|
5
5
|
import type {
|
|
6
|
-
ContextDependency,
|
|
7
6
|
Fiber,
|
|
8
7
|
FiberRoot,
|
|
9
8
|
HostFiber,
|
|
10
|
-
MemoizedState,
|
|
11
9
|
ReactDevToolsGlobalHook,
|
|
12
10
|
ReactRenderer,
|
|
13
11
|
} from "./react-internals/index.js";
|
|
14
12
|
|
|
15
|
-
import { BippyInstrumentationError, BippyReactDevToolsError, runWithBippyError } from "./errors.js";
|
|
16
|
-
|
|
17
13
|
import {
|
|
18
14
|
_onActiveListeners,
|
|
19
15
|
BIPPY_INSTRUMENTATION_STRING,
|
|
@@ -22,7 +18,6 @@ import {
|
|
|
22
18
|
hasRDTHook,
|
|
23
19
|
isRealReactDevtools,
|
|
24
20
|
onRDTHookReplace,
|
|
25
|
-
onRendererInject,
|
|
26
21
|
} from "./rdt-hook.js";
|
|
27
22
|
import type { Unsubscribe } from "./rdt-hook.js";
|
|
28
23
|
import {
|
|
@@ -34,44 +29,21 @@ import {
|
|
|
34
29
|
setReactWorkTagsForFiber,
|
|
35
30
|
} from "./react-internals/index.js";
|
|
36
31
|
|
|
37
|
-
export { getReactWorkTags, ReactSymbols } from "./react-internals/index.js";
|
|
38
|
-
export type { ReactWorkTagMap, ReactWorkTagVersion } from "./react-internals/index.js";
|
|
39
32
|
export {
|
|
40
33
|
BippyError,
|
|
41
|
-
BippyHookInstallationError,
|
|
42
34
|
BippyHookInspectionError,
|
|
43
|
-
BippyHookListenerError,
|
|
44
35
|
BippyHookRenderError,
|
|
45
|
-
BippyInstrumentationError,
|
|
46
|
-
BippyReactBuildError,
|
|
47
|
-
BippyReactDevToolsError,
|
|
48
36
|
BippySourceMapError,
|
|
49
37
|
BippyUnsupportedHookError,
|
|
50
38
|
} from "./errors.js";
|
|
51
39
|
|
|
52
|
-
const isObjectRecord = (value: unknown): value is Record<string, unknown> =>
|
|
53
|
-
typeof value === "object" && value !== null;
|
|
54
|
-
|
|
55
40
|
const isComponentType = (value: unknown): value is React.ComponentType<unknown> =>
|
|
56
41
|
typeof value === "function";
|
|
57
42
|
|
|
58
|
-
const getPropertyValue = (value: object, key: PropertyKey): unknown => {
|
|
59
|
-
let currentValue: object | null = value;
|
|
60
|
-
while (currentValue) {
|
|
61
|
-
const descriptor = Object.getOwnPropertyDescriptor(currentValue, key);
|
|
62
|
-
if (descriptor) {
|
|
63
|
-
if ("value" in descriptor) return descriptor.value;
|
|
64
|
-
return descriptor.get?.call(value);
|
|
65
|
-
}
|
|
66
|
-
currentValue = Object.getPrototypeOf(currentValue);
|
|
67
|
-
}
|
|
68
|
-
return undefined;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
43
|
const getTypeName = (value: object): string | null => {
|
|
72
|
-
const displayName =
|
|
44
|
+
const displayName = "displayName" in value ? value.displayName : null;
|
|
73
45
|
if (typeof displayName === "string" && displayName) return displayName;
|
|
74
|
-
const name =
|
|
46
|
+
const name = "name" in value ? value.name : null;
|
|
75
47
|
return typeof name === "string" && name ? name : null;
|
|
76
48
|
};
|
|
77
49
|
|
|
@@ -79,18 +51,8 @@ interface FiberSelector {
|
|
|
79
51
|
(node: Fiber): boolean | Promise<boolean | void> | void;
|
|
80
52
|
}
|
|
81
53
|
|
|
82
|
-
export interface FiberTimings {
|
|
83
|
-
selfTime: number;
|
|
84
|
-
totalTime: number;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
54
|
export interface RenderHandler {
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
interface ValueWrite {
|
|
92
|
-
path: string[];
|
|
93
|
-
value: unknown;
|
|
55
|
+
(fiber: Fiber, phase: RenderPhase): unknown;
|
|
94
56
|
}
|
|
95
57
|
|
|
96
58
|
/**
|
|
@@ -119,7 +81,10 @@ export const isValidFiber = (fiber: unknown): fiber is Fiber =>
|
|
|
119
81
|
"flags" in fiber;
|
|
120
82
|
|
|
121
83
|
const isFiberRoot = (fiberRoot: unknown): fiberRoot is FiberRoot =>
|
|
122
|
-
|
|
84
|
+
typeof fiberRoot === "object" &&
|
|
85
|
+
fiberRoot !== null &&
|
|
86
|
+
"current" in fiberRoot &&
|
|
87
|
+
isValidFiber(fiberRoot.current);
|
|
123
88
|
|
|
124
89
|
/**
|
|
125
90
|
* Returns `true` if fiber is a host fiber. Host fibers are DOM nodes in react-dom, `View` in react-native, etc.
|
|
@@ -168,90 +133,6 @@ export const isFiber = (maybeFiber: unknown): maybeFiber is Fiber => {
|
|
|
168
133
|
return "pendingProps" in maybeFiber && !("containerInfo" in maybeFiber);
|
|
169
134
|
};
|
|
170
135
|
|
|
171
|
-
/**
|
|
172
|
-
* Traverses up or down a {@link Fiber}'s contexts, return `true` to stop and select the current and previous context value.
|
|
173
|
-
*/
|
|
174
|
-
export const traverseContexts = (
|
|
175
|
-
fiber: Fiber,
|
|
176
|
-
selector: (
|
|
177
|
-
nextValue: ContextDependency<unknown> | null | undefined,
|
|
178
|
-
prevValue: ContextDependency<unknown> | null | undefined,
|
|
179
|
-
) => boolean | void,
|
|
180
|
-
): boolean => {
|
|
181
|
-
try {
|
|
182
|
-
const nextDependencies = fiber.dependencies;
|
|
183
|
-
const prevDependencies = fiber.alternate?.dependencies;
|
|
184
|
-
|
|
185
|
-
if (!nextDependencies || !prevDependencies) return false;
|
|
186
|
-
if (
|
|
187
|
-
typeof nextDependencies !== "object" ||
|
|
188
|
-
!("firstContext" in nextDependencies) ||
|
|
189
|
-
typeof prevDependencies !== "object" ||
|
|
190
|
-
!("firstContext" in prevDependencies)
|
|
191
|
-
) {
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
let nextContext: ContextDependency<unknown> | null | undefined = nextDependencies.firstContext;
|
|
195
|
-
let prevContext: ContextDependency<unknown> | null | undefined = prevDependencies.firstContext;
|
|
196
|
-
while (
|
|
197
|
-
(nextContext && typeof nextContext === "object" && "memoizedValue" in nextContext) ||
|
|
198
|
-
(prevContext && typeof prevContext === "object" && "memoizedValue" in prevContext)
|
|
199
|
-
) {
|
|
200
|
-
if (selector(nextContext, prevContext) === true) return true;
|
|
201
|
-
|
|
202
|
-
nextContext = nextContext?.next;
|
|
203
|
-
prevContext = prevContext?.next;
|
|
204
|
-
}
|
|
205
|
-
} catch {}
|
|
206
|
-
return false;
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Traverses up or down a {@link Fiber}'s states, return `true` to stop and select the current and previous state value. This stores both state values and effects.
|
|
211
|
-
*/
|
|
212
|
-
export const traverseState = (
|
|
213
|
-
fiber: Fiber,
|
|
214
|
-
selector: (
|
|
215
|
-
nextValue: MemoizedState | null | undefined,
|
|
216
|
-
prevValue: MemoizedState | null | undefined,
|
|
217
|
-
) => boolean | void,
|
|
218
|
-
): boolean => {
|
|
219
|
-
try {
|
|
220
|
-
let nextState: MemoizedState | null | undefined = fiber.memoizedState;
|
|
221
|
-
let prevState: MemoizedState | null | undefined = fiber.alternate?.memoizedState;
|
|
222
|
-
|
|
223
|
-
while (nextState || prevState) {
|
|
224
|
-
if (selector(nextState, prevState) === true) return true;
|
|
225
|
-
|
|
226
|
-
nextState = nextState?.next;
|
|
227
|
-
prevState = prevState?.next;
|
|
228
|
-
}
|
|
229
|
-
} catch {}
|
|
230
|
-
return false;
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Traverses up or down a {@link Fiber}'s props, return `true` to stop and select the current and previous props value.
|
|
235
|
-
*/
|
|
236
|
-
export const traverseProps = (
|
|
237
|
-
fiber: Fiber,
|
|
238
|
-
selector: (propName: string, nextValue: unknown, prevValue: unknown) => boolean | void,
|
|
239
|
-
): boolean => {
|
|
240
|
-
try {
|
|
241
|
-
const nextProps = fiber.memoizedProps;
|
|
242
|
-
const prevProps = fiber.alternate?.memoizedProps || {};
|
|
243
|
-
|
|
244
|
-
for (const propName of Object.keys(nextProps)) {
|
|
245
|
-
if (selector(propName, nextProps[propName], prevProps[propName]) === true) return true;
|
|
246
|
-
}
|
|
247
|
-
for (const propName of Object.keys(prevProps)) {
|
|
248
|
-
if (propName in nextProps) continue;
|
|
249
|
-
if (selector(propName, nextProps[propName], prevProps[propName]) === true) return true;
|
|
250
|
-
}
|
|
251
|
-
} catch {}
|
|
252
|
-
return false;
|
|
253
|
-
};
|
|
254
|
-
|
|
255
136
|
/**
|
|
256
137
|
* Returns `true` if the {@link Fiber} has rendered. Note that this does not mean the fiber has rendered in the current commit, just that it has rendered in the past.
|
|
257
138
|
*/
|
|
@@ -291,47 +172,6 @@ export const didFiberCommit = (fiber: Fiber): boolean => {
|
|
|
291
172
|
);
|
|
292
173
|
};
|
|
293
174
|
|
|
294
|
-
/**
|
|
295
|
-
* Returns all host {@link Fiber}s that have committed and rendered.
|
|
296
|
-
*/
|
|
297
|
-
export const getMutatedHostFibers = (fiber: Fiber): Fiber[] => {
|
|
298
|
-
const mutations: Fiber[] = [];
|
|
299
|
-
const stack: Fiber[] = [fiber];
|
|
300
|
-
|
|
301
|
-
while (stack.length) {
|
|
302
|
-
const node = stack.pop();
|
|
303
|
-
if (!node) continue;
|
|
304
|
-
|
|
305
|
-
if (isHostFiber(node) && didFiberCommit(node) && didFiberRender(node)) {
|
|
306
|
-
mutations.push(node);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (node.child) stack.push(node.child);
|
|
310
|
-
if (node.sibling) stack.push(node.sibling);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return mutations;
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* Returns the stack of {@link Fiber}s from the current fiber to the root fiber.
|
|
318
|
-
*
|
|
319
|
-
* @example
|
|
320
|
-
* ```ts
|
|
321
|
-
* [fiber, fiber.return, fiber.return.return, ...]
|
|
322
|
-
* ```
|
|
323
|
-
*/
|
|
324
|
-
export const getFiberStack = (fiber: Fiber): Fiber[] => {
|
|
325
|
-
const stack: Fiber[] = [];
|
|
326
|
-
let currentFiber = fiber;
|
|
327
|
-
while (currentFiber.return) {
|
|
328
|
-
stack.push(currentFiber);
|
|
329
|
-
const parentFiber = currentFiber.return;
|
|
330
|
-
currentFiber = parentFiber;
|
|
331
|
-
}
|
|
332
|
-
return stack;
|
|
333
|
-
};
|
|
334
|
-
|
|
335
175
|
/**
|
|
336
176
|
* Returns `true` if the {@link Fiber} should be filtered out during reconciliation.
|
|
337
177
|
*/
|
|
@@ -380,47 +220,6 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
380
220
|
}
|
|
381
221
|
};
|
|
382
222
|
|
|
383
|
-
/**
|
|
384
|
-
* Returns the nearest host {@link Fiber} to the current {@link Fiber}.
|
|
385
|
-
*/
|
|
386
|
-
export const getNearestHostFiber = (fiber: Fiber, ascending = false): Fiber | null => {
|
|
387
|
-
let hostFiber = traverseFiber(fiber, isHostFiber, ascending);
|
|
388
|
-
if (!hostFiber) {
|
|
389
|
-
hostFiber = traverseFiber(fiber, isHostFiber, !ascending);
|
|
390
|
-
}
|
|
391
|
-
return hostFiber;
|
|
392
|
-
};
|
|
393
|
-
|
|
394
|
-
/**
|
|
395
|
-
* Returns all host {@link Fiber}s in the tree that are associated with the current {@link Fiber}.
|
|
396
|
-
*/
|
|
397
|
-
export const getNearestHostFibers = (fiber: Fiber): Fiber[] => {
|
|
398
|
-
const hostFibers: Fiber[] = [];
|
|
399
|
-
const stack: Fiber[] = [];
|
|
400
|
-
|
|
401
|
-
if (isHostFiber(fiber)) {
|
|
402
|
-
hostFibers.push(fiber);
|
|
403
|
-
} else if (fiber.child) {
|
|
404
|
-
stack.push(fiber.child);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
while (stack.length) {
|
|
408
|
-
const currentNode = stack.pop();
|
|
409
|
-
if (!currentNode) break;
|
|
410
|
-
if (isHostFiber(currentNode)) {
|
|
411
|
-
hostFibers.push(currentNode);
|
|
412
|
-
} else if (currentNode.child) {
|
|
413
|
-
stack.push(currentNode.child);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (currentNode.sibling) {
|
|
417
|
-
stack.push(currentNode.sibling);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
return hostFibers;
|
|
422
|
-
};
|
|
423
|
-
|
|
424
223
|
/**
|
|
425
224
|
* Traverses up or down a {@link Fiber}, return `true` to stop and select a node.
|
|
426
225
|
*/
|
|
@@ -444,7 +243,17 @@ export function traverseFiber(
|
|
|
444
243
|
selector: FiberSelector,
|
|
445
244
|
ascending = false,
|
|
446
245
|
): Fiber | null | Promise<Fiber | null> {
|
|
447
|
-
|
|
246
|
+
if (!fiber) return null;
|
|
247
|
+
|
|
248
|
+
const selection = selector(fiber);
|
|
249
|
+
if (isPromiseLike<boolean | void>(selection)) {
|
|
250
|
+
return Promise.resolve(selection).then((didSelectFiber) =>
|
|
251
|
+
didSelectFiber === true ? fiber : traverseFiberChildren(fiber, selector, ascending),
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
if (selection === true) return fiber;
|
|
255
|
+
|
|
256
|
+
return traverseFiberChildren(fiber, selector, ascending);
|
|
448
257
|
}
|
|
449
258
|
|
|
450
259
|
const isPromiseLike = <Result>(value: unknown): value is PromiseLike<Result> =>
|
|
@@ -470,7 +279,7 @@ const traverseFiberSiblings = (
|
|
|
470
279
|
if (!fiber) return null;
|
|
471
280
|
|
|
472
281
|
const nextSibling = ascending ? null : fiber.sibling;
|
|
473
|
-
const match =
|
|
282
|
+
const match = traverseFiber(fiber, selector, ascending);
|
|
474
283
|
if (isPromiseLike<Fiber | null>(match)) {
|
|
475
284
|
return Promise.resolve(match).then(
|
|
476
285
|
(resolvedMatch) => resolvedMatch ?? traverseFiberSiblings(nextSibling, selector, ascending),
|
|
@@ -479,45 +288,6 @@ const traverseFiberSiblings = (
|
|
|
479
288
|
return match ?? traverseFiberSiblings(nextSibling, selector, ascending);
|
|
480
289
|
};
|
|
481
290
|
|
|
482
|
-
const traverseFiberInternal = (
|
|
483
|
-
fiber: Fiber | null,
|
|
484
|
-
selector: FiberSelector,
|
|
485
|
-
ascending: boolean,
|
|
486
|
-
): Fiber | null | Promise<Fiber | null> => {
|
|
487
|
-
if (!fiber) return null;
|
|
488
|
-
|
|
489
|
-
const selection = selector(fiber);
|
|
490
|
-
if (isPromiseLike<boolean | void>(selection)) {
|
|
491
|
-
return Promise.resolve(selection).then((didSelectFiber) =>
|
|
492
|
-
didSelectFiber === true ? fiber : traverseFiberChildren(fiber, selector, ascending),
|
|
493
|
-
);
|
|
494
|
-
}
|
|
495
|
-
if (selection === true) return fiber;
|
|
496
|
-
|
|
497
|
-
return traverseFiberChildren(fiber, selector, ascending);
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* Returns the timings of the {@link Fiber}.
|
|
502
|
-
*
|
|
503
|
-
* @example
|
|
504
|
-
* ```ts
|
|
505
|
-
* const { selfTime, totalTime } = getTimings(fiber);
|
|
506
|
-
* console.log(selfTime, totalTime);
|
|
507
|
-
* ```
|
|
508
|
-
*/
|
|
509
|
-
export const getTimings = (fiber?: Fiber | null): FiberTimings => {
|
|
510
|
-
const totalTime = fiber?.actualDuration ?? 0;
|
|
511
|
-
let selfTime = totalTime;
|
|
512
|
-
// TODO: calculate a DOM time, which is just host component summed up
|
|
513
|
-
let child = fiber?.child ?? null;
|
|
514
|
-
while (totalTime > 0 && child !== null) {
|
|
515
|
-
selfTime -= child.actualDuration ?? 0;
|
|
516
|
-
child = child.sibling;
|
|
517
|
-
}
|
|
518
|
-
return { selfTime, totalTime };
|
|
519
|
-
};
|
|
520
|
-
|
|
521
291
|
/**
|
|
522
292
|
* Returns `true` if the {@link Fiber} uses React Compiler's memo cache.
|
|
523
293
|
*/
|
|
@@ -530,8 +300,8 @@ export const hasMemoCache = (fiber: Fiber): boolean => {
|
|
|
530
300
|
*/
|
|
531
301
|
export const getType = (type: unknown): null | React.ComponentType<unknown> => {
|
|
532
302
|
if (isComponentType(type)) return type;
|
|
533
|
-
if (
|
|
534
|
-
return getType(
|
|
303
|
+
if (typeof type !== "object" || type === null) return null;
|
|
304
|
+
return getType(Reflect.get(type, "type") ?? Reflect.get(type, "render"));
|
|
535
305
|
};
|
|
536
306
|
|
|
537
307
|
/**
|
|
@@ -571,6 +341,7 @@ export const isInstrumentationActive = (): boolean => {
|
|
|
571
341
|
};
|
|
572
342
|
|
|
573
343
|
export const _fiberRoots = new Set<FiberRoot>();
|
|
344
|
+
const rootRendererIds = new WeakMap<FiberRoot, number>();
|
|
574
345
|
|
|
575
346
|
/**
|
|
576
347
|
* Returns the latest fiber (since it may be double-buffered).
|
|
@@ -590,6 +361,25 @@ export const getLatestFiber = (fiber: Fiber): Fiber => {
|
|
|
590
361
|
return fiber;
|
|
591
362
|
};
|
|
592
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Returns the renderer that owns the {@link Fiber}.
|
|
366
|
+
*/
|
|
367
|
+
export const getRenderer = (fiber: Fiber): ReactRenderer | null => {
|
|
368
|
+
if (!hasRDTHook()) return null;
|
|
369
|
+
|
|
370
|
+
let rootFiber = fiber;
|
|
371
|
+
while (rootFiber.return) {
|
|
372
|
+
rootFiber = rootFiber.return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const fiberRoot = rootFiber.stateNode;
|
|
376
|
+
if (!isFiberRoot(fiberRoot)) return null;
|
|
377
|
+
|
|
378
|
+
const rendererID = rootRendererIds.get(fiberRoot);
|
|
379
|
+
if (rendererID === undefined) return null;
|
|
380
|
+
return getRDTHook().renderers.get(rendererID) ?? null;
|
|
381
|
+
};
|
|
382
|
+
|
|
593
383
|
export type RenderPhase = "mount" | "unmount" | "update";
|
|
594
384
|
|
|
595
385
|
let nextFiberId = 0;
|
|
@@ -622,9 +412,7 @@ const mountFiberRecursively = (
|
|
|
622
412
|
let fiber: Fiber | null = firstChild;
|
|
623
413
|
|
|
624
414
|
while (fiber !== null) {
|
|
625
|
-
|
|
626
|
-
getFiberId(fiber);
|
|
627
|
-
}
|
|
415
|
+
getFiberId(fiber);
|
|
628
416
|
const shouldIncludeInTree = !shouldFilterFiber(fiber);
|
|
629
417
|
if (shouldIncludeInTree && didFiberRender(fiber)) {
|
|
630
418
|
onRender(fiber, "mount");
|
|
@@ -661,15 +449,10 @@ const updateFiberRecursively = (
|
|
|
661
449
|
onRender: RenderHandler,
|
|
662
450
|
nextFiber: Fiber,
|
|
663
451
|
prevFiber: Fiber | null,
|
|
664
|
-
parentFiber: Fiber | null,
|
|
665
452
|
): void => {
|
|
666
|
-
|
|
667
|
-
getFiberId(nextFiber);
|
|
668
|
-
}
|
|
453
|
+
getFiberId(nextFiber);
|
|
669
454
|
if (!prevFiber) return;
|
|
670
|
-
|
|
671
|
-
getFiberId(prevFiber);
|
|
672
|
-
}
|
|
455
|
+
getFiberId(prevFiber);
|
|
673
456
|
|
|
674
457
|
const isSuspense = nextFiber.tag === getReactWorkTagsForFiber(nextFiber).SuspenseComponent;
|
|
675
458
|
|
|
@@ -700,7 +483,7 @@ const updateFiberRecursively = (
|
|
|
700
483
|
const prevFallbackChildSet = prevFiber.child?.sibling ?? null;
|
|
701
484
|
|
|
702
485
|
if (nextFallbackChildSet !== null && prevFallbackChildSet !== null) {
|
|
703
|
-
updateFiberRecursively(onRender, nextFallbackChildSet, prevFallbackChildSet
|
|
486
|
+
updateFiberRecursively(onRender, nextFallbackChildSet, prevFallbackChildSet);
|
|
704
487
|
}
|
|
705
488
|
} else if (prevDidTimeout && !nextDidTimeOut) {
|
|
706
489
|
// Fallback -> Primary:
|
|
@@ -739,14 +522,7 @@ const updateFiberRecursively = (
|
|
|
739
522
|
// Schedule updates and mounts depending on whether alternates exist.
|
|
740
523
|
// We don't track deletions here because they are reported separately.
|
|
741
524
|
if (nextChild.alternate) {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
updateFiberRecursively(
|
|
745
|
-
onRender,
|
|
746
|
-
nextChild,
|
|
747
|
-
prevChild,
|
|
748
|
-
shouldIncludeInTree ? nextFiber : parentFiber,
|
|
749
|
-
);
|
|
525
|
+
updateFiberRecursively(onRender, nextChild, nextChild.alternate);
|
|
750
526
|
} else {
|
|
751
527
|
mountFiberRecursively(onRender, nextChild, false);
|
|
752
528
|
}
|
|
@@ -792,11 +568,9 @@ const unmountFiberChildrenRecursively = (onRender: RenderHandler, fiber: Fiber):
|
|
|
792
568
|
}
|
|
793
569
|
};
|
|
794
570
|
|
|
795
|
-
let commitId = 0;
|
|
796
571
|
const rootInstanceMap = new WeakMap<
|
|
797
572
|
Fiber | FiberRoot,
|
|
798
573
|
{
|
|
799
|
-
id: number;
|
|
800
574
|
prevFiber: Fiber | null;
|
|
801
575
|
}
|
|
802
576
|
>();
|
|
@@ -814,17 +588,17 @@ export const traverseRenderedFibers = (root: Fiber | FiberRoot, onRender: Render
|
|
|
814
588
|
let rootInstance = rootInstanceMap.get(root);
|
|
815
589
|
|
|
816
590
|
if (!rootInstance) {
|
|
817
|
-
rootInstance = {
|
|
591
|
+
rootInstance = { prevFiber: null };
|
|
818
592
|
rootInstanceMap.set(root, rootInstance);
|
|
819
593
|
}
|
|
820
594
|
|
|
821
595
|
const { prevFiber } = rootInstance;
|
|
822
|
-
// if fiberRoot don't have current instance, means it's been unmounted
|
|
823
596
|
if (!fiber) {
|
|
824
|
-
|
|
597
|
+
if (prevFiber) {
|
|
598
|
+
unmountFiber(onRender, prevFiber);
|
|
599
|
+
}
|
|
825
600
|
} else if (prevFiber !== null) {
|
|
826
601
|
const wasMounted =
|
|
827
|
-
prevFiber &&
|
|
828
602
|
prevFiber.memoizedState !== null &&
|
|
829
603
|
prevFiber.memoizedState.element !== null &&
|
|
830
604
|
prevFiber.memoizedState.element !== undefined &&
|
|
@@ -840,7 +614,7 @@ export const traverseRenderedFibers = (root: Fiber | FiberRoot, onRender: Render
|
|
|
840
614
|
if (!wasMounted && isMounted) {
|
|
841
615
|
mountFiberRecursively(onRender, fiber, false);
|
|
842
616
|
} else if (wasMounted && isMounted) {
|
|
843
|
-
updateFiberRecursively(onRender, fiber, fiber.alternate
|
|
617
|
+
updateFiberRecursively(onRender, fiber, fiber.alternate);
|
|
844
618
|
} else if (wasMounted && !isMounted) {
|
|
845
619
|
unmountFiber(onRender, fiber);
|
|
846
620
|
}
|
|
@@ -851,171 +625,6 @@ export const traverseRenderedFibers = (root: Fiber | FiberRoot, onRender: Render
|
|
|
851
625
|
rootInstance.prevFiber = fiber;
|
|
852
626
|
};
|
|
853
627
|
|
|
854
|
-
const overrideRenderers = new Set<ReactRenderer>();
|
|
855
|
-
let areOverrideRenderersWired = false;
|
|
856
|
-
|
|
857
|
-
const wireOverrideRenderers = (): void => {
|
|
858
|
-
if (!hasRDTHook()) return;
|
|
859
|
-
const rdtHook = getRDTHook();
|
|
860
|
-
|
|
861
|
-
setHookEventDispatchers(rdtHook);
|
|
862
|
-
for (const renderer of rdtHook.renderers.values()) {
|
|
863
|
-
overrideRenderers.add(renderer);
|
|
864
|
-
}
|
|
865
|
-
if (areOverrideRenderersWired) return;
|
|
866
|
-
areOverrideRenderersWired = true;
|
|
867
|
-
onRendererInject((renderer) => {
|
|
868
|
-
overrideRenderers.add(renderer);
|
|
869
|
-
});
|
|
870
|
-
};
|
|
871
|
-
|
|
872
|
-
const getRootRenderer = (fiber: Fiber): ReactRenderer | null => {
|
|
873
|
-
if (!hasRDTHook()) return null;
|
|
874
|
-
let hostRootFiber = fiber;
|
|
875
|
-
while (hostRootFiber.return) {
|
|
876
|
-
hostRootFiber = hostRootFiber.return;
|
|
877
|
-
}
|
|
878
|
-
const fiberRoot = hostRootFiber.stateNode;
|
|
879
|
-
if (!isFiberRoot(fiberRoot)) return null;
|
|
880
|
-
const rendererId = rootRendererIds.get(fiberRoot);
|
|
881
|
-
if (rendererId === undefined) return null;
|
|
882
|
-
return getRDTHook().renderers.get(rendererId) ?? null;
|
|
883
|
-
};
|
|
884
|
-
|
|
885
|
-
const resolveOverrideRenderers = (fiber: Fiber): ReactRenderer[] => {
|
|
886
|
-
wireOverrideRenderers();
|
|
887
|
-
const rootRenderer = getRootRenderer(fiber);
|
|
888
|
-
if (rootRenderer) return [rootRenderer];
|
|
889
|
-
return Array.from(overrideRenderers);
|
|
890
|
-
};
|
|
891
|
-
|
|
892
|
-
const applyPropsOverride = (
|
|
893
|
-
renderers: ReactRenderer[],
|
|
894
|
-
fiber: Fiber,
|
|
895
|
-
path: string[],
|
|
896
|
-
value: unknown,
|
|
897
|
-
): void => {
|
|
898
|
-
for (const renderer of renderers) {
|
|
899
|
-
try {
|
|
900
|
-
renderer.overrideProps?.(fiber, path, value);
|
|
901
|
-
} catch {}
|
|
902
|
-
}
|
|
903
|
-
};
|
|
904
|
-
|
|
905
|
-
const getHookStateDispatch = (
|
|
906
|
-
fiber: Fiber,
|
|
907
|
-
hookIndex: number,
|
|
908
|
-
): ((value: unknown) => void) | null => {
|
|
909
|
-
let hookState = fiber.memoizedState;
|
|
910
|
-
for (let currentHookIndex = 0; currentHookIndex < hookIndex; currentHookIndex++) {
|
|
911
|
-
if (!hookState?.next) return null;
|
|
912
|
-
hookState = hookState.next;
|
|
913
|
-
}
|
|
914
|
-
const queue = hookState?.queue;
|
|
915
|
-
if (!isPOJO(queue)) return null;
|
|
916
|
-
const dispatch = queue.dispatch;
|
|
917
|
-
return typeof dispatch === "function" ? (value) => dispatch(value) : null;
|
|
918
|
-
};
|
|
919
|
-
|
|
920
|
-
const findContextProviderFiber = (fiber: Fiber, contextType: unknown): Fiber | null => {
|
|
921
|
-
let currentFiber: Fiber | null = fiber;
|
|
922
|
-
while (currentFiber) {
|
|
923
|
-
const fiberType = currentFiber.type;
|
|
924
|
-
if (fiberType === contextType || fiberType?.Provider === contextType) {
|
|
925
|
-
return currentFiber;
|
|
926
|
-
}
|
|
927
|
-
currentFiber = currentFiber.return;
|
|
928
|
-
}
|
|
929
|
-
return null;
|
|
930
|
-
};
|
|
931
|
-
|
|
932
|
-
const isPOJO = (maybePOJO: unknown): maybePOJO is Record<string, unknown> => {
|
|
933
|
-
return (
|
|
934
|
-
Object.prototype.toString.call(maybePOJO) === "[object Object]" &&
|
|
935
|
-
(Object.getPrototypeOf(maybePOJO) === Object.prototype ||
|
|
936
|
-
Object.getPrototypeOf(maybePOJO) === null)
|
|
937
|
-
);
|
|
938
|
-
};
|
|
939
|
-
|
|
940
|
-
const buildPathsFromValue = (
|
|
941
|
-
maybePOJO: Record<string, unknown>,
|
|
942
|
-
basePath: string[] = [],
|
|
943
|
-
ancestors = new WeakSet<object>(),
|
|
944
|
-
): ValueWrite[] => {
|
|
945
|
-
if (!isPOJO(maybePOJO)) {
|
|
946
|
-
return [{ path: basePath, value: maybePOJO }];
|
|
947
|
-
}
|
|
948
|
-
if (ancestors.has(maybePOJO)) {
|
|
949
|
-
return [{ path: basePath, value: maybePOJO }];
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
ancestors.add(maybePOJO);
|
|
953
|
-
const paths: ValueWrite[] = [];
|
|
954
|
-
|
|
955
|
-
for (const [key, value] of Object.entries(maybePOJO)) {
|
|
956
|
-
const path = basePath.concat(key);
|
|
957
|
-
|
|
958
|
-
if (isPOJO(value)) {
|
|
959
|
-
paths.push(...buildPathsFromValue(value, path, ancestors));
|
|
960
|
-
} else {
|
|
961
|
-
paths.push({ path, value });
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
ancestors.delete(maybePOJO);
|
|
966
|
-
return paths;
|
|
967
|
-
};
|
|
968
|
-
|
|
969
|
-
const buildValueWrites = (partialValue: unknown): ValueWrite[] =>
|
|
970
|
-
isPOJO(partialValue) ? buildPathsFromValue(partialValue) : [{ path: [], value: partialValue }];
|
|
971
|
-
|
|
972
|
-
export const overrideProps = (fiber: Fiber, partialValue: Record<string, unknown>) => {
|
|
973
|
-
const renderers = resolveOverrideRenderers(fiber);
|
|
974
|
-
for (const { path, value } of buildValueWrites(partialValue)) {
|
|
975
|
-
applyPropsOverride(renderers, fiber, path, value);
|
|
976
|
-
}
|
|
977
|
-
};
|
|
978
|
-
|
|
979
|
-
export const overrideHookState = (fiber: Fiber, id: number, partialValue: unknown) => {
|
|
980
|
-
const renderers = resolveOverrideRenderers(fiber).filter((renderer) =>
|
|
981
|
-
Boolean(renderer.overrideHookState),
|
|
982
|
-
);
|
|
983
|
-
const writes = buildValueWrites(partialValue);
|
|
984
|
-
|
|
985
|
-
if (renderers.length > 0) {
|
|
986
|
-
for (const renderer of renderers) {
|
|
987
|
-
for (const { path, value } of writes) {
|
|
988
|
-
try {
|
|
989
|
-
renderer.overrideHookState?.(fiber, id, path, value);
|
|
990
|
-
} catch {}
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
// production renderers don't expose overrideHookState; dispatching through
|
|
997
|
-
// the hook's own queue still works there, but only for whole-value writes
|
|
998
|
-
// (a path write through dispatch would replace the entire hook state)
|
|
999
|
-
if (isPOJO(partialValue)) return;
|
|
1000
|
-
const dispatch = getHookStateDispatch(fiber, id);
|
|
1001
|
-
if (!dispatch) return;
|
|
1002
|
-
try {
|
|
1003
|
-
dispatch(partialValue);
|
|
1004
|
-
} catch {}
|
|
1005
|
-
};
|
|
1006
|
-
|
|
1007
|
-
export const overrideContext = (fiber: Fiber, contextType: unknown, partialValue: unknown) => {
|
|
1008
|
-
const providerFiber = findContextProviderFiber(fiber, contextType);
|
|
1009
|
-
if (!providerFiber) return;
|
|
1010
|
-
const renderers = resolveOverrideRenderers(providerFiber);
|
|
1011
|
-
for (const { path, value } of buildValueWrites(partialValue)) {
|
|
1012
|
-
applyPropsOverride(renderers, providerFiber, ["value", ...path], value);
|
|
1013
|
-
if (providerFiber.alternate) {
|
|
1014
|
-
applyPropsOverride(renderers, providerFiber.alternate, ["value", ...path], value);
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
};
|
|
1018
|
-
|
|
1019
628
|
export interface InstrumentationOptions {
|
|
1020
629
|
name?: string;
|
|
1021
630
|
onActive?: () => unknown;
|
|
@@ -1036,21 +645,6 @@ interface InstrumentationSubscription {
|
|
|
1036
645
|
|
|
1037
646
|
const instrumentationSubscriptions = new Set<InstrumentationSubscription>();
|
|
1038
647
|
|
|
1039
|
-
const runInstrumentationCallback = (
|
|
1040
|
-
instrumentationName: string,
|
|
1041
|
-
callbackName: string,
|
|
1042
|
-
callback: () => unknown,
|
|
1043
|
-
): void => {
|
|
1044
|
-
runWithBippyError(
|
|
1045
|
-
callback,
|
|
1046
|
-
(cause) => new BippyInstrumentationError(instrumentationName, callbackName, cause),
|
|
1047
|
-
);
|
|
1048
|
-
};
|
|
1049
|
-
|
|
1050
|
-
const runReactDevToolsCallback = (callbackName: string, callback: () => unknown): void => {
|
|
1051
|
-
runWithBippyError(callback, (cause) => new BippyReactDevToolsError(callbackName, cause));
|
|
1052
|
-
};
|
|
1053
|
-
|
|
1054
648
|
interface HookDispatchers {
|
|
1055
649
|
onCommitFiberRoot: ReactDevToolsGlobalHook["onCommitFiberRoot"];
|
|
1056
650
|
onCommitFiberUnmount: ReactDevToolsGlobalHook["onCommitFiberUnmount"];
|
|
@@ -1061,8 +655,6 @@ interface HookDispatchers {
|
|
|
1061
655
|
const hookDispatchers = new WeakMap<ReactDevToolsGlobalHook, Partial<HookDispatchers>>();
|
|
1062
656
|
let didSubscribeToHookReplacements = false;
|
|
1063
657
|
|
|
1064
|
-
const rootRendererIds = new WeakMap<FiberRoot, number>();
|
|
1065
|
-
|
|
1066
658
|
// each hook event is dispatched from a single re-installable wrapper. If
|
|
1067
659
|
// something overwrites the hook method (devtools, direct assignment), the
|
|
1068
660
|
// next instrument() call installs a fresh wrapper over it; a superseded
|
|
@@ -1084,9 +676,7 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
1084
676
|
didError,
|
|
1085
677
|
) => {
|
|
1086
678
|
if (prevOnCommitFiberRoot) {
|
|
1087
|
-
|
|
1088
|
-
prevOnCommitFiberRoot.call(rdtHook, rendererID, root, priority, didError),
|
|
1089
|
-
);
|
|
679
|
+
prevOnCommitFiberRoot.call(rdtHook, rendererID, root, priority, didError);
|
|
1090
680
|
}
|
|
1091
681
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberRoot !== dispatchCommitFiberRoot) return;
|
|
1092
682
|
setReactWorkTagsForFiber(root.current, rdtHook.renderers.get(rendererID));
|
|
@@ -1104,11 +694,7 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
1104
694
|
}
|
|
1105
695
|
for (const { options } of instrumentationSubscriptions) {
|
|
1106
696
|
if (options.onCommitFiberRoot) {
|
|
1107
|
-
|
|
1108
|
-
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1109
|
-
"onCommitFiberRoot",
|
|
1110
|
-
() => options.onCommitFiberRoot?.(rendererID, root, priority, didError),
|
|
1111
|
-
);
|
|
697
|
+
options.onCommitFiberRoot(rendererID, root, priority, didError);
|
|
1112
698
|
}
|
|
1113
699
|
}
|
|
1114
700
|
};
|
|
@@ -1127,20 +713,14 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
1127
713
|
) => {
|
|
1128
714
|
setReactWorkTagsForFiber(fiber, rdtHook.renderers.get(rendererID));
|
|
1129
715
|
if (prevOnCommitFiberUnmount) {
|
|
1130
|
-
|
|
1131
|
-
prevOnCommitFiberUnmount.call(rdtHook, rendererID, fiber),
|
|
1132
|
-
);
|
|
716
|
+
prevOnCommitFiberUnmount.call(rdtHook, rendererID, fiber);
|
|
1133
717
|
}
|
|
1134
718
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberUnmount !== dispatchCommitFiberUnmount) {
|
|
1135
719
|
return;
|
|
1136
720
|
}
|
|
1137
721
|
for (const { options } of instrumentationSubscriptions) {
|
|
1138
722
|
if (options.onCommitFiberUnmount) {
|
|
1139
|
-
|
|
1140
|
-
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1141
|
-
"onCommitFiberUnmount",
|
|
1142
|
-
() => options.onCommitFiberUnmount?.(rendererID, fiber),
|
|
1143
|
-
);
|
|
723
|
+
options.onCommitFiberUnmount(rendererID, fiber);
|
|
1144
724
|
}
|
|
1145
725
|
}
|
|
1146
726
|
};
|
|
@@ -1158,20 +738,14 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
1158
738
|
root,
|
|
1159
739
|
) => {
|
|
1160
740
|
if (prevOnPostCommitFiberRoot) {
|
|
1161
|
-
|
|
1162
|
-
prevOnPostCommitFiberRoot.call(rdtHook, rendererID, root),
|
|
1163
|
-
);
|
|
741
|
+
prevOnPostCommitFiberRoot.call(rdtHook, rendererID, root);
|
|
1164
742
|
}
|
|
1165
743
|
if (hookDispatchers.get(rdtHook)?.onPostCommitFiberRoot !== dispatchPostCommitFiberRoot) {
|
|
1166
744
|
return;
|
|
1167
745
|
}
|
|
1168
746
|
for (const { options } of instrumentationSubscriptions) {
|
|
1169
747
|
if (options.onPostCommitFiberRoot) {
|
|
1170
|
-
|
|
1171
|
-
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1172
|
-
"onPostCommitFiberRoot",
|
|
1173
|
-
() => options.onPostCommitFiberRoot?.(rendererID, root),
|
|
1174
|
-
);
|
|
748
|
+
options.onPostCommitFiberRoot(rendererID, root);
|
|
1175
749
|
}
|
|
1176
750
|
}
|
|
1177
751
|
};
|
|
@@ -1190,18 +764,12 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
1190
764
|
children,
|
|
1191
765
|
) => {
|
|
1192
766
|
if (prevOnScheduleFiberRoot) {
|
|
1193
|
-
|
|
1194
|
-
prevOnScheduleFiberRoot.call(rdtHook, rendererID, root, children),
|
|
1195
|
-
);
|
|
767
|
+
prevOnScheduleFiberRoot.call(rdtHook, rendererID, root, children);
|
|
1196
768
|
}
|
|
1197
769
|
if (hookDispatchers.get(rdtHook)?.onScheduleFiberRoot !== dispatchScheduleFiberRoot) return;
|
|
1198
770
|
for (const { options } of instrumentationSubscriptions) {
|
|
1199
771
|
if (options.onScheduleFiberRoot) {
|
|
1200
|
-
|
|
1201
|
-
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1202
|
-
"onScheduleFiberRoot",
|
|
1203
|
-
() => options.onScheduleFiberRoot?.(rendererID, root, children),
|
|
1204
|
-
);
|
|
772
|
+
options.onScheduleFiberRoot(rendererID, root, children);
|
|
1205
773
|
}
|
|
1206
774
|
}
|
|
1207
775
|
};
|
|
@@ -1210,6 +778,18 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
1210
778
|
}
|
|
1211
779
|
};
|
|
1212
780
|
|
|
781
|
+
const wireHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
782
|
+
if (!didSubscribeToHookReplacements) {
|
|
783
|
+
onRDTHookReplace(setHookEventDispatchers);
|
|
784
|
+
didSubscribeToHookReplacements = true;
|
|
785
|
+
}
|
|
786
|
+
setHookEventDispatchers(rdtHook);
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
if (hasRDTHook()) {
|
|
790
|
+
wireHookEventDispatchers(getRDTHook());
|
|
791
|
+
}
|
|
792
|
+
|
|
1213
793
|
/**
|
|
1214
794
|
* Instruments the DevTools hook. Each hook event is patched once and
|
|
1215
795
|
* dispatches to a set of listeners, so multiple `instrument` calls compose
|
|
@@ -1228,30 +808,15 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
1228
808
|
* unsubscribe();
|
|
1229
809
|
*/
|
|
1230
810
|
export const instrument = (options: InstrumentationOptions): Unsubscribe => {
|
|
1231
|
-
const
|
|
1232
|
-
const onActive = onActiveListener
|
|
1233
|
-
? () =>
|
|
1234
|
-
runInstrumentationCallback(
|
|
1235
|
-
options.name ?? BIPPY_INSTRUMENTATION_STRING,
|
|
1236
|
-
"onActive",
|
|
1237
|
-
onActiveListener,
|
|
1238
|
-
)
|
|
1239
|
-
: undefined;
|
|
1240
|
-
const rdtHook = getRDTHook(onActive);
|
|
1241
|
-
|
|
1242
|
-
if (!didSubscribeToHookReplacements) {
|
|
1243
|
-
onRDTHookReplace(setHookEventDispatchers);
|
|
1244
|
-
didSubscribeToHookReplacements = true;
|
|
1245
|
-
}
|
|
1246
|
-
|
|
811
|
+
const rdtHook = getRDTHook(options.onActive);
|
|
1247
812
|
rdtHook._instrumentationSource = options.name ?? BIPPY_INSTRUMENTATION_STRING;
|
|
1248
813
|
|
|
1249
|
-
|
|
814
|
+
wireHookEventDispatchers(rdtHook);
|
|
1250
815
|
const subscription: InstrumentationSubscription = { options };
|
|
1251
816
|
instrumentationSubscriptions.add(subscription);
|
|
1252
817
|
|
|
1253
818
|
return createUnsubscribe(() => {
|
|
1254
|
-
if (onActive) _onActiveListeners.delete(onActive);
|
|
819
|
+
if (options.onActive) _onActiveListeners.delete(options.onActive);
|
|
1255
820
|
instrumentationSubscriptions.delete(subscription);
|
|
1256
821
|
});
|
|
1257
822
|
};
|
|
@@ -1264,33 +829,38 @@ const isFiberPropertyKey = (key: string): boolean =>
|
|
|
1264
829
|
key.startsWith("__reactInternalInstance$") ||
|
|
1265
830
|
key.startsWith("__reactFiber");
|
|
1266
831
|
|
|
1267
|
-
const getLegacyRootFiber = (hostInstance:
|
|
1268
|
-
const reactRootContainer = hostInstance
|
|
1269
|
-
if (
|
|
1270
|
-
const internalRoot = reactRootContainer
|
|
1271
|
-
if (
|
|
1272
|
-
const current = internalRoot
|
|
1273
|
-
if (
|
|
1274
|
-
const child = current
|
|
832
|
+
const getLegacyRootFiber = (hostInstance: object): Fiber | null => {
|
|
833
|
+
const reactRootContainer = Reflect.get(hostInstance, "_reactRootContainer");
|
|
834
|
+
if (typeof reactRootContainer !== "object" || reactRootContainer === null) return null;
|
|
835
|
+
const internalRoot = Reflect.get(reactRootContainer, "_internalRoot");
|
|
836
|
+
if (typeof internalRoot !== "object" || internalRoot === null) return null;
|
|
837
|
+
const current = Reflect.get(internalRoot, "current");
|
|
838
|
+
if (typeof current !== "object" || current === null) return null;
|
|
839
|
+
const child = Reflect.get(current, "child");
|
|
1275
840
|
return isValidFiber(child) ? child : null;
|
|
1276
841
|
};
|
|
1277
842
|
|
|
1278
|
-
const getInternalInstanceHandle = (hostInstance:
|
|
843
|
+
const getInternalInstanceHandle = (hostInstance: object): Fiber | null => {
|
|
1279
844
|
const internalInstanceHandle =
|
|
1280
|
-
hostInstance
|
|
845
|
+
Reflect.get(hostInstance, "__internalInstanceHandle") ??
|
|
846
|
+
Reflect.get(hostInstance, "_internalInstanceHandle");
|
|
1281
847
|
return isValidFiber(internalInstanceHandle) ? internalInstanceHandle : null;
|
|
1282
848
|
};
|
|
1283
849
|
|
|
1284
850
|
const getPublicHostInstance = (stateNode: unknown): unknown => {
|
|
1285
|
-
if (
|
|
1286
|
-
const canonical = stateNode
|
|
1287
|
-
if (
|
|
1288
|
-
|
|
851
|
+
if (typeof stateNode !== "object" || stateNode === null) return stateNode;
|
|
852
|
+
const canonical = Reflect.get(stateNode, "canonical");
|
|
853
|
+
if (typeof canonical === "object" && canonical !== null) {
|
|
854
|
+
const publicInstance = Reflect.get(canonical, "publicInstance");
|
|
855
|
+
if (typeof publicInstance === "object" && publicInstance !== null) {
|
|
856
|
+
return publicInstance;
|
|
857
|
+
}
|
|
1289
858
|
}
|
|
1290
|
-
|
|
859
|
+
const nativeTag = Reflect.get(stateNode, "_nativeTag");
|
|
860
|
+
return typeof nativeTag === "number" ? nativeTag : stateNode;
|
|
1291
861
|
};
|
|
1292
862
|
|
|
1293
|
-
export const
|
|
863
|
+
export const getFiber = <T>(hostInstance: T): Fiber | null => {
|
|
1294
864
|
const rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
1295
865
|
if (rdtHook?.renderers) {
|
|
1296
866
|
for (const renderer of rdtHook.renderers.values()) {
|
|
@@ -1301,7 +871,7 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1301
871
|
}
|
|
1302
872
|
}
|
|
1303
873
|
|
|
1304
|
-
if (
|
|
874
|
+
if (typeof hostInstance === "object" && hostInstance !== null) {
|
|
1305
875
|
const legacyRootFiber = getLegacyRootFiber(hostInstance);
|
|
1306
876
|
if (legacyRootFiber) return legacyRootFiber;
|
|
1307
877
|
|
|
@@ -1309,14 +879,14 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1309
879
|
if (internalInstanceHandle) return internalInstanceHandle;
|
|
1310
880
|
|
|
1311
881
|
for (const knownKey of knownFiberPropertyKeys) {
|
|
1312
|
-
const fiber = hostInstance
|
|
882
|
+
const fiber = Reflect.get(hostInstance, knownKey);
|
|
1313
883
|
if (isValidFiber(fiber)) return fiber;
|
|
1314
884
|
}
|
|
1315
885
|
|
|
1316
886
|
for (const key of Object.keys(hostInstance)) {
|
|
1317
887
|
if (isFiberPropertyKey(key)) {
|
|
1318
888
|
knownFiberPropertyKeys.add(key);
|
|
1319
|
-
const fiber = hostInstance
|
|
889
|
+
const fiber = Reflect.get(hostInstance, key);
|
|
1320
890
|
if (isValidFiber(fiber)) return fiber;
|
|
1321
891
|
}
|
|
1322
892
|
}
|
|
@@ -1340,6 +910,8 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1340
910
|
return null;
|
|
1341
911
|
};
|
|
1342
912
|
|
|
913
|
+
export const getFiberFromHostInstance = getFiber;
|
|
914
|
+
|
|
1343
915
|
export {
|
|
1344
916
|
BIPPY_INSTRUMENTATION_STRING,
|
|
1345
917
|
_onActiveListeners,
|
|
@@ -1350,8 +922,7 @@ export {
|
|
|
1350
922
|
isRealReactDevtools,
|
|
1351
923
|
onRendererInject,
|
|
1352
924
|
patchRDTHook,
|
|
1353
|
-
safelyInstallRDTHook,
|
|
1354
925
|
version,
|
|
1355
926
|
} from "./rdt-hook.js";
|
|
1356
927
|
export type { Unsubscribe } from "./rdt-hook.js";
|
|
1357
|
-
export
|
|
928
|
+
export * from "./react-internals/index.js";
|