bippy 0.6.1-dev.3a24abf → 0.6.1-dev.93556ef

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +26 -1
  3. package/dist/core.cjs +1 -1
  4. package/dist/core.d.cts +39 -42
  5. package/dist/core.d.ts +39 -42
  6. package/dist/core.js +1 -1
  7. package/dist/core2.cjs +1 -1
  8. package/dist/core2.d.cts +11 -3
  9. package/dist/core2.d.ts +11 -3
  10. package/dist/core2.js +1 -1
  11. package/dist/{types.d.cts → errors.d.cts} +187 -68
  12. package/dist/{types.d.ts → errors.d.ts} +187 -68
  13. package/dist/index.cjs +1 -1
  14. package/dist/index.d.cts +11 -3
  15. package/dist/index.d.ts +11 -3
  16. package/dist/index.iife.js +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/install-hook-only.cjs +1 -1
  19. package/dist/install-hook-only.d.cts +8 -0
  20. package/dist/install-hook-only.d.ts +8 -0
  21. package/dist/install-hook-only.iife.js +1 -1
  22. package/dist/install-hook-only.js +1 -1
  23. package/dist/rdt-hook.cjs +1 -1
  24. package/dist/rdt-hook.js +1 -1
  25. package/dist/source.cjs +13 -14
  26. package/dist/source.d.cts +86 -69
  27. package/dist/source.d.ts +86 -69
  28. package/dist/source.js +13 -14
  29. package/package.json +10 -6
  30. package/src/core.ts +246 -293
  31. package/src/errors.ts +34 -0
  32. package/src/install-hook-only.ts +2 -2
  33. package/src/rdt-hook.ts +152 -110
  34. package/src/react-internals/generated/react-work-tags.ts +318 -0
  35. package/src/react-internals/index.ts +67 -0
  36. package/src/react-internals/semver.ts +80 -0
  37. package/src/{types.ts → react-internals/types.ts} +13 -86
  38. package/src/source/error-stack.ts +11 -0
  39. package/src/source/get-display-name-from-source.ts +44 -40
  40. package/src/source/get-source.ts +42 -26
  41. package/src/source/index.ts +11 -1
  42. package/src/source/inspect-hooks.ts +220 -207
  43. package/src/source/owner-stack.ts +86 -128
  44. package/src/source/parse-debug-stack.ts +4 -4
  45. package/src/source/parse-hook-names.ts +14 -53
  46. package/src/source/parse-stack.ts +14 -31
  47. package/src/source/renderer-dispatchers.ts +30 -0
  48. package/src/source/symbolication.ts +703 -135
  49. package/src/generated/react-work-tags.ts +0 -169
  50. package/src/react-internals.ts +0 -67
  51. package/src/unsubscribe.ts +0 -17
@@ -1,8 +1,29 @@
1
- import { Fiber } from "../types.js";
1
+ import type { Fiber } from "../react-internals/index.js";
2
2
  import { getDisplayName } from "../core.js";
3
- import { getParentStack } from "./owner-stack.js";
4
- import { getSourceFromSourceMap, getSourceMap } from "./symbolication.js";
5
- import { StackFrame } from "./parse-stack.js";
3
+ import { getDefinitionFrameFromOwnedChild, getRawParentStack } from "./owner-stack.js";
4
+ import {
5
+ getSourceContentFromSourceMap,
6
+ getSourceFromSourceMap,
7
+ getSourceMap,
8
+ type SourceFetch,
9
+ } from "./symbolication.js";
10
+ import type { StackFrame } from "./parse-stack.js";
11
+
12
+ const COMPONENT_DECLARATION_PATTERNS = [
13
+ /(?:^|export\s+)(?:const|let|var)\s+(\w+)\s*=/,
14
+ /(?:^|export\s+)function\s+(\w+)/,
15
+ /(?:^|export\s+)class\s+(\w+)/,
16
+ ];
17
+
18
+ const findComponentDeclarationOnLine = (line: string): string | null => {
19
+ for (const pattern of COMPONENT_DECLARATION_PATTERNS) {
20
+ const match = line.match(pattern);
21
+ if (match?.[1]) return match[1];
22
+ }
23
+ return null;
24
+ };
25
+
26
+ const MAX_DECLARATION_LINE_DISTANCE = 5;
6
27
 
7
28
  const extractComponentNameFromSource = (
8
29
  sourceContent: string,
@@ -15,27 +36,16 @@ const extractComponentNameFromSource = (
15
36
  return null;
16
37
  }
17
38
 
18
- const startLine = Math.max(0, targetLineIndex - 5);
19
- const endLine = Math.min(lines.length, targetLineIndex + 5);
20
- const contextLines = lines.slice(startLine, endLine).join("\n");
21
-
22
- const arrowFunctionPattern = /(?:^|export\s+)(?:const|let|var)\s+(\w+)\s*=/m;
23
- const functionPattern = /(?:^|export\s+)function\s+(\w+)/m;
24
- const classPattern = /(?:^|export\s+)class\s+(\w+)/m;
25
-
26
- const arrowMatch = contextLines.match(arrowFunctionPattern);
27
- if (arrowMatch?.[1]) {
28
- return arrowMatch[1];
29
- }
30
-
31
- const functionMatch = contextLines.match(functionPattern);
32
- if (functionMatch?.[1]) {
33
- return functionMatch[1];
34
- }
35
-
36
- const classMatch = contextLines.match(classPattern);
37
- if (classMatch?.[1]) {
38
- return classMatch[1];
39
+ for (let lineDistance = 0; lineDistance <= MAX_DECLARATION_LINE_DISTANCE; lineDistance++) {
40
+ const lineIndexes =
41
+ lineDistance === 0
42
+ ? [targetLineIndex]
43
+ : [targetLineIndex - lineDistance, targetLineIndex + lineDistance];
44
+ for (const lineIndex of lineIndexes) {
45
+ if (lineIndex < 0 || lineIndex >= lines.length) continue;
46
+ const declarationName = findComponentDeclarationOnLine(lines[lineIndex]);
47
+ if (declarationName) return declarationName;
48
+ }
39
49
  }
40
50
 
41
51
  return null;
@@ -44,10 +54,11 @@ const extractComponentNameFromSource = (
44
54
  export const getDisplayNameFromSource = async (
45
55
  fiber: Fiber,
46
56
  cache = true,
47
- fetchFn?: (url: string) => Promise<Response>,
57
+ fetchFn?: SourceFetch,
48
58
  ): Promise<string | null> => {
49
- const parentStackFrames = await getParentStack(fiber, cache, fetchFn);
50
- const stackFrame = parentStackFrames.filter((innerFrame) => innerFrame.fileName)[0];
59
+ const stackFrame =
60
+ getDefinitionFrameFromOwnedChild(fiber) ??
61
+ getRawParentStack(fiber).find((innerFrame) => innerFrame.fileName);
51
62
 
52
63
  if (!stackFrame?.fileName) {
53
64
  return getDisplayName(fiber.type);
@@ -73,21 +84,14 @@ export const getDisplayNameFromSource = async (
73
84
  return getDisplayName(fiber.type);
74
85
  }
75
86
 
76
- if (!bundleSourceMap.sourcesContent) {
77
- return getDisplayName(fiber.type);
78
- }
79
-
80
- const sourceIndex = bundleSourceMap.sources.indexOf(source.fileName);
81
- if (sourceIndex === -1 || !bundleSourceMap.sourcesContent[sourceIndex]) {
82
- return getDisplayName(fiber.type);
83
- }
84
-
85
- const sourceContent = bundleSourceMap.sourcesContent[sourceIndex];
86
- const extractedName = extractComponentNameFromSource(sourceContent, source.lineNumber);
87
+ const sourceContent = getSourceContentFromSourceMap(bundleSourceMap, source.fileName);
88
+ const extractedName = sourceContent
89
+ ? extractComponentNameFromSource(sourceContent, source.lineNumber)
90
+ : null;
87
91
 
88
92
  if (extractedName) {
89
93
  return extractedName;
90
94
  }
91
95
 
92
- return getDisplayName(fiber.type);
96
+ return source.functionName ?? getDisplayName(fiber.type);
93
97
  };
@@ -1,6 +1,7 @@
1
- import { Fiber } from "../types.js";
1
+ import type { Fiber } from "../react-internals/index.js";
2
+ import { getDisplayName } from "../core.js";
2
3
 
3
- import { FiberSource } from "./types.js";
4
+ import type { FiberSource } from "./types.js";
4
5
  import {
5
6
  SCHEME_REGEX,
6
7
  INTERNAL_SCHEME_PREFIXES,
@@ -12,8 +13,13 @@ import {
12
13
  } from "./constants.js";
13
14
  import { getDefinitionFrameFromOwnedChild, getParentStack, hasDebugStack } from "./owner-stack.js";
14
15
  import { parseDebugStack } from "./parse-debug-stack.js";
15
- import { StackFrame } from "./parse-stack.js";
16
- import { symbolicateStack } from "./symbolication.js";
16
+ import { parseStack, type StackFrame } from "./parse-stack.js";
17
+ import {
18
+ getSourceFromSourceMapByFunctionName,
19
+ getSourceMap,
20
+ symbolicateStack,
21
+ type SourceFetch,
22
+ } from "./symbolication.js";
17
23
 
18
24
  export const hasDebugSource = (
19
25
  fiber: Fiber,
@@ -26,10 +32,8 @@ export const hasDebugSource = (
26
32
  }
27
33
  return (
28
34
  typeof debugSource === "object" &&
29
- debugSource !== null &&
30
- "fileName" in debugSource &&
31
35
  typeof debugSource.fileName === "string" &&
32
- "lineNumber" in debugSource &&
36
+ debugSource.fileName !== "(native)" &&
33
37
  typeof debugSource.lineNumber === "number"
34
38
  );
35
39
  };
@@ -63,6 +67,30 @@ const getUsageFrameFromDebugStack = (fiber: Fiber): StackFrame | null => {
63
67
  return null;
64
68
  };
65
69
 
70
+ const getSourceByComponentName = async (
71
+ fiber: Fiber,
72
+ cache: boolean,
73
+ fetchFn: SourceFetch | undefined,
74
+ ): Promise<FiberSource | null> => {
75
+ const functionName = getDisplayName(fiber.type);
76
+ if (!functionName) return null;
77
+
78
+ const runtimeStackFrames = parseStack(new Error().stack ?? "");
79
+ const visitedFileNames = new Set<string>();
80
+ for (const stackFrame of runtimeStackFrames) {
81
+ const fileName = stackFrame.fileName;
82
+ if (!fileName || visitedFileNames.has(fileName)) {
83
+ continue;
84
+ }
85
+ visitedFileNames.add(fileName);
86
+ const sourceMap = await getSourceMap(fileName, cache, fetchFn);
87
+ if (!sourceMap) continue;
88
+ const source = getSourceFromSourceMapByFunctionName(sourceMap, functionName);
89
+ if (source && !source.isIgnoreListed) return toFiberSource(source);
90
+ }
91
+ return null;
92
+ };
93
+
66
94
  /**
67
95
  * Returns the source of where the component is used. Available only in dev, for composite {@link Fiber}s.
68
96
  *
@@ -92,11 +120,10 @@ const getUsageFrameFromDebugStack = (fiber: Fiber): StackFrame | null => {
92
120
  export const getSource = async (
93
121
  fiber: Fiber,
94
122
  cache = true,
95
- fetchFn?: (url: string) => Promise<Response>,
123
+ fetchFn?: SourceFetch,
96
124
  ): Promise<FiberSource | null> => {
97
125
  if (hasDebugSource(fiber)) {
98
- const debugSource = fiber._debugSource;
99
- return debugSource || null;
126
+ return fiber._debugSource;
100
127
  }
101
128
 
102
129
  const debugStackFrame =
@@ -115,16 +142,11 @@ export const getSource = async (
115
142
  return toFiberSource(stackFrame);
116
143
  }
117
144
  }
118
- return null;
145
+ return getSourceByComponentName(fiber, cache, fetchFn);
119
146
  };
120
147
 
121
148
  const getPathSegmentCount = (path: string): number => path.split("/").filter(Boolean).length;
122
149
 
123
- const getFirstPathSegment = (path: string): string | null => {
124
- const segments = path.split("/").filter(Boolean);
125
- return segments[0] ?? null;
126
- };
127
-
128
150
  const stripSingleBasePathPrefix = (path: string): string => {
129
151
  const firstSlashIndex = path.indexOf("/", 1);
130
152
  if (firstSlashIndex === -1) {
@@ -141,15 +163,12 @@ const stripSingleBasePathPrefix = (path: string): string => {
141
163
  return path;
142
164
  }
143
165
 
144
- if (getPathSegmentCount(remainderPath) < 2) {
145
- return path;
146
- }
147
-
148
- const firstRemainderSegment = getFirstPathSegment(remainderPath);
149
- if (!firstRemainderSegment) {
166
+ const remainderSegments = remainderPath.split("/").filter(Boolean);
167
+ if (remainderSegments.length < 2) {
150
168
  return path;
151
169
  }
152
170
 
171
+ const firstRemainderSegment = remainderSegments[0];
153
172
  if (firstRemainderSegment.startsWith("@")) {
154
173
  return path;
155
174
  }
@@ -180,9 +199,6 @@ export const normalizeFileName = (fileName: string): string => {
180
199
  const parsedUrl = new URL(normalizedFileName);
181
200
  normalizedFileName = parsedUrl.pathname;
182
201
  } catch {}
183
- }
184
-
185
- if (isHttpUrl) {
186
202
  normalizedFileName = stripSingleBasePathPrefix(normalizedFileName);
187
203
  }
188
204
 
@@ -215,7 +231,7 @@ export const normalizeFileName = (fileName: string): string => {
215
231
  }
216
232
  }
217
233
 
218
- if (!isWindowsDrivePath && SCHEME_REGEX.test(normalizedFileName)) {
234
+ if (!isWindowsDrivePath) {
219
235
  const schemeMatch = normalizedFileName.match(SCHEME_REGEX);
220
236
  if (schemeMatch) {
221
237
  normalizedFileName = normalizedFileName.slice(schemeMatch[0].length);
@@ -1,17 +1,27 @@
1
1
  export { formatOwnerStack, getOwnerStack, getParentStack, hasDebugStack } from "./owner-stack.js";
2
2
  export { getSource, isSourceFile, normalizeFileName } from "./get-source.js";
3
3
  export {
4
+ getSourceContentFromSourceMap,
4
5
  getSourceFromSourceMap,
6
+ getSourceFromSourceMapByFunctionName,
5
7
  getSourceMap,
6
8
  symbolicateStack,
7
9
  type DecodedSourceMapSection,
8
10
  type IndexSourceMap,
9
- type RawSourceMap,
11
+ type SourceFetch,
10
12
  type SourceMap,
13
+ type SourceMapRequestOptions,
11
14
  type StandardSourceMap,
12
15
  } from "./symbolication.js";
13
16
  export type { FiberSource } from "./types.js";
14
17
  export { parseStack, type ParseOptions, type StackFrame } from "./parse-stack.js";
15
18
  export { getDisplayNameFromSource } from "./get-display-name-from-source.js";
19
+ export {
20
+ BippyError,
21
+ BippyHookInspectionError,
22
+ BippyHookRenderError,
23
+ BippySourceMapError,
24
+ BippyUnsupportedHookError,
25
+ } from "../errors.js";
16
26
  export { getFiberHooks, type HookSource, type HooksNode, type HooksTree } from "./inspect-hooks.js";
17
27
  export { parseHookNames, type HookNames } from "./parse-hook-names.js";