1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
/* this source code form is subject to the terms of the mozilla public
* license, v. 2.0. if a copy of the mpl was not distributed with this
* file, you can obtain one at http://mozilla.org/mpl/2.0/. */
"use strict";
const {
startTracing,
addTracingListener,
stopTracing,
removeTracingListener,
} = require("resource://devtools/server/tracer/tracer.jsm");
let testFileContent;
function traceFrame({ frame }) {
const { script } = frame;
const { lineNumber, columnNumber } = script.getOffsetMetadata(frame.offset);
const { url } = script.source;
const filename = url.substr(url.lastIndexOf("/") + 1);
const line = testFileContent[lineNumber - 1];
// Grey out the beginning of the line, before frame's column,
// and display an arrow before displaying the rest of the line.
const code =
"\x1b[2m" +
line.substr(0, columnNumber - 1) +
"\x1b[0m" +
"\u21A6 " +
line.substr(columnNumber - 1);
const position = (lineNumber + ":" + columnNumber).padEnd(7);
logStep(`${filename} @ ${position} :: ${code}`);
// Disable builtin tracer logging
return false;
}
function logStep(message) {
dump(` \x1b[2m[STEP]\x1b[0m ${message}\n`);
}
const tracingListener = {
onTracingFrame: traceFrame,
onTracingFrameStep: traceFrame,
};
exports.start = function (testGlobal, testUrl, pause) {
const tracerOptions = {
global: testGlobal,
// Ensure tracing each execution within functions (and not only function calls)
traceSteps: true,
// Only trace the running test and nothing else
filterFrameSourceUrl: testUrl,
};
testFileContent = readURI(testUrl).split("\n");
// Only pause on each step if the passed value is a number,
// otherwise we are only going to print each executed line in the test script.
if (!isNaN(pause)) {
// Delay each step by an amount of milliseconds
tracerOptions.pauseOnStep = Number(pause);
logStep(`Tracing all test script steps with ${pause}ms pause`);
logStep(
`/!\\ Be conscious about each pause releasing the event loop and breaking run-to-completion.`
);
} else {
logStep(`Tracing all test script steps`);
}
logStep(
`'\u21A6 ' symbol highlights what precise instruction is being called`
);
startTracing(tracerOptions);
addTracingListener(tracingListener);
};
exports.stop = function () {
stopTracing();
removeTracingListener(tracingListener);
};
function readURI(uri) {
const { NetUtil } = ChromeUtils.importESModule(
"resource://gre/modules/NetUtil.sys.mjs",
{ global: "contextual" }
);
const stream = NetUtil.newChannel({
uri: NetUtil.newURI(uri, "UTF-8"),
loadUsingSystemPrincipal: true,
}).open();
const count = stream.available();
const data = NetUtil.readInputStreamToString(stream, count, {
charset: "UTF-8",
});
stream.close();
return data;
}
|