1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 /** @suppress {duplicate} */
11 * A single stack-frame describing a call-site.
13 * fn: The calling function.
14 * url: URL component of the file name. For extensions, this will typically
15 * be chrome-extension://<id>
16 * file: The file containing the calling function.
17 * line: The line number.
18 * column: The column number.
34 * @param {Error=} opt_error If present, an Error object from which to extract
35 * the callstack; if not specified, the current callstack (excluding this
36 * constructor) will be used.
39 base
.Callstack = function(opt_error
) {
40 /** @type {Array<base.StackFrame>} */
43 this.getCallstackFromError_(opt_error
|| new Error());
45 // If no explicit Error was specified, remove this frame from the stack.
47 this.callstack
.splice(0, 1);
52 * @return {string} The callstack as a newline-separated string.
54 base
.Callstack
.prototype.toString = function() {
56 * @param {base.StackFrame} frame
59 var frameToString = function(frame
) {
60 var location
= frame
.file
+ ':' + frame
.line
+ ':' + frame
.column
;
62 location
= frame
.url
+ '/' + location
;
65 location
= ' (' + location
+ ')';
67 return frame
.fn
+ location
;
70 return this.callstack
.map(frameToString
).join('\n');
74 * Parse the callstack of the specified Error.
76 * @param {Error} error
79 base
.Callstack
.prototype.getCallstackFromError_ = function(error
) {
81 * @param {string} frame
82 * @return {base.StackFrame}
84 var stringToFrame = function(frame
) {
86 // Function name (optional) and location are separated by a space. If a
87 // function name is present, location is enclosed in parentheses.
88 var fnAndLocation
= frame
.split(' ');
89 var location
= fnAndLocation
.pop().replace(/[()]/g, '');
90 result
.fn
= fnAndLocation
.shift() || '';
91 // Location, line and column are separated by colons. Colons are also
92 // used to separate the protocol and URL, so there may be more than two
93 // colons in the location.
94 var fullUrlAndLineAndCol
= location
.split(':');
95 result
.column
= parseInt(fullUrlAndLineAndCol
.pop(), 10);
96 result
.line
= parseInt(fullUrlAndLineAndCol
.pop(), 10);
97 var fullUrl
= fullUrlAndLineAndCol
.join(':');
98 // URL and file are separated by slashes. Slashes also separate the protocol
100 var urlAndFile
= fullUrl
.split('/');
101 result
.file
= urlAndFile
.pop();
102 result
.url
= urlAndFile
.join('/');
106 var callstack
= error
.stack
107 .replace(/^\s+at\s+/gm, '') // Remove 'at' and indentation.
109 callstack
.splice(0, 1); // Remove 'Error'
110 this.callstack
= callstack
.map(stringToFrame
);