bippy 0.7.3-dev.e2b879b → 0.7.3-dev.e6929e3
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 +1 -8
- package/dist/core.cjs +1 -1
- package/dist/core.js +1 -1
- package/dist/errors.d.cts +3 -0
- package/dist/errors.d.ts +3 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +27 -27
- package/dist/index.d.ts +29 -29
- package/dist/index.js +1 -1
- package/dist/rdt-hook.cjs +1 -1
- package/dist/rdt-hook.js +1 -1
- package/dist/source.cjs +11 -12
- package/dist/source.d.cts +22 -22
- package/dist/source.d.ts +22 -22
- package/dist/source.js +11 -12
- package/package.json +4 -4
- package/src/call-listener.ts +13 -0
- package/src/core.ts +99 -143
- package/src/rdt-hook.ts +5 -4
- package/src/react-internals/generated/react-work-tags.ts +3 -0
- package/src/react-internals/index.ts +36 -14
- package/src/react.ts +139 -75
- package/src/source/inspect-hooks.ts +5 -3
- package/src/source/parse-stack.ts +111 -63
- package/src/source/symbolication.ts +15 -4
package/src/core.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// React must remain a type-only import because this module loads immediately after the DevTools hook.
|
|
2
2
|
import type * as React from "react";
|
|
3
|
+
import { callListener } from "./call-listener.js";
|
|
3
4
|
|
|
4
5
|
import type {
|
|
5
6
|
Fiber,
|
|
@@ -167,16 +168,20 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
167
168
|
// https://github.com/bvaughn/react-devtools-experimental/issues/197
|
|
168
169
|
return true;
|
|
169
170
|
|
|
170
|
-
case workTags.
|
|
171
|
+
case workTags.HostPortal:
|
|
171
172
|
case workTags.HostText:
|
|
172
173
|
case workTags.LegacyHiddenComponent:
|
|
173
174
|
case workTags.OffscreenComponent:
|
|
175
|
+
case workTags.Throw:
|
|
174
176
|
return true;
|
|
175
177
|
|
|
176
178
|
case workTags.HostRoot:
|
|
177
179
|
// It is never valid to filter the root element.
|
|
178
180
|
return false;
|
|
179
181
|
|
|
182
|
+
case workTags.Fragment:
|
|
183
|
+
return fiber.key === null;
|
|
184
|
+
|
|
180
185
|
default: {
|
|
181
186
|
const symbolOrNumber =
|
|
182
187
|
typeof fiber.type === "object" && fiber.type !== null ? fiber.type.$$typeof : fiber.type;
|
|
@@ -184,7 +189,8 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
184
189
|
if (typeof symbolOrNumber === "symbol") {
|
|
185
190
|
return (
|
|
186
191
|
symbolOrNumber.description === ReactSymbols.CONCURRENT_MODE_SYMBOL_DESCRIPTION ||
|
|
187
|
-
symbolOrNumber.description === ReactSymbols.DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION
|
|
192
|
+
symbolOrNumber.description === ReactSymbols.DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION ||
|
|
193
|
+
symbolOrNumber.description === ReactSymbols.STRICT_MODE_SYMBOL_DESCRIPTION
|
|
188
194
|
);
|
|
189
195
|
}
|
|
190
196
|
|
|
@@ -192,6 +198,8 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
192
198
|
case ReactSymbols.CONCURRENT_MODE_NUMBER:
|
|
193
199
|
case ReactSymbols.CONCURRENT_MODE_SYMBOL_STRING:
|
|
194
200
|
case ReactSymbols.DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
|
|
201
|
+
case ReactSymbols.STRICT_MODE_NUMBER:
|
|
202
|
+
case ReactSymbols.STRICT_MODE_SYMBOL_STRING:
|
|
195
203
|
return true;
|
|
196
204
|
|
|
197
205
|
default:
|
|
@@ -458,131 +466,91 @@ const releaseFiberId = (fiber: Fiber): void => {
|
|
|
458
466
|
}
|
|
459
467
|
};
|
|
460
468
|
|
|
461
|
-
const
|
|
469
|
+
const getRenderedChild = (fiber: Fiber, skipPrimaryWrapper: boolean): Fiber | null => {
|
|
470
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
471
|
+
if (fiber.tag !== workTags.SuspenseComponent) return fiber.child;
|
|
472
|
+
if (fiber.memoizedState !== null) return fiber.child?.sibling?.child ?? null;
|
|
473
|
+
return skipPrimaryWrapper && workTags.OffscreenComponent !== -1
|
|
474
|
+
? (fiber.child?.child ?? null)
|
|
475
|
+
: fiber.child;
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
const mountFiberTree = (
|
|
462
479
|
onRender: RenderHandler,
|
|
463
480
|
firstChild: Fiber,
|
|
464
481
|
traverseSiblings: boolean,
|
|
465
482
|
): void => {
|
|
483
|
+
const pendingSiblings: Fiber[] = [];
|
|
466
484
|
let fiber: Fiber | null = firstChild;
|
|
467
|
-
|
|
468
|
-
while (fiber !== null) {
|
|
485
|
+
while (fiber) {
|
|
469
486
|
getFiberId(fiber);
|
|
470
|
-
|
|
471
|
-
if (
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
if (fiber.tag === getReactWorkTagsForFiber(fiber).SuspenseComponent) {
|
|
476
|
-
const isTimedOut = fiber.memoizedState !== null;
|
|
477
|
-
if (isTimedOut) {
|
|
478
|
-
// Special case: if Suspense mounts in a timed-out state,
|
|
479
|
-
// get the fallback child from the inner fragment and mount
|
|
480
|
-
// it as if it was our own child. Updates handle this too.
|
|
481
|
-
const primaryChildFragment = fiber.child;
|
|
482
|
-
const fallbackChildFragment = primaryChildFragment ? primaryChildFragment.sibling : null;
|
|
483
|
-
if (fallbackChildFragment) {
|
|
484
|
-
const fallbackChild = fallbackChildFragment.child;
|
|
485
|
-
if (fallbackChild !== null) {
|
|
486
|
-
mountFiberRecursively(onRender, fallbackChild, true);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
} else {
|
|
490
|
-
const primaryChild = fiber.child?.child ?? null;
|
|
491
|
-
if (primaryChild !== null) {
|
|
492
|
-
mountFiberRecursively(onRender, primaryChild, true);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
} else if (fiber.child !== null) {
|
|
496
|
-
mountFiberRecursively(onRender, fiber.child, true);
|
|
497
|
-
}
|
|
498
|
-
fiber = traverseSiblings ? fiber.sibling : null;
|
|
487
|
+
if (!shouldFilterFiber(fiber) && didFiberRender(fiber)) onRender(fiber, "mount");
|
|
488
|
+
if (traverseSiblings && fiber.sibling) pendingSiblings.push(fiber.sibling);
|
|
489
|
+
fiber = getRenderedChild(fiber, true) ?? pendingSiblings.pop() ?? null;
|
|
490
|
+
traverseSiblings = true;
|
|
499
491
|
}
|
|
500
492
|
};
|
|
501
493
|
|
|
502
|
-
|
|
494
|
+
interface FiberUpdate {
|
|
495
|
+
fiber: Fiber;
|
|
496
|
+
previousFiber: Fiber | null;
|
|
497
|
+
traverseSiblings: boolean;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const updateFiberTree = (
|
|
503
501
|
onRender: RenderHandler,
|
|
504
502
|
nextFiber: Fiber,
|
|
505
503
|
prevFiber: Fiber | null,
|
|
506
504
|
): void => {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
// The easiest fix is to strip out the intermediate Fragment fibers,
|
|
524
|
-
// so the Elements panel and Profiler don't need to special case them.
|
|
525
|
-
// Suspense components only have a non-null memoizedState if they're timed-out.
|
|
526
|
-
const prevDidTimeout = isSuspense && prevFiber.memoizedState !== null;
|
|
527
|
-
const nextDidTimeOut = isSuspense && nextFiber.memoizedState !== null;
|
|
528
|
-
|
|
529
|
-
// The logic below is inspired by the code paths in updateSuspenseComponent()
|
|
530
|
-
// inside ReactFiberBeginWork in the React source code.
|
|
531
|
-
if (prevDidTimeout && nextDidTimeOut) {
|
|
532
|
-
// Fallback -> Fallback:
|
|
533
|
-
// 1. Reconcile fallback set.
|
|
534
|
-
const nextFallbackChildSet = nextFiber.child?.sibling ?? null;
|
|
535
|
-
// Note: We can't use nextFiber.child.sibling.alternate
|
|
536
|
-
// because the set is special and alternate may not exist.
|
|
537
|
-
const prevFallbackChildSet = prevFiber.child?.sibling ?? null;
|
|
538
|
-
|
|
539
|
-
if (nextFallbackChildSet !== null && prevFallbackChildSet !== null) {
|
|
540
|
-
updateFiberRecursively(onRender, nextFallbackChildSet, prevFallbackChildSet);
|
|
505
|
+
if (!prevFiber) {
|
|
506
|
+
getFiberId(nextFiber);
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const pendingUpdates: FiberUpdate[] = [
|
|
510
|
+
{ fiber: nextFiber, previousFiber: prevFiber, traverseSiblings: false },
|
|
511
|
+
];
|
|
512
|
+
let update: FiberUpdate | undefined;
|
|
513
|
+
while ((update = pendingUpdates.pop())) {
|
|
514
|
+
const { fiber, previousFiber, traverseSiblings } = update;
|
|
515
|
+
if (traverseSiblings && fiber.sibling) {
|
|
516
|
+
pendingUpdates.push({
|
|
517
|
+
fiber: fiber.sibling,
|
|
518
|
+
previousFiber: fiber.sibling.alternate,
|
|
519
|
+
traverseSiblings: true,
|
|
520
|
+
});
|
|
541
521
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
// Note: don't emulate fallback unmount because React actually did it.
|
|
546
|
-
// 2. Mount primary set
|
|
547
|
-
const nextPrimaryChildSet = nextFiber.child;
|
|
548
|
-
|
|
549
|
-
if (nextPrimaryChildSet !== null) {
|
|
550
|
-
mountFiberRecursively(onRender, nextPrimaryChildSet, true);
|
|
522
|
+
if (!previousFiber) {
|
|
523
|
+
mountFiberTree(onRender, fiber, false);
|
|
524
|
+
continue;
|
|
551
525
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
// This is the same code path as for non-Suspense fibers.
|
|
568
|
-
|
|
569
|
-
// If the first child is different, we need to traverse them.
|
|
570
|
-
// Each next child will be either a new child (mount) or an alternate (update).
|
|
571
|
-
let nextChild = nextFiber.child;
|
|
572
|
-
|
|
573
|
-
while (nextChild) {
|
|
574
|
-
// We already know children will be referentially different because
|
|
575
|
-
// they are either new mounts or alternates of previous children.
|
|
576
|
-
// Schedule updates and mounts depending on whether alternates exist.
|
|
577
|
-
// We don't track deletions here because they are reported separately.
|
|
578
|
-
if (nextChild.alternate) {
|
|
579
|
-
updateFiberRecursively(onRender, nextChild, nextChild.alternate);
|
|
580
|
-
} else {
|
|
581
|
-
mountFiberRecursively(onRender, nextChild, false);
|
|
526
|
+
getFiberId(fiber);
|
|
527
|
+
getFiberId(previousFiber);
|
|
528
|
+
if (!shouldFilterFiber(fiber) && didFiberRender(fiber)) onRender(fiber, "update");
|
|
529
|
+
const isSuspense = fiber.tag === getReactWorkTagsForFiber(fiber).SuspenseComponent;
|
|
530
|
+
const wasTimedOut = isSuspense && previousFiber.memoizedState !== null;
|
|
531
|
+
const isTimedOut = isSuspense && fiber.memoizedState !== null;
|
|
532
|
+
if (wasTimedOut && isTimedOut) {
|
|
533
|
+
const nextFallback = fiber.child?.sibling;
|
|
534
|
+
const previousFallback = previousFiber.child?.sibling;
|
|
535
|
+
if (nextFallback && previousFallback) {
|
|
536
|
+
pendingUpdates.push({
|
|
537
|
+
fiber: nextFallback,
|
|
538
|
+
previousFiber: previousFallback,
|
|
539
|
+
traverseSiblings: false,
|
|
540
|
+
});
|
|
582
541
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
542
|
+
} else if (wasTimedOut && !isTimedOut) {
|
|
543
|
+
if (fiber.child) mountFiberTree(onRender, fiber.child, true);
|
|
544
|
+
} else if (!wasTimedOut && isTimedOut) {
|
|
545
|
+
unmountFiberChildren(onRender, previousFiber);
|
|
546
|
+
const fallback = fiber.child?.sibling;
|
|
547
|
+
if (fallback) mountFiberTree(onRender, fallback, true);
|
|
548
|
+
} else if (fiber.child && fiber.child !== previousFiber.child) {
|
|
549
|
+
pendingUpdates.push({
|
|
550
|
+
fiber: fiber.child,
|
|
551
|
+
previousFiber: fiber.child.alternate,
|
|
552
|
+
traverseSiblings: true,
|
|
553
|
+
});
|
|
586
554
|
}
|
|
587
555
|
}
|
|
588
556
|
};
|
|
@@ -595,30 +563,18 @@ const unmountFiber = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
|
595
563
|
}
|
|
596
564
|
};
|
|
597
565
|
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
if (isTimedOutSuspense) {
|
|
605
|
-
// If it's showing fallback tree, let's traverse it instead.
|
|
606
|
-
const primaryChildFragment = fiber.child;
|
|
607
|
-
const fallbackChildFragment = primaryChildFragment?.sibling ?? null;
|
|
608
|
-
|
|
609
|
-
// Skip over to the real Fiber child.
|
|
610
|
-
child = fallbackChildFragment?.child ?? null;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
while (child !== null) {
|
|
614
|
-
// Record simulated unmounts children-first.
|
|
615
|
-
// We skip nodes without return because those are real unmounts.
|
|
566
|
+
const unmountFiberChildren = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
567
|
+
const pendingSiblings: Fiber[] = [];
|
|
568
|
+
let child = getRenderedChild(fiber, false);
|
|
569
|
+
while (child) {
|
|
570
|
+
if (child.sibling) pendingSiblings.push(child.sibling);
|
|
616
571
|
if (child.return !== null) {
|
|
617
572
|
unmountFiber(onRender, child);
|
|
618
|
-
|
|
573
|
+
child = getRenderedChild(child, false);
|
|
574
|
+
} else {
|
|
575
|
+
child = null;
|
|
619
576
|
}
|
|
620
|
-
|
|
621
|
-
child = child.sibling;
|
|
577
|
+
child ??= pendingSiblings.pop() ?? null;
|
|
622
578
|
}
|
|
623
579
|
};
|
|
624
580
|
|
|
@@ -668,14 +624,14 @@ export const traverseRenderedFibers = (root: Fiber | FiberRoot, onRender: Render
|
|
|
668
624
|
const isMounted = isRootFiberMounted(fiber);
|
|
669
625
|
|
|
670
626
|
if (!wasMounted && isMounted) {
|
|
671
|
-
|
|
627
|
+
mountFiberTree(onRender, fiber, false);
|
|
672
628
|
} else if (wasMounted && isMounted) {
|
|
673
|
-
|
|
629
|
+
updateFiberTree(onRender, fiber, fiber.alternate);
|
|
674
630
|
} else if (wasMounted && !isMounted) {
|
|
675
631
|
unmountFiber(onRender, fiber);
|
|
676
632
|
}
|
|
677
633
|
} else {
|
|
678
|
-
|
|
634
|
+
mountFiberTree(onRender, fiber, true);
|
|
679
635
|
}
|
|
680
636
|
|
|
681
637
|
rootInstance.prevFiber = fiber;
|
|
@@ -735,7 +691,7 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
735
691
|
didError,
|
|
736
692
|
) => {
|
|
737
693
|
if (prevOnCommitFiberRoot) {
|
|
738
|
-
prevOnCommitFiberRoot
|
|
694
|
+
callListener(prevOnCommitFiberRoot, rdtHook, rendererID, root, priority, didError);
|
|
739
695
|
}
|
|
740
696
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberRoot !== dispatchCommitFiberRoot) return;
|
|
741
697
|
setReactWorkTagsForFiber(root.current, rdtHook.renderers.get(rendererID));
|
|
@@ -752,7 +708,7 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
752
708
|
}
|
|
753
709
|
for (const { options, target } of instrumentationSubscriptions) {
|
|
754
710
|
if (target === hookTargets.get(rdtHook) && options.onCommitFiberRoot) {
|
|
755
|
-
options.onCommitFiberRoot
|
|
711
|
+
callListener(options.onCommitFiberRoot, options, rendererID, root, priority, didError);
|
|
756
712
|
}
|
|
757
713
|
}
|
|
758
714
|
};
|
|
@@ -771,7 +727,7 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
771
727
|
) => {
|
|
772
728
|
setReactWorkTagsForFiber(fiber, rdtHook.renderers.get(rendererID));
|
|
773
729
|
if (prevOnCommitFiberUnmount) {
|
|
774
|
-
prevOnCommitFiberUnmount
|
|
730
|
+
callListener(prevOnCommitFiberUnmount, rdtHook, rendererID, fiber);
|
|
775
731
|
}
|
|
776
732
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberUnmount !== dispatchCommitFiberUnmount) {
|
|
777
733
|
return;
|
|
@@ -779,7 +735,7 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
779
735
|
try {
|
|
780
736
|
for (const { options, target } of instrumentationSubscriptions) {
|
|
781
737
|
if (target === hookTargets.get(rdtHook) && options.onCommitFiberUnmount) {
|
|
782
|
-
options.onCommitFiberUnmount
|
|
738
|
+
callListener(options.onCommitFiberUnmount, options, rendererID, fiber);
|
|
783
739
|
}
|
|
784
740
|
}
|
|
785
741
|
} finally {
|
|
@@ -800,14 +756,14 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
800
756
|
root,
|
|
801
757
|
) => {
|
|
802
758
|
if (prevOnPostCommitFiberRoot) {
|
|
803
|
-
prevOnPostCommitFiberRoot
|
|
759
|
+
callListener(prevOnPostCommitFiberRoot, rdtHook, rendererID, root);
|
|
804
760
|
}
|
|
805
761
|
if (hookDispatchers.get(rdtHook)?.onPostCommitFiberRoot !== dispatchPostCommitFiberRoot) {
|
|
806
762
|
return;
|
|
807
763
|
}
|
|
808
764
|
for (const { options, target } of instrumentationSubscriptions) {
|
|
809
765
|
if (target === hookTargets.get(rdtHook) && options.onPostCommitFiberRoot) {
|
|
810
|
-
options.onPostCommitFiberRoot
|
|
766
|
+
callListener(options.onPostCommitFiberRoot, options, rendererID, root);
|
|
811
767
|
}
|
|
812
768
|
}
|
|
813
769
|
};
|
|
@@ -826,12 +782,12 @@ const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
|
826
782
|
children,
|
|
827
783
|
) => {
|
|
828
784
|
if (prevOnScheduleFiberRoot) {
|
|
829
|
-
prevOnScheduleFiberRoot
|
|
785
|
+
callListener(prevOnScheduleFiberRoot, rdtHook, rendererID, root, children);
|
|
830
786
|
}
|
|
831
787
|
if (hookDispatchers.get(rdtHook)?.onScheduleFiberRoot !== dispatchScheduleFiberRoot) return;
|
|
832
788
|
for (const { options, target } of instrumentationSubscriptions) {
|
|
833
789
|
if (target === hookTargets.get(rdtHook) && options.onScheduleFiberRoot) {
|
|
834
|
-
options.onScheduleFiberRoot
|
|
790
|
+
callListener(options.onScheduleFiberRoot, options, rendererID, root, children);
|
|
835
791
|
}
|
|
836
792
|
}
|
|
837
793
|
};
|
package/src/rdt-hook.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// This module must load before React so renderers can inject into the hook.
|
|
2
2
|
|
|
3
|
+
import { callListener } from "./call-listener.js";
|
|
3
4
|
import type { FiberRoot, ReactDevToolsGlobalHook, ReactRenderer } from "./react-internals/index.js";
|
|
4
5
|
|
|
5
6
|
export interface Unsubscribe extends Disposable {
|
|
@@ -117,7 +118,7 @@ export const removeActiveListener = (
|
|
|
117
118
|
|
|
118
119
|
const notifyActiveListeners = (target: ReactDevToolsTarget): void => {
|
|
119
120
|
for (const listener of _onActiveListeners) {
|
|
120
|
-
if (activeListenerTargets.get(listener)?.has(target)) listener
|
|
121
|
+
if (activeListenerTargets.get(listener)?.has(target)) callListener(listener, undefined);
|
|
121
122
|
}
|
|
122
123
|
};
|
|
123
124
|
|
|
@@ -126,7 +127,7 @@ const notifyRendererInjectListeners = (
|
|
|
126
127
|
renderer: ReactRenderer,
|
|
127
128
|
): void => {
|
|
128
129
|
for (const subscription of rendererInjectSubscriptions) {
|
|
129
|
-
if (subscription.target === target) subscription.listener
|
|
130
|
+
if (subscription.target === target) callListener(subscription.listener, subscription, renderer);
|
|
130
131
|
}
|
|
131
132
|
};
|
|
132
133
|
|
|
@@ -135,7 +136,7 @@ const notifyRDTHookReplaceListeners = (
|
|
|
135
136
|
target: ReactDevToolsTarget,
|
|
136
137
|
): void => {
|
|
137
138
|
for (const listener of rdtHookReplaceListeners) {
|
|
138
|
-
listener
|
|
139
|
+
callListener(listener, undefined, rdtHook, target);
|
|
139
140
|
}
|
|
140
141
|
};
|
|
141
142
|
|
|
@@ -326,7 +327,7 @@ export const patchRDTHook = (
|
|
|
326
327
|
};
|
|
327
328
|
}
|
|
328
329
|
if (!didNotifyActiveListeners && (renderers.size || rdtHook._instrumentationIsActive)) {
|
|
329
|
-
onActive
|
|
330
|
+
if (onActive) callListener(onActive, undefined);
|
|
330
331
|
}
|
|
331
332
|
};
|
|
332
333
|
|
|
@@ -25,6 +25,9 @@ export const ReactSymbols = {
|
|
|
25
25
|
DEPRECATED_ASYNC_MODE_SYMBOL_STRING: "Symbol(react.async_mode)",
|
|
26
26
|
ELEMENT_SYMBOL_STRING: "Symbol(react.transitional.element)",
|
|
27
27
|
LEGACY_ELEMENT_SYMBOL_STRING: "Symbol(react.element)",
|
|
28
|
+
STRICT_MODE_NUMBER: 60108,
|
|
29
|
+
STRICT_MODE_SYMBOL_DESCRIPTION: "react.strict_mode",
|
|
30
|
+
STRICT_MODE_SYMBOL_STRING: "Symbol(react.strict_mode)",
|
|
28
31
|
} as const;
|
|
29
32
|
|
|
30
33
|
export interface ReactWorkTagMap {
|
|
@@ -18,8 +18,24 @@ export type {
|
|
|
18
18
|
} from "./generated/react-work-tags.js";
|
|
19
19
|
export * from "./types.js";
|
|
20
20
|
|
|
21
|
+
interface InheritedWorkTags {
|
|
22
|
+
workTags: Readonly<ReactWorkTagMap>;
|
|
23
|
+
generation: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
const defaultReactWorkTags = getReactWorkTags();
|
|
22
27
|
const fiberReactWorkTags = new WeakMap<Fiber, Readonly<ReactWorkTagMap>>();
|
|
28
|
+
const inheritedFiberWorkTags = new WeakMap<Fiber, InheritedWorkTags>();
|
|
29
|
+
let workTagGeneration = 0;
|
|
30
|
+
|
|
31
|
+
const getCachedWorkTags = (fiber: Fiber): Readonly<ReactWorkTagMap> | undefined => {
|
|
32
|
+
const assignedWorkTags = fiberReactWorkTags.get(fiber);
|
|
33
|
+
if (assignedWorkTags) return assignedWorkTags;
|
|
34
|
+
const inheritedWorkTags = inheritedFiberWorkTags.get(fiber);
|
|
35
|
+
return inheritedWorkTags?.generation === workTagGeneration
|
|
36
|
+
? inheritedWorkTags.workTags
|
|
37
|
+
: undefined;
|
|
38
|
+
};
|
|
23
39
|
|
|
24
40
|
// React's experimental channel historically reported "0.0.0-experimental-<sha>"
|
|
25
41
|
// as the runtime version; those builds use modern work tags, not the 16.x rows
|
|
@@ -39,30 +55,36 @@ export const getReactWorkTagsForRenderer = (
|
|
|
39
55
|
|
|
40
56
|
export const setReactWorkTagsForFiber = (fiber: Fiber, renderer?: ReactRenderer): void => {
|
|
41
57
|
const workTags = getReactWorkTagsForRenderer(renderer);
|
|
58
|
+
if (
|
|
59
|
+
getCachedWorkTags(fiber) !== workTags ||
|
|
60
|
+
(fiber.alternate && getCachedWorkTags(fiber.alternate) !== workTags)
|
|
61
|
+
) {
|
|
62
|
+
workTagGeneration++;
|
|
63
|
+
}
|
|
42
64
|
fiberReactWorkTags.set(fiber, workTags);
|
|
43
65
|
if (fiber.alternate) fiberReactWorkTags.set(fiber.alternate, workTags);
|
|
44
66
|
};
|
|
45
67
|
|
|
46
68
|
export const getReactWorkTagsForFiber = (fiber: Fiber): Readonly<ReactWorkTagMap> => {
|
|
47
|
-
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (ancestorWorkTags) {
|
|
57
|
-
workTags = ancestorWorkTags;
|
|
69
|
+
let workTags = getCachedWorkTags(fiber);
|
|
70
|
+
if (workTags) return workTags;
|
|
71
|
+
const traversedFibers: Fiber[] = [];
|
|
72
|
+
let ancestor = fiber;
|
|
73
|
+
while (!workTags) {
|
|
74
|
+
traversedFibers.push(ancestor);
|
|
75
|
+
const parent = ancestor.return;
|
|
76
|
+
if (!parent) {
|
|
77
|
+
workTags = inheritedFiberWorkTags.get(ancestor)?.workTags ?? defaultReactWorkTags;
|
|
58
78
|
break;
|
|
59
79
|
}
|
|
60
|
-
|
|
80
|
+
ancestor = parent;
|
|
81
|
+
workTags = getCachedWorkTags(ancestor);
|
|
61
82
|
}
|
|
83
|
+
const inheritedWorkTags = { workTags, generation: workTagGeneration };
|
|
62
84
|
for (const traversedFiber of traversedFibers) {
|
|
63
|
-
|
|
85
|
+
inheritedFiberWorkTags.set(traversedFiber, inheritedWorkTags);
|
|
64
86
|
if (traversedFiber.alternate) {
|
|
65
|
-
|
|
87
|
+
inheritedFiberWorkTags.set(traversedFiber.alternate, inheritedWorkTags);
|
|
66
88
|
}
|
|
67
89
|
}
|
|
68
90
|
return workTags;
|