|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 "use strict"; |
|
6 |
|
7 module.metadata = { |
|
8 "stability": "experimental" |
|
9 }; |
|
10 |
|
11 const { Cc, Ci, components } = require("chrome"); |
|
12 const { parseStack, sourceURI } = require("toolkit/loader"); |
|
13 const { readURISync } = require("../net/url"); |
|
14 |
|
15 exports.sourceURI = sourceURI |
|
16 |
|
17 function safeGetFileLine(path, line) { |
|
18 try { |
|
19 var scheme = require("../url").URL(path).scheme; |
|
20 // TODO: There should be an easier, more accurate way to figure out |
|
21 // what's the case here. |
|
22 if (!(scheme == "http" || scheme == "https")) |
|
23 return readURISync(path).split("\n")[line - 1]; |
|
24 } catch (e) {} |
|
25 return null; |
|
26 } |
|
27 |
|
28 function nsIStackFramesToJSON(frame) { |
|
29 var stack = []; |
|
30 |
|
31 while (frame) { |
|
32 if (frame.filename) { |
|
33 stack.unshift({ |
|
34 fileName: sourceURI(frame.filename), |
|
35 lineNumber: frame.lineNumber, |
|
36 name: frame.name |
|
37 }); |
|
38 } |
|
39 frame = frame.caller; |
|
40 } |
|
41 |
|
42 return stack; |
|
43 }; |
|
44 |
|
45 var fromException = exports.fromException = function fromException(e) { |
|
46 if (e instanceof Ci.nsIException) |
|
47 return nsIStackFramesToJSON(e.location); |
|
48 if (e.stack && e.stack.length) |
|
49 return parseStack(e.stack); |
|
50 if (e.fileName && typeof(e.lineNumber == "number")) |
|
51 return [{fileName: sourceURI(e.fileName), |
|
52 lineNumber: e.lineNumber, |
|
53 name: null}]; |
|
54 return []; |
|
55 }; |
|
56 |
|
57 var get = exports.get = function get() { |
|
58 return nsIStackFramesToJSON(components.stack.caller); |
|
59 }; |
|
60 |
|
61 var format = exports.format = function format(tbOrException) { |
|
62 if (tbOrException === undefined) { |
|
63 tbOrException = get(); |
|
64 tbOrException.pop(); |
|
65 } |
|
66 |
|
67 var tb; |
|
68 if (typeof(tbOrException) == "object" && |
|
69 tbOrException.constructor.name == "Array") |
|
70 tb = tbOrException; |
|
71 else |
|
72 tb = fromException(tbOrException); |
|
73 |
|
74 var lines = ["Traceback (most recent call last):"]; |
|
75 |
|
76 tb.forEach( |
|
77 function(frame) { |
|
78 if (!(frame.fileName || frame.lineNumber || frame.name)) |
|
79 return; |
|
80 |
|
81 lines.push(' File "' + frame.fileName + '", line ' + |
|
82 frame.lineNumber + ', in ' + frame.name); |
|
83 var sourceLine = safeGetFileLine(frame.fileName, frame.lineNumber); |
|
84 if (sourceLine) |
|
85 lines.push(' ' + sourceLine.trim()); |
|
86 }); |
|
87 |
|
88 return lines.join("\n"); |
|
89 }; |