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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-env mozilla/frame-script */
// This file expects frame-head.js to be loaded in the environment.
/* import-globals-from frame-head.js */
"use strict";
function forceSyncReflow(div) {
div.setAttribute("class", "resize-change-color");
// Force a reflow.
return div.offsetWidth;
}
function testSendingEvent() {
content.document.body.dispatchEvent(new content.Event("dog"));
}
function testConsoleTime() {
content.console.time("cats");
}
function testConsoleTimeEnd() {
content.console.timeEnd("cats");
}
function makePromise() {
let resolver;
new Promise(function(resolve, reject) {
testConsoleTime();
resolver = resolve;
}).then(function(val) {
testConsoleTimeEnd();
});
return resolver;
}
function resolvePromise(resolver) {
resolver(23);
}
var TESTS = [
{
desc: "Stack trace on sync reflow",
searchFor: "Reflow",
setup(docShell) {
let div = content.document.querySelector("div");
forceSyncReflow(div);
},
check(markers) {
markers = markers.filter(m => m.name == "Reflow");
ok(!!markers.length, "Reflow marker includes stack");
ok(markers[0].stack.functionDisplayName == "forceSyncReflow");
},
},
{
desc: "Stack trace on DOM event",
searchFor: "DOMEvent",
setup(docShell) {
content.document.body.addEventListener(
"dog",
function(e) {
console.log("hi");
},
true
);
testSendingEvent();
},
check(markers) {
markers = markers.filter(m => m.name == "DOMEvent");
ok(!!markers.length, "DOMEvent marker includes stack");
ok(
markers[0].stack.functionDisplayName == "testSendingEvent",
"testSendingEvent is on the stack"
);
},
},
{
desc: "Stack trace on console event",
searchFor: "ConsoleTime",
setup(docShell) {
testConsoleTime();
testConsoleTimeEnd();
},
check(markers) {
markers = markers.filter(m => m.name == "ConsoleTime");
ok(!!markers.length, "ConsoleTime marker includes stack");
ok(
markers[0].stack.functionDisplayName == "testConsoleTime",
"testConsoleTime is on the stack"
);
ok(
markers[0].endStack.functionDisplayName == "testConsoleTimeEnd",
"testConsoleTimeEnd is on the stack"
);
},
},
];
if (
!Services.prefs.getBoolPref(
"javascript.options.asyncstack_capture_debuggee_only"
)
) {
TESTS.push({
desc: "Async stack trace on Promise",
searchFor: "ConsoleTime",
setup(docShell) {
let resolver = makePromise();
resolvePromise(resolver);
},
check(markers) {
markers = markers.filter(m => m.name == "ConsoleTime");
ok(!!markers.length, "Promise marker includes stack");
ok(
markers[0].stack.functionDisplayName == "testConsoleTime",
"testConsoleTime is on the stack"
);
let frame = markers[0].endStack;
ok(
frame.functionDisplayName == "testConsoleTimeEnd",
"testConsoleTimeEnd is on the stack"
);
frame = frame.parent;
ok(
frame.functionDisplayName == "makePromise/<",
"makePromise/< is on the stack"
);
let asyncFrame = frame.asyncParent;
ok(asyncFrame !== null, "Frame has async parent");
is(
asyncFrame.asyncCause,
"promise callback",
"Async parent has correct cause"
);
// Skip over self-hosted parts of our Promise implementation.
while (asyncFrame.source === "self-hosted") {
asyncFrame = asyncFrame.parent;
}
is(
asyncFrame.functionDisplayName,
"makePromise",
"Async parent has correct function name"
);
},
});
}
timelineContentTest(TESTS);
|