1 // Set breakpoints "everywhere" in a function, then call the function and check that
2 // the breakpoints were added are at the expected columns, and the breakpoints
3 // were executed in th expected order.
5 // `code` is a JS Script. The final line should define a function `f` to validate.
6 // `expectedBpts` is a string of spaces and carets ('^'). Throws if we don't hit
7 // breakpoints on exactly the columns indicated by the carets.
8 // `expectedOrdering` is a string of integer indices for the offsets that are
9 // executed, in the order that then are executed. Test code can also push
10 // additional items into this string using items.push("!").
11 function assertOffsetColumns(code, expectedBpts, expectedOrdering = null) {
12 if (expectedOrdering === null) {
13 // The default ordering simply runs the breakpoints in order.
14 expectedOrdering = Array.from(expectedBpts.match(/\^/g), (_, i) => i).join(" ");
17 // Define the function `f` in a new global.
18 const global = newGlobal({newCompartment: true});
20 const lines = code.split(/\r?\n|\r]/g);
21 const initCode = lines.slice(0, -1).join("\n");
22 const execCode = lines[lines.length - 1];
24 // Treat everything but the last line as initialization code.
25 global.eval(initCode);
27 // Run the test code itself.
28 global.eval(execCode);
30 // Allow some tests to append to a log that will show up in expected ordering.
31 const hits = global.hits = [];
32 const bpts = new Set();
34 // Set breakpoints everywhere and call the function.
35 const dbg = new Debugger;
36 let debuggeeFn = dbg.addDebuggee(global).makeDebuggeeValue(global.f);
37 if (debuggeeFn.isBoundFunction) {
38 debuggeeFn = debuggeeFn.boundTargetFunction;
41 const { script } = debuggeeFn;
42 for (const offset of script.getAllColumnOffsets()) {
43 assertEq(offset.lineNumber, 1);
44 assertEq(offset.columnNumber < execCode.length, true);
45 bpts.add(offset.columnNumber);
47 script.setBreakpoint(offset.offset, {
49 hits.push(offset.columnNumber);
55 const actualBpts = Array.from(execCode, (_, i) => {
56 return bpts.has(i) ? "^" : " ";
59 if (actualBpts.trimEnd() !== expectedBpts.trimEnd()) {
60 throw new Error(`Assertion failed:
62 expected bpts: ${expectedBpts}
63 actual bpts: ${actualBpts}\n`);
66 const indexLookup = new Map(
67 Array.from(bpts).sort().map((col, i) => [col, i]));
68 const actualOrdering = hits
69 .map(item => typeof item === "number" ? indexLookup.get(item) : item)
72 if (actualOrdering.trimEnd() !== expectedOrdering.trimEnd()) {
73 throw new Error(`Assertion failed:
76 expected order: ${expectedOrdering}
77 actual order: ${actualOrdering}\n`);