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
|
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"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: function(docShell) {
let div = content.document.querySelector("div");
forceSyncReflow(div);
},
check: function(markers) {
markers = markers.filter(m => m.name == "Reflow");
ok(markers.length > 0, "Reflow marker includes stack");
ok(markers[0].stack.functionDisplayName == "forceSyncReflow");
}
}, {
desc: "Stack trace on DOM event",
searchFor: "DOMEvent",
setup: function(docShell) {
content.document.body.addEventListener("dog",
function(e) { console.log("hi"); },
true);
testSendingEvent();
},
check: function(markers) {
markers = markers.filter(m => m.name == "DOMEvent");
ok(markers.length > 0, "DOMEvent marker includes stack");
ok(markers[0].stack.functionDisplayName == "testSendingEvent",
"testSendingEvent is on the stack");
}
}, {
desc: "Stack trace on console event",
searchFor: "ConsoleTime",
setup: function(docShell) {
testConsoleTime();
testConsoleTimeEnd();
},
check: function(markers) {
markers = markers.filter(m => m.name == "ConsoleTime");
ok(markers.length > 0, "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")) {
TESTS.push({
desc: "Async stack trace on Promise",
searchFor: "ConsoleTime",
setup: function(docShell) {
let resolver = makePromise();
resolvePromise(resolver);
},
check: function(markers) {
markers = markers.filter(m => m.name == "ConsoleTime");
ok(markers.length > 0, "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);
|