bippy 0.6.1-dev.3a24abf → 0.6.1-dev.4ed5147
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +177 -478
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +39 -87
- package/dist/core.d.ts +39 -87
- package/dist/core.js +1 -1
- package/dist/core2.cjs +1 -1
- package/dist/core2.d.cts +11 -3
- package/dist/core2.d.ts +11 -3
- package/dist/core2.js +1 -1
- package/dist/{types.d.cts → errors.d.cts} +187 -68
- package/dist/{types.d.ts → errors.d.ts} +187 -68
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +1 -1
- package/dist/install-hook-only.cjs +1 -1
- package/dist/install-hook-only.d.cts +8 -0
- package/dist/install-hook-only.d.ts +8 -0
- package/dist/install-hook-only.js +1 -1
- package/dist/rdt-hook.cjs +1 -1
- package/dist/rdt-hook.js +1 -1
- package/dist/source.cjs +13 -14
- package/dist/source.d.cts +86 -69
- package/dist/source.d.ts +86 -69
- package/dist/source.js +13 -14
- package/package.json +14 -7
- package/src/core.ts +245 -629
- package/src/errors.ts +34 -0
- package/src/index.ts +1 -0
- package/src/install-hook-only.ts +2 -2
- package/src/rdt-hook.ts +152 -110
- package/src/react-internals/generated/react-work-tags.ts +318 -0
- package/src/react-internals/index.ts +67 -0
- package/src/react-internals/semver.ts +80 -0
- package/src/{types.ts → react-internals/types.ts} +13 -86
- package/src/react.ts +76 -0
- package/src/source/error-stack.ts +11 -0
- package/src/source/get-display-name-from-source.ts +44 -40
- package/src/source/get-source.ts +42 -26
- package/src/source/index.ts +11 -1
- package/src/source/inspect-hooks.ts +220 -207
- package/src/source/owner-stack.ts +86 -128
- package/src/source/parse-debug-stack.ts +4 -4
- 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 +703 -135
- package/dist/index.iife.js +0 -9
- package/dist/install-hook-only.iife.js +0 -9
- package/src/generated/react-work-tags.ts +0 -169
- package/src/react-internals.ts +0 -67
- package/src/unsubscribe.ts +0 -17
package/src/core.ts
CHANGED
|
@@ -3,109 +3,47 @@
|
|
|
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 "./
|
|
11
|
+
} from "./react-internals/index.js";
|
|
14
12
|
|
|
15
13
|
import {
|
|
16
14
|
_onActiveListeners,
|
|
17
15
|
BIPPY_INSTRUMENTATION_STRING,
|
|
16
|
+
createUnsubscribe,
|
|
18
17
|
getRDTHook,
|
|
19
18
|
hasRDTHook,
|
|
20
19
|
isRealReactDevtools,
|
|
21
|
-
|
|
20
|
+
onRDTHookReplace,
|
|
22
21
|
} from "./rdt-hook.js";
|
|
22
|
+
import type { Unsubscribe } from "./rdt-hook.js";
|
|
23
23
|
import {
|
|
24
|
-
|
|
25
|
-
CONCURRENT_MODE_NUMBER,
|
|
26
|
-
CONCURRENT_MODE_SYMBOL_DESCRIPTION,
|
|
27
|
-
CONCURRENT_MODE_SYMBOL_STRING,
|
|
28
|
-
ContextConsumerTag,
|
|
29
|
-
DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION,
|
|
30
|
-
DEPRECATED_ASYNC_MODE_SYMBOL_STRING,
|
|
31
|
-
DehydratedSuspenseComponentTag,
|
|
32
|
-
ELEMENT_TYPE_SYMBOL_STRING,
|
|
33
|
-
ForwardRefTag,
|
|
34
|
-
FragmentTag,
|
|
35
|
-
FunctionComponentTag,
|
|
36
|
-
HostComponentTag,
|
|
37
|
-
HostHoistableTag,
|
|
38
|
-
HostRootTag,
|
|
39
|
-
HostSingletonTag,
|
|
40
|
-
HostTextTag,
|
|
41
|
-
LegacyHiddenComponentTag,
|
|
42
|
-
MemoComponentTag,
|
|
24
|
+
getReactWorkTagsForFiber,
|
|
43
25
|
MutationMask,
|
|
44
|
-
OffscreenComponentTag,
|
|
45
26
|
ReactBuildType,
|
|
46
27
|
ReactFiberFlags,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
} from "./react-internals.js";
|
|
51
|
-
import { toUnsubscribe, type Unsubscribe } from "./unsubscribe.js";
|
|
28
|
+
ReactSymbols,
|
|
29
|
+
setReactWorkTagsForFiber,
|
|
30
|
+
} from "./react-internals/index.js";
|
|
52
31
|
|
|
53
32
|
export {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION,
|
|
61
|
-
DEPRECATED_ASYNC_MODE_SYMBOL_STRING,
|
|
62
|
-
DehydratedSuspenseComponentTag,
|
|
63
|
-
ELEMENT_TYPE_SYMBOL_STRING,
|
|
64
|
-
ForwardRefTag,
|
|
65
|
-
FragmentTag,
|
|
66
|
-
FunctionComponentTag,
|
|
67
|
-
HostComponentTag,
|
|
68
|
-
HostHoistableTag,
|
|
69
|
-
HostPortalTag,
|
|
70
|
-
HostRootTag,
|
|
71
|
-
HostSingletonTag,
|
|
72
|
-
HostTextTag,
|
|
73
|
-
LazyComponentTag,
|
|
74
|
-
LegacyHiddenComponentTag,
|
|
75
|
-
MemoComponentTag,
|
|
76
|
-
OffscreenComponentTag,
|
|
77
|
-
SimpleMemoComponentTag,
|
|
78
|
-
SuspenseComponentTag,
|
|
79
|
-
SuspenseListComponentTag,
|
|
80
|
-
TRANSITIONAL_ELEMENT_TYPE_SYMBOL_STRING,
|
|
81
|
-
ViewTransitionComponentTag,
|
|
82
|
-
} from "./react-internals.js";
|
|
83
|
-
|
|
84
|
-
const { Cloned, PerformedWork } = ReactFiberFlags;
|
|
85
|
-
|
|
86
|
-
const isObjectRecord = (value: unknown): value is Record<string, unknown> =>
|
|
87
|
-
typeof value === "object" && value !== null;
|
|
33
|
+
BippyError,
|
|
34
|
+
BippyHookInspectionError,
|
|
35
|
+
BippyHookRenderError,
|
|
36
|
+
BippySourceMapError,
|
|
37
|
+
BippyUnsupportedHookError,
|
|
38
|
+
} from "./errors.js";
|
|
88
39
|
|
|
89
40
|
const isComponentType = (value: unknown): value is React.ComponentType<unknown> =>
|
|
90
41
|
typeof value === "function";
|
|
91
42
|
|
|
92
|
-
const getPropertyValue = (value: object, key: PropertyKey): unknown => {
|
|
93
|
-
let currentValue: object | null = value;
|
|
94
|
-
while (currentValue) {
|
|
95
|
-
const descriptor = Object.getOwnPropertyDescriptor(currentValue, key);
|
|
96
|
-
if (descriptor) {
|
|
97
|
-
if ("value" in descriptor) return descriptor.value;
|
|
98
|
-
return descriptor.get?.call(value);
|
|
99
|
-
}
|
|
100
|
-
currentValue = Object.getPrototypeOf(currentValue);
|
|
101
|
-
}
|
|
102
|
-
return undefined;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
43
|
const getTypeName = (value: object): string | null => {
|
|
106
|
-
const displayName =
|
|
44
|
+
const displayName = "displayName" in value ? value.displayName : null;
|
|
107
45
|
if (typeof displayName === "string" && displayName) return displayName;
|
|
108
|
-
const name =
|
|
46
|
+
const name = "name" in value ? value.name : null;
|
|
109
47
|
return typeof name === "string" && name ? name : null;
|
|
110
48
|
};
|
|
111
49
|
|
|
@@ -113,6 +51,10 @@ interface FiberSelector {
|
|
|
113
51
|
(node: Fiber): boolean | Promise<boolean | void> | void;
|
|
114
52
|
}
|
|
115
53
|
|
|
54
|
+
export interface RenderHandler {
|
|
55
|
+
(fiber: Fiber, phase: RenderPhase): unknown;
|
|
56
|
+
}
|
|
57
|
+
|
|
116
58
|
/**
|
|
117
59
|
* Returns `true` if object is a React Element.
|
|
118
60
|
*
|
|
@@ -122,9 +64,8 @@ export const isValidElement = (element: unknown): element is React.ReactElement
|
|
|
122
64
|
typeof element === "object" &&
|
|
123
65
|
element !== null &&
|
|
124
66
|
"$$typeof" in element &&
|
|
125
|
-
|
|
126
|
-
String(element.$$typeof)
|
|
127
|
-
);
|
|
67
|
+
(String(element.$$typeof) === ReactSymbols.LEGACY_ELEMENT_SYMBOL_STRING ||
|
|
68
|
+
String(element.$$typeof) === ReactSymbols.ELEMENT_SYMBOL_STRING);
|
|
128
69
|
|
|
129
70
|
/**
|
|
130
71
|
* Returns `true` if object is a React Fiber.
|
|
@@ -139,17 +80,24 @@ export const isValidFiber = (fiber: unknown): fiber is Fiber =>
|
|
|
139
80
|
"sibling" in fiber &&
|
|
140
81
|
"flags" in fiber;
|
|
141
82
|
|
|
83
|
+
const isFiberRoot = (fiberRoot: unknown): fiberRoot is FiberRoot =>
|
|
84
|
+
typeof fiberRoot === "object" &&
|
|
85
|
+
fiberRoot !== null &&
|
|
86
|
+
"current" in fiberRoot &&
|
|
87
|
+
isValidFiber(fiberRoot.current);
|
|
88
|
+
|
|
142
89
|
/**
|
|
143
90
|
* Returns `true` if fiber is a host fiber. Host fibers are DOM nodes in react-dom, `View` in react-native, etc.
|
|
144
91
|
*
|
|
145
92
|
* @see https://reactnative.dev/architecture/glossary#host-view-tree-and-host-view
|
|
146
93
|
*/
|
|
147
94
|
export const isHostFiber = (fiber: Fiber): fiber is HostFiber => {
|
|
95
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
148
96
|
switch (fiber.tag) {
|
|
149
|
-
case
|
|
150
|
-
case
|
|
151
|
-
case
|
|
152
|
-
case
|
|
97
|
+
case workTags.HostComponent:
|
|
98
|
+
case workTags.HostText:
|
|
99
|
+
case workTags.HostHoistable:
|
|
100
|
+
case workTags.HostSingleton:
|
|
153
101
|
return true;
|
|
154
102
|
default:
|
|
155
103
|
return false;
|
|
@@ -162,12 +110,13 @@ export const isHostFiber = (fiber: Fiber): fiber is HostFiber => {
|
|
|
162
110
|
* @see https://reactnative.dev/architecture/glossary#react-composite-components
|
|
163
111
|
*/
|
|
164
112
|
export const isCompositeFiber = (fiber: Fiber): boolean => {
|
|
113
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
165
114
|
switch (fiber.tag) {
|
|
166
|
-
case
|
|
167
|
-
case
|
|
168
|
-
case
|
|
169
|
-
case
|
|
170
|
-
case
|
|
115
|
+
case workTags.ClassComponent:
|
|
116
|
+
case workTags.ForwardRef:
|
|
117
|
+
case workTags.FunctionComponent:
|
|
118
|
+
case workTags.MemoComponent:
|
|
119
|
+
case workTags.SimpleMemoComponent:
|
|
171
120
|
return true;
|
|
172
121
|
default:
|
|
173
122
|
return false;
|
|
@@ -184,90 +133,6 @@ export const isFiber = (maybeFiber: unknown): maybeFiber is Fiber => {
|
|
|
184
133
|
return "pendingProps" in maybeFiber && !("containerInfo" in maybeFiber);
|
|
185
134
|
};
|
|
186
135
|
|
|
187
|
-
/**
|
|
188
|
-
* Traverses up or down a {@link Fiber}'s contexts, return `true` to stop and select the current and previous context value.
|
|
189
|
-
*/
|
|
190
|
-
export const traverseContexts = (
|
|
191
|
-
fiber: Fiber,
|
|
192
|
-
selector: (
|
|
193
|
-
nextValue: ContextDependency<unknown> | null | undefined,
|
|
194
|
-
prevValue: ContextDependency<unknown> | null | undefined,
|
|
195
|
-
) => boolean | void,
|
|
196
|
-
): boolean => {
|
|
197
|
-
try {
|
|
198
|
-
const nextDependencies = fiber.dependencies;
|
|
199
|
-
const prevDependencies = fiber.alternate?.dependencies;
|
|
200
|
-
|
|
201
|
-
if (!nextDependencies || !prevDependencies) return false;
|
|
202
|
-
if (
|
|
203
|
-
typeof nextDependencies !== "object" ||
|
|
204
|
-
!("firstContext" in nextDependencies) ||
|
|
205
|
-
typeof prevDependencies !== "object" ||
|
|
206
|
-
!("firstContext" in prevDependencies)
|
|
207
|
-
) {
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
let nextContext: ContextDependency<unknown> | null | undefined = nextDependencies.firstContext;
|
|
211
|
-
let prevContext: ContextDependency<unknown> | null | undefined = prevDependencies.firstContext;
|
|
212
|
-
while (
|
|
213
|
-
(nextContext && typeof nextContext === "object" && "memoizedValue" in nextContext) ||
|
|
214
|
-
(prevContext && typeof prevContext === "object" && "memoizedValue" in prevContext)
|
|
215
|
-
) {
|
|
216
|
-
if (selector(nextContext, prevContext) === true) return true;
|
|
217
|
-
|
|
218
|
-
nextContext = nextContext?.next;
|
|
219
|
-
prevContext = prevContext?.next;
|
|
220
|
-
}
|
|
221
|
-
} catch {}
|
|
222
|
-
return false;
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* 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.
|
|
227
|
-
*/
|
|
228
|
-
export const traverseState = (
|
|
229
|
-
fiber: Fiber,
|
|
230
|
-
selector: (
|
|
231
|
-
nextValue: MemoizedState | null | undefined,
|
|
232
|
-
prevValue: MemoizedState | null | undefined,
|
|
233
|
-
) => boolean | void,
|
|
234
|
-
): boolean => {
|
|
235
|
-
try {
|
|
236
|
-
let nextState: MemoizedState | null | undefined = fiber.memoizedState;
|
|
237
|
-
let prevState: MemoizedState | null | undefined = fiber.alternate?.memoizedState;
|
|
238
|
-
|
|
239
|
-
while (nextState || prevState) {
|
|
240
|
-
if (selector(nextState, prevState) === true) return true;
|
|
241
|
-
|
|
242
|
-
nextState = nextState?.next;
|
|
243
|
-
prevState = prevState?.next;
|
|
244
|
-
}
|
|
245
|
-
} catch {}
|
|
246
|
-
return false;
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Traverses up or down a {@link Fiber}'s props, return `true` to stop and select the current and previous props value.
|
|
251
|
-
*/
|
|
252
|
-
export const traverseProps = (
|
|
253
|
-
fiber: Fiber,
|
|
254
|
-
selector: (propName: string, nextValue: unknown, prevValue: unknown) => boolean | void,
|
|
255
|
-
): boolean => {
|
|
256
|
-
try {
|
|
257
|
-
const nextProps = fiber.memoizedProps;
|
|
258
|
-
const prevProps = fiber.alternate?.memoizedProps || {};
|
|
259
|
-
|
|
260
|
-
for (const propName of Object.keys(nextProps)) {
|
|
261
|
-
if (selector(propName, nextProps[propName], prevProps[propName]) === true) return true;
|
|
262
|
-
}
|
|
263
|
-
for (const propName of Object.keys(prevProps)) {
|
|
264
|
-
if (propName in nextProps) continue;
|
|
265
|
-
if (selector(propName, nextProps[propName], prevProps[propName]) === true) return true;
|
|
266
|
-
}
|
|
267
|
-
} catch {}
|
|
268
|
-
return false;
|
|
269
|
-
};
|
|
270
|
-
|
|
271
136
|
/**
|
|
272
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.
|
|
273
138
|
*/
|
|
@@ -275,15 +140,16 @@ export const didFiberRender = (fiber: Fiber): boolean => {
|
|
|
275
140
|
const nextProps = fiber.memoizedProps;
|
|
276
141
|
const prevProps = fiber.alternate?.memoizedProps || {};
|
|
277
142
|
const flags = fiber.flags ?? fiber.effectTag ?? 0;
|
|
143
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
278
144
|
|
|
279
145
|
switch (fiber.tag) {
|
|
280
|
-
case
|
|
281
|
-
case
|
|
282
|
-
case
|
|
283
|
-
case
|
|
284
|
-
case
|
|
285
|
-
case
|
|
286
|
-
return (flags & PerformedWork) === PerformedWork;
|
|
146
|
+
case workTags.ClassComponent:
|
|
147
|
+
case workTags.ContextConsumer:
|
|
148
|
+
case workTags.ForwardRef:
|
|
149
|
+
case workTags.FunctionComponent:
|
|
150
|
+
case workTags.MemoComponent:
|
|
151
|
+
case workTags.SimpleMemoComponent: {
|
|
152
|
+
return (flags & ReactFiberFlags.PerformedWork) === ReactFiberFlags.PerformedWork;
|
|
287
153
|
}
|
|
288
154
|
default:
|
|
289
155
|
// Host nodes (DOM, root, etc.)
|
|
@@ -301,58 +167,18 @@ export const didFiberRender = (fiber: Fiber): boolean => {
|
|
|
301
167
|
*/
|
|
302
168
|
export const didFiberCommit = (fiber: Fiber): boolean => {
|
|
303
169
|
return Boolean(
|
|
304
|
-
(fiber.flags & (MutationMask | Cloned)) !== 0 ||
|
|
305
|
-
(fiber.subtreeFlags & (MutationMask | Cloned)) !== 0,
|
|
170
|
+
(fiber.flags & (MutationMask | ReactFiberFlags.Cloned)) !== 0 ||
|
|
171
|
+
(fiber.subtreeFlags & (MutationMask | ReactFiberFlags.Cloned)) !== 0,
|
|
306
172
|
);
|
|
307
173
|
};
|
|
308
174
|
|
|
309
|
-
/**
|
|
310
|
-
* Returns all host {@link Fiber}s that have committed and rendered.
|
|
311
|
-
*/
|
|
312
|
-
export const getMutatedHostFibers = (fiber: Fiber): Fiber[] => {
|
|
313
|
-
const mutations: Fiber[] = [];
|
|
314
|
-
const stack: Fiber[] = [fiber];
|
|
315
|
-
|
|
316
|
-
while (stack.length) {
|
|
317
|
-
const node = stack.pop();
|
|
318
|
-
if (!node) continue;
|
|
319
|
-
|
|
320
|
-
if (isHostFiber(node) && didFiberCommit(node) && didFiberRender(node)) {
|
|
321
|
-
mutations.push(node);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
if (node.child) stack.push(node.child);
|
|
325
|
-
if (node.sibling) stack.push(node.sibling);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return mutations;
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Returns the stack of {@link Fiber}s from the current fiber to the root fiber.
|
|
333
|
-
*
|
|
334
|
-
* @example
|
|
335
|
-
* ```ts
|
|
336
|
-
* [fiber, fiber.return, fiber.return.return, ...]
|
|
337
|
-
* ```
|
|
338
|
-
*/
|
|
339
|
-
export const getFiberStack = (fiber: Fiber): Fiber[] => {
|
|
340
|
-
const stack: Fiber[] = [];
|
|
341
|
-
let currentFiber = fiber;
|
|
342
|
-
while (currentFiber.return) {
|
|
343
|
-
stack.push(currentFiber);
|
|
344
|
-
const parentFiber = currentFiber.return;
|
|
345
|
-
currentFiber = parentFiber;
|
|
346
|
-
}
|
|
347
|
-
return stack;
|
|
348
|
-
};
|
|
349
|
-
|
|
350
175
|
/**
|
|
351
176
|
* Returns `true` if the {@link Fiber} should be filtered out during reconciliation.
|
|
352
177
|
*/
|
|
353
178
|
const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
179
|
+
const workTags = getReactWorkTagsForFiber(fiber);
|
|
354
180
|
switch (fiber.tag) {
|
|
355
|
-
case
|
|
181
|
+
case workTags.DehydratedSuspenseComponent:
|
|
356
182
|
// TODO: ideally we would show dehydrated Suspense immediately.
|
|
357
183
|
// However, it has some special behavior (like disconnecting
|
|
358
184
|
// an alternate and turning into real Suspense) which breaks DevTools.
|
|
@@ -360,13 +186,13 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
360
186
|
// https://github.com/bvaughn/react-devtools-experimental/issues/197
|
|
361
187
|
return true;
|
|
362
188
|
|
|
363
|
-
case
|
|
364
|
-
case
|
|
365
|
-
case
|
|
366
|
-
case
|
|
189
|
+
case workTags.Fragment:
|
|
190
|
+
case workTags.HostText:
|
|
191
|
+
case workTags.LegacyHiddenComponent:
|
|
192
|
+
case workTags.OffscreenComponent:
|
|
367
193
|
return true;
|
|
368
194
|
|
|
369
|
-
case
|
|
195
|
+
case workTags.HostRoot:
|
|
370
196
|
// It is never valid to filter the root element.
|
|
371
197
|
return false;
|
|
372
198
|
|
|
@@ -376,15 +202,15 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
376
202
|
|
|
377
203
|
if (typeof symbolOrNumber === "symbol") {
|
|
378
204
|
return (
|
|
379
|
-
symbolOrNumber.description === CONCURRENT_MODE_SYMBOL_DESCRIPTION ||
|
|
380
|
-
symbolOrNumber.description === DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION
|
|
205
|
+
symbolOrNumber.description === ReactSymbols.CONCURRENT_MODE_SYMBOL_DESCRIPTION ||
|
|
206
|
+
symbolOrNumber.description === ReactSymbols.DEPRECATED_ASYNC_MODE_SYMBOL_DESCRIPTION
|
|
381
207
|
);
|
|
382
208
|
}
|
|
383
209
|
|
|
384
210
|
switch (symbolOrNumber) {
|
|
385
|
-
case CONCURRENT_MODE_NUMBER:
|
|
386
|
-
case CONCURRENT_MODE_SYMBOL_STRING:
|
|
387
|
-
case DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
|
|
211
|
+
case ReactSymbols.CONCURRENT_MODE_NUMBER:
|
|
212
|
+
case ReactSymbols.CONCURRENT_MODE_SYMBOL_STRING:
|
|
213
|
+
case ReactSymbols.DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
|
|
388
214
|
return true;
|
|
389
215
|
|
|
390
216
|
default:
|
|
@@ -394,47 +220,6 @@ const shouldFilterFiber = (fiber: Fiber): boolean => {
|
|
|
394
220
|
}
|
|
395
221
|
};
|
|
396
222
|
|
|
397
|
-
/**
|
|
398
|
-
* Returns the nearest host {@link Fiber} to the current {@link Fiber}.
|
|
399
|
-
*/
|
|
400
|
-
export const getNearestHostFiber = (fiber: Fiber, ascending = false): Fiber | null => {
|
|
401
|
-
let hostFiber = traverseFiber(fiber, isHostFiber, ascending);
|
|
402
|
-
if (!hostFiber) {
|
|
403
|
-
hostFiber = traverseFiber(fiber, isHostFiber, !ascending);
|
|
404
|
-
}
|
|
405
|
-
return hostFiber;
|
|
406
|
-
};
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Returns all host {@link Fiber}s in the tree that are associated with the current {@link Fiber}.
|
|
410
|
-
*/
|
|
411
|
-
export const getNearestHostFibers = (fiber: Fiber): Fiber[] => {
|
|
412
|
-
const hostFibers: Fiber[] = [];
|
|
413
|
-
const stack: Fiber[] = [];
|
|
414
|
-
|
|
415
|
-
if (isHostFiber(fiber)) {
|
|
416
|
-
hostFibers.push(fiber);
|
|
417
|
-
} else if (fiber.child) {
|
|
418
|
-
stack.push(fiber.child);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
while (stack.length) {
|
|
422
|
-
const currentNode = stack.pop();
|
|
423
|
-
if (!currentNode) break;
|
|
424
|
-
if (isHostFiber(currentNode)) {
|
|
425
|
-
hostFibers.push(currentNode);
|
|
426
|
-
} else if (currentNode.child) {
|
|
427
|
-
stack.push(currentNode.child);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
if (currentNode.sibling) {
|
|
431
|
-
stack.push(currentNode.sibling);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
return hostFibers;
|
|
436
|
-
};
|
|
437
|
-
|
|
438
223
|
/**
|
|
439
224
|
* Traverses up or down a {@link Fiber}, return `true` to stop and select a node.
|
|
440
225
|
*/
|
|
@@ -448,6 +233,11 @@ export function traverseFiber(
|
|
|
448
233
|
selector: (node: Fiber) => Promise<boolean | void>,
|
|
449
234
|
ascending?: boolean,
|
|
450
235
|
): Promise<Fiber | null>;
|
|
236
|
+
export function traverseFiber(
|
|
237
|
+
fiber: Fiber | null,
|
|
238
|
+
selector: FiberSelector,
|
|
239
|
+
ascending?: boolean,
|
|
240
|
+
): Fiber | null | Promise<Fiber | null>;
|
|
451
241
|
export function traverseFiber(
|
|
452
242
|
fiber: Fiber | null,
|
|
453
243
|
selector: FiberSelector,
|
|
@@ -455,89 +245,47 @@ export function traverseFiber(
|
|
|
455
245
|
): Fiber | null | Promise<Fiber | null> {
|
|
456
246
|
if (!fiber) return null;
|
|
457
247
|
|
|
458
|
-
const
|
|
459
|
-
if (
|
|
460
|
-
return (
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
let child = ascending ? fiber.return : fiber.child;
|
|
464
|
-
while (child) {
|
|
465
|
-
const match = await traverseFiberAsync(child, selector, ascending);
|
|
466
|
-
if (match) return match;
|
|
467
|
-
child = ascending ? null : child.sibling;
|
|
468
|
-
}
|
|
469
|
-
return null;
|
|
470
|
-
})();
|
|
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
|
+
);
|
|
471
253
|
}
|
|
254
|
+
if (selection === true) return fiber;
|
|
472
255
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
let child = ascending ? fiber.return : fiber.child;
|
|
476
|
-
while (child) {
|
|
477
|
-
const match = traverseFiberSync(child, selector, ascending);
|
|
478
|
-
if (match) return match;
|
|
479
|
-
child = ascending ? null : child.sibling;
|
|
480
|
-
}
|
|
481
|
-
return null;
|
|
256
|
+
return traverseFiberChildren(fiber, selector, ascending);
|
|
482
257
|
}
|
|
483
258
|
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
if (!fiber) return null;
|
|
490
|
-
const selection = selector(fiber);
|
|
491
|
-
if (selection instanceof Promise) return null;
|
|
492
|
-
if (selection === true) return fiber;
|
|
493
|
-
|
|
494
|
-
let child = ascending ? fiber.return : fiber.child;
|
|
495
|
-
while (child) {
|
|
496
|
-
const match = traverseFiberSync(child, selector, ascending);
|
|
497
|
-
if (match) return match;
|
|
259
|
+
const isPromiseLike = <Result>(value: unknown): value is PromiseLike<Result> =>
|
|
260
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
261
|
+
value !== null &&
|
|
262
|
+
"then" in value &&
|
|
263
|
+
typeof value.then === "function";
|
|
498
264
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
265
|
+
const traverseFiberChildren = (
|
|
266
|
+
fiber: Fiber,
|
|
267
|
+
selector: FiberSelector,
|
|
268
|
+
ascending: boolean,
|
|
269
|
+
): Fiber | null | Promise<Fiber | null> => {
|
|
270
|
+
const firstChild = ascending ? fiber.return : fiber.child;
|
|
271
|
+
return traverseFiberSiblings(firstChild, selector, ascending);
|
|
502
272
|
};
|
|
503
273
|
|
|
504
|
-
const
|
|
274
|
+
const traverseFiberSiblings = (
|
|
505
275
|
fiber: Fiber | null,
|
|
506
276
|
selector: FiberSelector,
|
|
507
|
-
ascending
|
|
508
|
-
): Promise<Fiber | null> => {
|
|
277
|
+
ascending: boolean,
|
|
278
|
+
): Fiber | null | Promise<Fiber | null> => {
|
|
509
279
|
if (!fiber) return null;
|
|
510
|
-
if ((await selector(fiber)) === true) return fiber;
|
|
511
|
-
|
|
512
|
-
let child = ascending ? fiber.return : fiber.child;
|
|
513
|
-
while (child) {
|
|
514
|
-
const match = await traverseFiberAsync(child, selector, ascending);
|
|
515
|
-
if (match) return match;
|
|
516
280
|
|
|
517
|
-
|
|
281
|
+
const nextSibling = ascending ? null : fiber.sibling;
|
|
282
|
+
const match = traverseFiber(fiber, selector, ascending);
|
|
283
|
+
if (isPromiseLike<Fiber | null>(match)) {
|
|
284
|
+
return Promise.resolve(match).then(
|
|
285
|
+
(resolvedMatch) => resolvedMatch ?? traverseFiberSiblings(nextSibling, selector, ascending),
|
|
286
|
+
);
|
|
518
287
|
}
|
|
519
|
-
return
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* Returns the timings of the {@link Fiber}.
|
|
524
|
-
*
|
|
525
|
-
* @example
|
|
526
|
-
* ```ts
|
|
527
|
-
* const { selfTime, totalTime } = getTimings(fiber);
|
|
528
|
-
* console.log(selfTime, totalTime);
|
|
529
|
-
* ```
|
|
530
|
-
*/
|
|
531
|
-
export const getTimings = (fiber?: Fiber | null): { selfTime: number; totalTime: number } => {
|
|
532
|
-
const totalTime = fiber?.actualDuration ?? 0;
|
|
533
|
-
let selfTime = totalTime;
|
|
534
|
-
// TODO: calculate a DOM time, which is just host component summed up
|
|
535
|
-
let child = fiber?.child ?? null;
|
|
536
|
-
while (totalTime > 0 && child !== null) {
|
|
537
|
-
selfTime -= child.actualDuration ?? 0;
|
|
538
|
-
child = child.sibling;
|
|
539
|
-
}
|
|
540
|
-
return { selfTime, totalTime };
|
|
288
|
+
return match ?? traverseFiberSiblings(nextSibling, selector, ascending);
|
|
541
289
|
};
|
|
542
290
|
|
|
543
291
|
/**
|
|
@@ -552,8 +300,8 @@ export const hasMemoCache = (fiber: Fiber): boolean => {
|
|
|
552
300
|
*/
|
|
553
301
|
export const getType = (type: unknown): null | React.ComponentType<unknown> => {
|
|
554
302
|
if (isComponentType(type)) return type;
|
|
555
|
-
if (
|
|
556
|
-
return getType(
|
|
303
|
+
if (typeof type !== "object" || type === null) return null;
|
|
304
|
+
return getType(Reflect.get(type, "type") ?? Reflect.get(type, "render"));
|
|
557
305
|
};
|
|
558
306
|
|
|
559
307
|
/**
|
|
@@ -593,6 +341,7 @@ export const isInstrumentationActive = (): boolean => {
|
|
|
593
341
|
};
|
|
594
342
|
|
|
595
343
|
export const _fiberRoots = new Set<FiberRoot>();
|
|
344
|
+
const rootRendererIds = new WeakMap<FiberRoot, number>();
|
|
596
345
|
|
|
597
346
|
/**
|
|
598
347
|
* Returns the latest fiber (since it may be double-buffered).
|
|
@@ -605,35 +354,54 @@ export const getLatestFiber = (fiber: Fiber): Fiber => {
|
|
|
605
354
|
}
|
|
606
355
|
for (const root of _fiberRoots) {
|
|
607
356
|
const latestFiber = traverseFiber(root.current, (innerFiber) => {
|
|
608
|
-
if (innerFiber === fiber) return true;
|
|
357
|
+
if (innerFiber === fiber || innerFiber === alternate) return true;
|
|
609
358
|
});
|
|
610
359
|
if (latestFiber) return latestFiber;
|
|
611
360
|
}
|
|
612
361
|
return fiber;
|
|
613
362
|
};
|
|
614
363
|
|
|
615
|
-
|
|
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
|
+
};
|
|
616
382
|
|
|
617
383
|
export type RenderPhase = "mount" | "unmount" | "update";
|
|
618
384
|
|
|
619
|
-
let
|
|
385
|
+
let nextFiberId = 0;
|
|
620
386
|
const fiberIdMap = new WeakMap<Fiber, number>();
|
|
621
387
|
|
|
622
|
-
export const setFiberId = (fiber: Fiber,
|
|
623
|
-
fiberIdMap.set(fiber,
|
|
388
|
+
export const setFiberId = (fiber: Fiber, fiberId: number = nextFiberId++): void => {
|
|
389
|
+
fiberIdMap.set(fiber, fiberId);
|
|
390
|
+
if (Number.isSafeInteger(fiberId) && fiberId >= nextFiberId) {
|
|
391
|
+
nextFiberId = fiberId + 1;
|
|
392
|
+
}
|
|
624
393
|
};
|
|
625
394
|
|
|
626
|
-
// Fiber alternates share an identity across double-buffered commits.
|
|
627
395
|
export const getFiberId = (fiber: Fiber): number => {
|
|
628
|
-
let
|
|
629
|
-
if (
|
|
630
|
-
|
|
396
|
+
let currentFiberId = fiberIdMap.get(fiber);
|
|
397
|
+
if (currentFiberId === undefined && fiber.alternate) {
|
|
398
|
+
currentFiberId = fiberIdMap.get(fiber.alternate);
|
|
631
399
|
}
|
|
632
|
-
if (
|
|
633
|
-
|
|
634
|
-
setFiberId(fiber,
|
|
400
|
+
if (currentFiberId === undefined) {
|
|
401
|
+
currentFiberId = nextFiberId++;
|
|
402
|
+
setFiberId(fiber, currentFiberId);
|
|
635
403
|
}
|
|
636
|
-
return
|
|
404
|
+
return currentFiberId;
|
|
637
405
|
};
|
|
638
406
|
|
|
639
407
|
const mountFiberRecursively = (
|
|
@@ -644,15 +412,13 @@ const mountFiberRecursively = (
|
|
|
644
412
|
let fiber: Fiber | null = firstChild;
|
|
645
413
|
|
|
646
414
|
while (fiber !== null) {
|
|
647
|
-
|
|
648
|
-
getFiberId(fiber);
|
|
649
|
-
}
|
|
415
|
+
getFiberId(fiber);
|
|
650
416
|
const shouldIncludeInTree = !shouldFilterFiber(fiber);
|
|
651
417
|
if (shouldIncludeInTree && didFiberRender(fiber)) {
|
|
652
418
|
onRender(fiber, "mount");
|
|
653
419
|
}
|
|
654
420
|
|
|
655
|
-
if (fiber.tag ===
|
|
421
|
+
if (fiber.tag === getReactWorkTagsForFiber(fiber).SuspenseComponent) {
|
|
656
422
|
const isTimedOut = fiber.memoizedState !== null;
|
|
657
423
|
if (isTimedOut) {
|
|
658
424
|
// Special case: if Suspense mounts in a timed-out state,
|
|
@@ -682,18 +448,13 @@ const mountFiberRecursively = (
|
|
|
682
448
|
const updateFiberRecursively = (
|
|
683
449
|
onRender: RenderHandler,
|
|
684
450
|
nextFiber: Fiber,
|
|
685
|
-
prevFiber: Fiber,
|
|
686
|
-
parentFiber: Fiber | null,
|
|
451
|
+
prevFiber: Fiber | null,
|
|
687
452
|
): void => {
|
|
688
|
-
|
|
689
|
-
getFiberId(nextFiber);
|
|
690
|
-
}
|
|
453
|
+
getFiberId(nextFiber);
|
|
691
454
|
if (!prevFiber) return;
|
|
692
|
-
|
|
693
|
-
getFiberId(prevFiber);
|
|
694
|
-
}
|
|
455
|
+
getFiberId(prevFiber);
|
|
695
456
|
|
|
696
|
-
const isSuspense = nextFiber.tag ===
|
|
457
|
+
const isSuspense = nextFiber.tag === getReactWorkTagsForFiber(nextFiber).SuspenseComponent;
|
|
697
458
|
|
|
698
459
|
const shouldIncludeInTree = !shouldFilterFiber(nextFiber);
|
|
699
460
|
if (shouldIncludeInTree && didFiberRender(nextFiber)) {
|
|
@@ -722,7 +483,7 @@ const updateFiberRecursively = (
|
|
|
722
483
|
const prevFallbackChildSet = prevFiber.child?.sibling ?? null;
|
|
723
484
|
|
|
724
485
|
if (nextFallbackChildSet !== null && prevFallbackChildSet !== null) {
|
|
725
|
-
updateFiberRecursively(onRender, nextFallbackChildSet, prevFallbackChildSet
|
|
486
|
+
updateFiberRecursively(onRender, nextFallbackChildSet, prevFallbackChildSet);
|
|
726
487
|
}
|
|
727
488
|
} else if (prevDidTimeout && !nextDidTimeOut) {
|
|
728
489
|
// Fallback -> Primary:
|
|
@@ -761,14 +522,7 @@ const updateFiberRecursively = (
|
|
|
761
522
|
// Schedule updates and mounts depending on whether alternates exist.
|
|
762
523
|
// We don't track deletions here because they are reported separately.
|
|
763
524
|
if (nextChild.alternate) {
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
updateFiberRecursively(
|
|
767
|
-
onRender,
|
|
768
|
-
nextChild,
|
|
769
|
-
prevChild,
|
|
770
|
-
shouldIncludeInTree ? nextFiber : parentFiber,
|
|
771
|
-
);
|
|
525
|
+
updateFiberRecursively(onRender, nextChild, nextChild.alternate);
|
|
772
526
|
} else {
|
|
773
527
|
mountFiberRecursively(onRender, nextChild, false);
|
|
774
528
|
}
|
|
@@ -780,7 +534,7 @@ const updateFiberRecursively = (
|
|
|
780
534
|
};
|
|
781
535
|
|
|
782
536
|
const unmountFiber = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
783
|
-
const isRoot = fiber.tag ===
|
|
537
|
+
const isRoot = fiber.tag === getReactWorkTagsForFiber(fiber).HostRoot;
|
|
784
538
|
|
|
785
539
|
if (isRoot || !shouldFilterFiber(fiber)) {
|
|
786
540
|
onRender(fiber, "unmount");
|
|
@@ -789,7 +543,8 @@ const unmountFiber = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
|
789
543
|
|
|
790
544
|
const unmountFiberChildrenRecursively = (onRender: RenderHandler, fiber: Fiber): void => {
|
|
791
545
|
// We might meet a nested Suspense on our way.
|
|
792
|
-
const isTimedOutSuspense =
|
|
546
|
+
const isTimedOutSuspense =
|
|
547
|
+
fiber.tag === getReactWorkTagsForFiber(fiber).SuspenseComponent && fiber.memoizedState !== null;
|
|
793
548
|
let child = fiber.child;
|
|
794
549
|
|
|
795
550
|
if (isTimedOutSuspense) {
|
|
@@ -813,11 +568,9 @@ const unmountFiberChildrenRecursively = (onRender: RenderHandler, fiber: Fiber):
|
|
|
813
568
|
}
|
|
814
569
|
};
|
|
815
570
|
|
|
816
|
-
let commitId = 0;
|
|
817
571
|
const rootInstanceMap = new WeakMap<
|
|
818
|
-
FiberRoot,
|
|
572
|
+
Fiber | FiberRoot,
|
|
819
573
|
{
|
|
820
|
-
id: number;
|
|
821
574
|
prevFiber: Fiber | null;
|
|
822
575
|
}
|
|
823
576
|
>();
|
|
@@ -829,23 +582,23 @@ const rootInstanceMap = new WeakMap<
|
|
|
829
582
|
* console.log(phase)
|
|
830
583
|
* })
|
|
831
584
|
*/
|
|
832
|
-
export const traverseRenderedFibers = (root: FiberRoot, onRender: RenderHandler): void => {
|
|
585
|
+
export const traverseRenderedFibers = (root: Fiber | FiberRoot, onRender: RenderHandler): void => {
|
|
833
586
|
const fiber = "current" in root ? root.current : root;
|
|
834
587
|
|
|
835
588
|
let rootInstance = rootInstanceMap.get(root);
|
|
836
589
|
|
|
837
590
|
if (!rootInstance) {
|
|
838
|
-
rootInstance = {
|
|
591
|
+
rootInstance = { prevFiber: null };
|
|
839
592
|
rootInstanceMap.set(root, rootInstance);
|
|
840
593
|
}
|
|
841
594
|
|
|
842
595
|
const { prevFiber } = rootInstance;
|
|
843
|
-
// if fiberRoot don't have current instance, means it's been unmounted
|
|
844
596
|
if (!fiber) {
|
|
845
|
-
|
|
597
|
+
if (prevFiber) {
|
|
598
|
+
unmountFiber(onRender, prevFiber);
|
|
599
|
+
}
|
|
846
600
|
} else if (prevFiber !== null) {
|
|
847
601
|
const wasMounted =
|
|
848
|
-
prevFiber &&
|
|
849
602
|
prevFiber.memoizedState !== null &&
|
|
850
603
|
prevFiber.memoizedState.element !== null &&
|
|
851
604
|
prevFiber.memoizedState.element !== undefined &&
|
|
@@ -861,7 +614,7 @@ export const traverseRenderedFibers = (root: FiberRoot, onRender: RenderHandler)
|
|
|
861
614
|
if (!wasMounted && isMounted) {
|
|
862
615
|
mountFiberRecursively(onRender, fiber, false);
|
|
863
616
|
} else if (wasMounted && isMounted) {
|
|
864
|
-
updateFiberRecursively(onRender, fiber, fiber.alternate
|
|
617
|
+
updateFiberRecursively(onRender, fiber, fiber.alternate);
|
|
865
618
|
} else if (wasMounted && !isMounted) {
|
|
866
619
|
unmountFiber(onRender, fiber);
|
|
867
620
|
}
|
|
@@ -872,168 +625,6 @@ export const traverseRenderedFibers = (root: FiberRoot, onRender: RenderHandler)
|
|
|
872
625
|
rootInstance.prevFiber = fiber;
|
|
873
626
|
};
|
|
874
627
|
|
|
875
|
-
const overrideRenderers = new Set<ReactRenderer>();
|
|
876
|
-
let areOverrideRenderersWired = false;
|
|
877
|
-
|
|
878
|
-
const wireOverrideRenderers = (): void => {
|
|
879
|
-
if (!hasRDTHook()) return;
|
|
880
|
-
const rdtHook = getRDTHook();
|
|
881
|
-
if (!rdtHook?.renderers) return;
|
|
882
|
-
|
|
883
|
-
ensureHookDispatchesToListeners(rdtHook);
|
|
884
|
-
for (const renderer of rdtHook.renderers.values()) {
|
|
885
|
-
overrideRenderers.add(renderer);
|
|
886
|
-
}
|
|
887
|
-
if (areOverrideRenderersWired) return;
|
|
888
|
-
areOverrideRenderersWired = true;
|
|
889
|
-
onRendererInject((renderer) => {
|
|
890
|
-
overrideRenderers.add(renderer);
|
|
891
|
-
});
|
|
892
|
-
};
|
|
893
|
-
|
|
894
|
-
const getRootRenderer = (fiber: Fiber): ReactRenderer | null => {
|
|
895
|
-
if (!hasRDTHook()) return null;
|
|
896
|
-
let hostRootFiber = fiber;
|
|
897
|
-
while (hostRootFiber.return) {
|
|
898
|
-
hostRootFiber = hostRootFiber.return;
|
|
899
|
-
}
|
|
900
|
-
const rendererId = rootRendererIds.get(hostRootFiber.stateNode);
|
|
901
|
-
if (rendererId === undefined) return null;
|
|
902
|
-
return getRDTHook().renderers?.get(rendererId) ?? null;
|
|
903
|
-
};
|
|
904
|
-
|
|
905
|
-
// dispatch to the renderer that owns the fiber's root when known; renderers
|
|
906
|
-
// that never committed through bippy's hook patch fall back to "try all",
|
|
907
|
-
// which matches the pre-ownership behavior for single-renderer apps
|
|
908
|
-
const resolveOverrideRenderers = (fiber: Fiber): ReactRenderer[] => {
|
|
909
|
-
wireOverrideRenderers();
|
|
910
|
-
const rootRenderer = getRootRenderer(fiber);
|
|
911
|
-
if (rootRenderer) return [rootRenderer];
|
|
912
|
-
return Array.from(overrideRenderers);
|
|
913
|
-
};
|
|
914
|
-
|
|
915
|
-
const applyPropsOverride = (
|
|
916
|
-
renderers: ReactRenderer[],
|
|
917
|
-
fiber: Fiber,
|
|
918
|
-
path: string[],
|
|
919
|
-
value: unknown,
|
|
920
|
-
): void => {
|
|
921
|
-
for (const renderer of renderers) {
|
|
922
|
-
try {
|
|
923
|
-
renderer.overrideProps?.(fiber, path, value);
|
|
924
|
-
} catch {}
|
|
925
|
-
}
|
|
926
|
-
};
|
|
927
|
-
|
|
928
|
-
const getHookStateDispatch = (
|
|
929
|
-
fiber: Fiber,
|
|
930
|
-
hookIndex: number,
|
|
931
|
-
): ((value: unknown) => void) | null => {
|
|
932
|
-
let hookState = fiber.memoizedState;
|
|
933
|
-
for (let i = 0; i < hookIndex; i++) {
|
|
934
|
-
if (!hookState?.next) return null;
|
|
935
|
-
hookState = hookState.next;
|
|
936
|
-
}
|
|
937
|
-
const queue = hookState?.queue;
|
|
938
|
-
if (!isPOJO(queue)) return null;
|
|
939
|
-
const dispatch = queue.dispatch;
|
|
940
|
-
return typeof dispatch === "function" ? (value) => dispatch(value) : null;
|
|
941
|
-
};
|
|
942
|
-
|
|
943
|
-
const findContextProviderFiber = (fiber: Fiber, contextType: unknown): Fiber | null => {
|
|
944
|
-
let currentFiber: Fiber | null = fiber;
|
|
945
|
-
while (currentFiber) {
|
|
946
|
-
const fiberType = currentFiber.type;
|
|
947
|
-
if (fiberType === contextType || fiberType?.Provider === contextType) {
|
|
948
|
-
return currentFiber;
|
|
949
|
-
}
|
|
950
|
-
currentFiber = currentFiber.return;
|
|
951
|
-
}
|
|
952
|
-
return null;
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
const isPOJO = (maybePOJO: unknown): maybePOJO is Record<string, unknown> => {
|
|
956
|
-
return (
|
|
957
|
-
Object.prototype.toString.call(maybePOJO) === "[object Object]" &&
|
|
958
|
-
(Object.getPrototypeOf(maybePOJO) === Object.prototype ||
|
|
959
|
-
Object.getPrototypeOf(maybePOJO) === null)
|
|
960
|
-
);
|
|
961
|
-
};
|
|
962
|
-
|
|
963
|
-
const buildPathsFromValue = (
|
|
964
|
-
maybePOJO: Record<string, unknown>,
|
|
965
|
-
basePath: string[] = [],
|
|
966
|
-
): Array<{ path: string[]; value: unknown }> => {
|
|
967
|
-
if (!isPOJO(maybePOJO)) {
|
|
968
|
-
return [{ path: basePath, value: maybePOJO }];
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
const paths: Array<{ path: string[]; value: unknown }> = [];
|
|
972
|
-
|
|
973
|
-
for (const key in maybePOJO) {
|
|
974
|
-
const value = maybePOJO[key];
|
|
975
|
-
const path = basePath.concat(key);
|
|
976
|
-
|
|
977
|
-
if (isPOJO(value)) {
|
|
978
|
-
paths.push(...buildPathsFromValue(value, path));
|
|
979
|
-
} else {
|
|
980
|
-
paths.push({ path, value });
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
return paths;
|
|
985
|
-
};
|
|
986
|
-
|
|
987
|
-
const buildValueWrites = (partialValue: unknown): Array<{ path: string[]; value: unknown }> =>
|
|
988
|
-
isPOJO(partialValue) ? buildPathsFromValue(partialValue) : [{ path: [], value: partialValue }];
|
|
989
|
-
|
|
990
|
-
export const overrideProps = (fiber: Fiber, partialValue: Record<string, unknown>) => {
|
|
991
|
-
const renderers = resolveOverrideRenderers(fiber);
|
|
992
|
-
for (const { path, value } of buildValueWrites(partialValue)) {
|
|
993
|
-
applyPropsOverride(renderers, fiber, path, value);
|
|
994
|
-
}
|
|
995
|
-
};
|
|
996
|
-
|
|
997
|
-
export const overrideHookState = (fiber: Fiber, id: number, partialValue: unknown) => {
|
|
998
|
-
const renderers = resolveOverrideRenderers(fiber).filter((renderer) =>
|
|
999
|
-
Boolean(renderer.overrideHookState),
|
|
1000
|
-
);
|
|
1001
|
-
const writes = buildValueWrites(partialValue);
|
|
1002
|
-
|
|
1003
|
-
if (renderers.length > 0) {
|
|
1004
|
-
for (const renderer of renderers) {
|
|
1005
|
-
for (const { path, value } of writes) {
|
|
1006
|
-
try {
|
|
1007
|
-
renderer.overrideHookState?.(fiber, id, path, value);
|
|
1008
|
-
} catch {}
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
return;
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
// production renderers don't expose overrideHookState; dispatching through
|
|
1015
|
-
// the hook's own queue still works there, but only for whole-value writes
|
|
1016
|
-
// (a path write through dispatch would replace the entire hook state)
|
|
1017
|
-
if (isPOJO(partialValue)) return;
|
|
1018
|
-
const dispatch = getHookStateDispatch(fiber, id);
|
|
1019
|
-
if (!dispatch) return;
|
|
1020
|
-
try {
|
|
1021
|
-
dispatch(partialValue);
|
|
1022
|
-
} catch {}
|
|
1023
|
-
};
|
|
1024
|
-
|
|
1025
|
-
export const overrideContext = (fiber: Fiber, contextType: unknown, partialValue: unknown) => {
|
|
1026
|
-
const providerFiber = findContextProviderFiber(fiber, contextType);
|
|
1027
|
-
if (!providerFiber) return;
|
|
1028
|
-
const renderers = resolveOverrideRenderers(providerFiber);
|
|
1029
|
-
for (const { path, value } of buildValueWrites(partialValue)) {
|
|
1030
|
-
applyPropsOverride(renderers, providerFiber, ["value", ...path], value);
|
|
1031
|
-
if (providerFiber.alternate) {
|
|
1032
|
-
applyPropsOverride(renderers, providerFiber.alternate, ["value", ...path], value);
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
};
|
|
1036
|
-
|
|
1037
628
|
export interface InstrumentationOptions {
|
|
1038
629
|
name?: string;
|
|
1039
630
|
onActive?: () => unknown;
|
|
@@ -1048,18 +639,11 @@ export interface InstrumentationOptions {
|
|
|
1048
639
|
onScheduleFiberRoot?: (rendererID: number, root: FiberRoot, children: React.ReactNode) => unknown;
|
|
1049
640
|
}
|
|
1050
641
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
>();
|
|
1057
|
-
const postCommitFiberRootListeners = new Set<
|
|
1058
|
-
NonNullable<InstrumentationOptions["onPostCommitFiberRoot"]>
|
|
1059
|
-
>();
|
|
1060
|
-
const scheduleFiberRootListeners = new Set<
|
|
1061
|
-
NonNullable<InstrumentationOptions["onScheduleFiberRoot"]>
|
|
1062
|
-
>();
|
|
642
|
+
interface InstrumentationSubscription {
|
|
643
|
+
options: InstrumentationOptions;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const instrumentationSubscriptions = new Set<InstrumentationSubscription>();
|
|
1063
647
|
|
|
1064
648
|
interface HookDispatchers {
|
|
1065
649
|
onCommitFiberRoot: ReactDevToolsGlobalHook["onCommitFiberRoot"];
|
|
@@ -1069,15 +653,14 @@ interface HookDispatchers {
|
|
|
1069
653
|
}
|
|
1070
654
|
|
|
1071
655
|
const hookDispatchers = new WeakMap<ReactDevToolsGlobalHook, Partial<HookDispatchers>>();
|
|
1072
|
-
|
|
1073
|
-
const rootRendererIds = new WeakMap<FiberRoot, number>();
|
|
656
|
+
let didSubscribeToHookReplacements = false;
|
|
1074
657
|
|
|
1075
658
|
// each hook event is dispatched from a single re-installable wrapper. If
|
|
1076
659
|
// something overwrites the hook method (devtools, direct assignment), the
|
|
1077
660
|
// next instrument() call installs a fresh wrapper over it; a superseded
|
|
1078
661
|
// wrapper still forwards the previous chain but skips the listeners so
|
|
1079
662
|
// they never fire twice.
|
|
1080
|
-
const
|
|
663
|
+
const setHookEventDispatchers = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
1081
664
|
const dispatchers = hookDispatchers.get(rdtHook) ?? {};
|
|
1082
665
|
hookDispatchers.set(rdtHook, dispatchers);
|
|
1083
666
|
|
|
@@ -1092,8 +675,11 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1092
675
|
priority,
|
|
1093
676
|
didError,
|
|
1094
677
|
) => {
|
|
1095
|
-
prevOnCommitFiberRoot
|
|
678
|
+
if (prevOnCommitFiberRoot) {
|
|
679
|
+
prevOnCommitFiberRoot.call(rdtHook, rendererID, root, priority, didError);
|
|
680
|
+
}
|
|
1096
681
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberRoot !== dispatchCommitFiberRoot) return;
|
|
682
|
+
setReactWorkTagsForFiber(root.current, rdtHook.renderers.get(rendererID));
|
|
1097
683
|
const rootMemoizedState = root.current.memoizedState;
|
|
1098
684
|
const isUnmounting =
|
|
1099
685
|
rootMemoizedState === null ||
|
|
@@ -1106,8 +692,10 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1106
692
|
_fiberRoots.add(root);
|
|
1107
693
|
rootRendererIds.set(root, rendererID);
|
|
1108
694
|
}
|
|
1109
|
-
for (const
|
|
1110
|
-
|
|
695
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
696
|
+
if (options.onCommitFiberRoot) {
|
|
697
|
+
options.onCommitFiberRoot(rendererID, root, priority, didError);
|
|
698
|
+
}
|
|
1111
699
|
}
|
|
1112
700
|
};
|
|
1113
701
|
dispatchers.onCommitFiberRoot = dispatchCommitFiberRoot;
|
|
@@ -1123,12 +711,17 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1123
711
|
rendererID,
|
|
1124
712
|
fiber,
|
|
1125
713
|
) => {
|
|
1126
|
-
|
|
714
|
+
setReactWorkTagsForFiber(fiber, rdtHook.renderers.get(rendererID));
|
|
715
|
+
if (prevOnCommitFiberUnmount) {
|
|
716
|
+
prevOnCommitFiberUnmount.call(rdtHook, rendererID, fiber);
|
|
717
|
+
}
|
|
1127
718
|
if (hookDispatchers.get(rdtHook)?.onCommitFiberUnmount !== dispatchCommitFiberUnmount) {
|
|
1128
719
|
return;
|
|
1129
720
|
}
|
|
1130
|
-
for (const
|
|
1131
|
-
|
|
721
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
722
|
+
if (options.onCommitFiberUnmount) {
|
|
723
|
+
options.onCommitFiberUnmount(rendererID, fiber);
|
|
724
|
+
}
|
|
1132
725
|
}
|
|
1133
726
|
};
|
|
1134
727
|
dispatchers.onCommitFiberUnmount = dispatchCommitFiberUnmount;
|
|
@@ -1144,12 +737,16 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1144
737
|
rendererID,
|
|
1145
738
|
root,
|
|
1146
739
|
) => {
|
|
1147
|
-
prevOnPostCommitFiberRoot
|
|
740
|
+
if (prevOnPostCommitFiberRoot) {
|
|
741
|
+
prevOnPostCommitFiberRoot.call(rdtHook, rendererID, root);
|
|
742
|
+
}
|
|
1148
743
|
if (hookDispatchers.get(rdtHook)?.onPostCommitFiberRoot !== dispatchPostCommitFiberRoot) {
|
|
1149
744
|
return;
|
|
1150
745
|
}
|
|
1151
|
-
for (const
|
|
1152
|
-
|
|
746
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
747
|
+
if (options.onPostCommitFiberRoot) {
|
|
748
|
+
options.onPostCommitFiberRoot(rendererID, root);
|
|
749
|
+
}
|
|
1153
750
|
}
|
|
1154
751
|
};
|
|
1155
752
|
dispatchers.onPostCommitFiberRoot = dispatchPostCommitFiberRoot;
|
|
@@ -1166,10 +763,14 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1166
763
|
root,
|
|
1167
764
|
children,
|
|
1168
765
|
) => {
|
|
1169
|
-
prevOnScheduleFiberRoot
|
|
766
|
+
if (prevOnScheduleFiberRoot) {
|
|
767
|
+
prevOnScheduleFiberRoot.call(rdtHook, rendererID, root, children);
|
|
768
|
+
}
|
|
1170
769
|
if (hookDispatchers.get(rdtHook)?.onScheduleFiberRoot !== dispatchScheduleFiberRoot) return;
|
|
1171
|
-
for (const
|
|
1172
|
-
|
|
770
|
+
for (const { options } of instrumentationSubscriptions) {
|
|
771
|
+
if (options.onScheduleFiberRoot) {
|
|
772
|
+
options.onScheduleFiberRoot(rendererID, root, children);
|
|
773
|
+
}
|
|
1173
774
|
}
|
|
1174
775
|
};
|
|
1175
776
|
dispatchers.onScheduleFiberRoot = dispatchScheduleFiberRoot;
|
|
@@ -1177,13 +778,24 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1177
778
|
}
|
|
1178
779
|
};
|
|
1179
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
|
+
|
|
1180
793
|
/**
|
|
1181
794
|
* Instruments the DevTools hook. Each hook event is patched once and
|
|
1182
795
|
* dispatches to a set of listeners, so multiple `instrument` calls compose
|
|
1183
796
|
* without stacking patches. Returns an unsubscribe function that removes
|
|
1184
797
|
* exactly the handlers this call registered.
|
|
1185
|
-
* The
|
|
1186
|
-
* bippy subscriptions through `using`.
|
|
798
|
+
* The unsubscribe function can also be disposed through `using`.
|
|
1187
799
|
* @example
|
|
1188
800
|
* const unsubscribe = instrument({
|
|
1189
801
|
* onActive() {
|
|
@@ -1197,29 +809,15 @@ const ensureHookDispatchesToListeners = (rdtHook: ReactDevToolsGlobalHook): void
|
|
|
1197
809
|
*/
|
|
1198
810
|
export const instrument = (options: InstrumentationOptions): Unsubscribe => {
|
|
1199
811
|
const rdtHook = getRDTHook(options.onActive);
|
|
1200
|
-
|
|
1201
812
|
rdtHook._instrumentationSource = options.name ?? BIPPY_INSTRUMENTATION_STRING;
|
|
1202
813
|
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
onScheduleFiberRoot,
|
|
1211
|
-
} = options;
|
|
1212
|
-
if (onCommitFiberRoot) commitFiberRootListeners.add(onCommitFiberRoot);
|
|
1213
|
-
if (onCommitFiberUnmount) commitFiberUnmountListeners.add(onCommitFiberUnmount);
|
|
1214
|
-
if (onPostCommitFiberRoot) postCommitFiberRootListeners.add(onPostCommitFiberRoot);
|
|
1215
|
-
if (onScheduleFiberRoot) scheduleFiberRootListeners.add(onScheduleFiberRoot);
|
|
1216
|
-
|
|
1217
|
-
return toUnsubscribe(() => {
|
|
1218
|
-
if (onActive) _onActiveListeners.delete(onActive);
|
|
1219
|
-
if (onCommitFiberRoot) commitFiberRootListeners.delete(onCommitFiberRoot);
|
|
1220
|
-
if (onCommitFiberUnmount) commitFiberUnmountListeners.delete(onCommitFiberUnmount);
|
|
1221
|
-
if (onPostCommitFiberRoot) postCommitFiberRootListeners.delete(onPostCommitFiberRoot);
|
|
1222
|
-
if (onScheduleFiberRoot) scheduleFiberRootListeners.delete(onScheduleFiberRoot);
|
|
814
|
+
wireHookEventDispatchers(rdtHook);
|
|
815
|
+
const subscription: InstrumentationSubscription = { options };
|
|
816
|
+
instrumentationSubscriptions.add(subscription);
|
|
817
|
+
|
|
818
|
+
return createUnsubscribe(() => {
|
|
819
|
+
if (options.onActive) _onActiveListeners.delete(options.onActive);
|
|
820
|
+
instrumentationSubscriptions.delete(subscription);
|
|
1223
821
|
});
|
|
1224
822
|
};
|
|
1225
823
|
|
|
@@ -1231,33 +829,38 @@ const isFiberPropertyKey = (key: string): boolean =>
|
|
|
1231
829
|
key.startsWith("__reactInternalInstance$") ||
|
|
1232
830
|
key.startsWith("__reactFiber");
|
|
1233
831
|
|
|
1234
|
-
const getLegacyRootFiber = (hostInstance:
|
|
1235
|
-
const reactRootContainer = hostInstance
|
|
1236
|
-
if (
|
|
1237
|
-
const internalRoot = reactRootContainer
|
|
1238
|
-
if (
|
|
1239
|
-
const current = internalRoot
|
|
1240
|
-
if (
|
|
1241
|
-
const child = current
|
|
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");
|
|
1242
840
|
return isValidFiber(child) ? child : null;
|
|
1243
841
|
};
|
|
1244
842
|
|
|
1245
|
-
const getInternalInstanceHandle = (hostInstance:
|
|
843
|
+
const getInternalInstanceHandle = (hostInstance: object): Fiber | null => {
|
|
1246
844
|
const internalInstanceHandle =
|
|
1247
|
-
hostInstance
|
|
845
|
+
Reflect.get(hostInstance, "__internalInstanceHandle") ??
|
|
846
|
+
Reflect.get(hostInstance, "_internalInstanceHandle");
|
|
1248
847
|
return isValidFiber(internalInstanceHandle) ? internalInstanceHandle : null;
|
|
1249
848
|
};
|
|
1250
849
|
|
|
1251
850
|
const getPublicHostInstance = (stateNode: unknown): unknown => {
|
|
1252
|
-
if (
|
|
1253
|
-
const canonical = stateNode
|
|
1254
|
-
if (
|
|
1255
|
-
|
|
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
|
+
}
|
|
1256
858
|
}
|
|
1257
|
-
|
|
859
|
+
const nativeTag = Reflect.get(stateNode, "_nativeTag");
|
|
860
|
+
return typeof nativeTag === "number" ? nativeTag : stateNode;
|
|
1258
861
|
};
|
|
1259
862
|
|
|
1260
|
-
export const
|
|
863
|
+
export const getFiber = <T>(hostInstance: T): Fiber | null => {
|
|
1261
864
|
const rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
1262
865
|
if (rdtHook?.renderers) {
|
|
1263
866
|
for (const renderer of rdtHook.renderers.values()) {
|
|
@@ -1268,7 +871,7 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1268
871
|
}
|
|
1269
872
|
}
|
|
1270
873
|
|
|
1271
|
-
if (
|
|
874
|
+
if (typeof hostInstance === "object" && hostInstance !== null) {
|
|
1272
875
|
const legacyRootFiber = getLegacyRootFiber(hostInstance);
|
|
1273
876
|
if (legacyRootFiber) return legacyRootFiber;
|
|
1274
877
|
|
|
@@ -1276,14 +879,14 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1276
879
|
if (internalInstanceHandle) return internalInstanceHandle;
|
|
1277
880
|
|
|
1278
881
|
for (const knownKey of knownFiberPropertyKeys) {
|
|
1279
|
-
const fiber = hostInstance
|
|
882
|
+
const fiber = Reflect.get(hostInstance, knownKey);
|
|
1280
883
|
if (isValidFiber(fiber)) return fiber;
|
|
1281
884
|
}
|
|
1282
885
|
|
|
1283
886
|
for (const key of Object.keys(hostInstance)) {
|
|
1284
887
|
if (isFiberPropertyKey(key)) {
|
|
1285
888
|
knownFiberPropertyKeys.add(key);
|
|
1286
|
-
const fiber = hostInstance
|
|
889
|
+
const fiber = Reflect.get(hostInstance, key);
|
|
1287
890
|
if (isValidFiber(fiber)) return fiber;
|
|
1288
891
|
}
|
|
1289
892
|
}
|
|
@@ -1307,6 +910,19 @@ export const getFiberFromHostInstance = <T>(hostInstance: T): Fiber | null => {
|
|
|
1307
910
|
return null;
|
|
1308
911
|
};
|
|
1309
912
|
|
|
1310
|
-
export
|
|
1311
|
-
|
|
1312
|
-
export
|
|
913
|
+
export const getFiberFromHostInstance = getFiber;
|
|
914
|
+
|
|
915
|
+
export {
|
|
916
|
+
BIPPY_INSTRUMENTATION_STRING,
|
|
917
|
+
_onActiveListeners,
|
|
918
|
+
_renderers,
|
|
919
|
+
getRDTHook,
|
|
920
|
+
hasRDTHook,
|
|
921
|
+
installRDTHook,
|
|
922
|
+
isRealReactDevtools,
|
|
923
|
+
onRendererInject,
|
|
924
|
+
patchRDTHook,
|
|
925
|
+
version,
|
|
926
|
+
} from "./rdt-hook.js";
|
|
927
|
+
export type { Unsubscribe } from "./rdt-hook.js";
|
|
928
|
+
export * from "./react-internals/index.js";
|