bippy 0.6.1-dev.d7876ea → 0.6.1-dev.f9a65c0

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.
Files changed (50) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +211 -445
  3. package/dist/core.cjs +1 -1
  4. package/dist/core.d.cts +25 -75
  5. package/dist/core.d.ts +25 -75
  6. package/dist/core.js +1 -1
  7. package/dist/core2.cjs +1 -1
  8. package/dist/core2.d.cts +11 -3
  9. package/dist/core2.d.ts +11 -3
  10. package/dist/core2.js +1 -1
  11. package/dist/errors.d.cts +33 -59
  12. package/dist/errors.d.ts +33 -59
  13. package/dist/index.cjs +1 -1
  14. package/dist/index.d.cts +14 -3
  15. package/dist/index.d.ts +14 -3
  16. package/dist/index.js +1 -1
  17. package/dist/install-hook-only.cjs +1 -1
  18. package/dist/install-hook-only.d.cts +8 -0
  19. package/dist/install-hook-only.d.ts +8 -0
  20. package/dist/install-hook-only.js +1 -1
  21. package/dist/rdt-hook.cjs +1 -1
  22. package/dist/rdt-hook.js +1 -1
  23. package/dist/source.cjs +12 -13
  24. package/dist/source.d.cts +85 -77
  25. package/dist/source.d.ts +85 -77
  26. package/dist/source.js +12 -13
  27. package/package.json +6 -3
  28. package/src/core.ts +146 -579
  29. package/src/errors.ts +0 -65
  30. package/src/index.ts +1 -0
  31. package/src/install-hook-only.ts +2 -2
  32. package/src/rdt-hook.ts +39 -45
  33. package/src/{generated/react-work-tags.js → react-internals/generated/react-work-tags.ts} +85 -7
  34. package/src/{react-internals.ts → react-internals/index.ts} +6 -4
  35. package/src/{semver.ts → react-internals/semver.ts} +2 -0
  36. package/src/{types.ts → react-internals/types.ts} +1 -84
  37. package/src/react.ts +76 -0
  38. package/src/source/get-display-name-from-source.ts +44 -40
  39. package/src/source/get-source.ts +42 -26
  40. package/src/source/index.ts +2 -0
  41. package/src/source/inspect-hooks.ts +74 -96
  42. package/src/source/owner-stack.ts +66 -91
  43. package/src/source/parse-hook-names.ts +14 -53
  44. package/src/source/parse-stack.ts +14 -31
  45. package/src/source/renderer-dispatchers.ts +30 -0
  46. package/src/source/symbolication.ts +421 -108
  47. package/dist/index.iife.js +0 -9
  48. package/dist/install-hook-only.iife.js +0 -9
  49. package/src/generated/react-work-tags.d.ts +0 -261
  50. package/src/unsubscribe.ts +0 -17
package/src/core.ts CHANGED
@@ -3,26 +3,23 @@
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
- } from "./types.js";
14
-
15
- import { BippyInstrumentationError, BippyReactDevToolsError, runWithBippyError } from "./errors.js";
11
+ } from "./react-internals/index.js";
16
12
 
17
13
  import {
18
14
  _onActiveListeners,
19
15
  BIPPY_INSTRUMENTATION_STRING,
16
+ createUnsubscribe,
20
17
  getRDTHook,
21
18
  hasRDTHook,
22
19
  isRealReactDevtools,
23
20
  onRDTHookReplace,
24
- onRendererInject,
25
21
  } from "./rdt-hook.js";
22
+ import type { Unsubscribe } from "./rdt-hook.js";
26
23
  import {
27
24
  getReactWorkTagsForFiber,
28
25
  MutationMask,
@@ -30,47 +27,23 @@ import {
30
27
  ReactFiberFlags,
31
28
  ReactSymbols,
32
29
  setReactWorkTagsForFiber,
33
- } from "./react-internals.js";
34
- import { toUnsubscribe, type Unsubscribe } from "./unsubscribe.js";
30
+ } from "./react-internals/index.js";
35
31
 
36
- export { getReactWorkTags, ReactSymbols } from "./react-internals.js";
37
- export type { ReactWorkTagMap, ReactWorkTagVersion } from "./react-internals.js";
38
32
  export {
39
33
  BippyError,
40
- BippyHookInstallationError,
41
34
  BippyHookInspectionError,
42
- BippyHookListenerError,
43
35
  BippyHookRenderError,
44
- BippyInstrumentationError,
45
- BippyReactBuildError,
46
- BippyReactDevToolsError,
47
36
  BippySourceMapError,
48
37
  BippyUnsupportedHookError,
49
38
  } from "./errors.js";
50
39
 
51
- const isObjectRecord = (value: unknown): value is Record<string, unknown> =>
52
- typeof value === "object" && value !== null;
53
-
54
40
  const isComponentType = (value: unknown): value is React.ComponentType<unknown> =>
55
41
  typeof value === "function";
56
42
 
57
- const getPropertyValue = (value: object, key: PropertyKey): unknown => {
58
- let currentValue: object | null = value;
59
- while (currentValue) {
60
- const descriptor = Object.getOwnPropertyDescriptor(currentValue, key);
61
- if (descriptor) {
62
- if ("value" in descriptor) return descriptor.value;
63
- return descriptor.get?.call(value);
64
- }
65
- currentValue = Object.getPrototypeOf(currentValue);
66
- }
67
- return undefined;
68
- };
69
-
70
43
  const getTypeName = (value: object): string | null => {
71
- const displayName = getPropertyValue(value, "displayName");
44
+ const displayName = "displayName" in value ? value.displayName : null;
72
45
  if (typeof displayName === "string" && displayName) return displayName;
73
- const name = getPropertyValue(value, "name");
46
+ const name = "name" in value ? value.name : null;
74
47
  return typeof name === "string" && name ? name : null;
75
48
  };
76
49
 
@@ -78,18 +51,8 @@ interface FiberSelector {
78
51
  (node: Fiber): boolean | Promise<boolean | void> | void;
79
52
  }
80
53
 
81
- export interface FiberTimings {
82
- selfTime: number;
83
- totalTime: number;
84
- }
85
-
86
54
  export interface RenderHandler {
87
- <State>(fiber: Fiber, phase: RenderPhase, state?: State): unknown;
88
- }
89
-
90
- interface ValueWrite {
91
- path: string[];
92
- value: unknown;
55
+ (fiber: Fiber, phase: RenderPhase): unknown;
93
56
  }
94
57
 
95
58
  /**
@@ -101,14 +64,13 @@ export const isValidElement = (element: unknown): element is React.ReactElement
101
64
  typeof element === "object" &&
102
65
  element !== null &&
103
66
  "$$typeof" in element &&
104
- [ReactSymbols.LEGACY_ELEMENT_SYMBOL_STRING, ReactSymbols.ELEMENT_SYMBOL_STRING].includes(
105
- String(element.$$typeof),
106
- );
67
+ (String(element.$$typeof) === ReactSymbols.LEGACY_ELEMENT_SYMBOL_STRING ||
68
+ String(element.$$typeof) === ReactSymbols.ELEMENT_SYMBOL_STRING);
107
69
 
108
70
  /**
109
71
  * Returns `true` if object is a React Fiber.
110
72
  */
111
- export const isValidFiber = (fiber: unknown): fiber is Fiber =>
73
+ export const isFiber = (fiber: unknown): fiber is Fiber =>
112
74
  typeof fiber === "object" &&
113
75
  fiber !== null &&
114
76
  "tag" in fiber &&
@@ -118,6 +80,12 @@ export const isValidFiber = (fiber: unknown): fiber is Fiber =>
118
80
  "sibling" in fiber &&
119
81
  "flags" in fiber;
120
82
 
83
+ const isFiberRoot = (fiberRoot: unknown): fiberRoot is FiberRoot =>
84
+ typeof fiberRoot === "object" &&
85
+ fiberRoot !== null &&
86
+ "current" in fiberRoot &&
87
+ isFiber(fiberRoot.current);
88
+
121
89
  /**
122
90
  * Returns `true` if fiber is a host fiber. Host fibers are DOM nodes in react-dom, `View` in react-native, etc.
123
91
  *
@@ -155,100 +123,6 @@ export const isCompositeFiber = (fiber: Fiber): boolean => {
155
123
  }
156
124
  };
157
125
 
158
- /**
159
- * Returns `true` if the object is a {@link Fiber}
160
- */
161
- export const isFiber = (maybeFiber: unknown): maybeFiber is Fiber => {
162
- if (!maybeFiber || typeof maybeFiber !== "object") return false;
163
- // this is a fast check. pendingProps will ALWAYS exist in fiber
164
- // `containerInfo` is in FiberRootNode, not FiberNode
165
- return "pendingProps" in maybeFiber && !("containerInfo" in maybeFiber);
166
- };
167
-
168
- /**
169
- * Traverses up or down a {@link Fiber}'s contexts, return `true` to stop and select the current and previous context value.
170
- */
171
- export const traverseContexts = (
172
- fiber: Fiber,
173
- selector: (
174
- nextValue: ContextDependency<unknown> | null | undefined,
175
- prevValue: ContextDependency<unknown> | null | undefined,
176
- ) => boolean | void,
177
- ): boolean => {
178
- try {
179
- const nextDependencies = fiber.dependencies;
180
- const prevDependencies = fiber.alternate?.dependencies;
181
-
182
- if (!nextDependencies || !prevDependencies) return false;
183
- if (
184
- typeof nextDependencies !== "object" ||
185
- !("firstContext" in nextDependencies) ||
186
- typeof prevDependencies !== "object" ||
187
- !("firstContext" in prevDependencies)
188
- ) {
189
- return false;
190
- }
191
- let nextContext: ContextDependency<unknown> | null | undefined = nextDependencies.firstContext;
192
- let prevContext: ContextDependency<unknown> | null | undefined = prevDependencies.firstContext;
193
- while (
194
- (nextContext && typeof nextContext === "object" && "memoizedValue" in nextContext) ||
195
- (prevContext && typeof prevContext === "object" && "memoizedValue" in prevContext)
196
- ) {
197
- if (selector(nextContext, prevContext) === true) return true;
198
-
199
- nextContext = nextContext?.next;
200
- prevContext = prevContext?.next;
201
- }
202
- } catch {}
203
- return false;
204
- };
205
-
206
- /**
207
- * 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.
208
- */
209
- export const traverseState = (
210
- fiber: Fiber,
211
- selector: (
212
- nextValue: MemoizedState | null | undefined,
213
- prevValue: MemoizedState | null | undefined,
214
- ) => boolean | void,
215
- ): boolean => {
216
- try {
217
- let nextState: MemoizedState | null | undefined = fiber.memoizedState;
218
- let prevState: MemoizedState | null | undefined = fiber.alternate?.memoizedState;
219
-
220
- while (nextState || prevState) {
221
- if (selector(nextState, prevState) === true) return true;
222
-
223
- nextState = nextState?.next;
224
- prevState = prevState?.next;
225
- }
226
- } catch {}
227
- return false;
228
- };
229
-
230
- /**
231
- * Traverses up or down a {@link Fiber}'s props, return `true` to stop and select the current and previous props value.
232
- */
233
- export const traverseProps = (
234
- fiber: Fiber,
235
- selector: (propName: string, nextValue: unknown, prevValue: unknown) => boolean | void,
236
- ): boolean => {
237
- try {
238
- const nextProps = fiber.memoizedProps;
239
- const prevProps = fiber.alternate?.memoizedProps || {};
240
-
241
- for (const propName of Object.keys(nextProps)) {
242
- if (selector(propName, nextProps[propName], prevProps[propName]) === true) return true;
243
- }
244
- for (const propName of Object.keys(prevProps)) {
245
- if (propName in nextProps) continue;
246
- if (selector(propName, nextProps[propName], prevProps[propName]) === true) return true;
247
- }
248
- } catch {}
249
- return false;
250
- };
251
-
252
126
  /**
253
127
  * 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.
254
128
  */
@@ -288,47 +162,6 @@ export const didFiberCommit = (fiber: Fiber): boolean => {
288
162
  );
289
163
  };
290
164
 
291
- /**
292
- * Returns all host {@link Fiber}s that have committed and rendered.
293
- */
294
- export const getMutatedHostFibers = (fiber: Fiber): Fiber[] => {
295
- const mutations: Fiber[] = [];
296
- const stack: Fiber[] = [fiber];
297
-
298
- while (stack.length) {
299
- const node = stack.pop();
300
- if (!node) continue;
301
-
302
- if (isHostFiber(node) && didFiberCommit(node) && didFiberRender(node)) {
303
- mutations.push(node);
304
- }
305
-
306
- if (node.child) stack.push(node.child);
307
- if (node.sibling) stack.push(node.sibling);
308
- }
309
-
310
- return mutations;
311
- };
312
-
313
- /**
314
- * Returns the stack of {@link Fiber}s from the current fiber to the root fiber.
315
- *
316
- * @example
317
- * ```ts
318
- * [fiber, fiber.return, fiber.return.return, ...]
319
- * ```
320
- */
321
- export const getFiberStack = (fiber: Fiber): Fiber[] => {
322
- const stack: Fiber[] = [];
323
- let currentFiber = fiber;
324
- while (currentFiber.return) {
325
- stack.push(currentFiber);
326
- const parentFiber = currentFiber.return;
327
- currentFiber = parentFiber;
328
- }
329
- return stack;
330
- };
331
-
332
165
  /**
333
166
  * Returns `true` if the {@link Fiber} should be filtered out during reconciliation.
334
167
  */
@@ -377,47 +210,6 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
377
210
  }
378
211
  };
379
212
 
380
- /**
381
- * Returns the nearest host {@link Fiber} to the current {@link Fiber}.
382
- */
383
- export const getNearestHostFiber = (fiber: Fiber, ascending = false): Fiber | null => {
384
- let hostFiber = traverseFiber(fiber, isHostFiber, ascending);
385
- if (!hostFiber) {
386
- hostFiber = traverseFiber(fiber, isHostFiber, !ascending);
387
- }
388
- return hostFiber;
389
- };
390
-
391
- /**
392
- * Returns all host {@link Fiber}s in the tree that are associated with the current {@link Fiber}.
393
- */
394
- export const getNearestHostFibers = (fiber: Fiber): Fiber[] => {
395
- const hostFibers: Fiber[] = [];
396
- const stack: Fiber[] = [];
397
-
398
- if (isHostFiber(fiber)) {
399
- hostFibers.push(fiber);
400
- } else if (fiber.child) {
401
- stack.push(fiber.child);
402
- }
403
-
404
- while (stack.length) {
405
- const currentNode = stack.pop();
406
- if (!currentNode) break;
407
- if (isHostFiber(currentNode)) {
408
- hostFibers.push(currentNode);
409
- } else if (currentNode.child) {
410
- stack.push(currentNode.child);
411
- }
412
-
413
- if (currentNode.sibling) {
414
- stack.push(currentNode.sibling);
415
- }
416
- }
417
-
418
- return hostFibers;
419
- };
420
-
421
213
  /**
422
214
  * Traverses up or down a {@link Fiber}, return `true` to stop and select a node.
423
215
  */
@@ -431,6 +223,11 @@ export function traverseFiber(
431
223
  selector: (node: Fiber) => Promise<boolean | void>,
432
224
  ascending?: boolean,
433
225
  ): Promise<Fiber | null>;
226
+ export function traverseFiber(
227
+ fiber: Fiber | null,
228
+ selector: FiberSelector,
229
+ ascending?: boolean,
230
+ ): Fiber | null | Promise<Fiber | null>;
434
231
  export function traverseFiber(
435
232
  fiber: Fiber | null,
436
233
  selector: FiberSelector,
@@ -438,89 +235,47 @@ export function traverseFiber(
438
235
  ): Fiber | null | Promise<Fiber | null> {
439
236
  if (!fiber) return null;
440
237
 
441
- const firstResult = selector(fiber);
442
- if (firstResult instanceof Promise) {
443
- return (async () => {
444
- if ((await firstResult) === true) return fiber;
445
-
446
- let child = ascending ? fiber.return : fiber.child;
447
- while (child) {
448
- const match = await traverseFiberAsync(child, selector, ascending);
449
- if (match) return match;
450
- child = ascending ? null : child.sibling;
451
- }
452
- return null;
453
- })();
238
+ const selection = selector(fiber);
239
+ if (isPromiseLike<boolean | void>(selection)) {
240
+ return Promise.resolve(selection).then((didSelectFiber) =>
241
+ didSelectFiber === true ? fiber : traverseFiberChildren(fiber, selector, ascending),
242
+ );
454
243
  }
244
+ if (selection === true) return fiber;
455
245
 
456
- if (firstResult === true) return fiber;
457
-
458
- let child = ascending ? fiber.return : fiber.child;
459
- while (child) {
460
- const match = traverseFiberSync(child, selector, ascending);
461
- if (match) return match;
462
- child = ascending ? null : child.sibling;
463
- }
464
- return null;
246
+ return traverseFiberChildren(fiber, selector, ascending);
465
247
  }
466
248
 
467
- const traverseFiberSync = (
468
- fiber: Fiber | null,
469
- selector: FiberSelector,
470
- ascending = false,
471
- ): Fiber | null => {
472
- if (!fiber) return null;
473
- const selection = selector(fiber);
474
- if (selection instanceof Promise) return null;
475
- if (selection === true) return fiber;
476
-
477
- let child = ascending ? fiber.return : fiber.child;
478
- while (child) {
479
- const match = traverseFiberSync(child, selector, ascending);
480
- if (match) return match;
249
+ const isPromiseLike = <Result>(value: unknown): value is PromiseLike<Result> =>
250
+ (typeof value === "object" || typeof value === "function") &&
251
+ value !== null &&
252
+ "then" in value &&
253
+ typeof value.then === "function";
481
254
 
482
- child = ascending ? null : child.sibling;
483
- }
484
- return null;
255
+ const traverseFiberChildren = (
256
+ fiber: Fiber,
257
+ selector: FiberSelector,
258
+ ascending: boolean,
259
+ ): Fiber | null | Promise<Fiber | null> => {
260
+ const firstChild = ascending ? fiber.return : fiber.child;
261
+ return traverseFiberSiblings(firstChild, selector, ascending);
485
262
  };
486
263
 
487
- const traverseFiberAsync = async (
264
+ const traverseFiberSiblings = (
488
265
  fiber: Fiber | null,
489
266
  selector: FiberSelector,
490
- ascending = false,
491
- ): Promise<Fiber | null> => {
267
+ ascending: boolean,
268
+ ): Fiber | null | Promise<Fiber | null> => {
492
269
  if (!fiber) return null;
493
- if ((await selector(fiber)) === true) return fiber;
494
-
495
- let child = ascending ? fiber.return : fiber.child;
496
- while (child) {
497
- const match = await traverseFiberAsync(child, selector, ascending);
498
- if (match) return match;
499
270
 
500
- child = ascending ? null : child.sibling;
271
+ const nextSibling = ascending ? null : fiber.sibling;
272
+ const match = traverseFiber(fiber, selector, ascending);
273
+ if (isPromiseLike<Fiber | null>(match)) {
274
+ return Promise.resolve(match).then(
275
+ (resolvedMatch) => resolvedMatch ?? traverseFiberSiblings(nextSibling, selector, ascending),
276
+ );
501
277
  }
502
- return null;
503
- };
504
-
505
- /**
506
- * Returns the timings of the {@link Fiber}.
507
- *
508
- * @example
509
- * ```ts
510
- * const { selfTime, totalTime } = getTimings(fiber);
511
- * console.log(selfTime, totalTime);
512
- * ```
513
- */
514
- export const getTimings = (fiber?: Fiber | null): FiberTimings => {
515
- const totalTime = fiber?.actualDuration ?? 0;
516
- let selfTime = totalTime;
517
- // TODO: calculate a DOM time, which is just host component summed up
518
- let child = fiber?.child ?? null;
519
- while (totalTime > 0 && child !== null) {
520
- selfTime -= child.actualDuration ?? 0;
521
- child = child.sibling;
522
- }
523
- return { selfTime, totalTime };
278
+ return match ?? traverseFiberSiblings(nextSibling, selector, ascending);
524
279
  };
525
280
 
526
281
  /**
@@ -535,8 +290,8 @@ export const hasMemoCache = (fiber: Fiber): boolean => {
535
290
  */
536
291
  export const getType = (type: unknown): null | React.ComponentType<unknown> => {
537
292
  if (isComponentType(type)) return type;
538
- if (!isObjectRecord(type)) return null;
539
- return getType(type.type ?? type.render);
293
+ if (typeof type !== "object" || type === null) return null;
294
+ return getType(Reflect.get(type, "type") ?? Reflect.get(type, "render"));
540
295
  };
541
296
 
542
297
  /**
@@ -576,6 +331,7 @@ export const isInstrumentationActive = (): boolean => {
576
331
  };
577
332
 
578
333
  export const _fiberRoots = new Set<FiberRoot>();
334
+ const rootRendererIds = new WeakMap<FiberRoot, number>();
579
335
 
580
336
  /**
581
337
  * Returns the latest fiber (since it may be double-buffered).
@@ -588,13 +344,32 @@ export const getLatestFiber = (fiber: Fiber): Fiber => {
588
344
  }
589
345
  for (const root of _fiberRoots) {
590
346
  const latestFiber = traverseFiber(root.current, (innerFiber) => {
591
- if (innerFiber === fiber) return true;
347
+ if (innerFiber === fiber || innerFiber === alternate) return true;
592
348
  });
593
349
  if (latestFiber) return latestFiber;
594
350
  }
595
351
  return fiber;
596
352
  };
597
353
 
354
+ /**
355
+ * Returns the renderer that owns the {@link Fiber}.
356
+ */
357
+ export const getRenderer = (fiber: Fiber): ReactRenderer | null => {
358
+ if (!hasRDTHook()) return null;
359
+
360
+ let rootFiber = fiber;
361
+ while (rootFiber.return) {
362
+ rootFiber = rootFiber.return;
363
+ }
364
+
365
+ const fiberRoot = rootFiber.stateNode;
366
+ if (!isFiberRoot(fiberRoot)) return null;
367
+
368
+ const rendererID = rootRendererIds.get(fiberRoot);
369
+ if (rendererID === undefined) return null;
370
+ return getRDTHook().renderers.get(rendererID) ?? null;
371
+ };
372
+
598
373
  export type RenderPhase = "mount" | "unmount" | "update";
599
374
 
600
375
  let nextFiberId = 0;
@@ -602,6 +377,9 @@ const fiberIdMap = new WeakMap<Fiber, number>();
602
377
 
603
378
  export const setFiberId = (fiber: Fiber, fiberId: number = nextFiberId++): void => {
604
379
  fiberIdMap.set(fiber, fiberId);
380
+ if (Number.isSafeInteger(fiberId) && fiberId >= nextFiberId) {
381
+ nextFiberId = fiberId + 1;
382
+ }
605
383
  };
606
384
 
607
385
  export const getFiberId = (fiber: Fiber): number => {
@@ -624,9 +402,7 @@ const mountFiberRecursively = (
624
402
  let fiber: Fiber | null = firstChild;
625
403
 
626
404
  while (fiber !== null) {
627
- if (!fiberIdMap.has(fiber)) {
628
- getFiberId(fiber);
629
- }
405
+ getFiberId(fiber);
630
406
  const shouldIncludeInTree = !shouldFilterFiber(fiber);
631
407
  if (shouldIncludeInTree && didFiberRender(fiber)) {
632
408
  onRender(fiber, "mount");
@@ -662,16 +438,11 @@ const mountFiberRecursively = (
662
438
  const updateFiberRecursively = (
663
439
  onRender: RenderHandler,
664
440
  nextFiber: Fiber,
665
- prevFiber: Fiber,
666
- parentFiber: Fiber | null,
441
+ prevFiber: Fiber | null,
667
442
  ): void => {
668
- if (!fiberIdMap.has(nextFiber)) {
669
- getFiberId(nextFiber);
670
- }
443
+ getFiberId(nextFiber);
671
444
  if (!prevFiber) return;
672
- if (!fiberIdMap.has(prevFiber)) {
673
- getFiberId(prevFiber);
674
- }
445
+ getFiberId(prevFiber);
675
446
 
676
447
  const isSuspense = nextFiber.tag === getReactWorkTagsForFiber(nextFiber).SuspenseComponent;
677
448
 
@@ -702,7 +473,7 @@ const updateFiberRecursively = (
702
473
  const prevFallbackChildSet = prevFiber.child?.sibling ?? null;
703
474
 
704
475
  if (nextFallbackChildSet !== null && prevFallbackChildSet !== null) {
705
- updateFiberRecursively(onRender, nextFallbackChildSet, prevFallbackChildSet, nextFiber);
476
+ updateFiberRecursively(onRender, nextFallbackChildSet, prevFallbackChildSet);
706
477
  }
707
478
  } else if (prevDidTimeout && !nextDidTimeOut) {
708
479
  // Fallback -> Primary:
@@ -741,14 +512,7 @@ const updateFiberRecursively = (
741
512
  // Schedule updates and mounts depending on whether alternates exist.
742
513
  // We don't track deletions here because they are reported separately.
743
514
  if (nextChild.alternate) {
744
- const prevChild = nextChild.alternate;
745
-
746
- updateFiberRecursively(
747
- onRender,
748
- nextChild,
749
- prevChild,
750
- shouldIncludeInTree ? nextFiber : parentFiber,
751
- );
515
+ updateFiberRecursively(onRender, nextChild, nextChild.alternate);
752
516
  } else {
753
517
  mountFiberRecursively(onRender, nextChild, false);
754
518
  }
@@ -794,11 +558,9 @@ const unmountFiberChildrenRecursively = (onRender: RenderHandler, fiber: Fiber):
794
558
  }
795
559
  };
796
560
 
797
- let commitId = 0;
798
561
  const rootInstanceMap = new WeakMap<
799
- FiberRoot,
562
+ Fiber | FiberRoot,
800
563
  {
801
- id: number;
802
564
  prevFiber: Fiber | null;
803
565
  }
804
566
  >();
@@ -810,23 +572,23 @@ const rootInstanceMap = new WeakMap<
810
572
  * console.log(phase)
811
573
  * })
812
574
  */
813
- export const traverseRenderedFibers = (root: FiberRoot, onRender: RenderHandler): void => {
575
+ export const traverseRenderedFibers = (root: Fiber | FiberRoot, onRender: RenderHandler): void => {
814
576
  const fiber = "current" in root ? root.current : root;
815
577
 
816
578
  let rootInstance = rootInstanceMap.get(root);
817
579
 
818
580
  if (!rootInstance) {
819
- rootInstance = { id: commitId++, prevFiber: null };
581
+ rootInstance = { prevFiber: null };
820
582
  rootInstanceMap.set(root, rootInstance);
821
583
  }
822
584
 
823
585
  const { prevFiber } = rootInstance;
824
- // if fiberRoot don't have current instance, means it's been unmounted
825
586
  if (!fiber) {
826
- unmountFiber(onRender, fiber);
587
+ if (prevFiber) {
588
+ unmountFiber(onRender, prevFiber);
589
+ }
827
590
  } else if (prevFiber !== null) {
828
591
  const wasMounted =
829
- prevFiber &&
830
592
  prevFiber.memoizedState !== null &&
831
593
  prevFiber.memoizedState.element !== null &&
832
594
  prevFiber.memoizedState.element !== undefined &&
@@ -842,7 +604,7 @@ export const traverseRenderedFibers = (root: FiberRoot, onRender: RenderHandler)
842
604
  if (!wasMounted && isMounted) {
843
605
  mountFiberRecursively(onRender, fiber, false);
844
606
  } else if (wasMounted && isMounted) {
845
- updateFiberRecursively(onRender, fiber, fiber.alternate, null);
607
+ updateFiberRecursively(onRender, fiber, fiber.alternate);
846
608
  } else if (wasMounted && !isMounted) {
847
609
  unmountFiber(onRender, fiber);
848
610
  }
@@ -853,164 +615,6 @@ export const traverseRenderedFibers = (root: FiberRoot, onRender: RenderHandler)
853
615
  rootInstance.prevFiber = fiber;
854
616
  };
855
617
 
856
- const overrideRenderers = new Set<ReactRenderer>();
857
- let areOverrideRenderersWired = false;
858
-
859
- const wireOverrideRenderers = (): void => {
860
- if (!hasRDTHook()) return;
861
- const rdtHook = getRDTHook();
862
-
863
- setHookEventDispatchers(rdtHook);
864
- for (const renderer of rdtHook.renderers.values()) {
865
- overrideRenderers.add(renderer);
866
- }
867
- if (areOverrideRenderersWired) return;
868
- areOverrideRenderersWired = true;
869
- onRendererInject((renderer) => {
870
- overrideRenderers.add(renderer);
871
- });
872
- };
873
-
874
- const getRootRenderer = (fiber: Fiber): ReactRenderer | null => {
875
- if (!hasRDTHook()) return null;
876
- let hostRootFiber = fiber;
877
- while (hostRootFiber.return) {
878
- hostRootFiber = hostRootFiber.return;
879
- }
880
- const rendererId = rootRendererIds.get(hostRootFiber.stateNode);
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
- ): ValueWrite[] => {
944
- if (!isPOJO(maybePOJO)) {
945
- return [{ path: basePath, value: maybePOJO }];
946
- }
947
-
948
- const paths: ValueWrite[] = [];
949
-
950
- for (const key in maybePOJO) {
951
- const value = maybePOJO[key];
952
- const path = basePath.concat(key);
953
-
954
- if (isPOJO(value)) {
955
- paths.push(...buildPathsFromValue(value, path));
956
- } else {
957
- paths.push({ path, value });
958
- }
959
- }
960
-
961
- return paths;
962
- };
963
-
964
- const buildValueWrites = (partialValue: unknown): ValueWrite[] =>
965
- isPOJO(partialValue) ? buildPathsFromValue(partialValue) : [{ path: [], value: partialValue }];
966
-
967
- export const overrideProps = (fiber: Fiber, partialValue: Record<string, unknown>) => {
968
- const renderers = resolveOverrideRenderers(fiber);
969
- for (const { path, value } of buildValueWrites(partialValue)) {
970
- applyPropsOverride(renderers, fiber, path, value);
971
- }
972
- };
973
-
974
- export const overrideHookState = (fiber: Fiber, id: number, partialValue: unknown) => {
975
- const renderers = resolveOverrideRenderers(fiber).filter((renderer) =>
976
- Boolean(renderer.overrideHookState),
977
- );
978
- const writes = buildValueWrites(partialValue);
979
-
980
- if (renderers.length > 0) {
981
- for (const renderer of renderers) {
982
- for (const { path, value } of writes) {
983
- try {
984
- renderer.overrideHookState?.(fiber, id, path, value);
985
- } catch {}
986
- }
987
- }
988
- return;
989
- }
990
-
991
- // production renderers don't expose overrideHookState; dispatching through
992
- // the hook's own queue still works there, but only for whole-value writes
993
- // (a path write through dispatch would replace the entire hook state)
994
- if (isPOJO(partialValue)) return;
995
- const dispatch = getHookStateDispatch(fiber, id);
996
- if (!dispatch) return;
997
- try {
998
- dispatch(partialValue);
999
- } catch {}
1000
- };
1001
-
1002
- export const overrideContext = (fiber: Fiber, contextType: unknown, partialValue: unknown) => {
1003
- const providerFiber = findContextProviderFiber(fiber, contextType);
1004
- if (!providerFiber) return;
1005
- const renderers = resolveOverrideRenderers(providerFiber);
1006
- for (const { path, value } of buildValueWrites(partialValue)) {
1007
- applyPropsOverride(renderers, providerFiber, ["value", ...path], value);
1008
- if (providerFiber.alternate) {
1009
- applyPropsOverride(renderers, providerFiber.alternate, ["value", ...path], value);
1010
- }
1011
- }
1012
- };
1013
-
1014
618
  export interface InstrumentationOptions {
1015
619
  name?: string;
1016
620
  onActive?: () => unknown;
@@ -1031,19 +635,6 @@ interface InstrumentationSubscription {
1031
635
 
1032
636
  const instrumentationSubscriptions = new Set<InstrumentationSubscription>();
1033
637
 
1034
- const runInstrumentationCallback = (
1035
- instrumentationName: string,
1036
- callbackName: string,
1037
- callback: () => unknown,
1038
- ): void =>
1039
- runWithBippyError(
1040
- callback,
1041
- (cause) => new BippyInstrumentationError(instrumentationName, callbackName, cause),
1042
- );
1043
-
1044
- const runReactDevToolsCallback = (callbackName: string, callback: () => unknown): void =>
1045
- runWithBippyError(callback, (cause) => new BippyReactDevToolsError(callbackName, cause));
1046
-
1047
638
  interface HookDispatchers {
1048
639
  onCommitFiberRoot: ReactDevToolsGlobalHook["onCommitFiberRoot"];
1049
640
  onCommitFiberUnmount: ReactDevToolsGlobalHook["onCommitFiberUnmount"];
@@ -1054,8 +645,6 @@ interface HookDispatchers {
1054
645
  const hookDispatchers = new WeakMap<ReactDevToolsGlobalHook, Partial<HookDispatchers>>();
1055
646
  let didSubscribeToHookReplacements = false;
1056
647
 
1057
- const rootRendererIds = new WeakMap<FiberRoot, number>();
1058
-
1059
648
  // each hook event is dispatched from a single re-installable wrapper. If
1060
649
  // something overwrites the hook method (devtools, direct assignment), the
1061
650
  // next instrument() call installs a fresh wrapper over it; a superseded
@@ -1077,9 +666,7 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
1077
666
  didError,
1078
667
  ) => {
1079
668
  if (prevOnCommitFiberRoot) {
1080
- runReactDevToolsCallback("onCommitFiberRoot", () =>
1081
- prevOnCommitFiberRoot(rendererID, root, priority, didError),
1082
- );
669
+ prevOnCommitFiberRoot.call(rdtHook, rendererID, root, priority, didError);
1083
670
  }
1084
671
  if (hookDispatchers.get(rdtHook)?.onCommitFiberRoot !== dispatchCommitFiberRoot) return;
1085
672
  setReactWorkTagsForFiber(root.current, rdtHook.renderers.get(rendererID));
@@ -1097,11 +684,7 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
1097
684
  }
1098
685
  for (const { options } of instrumentationSubscriptions) {
1099
686
  if (options.onCommitFiberRoot) {
1100
- runInstrumentationCallback(
1101
- options.name ?? BIPPY_INSTRUMENTATION_STRING,
1102
- "onCommitFiberRoot",
1103
- () => options.onCommitFiberRoot?.(rendererID, root, priority, didError),
1104
- );
687
+ options.onCommitFiberRoot(rendererID, root, priority, didError);
1105
688
  }
1106
689
  }
1107
690
  };
@@ -1120,20 +703,14 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
1120
703
  ) => {
1121
704
  setReactWorkTagsForFiber(fiber, rdtHook.renderers.get(rendererID));
1122
705
  if (prevOnCommitFiberUnmount) {
1123
- runReactDevToolsCallback("onCommitFiberUnmount", () =>
1124
- prevOnCommitFiberUnmount(rendererID, fiber),
1125
- );
706
+ prevOnCommitFiberUnmount.call(rdtHook, rendererID, fiber);
1126
707
  }
1127
708
  if (hookDispatchers.get(rdtHook)?.onCommitFiberUnmount !== dispatchCommitFiberUnmount) {
1128
709
  return;
1129
710
  }
1130
711
  for (const { options } of instrumentationSubscriptions) {
1131
712
  if (options.onCommitFiberUnmount) {
1132
- runInstrumentationCallback(
1133
- options.name ?? BIPPY_INSTRUMENTATION_STRING,
1134
- "onCommitFiberUnmount",
1135
- () => options.onCommitFiberUnmount?.(rendererID, fiber),
1136
- );
713
+ options.onCommitFiberUnmount(rendererID, fiber);
1137
714
  }
1138
715
  }
1139
716
  };
@@ -1151,20 +728,14 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
1151
728
  root,
1152
729
  ) => {
1153
730
  if (prevOnPostCommitFiberRoot) {
1154
- runReactDevToolsCallback("onPostCommitFiberRoot", () =>
1155
- prevOnPostCommitFiberRoot(rendererID, root),
1156
- );
731
+ prevOnPostCommitFiberRoot.call(rdtHook, rendererID, root);
1157
732
  }
1158
733
  if (hookDispatchers.get(rdtHook)?.onPostCommitFiberRoot !== dispatchPostCommitFiberRoot) {
1159
734
  return;
1160
735
  }
1161
736
  for (const { options } of instrumentationSubscriptions) {
1162
737
  if (options.onPostCommitFiberRoot) {
1163
- runInstrumentationCallback(
1164
- options.name ?? BIPPY_INSTRUMENTATION_STRING,
1165
- "onPostCommitFiberRoot",
1166
- () => options.onPostCommitFiberRoot?.(rendererID, root),
1167
- );
738
+ options.onPostCommitFiberRoot(rendererID, root);
1168
739
  }
1169
740
  }
1170
741
  };
@@ -1183,18 +754,12 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
1183
754
  children,
1184
755
  ) => {
1185
756
  if (prevOnScheduleFiberRoot) {
1186
- runReactDevToolsCallback("onScheduleFiberRoot", () =>
1187
- prevOnScheduleFiberRoot(rendererID, root, children),
1188
- );
757
+ prevOnScheduleFiberRoot.call(rdtHook, rendererID, root, children);
1189
758
  }
1190
759
  if (hookDispatchers.get(rdtHook)?.onScheduleFiberRoot !== dispatchScheduleFiberRoot) return;
1191
760
  for (const { options } of instrumentationSubscriptions) {
1192
761
  if (options.onScheduleFiberRoot) {
1193
- runInstrumentationCallback(
1194
- options.name ?? BIPPY_INSTRUMENTATION_STRING,
1195
- "onScheduleFiberRoot",
1196
- () => options.onScheduleFiberRoot?.(rendererID, root, children),
1197
- );
762
+ options.onScheduleFiberRoot(rendererID, root, children);
1198
763
  }
1199
764
  }
1200
765
  };
@@ -1203,13 +768,24 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
1203
768
  }
1204
769
  };
1205
770
 
771
+ const wireHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
772
+ if (!didSubscribeToHookReplacements) {
773
+ onRDTHookReplace(setHookEventDispatchers);
774
+ didSubscribeToHookReplacements = true;
775
+ }
776
+ setHookEventDispatchers(rdtHook);
777
+ };
778
+
779
+ if (hasRDTHook()) {
780
+ wireHookEventDispatchers(getRDTHook());
781
+ }
782
+
1206
783
  /**
1207
784
  * Instruments the DevTools hook. Each hook event is patched once and
1208
785
  * dispatches to a set of listeners, so multiple `instrument` calls compose
1209
786
  * without stacking patches. Returns an unsubscribe function that removes
1210
787
  * exactly the handlers this call registered.
1211
- * The returned function is also a `Disposable`, so it composes with other
1212
- * bippy subscriptions through `using`.
788
+ * The unsubscribe function can also be disposed through `using`.
1213
789
  * @example
1214
790
  * const unsubscribe = instrument({
1215
791
  * onActive() {
@@ -1222,30 +798,15 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
1222
798
  * unsubscribe();
1223
799
  */
1224
800
  export const instrument = (options: InstrumentationOptions): Unsubscribe => {
1225
- const onActiveListener = options.onActive;
1226
- const onActive = onActiveListener
1227
- ? () =>
1228
- runInstrumentationCallback(
1229
- options.name ?? BIPPY_INSTRUMENTATION_STRING,
1230
- "onActive",
1231
- onActiveListener,
1232
- )
1233
- : undefined;
1234
- const rdtHook = getRDTHook(onActive);
1235
-
1236
- if (!didSubscribeToHookReplacements) {
1237
- onRDTHookReplace(setHookEventDispatchers);
1238
- didSubscribeToHookReplacements = true;
1239
- }
1240
-
801
+ const rdtHook = getRDTHook(options.onActive);
1241
802
  rdtHook._instrumentationSource = options.name ?? BIPPY_INSTRUMENTATION_STRING;
1242
803
 
1243
- setHookEventDispatchers(rdtHook);
804
+ wireHookEventDispatchers(rdtHook);
1244
805
  const subscription: InstrumentationSubscription = { options };
1245
806
  instrumentationSubscriptions.add(subscription);
1246
807
 
1247
- return toUnsubscribe(() => {
1248
- if (onActive) _onActiveListeners.delete(onActive);
808
+ return createUnsubscribe(() => {
809
+ if (options.onActive) _onActiveListeners.delete(options.onActive);
1249
810
  instrumentationSubscriptions.delete(subscription);
1250
811
  });
1251
812
  };
@@ -1258,33 +819,38 @@ const isFiberPropertyKey = (key: string): boolean =>
1258
819
  key.startsWith("__reactInternalInstance$") ||
1259
820
  key.startsWith("__reactFiber");
1260
821
 
1261
- const getLegacyRootFiber = (hostInstance: Record<string, unknown>): Fiber | null => {
1262
- const reactRootContainer = hostInstance._reactRootContainer;
1263
- if (!isObjectRecord(reactRootContainer)) return null;
1264
- const internalRoot = reactRootContainer._internalRoot;
1265
- if (!isObjectRecord(internalRoot)) return null;
1266
- const current = internalRoot.current;
1267
- if (!isObjectRecord(current)) return null;
1268
- const child = current.child;
1269
- return isValidFiber(child) ? child : null;
822
+ const getLegacyRootFiber = (hostInstance: object): Fiber | null => {
823
+ const reactRootContainer = Reflect.get(hostInstance, "_reactRootContainer");
824
+ if (typeof reactRootContainer !== "object" || reactRootContainer === null) return null;
825
+ const internalRoot = Reflect.get(reactRootContainer, "_internalRoot");
826
+ if (typeof internalRoot !== "object" || internalRoot === null) return null;
827
+ const current = Reflect.get(internalRoot, "current");
828
+ if (typeof current !== "object" || current === null) return null;
829
+ const child = Reflect.get(current, "child");
830
+ return isFiber(child) ? child : null;
1270
831
  };
1271
832
 
1272
- const getInternalInstanceHandle = (hostInstance: Record<string, unknown>): Fiber | null => {
833
+ const getInternalInstanceHandle = (hostInstance: object): Fiber | null => {
1273
834
  const internalInstanceHandle =
1274
- hostInstance.__internalInstanceHandle ?? hostInstance._internalInstanceHandle;
1275
- return isValidFiber(internalInstanceHandle) ? internalInstanceHandle : null;
835
+ Reflect.get(hostInstance, "__internalInstanceHandle") ??
836
+ Reflect.get(hostInstance, "_internalInstanceHandle");
837
+ return isFiber(internalInstanceHandle) ? internalInstanceHandle : null;
1276
838
  };
1277
839
 
1278
840
  const getPublicHostInstance = (stateNode: unknown): unknown => {
1279
- if (!isObjectRecord(stateNode)) return stateNode;
1280
- const canonical = stateNode.canonical;
1281
- if (isObjectRecord(canonical) && isObjectRecord(canonical.publicInstance)) {
1282
- return canonical.publicInstance;
841
+ if (typeof stateNode !== "object" || stateNode === null) return stateNode;
842
+ const canonical = Reflect.get(stateNode, "canonical");
843
+ if (typeof canonical === "object" && canonical !== null) {
844
+ const publicInstance = Reflect.get(canonical, "publicInstance");
845
+ if (typeof publicInstance === "object" && publicInstance !== null) {
846
+ return publicInstance;
847
+ }
1283
848
  }
1284
- return typeof stateNode._nativeTag === "number" ? stateNode._nativeTag : stateNode;
849
+ const nativeTag = Reflect.get(stateNode, "_nativeTag");
850
+ return typeof nativeTag === "number" ? nativeTag : stateNode;
1285
851
  };
1286
852
 
1287
- export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
853
+ export const getFiber = <T>(hostInstance: T): Fiber | null => {
1288
854
  const rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
1289
855
  if (rdtHook?.renderers) {
1290
856
  for (const renderer of rdtHook.renderers.values()) {
@@ -1295,7 +861,7 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
1295
861
  }
1296
862
  }
1297
863
 
1298
- if (isObjectRecord(hostInstance)) {
864
+ if (typeof hostInstance === "object" && hostInstance !== null) {
1299
865
  const legacyRootFiber = getLegacyRootFiber(hostInstance);
1300
866
  if (legacyRootFiber) return legacyRootFiber;
1301
867
 
@@ -1303,15 +869,15 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
1303
869
  if (internalInstanceHandle) return internalInstanceHandle;
1304
870
 
1305
871
  for (const knownKey of knownFiberPropertyKeys) {
1306
- const fiber = hostInstance[knownKey];
1307
- if (isValidFiber(fiber)) return fiber;
872
+ const fiber = Reflect.get(hostInstance, knownKey);
873
+ if (isFiber(fiber)) return fiber;
1308
874
  }
1309
875
 
1310
876
  for (const key of Object.keys(hostInstance)) {
1311
877
  if (isFiberPropertyKey(key)) {
1312
878
  knownFiberPropertyKeys.add(key);
1313
- const fiber = hostInstance[key];
1314
- if (isValidFiber(fiber)) return fiber;
879
+ const fiber = Reflect.get(hostInstance, key);
880
+ if (isFiber(fiber)) return fiber;
1315
881
  }
1316
882
  }
1317
883
  }
@@ -1334,6 +900,8 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
1334
900
  return null;
1335
901
  };
1336
902
 
903
+ export const getFiberFromHostInstance = getFiber;
904
+
1337
905
  export {
1338
906
  BIPPY_INSTRUMENTATION_STRING,
1339
907
  _onActiveListeners,
@@ -1344,8 +912,7 @@ export {
1344
912
  isRealReactDevtools,
1345
913
  onRendererInject,
1346
914
  patchRDTHook,
1347
- safelyInstallRDTHook,
1348
915
  version,
1349
916
  } from "./rdt-hook.js";
1350
- export * from "./unsubscribe.js";
1351
- export type * from "./types.js";
917
+ export type { Unsubscribe } from "./rdt-hook.js";
918
+ export * from "./react-internals/index.js";