warpo 3.1.0 → 3.1.2

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 (178) hide show
  1. package/dist/debug_server/debugPath.d.ts +1 -0
  2. package/dist/debug_server/debugPath.js +10 -0
  3. package/dist/debug_server/debugPath.js.map +1 -0
  4. package/dist/debug_server/debugSession.d.ts +60 -2
  5. package/dist/debug_server/debugSession.js +883 -40
  6. package/dist/debug_server/debugSession.js.map +1 -1
  7. package/dist/debug_server/debugger.d.ts +30 -2
  8. package/dist/debug_server/debuggerWasmModule.d.ts +58 -3
  9. package/dist/debug_server/debuggerWasmModule.js +222 -14
  10. package/dist/debug_server/debuggerWasmModule.js.map +1 -1
  11. package/dist/debug_server/nodeDebugger.d.ts +37 -3
  12. package/dist/debug_server/nodeDebugger.js +590 -59
  13. package/dist/debug_server/nodeDebugger.js.map +1 -1
  14. package/dist/debug_server/tests/debugSession.test.js +1015 -26
  15. package/dist/debug_server/tests/debugSession.test.js.map +1 -1
  16. package/dist/debug_server/tests/launcher.js +1 -0
  17. package/dist/debug_server/tests/launcher.js.map +1 -1
  18. package/dist/debug_server/tests/testModule/debugger_array.d.ts +1 -0
  19. package/dist/debug_server/tests/testModule/debugger_array.js +9 -0
  20. package/dist/debug_server/tests/testModule/debugger_array.js.map +1 -0
  21. package/dist/debug_server/tests/testModule/debugger_array_buffer.d.ts +1 -0
  22. package/dist/debug_server/tests/testModule/debugger_array_buffer.js +12 -0
  23. package/dist/debug_server/tests/testModule/debugger_array_buffer.js.map +1 -0
  24. package/dist/debug_server/tests/testModule/debugger_basic.d.ts +1 -0
  25. package/dist/debug_server/tests/testModule/debugger_basic.js +9 -1
  26. package/dist/debug_server/tests/testModule/debugger_basic.js.map +1 -1
  27. package/dist/debug_server/tests/testModule/debugger_callee.d.ts +10 -0
  28. package/dist/debug_server/tests/testModule/debugger_callee.js +106 -0
  29. package/dist/debug_server/tests/testModule/debugger_callee.js.map +1 -0
  30. package/dist/debug_server/tests/testModule/debugger_caller.d.ts +1 -0
  31. package/dist/debug_server/tests/testModule/debugger_caller.js +7 -0
  32. package/dist/debug_server/tests/testModule/debugger_caller.js.map +1 -0
  33. package/dist/debug_server/tests/testModule/debugger_class.d.ts +1 -0
  34. package/dist/debug_server/tests/testModule/debugger_class.js +39 -0
  35. package/dist/debug_server/tests/testModule/debugger_class.js.map +1 -0
  36. package/dist/debug_server/tests/testModule/debugger_class_array.d.ts +1 -0
  37. package/dist/debug_server/tests/testModule/debugger_class_array.js +15 -0
  38. package/dist/debug_server/tests/testModule/debugger_class_array.js.map +1 -0
  39. package/dist/debug_server/tests/testModule/debugger_closure.d.ts +1 -0
  40. package/dist/debug_server/tests/testModule/debugger_closure.js +48 -0
  41. package/dist/debug_server/tests/testModule/debugger_closure.js.map +1 -0
  42. package/dist/debug_server/tests/testModule/debugger_closure_if.d.ts +1 -0
  43. package/dist/debug_server/tests/testModule/debugger_closure_if.js +16 -0
  44. package/dist/debug_server/tests/testModule/debugger_closure_if.js.map +1 -0
  45. package/dist/debug_server/tests/testModule/debugger_global.d.ts +1 -0
  46. package/dist/debug_server/tests/testModule/debugger_global.js +11 -0
  47. package/dist/debug_server/tests/testModule/debugger_global.js.map +1 -0
  48. package/dist/debug_server/tests/testModule/debugger_map.d.ts +1 -0
  49. package/dist/debug_server/tests/testModule/debugger_map.js +22 -0
  50. package/dist/debug_server/tests/testModule/debugger_map.js.map +1 -0
  51. package/dist/debug_server/tests/testModule/debugger_scopes.d.ts +1 -0
  52. package/dist/debug_server/tests/testModule/debugger_scopes.js +22 -0
  53. package/dist/debug_server/tests/testModule/debugger_scopes.js.map +1 -0
  54. package/dist/debug_server/tests/testModule/debugger_set.d.ts +1 -0
  55. package/dist/debug_server/tests/testModule/debugger_set.js +23 -0
  56. package/dist/debug_server/tests/testModule/debugger_set.js.map +1 -0
  57. package/dist/debug_server/tests/testModule/debugger_static_array.d.ts +1 -0
  58. package/dist/debug_server/tests/testModule/debugger_static_array.js +21 -0
  59. package/dist/debug_server/tests/testModule/debugger_static_array.js.map +1 -0
  60. package/dist/debug_server/tests/testModule/debugger_string.d.ts +1 -0
  61. package/dist/debug_server/tests/testModule/debugger_string.js +16 -0
  62. package/dist/debug_server/tests/testModule/debugger_string.js.map +1 -0
  63. package/dist/debug_server/tests/testModule/debugger_trap.d.ts +1 -0
  64. package/dist/debug_server/tests/testModule/debugger_trap.js +9 -0
  65. package/dist/debug_server/tests/testModule/debugger_trap.js.map +1 -0
  66. package/dist/debug_server/tests/testModule/debugger_tuple.d.ts +1 -0
  67. package/dist/debug_server/tests/testModule/debugger_tuple.js +15 -0
  68. package/dist/debug_server/tests/testModule/debugger_tuple.js.map +1 -0
  69. package/dist/debug_server/tests/testModule/import_failure.d.ts +1 -0
  70. package/dist/debug_server/tests/testModule/import_failure.js +4 -0
  71. package/dist/debug_server/tests/testModule/import_failure.js.map +1 -0
  72. package/dist/debug_server/tests/testModule/unittest_debug.case.js +10 -0
  73. package/dist/debug_server/tests/testModule/unittest_debug.case.js.map +1 -0
  74. package/dist/debug_server/tests/testModule/unittest_debug.d.ts +1 -0
  75. package/dist/debug_server/tests/testModule/unittest_debug.js +6 -0
  76. package/dist/debug_server/tests/testModule/unittest_debug.js.map +1 -0
  77. package/dist/debug_server/wasmEntry.js +32 -12
  78. package/dist/debug_server/wasmEntry.js.map +1 -1
  79. package/dist/dwarf/classDebugInfo.d.ts +45 -0
  80. package/dist/dwarf/classDebugInfo.js +292 -0
  81. package/dist/dwarf/classDebugInfo.js.map +1 -0
  82. package/dist/{heap_analyzer/src → dwarf}/dwarfParser.js +2 -0
  83. package/dist/dwarf/dwarfParser.js.map +1 -0
  84. package/dist/dwarf/functionDebugInfo.d.ts +63 -0
  85. package/dist/dwarf/functionDebugInfo.js +377 -0
  86. package/dist/dwarf/functionDebugInfo.js.map +1 -0
  87. package/dist/dwarf/tests/fixtures/functionDebugInfo.d.ts +3 -0
  88. package/dist/dwarf/tests/fixtures/functionDebugInfo.js +24 -0
  89. package/dist/dwarf/tests/fixtures/functionDebugInfo.js.map +1 -0
  90. package/dist/dwarf/tests/functionDebugInfo.test.d.ts +1 -0
  91. package/dist/dwarf/tests/functionDebugInfo.test.js +102 -0
  92. package/dist/dwarf/tests/functionDebugInfo.test.js.map +1 -0
  93. package/dist/heap_analyzer/cli.d.ts +1 -0
  94. package/dist/heap_analyzer/cli.js +172 -0
  95. package/dist/heap_analyzer/cli.js.map +1 -0
  96. package/dist/heap_analyzer/src/constants.js +2 -1
  97. package/dist/heap_analyzer/src/constants.js.map +1 -1
  98. package/dist/heap_analyzer/src/debugInfoResolver.d.ts +4 -15
  99. package/dist/heap_analyzer/src/debugInfoResolver.js +20 -231
  100. package/dist/heap_analyzer/src/debugInfoResolver.js.map +1 -1
  101. package/dist/heap_analyzer/src/dominator.js +4 -1
  102. package/dist/heap_analyzer/src/dominator.js.map +1 -1
  103. package/dist/heap_analyzer/src/referenceScanner.js +7 -7
  104. package/dist/heap_analyzer/src/referenceScanner.js.map +1 -1
  105. package/dist/heap_analyzer/src/retainedSize.js +2 -0
  106. package/dist/heap_analyzer/src/retainedSize.js.map +1 -1
  107. package/dist/heap_analyzer/src/snapshot.js +1 -1
  108. package/dist/heap_analyzer/src/snapshot.js.map +1 -1
  109. package/dist/heap_analyzer/src/{tlsf.js → tlsfBlockWalker.js} +4 -3
  110. package/dist/heap_analyzer/src/tlsfBlockWalker.js.map +1 -0
  111. package/dist/heap_analyzer/src/types.d.ts +3 -32
  112. package/dist/heap_analyzer/src/types.js +1 -8
  113. package/dist/heap_analyzer/src/types.js.map +1 -1
  114. package/dist/heap_analyzer/tests/debugInfoResolver.test.js +1 -1
  115. package/dist/heap_analyzer/tests/debugInfoResolver.test.js.map +1 -1
  116. package/dist/heap_analyzer/tests/dwarfParser.test.js +57 -40
  117. package/dist/heap_analyzer/tests/dwarfParser.test.js.map +1 -1
  118. package/dist/heap_analyzer/tests/roots.test.js +1 -1
  119. package/dist/heap_analyzer/tests/roots.test.js.map +1 -1
  120. package/dist/heap_analyzer/tests/snapshot.test.js +4 -4
  121. package/dist/heap_analyzer/tests/testHelper.js +4 -7
  122. package/dist/heap_analyzer/tests/testHelper.js.map +1 -1
  123. package/dist/heap_analyzer/tests/tlsfBlockWalker.test.d.ts +1 -0
  124. package/dist/heap_analyzer/tests/{tlsf.test.js → tlsfBlockWalker.test.js} +2 -2
  125. package/dist/heap_analyzer/tests/tlsfBlockWalker.test.js.map +1 -0
  126. package/dist/heap_analyzer/tests/wasmExecutor.d.ts +2 -2
  127. package/dist/heap_analyzer/tests/wasmExecutor.js +5 -5
  128. package/dist/heap_analyzer/tests/wasmExecutor.js.map +1 -1
  129. package/dist/runtime/objectLayout.d.ts +10 -0
  130. package/dist/runtime/objectLayout.js +13 -0
  131. package/dist/runtime/objectLayout.js.map +1 -0
  132. package/dist/scripts/lib.d.ts +1 -0
  133. package/dist/scripts/lib.js +86 -22
  134. package/dist/scripts/lib.js.map +1 -1
  135. package/dist/test_runner/cli.d.ts +0 -1
  136. package/dist/test_runner/cli.js +37 -19
  137. package/dist/test_runner/cli.js.map +1 -1
  138. package/dist/test_runner/config.d.ts +3 -0
  139. package/dist/test_runner/config.js +8 -0
  140. package/dist/test_runner/config.js.map +1 -0
  141. package/dist/test_runner/core/analyze.js +12 -3
  142. package/dist/test_runner/core/analyze.js.map +1 -1
  143. package/dist/test_runner/core/compile.js +1 -4
  144. package/dist/test_runner/core/compile.js.map +1 -1
  145. package/dist/test_runner/core/execute.js +20 -3
  146. package/dist/test_runner/core/execute.js.map +1 -1
  147. package/dist/test_runner/executionResult.js +10 -8
  148. package/dist/test_runner/executionResult.js.map +1 -1
  149. package/dist/test_runner/generator/table-generator/index.js +4 -2
  150. package/dist/test_runner/generator/table-generator/index.js.map +1 -1
  151. package/dist/test_runner/parser/index.js +6 -5
  152. package/dist/test_runner/parser/index.js.map +1 -1
  153. package/dist/test_runner/parser/singleFileAnalysis.js +7 -4
  154. package/dist/test_runner/parser/singleFileAnalysis.js.map +1 -1
  155. package/dist/test_runner/parser/singleFunctionAnalysis.js +1 -1
  156. package/dist/test_runner/parser/singleFunctionAnalysis.js.map +1 -1
  157. package/dist/test_runner/utils/errorTraceHandler.js +2 -1
  158. package/dist/test_runner/utils/errorTraceHandler.js.map +1 -1
  159. package/dist/test_runner/utils/index.js +9 -2
  160. package/dist/test_runner/utils/index.js.map +1 -1
  161. package/dist/test_runner/utils/interface.js +2 -1
  162. package/dist/test_runner/utils/interface.js.map +1 -1
  163. package/dist/test_runner/utils/pathResolver.js +9 -7
  164. package/dist/test_runner/utils/pathResolver.js.map +1 -1
  165. package/dist/test_runner/utils/wasm.js +16 -8
  166. package/dist/test_runner/utils/wasm.js.map +1 -1
  167. package/dist/trace_visualizer.d.ts +2 -0
  168. package/dist/trace_visualizer.js +18 -0
  169. package/dist/trace_visualizer.js.map +1 -0
  170. package/dist/warpo.js +2 -1
  171. package/dist/warpo.js.map +1 -1
  172. package/package.json +10 -5
  173. package/dist/heap_analyzer/src/dwarfParser.js.map +0 -1
  174. package/dist/heap_analyzer/src/tlsf.js.map +0 -1
  175. package/dist/heap_analyzer/tests/tlsf.test.js.map +0 -1
  176. /package/dist/{heap_analyzer/tests/tlsf.test.d.ts → debug_server/tests/testModule/unittest_debug.case.d.ts} +0 -0
  177. /package/dist/{heap_analyzer/src → dwarf}/dwarfParser.d.ts +0 -0
  178. /package/dist/heap_analyzer/src/{tlsf.d.ts → tlsfBlockWalker.d.ts} +0 -0
@@ -9,6 +9,8 @@ import { DebuggerWasmModule } from "./debuggerWasmModule.js";
9
9
  const DIRNAME = path.dirname(fileURLToPath(import.meta.url));
10
10
  const DEBUG_SERVER_TRACE_ENABLED = process.env.WARPO_DEBUG_SERVER_TRACE === "1";
11
11
  const DEBUG_SERVER_TRACE_FILE = path.join(process.cwd(), ".warpo-debug-server-trace.log");
12
+ const LINEAR_MEMORY_OBJECT_GROUP = "warpo-linear-memory";
13
+ const NODE_WAITING_FOR_DEBUGGER_DISCONNECT = "Waiting for the debugger to disconnect...";
12
14
  if (DEBUG_SERVER_TRACE_ENABLED) {
13
15
  try {
14
16
  writeFileSync(DEBUG_SERVER_TRACE_FILE, "");
@@ -27,6 +29,25 @@ function trace(message) {
27
29
  }
28
30
  }
29
31
  }
32
+ const READ_WASM_MEMORY_FUNCTION = function (address, byteLength) {
33
+ const buffer = this instanceof ArrayBuffer || (typeof SharedArrayBuffer !== "undefined" && this instanceof SharedArrayBuffer)
34
+ ? this
35
+ : this.buffer;
36
+ if (!(buffer instanceof ArrayBuffer) &&
37
+ !(typeof SharedArrayBuffer !== "undefined" && buffer instanceof SharedArrayBuffer)) {
38
+ return;
39
+ }
40
+ if (address < 0 || byteLength < 0 || address + byteLength > buffer.byteLength) {
41
+ return;
42
+ }
43
+ return Array.from(new Uint8Array(buffer, address, byteLength));
44
+ }.toString();
45
+ const GET_WASM_MEMORY_BUFFER_FUNCTION = function () {
46
+ if (this instanceof ArrayBuffer || (typeof SharedArrayBuffer !== "undefined" && this instanceof SharedArrayBuffer)) {
47
+ return this;
48
+ }
49
+ return this.buffer;
50
+ }.toString();
30
51
  function findFreePort() {
31
52
  return new Promise((resolve, reject) => {
32
53
  const srv = net.createServer();
@@ -51,28 +72,97 @@ export class NodeDebugger {
51
72
  name = "node";
52
73
  onModuleLoad;
53
74
  onPause;
75
+ onRuntimeError;
76
+ onRuntimeExit;
77
+ onLog;
54
78
  child;
55
79
  ws;
56
80
  cdpId = 0;
57
81
  pendingCommandCallbacks = new Map();
58
82
  paused = false;
59
83
  wasmFilePath;
84
+ wasmScriptId;
85
+ pausedCallFrames = [];
86
+ wasmMemoryBufferObjectId;
87
+ wasmGlobalsObjectId;
88
+ stderrOutput = "";
89
+ disposed = false;
90
+ runtimeExitPromise;
91
+ log(message) {
92
+ trace(message);
93
+ this.onLog?.(`[${this.name}] ${message}`);
94
+ }
60
95
  async launch(config) {
96
+ this.disposed = false;
61
97
  this.wasmFilePath = config.wasmFilePath;
62
98
  const port = await findFreePort();
63
- this.child = spawn(process.execPath, [
64
- `--inspect=${port}`,
65
- path.join(DIRNAME, "wasmEntry.js"),
66
- config.wasmFilePath,
67
- config.entryFunctionName,
68
- ...config.args.map(String),
69
- ], { stdio: ["pipe", "pipe", "pipe"] });
99
+ this.log(`launch wasmFilePath=${config.wasmFilePath} inspectPort=${port}`);
100
+ const launchArgs = "cwd" in config
101
+ ? [`--inspect-brk=${port}`, config.warpoPath ?? path.join(DIRNAME, "..", "warpo.js"), "test"]
102
+ : [
103
+ `--inspect-brk=${port}`,
104
+ path.join(DIRNAME, "wasmEntry.js"),
105
+ config.wasmFilePath,
106
+ config.entryFunctionName,
107
+ ...config.args.map(String),
108
+ ];
109
+ this.child = spawn(process.execPath, launchArgs, {
110
+ cwd: "cwd" in config ? config.cwd : undefined,
111
+ env: getRuntimeEnv(),
112
+ stdio: ["pipe", "pipe", "pipe"],
113
+ });
114
+ this.log(`runtime child spawned pid=${this.child.pid ?? "unknown"}`);
115
+ this.runtimeExitPromise = new Promise((resolve) => {
116
+ this.child?.once("exit", () => resolve());
117
+ this.child?.once("error", () => resolve());
118
+ });
119
+ this.child.stdout?.on("data", (chunk) => {
120
+ const text = chunk.toString().trim();
121
+ if (text) {
122
+ this.log(`runtime stdout: ${text}`);
123
+ }
124
+ });
125
+ this.child.stderr?.on("data", (chunk) => {
126
+ const stderr = parseRuntimeStderr(chunk.toString());
127
+ this.stderrOutput += stderr.output;
128
+ const text = stderr.output.trim();
129
+ if (text) {
130
+ this.log(`runtime stderr: ${text}`);
131
+ }
132
+ if (stderr.waitingForDebuggerDisconnect) {
133
+ this.log("runtime waiting for debugger disconnect -> close websocket");
134
+ this.ws?.close();
135
+ }
136
+ });
137
+ this.child.on("error", (error) => {
138
+ this.log(`runtime child error: ${error.message}`);
139
+ this.onRuntimeError?.(error.message);
140
+ this.onRuntimeExit?.();
141
+ });
142
+ this.child.on("exit", (code, signal) => {
143
+ this.log(`runtime exit code=${code ?? "null"} signal=${signal ?? "null"}`);
144
+ if (this.disposed) {
145
+ return;
146
+ }
147
+ if (code && code !== 0) {
148
+ this.onRuntimeError?.(this.stderrOutput.trim() || `Debug runtime exited with code ${code}`);
149
+ }
150
+ this.onRuntimeExit?.();
151
+ });
70
152
  const wsUrl = await this.fetchWsUrl(port);
71
- await this.connectCDP(wsUrl);
153
+ this.log(`inspector websocket discovered: ${wsUrl}`);
154
+ await Promise.race([this.connectCDP(wsUrl), this.runtimeExitPromise]);
72
155
  }
73
156
  dispose() {
157
+ this.disposed = true;
74
158
  this.paused = false;
75
159
  this.wasmFilePath = undefined;
160
+ this.wasmScriptId = undefined;
161
+ this.pausedCallFrames = [];
162
+ this.wasmMemoryBufferObjectId = undefined;
163
+ this.wasmGlobalsObjectId = undefined;
164
+ this.stderrOutput = "";
165
+ this.runtimeExitPromise = undefined;
76
166
  this.ws?.close();
77
167
  this.child?.kill();
78
168
  }
@@ -85,28 +175,114 @@ export class NodeDebugger {
85
175
  async resume() {
86
176
  await this.waitForCommand("Debugger.resume");
87
177
  this.paused = false;
178
+ this.pausedCallFrames = [];
179
+ this.wasmMemoryBufferObjectId = undefined;
180
+ this.wasmGlobalsObjectId = undefined;
88
181
  }
89
182
  finishModuleLoad() {
183
+ this.log("finishModuleLoad -> Runtime.runIfWaitingForDebugger");
90
184
  this.sendCommand("Runtime.runIfWaitingForDebugger");
91
185
  }
92
- setWasmBreakpoint(module, bytecodeOffset, callbacks) {
93
- this.sendCommand("Debugger.setBreakpointByUrl", {
94
- url: module.url,
95
- lineNumber: 0,
96
- columnNumber: bytecodeOffset,
97
- }, {
98
- onSuccess: () => {
99
- trace(`setWasmBreakpoint success offset=${bytecodeOffset}`);
186
+ setWasmBreakpoint(module, wasmBytecodeOffset, callbacks) {
187
+ void (async () => {
188
+ try {
189
+ const location = this.resolveWasmBytecodeOffsetLocation(module, wasmBytecodeOffset);
190
+ this.log(`setWasmBreakpoint offset=${wasmBytecodeOffset} url=${module.url}`);
191
+ await this.waitForCommandResult("Debugger.setBreakpointByUrl", {
192
+ lineNumber: location.lineNumber,
193
+ url: module.url,
194
+ columnNumber: location.columnNumber,
195
+ condition: "",
196
+ });
197
+ this.log(`setWasmBreakpoint success offset=${wasmBytecodeOffset}`);
100
198
  callbacks?.onSuccess?.();
101
- },
102
- onError: (error) => {
103
- trace(`setWasmBreakpoint error offset=${bytecodeOffset} message=${error.message}`);
104
- callbacks?.onError?.(error);
105
- },
199
+ }
200
+ catch (error) {
201
+ const commandError = error instanceof Error ? error : new Error(String(error));
202
+ this.log(`setWasmBreakpoint error offset=${wasmBytecodeOffset} message=${commandError.message}`);
203
+ callbacks?.onError?.(commandError);
204
+ }
205
+ })();
206
+ }
207
+ resolveWasmBytecodeOffsetLocation(module, wasmBytecodeOffset) {
208
+ if (!module.url) {
209
+ throw new Error("Wasm script URL is not available");
210
+ }
211
+ return { scriptId: module.scriptId, lineNumber: 0, columnNumber: wasmBytecodeOffset };
212
+ }
213
+ resolveWasmLocationBytecodeOffset(location) {
214
+ if (location.lineNumber !== 0) {
215
+ return undefined;
216
+ }
217
+ return location.columnNumber;
218
+ }
219
+ getPausedWasmFrames() {
220
+ const frames = this.pausedCallFrames.map((callFrame) => this.toPausedWasmFrame(callFrame));
221
+ this.log(`getPausedWasmFrames count=${frames.length}`);
222
+ for (const [index, frame] of frames.entries()) {
223
+ this.log(` wasm frame ${index}: name=${frame.functionName}, offset=${frame.wasmBytecodeOffset ?? "unknown"}`);
224
+ }
225
+ return frames;
226
+ }
227
+ async getPausedWasmFrameVariables(frameIndex) {
228
+ const callFrame = this.pausedCallFrames[frameIndex];
229
+ if (!callFrame) {
230
+ this.log(`getPausedWasmFrameVariables frameIndex=${frameIndex} unavailable`);
231
+ return [];
232
+ }
233
+ const variables = await this.getLocalScopeVariables(callFrame);
234
+ this.log(`getPausedWasmFrameVariables frameIndex=${frameIndex} variables=${variables.length}`);
235
+ return variables;
236
+ }
237
+ async getPausedWasmGlobalVariables() {
238
+ const globalsObjectId = await this.getWasmGlobalsObjectId();
239
+ if (!globalsObjectId) {
240
+ return [];
241
+ }
242
+ const globalsResult = await this.waitForCommandResult("Runtime.getProperties", {
243
+ objectId: globalsObjectId,
244
+ ownProperties: true,
106
245
  });
246
+ const globals = Array.isArray(globalsResult.result) ? globalsResult.result.filter(isCDPPropertyDescriptor) : [];
247
+ const values = [];
248
+ for (const [globalIndex, global] of globals.entries()) {
249
+ if (!global.value) {
250
+ continue;
251
+ }
252
+ values.push({
253
+ globalIndex,
254
+ value: await this.readRemoteObjectValue(global.value),
255
+ type: global.value.description ?? global.value.type,
256
+ });
257
+ }
258
+ return values;
259
+ }
260
+ async readWasmMemory(address, byteLength) {
261
+ this.log(`readWasmMemory address=${address} byteLength=${byteLength}`);
262
+ const memoryBufferObjectId = await this.getWasmMemoryBufferObjectId();
263
+ if (!memoryBufferObjectId) {
264
+ this.log("readWasmMemory skipped: memory buffer unavailable");
265
+ return undefined;
266
+ }
267
+ this.log("readWasmMemory -> Runtime.callFunctionOn");
268
+ const result = await this.waitForCommandResult("Runtime.callFunctionOn", {
269
+ objectId: memoryBufferObjectId,
270
+ functionDeclaration: READ_WASM_MEMORY_FUNCTION,
271
+ arguments: [{ value: address }, { value: byteLength }],
272
+ silent: true,
273
+ returnByValue: true,
274
+ });
275
+ const remoteObject = getRuntimeEvaluateRemoteObject(result);
276
+ if (!Array.isArray(remoteObject?.value) || !remoteObject.value.every((value) => typeof value === "number")) {
277
+ this.log("readWasmMemory failed: runtime returned non-byte-array value");
278
+ return undefined;
279
+ }
280
+ this.log(`readWasmMemory success bytes=${remoteObject.value.length}`);
281
+ return Uint8Array.from(remoteObject.value);
107
282
  }
108
283
  async fetchWsUrl(port) {
109
284
  const deadline = Date.now() + 5000;
285
+ this.log(`waiting for inspector endpoint on port ${port}`);
110
286
  while (Date.now() < deadline) {
111
287
  try {
112
288
  const resp = await fetch(`http://127.0.0.1:${port}/json`);
@@ -115,10 +291,12 @@ export class NodeDebugger {
115
291
  }
116
292
  const [info] = (await resp.json());
117
293
  if (info?.webSocketDebuggerUrl) {
294
+ this.log(`inspector endpoint ready on port ${port}`);
118
295
  return info.webSocketDebuggerUrl;
119
296
  }
120
297
  }
121
- catch {
298
+ catch (error) {
299
+ trace(`inspector endpoint not ready: ${error instanceof Error ? error.message : "unknown error"}`);
122
300
  // The inspector endpoint is not always ready immediately after spawn.
123
301
  }
124
302
  await wait(50);
@@ -133,15 +311,33 @@ export class NodeDebugger {
133
311
  if (callbacks) {
134
312
  this.pendingCommandCallbacks.set(id, callbacks);
135
313
  }
314
+ this.log(`CDP -> ${method} id=${id}`);
136
315
  this.ws.send(JSON.stringify({ id, method, params }));
316
+ return id;
137
317
  }
138
318
  waitForCommand(method, params) {
139
319
  return new Promise((resolve, reject) => {
140
- this.sendCommand(method, params, {
320
+ const id = this.sendCommand(method, params, {
141
321
  onSuccess: () => {
322
+ this.log(`CDP command completed ${method} id=${id}`);
142
323
  resolve();
143
324
  },
144
325
  onError: (error) => {
326
+ this.log(`CDP command failed ${method} id=${id}: ${error.message}`);
327
+ reject(error);
328
+ },
329
+ });
330
+ });
331
+ }
332
+ waitForCommandResult(method, params) {
333
+ return new Promise((resolve, reject) => {
334
+ const id = this.sendCommand(method, params, {
335
+ onSuccess: (result) => {
336
+ this.log(`CDP command completed ${method} id=${id}`);
337
+ resolve(result ?? {});
338
+ },
339
+ onError: (error) => {
340
+ this.log(`CDP command failed ${method} id=${id}: ${error.message}`);
145
341
  reject(error);
146
342
  },
147
343
  });
@@ -154,60 +350,143 @@ export class NodeDebugger {
154
350
  ws.addEventListener("open", () => {
155
351
  void (async () => {
156
352
  try {
157
- trace("ws open -> Debugger.enable");
353
+ this.log("websocket open -> Runtime.enable");
354
+ await this.waitForCommand("Runtime.enable");
355
+ this.log("Runtime.enable complete -> Debugger.enable");
158
356
  await this.waitForCommand("Debugger.enable");
159
- trace("Debugger.enable -> Debugger.setBreakpointsActive");
160
- await this.waitForCommand("Debugger.setBreakpointsActive", { active: true });
161
- trace("Debugger.setBreakpointsActive -> Runtime.runIfWaitingForDebugger");
357
+ this.log("Debugger.enable complete -> Runtime.runIfWaitingForDebugger");
162
358
  await this.waitForCommand("Runtime.runIfWaitingForDebugger");
163
- trace("Runtime.runIfWaitingForDebugger -> launch ready");
359
+ this.log("Runtime.runIfWaitingForDebugger complete -> Debugger.setBreakpointsActive");
360
+ await this.waitForCommand("Debugger.setBreakpointsActive", { active: true });
361
+ this.log("Debugger.setBreakpointsActive complete -> Debugger.setPauseOnExceptions");
362
+ await this.waitForCommand("Debugger.setPauseOnExceptions", { state: "all" });
363
+ this.log("Debugger.setPauseOnExceptions complete -> launch ready");
164
364
  resolve();
165
365
  }
166
366
  catch (error) {
367
+ this.log(`CDP setup failed: ${error instanceof Error ? error.message : "unknown error"}`);
167
368
  reject(error instanceof Error ? error : new Error(String(error)));
168
369
  }
169
370
  })();
170
371
  });
171
372
  ws.addEventListener("error", (e) => {
172
373
  const message = e instanceof Error ? e.message : "WebSocket connection failed";
374
+ this.log(`websocket error: ${message}`);
173
375
  reject(new Error(message));
174
376
  });
377
+ ws.addEventListener("close", (event) => {
378
+ this.log(`websocket close code=${event.code} reason=${event.reason || ""}`);
379
+ });
175
380
  ws.addEventListener("message", (ev) => {
176
381
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
177
382
  const msg = JSON.parse(String(ev.data));
178
- if (typeof msg.id === "number") {
179
- this.handleCommandResponse(msg.id, msg);
180
- return;
181
- }
182
- if (msg.method === "Debugger.paused") {
183
- const reason = this.getPauseReason(msg.params);
184
- this.paused = true;
185
- trace(`Debugger.paused reason=${reason}`);
186
- void Promise.resolve(this.onPause?.({ reason })).catch((error) => {
187
- trace(`pause handler failed: ${error instanceof Error ? error.message : "unknown error"}`);
188
- });
189
- return;
190
- }
191
- if (msg.method === "Debugger.scriptParsed") {
192
- const params = msg.params;
193
- const lang = typeof params?.scriptLanguage === "string" ? params.scriptLanguage : "unknown";
194
- const url = typeof params?.url === "string" ? params.url : "";
195
- trace(`Debugger.scriptParsed language=${lang} url=${url}`);
196
- if (params && lang === "WebAssembly" && typeof params.scriptId === "string") {
197
- trace(`wasm module detected scriptId=${params.scriptId}`);
198
- void this.handleModuleLoad({
199
- scriptId: params.scriptId,
200
- url,
201
- }).catch((error) => {
202
- const message = error instanceof Error ? error.message : "unknown error";
203
- trace(`module load handler failed: ${message}`);
204
- process.stderr.write(`[node-debugger] module load handler failed: ${message}\n`);
205
- });
206
- }
207
- }
383
+ this.handleCdpMessage(msg);
208
384
  });
209
385
  });
210
386
  }
387
+ handleCdpMessage(msg) {
388
+ if (typeof msg.id === "number") {
389
+ this.handleCommandResponse(msg.id, msg);
390
+ return;
391
+ }
392
+ if (msg.method === "Debugger.paused") {
393
+ this.handleDebuggerPaused(msg.params);
394
+ return;
395
+ }
396
+ if (msg.method === "Debugger.scriptParsed") {
397
+ this.handleScriptParsed(msg.params);
398
+ }
399
+ }
400
+ handleDebuggerPaused(params) {
401
+ const reason = this.getPauseReason(params);
402
+ this.pausedCallFrames = this.getPausedWasmCallFrames(params);
403
+ this.wasmMemoryBufferObjectId = undefined;
404
+ this.wasmGlobalsObjectId = undefined;
405
+ if (reason === "Break on start" && !this.wasmScriptId) {
406
+ this.log("Debugger.paused reason=Break on start location=inspect-brk startup");
407
+ void this.resumeInternalStartupPause();
408
+ return;
409
+ }
410
+ if (reason === "other" && this.wasmScriptId) {
411
+ this.log("Debugger.paused reason=other location=wasm pre-entry gate");
412
+ return;
413
+ }
414
+ const isExceptionPause = reason === "exception" || reason === "promiseRejection";
415
+ // CDP can only pause on exceptions for the whole Node process, not for a specific wasm module. We need
416
+ // "all" because the JavaScript wrapper can catch a wasm trap, but that also pauses for unrelated JavaScript
417
+ // exceptions. Treat the top frame belonging to our wasm module as the filter for a debugger-visible trap.
418
+ if (isExceptionPause && !this.isTopFrameWasm(params)) {
419
+ this.log(`Debugger.paused reason=${reason} outside wasm -> resume`);
420
+ void this.resumeIgnoredPause();
421
+ return;
422
+ }
423
+ const isWasmTrap = isExceptionPause;
424
+ if (isWasmTrap) {
425
+ this.paused = true;
426
+ this.log(`Debugger.paused reason=${reason} (wasm trap)`);
427
+ void this.notifyPause("exception");
428
+ return;
429
+ }
430
+ this.paused = true;
431
+ this.log(`Debugger.paused reason=${reason}`);
432
+ void this.notifyPause(reason);
433
+ }
434
+ async notifyPause(reason) {
435
+ try {
436
+ const pausedCallFrame = this.pausedCallFrames[0];
437
+ const wasmBytecodeOffset = pausedCallFrame
438
+ ? this.resolveWasmLocationBytecodeOffset(pausedCallFrame.location)
439
+ : undefined;
440
+ await this.onPause?.({ reason, wasmBytecodeOffset });
441
+ }
442
+ catch (error) {
443
+ this.log(`pause handler failed: ${error instanceof Error ? error.message : "unknown error"}`);
444
+ }
445
+ }
446
+ handleScriptParsed(params) {
447
+ const lang = typeof params?.scriptLanguage === "string" ? params.scriptLanguage : "unknown";
448
+ const url = typeof params?.url === "string" ? params.url : "";
449
+ this.log(`Debugger.scriptParsed language=${lang} url=${url}`);
450
+ if (!params || lang !== "WebAssembly" || typeof params.scriptId !== "string") {
451
+ return;
452
+ }
453
+ if (!this.isExpectedWasmModule(params)) {
454
+ this.log(`ignoring non-target wasm module scriptId=${params.scriptId} url=${url}`);
455
+ return;
456
+ }
457
+ this.wasmScriptId = params.scriptId;
458
+ this.log(`wasm module detected scriptId=${params.scriptId}`);
459
+ void this.handleModuleLoad({
460
+ scriptId: params.scriptId,
461
+ url,
462
+ }).catch((error) => {
463
+ const message = error instanceof Error ? error.message : "unknown error";
464
+ this.log(`module load handler failed: ${message}`);
465
+ process.stderr.write(`Module load handler failed: ${message}\n`);
466
+ });
467
+ }
468
+ isExpectedWasmModule(params) {
469
+ if (!this.wasmFilePath) {
470
+ return false;
471
+ }
472
+ return params.sourceMapURL === `${path.basename(this.wasmFilePath)}.map`;
473
+ }
474
+ async resumeInternalStartupPause() {
475
+ await this.resumeIgnoredPause("inspect-brk startup pause");
476
+ }
477
+ async resumeIgnoredPause(description = "non-wasm exception pause") {
478
+ try {
479
+ await this.waitForCommand("Debugger.resume");
480
+ this.paused = false;
481
+ this.pausedCallFrames = [];
482
+ this.wasmMemoryBufferObjectId = undefined;
483
+ this.wasmGlobalsObjectId = undefined;
484
+ this.log(`${description} resumed`);
485
+ }
486
+ catch (error) {
487
+ this.log(`failed to resume ${description}: ${error instanceof Error ? error.message : "unknown error"}`);
488
+ }
489
+ }
211
490
  handleCommandResponse(id, msg) {
212
491
  const callbacks = this.pendingCommandCallbacks.get(id);
213
492
  if (!callbacks) {
@@ -215,10 +494,12 @@ export class NodeDebugger {
215
494
  }
216
495
  this.pendingCommandCallbacks.delete(id);
217
496
  if (msg.error) {
497
+ this.log(`CDP <- error id=${id} message=${msg.error.message ?? "CDP command failed"}`);
218
498
  callbacks.onError?.(new Error(msg.error.message ?? "CDP command failed"));
219
499
  return;
220
500
  }
221
- callbacks.onSuccess?.();
501
+ this.log(`CDP <- success id=${id}`);
502
+ callbacks.onSuccess?.(msg.result);
222
503
  }
223
504
  getPauseReason(params) {
224
505
  if (Array.isArray(params?.hitBreakpoints) && params.hitBreakpoints.length > 0) {
@@ -229,12 +510,262 @@ export class NodeDebugger {
229
510
  }
230
511
  return "unknown";
231
512
  }
513
+ getPausedWasmCallFrames(params) {
514
+ if (!Array.isArray(params?.callFrames)) {
515
+ return [];
516
+ }
517
+ const callFrames = params.callFrames.filter(isCDPCallFrame);
518
+ if (!this.wasmScriptId) {
519
+ this.log(`getPausedWasmCallFrames skipped ${callFrames.length} non-wasm startup frames before wasm script load`);
520
+ return [];
521
+ }
522
+ const wasmCallFrames = callFrames.filter((callFrame) => callFrame.location.scriptId === this.wasmScriptId);
523
+ this.log(`getPausedWasmCallFrames total=${callFrames.length} wasm=${wasmCallFrames.length}`);
524
+ return wasmCallFrames;
525
+ }
526
+ isTopFrameWasm(params) {
527
+ if (!Array.isArray(params?.callFrames) || !this.wasmScriptId) {
528
+ return false;
529
+ }
530
+ const topCallFrame = params.callFrames.find(isCDPCallFrame);
531
+ return topCallFrame?.location.scriptId === this.wasmScriptId;
532
+ }
533
+ toPausedWasmFrame(callFrame) {
534
+ return {
535
+ functionName: callFrame.functionName,
536
+ wasmBytecodeOffset: this.resolveWasmLocationBytecodeOffset(callFrame.location),
537
+ };
538
+ }
539
+ async getLocalScopeVariables(callFrame) {
540
+ const localScope = callFrame.scopeChain.find((scope) => scope.type === "local") ?? callFrame.scopeChain[0];
541
+ const objectId = localScope?.object.objectId;
542
+ if (!objectId) {
543
+ return [];
544
+ }
545
+ const result = await this.waitForCommandResult("Runtime.getProperties", {
546
+ objectId,
547
+ ownProperties: true,
548
+ });
549
+ const properties = Array.isArray(result.result) ? result.result.filter(isCDPPropertyDescriptor) : [];
550
+ const variables = [];
551
+ for (const property of properties) {
552
+ if (!property.value) {
553
+ continue;
554
+ }
555
+ const localIndex = variables.length;
556
+ variables.push({
557
+ name: `local${localIndex}`,
558
+ value: await this.readRemoteObjectValue(property.value),
559
+ type: property.value.description ?? property.value.type,
560
+ localIndex,
561
+ });
562
+ }
563
+ return variables;
564
+ }
565
+ async getWasmMemoryBufferObjectId() {
566
+ if (this.wasmMemoryBufferObjectId) {
567
+ return this.wasmMemoryBufferObjectId;
568
+ }
569
+ this.log("getWasmMemoryBufferObjectId -> getWasmMemoryObjectId");
570
+ const memoryObjectId = await this.getWasmMemoryObjectId();
571
+ if (!memoryObjectId) {
572
+ this.log("getWasmMemoryBufferObjectId failed: memory object unavailable");
573
+ return undefined;
574
+ }
575
+ this.log("getWasmMemoryBufferObjectId -> Runtime.callFunctionOn buffer");
576
+ const bufferResult = await this.waitForCommandResult("Runtime.callFunctionOn", {
577
+ objectId: memoryObjectId,
578
+ functionDeclaration: GET_WASM_MEMORY_BUFFER_FUNCTION,
579
+ silent: true,
580
+ objectGroup: LINEAR_MEMORY_OBJECT_GROUP,
581
+ });
582
+ const bufferObject = getRuntimeEvaluateRemoteObject(bufferResult);
583
+ this.wasmMemoryBufferObjectId = bufferObject?.objectId;
584
+ this.log(`getWasmMemoryBufferObjectId result=${this.wasmMemoryBufferObjectId ?? "undefined"}`);
585
+ return this.wasmMemoryBufferObjectId;
586
+ }
587
+ async getWasmMemoryObjectId() {
588
+ const moduleScope = this.pausedCallFrames[0]?.scopeChain.find((scope) => scope.type === "module");
589
+ const objectId = moduleScope?.object.objectId;
590
+ if (!objectId) {
591
+ return undefined;
592
+ }
593
+ this.log("getWasmMemoryObjectId -> Runtime.getProperties module scope");
594
+ const result = await this.waitForCommandResult("Runtime.getProperties", {
595
+ objectId,
596
+ ownProperties: false,
597
+ });
598
+ const properties = Array.isArray(result.result) ? result.result.filter(isCDPPropertyDescriptor) : [];
599
+ const memoriesProperty = properties.find((property) => property.name === "memories" && property.value?.objectId);
600
+ if (!memoriesProperty?.value?.objectId) {
601
+ return undefined;
602
+ }
603
+ this.log("getWasmMemoryObjectId -> Runtime.getProperties memories");
604
+ const memoriesResult = await this.waitForCommandResult("Runtime.getProperties", {
605
+ objectId: memoriesProperty.value.objectId,
606
+ ownProperties: false,
607
+ });
608
+ const memories = Array.isArray(memoriesResult.result) ? memoriesResult.result.filter(isCDPPropertyDescriptor) : [];
609
+ const nestedMemory = memories.find((property) => property.value && isWasmMemoryObject(property.value));
610
+ this.log(`getWasmMemoryObjectId result=${nestedMemory?.value?.objectId ?? "undefined"}`);
611
+ return nestedMemory?.value?.objectId;
612
+ }
613
+ async getWasmGlobalsObjectId() {
614
+ if (this.wasmGlobalsObjectId) {
615
+ return this.wasmGlobalsObjectId;
616
+ }
617
+ const moduleScope = this.pausedCallFrames[0]?.scopeChain.find((scope) => scope.type === "module");
618
+ const moduleObjectId = moduleScope?.object.objectId;
619
+ if (!moduleObjectId) {
620
+ return undefined;
621
+ }
622
+ const moduleResult = await this.waitForCommandResult("Runtime.getProperties", {
623
+ objectId: moduleObjectId,
624
+ ownProperties: false,
625
+ });
626
+ const moduleProperties = Array.isArray(moduleResult.result)
627
+ ? moduleResult.result.filter(isCDPPropertyDescriptor)
628
+ : [];
629
+ this.wasmGlobalsObjectId = moduleProperties.find((property) => property.name === "globals")?.value?.objectId;
630
+ return this.wasmGlobalsObjectId;
631
+ }
632
+ async readRemoteObjectValue(value) {
633
+ if (value.subtype !== "wasmvalue" || !value.objectId) {
634
+ return formatRemoteObject(value);
635
+ }
636
+ const result = await this.waitForCommandResult("Runtime.getProperties", {
637
+ objectId: value.objectId,
638
+ ownProperties: true,
639
+ });
640
+ const innerProperties = Array.isArray(result.result) ? result.result.filter(isCDPPropertyDescriptor) : [];
641
+ const valueProperty = innerProperties.find((property) => property.name === "value" || property.name === "0");
642
+ return valueProperty?.value ? formatRemoteObject(valueProperty.value) : formatRemoteObject(value);
643
+ }
232
644
  async handleModuleLoad(runtimeInfo) {
645
+ if (this.hasRuntimeExited()) {
646
+ this.log("skip wasm module load because runtime already exited");
647
+ return;
648
+ }
233
649
  if (!this.wasmFilePath) {
234
650
  throw new Error("wasm file path is not available");
235
651
  }
652
+ this.log(`loading wasm debug metadata from ${this.wasmFilePath}`);
236
653
  const module = await DebuggerWasmModule.load(this.wasmFilePath, runtimeInfo);
654
+ this.log(`wasm debug metadata loaded from ${module.sourceMapFilePath}`);
237
655
  void this.onModuleLoad?.(module);
238
656
  }
657
+ hasRuntimeExited() {
658
+ return this.child !== undefined && (this.child.exitCode !== null || this.child.signalCode !== null);
659
+ }
660
+ }
661
+ function parseRuntimeStderr(text) {
662
+ let waitingForDebuggerDisconnect = false;
663
+ const output = text
664
+ .split(/(?<=\n)/)
665
+ .filter((line) => {
666
+ const trimmed = line.trim();
667
+ if (trimmed === NODE_WAITING_FOR_DEBUGGER_DISCONNECT) {
668
+ waitingForDebuggerDisconnect = true;
669
+ return false;
670
+ }
671
+ return (trimmed !== "" &&
672
+ !trimmed.startsWith("Debugger listening on") &&
673
+ !trimmed.startsWith("For help, see:") &&
674
+ trimmed !== "Debugger attached.");
675
+ })
676
+ .join("");
677
+ return { output, waitingForDebuggerDisconnect };
678
+ }
679
+ function getRuntimeEnv() {
680
+ const env = { ...process.env };
681
+ delete env.VSCODE_INSPECTOR_OPTIONS;
682
+ const nodeOptions = filterAutoAttachNodeOptions(env.NODE_OPTIONS);
683
+ if (nodeOptions) {
684
+ env.NODE_OPTIONS = nodeOptions;
685
+ }
686
+ else {
687
+ delete env.NODE_OPTIONS;
688
+ }
689
+ return env;
690
+ }
691
+ function filterAutoAttachNodeOptions(nodeOptions) {
692
+ if (!nodeOptions) {
693
+ return "";
694
+ }
695
+ const parts = nodeOptions.split(/\s+/).filter(Boolean);
696
+ const filtered = [];
697
+ for (let i = 0; i < parts.length; i++) {
698
+ const part = parts[i];
699
+ const next = parts[i + 1];
700
+ if ((part === "--require" || part === "-r") && next && isVsCodeJsDebugBootloader(next)) {
701
+ i++;
702
+ continue;
703
+ }
704
+ if ((part.startsWith("--require=") || part.startsWith("-r=")) && isVsCodeJsDebugBootloader(part)) {
705
+ continue;
706
+ }
707
+ filtered.push(part);
708
+ }
709
+ return filtered.join(" ");
710
+ }
711
+ function isVsCodeJsDebugBootloader(value) {
712
+ return value.includes("js-debug") || value.includes("vscode-js-debug");
713
+ }
714
+ function isCDPPropertyDescriptor(value) {
715
+ if (!value || typeof value !== "object") {
716
+ return false;
717
+ }
718
+ return typeof value.name === "string";
719
+ }
720
+ function isCDPCallFrame(value) {
721
+ if (typeof value !== "object" || value === null) {
722
+ return false;
723
+ }
724
+ const callFrame = value;
725
+ return (typeof callFrame.callFrameId === "string" &&
726
+ typeof callFrame.functionName === "string" &&
727
+ isCDPLocation(callFrame.location) &&
728
+ Array.isArray(callFrame.scopeChain));
729
+ }
730
+ function isCDPLocation(value) {
731
+ if (typeof value !== "object" || value === null) {
732
+ return false;
733
+ }
734
+ const location = value;
735
+ return (typeof location.scriptId === "string" &&
736
+ typeof location.lineNumber === "number" &&
737
+ typeof location.columnNumber === "number");
738
+ }
739
+ function isWasmMemoryObject(value) {
740
+ return value.objectId !== undefined && value.subtype === "webassemblymemory";
741
+ }
742
+ function getRuntimeEvaluateRemoteObject(result) {
743
+ const remoteObject = result.result;
744
+ if (!remoteObject || typeof remoteObject !== "object") {
745
+ return undefined;
746
+ }
747
+ return remoteObject;
748
+ }
749
+ function formatRemoteObject(value) {
750
+ if (value.unserializableValue !== undefined) {
751
+ return value.unserializableValue;
752
+ }
753
+ const rawValue = value.value;
754
+ if (rawValue !== undefined) {
755
+ if (rawValue === null) {
756
+ return "null";
757
+ }
758
+ if (typeof rawValue === "object") {
759
+ return value.description ?? value.type ?? "<unavailable>";
760
+ }
761
+ if (typeof rawValue === "string") {
762
+ return rawValue;
763
+ }
764
+ if (typeof rawValue === "number" || typeof rawValue === "boolean" || typeof rawValue === "bigint") {
765
+ return rawValue.toString();
766
+ }
767
+ return value.description ?? value.type ?? "<unavailable>";
768
+ }
769
+ return value.description ?? value.type ?? "<unavailable>";
239
770
  }
240
771
  //# sourceMappingURL=nodeDebugger.js.map