-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathconsoleHelper.ts
148 lines (129 loc) · 5.18 KB
/
consoleHelper.ts
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
138
139
140
141
142
143
144
145
146
147
148
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
import * as url from 'url';
import * as Utilities from './utilities';
export function formatConsoleMessage(m: WebKitProtocol.Console.Message, isClientPath :boolean = false): { text: string, isError: boolean } {
let outputText: string;
if (m.type === 'log') {
outputText = resolveParams(m);
if (m.source === 'network') {
outputText += ` (${m.url})`;
}
else if (m.source === 'console-api' && m.url) {
let fileName = m.url;
if (!isClientPath) {
const fileName = url.parse(m.url).pathname;
}
const output = `${fileName}:${m.line}:${m.column}`;
outputText += ` (${output})`;
return { text: outputText, isError: m.level === 'error' };
}
} else if (m.type === 'assert') {
outputText = 'Assertion failed';
if (m.parameters && m.parameters.length) {
outputText += ': ' + m.parameters.map(p => p.value).join(' ');
}
outputText += '\n' + stackTraceToString(m.stackTrace);
} else if (m.type === 'startGroup' || m.type === 'startGroupCollapsed') {
outputText = '‹Start group›';
if (m.text) {
// Or wherever the label is
outputText += ': ' + m.text;
}
} else if (m.type === 'endGroup') {
outputText = '‹End group›';
} else if (m.type === 'trace') {
outputText = 'console.trace()\n' + stackTraceToString(m.stackTrace);
} else {
// Some types we have to ignore
outputText = 'Unimplemented console API: ' + m.type;
}
return { text: outputText, isError: m.level === 'error' };
}
function resolveParams(m: WebKitProtocol.Console.Message): string {
if (!m.parameters || !m.parameters.length) {
return m.text;
}
const textParam = m.parameters[0];
let text = remoteObjectToString(textParam);
m.parameters.shift();
// Find all %s, %i, etc in the first parameter, which is always the main text. Strip %
let formatSpecifiers: string[] = [];
if (textParam.type === 'string') {
formatSpecifiers = textParam.value.match(/\%[sidfoOc]/g) || [];
formatSpecifiers = formatSpecifiers.map(spec => spec[1]);
}
// Append all parameters, formatting properly if there's a format specifier
m.parameters.forEach((param, i) => {
let formatted: any;
if (formatSpecifiers[i] === 's') {
formatted = param.value;
} else if (['i', 'd'].indexOf(formatSpecifiers[i]) >= 0) {
formatted = Math.floor(+param.value);
} else if (formatSpecifiers[i] === 'f') {
formatted = +param.value;
} else if (['o', 'O', 'c'].indexOf(formatSpecifiers[i]) >= 0) {
// um
formatted = param.value;
}
// If this param had a format specifier, search and replace it with the formatted param.
// Otherwise, append it to the end of the text
if (formatSpecifiers[i]) {
text = text.replace('%' + formatSpecifiers[i], formatted);
} else {
text += ' ' + remoteObjectToString(param);
}
});
return text;
}
function remoteObjectToString(obj: WebKitProtocol.Runtime.RemoteObject): string {
const result = Utilities.remoteObjectToValue(obj, /*stringify=*/false);
if (result.variableHandleRef) {
// The DebugProtocol console API doesn't support returning a variable reference, so do our best to
// build a useful string out of this object.
if (obj.subtype === 'array') {
return arrayRemoteObjToString(obj);
} else if (obj.preview && obj.preview.properties) {
let props: string = obj.preview.properties
.map(prop => {
let propStr = prop.name + ': ';
if (prop.type === 'string') {
propStr += `"${prop.value}"`;
} else {
propStr += prop.value;
}
return propStr;
})
.join(', ');
if (obj.preview.overflow) {
props += '…';
}
return `${obj.className} {${props}}`;
}
} else {
return result.value;
}
}
function arrayRemoteObjToString(obj: WebKitProtocol.Runtime.RemoteObject): string {
if (obj.preview && obj.preview.properties) {
let props: string = obj.preview.properties
.map(prop => prop.value)
.join(', ');
if (obj.preview.overflow) {
props += '…';
}
return `[${props}]`;
} else {
return obj.description;
}
}
function stackTraceToString(stackTrace: WebKitProtocol.Console.StackTrace): string {
return stackTrace
.map(frame => {
const fnName = frame.functionName || (frame.url ? '(anonymous)' : '(eval)');
const fileName = frame.url ? url.parse(frame.url).pathname : '(eval)';
return ` ${fnName} @${fileName}:${frame.lineNumber}`;
})
.join('\n');
}