bippy 0.7.3-dev.e910a3b → 0.7.3-dev.fbafc40
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 +0 -1
- package/README.md +4 -11
- package/dist/core.cjs +1 -1
- package/dist/core.js +1 -1
- package/dist/errors.d.cts +5 -2
- package/dist/errors.d.ts +5 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +27 -27
- package/dist/index.d.ts +27 -27
- 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 +24 -22
- package/dist/source.d.ts +24 -22
- package/dist/source.js +12 -13
- package/package.json +71 -7
- package/src/call-listener.ts +13 -0
- package/src/core.ts +197 -192
- package/src/index.ts +3 -3
- package/src/install-hook-only.ts +1 -1
- package/src/rdt-hook.ts +44 -30
- package/src/react-internals/current-fiber.ts +2 -2
- package/src/react-internals/generated/react-work-tags.ts +4 -1
- package/src/react-internals/index.ts +44 -22
- package/src/react-internals/types.ts +1 -1
- package/src/react.ts +16 -6
- package/src/source/constants.ts +10 -6
- package/src/source/get-display-name-from-source.ts +5 -5
- package/src/source/get-source.ts +8 -143
- package/src/source/index.ts +9 -9
- package/src/source/inspect-hooks.ts +11 -13
- package/src/source/normalize-file-name.ts +416 -0
- package/src/source/owner-stack.ts +9 -21
- package/src/source/parse-debug-stack.ts +3 -3
- package/src/source/parse-hook-names.ts +2 -2
- package/src/source/parse-stack.ts +111 -63
- package/src/source/renderer-dispatchers.ts +3 -3
- package/src/source/symbolication.ts +81 -41
package/src/rdt-hook.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// This module must load before React so renderers can inject into the hook.
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { callListener } from "./call-listener";
|
|
4
|
+
import type { FiberRoot, ReactDevToolsGlobalHook, ReactRenderer } from "./react-internals/index";
|
|
4
5
|
|
|
5
6
|
export interface Unsubscribe extends Disposable {
|
|
6
7
|
(): void;
|
|
@@ -23,6 +24,10 @@ interface RDTHookReplaceListener {
|
|
|
23
24
|
(rdtHook: ReactDevToolsGlobalHook, target: ReactDevToolsTarget): void;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
interface RDTHookReplaceSubscription {
|
|
28
|
+
listener: RDTHookReplaceListener;
|
|
29
|
+
}
|
|
30
|
+
|
|
26
31
|
export interface ReactDevToolsTarget {
|
|
27
32
|
__REACT_DEVTOOLS_GLOBAL_HOOK__?: ReactDevToolsGlobalHook;
|
|
28
33
|
}
|
|
@@ -93,7 +98,7 @@ export const _renderers = new Set<ReactRenderer>();
|
|
|
93
98
|
|
|
94
99
|
const activeListenerTargets = new WeakMap<ActiveListener, Set<ReactDevToolsTarget>>();
|
|
95
100
|
const rendererInjectSubscriptions = new Set<RendererInjectSubscription>();
|
|
96
|
-
const
|
|
101
|
+
const rdtHookReplaceSubscriptions = new Set<RDTHookReplaceSubscription>();
|
|
97
102
|
const notifiedRenderersByTarget = new WeakMap<ReactDevToolsTarget, WeakSet<ReactRenderer>>();
|
|
98
103
|
|
|
99
104
|
const addActiveListener = (listener: ActiveListener, target: ReactDevToolsTarget): void => {
|
|
@@ -115,9 +120,12 @@ export const removeActiveListener = (
|
|
|
115
120
|
}
|
|
116
121
|
};
|
|
117
122
|
|
|
118
|
-
const notifyActiveListeners = (
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
const notifyActiveListeners = (
|
|
124
|
+
target: ReactDevToolsTarget,
|
|
125
|
+
pendingListeners = [..._onActiveListeners],
|
|
126
|
+
): void => {
|
|
127
|
+
for (const listener of pendingListeners) {
|
|
128
|
+
if (activeListenerTargets.get(listener)?.has(target)) callListener(listener, undefined);
|
|
121
129
|
}
|
|
122
130
|
};
|
|
123
131
|
|
|
@@ -125,8 +133,11 @@ const notifyRendererInjectListeners = (
|
|
|
125
133
|
target: ReactDevToolsTarget,
|
|
126
134
|
renderer: ReactRenderer,
|
|
127
135
|
): void => {
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
const subscriptionSnapshot = [...rendererInjectSubscriptions];
|
|
137
|
+
for (const subscription of subscriptionSnapshot) {
|
|
138
|
+
if (rendererInjectSubscriptions.has(subscription) && subscription.target === target) {
|
|
139
|
+
callListener(subscription.listener, subscription, renderer);
|
|
140
|
+
}
|
|
130
141
|
}
|
|
131
142
|
};
|
|
132
143
|
|
|
@@ -134,8 +145,11 @@ const notifyRDTHookReplaceListeners = (
|
|
|
134
145
|
rdtHook: ReactDevToolsGlobalHook,
|
|
135
146
|
target: ReactDevToolsTarget,
|
|
136
147
|
): void => {
|
|
137
|
-
|
|
138
|
-
|
|
148
|
+
const subscriptionSnapshot = [...rdtHookReplaceSubscriptions];
|
|
149
|
+
for (const subscription of subscriptionSnapshot) {
|
|
150
|
+
if (rdtHookReplaceSubscriptions.has(subscription)) {
|
|
151
|
+
callListener(subscription.listener, undefined, rdtHook, target);
|
|
152
|
+
}
|
|
139
153
|
}
|
|
140
154
|
};
|
|
141
155
|
|
|
@@ -152,9 +166,10 @@ export const onRendererInject = (
|
|
|
152
166
|
};
|
|
153
167
|
|
|
154
168
|
export const onRDTHookReplace = (listener: RDTHookReplaceListener): Unsubscribe => {
|
|
155
|
-
|
|
169
|
+
const subscription = { listener };
|
|
170
|
+
rdtHookReplaceSubscriptions.add(subscription);
|
|
156
171
|
return createUnsubscribe(() => {
|
|
157
|
-
|
|
172
|
+
rdtHookReplaceSubscriptions.delete(subscription);
|
|
158
173
|
});
|
|
159
174
|
};
|
|
160
175
|
|
|
@@ -242,10 +257,11 @@ export const installRDTHook = (
|
|
|
242
257
|
_renderers.add(renderer);
|
|
243
258
|
nextRenderers.set(rendererId, renderer);
|
|
244
259
|
});
|
|
245
|
-
if (ourRenderers.size > 0 ||
|
|
246
|
-
patchRDTHook(
|
|
260
|
+
if (ourRenderers.size > 0 || rdtHookReplaceSubscriptions.size > 0) {
|
|
261
|
+
patchRDTHook(undefined, target, () => notifyRDTHookReplaceListeners(newHook, target));
|
|
262
|
+
} else {
|
|
263
|
+
notifyRDTHookReplaceListeners(newHook, target);
|
|
247
264
|
}
|
|
248
|
-
notifyRDTHookReplaceListeners(rdtHook, target);
|
|
249
265
|
}
|
|
250
266
|
},
|
|
251
267
|
});
|
|
@@ -287,9 +303,10 @@ export const installRDTHook = (
|
|
|
287
303
|
export const patchRDTHook = (
|
|
288
304
|
onActive?: ActiveListener,
|
|
289
305
|
target: ReactDevToolsTarget = globalThis,
|
|
306
|
+
onReady?: () => void,
|
|
290
307
|
): void => {
|
|
291
308
|
if (onActive) addActiveListener(onActive, target);
|
|
292
|
-
let
|
|
309
|
+
let shouldNotifyActiveListeners = false;
|
|
293
310
|
const rdtHook = getTargetHook(target);
|
|
294
311
|
if (!rdtHook) return;
|
|
295
312
|
const renderers = getRendererMap(rdtHook);
|
|
@@ -305,28 +322,25 @@ export const patchRDTHook = (
|
|
|
305
322
|
if (!isReactDevtools) {
|
|
306
323
|
rdtHook.on = noOp;
|
|
307
324
|
}
|
|
308
|
-
|
|
309
|
-
renderers.forEach((renderer) => _renderers.add(renderer));
|
|
310
|
-
rdtHook._instrumentationIsActive = true;
|
|
311
|
-
notifyActiveListeners(target);
|
|
312
|
-
didNotifyActiveListeners = true;
|
|
313
|
-
} else if (!isReactDevtools && isReactRefresh(rdtHook)) {
|
|
314
|
-
// HACK: react-refresh's stub inject never records renderers, so a React app
|
|
315
|
-
// that injected before bippy loaded is undetectable through the renderers map.
|
|
316
|
-
// A react-refresh hook implies a dev renderer, so activate immediately.
|
|
317
|
-
rdtHook._instrumentationIsActive = true;
|
|
318
|
-
notifyActiveListeners(target);
|
|
319
|
-
didNotifyActiveListeners = true;
|
|
320
|
-
}
|
|
325
|
+
const shouldActivate = renderers.size > 0 || (!isReactDevtools && isReactRefresh(rdtHook));
|
|
321
326
|
const previousInject = rdtHook.inject;
|
|
322
327
|
rdtHook.inject = (renderer) => {
|
|
323
328
|
const rendererId = previousInject.call(rdtHook, renderer);
|
|
324
329
|
trackInjectedRenderer(rdtHook, target, renderers, rendererId, renderer);
|
|
325
330
|
return rendererId;
|
|
326
331
|
};
|
|
332
|
+
if (shouldActivate) {
|
|
333
|
+
renderers.forEach((renderer) => _renderers.add(renderer));
|
|
334
|
+
rdtHook._instrumentationIsActive = true;
|
|
335
|
+
shouldNotifyActiveListeners = true;
|
|
336
|
+
}
|
|
327
337
|
}
|
|
328
|
-
|
|
329
|
-
|
|
338
|
+
const pendingListeners = shouldNotifyActiveListeners ? [..._onActiveListeners] : [];
|
|
339
|
+
onReady?.();
|
|
340
|
+
if (shouldNotifyActiveListeners) {
|
|
341
|
+
notifyActiveListeners(target, pendingListeners);
|
|
342
|
+
} else if (onActive && (renderers.size || rdtHook._instrumentationIsActive)) {
|
|
343
|
+
callListener(onActive, undefined);
|
|
330
344
|
}
|
|
331
345
|
};
|
|
332
346
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Adapted from ReactFiberTreeReflection.js. Copyright (c) Meta Platforms, Inc. and affiliates. MIT licensed.
|
|
2
|
-
import type { Fiber } from "./types
|
|
3
|
-
import { getReactWorkTagsForFiber } from "./index
|
|
2
|
+
import type { Fiber } from "./types";
|
|
3
|
+
import { getReactWorkTagsForFiber } from "./index";
|
|
4
4
|
|
|
5
5
|
export const getCurrentFiberFromRoot = (fiber: Fiber): Fiber | null => {
|
|
6
6
|
const alternate = fiber.alternate;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { compareSemver } from "../semver
|
|
1
|
+
import { compareSemver } from "../semver";
|
|
2
2
|
|
|
3
3
|
export const ReactBuildType = {
|
|
4
4
|
Development: 1,
|
|
@@ -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 {
|
|
@@ -1,25 +1,41 @@
|
|
|
1
|
-
import { getReactWorkTags, ReactFiberFlags } from "./generated/react-work-tags
|
|
2
|
-
import type { ReactWorkTagMap } from "./generated/react-work-tags
|
|
3
|
-
import { isSemver } from "./semver
|
|
4
|
-
import type { Fiber, ReactRenderer } from "./types
|
|
1
|
+
import { getReactWorkTags, ReactFiberFlags } from "./generated/react-work-tags";
|
|
2
|
+
import type { ReactWorkTagMap } from "./generated/react-work-tags";
|
|
3
|
+
import { isSemver } from "./semver";
|
|
4
|
+
import type { Fiber, ReactRenderer } from "./types";
|
|
5
5
|
|
|
6
|
-
export { compareSemver } from "./semver
|
|
6
|
+
export { compareSemver } from "./semver";
|
|
7
7
|
export {
|
|
8
8
|
getReactWorkTags,
|
|
9
9
|
ReactBuildType,
|
|
10
10
|
ReactFiberFlags,
|
|
11
11
|
ReactSymbols,
|
|
12
|
-
} from "./generated/react-work-tags
|
|
12
|
+
} from "./generated/react-work-tags";
|
|
13
13
|
export type {
|
|
14
14
|
HostWorkTag,
|
|
15
15
|
ReactWorkTag,
|
|
16
16
|
ReactWorkTagMap,
|
|
17
17
|
ReactWorkTagVersion,
|
|
18
|
-
} from "./generated/react-work-tags
|
|
19
|
-
export * from "./types
|
|
18
|
+
} from "./generated/react-work-tags";
|
|
19
|
+
export * from "./types";
|
|
20
|
+
|
|
21
|
+
interface InheritedWorkTags {
|
|
22
|
+
workTags: Readonly<ReactWorkTagMap>;
|
|
23
|
+
generation: number;
|
|
24
|
+
}
|
|
20
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;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type ReactReconciler from "react-reconciler";
|
|
3
|
-
import type { HostWorkTag, ReactWorkTag } from "./generated/react-work-tags
|
|
3
|
+
import type { HostWorkTag, ReactWorkTag } from "./generated/react-work-tags";
|
|
4
4
|
|
|
5
5
|
export type WorkTag = ReactReconciler.WorkTag | ReactWorkTag;
|
|
6
6
|
|
package/src/react.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import "./install-hook-only
|
|
1
|
+
import "./install-hook-only";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { isFiber, traverseFiber } from "./core
|
|
4
|
-
import { _renderers } from "./rdt-hook
|
|
5
|
-
import
|
|
3
|
+
import { isFiber, traverseFiber } from "./core";
|
|
4
|
+
import { _renderers } from "./rdt-hook";
|
|
5
|
+
import { getCurrentFiberFromRoot } from "./react-internals/current-fiber";
|
|
6
|
+
import type { Fiber } from "./react-internals/index";
|
|
6
7
|
|
|
7
|
-
export type { Fiber } from "./react-internals/index
|
|
8
|
+
export type { Fiber } from "./react-internals/index";
|
|
8
9
|
|
|
9
10
|
interface RenderMarker {
|
|
10
11
|
(state: undefined): undefined;
|
|
@@ -115,6 +116,12 @@ const getRenderingFiberFromRoot = (
|
|
|
115
116
|
return null;
|
|
116
117
|
}
|
|
117
118
|
const renderingRoot = root.current.alternate;
|
|
119
|
+
const renderingFiber = getCurrentFiberFromRoot(fiber)?.alternate;
|
|
120
|
+
if (renderingFiber) {
|
|
121
|
+
let ancestor = renderingFiber;
|
|
122
|
+
while (ancestor.return) ancestor = ancestor.return;
|
|
123
|
+
if (ancestor === renderingRoot) return renderingFiber;
|
|
124
|
+
}
|
|
118
125
|
return traverseFiber(renderingRoot, (candidate) => {
|
|
119
126
|
if (candidate !== fiber && candidate !== fiber.alternate) return false;
|
|
120
127
|
let parent = candidate;
|
|
@@ -147,6 +154,9 @@ export const useFiber = (): Fiber | undefined => {
|
|
|
147
154
|
: knownFiber.alternate && hasRenderMarker(knownFiber.alternate, renderMarker)
|
|
148
155
|
? knownFiber.alternate
|
|
149
156
|
: getRenderingFiberFromRoot(knownCapture, renderMarker));
|
|
150
|
-
if (fiber)
|
|
157
|
+
if (fiber) {
|
|
158
|
+
knownCapture.fiber = fiber;
|
|
159
|
+
fiberRef.current = knownCapture;
|
|
160
|
+
}
|
|
151
161
|
return fiber ?? undefined;
|
|
152
162
|
};
|
package/src/source/constants.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
export const SCHEME_REGEX = /^[a-zA-Z][a-zA-Z\d+\-.]*:/;
|
|
2
2
|
|
|
3
3
|
export const INTERNAL_SCHEME_PREFIXES = [
|
|
4
|
-
"
|
|
5
|
-
"file:///",
|
|
4
|
+
"rspack-internal://",
|
|
6
5
|
"webpack-internal://",
|
|
7
|
-
"webpack://",
|
|
8
|
-
"node:",
|
|
9
6
|
"turbopack://",
|
|
7
|
+
"webpack://",
|
|
8
|
+
"rspack://",
|
|
9
|
+
"parcel://",
|
|
10
10
|
"metro://",
|
|
11
|
-
"
|
|
11
|
+
"file:///",
|
|
12
|
+
"rsc://",
|
|
13
|
+
"node:",
|
|
14
|
+
"bun:",
|
|
12
15
|
"/(app-pages-browser)/",
|
|
16
|
+
"/app-pages-browser/",
|
|
13
17
|
] as const;
|
|
14
18
|
|
|
15
19
|
export const ABOUT_REACT_PREFIX = "about://React/";
|
|
@@ -21,7 +25,7 @@ export const ANONYMOUS_FILE_PATTERNS = ["<anonymous>", "eval", ""] as const;
|
|
|
21
25
|
export const SOURCE_FILE_EXTENSION_REGEX = /\.(cjs|cts|js|jsx|mdx|mjs|mts|ts|tsx)$/;
|
|
22
26
|
|
|
23
27
|
export const BUNDLED_FILE_PATTERN_REGEX =
|
|
24
|
-
/(\.min|bundle|chunk|vendor|vendors|runtime|polyfill|polyfills)\.(js|mjs|cjs)$|(chunk|bundle|vendor|vendors|runtime|polyfill|polyfills|framework|app|main|index)[-_.][A-Za-z0-9_-]{4,}\.(js|mjs|cjs)$|[\da-f]{8,}\.(js|mjs|cjs)$|[-_.][\da-f]{20,}\.(js|mjs|cjs)$|\/dist\/|\/build\/|\/.next\/|\/out\/|\/node_modules\/|\.webpack\.|\.vite\.|\.turbopack
|
|
28
|
+
/(\.min|bundle|chunk|vendor|vendors|runtime|polyfill|polyfills)\.(js|mjs|cjs)$|(chunk|bundle|vendor|vendors|runtime|polyfill|polyfills|framework|app|main|index)[-_.][A-Za-z0-9_-]{4,}\.(js|mjs|cjs)$|[\da-f]{8,}\.(js|mjs|cjs)$|[-_.][\da-f]{20,}\.(js|mjs|cjs)$|\/dist\/|\/build\/|\/.next\/|\/out\/|\/node_modules\/|\/_next\/|\/_expo\/|\/_nuxt\/|\/@vite\/|\/@react-refresh|\/\.parcel-cache\/|\/\.expo\/|\/\.rsbuild\/|\/\.vite\/|\/\.svelte-kit\/|\/\.astro\/|\/\.nuxt\/|\/\.angular\/|\.webpack\.|\.vite\.|\.turbopack\.|\[root-of-the-server\]/i;
|
|
25
29
|
|
|
26
30
|
export const QUERY_PARAMETER_PATTERN_REGEX = /^\?[\w~.-]+(?:=[^&#]*)?(?:&[\w~.-]+(?:=[^&#]*)?)*$/;
|
|
27
31
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type { Fiber } from "../react-internals/index
|
|
2
|
-
import { getDisplayName } from "../core
|
|
3
|
-
import { getDefinitionFrameFromOwnedChild, getRawParentStack } from "./owner-stack
|
|
1
|
+
import type { Fiber } from "../react-internals/index";
|
|
2
|
+
import { getDisplayName } from "../core";
|
|
3
|
+
import { getDefinitionFrameFromOwnedChild, getRawParentStack } from "./owner-stack";
|
|
4
4
|
import {
|
|
5
5
|
getSourceContentFromSourceMap,
|
|
6
6
|
getSourceFromSourceMap,
|
|
7
7
|
getSourceMap,
|
|
8
8
|
type SourceFetch,
|
|
9
9
|
type SourceMapRequestOptions,
|
|
10
|
-
} from "./symbolication
|
|
11
|
-
import type { StackFrame } from "./parse-stack
|
|
10
|
+
} from "./symbolication";
|
|
11
|
+
import type { StackFrame } from "./parse-stack";
|
|
12
12
|
|
|
13
13
|
const COMPONENT_DECLARATION_PATTERNS = [
|
|
14
14
|
/(?:^|export\s+)(?:const|let|var)\s+(\w+)\s*=/,
|
package/src/source/get-source.ts
CHANGED
|
@@ -1,26 +1,17 @@
|
|
|
1
|
-
import type { Fiber } from "../react-internals/index
|
|
2
|
-
import { getDisplayName } from "../core
|
|
1
|
+
import type { Fiber } from "../react-internals/index";
|
|
2
|
+
import { getDisplayName } from "../core";
|
|
3
3
|
|
|
4
|
-
import type { FiberSource } from "./types
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
ABOUT_REACT_PREFIX,
|
|
9
|
-
ANONYMOUS_FILE_PATTERNS,
|
|
10
|
-
SOURCE_FILE_EXTENSION_REGEX,
|
|
11
|
-
BUNDLED_FILE_PATTERN_REGEX,
|
|
12
|
-
QUERY_PARAMETER_PATTERN_REGEX,
|
|
13
|
-
} from "./constants.js";
|
|
14
|
-
import { getDefinitionFrameFromOwnedChild, getParentStack, hasDebugStack } from "./owner-stack.js";
|
|
15
|
-
import { parseDebugStack } from "./parse-debug-stack.js";
|
|
16
|
-
import { parseStack, type StackFrame } from "./parse-stack.js";
|
|
4
|
+
import type { FiberSource } from "./types";
|
|
5
|
+
import { getDefinitionFrameFromOwnedChild, getParentStack, hasDebugStack } from "./owner-stack";
|
|
6
|
+
import { parseDebugStack } from "./parse-debug-stack";
|
|
7
|
+
import { parseStack, type StackFrame } from "./parse-stack";
|
|
17
8
|
import {
|
|
18
9
|
getSourceFromSourceMapByFunctionName,
|
|
19
10
|
getSourceMap,
|
|
20
11
|
symbolicateStack,
|
|
21
12
|
type SourceFetch,
|
|
22
13
|
type SourceMapRequestOptions,
|
|
23
|
-
} from "./symbolication
|
|
14
|
+
} from "./symbolication";
|
|
24
15
|
|
|
25
16
|
export const hasDebugSource = (
|
|
26
17
|
fiber: Fiber,
|
|
@@ -165,130 +156,4 @@ export const getSource = async (
|
|
|
165
156
|
return getSourceByComponentName(fiber, shouldUseCache, sourceFetch, requestOptions);
|
|
166
157
|
};
|
|
167
158
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const stripSingleBasePathPrefix = (path: string): string => {
|
|
171
|
-
const firstSlashIndex = path.indexOf("/", 1);
|
|
172
|
-
if (firstSlashIndex === -1) {
|
|
173
|
-
return path;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const basePath = path.slice(0, firstSlashIndex);
|
|
177
|
-
if (getPathSegmentCount(basePath) !== 1) {
|
|
178
|
-
return path;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const remainderPath = path.slice(firstSlashIndex);
|
|
182
|
-
if (!SOURCE_FILE_EXTENSION_REGEX.test(remainderPath)) {
|
|
183
|
-
return path;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const remainderSegments = remainderPath.split("/").filter(Boolean);
|
|
187
|
-
if (remainderSegments.length < 2) {
|
|
188
|
-
return path;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const firstRemainderSegment = remainderSegments[0];
|
|
192
|
-
if (firstRemainderSegment.startsWith("@")) {
|
|
193
|
-
return path;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (firstRemainderSegment.length > 4) {
|
|
197
|
-
return path;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return remainderPath;
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
export const normalizeFileName = (fileName: string): string => {
|
|
204
|
-
if (!fileName) {
|
|
205
|
-
return "";
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (ANONYMOUS_FILE_PATTERNS.some((pattern) => pattern === fileName)) {
|
|
209
|
-
return "";
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
let normalizedFileName = fileName;
|
|
213
|
-
const isWindowsDrivePath = /^[a-zA-Z]:[\\/]/.test(normalizedFileName);
|
|
214
|
-
|
|
215
|
-
const isHttpUrl =
|
|
216
|
-
normalizedFileName.startsWith("http://") || normalizedFileName.startsWith("https://");
|
|
217
|
-
if (isHttpUrl) {
|
|
218
|
-
try {
|
|
219
|
-
const parsedUrl = new URL(normalizedFileName);
|
|
220
|
-
normalizedFileName = parsedUrl.pathname;
|
|
221
|
-
} catch {}
|
|
222
|
-
normalizedFileName = stripSingleBasePathPrefix(normalizedFileName);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (normalizedFileName.startsWith(ABOUT_REACT_PREFIX)) {
|
|
226
|
-
const remainder = normalizedFileName.slice(ABOUT_REACT_PREFIX.length);
|
|
227
|
-
const slashIndex = remainder.indexOf("/");
|
|
228
|
-
const colonIndex = remainder.indexOf(":");
|
|
229
|
-
|
|
230
|
-
if (slashIndex !== -1 && (colonIndex === -1 || slashIndex < colonIndex)) {
|
|
231
|
-
normalizedFileName = remainder.slice(slashIndex + 1);
|
|
232
|
-
} else {
|
|
233
|
-
normalizedFileName = remainder;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
let didStripPrefix = true;
|
|
238
|
-
while (didStripPrefix) {
|
|
239
|
-
didStripPrefix = false;
|
|
240
|
-
for (const prefix of INTERNAL_SCHEME_PREFIXES) {
|
|
241
|
-
if (normalizedFileName.startsWith(prefix)) {
|
|
242
|
-
normalizedFileName = normalizedFileName.slice(prefix.length);
|
|
243
|
-
|
|
244
|
-
if (prefix === "file:///") {
|
|
245
|
-
normalizedFileName = `/${normalizedFileName.replace(/^\/+/, "")}`;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
didStripPrefix = true;
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (!isWindowsDrivePath) {
|
|
255
|
-
const schemeMatch = normalizedFileName.match(SCHEME_REGEX);
|
|
256
|
-
if (schemeMatch) {
|
|
257
|
-
normalizedFileName = normalizedFileName.slice(schemeMatch[0].length);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (normalizedFileName.startsWith("//")) {
|
|
262
|
-
const firstPathSlashIndex = normalizedFileName.indexOf("/", 2);
|
|
263
|
-
normalizedFileName =
|
|
264
|
-
firstPathSlashIndex === -1 ? "" : normalizedFileName.slice(firstPathSlashIndex);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const queryParameterIndex = normalizedFileName.indexOf("?");
|
|
268
|
-
if (queryParameterIndex !== -1) {
|
|
269
|
-
const potentialQueryParameters = normalizedFileName.slice(queryParameterIndex);
|
|
270
|
-
if (QUERY_PARAMETER_PATTERN_REGEX.test(potentialQueryParameters)) {
|
|
271
|
-
normalizedFileName = normalizedFileName.slice(0, queryParameterIndex);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return normalizedFileName;
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
export const isSourceFile = (fileName: string): boolean => {
|
|
279
|
-
const normalizedFileName = normalizeFileName(fileName);
|
|
280
|
-
|
|
281
|
-
if (!normalizedFileName) {
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (!SOURCE_FILE_EXTENSION_REGEX.test(normalizedFileName)) {
|
|
286
|
-
return false;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (BUNDLED_FILE_PATTERN_REGEX.test(normalizedFileName)) {
|
|
290
|
-
return false;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return true;
|
|
294
|
-
};
|
|
159
|
+
export { isSourceFile, normalizeFileName } from "./normalize-file-name";
|
package/src/source/index.ts
CHANGED
|
@@ -6,8 +6,8 @@ export {
|
|
|
6
6
|
getParentStack,
|
|
7
7
|
getRawOwnerStack,
|
|
8
8
|
hasDebugStack,
|
|
9
|
-
} from "./owner-stack
|
|
10
|
-
export { getRawSource, getSource, isSourceFile, normalizeFileName } from "./get-source
|
|
9
|
+
} from "./owner-stack";
|
|
10
|
+
export { getRawSource, getSource, isSourceFile, normalizeFileName } from "./get-source";
|
|
11
11
|
export {
|
|
12
12
|
getSourceContentFromSourceMap,
|
|
13
13
|
getSourceFromSourceMap,
|
|
@@ -20,22 +20,22 @@ export {
|
|
|
20
20
|
type SourceMap,
|
|
21
21
|
type SourceMapRequestOptions,
|
|
22
22
|
type StandardSourceMap,
|
|
23
|
-
} from "./symbolication
|
|
24
|
-
export type { FiberSource } from "./types
|
|
25
|
-
export { parseStack, type ParseOptions, type StackFrame } from "./parse-stack
|
|
26
|
-
export { getDisplayNameFromSource } from "./get-display-name-from-source
|
|
23
|
+
} from "./symbolication";
|
|
24
|
+
export type { FiberSource } from "./types";
|
|
25
|
+
export { parseStack, type ParseOptions, type StackFrame } from "./parse-stack";
|
|
26
|
+
export { getDisplayNameFromSource } from "./get-display-name-from-source";
|
|
27
27
|
export {
|
|
28
28
|
BippyError,
|
|
29
29
|
BippyHookInspectionError,
|
|
30
30
|
BippyHookRenderError,
|
|
31
31
|
BippySourceMapError,
|
|
32
32
|
BippyUnsupportedHookError,
|
|
33
|
-
} from "../errors
|
|
33
|
+
} from "../errors";
|
|
34
34
|
export {
|
|
35
35
|
getFiberHooks,
|
|
36
36
|
inspectHooks,
|
|
37
37
|
type HookSource,
|
|
38
38
|
type HooksNode,
|
|
39
39
|
type HooksTree,
|
|
40
|
-
} from "./inspect-hooks
|
|
41
|
-
export { parseHookNames, type HookNames } from "./parse-hook-names
|
|
40
|
+
} from "./inspect-hooks";
|
|
41
|
+
export { parseHookNames, type HookNames } from "./parse-hook-names";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getRenderer } from "../core
|
|
2
|
-
import type { ReactDevToolsTarget } from "../rdt-hook
|
|
1
|
+
import { getRenderer } from "../core";
|
|
2
|
+
import type { ReactDevToolsTarget } from "../rdt-hook";
|
|
3
3
|
import type {
|
|
4
4
|
Fiber,
|
|
5
5
|
ContextDependency,
|
|
@@ -7,19 +7,15 @@ import type {
|
|
|
7
7
|
ReactContext,
|
|
8
8
|
ReactDebugInfo,
|
|
9
9
|
RendererDispatcherRef,
|
|
10
|
-
} from "../react-internals/index
|
|
10
|
+
} from "../react-internals/index";
|
|
11
11
|
import {
|
|
12
12
|
BippyHookInspectionError,
|
|
13
13
|
BippyHookRenderError,
|
|
14
14
|
BippyUnsupportedHookError,
|
|
15
|
-
} from "../errors
|
|
16
|
-
import { getReactWorkTagsForFiber } from "../react-internals/index
|
|
17
|
-
import { parseStack, type StackFrame } from "./parse-stack
|
|
18
|
-
import {
|
|
19
|
-
getRendererDispatcherRefs,
|
|
20
|
-
readDispatcher,
|
|
21
|
-
writeDispatcher,
|
|
22
|
-
} from "./renderer-dispatchers.js";
|
|
15
|
+
} from "../errors";
|
|
16
|
+
import { getReactWorkTagsForFiber } from "../react-internals/index";
|
|
17
|
+
import { createStackParser, parseStack, type StackFrame } from "./parse-stack";
|
|
18
|
+
import { getRendererDispatcherRefs, readDispatcher, writeDispatcher } from "./renderer-dispatchers";
|
|
23
19
|
|
|
24
20
|
const REACT_CONTEXT_TYPE = Symbol.for("react.context");
|
|
25
21
|
const REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
|
|
@@ -604,8 +600,9 @@ const findPrimitiveIndex = (hookStack: StackFrame[], hook: HookLogEntry): number
|
|
|
604
600
|
const parseTrimmedStack = (
|
|
605
601
|
rootStack: StackFrame[],
|
|
606
602
|
hook: HookLogEntry,
|
|
603
|
+
parseHookStack: (stack: string) => StackFrame[],
|
|
607
604
|
): [StackFrame | null, StackFrame[] | null] => {
|
|
608
|
-
const hookStack =
|
|
605
|
+
const hookStack = parseHookStack(hook.stackError.stack || "");
|
|
609
606
|
const rootIndex = findCommonAncestorIndex(rootStack, hookStack);
|
|
610
607
|
const primitiveIndex = findPrimitiveIndex(hookStack, hook);
|
|
611
608
|
if (rootIndex === -1 || primitiveIndex === -1 || rootIndex - primitiveIndex < 2) {
|
|
@@ -626,13 +623,14 @@ const NON_ID_HOOK_PRIMITIVES = new Set([
|
|
|
626
623
|
|
|
627
624
|
const buildTree = (rootStack: StackFrame[], capturedHookLog: HookLogEntry[]): HooksTree => {
|
|
628
625
|
const rootChildren: HooksNode[] = [];
|
|
626
|
+
const parseHookStack = createStackParser();
|
|
629
627
|
let previousStack: StackFrame[] | null = null;
|
|
630
628
|
let levelChildren = rootChildren;
|
|
631
629
|
let nativeHookID = 0;
|
|
632
630
|
const childrenStack: HooksNode[][] = [];
|
|
633
631
|
|
|
634
632
|
for (const hook of capturedHookLog) {
|
|
635
|
-
const [primitiveFrame, stack] = parseTrimmedStack(rootStack, hook);
|
|
633
|
+
const [primitiveFrame, stack] = parseTrimmedStack(rootStack, hook, parseHookStack);
|
|
636
634
|
let displayName = hook.displayName;
|
|
637
635
|
if (displayName === null && primitiveFrame !== null) {
|
|
638
636
|
const primitiveName = parseHookName(primitiveFrame.functionName);
|