forked from nodejs/llnode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathframe-test.js
More file actions
137 lines (116 loc) · 4.47 KB
/
Copy pathframe-test.js
File metadata and controls
137 lines (116 loc) · 4.47 KB
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
'use strict';
const { promisify } = require('util');
const tape = require('tape');
const common = require('../common');
const sourceCodes = {
"fnFunctionName": [
"26 function fnFunctionName() {",
"27 (new Module()).fnInferredNamePrototype();",
"28 return this; // Force definition of |this|.",
"29 }",
],
"fnInferredNamePrototype": [
"22 Module.prototype.fnInferredNamePrototype = function() {",
"23 fnInferredName();",
"24 }",
"25",
],
"fnInferredName": [
"14 fnInferredName = (() => function () {",
"15 crasher(); // # args < # formal parameters inserts an adaptor frame.",
"16 })();",
"17",
],
};
function fatalError(t, sess, err) {
t.error(err);
sess.quit();
return t.end();
}
async function testFrameList(t, sess, frameNumber, sourceCode, cb) {
const lastLine = new RegExp(sourceCode[sourceCode.length - 1]);
sess.send(`frame select ${frameNumber}`);
await sess.linesUntil(/frame/);
sess.send('v8 source list');
await sess.linesUntil(/v8 source list/);
let lines = await sess.linesUntil(lastLine);
t.equal(lines.length, sourceCode.length,
`v8 source list correct size`);
for (let i = 0; i < lines.length; i++) {
t.equal(lines[i].trim(), sourceCode[i], `v8 source list #${i}`);
}
sess.send('v8 source list -l 2');
await sess.linesUntil(/v8 source list/);
lines = await sess.linesUntil(lastLine);
t.equal(lines.length, sourceCode.length - 1,
`v8 source list -l 2 correct size`);
for (let i = 0; i < lines.length; i++) {
t.equal(lines[i].trim(), sourceCode[i + 1],
`v8 source list -l 2 #${i}`);
}
}
tape('v8 stack', async (t) => {
t.timeoutAfter(15000);
const sess = common.Session.create('frame-scenario.js');
sess.waitBreak = promisify(sess.waitBreak);
sess.linesUntil = promisify(sess.linesUntil);
try {
await sess.waitBreak();
sess.send('v8 bt');
let lines = await sess.linesUntil(/\sfnFunctionName\(/);
lines.reverse();
t.ok(lines.length > 4, 'frame count');
lines = lines.filter((s) => !/<builtin>|<stub>/.test(s));
const exit = lines[5];
const crasher = lines[4];
const adapter = lines[3];
const fnInferredName = lines[2];
const fnInferredNamePrototype = lines[1];
const fnFunctionName = lines[0];
t.ok(/<exit>/.test(exit), 'exit frame');
t.ok(/crasher/.test(crasher), 'crasher frame');
t.ok(/<adaptor>/.test(adapter), 'arguments adapter frame');
t.ok(/\sfnInferredName\(/.test(fnInferredName), 'fnInferredName frame');
t.ok(/\sModule.fnInferredNamePrototype\(/.test(fnInferredNamePrototype),
'fnInferredNamePrototype frame');
t.ok(/\sfnFunctionName\(/.test(fnFunctionName), 'fnFunctionName frame');
// fn() is a sloppy mode function that should have an implicit
// |this| that is the global object. crasher() is a strict mode function
// that should have a |this| that is the |undefined| value.
//
// Interestingly, V8 4.5 has a quirk where the |this| value is |undefined|
// in both strict and sloppy mode unless the function actually uses |this|.
// The test adds unreachable `return this` statements as a workaround.
t.ok(/this=(0x[0-9a-f]+):<Global proxy>/.test(fnFunctionName),
'global this');
t.ok(/this=(0x[0-9a-f]+):<undefined>/.test(crasher), 'undefined this');
// TODO(mmarchini): also test positional info (line, column)
const fnFunctionNameFrame = fnFunctionName.match(/frame #([0-9]+)/)[1];
if (fnFunctionNameFrame) {
await testFrameList(t, sess, fnFunctionNameFrame,
sourceCodes['fnFunctionName']);
} else {
fatalError(t, sess, "Couldn't determine fnFunctionName's frame number");
}
const fnInferredNamePrototypeFrame =
fnInferredNamePrototype.match(/frame #([0-9]+)/)[1];
if (fnInferredNamePrototypeFrame) {
await testFrameList(t, sess, fnInferredNamePrototypeFrame,
sourceCodes['fnInferredNamePrototype']);
} else {
fatalError(t, sess,
"Couldn't determine fnInferredNamePrototype's frame number");
}
const fnInferredNameFrame = fnInferredName.match(/frame #([0-9]+)/)[1];
if (fnInferredNameFrame) {
await testFrameList(t, sess,
fnInferredNameFrame, sourceCodes['fnInferredName']);
} else {
fatalError(t, sess, "Couldn't determine fnInferredName's frame number");
}
sess.quit();
return t.end();
} catch (err) {
fatalError(t, sess, err);
}
});