Roll src/third_party/WebKit 3529d49:06e8485 (svn 202554:202555)
[chromium-blink-merge.git] / remoting / webapp / base / js / callstack.js
blobd6e332583622c6c9730f7268feeee8edeef58eb4
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.
5 'use strict';
7 /** @suppress {duplicate} */
8 var base = base || {};
10 /**
11  * A single stack-frame describing a call-site.
12  *
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.
19  *
20  * @typedef {{
21  *   fn: string,
22  *   url: string,
23  *   file: string,
24  *   line: number,
25  *   column: number
26  * }}
27  */
28 base.StackFrame;
31 (function() {
33 /**
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.
37  * @constructor
38  */
39 base.Callstack = function(opt_error) {
40   /** @type {Array<base.StackFrame>} */
41   this.callstack = [];
43   this.getCallstackFromError_(opt_error || new Error());
45   // If no explicit Error was specified, remove this frame from the stack.
46   if (!opt_error) {
47     this.callstack.splice(0, 1);
48   }
51 /**
52  * @return {string} The callstack as a newline-separated string.
53  */
54 base.Callstack.prototype.toString = function() {
55   /**
56    * @param {base.StackFrame} frame
57    * @return {string}
58    */
59   var frameToString = function(frame) {
60     var location = frame.file + ':' + frame.line + ':' + frame.column;
61     if (frame.url) {
62       location = frame.url + '/' + location;
63     }
64     if (frame.fn) {
65       location = ' (' + location + ')';
66     }
67     return frame.fn + location;
68   }
70   return this.callstack.map(frameToString).join('\n');
73 /**
74  * Parse the callstack of the specified Error.
75  *
76  * @param {Error} error
77  * @private
78  */
79 base.Callstack.prototype.getCallstackFromError_ = function(error) {
80   /**
81    * @param {string} frame
82    * @return {base.StackFrame}
83    */
84   var stringToFrame = function(frame) {
85     var result = {};
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
99     // and URL.
100     var urlAndFile = fullUrl.split('/');
101     result.file = urlAndFile.pop();
102     result.url = urlAndFile.join('/');
103     return result;
104   };
106   var callstack = error.stack
107       .replace(/^\s+at\s+/gm, '') // Remove 'at' and indentation.
108       .split('\n');
109   callstack.splice(0, 1); // Remove 'Error'
110   this.callstack = callstack.map(stringToFrame);
113 })();