blob: 813b9da1215a90d5282abf3faa9e639f724ee66f [file] [log] [blame] [view]
Benedikt Meurere8783db2024-08-21 12:16:031# Chromium DevTools support checklist for JavaScript language features
2
3[goo.gle/v8-checklist](https://goo.gle/v8-checklist)
4
5Implementation for new language features (NLF) are often intrusive and affect many parts of
6[V8](https://v8.dev). This sometimes causes the debugger to not work seamlessly with the NLF
7out of the box. We generally make the distinction between _Basic functionality_ and _Extended
8functionality_ when talking about debugger support:
9
10- Basic functionality is required for every NLF in order to launch. The debugger must not crash
11 or act in a confusing way when interacting with the NLF. For example, stepping into a `Proxy`
12 trap handler should be possible.
13- Extended functionality is often just nice-to-have, but in some cases required for launch.
14 This includes debugging capabilities specific to the language feature. For example, catch
15 prediction should work as expected for `Promise`s.
16
17This document attempts to list all relevant aspects of V8s JavaScript debugger that constitute
18basic functionality (checkout [this document](https://goo.gle/devtools-wasm-checklist) for V8's
19WebAssembly debugger features). Items on the list may not apply to every language feature,
20depending on its nature.
21
Benedikt Meurer4385a562024-08-21 13:19:5222*** note
23**IMPORTANT:** Please take a look at the [DevTools UI feature checklist](./ui.md) prior
24to changing or extending the DevTools user interface (UI).
25***
26
Benedikt Meurere8783db2024-08-21 12:16:0327[TOC]
28
29## Console printing
30
31DevTools offers a REPL through the Console panel. Logging a value should print reasonable output.
32
33### Affected
34
35All NLFs that affect how values should be printed in a REPL, such as NLFs that introduce new primitives, new `RegExp` flags, etc.
36
37### How to test
38
39Open DevTools, select the Console panel, and enter a source snippet with the NLF. The printed result should look alright.
40
41### Reading material
42
43[Example CL that adds printing support for a new `RegExp` flag](https://chromium-review.googlesource.com/c/v8/v8/+/2848460)
44
45
46## Syntax highlighting and pretty-printing
47
48DevTools provides syntax highlighting and pretty-printing for JavaScript sources.
49
50### Affected
51
52All NLFs that introduce new syntax.
53
54### How to test
55
56Open DevTools, select the Sources panel, and create a new source snippet with the NLF. The syntax highlighting of the source
57should look alright. This is handled by [CodeMirror](https://codemirror.net/) inside of Chromium DevTools.
58
59Clicking on the pretty-printing button on the bottom left ("{}") should yield reasonable results. The formatting relies on the
60[acorn](https://github.com/acornjs/acorn) parser, which needs to support the NLF in question for this to work.
61
62
63## Stack traces
64
65Stack traces is the most often used way for developers to debug issues. Aside from the default `Error.stack` string, we also
66offer a way for user code to override how to format the `stack` property, and collect a more detailed structured stack trace
67for DevTools.
68
69Sometimes, due to the way a feature is implemented, there may be stack frames that show up on the stack trace when they should
70not, or vice versa.
71
72For runtime exceptions, we look for the closest code position that has a source position attached. That source position is used
73as expression position for the exception. For syntax errors, we should report the correct location of the syntax error via
74[`MessageHandler::ReportMessage()`](https://source.chromium.org/chromium/chromium/src/+/main:v8/src/execution/messages.h;l=174-176;drc=4e40b002b46c019d18eae68b5e5a342605609d95).
75
76Note that `Error.stack` is only collected for `Error` objects, at the time the `Error` object is constructed. This may be different
77than the stack trace passed to DevTools via [`JSMessageObject`](https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-objects.h;l=1264-1345;drc=82dff63dbf9db05e9274e11d9128af7b9f51ceaa).
78
Benedikt Meurere8783db2024-08-21 12:16:0379### Affected
80
81NLFs that can cause an exception to be thrown, or can call into another function that throws.
82
83### How to test
84
85When throwing inside the NLF, or with it on the stack, the stack trace including source positions should make sense. Also check
86the structured stack trace when the exception is not caught and logged into Chrome's DevTools console.
87
88Repeat with the "Disable async stack traces" checkbox in the Preferences checked.
89
90### Test cases
91
92Test cases for stack traces is mandatory, if there is any way the NLF can interact with throwing exceptions. For examples look
93for `mjsunit` tests with `stack-trace` in their names.
94
Benedikt Meurere8783db2024-08-21 12:16:0395### Reading material
96
97[Design doc for debugging support for tail-calls](https://docs.google.com/a/google.com/document/d/1Bk4QahtaT-XzrMlHTkm0SVol3LoKXTrC9E7INxJBHrE/edit?usp=drive\_web)
98
Simon Zünd5cfe4e72024-10-22 07:36:5099## Async stack traces
100
101DevTools offers a way to show async stack traces by stitching together stack traces collected at the
102location where the callback is passed, and the actual location of the exception inside the callback.
103
104The canonical example of this is throwing inside a `setTimeout` callback. The async stack trace will
105consist of the stack trace of the error plus a stack trace captured at the `setTimeout` call-site.
106
107The instrumentation is based on four [`ayncTask*` methods](https://source.chromium.org/chromium/chromium/src/+/main:v8/include/v8-inspector.h;l=370-375;drc=aafd25ffbc72935b52fee731f957e5827c73a096). Namely `asyncTaskScheduled`, `asyncTaskStarted`, `asyncTaskFinished` and `asyncTaskCancelled`.
108V8 has a [higher-level interface](https://source.chromium.org/chromium/chromium/src/+/main:v8/src/debug/debug-interface.h;l=351-352;drc=e6fc2038d73ef96ff47deda3146d94d25530e13b) that translates Promise events (such as `await`, `.then`, etc) to these for `asyncTask*` methods.
109
110### Affected
111
112NLFs touching promises or callback scheduling.
113
114### How to test
115
116Throw or pause inside a new language feature and check either the call stack sidebar panel in "Sources"
117or use a `console.trace` and check the async stack trace in the console.
118
119### Test cases
120
121Test cases for async stack traces are mandatory, if there is any way the NLF interacts with callback scheduling or
122Promises. For examples look in V8 `inspector` tests with `async-stack` in their name (e.g. [here](https://source.chromium.org/chromium/chromium/src/+/main:v8/test/inspector/debugger/async-stack-await.js)).
Benedikt Meurere8783db2024-08-21 12:16:03123
124## Catch prediction
125
126Aside from offering stack traces, V8's debugger supports DevTools' pause-on-exception feature. This comes in two flavors:
127pause on all exceptions, and pause on uncaught exceptions. In both cases, we break at the throw site (not at the `catch`,
128or any rethrow via `try`-`finally`).
129
130For the former, this is as easy as breaking in the debugger on `Isolate::Throw()`. For the latter, we have to predict whether
131the thrown exception will be caught or otherwise handled (for example by a `Promise`'s catch handler).
132
133### Affected
134
135NLFs that can cause an exception to be thrown, or can call into another function that throws.
136
137### How to test
138
139When pause-on-exception is enabled, and throwing inside the NLF or with it on the stack, the script should pause as expected.
140
141Repeat with the "pause on caught exception" checkbox checked.
142
143### Test cases
144
145Test cases for exception prediction is mandatory, if there is any way the NLF can interact with exceptions, be it by throwing
146exceptions, or by relying on `try`-`catch` or `try`-`finally` in its implementation. Look for `mjsunit` tests that contain the
147string `setBreakOnException` or `setBreakOnUncaughtException`.
148
149### Reading material
150
151[Design doc for exception prediction for async-await](https://docs.google.com/a/google.com/document/d/1ef1drN6RTRN7iDB8FXJg\_JJZFNObCFbM1UjZWK\_ORUE/edit?usp=drive\_web)
152
153
154## Breakpoints
155
156One of the most important features is setting break points. The semantics should be obvious.
157
158Break locations are function calls, return sites, and statements. Special care are necessary for loops: for example, in `for`-loops
159we do want to be able to break separately at the loop entry, condition evaluation, and increment.
160
161When setting a break point at an arbitrary source position, we actually check for the closest breakable source position, and move
162the break point there. Consecutive debug break events at the same source position are ignored by the debugger.
163
164### Affected
165
166NLFs that change generated code, and especially once that introduce new break locations.
167
168### How to test
169
170Open DevTools and set break points in parts of script related to the NLF, then run the script.
171
172### Test cases
173
174Look for `mjsunit` tests with `debug-break` in their names.
175
176
177## Stepping
178
179Stepping is the logical consequence to breakpoints, and is based on the same mechanism in the debugger. We differentiate between
180
181* Step out, which takes us to the next break location in the caller.
182* Step next, which takes us to the next break location while ignoring calls into other functions. Note that this includes recursive
183 calls. Step next at a return site is equivalent to a step out.
184* Step in, which takes us to the next break location including calls into another function.
185* Step frame, which takes us to another function, either a callee or a caller. This is used for framework blackboxing, where the V8
186 inspector is not interested in stepping in the current function, and wants to be notified once we arrive at another function
187
188### Affected
189
190NLFs that are affect breakpoints
191
192### How to test
193
194Break inside the part of script related to the NLF, and try stepping in, next, and out.
195
196### Test cases
197
198Look for `mjsunit` tests with `debug-step` in their names.
199
200### Reading material
201
202[Design doc on stepping in async-await](https://docs.google.com/a/google.com/document/d/1nj3nMlQVEFlq57dA-K8wFxdOB5ovvNuwNbWxBhcBOKE/edit?usp=drive\_web)
203
204
205## Frame inspector
206
207The frame inspector in V8 offers a way to a way to introspect frames on the call stack at the debug break. For the top-most frame,
208the break location is that of the debug break. For frames below the break location is the call site leading to the frame above.
209
210For each frame, we can
211
212- inspect the scope chain at the break location with the scope iterator,
213- find out whether it's called as constructor,
214- find out whether we are at a return position,
215- get the function being called,
216- get the receiver,
217- get the arguments, and
218- get the number of stack-allocated locals.
219
220For optimized code, we use the deoptimizer to get hold of receiver, arguments and stack locals, but this is often not possible, and we
221get the `optimzed_out` sentinel value.
222
223### Affected
224
225NLFs that affect the way V8 calls functions.
226
227### How to test
228
229When paused inside the function affected by the NLF, the Call Stack view in the DevTools' Source panel should show useful information.
230
231### Test cases
232
233Take a look at `test/mjsunit/wasm/frame-inspection.js`.
234
235
236## Scope iterator
237
238The scope iterator in V8 offers a way to introspect the scope chain at the break location. It includes not only the scopes outside of
239the current function, but also scopes inside it, for example inner block scopes, catch scopes, with scopes, etc.
240
241For each scope inside the current function, we can materialize an object representing local variables belonging to it. For scopes
242outside the current function this is not possible.
243
244We can use the scope iterator to alter the value of local variables, unless we are inside an optimized frame.
245
246### Affected
247
248NLFs that introduce new scopes.
249
250### How to test
251
252When paused in DevTools inside the scope introduced by the NLF, the "Scope" view on the Sources panel should show useful information.
253Scopes that are introduced by the NLF for desugaring purposes may better be hidden.
254
255### Test cases
256
257Take a look at `test/mjsunit/debug-scopes.js`.
258
259### Reading material
260
261[CL that introduces hidden scopes](https://chromium.googlesource.com/v8/v8/+/672983830f36222d90748ff588831b6dae565c38)
262
263
264## Debug evaluate
265
266With debug-evaluate, V8 offers a way to evaluate scripts at a break, attempting to behave as if the script code was executed
267right at the break location. It is based on the frame inspector and the scope iterator.
268
269It works by creating a context chain that not only references contexts on the current context chain, but also contains the
270materialized stack, including arguments object and the receiver. The script is then compiled and executed inside this context chain.
271
272There are some limitations, and special attention has to be paid to variable name shadowing.
273
274Side-effect-free debug-evaluate statically determines whether a function should throw. You should check whether to update the
275whitelist in `src/debug/debug-evaluate.cc`.
276
277### Affected
278
279NLFs that are also affected by the scope iterator and frame inspector.
280
281### How to test
282
283Use the DevTools console to run scripts at a debug break. In particular the preview shown in the DevTools console by default indicates
284whether the side-effect detection works correctly (i.e. whether you updated the whitelist correctly).
285
286### Test cases
287
288Look for mjsunit tests with "debug-evaluate" in their names.
289
290### Reading material
291
292This [tea-and-crumpets](https://drive.google.com/file/d/0BwPS\_JpKyELWTXV4NGZzS085NVE/view) [presentation](https://docs.google.com/a/google.com/presentation/d/18-c04ri-Whcp1dbteVTqLtK2wqlUzFgfU4kp8KgyF3I/edit?usp=drive\_web)
293
294Debug-evaluate without side effect [doc](https://docs.google.com/document/d/1l\_JzDbOZ6Cn1k0c5vnyEXHe7B2Xxm7lROs1vYR3nR2I/edit) and [presentation](https://docs.google.com/presentation/d/1u9lDBPMRo-mSQ6mmO03ZmpIiQ-haKyd9O4aFF0nomWs/edit)
295
296
297## Code Coverage
298
299Code coverage gathers execution counts and exposes them to developers through the Inspector protocol.
300
301### Affected
302
303NLFs that contain control flow (e.g branches, loops, etc.).
304
305### How to test
306
307Run `d8` with `--lcov` and check whether the produced coverage information is correct. E.g. like this:
308
309```
310./d8 --lcov=cov.info test.js
311genhtml cov.info -o coverage
312```
313
314Then navigate your browser to `coverage/index.html`.
315
316### Test cases
317
318`test/mjsunit/code-coverage-block.js`
319
320### Reading material
321
322Design doc: [go/v8-designdoc-block-code-coverage](http://go/v8-designdoc-block-code-coverage)
323
324
325## Heap profiler
326
327The heap profiler is a tool usually used to find out what is taking so much memory, and find potential memory leaks. It is an object graph visitor.
328
329### Affected
330
331NLFs that change object layouts or introduce new object types
332
333### How to test
334
335Take a heap Snapshot in DevTools' Profiler panel and inspect the result. Objects related to the NLF should fan out to all objects it references to.
336
337### Test cases
338
339Take a look at `test/cctest/test-heap-profiler.cc`.
340
Simon Zünd5cfe4e72024-10-22 07:36:50341## Restart frame
342
343DevTools allows restarting of some stack frames, not just the top-level one. The feature is implemented by throwing a termination exception and unwinding the stack
344until after the function we want to restart, and then re-invoking the function. This only works for certain functions, e.g. async functions can't be restarted
345as that would require rolling back the underlying generator.
346
347### Affected
348
349NLFs that change function execution or require a function to carry state (e.g. async functions
350need a generator that can't be reset).
351
352### How to test
353
354While paused, right click a stack frame with the NLF in the call stack view and select "Restart frame". If the NLF prevents the frame from being restarted, then
355the "Restart frame" menu item must be disabled, otherwise the frame must be properly restarted.
356
357### Test cases
358
359Take a look in `test/inspector/debugger/restart-frame/*`.
Benedikt Meurere8783db2024-08-21 12:16:03360
361## LiveEdit
362
363LiveEdit is a feature that allows for script content to be replaced during its execution. While it has many limitations, the most often use case
Simon Zünd5cfe4e72024-10-22 07:36:50364of editing the function we are paused in and restarting said function afterwards.
Benedikt Meurere8783db2024-08-21 12:16:03365
366### Affected
367
368NLFs that affect code execution
369
370### How to test
371
Simon Zünd5cfe4e72024-10-22 07:36:50372Open DevTools and break inside the part of script affected by the NLF. Change the code inside the function with the NLF and save the script.
Benedikt Meurere8783db2024-08-21 12:16:03373
374### Test cases
375
376Look for `mjsunit` tests with `liveedit` in their names.