blob: cf47ee3fbdc49bf4e7ddf4928a8ca6a3c4681643 [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
22[TOC]
23
24## Console printing
25
26DevTools offers a REPL through the Console panel. Logging a value should print reasonable output.
27
28### Affected
29
30All NLFs that affect how values should be printed in a REPL, such as NLFs that introduce new primitives, new `RegExp` flags, etc.
31
32### How to test
33
34Open DevTools, select the Console panel, and enter a source snippet with the NLF. The printed result should look alright.
35
36### Reading material
37
38[Example CL that adds printing support for a new `RegExp` flag](https://chromium-review.googlesource.com/c/v8/v8/+/2848460)
39
40
41## Syntax highlighting and pretty-printing
42
43DevTools provides syntax highlighting and pretty-printing for JavaScript sources.
44
45### Affected
46
47All NLFs that introduce new syntax.
48
49### How to test
50
51Open DevTools, select the Sources panel, and create a new source snippet with the NLF. The syntax highlighting of the source
52should look alright. This is handled by [CodeMirror](https://codemirror.net/) inside of Chromium DevTools.
53
54Clicking on the pretty-printing button on the bottom left ("{}") should yield reasonable results. The formatting relies on the
55[acorn](https://github.com/acornjs/acorn) parser, which needs to support the NLF in question for this to work.
56
57
58## Stack traces
59
60Stack traces is the most often used way for developers to debug issues. Aside from the default `Error.stack` string, we also
61offer a way for user code to override how to format the `stack` property, and collect a more detailed structured stack trace
62for DevTools.
63
64Sometimes, due to the way a feature is implemented, there may be stack frames that show up on the stack trace when they should
65not, or vice versa.
66
67For runtime exceptions, we look for the closest code position that has a source position attached. That source position is used
68as expression position for the exception. For syntax errors, we should report the correct location of the syntax error via
69[`MessageHandler::ReportMessage()`](https://source.chromium.org/chromium/chromium/src/+/main:v8/src/execution/messages.h;l=174-176;drc=4e40b002b46c019d18eae68b5e5a342605609d95).
70
71Note that `Error.stack` is only collected for `Error` objects, at the time the `Error` object is constructed. This may be different
72than 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).
73
74Independently from V8, DevTools offers a way to show async stack traces by stitching together stack traces collected at the
75location where the callback is passed, and the actual location of the exception inside the callback.
76
77### Affected
78
79NLFs that can cause an exception to be thrown, or can call into another function that throws.
80
81### How to test
82
83When throwing inside the NLF, or with it on the stack, the stack trace including source positions should make sense. Also check
84the structured stack trace when the exception is not caught and logged into Chrome's DevTools console.
85
86Repeat with the "Disable async stack traces" checkbox in the Preferences checked.
87
88### Test cases
89
90Test cases for stack traces is mandatory, if there is any way the NLF can interact with throwing exceptions. For examples look
91for `mjsunit` tests with `stack-trace` in their names.
92
93For async stack traces, please look at Blink LayoutTests such as [this one](https://chromium.googlesource.com/chromium/src/+/3daa588ce613845e298cbd667fa6f5787f95d574/third\_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await.html).
94
95### 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
99
100## Catch prediction
101
102Aside from offering stack traces, V8's debugger supports DevTools' pause-on-exception feature. This comes in two flavors:
103pause on all exceptions, and pause on uncaught exceptions. In both cases, we break at the throw site (not at the `catch`,
104or any rethrow via `try`-`finally`).
105
106For the former, this is as easy as breaking in the debugger on `Isolate::Throw()`. For the latter, we have to predict whether
107the thrown exception will be caught or otherwise handled (for example by a `Promise`'s catch handler).
108
109### Affected
110
111NLFs that can cause an exception to be thrown, or can call into another function that throws.
112
113### How to test
114
115When pause-on-exception is enabled, and throwing inside the NLF or with it on the stack, the script should pause as expected.
116
117Repeat with the "pause on caught exception" checkbox checked.
118
119### Test cases
120
121Test cases for exception prediction is mandatory, if there is any way the NLF can interact with exceptions, be it by throwing
122exceptions, or by relying on `try`-`catch` or `try`-`finally` in its implementation. Look for `mjsunit` tests that contain the
123string `setBreakOnException` or `setBreakOnUncaughtException`.
124
125### Reading material
126
127[Design doc for exception prediction for async-await](https://docs.google.com/a/google.com/document/d/1ef1drN6RTRN7iDB8FXJg\_JJZFNObCFbM1UjZWK\_ORUE/edit?usp=drive\_web)
128
129
130## Breakpoints
131
132One of the most important features is setting break points. The semantics should be obvious.
133
134Break locations are function calls, return sites, and statements. Special care are necessary for loops: for example, in `for`-loops
135we do want to be able to break separately at the loop entry, condition evaluation, and increment.
136
137When setting a break point at an arbitrary source position, we actually check for the closest breakable source position, and move
138the break point there. Consecutive debug break events at the same source position are ignored by the debugger.
139
140### Affected
141
142NLFs that change generated code, and especially once that introduce new break locations.
143
144### How to test
145
146Open DevTools and set break points in parts of script related to the NLF, then run the script.
147
148### Test cases
149
150Look for `mjsunit` tests with `debug-break` in their names.
151
152
153## Stepping
154
155Stepping is the logical consequence to breakpoints, and is based on the same mechanism in the debugger. We differentiate between
156
157* Step out, which takes us to the next break location in the caller.
158* Step next, which takes us to the next break location while ignoring calls into other functions. Note that this includes recursive
159 calls. Step next at a return site is equivalent to a step out.
160* Step in, which takes us to the next break location including calls into another function.
161* Step frame, which takes us to another function, either a callee or a caller. This is used for framework blackboxing, where the V8
162 inspector is not interested in stepping in the current function, and wants to be notified once we arrive at another function
163
164### Affected
165
166NLFs that are affect breakpoints
167
168### How to test
169
170Break inside the part of script related to the NLF, and try stepping in, next, and out.
171
172### Test cases
173
174Look for `mjsunit` tests with `debug-step` in their names.
175
176### Reading material
177
178[Design doc on stepping in async-await](https://docs.google.com/a/google.com/document/d/1nj3nMlQVEFlq57dA-K8wFxdOB5ovvNuwNbWxBhcBOKE/edit?usp=drive\_web)
179
180
181## Frame inspector
182
183The 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,
184the break location is that of the debug break. For frames below the break location is the call site leading to the frame above.
185
186For each frame, we can
187
188- inspect the scope chain at the break location with the scope iterator,
189- find out whether it's called as constructor,
190- find out whether we are at a return position,
191- get the function being called,
192- get the receiver,
193- get the arguments, and
194- get the number of stack-allocated locals.
195
196For optimized code, we use the deoptimizer to get hold of receiver, arguments and stack locals, but this is often not possible, and we
197get the `optimzed_out` sentinel value.
198
199### Affected
200
201NLFs that affect the way V8 calls functions.
202
203### How to test
204
205When paused inside the function affected by the NLF, the Call Stack view in the DevTools' Source panel should show useful information.
206
207### Test cases
208
209Take a look at `test/mjsunit/wasm/frame-inspection.js`.
210
211
212## Scope iterator
213
214The scope iterator in V8 offers a way to introspect the scope chain at the break location. It includes not only the scopes outside of
215the current function, but also scopes inside it, for example inner block scopes, catch scopes, with scopes, etc.
216
217For each scope inside the current function, we can materialize an object representing local variables belonging to it. For scopes
218outside the current function this is not possible.
219
220We can use the scope iterator to alter the value of local variables, unless we are inside an optimized frame.
221
222### Affected
223
224NLFs that introduce new scopes.
225
226### How to test
227
228When paused in DevTools inside the scope introduced by the NLF, the "Scope" view on the Sources panel should show useful information.
229Scopes that are introduced by the NLF for desugaring purposes may better be hidden.
230
231### Test cases
232
233Take a look at `test/mjsunit/debug-scopes.js`.
234
235### Reading material
236
237[CL that introduces hidden scopes](https://chromium.googlesource.com/v8/v8/+/672983830f36222d90748ff588831b6dae565c38)
238
239
240## Debug evaluate
241
242With debug-evaluate, V8 offers a way to evaluate scripts at a break, attempting to behave as if the script code was executed
243right at the break location. It is based on the frame inspector and the scope iterator.
244
245It works by creating a context chain that not only references contexts on the current context chain, but also contains the
246materialized stack, including arguments object and the receiver. The script is then compiled and executed inside this context chain.
247
248There are some limitations, and special attention has to be paid to variable name shadowing.
249
250Side-effect-free debug-evaluate statically determines whether a function should throw. You should check whether to update the
251whitelist in `src/debug/debug-evaluate.cc`.
252
253### Affected
254
255NLFs that are also affected by the scope iterator and frame inspector.
256
257### How to test
258
259Use the DevTools console to run scripts at a debug break. In particular the preview shown in the DevTools console by default indicates
260whether the side-effect detection works correctly (i.e. whether you updated the whitelist correctly).
261
262### Test cases
263
264Look for mjsunit tests with "debug-evaluate" in their names.
265
266### Reading material
267
268This [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)
269
270Debug-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)
271
272
273## Code Coverage
274
275Code coverage gathers execution counts and exposes them to developers through the Inspector protocol.
276
277### Affected
278
279NLFs that contain control flow (e.g branches, loops, etc.).
280
281### How to test
282
283Run `d8` with `--lcov` and check whether the produced coverage information is correct. E.g. like this:
284
285```
286./d8 --lcov=cov.info test.js
287genhtml cov.info -o coverage
288```
289
290Then navigate your browser to `coverage/index.html`.
291
292### Test cases
293
294`test/mjsunit/code-coverage-block.js`
295
296### Reading material
297
298Design doc: [go/v8-designdoc-block-code-coverage](http://go/v8-designdoc-block-code-coverage)
299
300
301## Heap profiler
302
303The 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.
304
305### Affected
306
307NLFs that change object layouts or introduce new object types
308
309### How to test
310
311Take 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.
312
313### Test cases
314
315Take a look at `test/cctest/test-heap-profiler.cc`.
316
317
318## LiveEdit
319
320LiveEdit is a feature that allows for script content to be replaced during its execution. While it has many limitations, the most often use case
321of editing the function we are paused in and restarting said function usually works.
322
323### Affected
324
325NLFs that affect code execution
326
327### How to test
328
329Open DevTools and break inside the part of script affected by the NLF. In the Source panel's Call Stack view, right-click the top-most frame and select
330Restart Frame.
331
332### Test cases
333
334Look for `mjsunit` tests with `liveedit` in their names.