2
// Copyright (C) 2008 Loic Dachary <loic@dachary.org>
3
// Copyright (C) 2008 Johan Euphrosine <proppy@aminche.com>
4
// Copyright (C) 2010 Eric Wendelin <emwendelin@gmail.com>
6
// This program is free software: you can redistribute it and/or modify
7
// it under the terms of the GNU General Public License as published by
8
// the Free Software Foundation, either version 3 of the License, or
9
// (at your option) any later version.
11
// This program is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with this program. If not, see <http://www.gnu.org/licenses/>.
22
test("printStackTrace", function() {
24
var r = printStackTrace();
25
equals(r.constructor, Array, 'printStackTrace returns an array');
28
test("printStackTrace options", function() {
30
var guessFunctions = printStackTrace.implementation.prototype.guessFunctions;
31
printStackTrace.implementation.prototype.guessFunctions = function() {
32
printStackTrace.implementation.prototype.guessFunctions = guessFunctions;
33
ok(true, 'guessFunctions called');
35
var r = printStackTrace({guess: true});
40
test("mode", function() {
42
equals("chrome firefox other opera opera10".indexOf(printStackTrace.implementation.prototype.mode()) >= 0,true);
45
test("run mode", function() {
47
var p = new printStackTrace.implementation();
48
p.other = p.firefox = p.chrome = p.opera = p.opera10 = function() { equals(1,1,'called'); };
52
test("run firefox", function() {
54
var p = new printStackTrace.implementation();
56
p.other = p.opera = function() { equals(1,0,'must not be called'); };
57
p.firefox = function() { equals(1,1,'called'); };
61
test("run opera", function() {
63
var p = new printStackTrace.implementation();
65
p.opera10 = p.other = p.firefox = p.chrome = function() { equals(1,0,'must not be called'); };
66
p.opera = function() { equals(1,1,'called'); };
70
test("run opera10", function() {
72
var p = new printStackTrace.implementation();
74
p.opera = p.other = p.firefox = p.chrome = function() { equals(1,0,'must not be called'); };
75
p.opera10 = function() { equals(1,1,'called'); };
79
test("run other", function() {
81
var p = new printStackTrace.implementation();
83
p.opera = p.firefox = function() { equals(1,0,'must not be called'); };
84
p.other = function() { equals(1,1,'called'); };
88
test("firefox", function() {
89
var mode = printStackTrace.implementation.prototype.mode();
91
e.push({ stack: 'discarded()...\nf1(1,"abc")@file.js:40\n()@file.js:41\n@:0 \nf44()@file.js:494'});
92
if(mode == 'firefox') {
93
function discarded() {
94
try {(0)();} catch (exception) {
98
function f1(arg1, arg2) {
101
var f2 = function() {
106
expect(4 * e.length);
107
for(var i = 0; i < e.length; i++) {
108
var stack = printStackTrace.implementation.prototype.firefox(e[i]);
109
var stack_string = stack.join("\n");
110
//equals(message_string, '', 'debug');
111
equals(stack_string.indexOf('discarded'), -1, 'discarded');
112
equals(stack[0].indexOf('f1(1,"abc")') >= 0, true, 'f1');
113
equals(stack[1].indexOf('{anonymous}()@') >= 0, true, 'f2 anonymous');
114
equals(stack[2].indexOf('@:0'), -1, '@:0 discarded');
118
test("chrome", function() {
119
var mode = printStackTrace.implementation.prototype.mode();
121
e.push({ stack: 'ignored\nignored\n at discarded (file.js:132:3)\n at file.js:135:3\n at f1 (file.js:132:13)\n at file.js:135:23\n at Object.<anonymous> (file.js:137:9)\n at file.js:137:32 at process (file.js:594:22)'});
122
if(mode == 'chrome') {
123
function discarded() {
124
try {(0)();} catch (exception) {
128
function f1(arg1, arg2) {
131
var f2 = function() {
136
expect(4 * e.length);
137
for(var i = 0; i < e.length; i++) {
138
var message = printStackTrace.implementation.prototype.chrome(e[i]);
139
var message_string = message.join("\n");
140
//equals(message_string, '', 'debug');
141
equals(message_string.indexOf('discarded'), -1, 'discarded');
142
equals(message[0].indexOf('f1') >= 0, true, 'f1');
143
equals(message[1].indexOf('anonymous') >= 0, true, 'f2 anonymous');
144
equals(message[2].indexOf('unknown source'), -1, 'unknown source discarded');
148
test("opera10", function() {
149
var mode = printStackTrace.implementation.prototype.mode();
151
e.push({ stack: 'ignored\nf1([arguments not available])@http://site.com/main.js:2\n<anonymous function: f2>([arguments not available])@http://site.com/main.js:4\n@',
152
stacktrace: 'ignored\nError thrown at line 1, column 55 in discarded():\n (0)();\ncalled from line 1, column 333 in f1(arg1, arg2):\n discarded();\ncalled from line 1, column 470 in <anonymous function>():\n f1(1, "abc");\ncalled from line 1, column 278 in program code:\n f2();' });
153
if (mode == 'opera10') {
154
function discarded() {
155
try {(0)();} catch (exception) {
159
function f1(arg1, arg2) {
163
var f2 = function() {
168
expect(3 * e.length);
169
for(var i = 0; i < e.length; i++) {
170
var stack = printStackTrace.implementation.prototype.opera10(e[i]);
171
var stack_string = stack.join('\n');
172
// equals(stack[1], '', 'debug');
173
equals(stack_string.indexOf('ignored'), -1, 'ignored');
174
equals(stack[0].indexOf('f1(') >= 0, true, 'f1 function name');
175
equals(stack[1].indexOf('{anonymous}()') >= 0, true, 'f2 is anonymous');
176
//FIXME: Clean up stack[2], opera has some internal stack weirdness
180
test("opera", function() {
181
var mode = printStackTrace.implementation.prototype.mode();
183
e.push({ message: 'ignored\nignored\nignored\nignored\nLine 40 of linked script http://site.com: in function f1\n discarded()\nLine 44 of linked script http://site.com\n f1(1, "abc")\nignored\nignored'});
184
if(mode == 'opera') {
185
function discarded() {
186
try {(0)();} catch (exception) {
190
function f1(arg1, arg2) {
193
var f2 = function() {
198
expect(5 * e.length);
199
for(var i = 0; i < e.length; i++) {
200
var message = printStackTrace.implementation.prototype.opera(e[i]);
201
var message_string = message.join("\n");
202
equals(message_string.indexOf('ignored'), -1, 'ignored');
203
equals(message[0].indexOf('f1()') >= 0, true, 'f1 function name');
204
equals(message[0].indexOf('discarded()') >= 0, true, 'f1 statement');
205
equals(message[1].indexOf('{anonymous}()@') >= 0, true, 'f2 is anonymous');
206
equals(message[1].indexOf('f1(1, "abc")') >= 0, true, 'f2 statement');
210
test("other", function() {
211
var mode = printStackTrace.implementation.prototype.mode();
212
var frame = function(args, fun, caller) {
213
this['arguments'] = args;
214
this.caller = caller;
217
frame.prototype.toString = function() { return 'function '+this.fun+'() {}'; };
219
var frame_f2 = new frame([], '', undefined);
220
var frame_f1 = new frame([1, 'abc', f10, {1: {2: {3: 4} } }], 'FUNCTION f1 (a,b,c)', frame_f2);
221
expect(mode == 'other' ? 4 : 2);
222
var message = printStackTrace.implementation.prototype.other(frame_f1);
223
var message_string = message.join("\n");
224
equals(message[0].indexOf('f1(1,"abc",#function,#object)') >= 0, true, 'f1');
225
equals(message[1].indexOf('{anonymous}()') >= 0, true, 'f2 anonymous');
226
if(mode == 'other') {
227
function f1(arg1, arg2) {
228
var message = printStackTrace.implementation.prototype.other(arguments.callee);
229
var message_string = message.join("\n");
230
//equals(message_string, '', 'debug');
231
equals(message[0].indexOf('f1(1,"abc",#function,#object)') >= 0, true, 'f1');
232
equals(message[1].indexOf('{anonymous}()') >= 0, true, 'f2 anonymous');
234
var f2 = function() {
235
f1(1, 'abc', f10, {1: {2: {3: 4} } });
243
test("recursion other", function() {
244
var mode = printStackTrace.implementation.prototype.mode();
245
expect(mode == 'other' ? 2 : 0);
246
if (mode == 'other') {
247
function recurse(b) {
249
var message = printStackTrace.implementation.prototype.other(arguments.callee);
250
var message_string = message.join("\n");
251
//equals(message_string, '', 'debug');
252
equals(message[0].indexOf('recurse(false)') >= 0, true, 'first recurse false');
253
equals(message[1].indexOf('recurse(true)') >= 0, true, 'second recurse true');
262
test("stringify", function() {
264
equals(printStackTrace.implementation.prototype.stringifyArguments(["a", 1, {}, function() {}, undefined]), '"a",1,#object,#function,undefined');
265
equals(printStackTrace.implementation.prototype.stringifyArguments([0, 1, 2, 3]), '0,1,2,3');
266
equals(printStackTrace.implementation.prototype.stringifyArguments([['a', null]]), '["a",null]');
267
equals(printStackTrace.implementation.prototype.stringifyArguments([[2, 4, 6, 8, 10, 12, 14]]), '[2...14]');
268
equals(printStackTrace.implementation.prototype.stringifyArguments([]), '');
271
test("isSameDomain", function() {
273
ok(printStackTrace.implementation.prototype.isSameDomain(location.href));
277
test("guessFunctionNameFromLines", function() {
279
equals(printStackTrace.implementation.prototype.guessFunctionNameFromLines(2, ['var a = function() {', 'var b = 2;', '};']), 'a');
280
equals(printStackTrace.implementation.prototype.guessFunctionNameFromLines(2, ['function a() {', 'var b = 2;', '};']), 'a');
281
equals(printStackTrace.implementation.prototype.guessFunctionNameFromLines(2, ['var a = 1;', 'var b = 2;', 'var c = 3;']), '(?)');
284
test("getSource cache miss", function() {
286
var p = new printStackTrace.implementation();
287
var file = 'file:///test';
288
p.ajax = function(fileArg, callback) {
289
equals(fileArg, file, 'cache miss');
290
return 'line0\nline1\n';
292
var lines = p.getSource(file);
293
equals(lines[0], 'line0');
294
equals(lines[1], 'line1');
297
test("getSource cache hit", function() {
299
var p = new printStackTrace.implementation();
300
var file = 'file:///test';
301
p.ajax = function(fileArg, callback) {
302
ok(false, 'not called');
304
p.sourceCache[file] = ['line0', 'line1'];
305
var lines = p.getSource(file);
306
equals(lines[0], 'line0');
307
equals(lines[1], 'line1');
310
test("sync ajax", function() {
312
var p = new printStackTrace.implementation();
313
var data = p.ajax(document.location.href);
314
ok(data.indexOf('stacktrace') >= 0, 'synchronous get');
317
test("guessFunctionName", function() {
319
var p = new printStackTrace.implementation();
320
var file = 'http://' + window.location.hostname + '/file.js';
321
p.sourceCache[file] = ['var a = function() {', 'var b = 2;', '};'];
322
equals(p.guessFunctionName(file, 2), 'a');
325
test("guessFunctionName exception", function() {
327
var p = new printStackTrace.implementation();
328
p.getSource = function() {
329
throw 'permission denied';
331
var file = 'file:///test';
332
equals(p.guessFunctionName(file, 2), 'getSource failed with url: file:///test, exception: permission denied');
335
test("guessFunctions firefox", function() {
337
var mode = printStackTrace.implementation.prototype.mode();
338
var p = new printStackTrace.implementation();
340
var file = 'http://' + window.location.hostname + '/file.js';
341
p.sourceCache[file] = ['var f2 = function() {', 'var b = 2;', '};'];
342
results.push(['run() ('+file+':1)', 'f2()@'+file+':1']);
344
if (mode == 'firefox') {
345
var f2 = function() {
349
results.push(p.run());
355
expect(results.length * 1);
356
for (var i = 0; i < results.length; ++i) {
357
//equals(p.guessFunctions(results[i]), '', 'debug');
358
equals(p.guessFunctions(results[i])[1].indexOf('f2'), 0, 'f2');
362
test("guessFunctions chrome", function() {
364
var mode = printStackTrace.implementation.prototype.mode();
365
var p = new printStackTrace.implementation();
367
var file = 'http://' + window.location.hostname + '/file.js';
368
p.sourceCache[file] = ['var f2 = function() {', 'var b = 2;', '};'];
369
results.push(['run() ('+file+':1:1)', 'f2() ('+file+':1:1)']);
371
if (mode == 'chrome') {
372
var f2 = function() {
376
results.push(p.run());
382
expect(results.length);
383
for (var i = 0; i < results.length; ++i) {
384
//equals((results[i]), '', 'debug');
385
equals(p.guessFunctions(results[i])[1].indexOf('f2()'), 0, 'f2');
389
test("guessFunctions opera", function() {
391
var mode = printStackTrace.implementation.prototype.mode();
392
var p = new printStackTrace.implementation();
394
var file = 'http://' + window.location.hostname + '/file.js';
395
p.sourceCache[file] = ['var f2 = function() {', 'var b = 2;', '};'];
396
results.push(['f2()@'+file+':2 -- code']);
398
if (mode == 'opera') {
399
var f2 = function() {
403
results.push(p.run());
409
expect(results.length * 1);
410
for (var i = 0; i < results.length; ++i) {
411
// equals(p.guessFunctions(results[i]), '', 'debug');
412
equals(p.guessFunctions(results[i])[0].indexOf('f2'), 0, 'f2');
416
test("guessFunctions other", function() {
418
var mode = printStackTrace.implementation.prototype.mode();
419
var p = new printStackTrace.implementation();
421
var file = 'http://' + window.location.hostname + '/file.js';
422
p.sourceCache[file] = ['var f2 = function() {', 'var b = 2;', '};'];
423
results.push(['{anonymous}()']);
425
if (mode == 'other') {
426
var f2 = function() {
427
try { (0)(); } catch(e) {
428
results.push(p.run());
434
expect(1 * results.length);
435
for (var i = 0; i < results.length; ++i) {
436
//equals((results[i]), '', 'debug');
437
equals(p.guessFunctions(results[i])[0].indexOf('{anonymous}'), 0, 'no file and line number on other');