main
js 139 lines 3.58 KB
Raw
1 'use strict';
2
3 type DebugInfoConfig = {
4 ignoreProps?: boolean,
5 ignoreRscStreamInfo?: boolean,
6 useFixedTime?: boolean,
7 useV8Stack?: boolean,
8 };
9
10 function formatV8Stack(stack) {
11 let v8StyleStack = '';
12 if (stack) {
13 for (let i = 0; i < stack.length; i++) {
14 const [name] = stack[i];
15 if (v8StyleStack !== '') {
16 v8StyleStack += '\n';
17 }
18 v8StyleStack += ' in ' + name + ' (at **)';
19 }
20 }
21 return v8StyleStack;
22 }
23
24 function normalizeStack(stack) {
25 if (!stack) {
26 return stack;
27 }
28 const copy = [];
29 for (let i = 0; i < stack.length; i++) {
30 const [name, file, line, col, enclosingLine, enclosingCol] = stack[i];
31 copy.push([
32 name,
33 file.replace(__REACT_ROOT_PATH_TEST__, ''),
34 line,
35 col,
36 enclosingLine,
37 enclosingCol,
38 ]);
39 }
40 return copy;
41 }
42
43 function normalizeIOInfo(config: DebugInfoConfig, ioInfo) {
44 const {debugTask, debugStack, debugLocation, ...copy} = ioInfo;
45 if (ioInfo.stack) {
46 copy.stack = config.useV8Stack
47 ? formatV8Stack(ioInfo.stack)
48 : normalizeStack(ioInfo.stack);
49 }
50 if (ioInfo.owner) {
51 copy.owner = normalizeDebugInfo(config, ioInfo.owner);
52 }
53 if (typeof ioInfo.start === 'number' && config.useFixedTime) {
54 copy.start = 0;
55 }
56 if (typeof ioInfo.end === 'number' && config.useFixedTime) {
57 copy.end = 0;
58 }
59 const promise = ioInfo.value;
60 if (promise) {
61 promise.then(); // init
62 if (promise.status === 'fulfilled') {
63 if (ioInfo.name === 'rsc stream') {
64 copy.byteSize = 0;
65 copy.value = {
66 value: 'stream',
67 };
68 } else {
69 copy.value = {
70 value: promise.value,
71 };
72 }
73 } else if (promise.status === 'rejected') {
74 copy.value = {
75 reason: promise.reason,
76 };
77 } else {
78 copy.value = {
79 status: promise.status,
80 };
81 }
82 } else if ('value' in ioInfo) {
83 // If value exists in ioInfo but is undefined (e.g., WeakRef was GC'd),
84 // ensure we still include it in the normalized output for consistency
85 copy.value = {
86 value: undefined,
87 };
88 } else if (ioInfo.name && ioInfo.name !== 'rsc stream') {
89 // For non-rsc-stream IO that doesn't have a value field, add a default.
90 // This handles the case where the server doesn't send the field when WeakRef is GC'd.
91 copy.value = {
92 value: undefined,
93 };
94 }
95 return copy;
96 }
97
98 function normalizeDebugInfo(config: DebugInfoConfig, original) {
99 const {debugTask, debugStack, debugLocation, ...debugInfo} = original;
100 if (original.owner) {
101 debugInfo.owner = normalizeDebugInfo(config, original.owner);
102 }
103 if (original.awaited) {
104 debugInfo.awaited = normalizeIOInfo(config, original.awaited);
105 }
106 if (debugInfo.props && config.ignoreProps) {
107 debugInfo.props = {};
108 }
109 if (Array.isArray(debugInfo.stack)) {
110 debugInfo.stack = config.useV8Stack
111 ? formatV8Stack(debugInfo.stack)
112 : normalizeStack(debugInfo.stack);
113 return debugInfo;
114 } else if (typeof debugInfo.time === 'number' && config.useFixedTime) {
115 return {...debugInfo, time: 0};
116 } else {
117 return debugInfo;
118 }
119 }
120
121 export function getDebugInfo(config: DebugInfoConfig, obj) {
122 const debugInfo = obj._debugInfo;
123 if (debugInfo) {
124 const copy = [];
125 for (let i = 0; i < debugInfo.length; i++) {
126 if (
127 debugInfo[i].awaited &&
128 debugInfo[i].awaited.name === 'rsc stream' &&
129 config.ignoreRscStreamInfo
130 ) {
131 // Ignore RSC stream I/O info.
132 } else {
133 copy.push(normalizeDebugInfo(config, debugInfo[i]));
134 }
135 }
136 return copy;
137 }
138 return debugInfo;
139 }