blob: b2ad49b3dadd84594f7f142547e12a91a5ec6657 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2009 Joseph Pecoraro
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30/**
31 * @implements {Console.ConsoleViewportElement}
32 * @unrestricted
33 */
34Console.ConsoleViewMessage = class {
35 /**
36 * @param {!SDK.ConsoleMessage} consoleMessage
37 * @param {!Components.Linkifier} linkifier
38 * @param {!ProductRegistry.BadgePool} badgePool
39 * @param {number} nestingLevel
Erik Luo840be6b2018-12-03 20:54:2740 * @param {function(!Common.Event)} onResize
Blink Reformat4c46d092018-04-07 15:32:3741 */
Erik Luo840be6b2018-12-03 20:54:2742 constructor(consoleMessage, linkifier, badgePool, nestingLevel, onResize) {
Blink Reformat4c46d092018-04-07 15:32:3743 this._message = consoleMessage;
44 this._linkifier = linkifier;
45 this._badgePool = badgePool;
46 this._repeatCount = 1;
47 this._closeGroupDecorationCount = 0;
48 this._nestingLevel = nestingLevel;
Erik Luo31c21f62018-12-13 03:39:3949 /** @type {!Array<{element: !Element, forceSelect: function()}>} */
Erik Luo383f21d2018-11-07 23:16:3750 this._selectableChildren = [];
Erik Luo840be6b2018-12-03 20:54:2751 this._messageResized = onResize;
Blink Reformat4c46d092018-04-07 15:32:3752
53 /** @type {?DataGrid.DataGrid} */
54 this._dataGrid = null;
55 this._previewFormatter = new ObjectUI.RemoteObjectPreviewFormatter();
56 this._searchRegex = null;
57 /** @type {?UI.Icon} */
58 this._messageLevelIcon = null;
Erik Luo8ef5d0c2018-09-25 21:16:0059 this._traceExpanded = false;
60 /** @type {?function(boolean)} */
61 this._expandTrace = null;
John Emaubb2897a2019-10-04 17:37:3262 /** @type {?Element} */
63 this._anchorElement = null;
Blink Reformat4c46d092018-04-07 15:32:3764 }
65
66 /**
67 * @override
68 * @return {!Element}
69 */
70 element() {
71 return this.toMessageElement();
72 }
73
74 /**
Blink Reformat4c46d092018-04-07 15:32:3775 * @override
76 */
77 wasShown() {
Tim van der Lippe1d6e57a2019-09-30 11:55:3478 if (this._dataGrid) {
Blink Reformat4c46d092018-04-07 15:32:3779 this._dataGrid.updateWidths();
Tim van der Lippe1d6e57a2019-09-30 11:55:3480 }
Blink Reformat4c46d092018-04-07 15:32:3781 this._isVisible = true;
82 }
83
84 onResize() {
Tim van der Lippe1d6e57a2019-09-30 11:55:3485 if (!this._isVisible) {
Blink Reformat4c46d092018-04-07 15:32:3786 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:3487 }
88 if (this._dataGrid) {
Blink Reformat4c46d092018-04-07 15:32:3789 this._dataGrid.onResize();
Tim van der Lippe1d6e57a2019-09-30 11:55:3490 }
Blink Reformat4c46d092018-04-07 15:32:3791 }
92
93 /**
94 * @override
95 */
96 willHide() {
97 this._isVisible = false;
Erik Luo4b002322018-07-30 21:23:3198 this._cachedHeight = this.element().offsetHeight;
Blink Reformat4c46d092018-04-07 15:32:3799 }
100
101 /**
102 * @return {number}
103 */
104 fastHeight() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34105 if (this._cachedHeight) {
Blink Reformat4c46d092018-04-07 15:32:37106 return this._cachedHeight;
Tim van der Lippe1d6e57a2019-09-30 11:55:34107 }
Blink Reformat4c46d092018-04-07 15:32:37108 // This value reflects the 18px min-height of .console-message, plus the
109 // 1px border of .console-message-wrapper. Keep in sync with consoleView.css.
110 const defaultConsoleRowHeight = 19;
111 if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
112 const table = this._message.parameters[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34113 if (table && table.preview) {
Blink Reformat4c46d092018-04-07 15:32:37114 return defaultConsoleRowHeight * table.preview.properties.length;
Tim van der Lippe1d6e57a2019-09-30 11:55:34115 }
Blink Reformat4c46d092018-04-07 15:32:37116 }
117 return defaultConsoleRowHeight;
118 }
119
120 /**
121 * @return {!SDK.ConsoleMessage}
122 */
123 consoleMessage() {
124 return this._message;
125 }
126
127 /**
128 * @return {!Element}
129 */
130 _buildTableMessage() {
131 const formattedMessage = createElementWithClass('span', 'source-code');
Erik Luo5976c8c2018-07-24 02:03:09132 this._anchorElement = this._buildMessageAnchor();
Tim van der Lippe1d6e57a2019-09-30 11:55:34133 if (this._anchorElement) {
Erik Luo5976c8c2018-07-24 02:03:09134 formattedMessage.appendChild(this._anchorElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34135 }
Blink Reformat4c46d092018-04-07 15:32:37136 const badgeElement = this._buildMessageBadge();
Tim van der Lippe1d6e57a2019-09-30 11:55:34137 if (badgeElement) {
Blink Reformat4c46d092018-04-07 15:32:37138 formattedMessage.appendChild(badgeElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34139 }
Blink Reformat4c46d092018-04-07 15:32:37140
141 let table = this._message.parameters && this._message.parameters.length ? this._message.parameters[0] : null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34142 if (table) {
Blink Reformat4c46d092018-04-07 15:32:37143 table = this._parameterToRemoteObject(table);
Tim van der Lippe1d6e57a2019-09-30 11:55:34144 }
145 if (!table || !table.preview) {
Erik Luo16e3e382018-11-09 02:56:01146 return this._buildMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:34147 }
Blink Reformat4c46d092018-04-07 15:32:37148
149 const rawValueColumnSymbol = Symbol('rawValueColumn');
150 const columnNames = [];
151 const preview = table.preview;
152 const rows = [];
153 for (let i = 0; i < preview.properties.length; ++i) {
154 const rowProperty = preview.properties[i];
155 let rowSubProperties;
Tim van der Lippe1d6e57a2019-09-30 11:55:34156 if (rowProperty.valuePreview) {
Blink Reformat4c46d092018-04-07 15:32:37157 rowSubProperties = rowProperty.valuePreview.properties;
Tim van der Lippe1d6e57a2019-09-30 11:55:34158 } else if (rowProperty.value) {
Blink Reformat4c46d092018-04-07 15:32:37159 rowSubProperties = [{name: rawValueColumnSymbol, type: rowProperty.type, value: rowProperty.value}];
Tim van der Lippe1d6e57a2019-09-30 11:55:34160 } else {
Blink Reformat4c46d092018-04-07 15:32:37161 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34162 }
Blink Reformat4c46d092018-04-07 15:32:37163
164 const rowValue = {};
165 const maxColumnsToRender = 20;
166 for (let j = 0; j < rowSubProperties.length; ++j) {
167 const cellProperty = rowSubProperties[j];
168 let columnRendered = columnNames.indexOf(cellProperty.name) !== -1;
169 if (!columnRendered) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34170 if (columnNames.length === maxColumnsToRender) {
Blink Reformat4c46d092018-04-07 15:32:37171 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34172 }
Blink Reformat4c46d092018-04-07 15:32:37173 columnRendered = true;
174 columnNames.push(cellProperty.name);
175 }
176
177 if (columnRendered) {
178 const cellElement = this._renderPropertyPreviewOrAccessor(table, [rowProperty, cellProperty]);
179 cellElement.classList.add('console-message-nowrap-below');
180 rowValue[cellProperty.name] = cellElement;
181 }
182 }
183 rows.push([rowProperty.name, rowValue]);
184 }
185
186 const flatValues = [];
187 for (let i = 0; i < rows.length; ++i) {
188 const rowName = rows[i][0];
189 const rowValue = rows[i][1];
190 flatValues.push(rowName);
Tim van der Lippe1d6e57a2019-09-30 11:55:34191 for (let j = 0; j < columnNames.length; ++j) {
Blink Reformat4c46d092018-04-07 15:32:37192 flatValues.push(rowValue[columnNames[j]]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34193 }
Blink Reformat4c46d092018-04-07 15:32:37194 }
195 columnNames.unshift(Common.UIString('(index)'));
196 const columnDisplayNames = columnNames.map(name => name === rawValueColumnSymbol ? Common.UIString('Value') : name);
197
198 if (flatValues.length) {
199 this._dataGrid = DataGrid.SortableDataGrid.create(columnDisplayNames, flatValues);
200 this._dataGrid.setStriped(true);
Anubha Mathurfbacf4e2019-10-28 19:08:03201 this._dataGrid.setFocusable(false);
Blink Reformat4c46d092018-04-07 15:32:37202
203 const formattedResult = createElementWithClass('span', 'console-message-text');
204 const tableElement = formattedResult.createChild('div', 'console-message-formatted-table');
205 const dataGridContainer = tableElement.createChild('span');
206 tableElement.appendChild(this._formatParameter(table, true, false));
207 dataGridContainer.appendChild(this._dataGrid.element);
208 formattedMessage.appendChild(formattedResult);
209 this._dataGrid.renderInline();
210 }
211 return formattedMessage;
212 }
213
214 /**
215 * @return {!Element}
216 */
217 _buildMessage() {
218 let messageElement;
219 let messageText = this._message.messageText;
220 if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
221 switch (this._message.type) {
222 case SDK.ConsoleMessage.MessageType.Trace:
223 messageElement = this._format(this._message.parameters || ['console.trace']);
224 break;
225 case SDK.ConsoleMessage.MessageType.Clear:
226 messageElement = createElementWithClass('span', 'console-info');
Tim van der Lippe1d6e57a2019-09-30 11:55:34227 if (Common.moduleSetting('preserveConsoleLog').get()) {
Blink Reformat4c46d092018-04-07 15:32:37228 messageElement.textContent = Common.UIString('console.clear() was prevented due to \'Preserve log\'');
Tim van der Lippe1d6e57a2019-09-30 11:55:34229 } else {
Blink Reformat4c46d092018-04-07 15:32:37230 messageElement.textContent = Common.UIString('Console was cleared');
Tim van der Lippe1d6e57a2019-09-30 11:55:34231 }
Blink Reformat4c46d092018-04-07 15:32:37232 messageElement.title =
Lorne Mitchell81a1a972019-03-06 18:13:13233 ls`Clear all messages with ${UI.shortcutRegistry.shortcutTitleForAction('console.clear')}`;
Blink Reformat4c46d092018-04-07 15:32:37234 break;
Blink Reformat4c46d092018-04-07 15:32:37235 case SDK.ConsoleMessage.MessageType.Dir: {
236 const obj = this._message.parameters ? this._message.parameters[0] : undefined;
237 const args = ['%O', obj];
238 messageElement = this._format(args);
239 break;
240 }
241 case SDK.ConsoleMessage.MessageType.Profile:
242 case SDK.ConsoleMessage.MessageType.ProfileEnd:
243 messageElement = this._format([messageText]);
244 break;
Pavel Feldman9f0f0a32018-12-18 02:09:13245 case SDK.ConsoleMessage.MessageType.Assert:
246 this._messagePrefix = ls`Assertion failed: `;
247 // Fall through.
Blink Reformat4c46d092018-04-07 15:32:37248 default: {
249 if (this._message.parameters && this._message.parameters.length === 1 &&
Tim van der Lippe1d6e57a2019-09-30 11:55:34250 this._message.parameters[0].type === 'string') {
Blink Reformat4c46d092018-04-07 15:32:37251 messageElement = this._tryFormatAsError(/** @type {string} */ (this._message.parameters[0].value));
Tim van der Lippe1d6e57a2019-09-30 11:55:34252 }
Blink Reformat4c46d092018-04-07 15:32:37253 const args = this._message.parameters || [messageText];
254 messageElement = messageElement || this._format(args);
255 }
256 }
257 } else {
Erik Luofc2214f2018-11-21 19:54:58258 if (this._message.source === SDK.ConsoleMessage.MessageSource.Network) {
259 messageElement = this._formatAsNetworkRequest() || this._format([messageText]);
260 } else {
Blink Reformat4c46d092018-04-07 15:32:37261 const messageInParameters =
262 this._message.parameters && messageText === /** @type {string} */ (this._message.parameters[0]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34263 if (this._message.source === SDK.ConsoleMessage.MessageSource.Violation) {
Blink Reformat4c46d092018-04-07 15:32:37264 messageText = Common.UIString('[Violation] %s', messageText);
Tim van der Lippe1d6e57a2019-09-30 11:55:34265 } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Intervention) {
Blink Reformat4c46d092018-04-07 15:32:37266 messageText = Common.UIString('[Intervention] %s', messageText);
Tim van der Lippe1d6e57a2019-09-30 11:55:34267 } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation) {
Blink Reformat4c46d092018-04-07 15:32:37268 messageText = Common.UIString('[Deprecation] %s', messageText);
Tim van der Lippe1d6e57a2019-09-30 11:55:34269 }
Blink Reformat4c46d092018-04-07 15:32:37270 const args = this._message.parameters || [messageText];
Tim van der Lippe1d6e57a2019-09-30 11:55:34271 if (messageInParameters) {
Blink Reformat4c46d092018-04-07 15:32:37272 args[0] = messageText;
Tim van der Lippe1d6e57a2019-09-30 11:55:34273 }
Blink Reformat4c46d092018-04-07 15:32:37274 messageElement = this._format(args);
275 }
276 }
277 messageElement.classList.add('console-message-text');
278
279 const formattedMessage = createElementWithClass('span', 'source-code');
Erik Luo5976c8c2018-07-24 02:03:09280 this._anchorElement = this._buildMessageAnchor();
Tim van der Lippe1d6e57a2019-09-30 11:55:34281 if (this._anchorElement) {
Erik Luo5976c8c2018-07-24 02:03:09282 formattedMessage.appendChild(this._anchorElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34283 }
Blink Reformat4c46d092018-04-07 15:32:37284 const badgeElement = this._buildMessageBadge();
Tim van der Lippe1d6e57a2019-09-30 11:55:34285 if (badgeElement) {
Blink Reformat4c46d092018-04-07 15:32:37286 formattedMessage.appendChild(badgeElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34287 }
Blink Reformat4c46d092018-04-07 15:32:37288 formattedMessage.appendChild(messageElement);
289 return formattedMessage;
290 }
291
292 /**
293 * @return {?Element}
294 */
Erik Luofc2214f2018-11-21 19:54:58295 _formatAsNetworkRequest() {
296 const request = SDK.NetworkLog.requestForConsoleMessage(this._message);
Tim van der Lippe1d6e57a2019-09-30 11:55:34297 if (!request) {
Erik Luofc2214f2018-11-21 19:54:58298 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34299 }
Erik Luofc2214f2018-11-21 19:54:58300 const messageElement = createElement('span');
301 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
302 messageElement.createTextChild(request.requestMethod + ' ');
Erik Luo182bece2018-11-29 03:15:22303 const linkElement = Components.Linkifier.linkifyRevealable(request, request.url(), request.url());
304 // Focus is handled by the viewport.
305 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:39306 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo182bece2018-11-29 03:15:22307 messageElement.appendChild(linkElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34308 if (request.failed) {
Erik Luofc2214f2018-11-21 19:54:58309 messageElement.createTextChildren(' ', request.localizedFailDescription);
Tim van der Lippe1d6e57a2019-09-30 11:55:34310 }
311 if (request.statusCode !== 0) {
Erik Luofc2214f2018-11-21 19:54:58312 messageElement.createTextChildren(' ', String(request.statusCode));
Tim van der Lippe1d6e57a2019-09-30 11:55:34313 }
314 if (request.statusText) {
Erik Luofc2214f2018-11-21 19:54:58315 messageElement.createTextChildren(' (', request.statusText, ')');
Tim van der Lippe1d6e57a2019-09-30 11:55:34316 }
Erik Luofc2214f2018-11-21 19:54:58317 } else {
Erik Luoad5f3942019-03-26 20:53:44318 const messageText = this._message.messageText;
319 const fragment = this._linkifyWithCustomLinkifier(messageText, (text, url, lineNumber, columnNumber) => {
320 let linkElement;
321 if (url === request.url()) {
322 linkElement = Components.Linkifier.linkifyRevealable(
323 /** @type {!SDK.NetworkRequest} */ (request), url, request.url());
324 } else {
325 linkElement = Components.Linkifier.linkifyURL(url, {text, lineNumber, columnNumber});
326 }
Erik Luo182bece2018-11-29 03:15:22327 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:39328 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo182bece2018-11-29 03:15:22329 return linkElement;
330 });
Erik Luofc2214f2018-11-21 19:54:58331 messageElement.appendChild(fragment);
332 }
333 return messageElement;
334 }
335
336 /**
337 * @return {?Element}
338 */
Blink Reformat4c46d092018-04-07 15:32:37339 _buildMessageAnchor() {
340 let anchorElement = null;
341 if (this._message.scriptId) {
342 anchorElement = this._linkifyScriptId(
343 this._message.scriptId, this._message.url || '', this._message.line, this._message.column);
344 } else if (this._message.stackTrace && this._message.stackTrace.callFrames.length) {
345 anchorElement = this._linkifyStackTraceTopFrame(this._message.stackTrace);
346 } else if (this._message.url && this._message.url !== 'undefined') {
347 anchorElement = this._linkifyLocation(this._message.url, this._message.line, this._message.column);
348 }
349
350 // Append a space to prevent the anchor text from being glued to the console message when the user selects and copies the console messages.
351 if (anchorElement) {
John Emauf7e30fb2019-10-04 19:12:32352 anchorElement.tabIndex = -1;
353 this._selectableChildren.push({
354 element: anchorElement,
355 forceSelect: () => anchorElement.focus(),
356 });
Blink Reformat4c46d092018-04-07 15:32:37357 const anchorWrapperElement = createElementWithClass('span', 'console-message-anchor');
358 anchorWrapperElement.appendChild(anchorElement);
359 anchorWrapperElement.createTextChild(' ');
360 return anchorWrapperElement;
361 }
362 return null;
363 }
364
365 /**
366 * @return {?Element}
367 */
368 _buildMessageBadge() {
369 const badgeElement = this._badgeElement();
Tim van der Lippe1d6e57a2019-09-30 11:55:34370 if (!badgeElement) {
Blink Reformat4c46d092018-04-07 15:32:37371 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34372 }
Blink Reformat4c46d092018-04-07 15:32:37373 badgeElement.classList.add('console-message-badge');
374 return badgeElement;
375 }
376
377 /**
378 * @return {?Element}
379 */
380 _badgeElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34381 if (this._message._url) {
Blink Reformat4c46d092018-04-07 15:32:37382 return this._badgePool.badgeForURL(new Common.ParsedURL(this._message._url));
Tim van der Lippe1d6e57a2019-09-30 11:55:34383 }
Blink Reformat4c46d092018-04-07 15:32:37384 if (this._message.stackTrace) {
385 let stackTrace = this._message.stackTrace;
386 while (stackTrace) {
387 for (const callFrame of this._message.stackTrace.callFrames) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34388 if (callFrame.url) {
Blink Reformat4c46d092018-04-07 15:32:37389 return this._badgePool.badgeForURL(new Common.ParsedURL(callFrame.url));
Tim van der Lippe1d6e57a2019-09-30 11:55:34390 }
Blink Reformat4c46d092018-04-07 15:32:37391 }
392 stackTrace = stackTrace.parent;
393 }
394 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34395 if (!this._message.executionContextId) {
Blink Reformat4c46d092018-04-07 15:32:37396 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34397 }
Blink Reformat4c46d092018-04-07 15:32:37398 const runtimeModel = this._message.runtimeModel();
Tim van der Lippe1d6e57a2019-09-30 11:55:34399 if (!runtimeModel) {
Blink Reformat4c46d092018-04-07 15:32:37400 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34401 }
Blink Reformat4c46d092018-04-07 15:32:37402 const executionContext = runtimeModel.executionContext(this._message.executionContextId);
Tim van der Lippe1d6e57a2019-09-30 11:55:34403 if (!executionContext || !executionContext.frameId) {
Blink Reformat4c46d092018-04-07 15:32:37404 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34405 }
Blink Reformat4c46d092018-04-07 15:32:37406 const resourceTreeModel = executionContext.target().model(SDK.ResourceTreeModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34407 if (!resourceTreeModel) {
Blink Reformat4c46d092018-04-07 15:32:37408 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34409 }
Blink Reformat4c46d092018-04-07 15:32:37410 const frame = resourceTreeModel.frameForId(executionContext.frameId);
Tim van der Lippe1d6e57a2019-09-30 11:55:34411 if (!frame || !frame.parentFrame) {
Blink Reformat4c46d092018-04-07 15:32:37412 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34413 }
Blink Reformat4c46d092018-04-07 15:32:37414 return this._badgePool.badgeForFrame(frame);
415 }
416
417 /**
418 * @return {!Element}
419 */
420 _buildMessageWithStackTrace() {
421 const toggleElement = createElementWithClass('div', 'console-message-stack-trace-toggle');
422 const contentElement = toggleElement.createChild('div', 'console-message-stack-trace-wrapper');
423
424 const messageElement = this._buildMessage();
425 const icon = UI.Icon.create('smallicon-triangle-right', 'console-message-expand-icon');
426 const clickableElement = contentElement.createChild('div');
427 clickableElement.appendChild(icon);
Erik Luob5bfff42018-09-20 02:52:39428 // Intercept focus to avoid highlight on click.
429 clickableElement.tabIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:37430
431 clickableElement.appendChild(messageElement);
432 const stackTraceElement = contentElement.createChild('div');
433 const stackTracePreview = Components.JSPresentationUtils.buildStackTracePreviewContents(
434 this._message.runtimeModel().target(), this._linkifier, this._message.stackTrace);
Erik Luo182bece2018-11-29 03:15:22435 stackTraceElement.appendChild(stackTracePreview.element);
436 for (const linkElement of stackTracePreview.links) {
437 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:39438 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo182bece2018-11-29 03:15:22439 }
Blink Reformat4c46d092018-04-07 15:32:37440 stackTraceElement.classList.add('hidden');
Erik Luo8ef5d0c2018-09-25 21:16:00441 this._expandTrace = expand => {
Blink Reformat4c46d092018-04-07 15:32:37442 icon.setIconType(expand ? 'smallicon-triangle-down' : 'smallicon-triangle-right');
443 stackTraceElement.classList.toggle('hidden', !expand);
Erik Luo8ef5d0c2018-09-25 21:16:00444 this._traceExpanded = expand;
445 };
Blink Reformat4c46d092018-04-07 15:32:37446
447 /**
Erik Luo8ef5d0c2018-09-25 21:16:00448 * @this {!Console.ConsoleViewMessage}
Blink Reformat4c46d092018-04-07 15:32:37449 * @param {?Event} event
450 */
451 function toggleStackTrace(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34452 if (UI.isEditing() || contentElement.hasSelection()) {
Blink Reformat4c46d092018-04-07 15:32:37453 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34454 }
Erik Luo8ef5d0c2018-09-25 21:16:00455 this._expandTrace(stackTraceElement.classList.contains('hidden'));
Blink Reformat4c46d092018-04-07 15:32:37456 event.consume();
457 }
458
Erik Luo8ef5d0c2018-09-25 21:16:00459 clickableElement.addEventListener('click', toggleStackTrace.bind(this), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34460 if (this._message.type === SDK.ConsoleMessage.MessageType.Trace) {
Erik Luo8ef5d0c2018-09-25 21:16:00461 this._expandTrace(true);
Tim van der Lippe1d6e57a2019-09-30 11:55:34462 }
Blink Reformat4c46d092018-04-07 15:32:37463
Erik Luo8ef5d0c2018-09-25 21:16:00464 toggleElement._expandStackTraceForTest = this._expandTrace.bind(this, true);
Blink Reformat4c46d092018-04-07 15:32:37465 return toggleElement;
466 }
467
468 /**
469 * @param {string} url
470 * @param {number} lineNumber
471 * @param {number} columnNumber
472 * @return {?Element}
473 */
474 _linkifyLocation(url, lineNumber, columnNumber) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34475 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37476 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34477 }
Blink Reformat4c46d092018-04-07 15:32:37478 return this._linkifier.linkifyScriptLocation(
479 this._message.runtimeModel().target(), null, url, lineNumber, columnNumber);
480 }
481
482 /**
483 * @param {!Protocol.Runtime.StackTrace} stackTrace
484 * @return {?Element}
485 */
486 _linkifyStackTraceTopFrame(stackTrace) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34487 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37488 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34489 }
Blink Reformat4c46d092018-04-07 15:32:37490 return this._linkifier.linkifyStackTraceTopFrame(this._message.runtimeModel().target(), stackTrace);
491 }
492
493 /**
494 * @param {string} scriptId
495 * @param {string} url
496 * @param {number} lineNumber
497 * @param {number} columnNumber
498 * @return {?Element}
499 */
500 _linkifyScriptId(scriptId, url, lineNumber, columnNumber) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34501 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37502 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34503 }
Blink Reformat4c46d092018-04-07 15:32:37504 return this._linkifier.linkifyScriptLocation(
505 this._message.runtimeModel().target(), scriptId, url, lineNumber, columnNumber);
506 }
507
508 /**
509 * @param {!SDK.RemoteObject|!Protocol.Runtime.RemoteObject|string} parameter
510 * @return {!SDK.RemoteObject}
511 */
512 _parameterToRemoteObject(parameter) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34513 if (parameter instanceof SDK.RemoteObject) {
Blink Reformat4c46d092018-04-07 15:32:37514 return parameter;
Tim van der Lippe1d6e57a2019-09-30 11:55:34515 }
Blink Reformat4c46d092018-04-07 15:32:37516 const runtimeModel = this._message.runtimeModel();
Tim van der Lippe1d6e57a2019-09-30 11:55:34517 if (!runtimeModel) {
Blink Reformat4c46d092018-04-07 15:32:37518 return SDK.RemoteObject.fromLocalObject(parameter);
Tim van der Lippe1d6e57a2019-09-30 11:55:34519 }
520 if (typeof parameter === 'object') {
Blink Reformat4c46d092018-04-07 15:32:37521 return runtimeModel.createRemoteObject(parameter);
Tim van der Lippe1d6e57a2019-09-30 11:55:34522 }
Blink Reformat4c46d092018-04-07 15:32:37523 return runtimeModel.createRemoteObjectFromPrimitiveValue(parameter);
524 }
525
526 /**
527 * @param {!Array.<!SDK.RemoteObject|string>} rawParameters
528 * @return {!Element}
529 */
530 _format(rawParameters) {
531 // This node is used like a Builder. Values are continually appended onto it.
532 const formattedResult = createElement('span');
Tim van der Lippe1d6e57a2019-09-30 11:55:34533 if (this._messagePrefix) {
Pavel Feldman9f0f0a32018-12-18 02:09:13534 formattedResult.createChild('span').textContent = this._messagePrefix;
Tim van der Lippe1d6e57a2019-09-30 11:55:34535 }
536 if (!rawParameters.length) {
Blink Reformat4c46d092018-04-07 15:32:37537 return formattedResult;
Tim van der Lippe1d6e57a2019-09-30 11:55:34538 }
Blink Reformat4c46d092018-04-07 15:32:37539
540 // Formatting code below assumes that parameters are all wrappers whereas frontend console
541 // API allows passing arbitrary values as messages (strings, numbers, etc.). Wrap them here.
542 // FIXME: Only pass runtime wrappers here.
543 let parameters = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:34544 for (let i = 0; i < rawParameters.length; ++i) {
Blink Reformat4c46d092018-04-07 15:32:37545 parameters[i] = this._parameterToRemoteObject(rawParameters[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34546 }
Blink Reformat4c46d092018-04-07 15:32:37547
548 // There can be string log and string eval result. We distinguish between them based on message type.
549 const shouldFormatMessage =
550 SDK.RemoteObject.type((/** @type {!Array.<!SDK.RemoteObject>} **/ (parameters))[0]) === 'string' &&
551 (this._message.type !== SDK.ConsoleMessage.MessageType.Result ||
552 this._message.level === SDK.ConsoleMessage.MessageLevel.Error);
553
554 // Multiple parameters with the first being a format string. Save unused substitutions.
555 if (shouldFormatMessage) {
556 const result = this._formatWithSubstitutionString(
557 /** @type {string} **/ (parameters[0].description), parameters.slice(1), formattedResult);
558 parameters = result.unusedSubstitutions;
Tim van der Lippe1d6e57a2019-09-30 11:55:34559 if (parameters.length) {
Blink Reformat4c46d092018-04-07 15:32:37560 formattedResult.createTextChild(' ');
Tim van der Lippe1d6e57a2019-09-30 11:55:34561 }
Blink Reformat4c46d092018-04-07 15:32:37562 }
563
564 // Single parameter, or unused substitutions from above.
565 for (let i = 0; i < parameters.length; ++i) {
566 // Inline strings when formatting.
Tim van der Lippe1d6e57a2019-09-30 11:55:34567 if (shouldFormatMessage && parameters[i].type === 'string') {
Erik Luo383f21d2018-11-07 23:16:37568 formattedResult.appendChild(this._linkifyStringAsFragment(parameters[i].description));
Tim van der Lippe1d6e57a2019-09-30 11:55:34569 } else {
Blink Reformat4c46d092018-04-07 15:32:37570 formattedResult.appendChild(this._formatParameter(parameters[i], false, true));
Tim van der Lippe1d6e57a2019-09-30 11:55:34571 }
572 if (i < parameters.length - 1) {
Blink Reformat4c46d092018-04-07 15:32:37573 formattedResult.createTextChild(' ');
Tim van der Lippe1d6e57a2019-09-30 11:55:34574 }
Blink Reformat4c46d092018-04-07 15:32:37575 }
576 return formattedResult;
577 }
578
579 /**
580 * @param {!SDK.RemoteObject} output
581 * @param {boolean=} forceObjectFormat
582 * @param {boolean=} includePreview
583 * @return {!Element}
584 */
585 _formatParameter(output, forceObjectFormat, includePreview) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34586 if (output.customPreview()) {
Blink Reformat4c46d092018-04-07 15:32:37587 return (new ObjectUI.CustomPreviewComponent(output)).element;
Tim van der Lippe1d6e57a2019-09-30 11:55:34588 }
Blink Reformat4c46d092018-04-07 15:32:37589
590 const type = forceObjectFormat ? 'object' : (output.subtype || output.type);
591 let element;
592 switch (type) {
593 case 'error':
594 element = this._formatParameterAsError(output);
595 break;
596 case 'function':
597 element = this._formatParameterAsFunction(output, includePreview);
598 break;
599 case 'array':
600 case 'arraybuffer':
601 case 'blob':
602 case 'dataview':
603 case 'generator':
604 case 'iterator':
605 case 'map':
606 case 'object':
607 case 'promise':
608 case 'proxy':
609 case 'set':
610 case 'typedarray':
611 case 'weakmap':
612 case 'weakset':
613 element = this._formatParameterAsObject(output, includePreview);
614 break;
615 case 'node':
616 element = output.isNode() ? this._formatParameterAsNode(output) : this._formatParameterAsObject(output, false);
617 break;
618 case 'string':
619 element = this._formatParameterAsString(output);
620 break;
621 case 'boolean':
622 case 'date':
623 case 'null':
624 case 'number':
625 case 'regexp':
626 case 'symbol':
627 case 'undefined':
628 case 'bigint':
629 element = this._formatParameterAsValue(output);
630 break;
631 default:
632 element = this._formatParameterAsValue(output);
633 console.error('Tried to format remote object of unknown type.');
634 }
635 element.classList.add('object-value-' + type);
636 element.classList.add('source-code');
637 return element;
638 }
639
640 /**
641 * @param {!SDK.RemoteObject} obj
642 * @return {!Element}
643 */
644 _formatParameterAsValue(obj) {
645 const result = createElement('span');
646 const description = obj.description || '';
Tim van der Lippe1d6e57a2019-09-30 11:55:34647 if (description.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Erik Luo5fb33bd2018-06-04 23:23:52648 result.appendChild(UI.createExpandableText(description, Console.ConsoleViewMessage._LongStringVisibleLength));
Tim van der Lippe1d6e57a2019-09-30 11:55:34649 } else {
Blink Reformat4c46d092018-04-07 15:32:37650 result.createTextChild(description);
Tim van der Lippe1d6e57a2019-09-30 11:55:34651 }
652 if (obj.objectId) {
Blink Reformat4c46d092018-04-07 15:32:37653 result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, obj), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34654 }
Blink Reformat4c46d092018-04-07 15:32:37655 return result;
656 }
657
658 /**
659 * @param {!SDK.RemoteObject} obj
660 * @param {boolean=} includePreview
661 * @return {!Element}
662 */
663 _formatParameterAsObject(obj, includePreview) {
664 const titleElement = createElementWithClass('span', 'console-object');
665 if (includePreview && obj.preview) {
666 titleElement.classList.add('console-object-preview');
667 this._previewFormatter.appendObjectPreview(titleElement, obj.preview, false /* isEntry */);
668 } else if (obj.type === 'function') {
669 const functionElement = titleElement.createChild('span');
670 ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(obj, functionElement, false);
671 titleElement.classList.add('object-value-function');
672 } else {
673 titleElement.createTextChild(obj.description || '');
674 }
675
Tim van der Lippe1d6e57a2019-09-30 11:55:34676 if (!obj.hasChildren || obj.customPreview()) {
Blink Reformat4c46d092018-04-07 15:32:37677 return titleElement;
Tim van der Lippe1d6e57a2019-09-30 11:55:34678 }
Blink Reformat4c46d092018-04-07 15:32:37679
680 const note = titleElement.createChild('span', 'object-state-note info-note');
Tim van der Lippe1d6e57a2019-09-30 11:55:34681 if (this._message.type === SDK.ConsoleMessage.MessageType.QueryObjectResult) {
Blink Reformat4c46d092018-04-07 15:32:37682 note.title = ls`This value will not be collected until console is cleared.`;
Tim van der Lippe1d6e57a2019-09-30 11:55:34683 } else {
Blink Reformat4c46d092018-04-07 15:32:37684 note.title = ls`Value below was evaluated just now.`;
Tim van der Lippe1d6e57a2019-09-30 11:55:34685 }
Blink Reformat4c46d092018-04-07 15:32:37686
687 const section = new ObjectUI.ObjectPropertiesSection(obj, titleElement, this._linkifier);
688 section.element.classList.add('console-view-object-properties-section');
689 section.enableContextMenu();
Erik Luocc14b812018-11-03 01:33:09690 section.setShowSelectionOnKeyboardFocus(true, true);
Erik Luo383f21d2018-11-07 23:16:37691 this._selectableChildren.push(section);
Erik Luo840be6b2018-12-03 20:54:27692 section.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
693 section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
694 section.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
Blink Reformat4c46d092018-04-07 15:32:37695 return section.element;
696 }
697
698 /**
699 * @param {!SDK.RemoteObject} func
700 * @param {boolean=} includePreview
701 * @return {!Element}
702 */
703 _formatParameterAsFunction(func, includePreview) {
704 const result = createElement('span');
705 SDK.RemoteFunction.objectAsFunction(func).targetFunction().then(formatTargetFunction.bind(this));
706 return result;
707
708 /**
709 * @param {!SDK.RemoteObject} targetFunction
710 * @this {Console.ConsoleViewMessage}
711 */
712 function formatTargetFunction(targetFunction) {
713 const functionElement = createElement('span');
Joey Arhard78a58f2018-12-05 01:59:45714 const promise = ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(
715 targetFunction, functionElement, true, includePreview);
Blink Reformat4c46d092018-04-07 15:32:37716 result.appendChild(functionElement);
717 if (targetFunction !== func) {
718 const note = result.createChild('span', 'object-info-state-note');
719 note.title = Common.UIString('Function was resolved from bound function.');
720 }
721 result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, targetFunction), false);
Joey Arhard78a58f2018-12-05 01:59:45722 promise.then(() => this._formattedParameterAsFunctionForTest());
Blink Reformat4c46d092018-04-07 15:32:37723 }
724 }
725
Joey Arhard78a58f2018-12-05 01:59:45726 _formattedParameterAsFunctionForTest() {
727 }
728
Blink Reformat4c46d092018-04-07 15:32:37729 /**
730 * @param {!SDK.RemoteObject} obj
731 * @param {!Event} event
732 */
733 _contextMenuEventFired(obj, event) {
734 const contextMenu = new UI.ContextMenu(event);
735 contextMenu.appendApplicableItems(obj);
736 contextMenu.show();
737 }
738
739 /**
740 * @param {?SDK.RemoteObject} object
741 * @param {!Array.<!Protocol.Runtime.PropertyPreview>} propertyPath
742 * @return {!Element}
743 */
744 _renderPropertyPreviewOrAccessor(object, propertyPath) {
745 const property = propertyPath.peekLast();
Tim van der Lippe1d6e57a2019-09-30 11:55:34746 if (property.type === 'accessor') {
Blink Reformat4c46d092018-04-07 15:32:37747 return this._formatAsAccessorProperty(object, propertyPath.map(property => property.name), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34748 }
Blink Reformat4c46d092018-04-07 15:32:37749 return this._previewFormatter.renderPropertyPreview(
750 property.type, /** @type {string} */ (property.subtype), property.value);
751 }
752
753 /**
754 * @param {!SDK.RemoteObject} remoteObject
755 * @return {!Element}
756 */
757 _formatParameterAsNode(remoteObject) {
758 const result = createElement('span');
759
760 const domModel = remoteObject.runtimeModel().target().model(SDK.DOMModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34761 if (!domModel) {
Blink Reformat4c46d092018-04-07 15:32:37762 return result;
Tim van der Lippe1d6e57a2019-09-30 11:55:34763 }
Erik Luo54fdd912018-11-01 17:57:01764 domModel.pushObjectAsNodeToFrontend(remoteObject).then(async node => {
Blink Reformat4c46d092018-04-07 15:32:37765 if (!node) {
766 result.appendChild(this._formatParameterAsObject(remoteObject, false));
767 return;
768 }
Erik Luo54fdd912018-11-01 17:57:01769 const renderResult = await UI.Renderer.render(/** @type {!Object} */ (node));
Erik Luofc6a6302018-11-02 06:48:52770 if (renderResult) {
Erik Luo840be6b2018-12-03 20:54:27771 if (renderResult.tree) {
Erik Luo383f21d2018-11-07 23:16:37772 this._selectableChildren.push(renderResult.tree);
Erik Luo840be6b2018-12-03 20:54:27773 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
774 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
775 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
776 }
Erik Luofc6a6302018-11-02 06:48:52777 result.appendChild(renderResult.node);
778 } else {
779 result.appendChild(this._formatParameterAsObject(remoteObject, false));
780 }
Erik Luo54fdd912018-11-01 17:57:01781 this._formattedParameterAsNodeForTest();
Blink Reformat4c46d092018-04-07 15:32:37782 });
783
784 return result;
785 }
786
787 _formattedParameterAsNodeForTest() {
788 }
789
790 /**
791 * @param {!SDK.RemoteObject} output
792 * @return {!Element}
793 */
794 _formatParameterAsString(output) {
795 const span = createElement('span');
Erik Luo383f21d2018-11-07 23:16:37796 span.appendChild(this._linkifyStringAsFragment(output.description || ''));
Blink Reformat4c46d092018-04-07 15:32:37797
798 const result = createElement('span');
799 result.createChild('span', 'object-value-string-quote').textContent = '"';
800 result.appendChild(span);
801 result.createChild('span', 'object-value-string-quote').textContent = '"';
802 return result;
803 }
804
805 /**
806 * @param {!SDK.RemoteObject} output
807 * @return {!Element}
808 */
809 _formatParameterAsError(output) {
810 const result = createElement('span');
811 const errorSpan = this._tryFormatAsError(output.description || '');
Erik Luo383f21d2018-11-07 23:16:37812 result.appendChild(errorSpan ? errorSpan : this._linkifyStringAsFragment(output.description || ''));
Blink Reformat4c46d092018-04-07 15:32:37813 return result;
814 }
815
816 /**
817 * @param {!SDK.RemoteObject} output
818 * @return {!Element}
819 */
820 _formatAsArrayEntry(output) {
821 return this._previewFormatter.renderPropertyPreview(output.type, output.subtype, output.description);
822 }
823
824 /**
825 * @param {?SDK.RemoteObject} object
826 * @param {!Array.<string>} propertyPath
827 * @param {boolean} isArrayEntry
828 * @return {!Element}
829 */
830 _formatAsAccessorProperty(object, propertyPath, isArrayEntry) {
831 const rootElement = ObjectUI.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan(
832 object, propertyPath, onInvokeGetterClick.bind(this));
833
834 /**
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18835 * @param {!SDK.CallFunctionResult} result
Blink Reformat4c46d092018-04-07 15:32:37836 * @this {Console.ConsoleViewMessage}
837 */
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18838 function onInvokeGetterClick(result) {
839 const wasThrown = result.wasThrown;
840 const object = result.object;
Tim van der Lippe1d6e57a2019-09-30 11:55:34841 if (!object) {
Blink Reformat4c46d092018-04-07 15:32:37842 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34843 }
Blink Reformat4c46d092018-04-07 15:32:37844 rootElement.removeChildren();
845 if (wasThrown) {
846 const element = rootElement.createChild('span');
847 element.textContent = Common.UIString('<exception>');
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18848 element.title = /** @type {string} */ (object.description);
Blink Reformat4c46d092018-04-07 15:32:37849 } else if (isArrayEntry) {
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18850 rootElement.appendChild(this._formatAsArrayEntry(object));
Blink Reformat4c46d092018-04-07 15:32:37851 } else {
852 // Make a PropertyPreview from the RemoteObject similar to the backend logic.
853 const maxLength = 100;
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18854 const type = object.type;
855 const subtype = object.subtype;
Blink Reformat4c46d092018-04-07 15:32:37856 let description = '';
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18857 if (type !== 'function' && object.description) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34858 if (type === 'string' || subtype === 'regexp') {
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18859 description = object.description.trimMiddle(maxLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:34860 } else {
Tim van der Lippeffa78622019-09-16 12:07:12861 description = object.description.trimEndWithMaxLength(maxLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:34862 }
Blink Reformat4c46d092018-04-07 15:32:37863 }
864 rootElement.appendChild(this._previewFormatter.renderPropertyPreview(type, subtype, description));
865 }
866 }
867
868 return rootElement;
869 }
870
871 /**
872 * @param {string} format
873 * @param {!Array.<!SDK.RemoteObject>} parameters
874 * @param {!Element} formattedResult
875 */
876 _formatWithSubstitutionString(format, parameters, formattedResult) {
877 const formatters = {};
878
879 /**
880 * @param {boolean} force
881 * @param {boolean} includePreview
882 * @param {!SDK.RemoteObject} obj
883 * @return {!Element}
884 * @this {Console.ConsoleViewMessage}
885 */
886 function parameterFormatter(force, includePreview, obj) {
887 return this._formatParameter(obj, force, includePreview);
888 }
889
890 function stringFormatter(obj) {
891 return obj.description;
892 }
893
894 function floatFormatter(obj) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34895 if (typeof obj.value !== 'number') {
Blink Reformat4c46d092018-04-07 15:32:37896 return 'NaN';
Tim van der Lippe1d6e57a2019-09-30 11:55:34897 }
Blink Reformat4c46d092018-04-07 15:32:37898 return obj.value;
899 }
900
901 function integerFormatter(obj) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34902 if (obj.type === 'bigint') {
Alexey Kozyatinskiybeb38de2018-08-10 18:54:19903 return obj.description;
Tim van der Lippe1d6e57a2019-09-30 11:55:34904 }
905 if (typeof obj.value !== 'number') {
Blink Reformat4c46d092018-04-07 15:32:37906 return 'NaN';
Tim van der Lippe1d6e57a2019-09-30 11:55:34907 }
Blink Reformat4c46d092018-04-07 15:32:37908 return Math.floor(obj.value);
909 }
910
911 function bypassFormatter(obj) {
912 return (obj instanceof Node) ? obj : '';
913 }
914
915 let currentStyle = null;
916 function styleFormatter(obj) {
917 currentStyle = {};
918 const buffer = createElement('span');
919 buffer.setAttribute('style', obj.description);
920 for (let i = 0; i < buffer.style.length; i++) {
921 const property = buffer.style[i];
Tim van der Lippe1d6e57a2019-09-30 11:55:34922 if (isWhitelistedProperty(property)) {
Blink Reformat4c46d092018-04-07 15:32:37923 currentStyle[property] = buffer.style[property];
Tim van der Lippe1d6e57a2019-09-30 11:55:34924 }
Blink Reformat4c46d092018-04-07 15:32:37925 }
926 }
927
928 function isWhitelistedProperty(property) {
929 // Make sure that allowed properties do not interfere with link visibility.
930 const prefixes = [
931 'background', 'border', 'color', 'font', 'line', 'margin', 'padding', 'text', '-webkit-background',
932 '-webkit-border', '-webkit-font', '-webkit-margin', '-webkit-padding', '-webkit-text'
933 ];
934 for (let i = 0; i < prefixes.length; i++) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34935 if (property.startsWith(prefixes[i])) {
Blink Reformat4c46d092018-04-07 15:32:37936 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:34937 }
Blink Reformat4c46d092018-04-07 15:32:37938 }
939 return false;
940 }
941
942 // Firebug uses %o for formatting objects.
943 formatters.o = parameterFormatter.bind(this, false /* force */, true /* includePreview */);
944 formatters.s = stringFormatter;
945 formatters.f = floatFormatter;
946 // Firebug allows both %i and %d for formatting integers.
947 formatters.i = integerFormatter;
948 formatters.d = integerFormatter;
949
950 // Firebug uses %c for styling the message.
951 formatters.c = styleFormatter;
952
953 // Support %O to force object formatting, instead of the type-based %o formatting.
954 formatters.O = parameterFormatter.bind(this, true /* force */, false /* includePreview */);
955
956 formatters._ = bypassFormatter;
957
958 /**
959 * @param {!Element} a
960 * @param {*} b
961 * @this {!Console.ConsoleViewMessage}
Erik Luo17926392018-05-17 22:06:12962 * @return {!Element}
Blink Reformat4c46d092018-04-07 15:32:37963 */
964 function append(a, b) {
965 if (b instanceof Node) {
966 a.appendChild(b);
Erik Luo17926392018-05-17 22:06:12967 return a;
968 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34969 if (typeof b === 'undefined') {
Erik Luo17926392018-05-17 22:06:12970 return a;
Tim van der Lippe1d6e57a2019-09-30 11:55:34971 }
Erik Luo17926392018-05-17 22:06:12972 if (!currentStyle) {
Erik Luo383f21d2018-11-07 23:16:37973 a.appendChild(this._linkifyStringAsFragment(String(b)));
Erik Luo17926392018-05-17 22:06:12974 return a;
975 }
976 const lines = String(b).split('\n');
977 for (let i = 0; i < lines.length; i++) {
978 const line = lines[i];
Erik Luo383f21d2018-11-07 23:16:37979 const lineFragment = this._linkifyStringAsFragment(line);
Erik Luo17926392018-05-17 22:06:12980 const wrapper = createElement('span');
981 wrapper.style.setProperty('contain', 'paint');
982 wrapper.style.setProperty('display', 'inline-block');
983 wrapper.style.setProperty('max-width', '100%');
984 wrapper.appendChild(lineFragment);
985 applyCurrentStyle(wrapper);
986 for (const child of wrapper.children) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34987 if (child.classList.contains('devtools-link')) {
Erik Luo17926392018-05-17 22:06:12988 this._applyForcedVisibleStyle(child);
Tim van der Lippe1d6e57a2019-09-30 11:55:34989 }
Blink Reformat4c46d092018-04-07 15:32:37990 }
Erik Luo17926392018-05-17 22:06:12991 a.appendChild(wrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34992 if (i < lines.length - 1) {
Erik Luo17926392018-05-17 22:06:12993 a.appendChild(createElement('br'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34994 }
Blink Reformat4c46d092018-04-07 15:32:37995 }
996 return a;
997 }
998
999 /**
1000 * @param {!Element} element
1001 */
1002 function applyCurrentStyle(element) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341003 for (const key in currentStyle) {
Blink Reformat4c46d092018-04-07 15:32:371004 element.style[key] = currentStyle[key];
Tim van der Lippe1d6e57a2019-09-30 11:55:341005 }
Blink Reformat4c46d092018-04-07 15:32:371006 }
1007
1008 // String.format does treat formattedResult like a Builder, result is an object.
1009 return String.format(format, parameters, formatters, formattedResult, append.bind(this));
1010 }
1011
1012 /**
1013 * @param {!Element} element
1014 */
1015 _applyForcedVisibleStyle(element) {
1016 element.style.setProperty('-webkit-text-stroke', '0', 'important');
1017 element.style.setProperty('text-decoration', 'underline', 'important');
1018
1019 const themedColor = UI.themeSupport.patchColorText('rgb(33%, 33%, 33%)', UI.ThemeSupport.ColorUsage.Foreground);
1020 element.style.setProperty('color', themedColor, 'important');
1021
1022 let backgroundColor = 'hsl(0, 0%, 100%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:341023 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
Blink Reformat4c46d092018-04-07 15:32:371024 backgroundColor = 'hsl(0, 100%, 97%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:341025 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning || this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:371026 backgroundColor = 'hsl(50, 100%, 95%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:341027 }
Blink Reformat4c46d092018-04-07 15:32:371028 const themedBackgroundColor =
1029 UI.themeSupport.patchColorText(backgroundColor, UI.ThemeSupport.ColorUsage.Background);
1030 element.style.setProperty('background-color', themedBackgroundColor, 'important');
1031 }
1032
1033 /**
1034 * @return {boolean}
1035 */
1036 matchesFilterRegex(regexObject) {
1037 regexObject.lastIndex = 0;
Erik Luo5976c8c2018-07-24 02:03:091038 const contentElement = this.contentElement();
1039 const anchorText = this._anchorElement ? this._anchorElement.deepTextContent() : '';
1040 return (anchorText && regexObject.test(anchorText.trim())) ||
1041 regexObject.test(contentElement.deepTextContent().slice(anchorText.length));
Blink Reformat4c46d092018-04-07 15:32:371042 }
1043
1044 /**
1045 * @param {string} filter
1046 * @return {boolean}
1047 */
1048 matchesFilterText(filter) {
1049 const text = this.contentElement().deepTextContent();
1050 return text.toLowerCase().includes(filter.toLowerCase());
1051 }
1052
1053 updateTimestamp() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341054 if (!this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371055 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341056 }
Blink Reformat4c46d092018-04-07 15:32:371057
1058 if (Common.moduleSetting('consoleTimestampsEnabled').get()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341059 if (!this._timestampElement) {
Blink Reformat4c46d092018-04-07 15:32:371060 this._timestampElement = createElementWithClass('span', 'console-timestamp');
Tim van der Lippe1d6e57a2019-09-30 11:55:341061 }
Rayan Kansoaca06e72019-03-27 11:57:061062 this._timestampElement.textContent = UI.formatTimestamp(this._message.timestamp, false) + ' ';
1063 this._timestampElement.title = UI.formatTimestamp(this._message.timestamp, true);
Blink Reformat4c46d092018-04-07 15:32:371064 this._contentElement.insertBefore(this._timestampElement, this._contentElement.firstChild);
1065 } else if (this._timestampElement) {
1066 this._timestampElement.remove();
1067 delete this._timestampElement;
1068 }
Blink Reformat4c46d092018-04-07 15:32:371069 }
1070
1071 /**
1072 * @return {number}
1073 */
1074 nestingLevel() {
1075 return this._nestingLevel;
1076 }
1077
1078 /**
1079 * @param {boolean} inSimilarGroup
1080 * @param {boolean=} isLast
1081 */
1082 setInSimilarGroup(inSimilarGroup, isLast) {
1083 this._inSimilarGroup = inSimilarGroup;
1084 this._lastInSimilarGroup = inSimilarGroup && !!isLast;
1085 if (this._similarGroupMarker && !inSimilarGroup) {
1086 this._similarGroupMarker.remove();
1087 this._similarGroupMarker = null;
1088 } else if (this._element && !this._similarGroupMarker && inSimilarGroup) {
1089 this._similarGroupMarker = createElementWithClass('div', 'nesting-level-marker');
1090 this._element.insertBefore(this._similarGroupMarker, this._element.firstChild);
1091 this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
1092 }
1093 }
1094
1095 /**
1096 * @return {boolean}
1097 */
1098 isLastInSimilarGroup() {
1099 return this._inSimilarGroup && this._lastInSimilarGroup;
1100 }
1101
1102 resetCloseGroupDecorationCount() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341103 if (!this._closeGroupDecorationCount) {
Blink Reformat4c46d092018-04-07 15:32:371104 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341105 }
Blink Reformat4c46d092018-04-07 15:32:371106 this._closeGroupDecorationCount = 0;
1107 this._updateCloseGroupDecorations();
1108 }
1109
1110 incrementCloseGroupDecorationCount() {
1111 ++this._closeGroupDecorationCount;
1112 this._updateCloseGroupDecorations();
1113 }
1114
1115 _updateCloseGroupDecorations() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341116 if (!this._nestingLevelMarkers) {
Blink Reformat4c46d092018-04-07 15:32:371117 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341118 }
Blink Reformat4c46d092018-04-07 15:32:371119 for (let i = 0, n = this._nestingLevelMarkers.length; i < n; ++i) {
1120 const marker = this._nestingLevelMarkers[i];
1121 marker.classList.toggle('group-closed', n - i <= this._closeGroupDecorationCount);
1122 }
1123 }
1124
1125 /**
Erik Luo0b8282e2018-10-08 20:37:461126 * @return {number}
1127 */
1128 _focusedChildIndex() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341129 if (!this._selectableChildren.length) {
Erik Luo0b8282e2018-10-08 20:37:461130 return -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341131 }
Erik Luo383f21d2018-11-07 23:16:371132 return this._selectableChildren.findIndex(child => child.element.hasFocus());
Erik Luo0b8282e2018-10-08 20:37:461133 }
1134
1135 /**
Erik Luo8ef5d0c2018-09-25 21:16:001136 * @param {!Event} event
1137 */
1138 _onKeyDown(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341139 if (UI.isEditing() || !this._element.hasFocus() || this._element.hasSelection()) {
Erik Luo8ef5d0c2018-09-25 21:16:001140 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341141 }
1142 if (this.maybeHandleOnKeyDown(event)) {
Erik Luo8ef5d0c2018-09-25 21:16:001143 event.consume(true);
Tim van der Lippe1d6e57a2019-09-30 11:55:341144 }
Erik Luo8ef5d0c2018-09-25 21:16:001145 }
1146
1147 /**
1148 * @protected
1149 * @param {!Event} event
1150 */
1151 maybeHandleOnKeyDown(event) {
1152 // Handle trace expansion.
Erik Luo0b8282e2018-10-08 20:37:461153 const focusedChildIndex = this._focusedChildIndex();
1154 const isWrapperFocused = focusedChildIndex === -1;
1155 if (this._expandTrace && isWrapperFocused) {
Erik Luo8ef5d0c2018-09-25 21:16:001156 if ((event.key === 'ArrowLeft' && this._traceExpanded) || (event.key === 'ArrowRight' && !this._traceExpanded)) {
1157 this._expandTrace(!this._traceExpanded);
1158 return true;
1159 }
1160 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341161 if (!this._selectableChildren.length) {
Erik Luo0b8282e2018-10-08 20:37:461162 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:341163 }
Erik Luo0b8282e2018-10-08 20:37:461164
1165 if (event.key === 'ArrowLeft') {
1166 this._element.focus();
1167 return true;
1168 }
1169 if (event.key === 'ArrowRight') {
Tim van der Lippe1d6e57a2019-09-30 11:55:341170 if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
Erik Luo0b8282e2018-10-08 20:37:461171 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341172 }
Erik Luo0b8282e2018-10-08 20:37:461173 }
1174 if (event.key === 'ArrowUp') {
Erik Luo182bece2018-11-29 03:15:221175 const firstVisibleChild = this._nearestVisibleChild(0);
1176 if (this._selectableChildren[focusedChildIndex] === firstVisibleChild && firstVisibleChild) {
Erik Luo0b8282e2018-10-08 20:37:461177 this._element.focus();
1178 return true;
Erik Luo182bece2018-11-29 03:15:221179 } else if (this._selectNearestVisibleChild(focusedChildIndex - 1, true /* backwards */)) {
Erik Luo0b8282e2018-10-08 20:37:461180 return true;
1181 }
1182 }
1183 if (event.key === 'ArrowDown') {
Tim van der Lippe1d6e57a2019-09-30 11:55:341184 if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
Erik Luo0b8282e2018-10-08 20:37:461185 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341186 }
1187 if (!isWrapperFocused && this._selectNearestVisibleChild(focusedChildIndex + 1)) {
Erik Luo0b8282e2018-10-08 20:37:461188 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341189 }
Erik Luo0b8282e2018-10-08 20:37:461190 }
Erik Luo8ef5d0c2018-09-25 21:16:001191 return false;
1192 }
1193
Erik Luo182bece2018-11-29 03:15:221194 /**
1195 * @param {number} fromIndex
1196 * @param {boolean=} backwards
1197 * @return {boolean}
1198 */
1199 _selectNearestVisibleChild(fromIndex, backwards) {
1200 const nearestChild = this._nearestVisibleChild(fromIndex, backwards);
1201 if (nearestChild) {
Erik Luo31c21f62018-12-13 03:39:391202 nearestChild.forceSelect();
Erik Luo182bece2018-11-29 03:15:221203 return true;
1204 }
1205 return false;
1206 }
1207
1208 /**
1209 * @param {number} fromIndex
1210 * @param {boolean=} backwards
Erik Luo31c21f62018-12-13 03:39:391211 * @return {?{element: !Element, forceSelect: function()}}
Erik Luo182bece2018-11-29 03:15:221212 */
1213 _nearestVisibleChild(fromIndex, backwards) {
1214 const childCount = this._selectableChildren.length;
Tim van der Lippe1d6e57a2019-09-30 11:55:341215 if (fromIndex < 0 || fromIndex >= childCount) {
Erik Luo182bece2018-11-29 03:15:221216 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341217 }
Erik Luo182bece2018-11-29 03:15:221218 const direction = backwards ? -1 : 1;
1219 let index = fromIndex;
1220
1221 while (!this._selectableChildren[index].element.offsetParent) {
1222 index += direction;
Tim van der Lippe1d6e57a2019-09-30 11:55:341223 if (index < 0 || index >= childCount) {
Erik Luo182bece2018-11-29 03:15:221224 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341225 }
Erik Luo182bece2018-11-29 03:15:221226 }
1227 return this._selectableChildren[index];
1228 }
1229
Erik Luo0b8282e2018-10-08 20:37:461230 focusLastChildOrSelf() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341231 if (this._element && !this._selectNearestVisibleChild(this._selectableChildren.length - 1, true /* backwards */)) {
Erik Luo0b8282e2018-10-08 20:37:461232 this._element.focus();
Tim van der Lippe1d6e57a2019-09-30 11:55:341233 }
Erik Luo0b8282e2018-10-08 20:37:461234 }
1235
1236 /**
Blink Reformat4c46d092018-04-07 15:32:371237 * @return {!Element}
1238 */
1239 contentElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341240 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371241 return this._contentElement;
Tim van der Lippe1d6e57a2019-09-30 11:55:341242 }
Blink Reformat4c46d092018-04-07 15:32:371243
1244 const contentElement = createElementWithClass('div', 'console-message');
Tim van der Lippe1d6e57a2019-09-30 11:55:341245 if (this._messageLevelIcon) {
Blink Reformat4c46d092018-04-07 15:32:371246 contentElement.appendChild(this._messageLevelIcon);
Tim van der Lippe1d6e57a2019-09-30 11:55:341247 }
Blink Reformat4c46d092018-04-07 15:32:371248 this._contentElement = contentElement;
1249
1250 let formattedMessage;
1251 const shouldIncludeTrace = !!this._message.stackTrace &&
1252 (this._message.source === SDK.ConsoleMessage.MessageSource.Network ||
1253 this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
1254 this._message.level === SDK.ConsoleMessage.MessageLevel.Error ||
1255 this._message.level === SDK.ConsoleMessage.MessageLevel.Warning ||
1256 this._message.type === SDK.ConsoleMessage.MessageType.Trace);
Tim van der Lippe1d6e57a2019-09-30 11:55:341257 if (this._message.runtimeModel() && shouldIncludeTrace) {
Blink Reformat4c46d092018-04-07 15:32:371258 formattedMessage = this._buildMessageWithStackTrace();
Tim van der Lippe1d6e57a2019-09-30 11:55:341259 } else if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
Blink Reformat4c46d092018-04-07 15:32:371260 formattedMessage = this._buildTableMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:341261 } else {
Blink Reformat4c46d092018-04-07 15:32:371262 formattedMessage = this._buildMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:341263 }
Blink Reformat4c46d092018-04-07 15:32:371264 contentElement.appendChild(formattedMessage);
1265
1266 this.updateTimestamp();
1267 return this._contentElement;
1268 }
1269
1270 /**
1271 * @return {!Element}
1272 */
1273 toMessageElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341274 if (this._element) {
Blink Reformat4c46d092018-04-07 15:32:371275 return this._element;
Tim van der Lippe1d6e57a2019-09-30 11:55:341276 }
Blink Reformat4c46d092018-04-07 15:32:371277
1278 this._element = createElement('div');
Pavel Feldmandb310912019-01-30 00:31:201279 this._element.tabIndex = -1;
1280 this._element.addEventListener('keydown', this._onKeyDown.bind(this));
Blink Reformat4c46d092018-04-07 15:32:371281 this.updateMessageElement();
1282 return this._element;
1283 }
1284
1285 updateMessageElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341286 if (!this._element) {
Blink Reformat4c46d092018-04-07 15:32:371287 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341288 }
Blink Reformat4c46d092018-04-07 15:32:371289
1290 this._element.className = 'console-message-wrapper';
1291 this._element.removeChildren();
Tim van der Lippe1d6e57a2019-09-30 11:55:341292 if (this._message.isGroupStartMessage()) {
Blink Reformat4c46d092018-04-07 15:32:371293 this._element.classList.add('console-group-title');
Tim van der Lippe1d6e57a2019-09-30 11:55:341294 }
1295 if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
Blink Reformat4c46d092018-04-07 15:32:371296 this._element.classList.add('console-from-api');
Tim van der Lippe1d6e57a2019-09-30 11:55:341297 }
Blink Reformat4c46d092018-04-07 15:32:371298 if (this._inSimilarGroup) {
1299 this._similarGroupMarker = this._element.createChild('div', 'nesting-level-marker');
1300 this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
1301 }
1302
1303 this._nestingLevelMarkers = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341304 for (let i = 0; i < this._nestingLevel; ++i) {
Blink Reformat4c46d092018-04-07 15:32:371305 this._nestingLevelMarkers.push(this._element.createChild('div', 'nesting-level-marker'));
Tim van der Lippe1d6e57a2019-09-30 11:55:341306 }
Blink Reformat4c46d092018-04-07 15:32:371307 this._updateCloseGroupDecorations();
1308 this._element.message = this;
1309
1310 switch (this._message.level) {
1311 case SDK.ConsoleMessage.MessageLevel.Verbose:
1312 this._element.classList.add('console-verbose-level');
Blink Reformat4c46d092018-04-07 15:32:371313 break;
1314 case SDK.ConsoleMessage.MessageLevel.Info:
1315 this._element.classList.add('console-info-level');
Tim van der Lippe1d6e57a2019-09-30 11:55:341316 if (this._message.type === SDK.ConsoleMessage.MessageType.System) {
Blink Reformat4c46d092018-04-07 15:32:371317 this._element.classList.add('console-system-type');
Tim van der Lippe1d6e57a2019-09-30 11:55:341318 }
Blink Reformat4c46d092018-04-07 15:32:371319 break;
1320 case SDK.ConsoleMessage.MessageLevel.Warning:
1321 this._element.classList.add('console-warning-level');
Blink Reformat4c46d092018-04-07 15:32:371322 break;
1323 case SDK.ConsoleMessage.MessageLevel.Error:
1324 this._element.classList.add('console-error-level');
Blink Reformat4c46d092018-04-07 15:32:371325 break;
1326 }
Erik Luofd3e7d42018-09-25 02:12:351327 this._updateMessageLevelIcon();
Tim van der Lippe1d6e57a2019-09-30 11:55:341328 if (this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:371329 this._element.classList.add('console-warning-level');
Tim van der Lippe1d6e57a2019-09-30 11:55:341330 }
Blink Reformat4c46d092018-04-07 15:32:371331
1332 this._element.appendChild(this.contentElement());
Tim van der Lippe1d6e57a2019-09-30 11:55:341333 if (this._repeatCount > 1) {
Blink Reformat4c46d092018-04-07 15:32:371334 this._showRepeatCountElement();
Tim van der Lippe1d6e57a2019-09-30 11:55:341335 }
Blink Reformat4c46d092018-04-07 15:32:371336 }
1337
1338 /**
1339 * @return {boolean}
1340 */
1341 _shouldRenderAsWarning() {
1342 return (this._message.level === SDK.ConsoleMessage.MessageLevel.Verbose ||
1343 this._message.level === SDK.ConsoleMessage.MessageLevel.Info) &&
1344 (this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
1345 this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation ||
1346 this._message.source === SDK.ConsoleMessage.MessageSource.Intervention ||
1347 this._message.source === SDK.ConsoleMessage.MessageSource.Recommendation);
1348 }
1349
Erik Luofd3e7d42018-09-25 02:12:351350 _updateMessageLevelIcon() {
1351 let iconType = '';
1352 let accessibleName = '';
1353 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
1354 iconType = 'smallicon-warning';
1355 accessibleName = ls`Warning`;
1356 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
1357 iconType = 'smallicon-error';
1358 accessibleName = ls`Error`;
1359 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341360 if (!iconType && !this._messageLevelIcon) {
Blink Reformat4c46d092018-04-07 15:32:371361 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341362 }
Blink Reformat4c46d092018-04-07 15:32:371363 if (iconType && !this._messageLevelIcon) {
1364 this._messageLevelIcon = UI.Icon.create('', 'message-level-icon');
Tim van der Lippe1d6e57a2019-09-30 11:55:341365 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371366 this._contentElement.insertBefore(this._messageLevelIcon, this._contentElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341367 }
Blink Reformat4c46d092018-04-07 15:32:371368 }
1369 this._messageLevelIcon.setIconType(iconType);
Erik Luofd3e7d42018-09-25 02:12:351370 UI.ARIAUtils.setAccessibleName(this._messageLevelIcon, accessibleName);
Blink Reformat4c46d092018-04-07 15:32:371371 }
1372
1373 /**
1374 * @return {number}
1375 */
1376 repeatCount() {
1377 return this._repeatCount || 1;
1378 }
1379
1380 resetIncrementRepeatCount() {
1381 this._repeatCount = 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341382 if (!this._repeatCountElement) {
Blink Reformat4c46d092018-04-07 15:32:371383 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341384 }
Blink Reformat4c46d092018-04-07 15:32:371385
1386 this._repeatCountElement.remove();
Tim van der Lippe1d6e57a2019-09-30 11:55:341387 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371388 this._contentElement.classList.remove('repeated-message');
Tim van der Lippe1d6e57a2019-09-30 11:55:341389 }
Blink Reformat4c46d092018-04-07 15:32:371390 delete this._repeatCountElement;
1391 }
1392
1393 incrementRepeatCount() {
1394 this._repeatCount++;
1395 this._showRepeatCountElement();
1396 }
1397
1398 /**
1399 * @param {number} repeatCount
1400 */
1401 setRepeatCount(repeatCount) {
1402 this._repeatCount = repeatCount;
1403 this._showRepeatCountElement();
1404 }
1405
1406 _showRepeatCountElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341407 if (!this._element) {
Blink Reformat4c46d092018-04-07 15:32:371408 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341409 }
Blink Reformat4c46d092018-04-07 15:32:371410
1411 if (!this._repeatCountElement) {
Joel Einbinder7fbe24c2019-01-24 05:19:011412 this._repeatCountElement = createElementWithClass('span', 'console-message-repeat-count', 'dt-small-bubble');
Blink Reformat4c46d092018-04-07 15:32:371413 switch (this._message.level) {
1414 case SDK.ConsoleMessage.MessageLevel.Warning:
1415 this._repeatCountElement.type = 'warning';
1416 break;
1417 case SDK.ConsoleMessage.MessageLevel.Error:
1418 this._repeatCountElement.type = 'error';
1419 break;
1420 case SDK.ConsoleMessage.MessageLevel.Verbose:
1421 this._repeatCountElement.type = 'verbose';
1422 break;
1423 default:
1424 this._repeatCountElement.type = 'info';
1425 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341426 if (this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:371427 this._repeatCountElement.type = 'warning';
Tim van der Lippe1d6e57a2019-09-30 11:55:341428 }
Blink Reformat4c46d092018-04-07 15:32:371429
1430 this._element.insertBefore(this._repeatCountElement, this._contentElement);
1431 this._contentElement.classList.add('repeated-message');
1432 }
1433 this._repeatCountElement.textContent = this._repeatCount;
Erik Luofd3e7d42018-09-25 02:12:351434 let accessibleName = ls`Repeat ${this._repeatCount}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341435 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
Erik Luofd3e7d42018-09-25 02:12:351436 accessibleName = ls`Warning ${accessibleName}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341437 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
Erik Luofd3e7d42018-09-25 02:12:351438 accessibleName = ls`Error ${accessibleName}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341439 }
Erik Luofd3e7d42018-09-25 02:12:351440 UI.ARIAUtils.setAccessibleName(this._repeatCountElement, accessibleName);
Blink Reformat4c46d092018-04-07 15:32:371441 }
1442
1443 get text() {
1444 return this._message.messageText;
1445 }
1446
1447 /**
1448 * @return {string}
1449 */
1450 toExportString() {
1451 const lines = [];
1452 const nodes = this.contentElement().childTextNodes();
1453 const messageContent = nodes.map(Components.Linkifier.untruncatedNodeText).join('');
Tim van der Lippe1d6e57a2019-09-30 11:55:341454 for (let i = 0; i < this.repeatCount(); ++i) {
Blink Reformat4c46d092018-04-07 15:32:371455 lines.push(messageContent);
Tim van der Lippe1d6e57a2019-09-30 11:55:341456 }
Blink Reformat4c46d092018-04-07 15:32:371457 return lines.join('\n');
1458 }
1459
1460 /**
1461 * @param {?RegExp} regex
1462 */
1463 setSearchRegex(regex) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341464 if (this._searchHiglightNodeChanges && this._searchHiglightNodeChanges.length) {
Blink Reformat4c46d092018-04-07 15:32:371465 UI.revertDomChanges(this._searchHiglightNodeChanges);
Tim van der Lippe1d6e57a2019-09-30 11:55:341466 }
Blink Reformat4c46d092018-04-07 15:32:371467 this._searchRegex = regex;
1468 this._searchHighlightNodes = [];
1469 this._searchHiglightNodeChanges = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341470 if (!this._searchRegex) {
Blink Reformat4c46d092018-04-07 15:32:371471 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341472 }
Blink Reformat4c46d092018-04-07 15:32:371473
1474 const text = this.contentElement().deepTextContent();
1475 let match;
1476 this._searchRegex.lastIndex = 0;
1477 const sourceRanges = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341478 while ((match = this._searchRegex.exec(text)) && match[0]) {
Blink Reformat4c46d092018-04-07 15:32:371479 sourceRanges.push(new TextUtils.SourceRange(match.index, match[0].length));
Tim van der Lippe1d6e57a2019-09-30 11:55:341480 }
Blink Reformat4c46d092018-04-07 15:32:371481
1482 if (sourceRanges.length) {
1483 this._searchHighlightNodes =
1484 UI.highlightSearchResults(this.contentElement(), sourceRanges, this._searchHiglightNodeChanges);
1485 }
1486 }
1487
1488 /**
1489 * @return {?RegExp}
1490 */
1491 searchRegex() {
1492 return this._searchRegex;
1493 }
1494
1495 /**
1496 * @return {number}
1497 */
1498 searchCount() {
1499 return this._searchHighlightNodes.length;
1500 }
1501
1502 /**
1503 * @return {!Element}
1504 */
1505 searchHighlightNode(index) {
1506 return this._searchHighlightNodes[index];
1507 }
1508
1509 /**
1510 * @param {string} string
1511 * @return {?Element}
1512 */
1513 _tryFormatAsError(string) {
1514 /**
1515 * @param {string} prefix
1516 */
1517 function startsWith(prefix) {
1518 return string.startsWith(prefix);
1519 }
1520
1521 const errorPrefixes =
1522 ['EvalError', 'ReferenceError', 'SyntaxError', 'TypeError', 'RangeError', 'Error', 'URIError'];
Tim van der Lippe1d6e57a2019-09-30 11:55:341523 if (!this._message.runtimeModel() || !errorPrefixes.some(startsWith)) {
Blink Reformat4c46d092018-04-07 15:32:371524 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341525 }
Blink Reformat4c46d092018-04-07 15:32:371526 const debuggerModel = this._message.runtimeModel().debuggerModel();
1527 const baseURL = this._message.runtimeModel().target().inspectedURL();
1528
1529 const lines = string.split('\n');
1530 const links = [];
1531 let position = 0;
1532 for (let i = 0; i < lines.length; ++i) {
1533 position += i > 0 ? lines[i - 1].length + 1 : 0;
1534 const isCallFrameLine = /^\s*at\s/.test(lines[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341535 if (!isCallFrameLine && links.length) {
Blink Reformat4c46d092018-04-07 15:32:371536 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341537 }
Blink Reformat4c46d092018-04-07 15:32:371538
Tim van der Lippe1d6e57a2019-09-30 11:55:341539 if (!isCallFrameLine) {
Blink Reformat4c46d092018-04-07 15:32:371540 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341541 }
Blink Reformat4c46d092018-04-07 15:32:371542
1543 let openBracketIndex = -1;
1544 let closeBracketIndex = -1;
Yang Guo39256bd2019-07-18 06:02:251545 const inBracketsWithLineAndColumn = /\([^\)\(]+:\d+:\d+\)/g;
1546 const inBrackets = /\([^\)\(]+\)/g;
1547 let lastMatch = null;
1548 let currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341549 while ((currentMatch = inBracketsWithLineAndColumn.exec(lines[i]))) {
Yang Guo39256bd2019-07-18 06:02:251550 lastMatch = currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341551 }
Yang Guo39256bd2019-07-18 06:02:251552 if (!lastMatch) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341553 while ((currentMatch = inBrackets.exec(lines[i]))) {
Yang Guo39256bd2019-07-18 06:02:251554 lastMatch = currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341555 }
Yang Guo39256bd2019-07-18 06:02:251556 }
1557 if (lastMatch) {
1558 openBracketIndex = lastMatch.index;
1559 closeBracketIndex = lastMatch.index + lastMatch[0].length - 1;
Blink Reformat4c46d092018-04-07 15:32:371560 }
1561 const hasOpenBracket = openBracketIndex !== -1;
1562 const left = hasOpenBracket ? openBracketIndex + 1 : lines[i].indexOf('at') + 3;
1563 const right = hasOpenBracket ? closeBracketIndex : lines[i].length;
1564 const linkCandidate = lines[i].substring(left, right);
1565 const splitResult = Common.ParsedURL.splitLineAndColumn(linkCandidate);
Tim van der Lippe1d6e57a2019-09-30 11:55:341566 if (!splitResult) {
Blink Reformat4c46d092018-04-07 15:32:371567 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341568 }
Blink Reformat4c46d092018-04-07 15:32:371569
Tim van der Lippe1d6e57a2019-09-30 11:55:341570 if (splitResult.url === '<anonymous>') {
Blink Reformat4c46d092018-04-07 15:32:371571 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341572 }
Blink Reformat4c46d092018-04-07 15:32:371573 let url = parseOrScriptMatch(splitResult.url);
Tim van der Lippe1d6e57a2019-09-30 11:55:341574 if (!url && Common.ParsedURL.isRelativeURL(splitResult.url)) {
Blink Reformat4c46d092018-04-07 15:32:371575 url = parseOrScriptMatch(Common.ParsedURL.completeURL(baseURL, splitResult.url));
Tim van der Lippe1d6e57a2019-09-30 11:55:341576 }
1577 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:371578 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341579 }
Blink Reformat4c46d092018-04-07 15:32:371580
1581 links.push({
1582 url: url,
1583 positionLeft: position + left,
1584 positionRight: position + right,
1585 lineNumber: splitResult.lineNumber,
1586 columnNumber: splitResult.columnNumber
1587 });
1588 }
1589
Tim van der Lippe1d6e57a2019-09-30 11:55:341590 if (!links.length) {
Blink Reformat4c46d092018-04-07 15:32:371591 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341592 }
Blink Reformat4c46d092018-04-07 15:32:371593
1594 const formattedResult = createElement('span');
1595 let start = 0;
1596 for (let i = 0; i < links.length; ++i) {
Erik Luo383f21d2018-11-07 23:16:371597 formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start, links[i].positionLeft)));
Erik Luo182bece2018-11-29 03:15:221598 const scriptLocationLink = this._linkifier.linkifyScriptLocation(
1599 debuggerModel.target(), null, links[i].url, links[i].lineNumber, links[i].columnNumber);
1600 scriptLocationLink.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:391601 this._selectableChildren.push({element: scriptLocationLink, forceSelect: () => scriptLocationLink.focus()});
Erik Luo182bece2018-11-29 03:15:221602 formattedResult.appendChild(scriptLocationLink);
Blink Reformat4c46d092018-04-07 15:32:371603 start = links[i].positionRight;
1604 }
1605
Tim van der Lippe1d6e57a2019-09-30 11:55:341606 if (start !== string.length) {
Erik Luo383f21d2018-11-07 23:16:371607 formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start)));
Tim van der Lippe1d6e57a2019-09-30 11:55:341608 }
Blink Reformat4c46d092018-04-07 15:32:371609
1610 return formattedResult;
1611
1612 /**
1613 * @param {?string} url
1614 * @return {?string}
1615 */
1616 function parseOrScriptMatch(url) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341617 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:371618 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341619 }
Blink Reformat4c46d092018-04-07 15:32:371620 const parsedURL = url.asParsedURL();
Tim van der Lippe1d6e57a2019-09-30 11:55:341621 if (parsedURL) {
Blink Reformat4c46d092018-04-07 15:32:371622 return parsedURL.url;
Tim van der Lippe1d6e57a2019-09-30 11:55:341623 }
1624 if (debuggerModel.scriptsForSourceURL(url).length) {
Blink Reformat4c46d092018-04-07 15:32:371625 return url;
Tim van der Lippe1d6e57a2019-09-30 11:55:341626 }
Blink Reformat4c46d092018-04-07 15:32:371627 return null;
1628 }
1629 }
1630
1631 /**
1632 * @param {string} string
1633 * @param {function(string,string,number=,number=):!Node} linkifier
1634 * @return {!DocumentFragment}
1635 */
Erik Luofc2214f2018-11-21 19:54:581636 _linkifyWithCustomLinkifier(string, linkifier) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341637 if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Erik Luo5fb33bd2018-06-04 23:23:521638 return UI.createExpandableText(string, Console.ConsoleViewMessage._LongStringVisibleLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:341639 }
Blink Reformat4c46d092018-04-07 15:32:371640 const container = createDocumentFragment();
Erik Luofc2214f2018-11-21 19:54:581641 const tokens = Console.ConsoleViewMessage._tokenizeMessageText(string);
Blink Reformat4c46d092018-04-07 15:32:371642 for (const token of tokens) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341643 if (!token.text) {
Erik Luofc2214f2018-11-21 19:54:581644 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341645 }
Blink Reformat4c46d092018-04-07 15:32:371646 switch (token.type) {
1647 case 'url': {
1648 const realURL = (token.text.startsWith('www.') ? 'http://' + token.text : token.text);
1649 const splitResult = Common.ParsedURL.splitLineAndColumn(realURL);
1650 let linkNode;
Tim van der Lippe1d6e57a2019-09-30 11:55:341651 if (splitResult) {
Blink Reformat4c46d092018-04-07 15:32:371652 linkNode = linkifier(token.text, splitResult.url, splitResult.lineNumber, splitResult.columnNumber);
Tim van der Lippe1d6e57a2019-09-30 11:55:341653 } else {
Blink Reformat4c46d092018-04-07 15:32:371654 linkNode = linkifier(token.text, token.value);
Tim van der Lippe1d6e57a2019-09-30 11:55:341655 }
Blink Reformat4c46d092018-04-07 15:32:371656 container.appendChild(linkNode);
1657 break;
1658 }
1659 default:
1660 container.appendChild(createTextNode(token.text));
1661 break;
1662 }
1663 }
1664 return container;
1665 }
1666
1667 /**
Blink Reformat4c46d092018-04-07 15:32:371668 * @param {string} string
1669 * @return {!DocumentFragment}
1670 */
Erik Luo383f21d2018-11-07 23:16:371671 _linkifyStringAsFragment(string) {
Erik Luofc2214f2018-11-21 19:54:581672 return this._linkifyWithCustomLinkifier(string, (text, url, lineNumber, columnNumber) => {
Erik Luo383f21d2018-11-07 23:16:371673 const linkElement = Components.Linkifier.linkifyURL(url, {text, lineNumber, columnNumber});
1674 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:391675 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo383f21d2018-11-07 23:16:371676 return linkElement;
Blink Reformat4c46d092018-04-07 15:32:371677 });
1678 }
1679
1680 /**
1681 * @param {string} string
1682 * @return {!Array<{type: string, text: (string|undefined)}>}
1683 */
1684 static _tokenizeMessageText(string) {
1685 if (!Console.ConsoleViewMessage._tokenizerRegexes) {
1686 const controlCodes = '\\u0000-\\u0020\\u007f-\\u009f';
1687 const linkStringRegex = new RegExp(
1688 '(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|data:|www\\.)[^\\s' + controlCodes + '"]{2,}[^\\s' + controlCodes +
1689 '"\')}\\],:;.!?]',
1690 'u');
1691 const pathLineRegex = /(?:\/[\w\.-]*)+\:[\d]+/;
1692 const timeRegex = /took [\d]+ms/;
1693 const eventRegex = /'\w+' event/;
1694 const milestoneRegex = /\sM[6-7]\d/;
1695 const autofillRegex = /\(suggested: \"[\w-]+\"\)/;
1696 const handlers = new Map();
1697 handlers.set(linkStringRegex, 'url');
1698 handlers.set(pathLineRegex, 'url');
1699 handlers.set(timeRegex, 'time');
1700 handlers.set(eventRegex, 'event');
1701 handlers.set(milestoneRegex, 'milestone');
1702 handlers.set(autofillRegex, 'autofill');
1703 Console.ConsoleViewMessage._tokenizerRegexes = Array.from(handlers.keys());
1704 Console.ConsoleViewMessage._tokenizerTypes = Array.from(handlers.values());
1705 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341706 if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Blink Reformat4c46d092018-04-07 15:32:371707 return [{text: string, type: undefined}];
Tim van der Lippe1d6e57a2019-09-30 11:55:341708 }
Blink Reformat4c46d092018-04-07 15:32:371709 const results = TextUtils.TextUtils.splitStringByRegexes(string, Console.ConsoleViewMessage._tokenizerRegexes);
1710 return results.map(
1711 result => ({text: result.value, type: Console.ConsoleViewMessage._tokenizerTypes[result.regexIndex]}));
1712 }
1713
1714 /**
1715 * @return {string}
1716 */
1717 groupKey() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341718 if (!this._groupKey) {
Blink Reformat4c46d092018-04-07 15:32:371719 this._groupKey = this._message.groupCategoryKey() + ':' + this.groupTitle();
Tim van der Lippe1d6e57a2019-09-30 11:55:341720 }
Blink Reformat4c46d092018-04-07 15:32:371721 return this._groupKey;
1722 }
1723
1724 /**
1725 * @return {string}
1726 */
1727 groupTitle() {
1728 const tokens = Console.ConsoleViewMessage._tokenizeMessageText(this._message.messageText);
1729 const result = tokens.reduce((acc, token) => {
1730 let text = token.text;
Tim van der Lippe1d6e57a2019-09-30 11:55:341731 if (token.type === 'url') {
Blink Reformat4c46d092018-04-07 15:32:371732 text = Common.UIString('<URL>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341733 } else if (token.type === 'time') {
Blink Reformat4c46d092018-04-07 15:32:371734 text = Common.UIString('took <N>ms');
Tim van der Lippe1d6e57a2019-09-30 11:55:341735 } else if (token.type === 'event') {
Blink Reformat4c46d092018-04-07 15:32:371736 text = Common.UIString('<some> event');
Tim van der Lippe1d6e57a2019-09-30 11:55:341737 } else if (token.type === 'milestone') {
Blink Reformat4c46d092018-04-07 15:32:371738 text = Common.UIString(' M<XX>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341739 } else if (token.type === 'autofill') {
Blink Reformat4c46d092018-04-07 15:32:371740 text = Common.UIString('<attribute>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341741 }
Blink Reformat4c46d092018-04-07 15:32:371742 return acc + text;
1743 }, '');
1744 return result.replace(/[%]o/g, '');
1745 }
1746};
1747
1748/**
1749 * @unrestricted
1750 */
1751Console.ConsoleGroupViewMessage = class extends Console.ConsoleViewMessage {
1752 /**
1753 * @param {!SDK.ConsoleMessage} consoleMessage
1754 * @param {!Components.Linkifier} linkifier
1755 * @param {!ProductRegistry.BadgePool} badgePool
1756 * @param {number} nestingLevel
Erik Luo8ef5d0c2018-09-25 21:16:001757 * @param {function()} onToggle
Erik Luo840be6b2018-12-03 20:54:271758 * @param {function(!Common.Event)} onResize
Blink Reformat4c46d092018-04-07 15:32:371759 */
Erik Luo840be6b2018-12-03 20:54:271760 constructor(consoleMessage, linkifier, badgePool, nestingLevel, onToggle, onResize) {
Blink Reformat4c46d092018-04-07 15:32:371761 console.assert(consoleMessage.isGroupStartMessage());
Erik Luo840be6b2018-12-03 20:54:271762 super(consoleMessage, linkifier, badgePool, nestingLevel, onResize);
Blink Reformat4c46d092018-04-07 15:32:371763 this._collapsed = consoleMessage.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed;
1764 /** @type {?UI.Icon} */
1765 this._expandGroupIcon = null;
Erik Luo8ef5d0c2018-09-25 21:16:001766 this._onToggle = onToggle;
Blink Reformat4c46d092018-04-07 15:32:371767 }
1768
1769 /**
1770 * @param {boolean} collapsed
1771 */
Erik Luo8ef5d0c2018-09-25 21:16:001772 _setCollapsed(collapsed) {
Blink Reformat4c46d092018-04-07 15:32:371773 this._collapsed = collapsed;
Tim van der Lippe1d6e57a2019-09-30 11:55:341774 if (this._expandGroupIcon) {
Blink Reformat4c46d092018-04-07 15:32:371775 this._expandGroupIcon.setIconType(this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down');
Tim van der Lippe1d6e57a2019-09-30 11:55:341776 }
Erik Luo8ef5d0c2018-09-25 21:16:001777 this._onToggle.call(null);
Blink Reformat4c46d092018-04-07 15:32:371778 }
1779
1780 /**
1781 * @return {boolean}
1782 */
1783 collapsed() {
1784 return this._collapsed;
1785 }
1786
1787 /**
1788 * @override
Erik Luo8ef5d0c2018-09-25 21:16:001789 * @param {!Event} event
1790 */
1791 maybeHandleOnKeyDown(event) {
Erik Luo0b8282e2018-10-08 20:37:461792 const focusedChildIndex = this._focusedChildIndex();
1793 if (focusedChildIndex === -1) {
1794 if ((event.key === 'ArrowLeft' && !this._collapsed) || (event.key === 'ArrowRight' && this._collapsed)) {
1795 this._setCollapsed(!this._collapsed);
1796 return true;
1797 }
Erik Luo8ef5d0c2018-09-25 21:16:001798 }
1799 return super.maybeHandleOnKeyDown(event);
1800 }
1801
1802 /**
1803 * @override
Blink Reformat4c46d092018-04-07 15:32:371804 * @return {!Element}
1805 */
1806 toMessageElement() {
1807 if (!this._element) {
1808 super.toMessageElement();
Erik Luo8ef5d0c2018-09-25 21:16:001809 const iconType = this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down';
1810 this._expandGroupIcon = UI.Icon.create(iconType, 'expand-group-icon');
Erik Luob5bfff42018-09-20 02:52:391811 // Intercept focus to avoid highlight on click.
1812 this._contentElement.tabIndex = -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341813 if (this._repeatCountElement) {
Blink Reformat4c46d092018-04-07 15:32:371814 this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341815 } else {
Blink Reformat4c46d092018-04-07 15:32:371816 this._element.insertBefore(this._expandGroupIcon, this._contentElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:341817 }
Erik Luo8ef5d0c2018-09-25 21:16:001818 this._element.addEventListener('click', () => this._setCollapsed(!this._collapsed));
Blink Reformat4c46d092018-04-07 15:32:371819 }
1820 return this._element;
1821 }
1822
1823 /**
1824 * @override
1825 */
1826 _showRepeatCountElement() {
1827 super._showRepeatCountElement();
Tim van der Lippe1d6e57a2019-09-30 11:55:341828 if (this._repeatCountElement && this._expandGroupIcon) {
Blink Reformat4c46d092018-04-07 15:32:371829 this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341830 }
Blink Reformat4c46d092018-04-07 15:32:371831 }
1832};
1833
1834/**
1835 * @const
1836 * @type {number}
1837 */
1838Console.ConsoleViewMessage.MaxLengthForLinks = 40;
1839
1840Console.ConsoleViewMessage._MaxTokenizableStringLength = 10000;
1841
1842Console.ConsoleViewMessage._LongStringVisibleLength = 5000;