blob: d7f1a4e1f20e9e7650d0991177ec6e83798ae73c [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 */
Tim van der Lippeeaacb722020-01-10 12:16:0030import {ConsoleViewportElement} from './ConsoleViewport.js'; // eslint-disable-line no-unused-vars
31
Blink Reformat4c46d092018-04-07 15:32:3732/**
Tim van der Lippeeaacb722020-01-10 12:16:0033 * @implements {ConsoleViewportElement}
Blink Reformat4c46d092018-04-07 15:32:3734 * @unrestricted
35 */
Tim van der Lippeeaacb722020-01-10 12:16:0036export class ConsoleViewMessage {
Blink Reformat4c46d092018-04-07 15:32:3737 /**
38 * @param {!SDK.ConsoleMessage} consoleMessage
39 * @param {!Components.Linkifier} linkifier
Blink Reformat4c46d092018-04-07 15:32:3740 * @param {number} nestingLevel
Erik Luo840be6b2018-12-03 20:54:2741 * @param {function(!Common.Event)} onResize
Blink Reformat4c46d092018-04-07 15:32:3742 */
Tim van der Lippeb45d9a02019-11-05 17:24:4143 constructor(consoleMessage, linkifier, nestingLevel, onResize) {
Blink Reformat4c46d092018-04-07 15:32:3744 this._message = consoleMessage;
45 this._linkifier = linkifier;
Blink Reformat4c46d092018-04-07 15:32:3746 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
137 let table = this._message.parameters && this._message.parameters.length ? this._message.parameters[0] : null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34138 if (table) {
Blink Reformat4c46d092018-04-07 15:32:37139 table = this._parameterToRemoteObject(table);
Tim van der Lippe1d6e57a2019-09-30 11:55:34140 }
141 if (!table || !table.preview) {
Erik Luo16e3e382018-11-09 02:56:01142 return this._buildMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:34143 }
Blink Reformat4c46d092018-04-07 15:32:37144
145 const rawValueColumnSymbol = Symbol('rawValueColumn');
146 const columnNames = [];
147 const preview = table.preview;
148 const rows = [];
149 for (let i = 0; i < preview.properties.length; ++i) {
150 const rowProperty = preview.properties[i];
151 let rowSubProperties;
Tim van der Lippe1d6e57a2019-09-30 11:55:34152 if (rowProperty.valuePreview) {
Blink Reformat4c46d092018-04-07 15:32:37153 rowSubProperties = rowProperty.valuePreview.properties;
Tim van der Lippe1d6e57a2019-09-30 11:55:34154 } else if (rowProperty.value) {
Blink Reformat4c46d092018-04-07 15:32:37155 rowSubProperties = [{name: rawValueColumnSymbol, type: rowProperty.type, value: rowProperty.value}];
Tim van der Lippe1d6e57a2019-09-30 11:55:34156 } else {
Blink Reformat4c46d092018-04-07 15:32:37157 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34158 }
Blink Reformat4c46d092018-04-07 15:32:37159
160 const rowValue = {};
161 const maxColumnsToRender = 20;
162 for (let j = 0; j < rowSubProperties.length; ++j) {
163 const cellProperty = rowSubProperties[j];
164 let columnRendered = columnNames.indexOf(cellProperty.name) !== -1;
165 if (!columnRendered) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34166 if (columnNames.length === maxColumnsToRender) {
Blink Reformat4c46d092018-04-07 15:32:37167 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34168 }
Blink Reformat4c46d092018-04-07 15:32:37169 columnRendered = true;
170 columnNames.push(cellProperty.name);
171 }
172
173 if (columnRendered) {
174 const cellElement = this._renderPropertyPreviewOrAccessor(table, [rowProperty, cellProperty]);
175 cellElement.classList.add('console-message-nowrap-below');
176 rowValue[cellProperty.name] = cellElement;
177 }
178 }
179 rows.push([rowProperty.name, rowValue]);
180 }
181
182 const flatValues = [];
183 for (let i = 0; i < rows.length; ++i) {
184 const rowName = rows[i][0];
185 const rowValue = rows[i][1];
186 flatValues.push(rowName);
Tim van der Lippe1d6e57a2019-09-30 11:55:34187 for (let j = 0; j < columnNames.length; ++j) {
Blink Reformat4c46d092018-04-07 15:32:37188 flatValues.push(rowValue[columnNames[j]]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34189 }
Blink Reformat4c46d092018-04-07 15:32:37190 }
191 columnNames.unshift(Common.UIString('(index)'));
192 const columnDisplayNames = columnNames.map(name => name === rawValueColumnSymbol ? Common.UIString('Value') : name);
193
194 if (flatValues.length) {
Michael Liao18769f22019-12-12 19:01:25195 this._dataGrid = DataGrid.SortableDataGrid.create(columnDisplayNames, flatValues, ls`Console`);
Blink Reformat4c46d092018-04-07 15:32:37196 this._dataGrid.setStriped(true);
Anubha Mathurfbacf4e2019-10-28 19:08:03197 this._dataGrid.setFocusable(false);
Blink Reformat4c46d092018-04-07 15:32:37198
199 const formattedResult = createElementWithClass('span', 'console-message-text');
200 const tableElement = formattedResult.createChild('div', 'console-message-formatted-table');
201 const dataGridContainer = tableElement.createChild('span');
202 tableElement.appendChild(this._formatParameter(table, true, false));
203 dataGridContainer.appendChild(this._dataGrid.element);
204 formattedMessage.appendChild(formattedResult);
205 this._dataGrid.renderInline();
206 }
207 return formattedMessage;
208 }
209
210 /**
211 * @return {!Element}
212 */
213 _buildMessage() {
214 let messageElement;
215 let messageText = this._message.messageText;
216 if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
217 switch (this._message.type) {
218 case SDK.ConsoleMessage.MessageType.Trace:
219 messageElement = this._format(this._message.parameters || ['console.trace']);
220 break;
221 case SDK.ConsoleMessage.MessageType.Clear:
222 messageElement = createElementWithClass('span', 'console-info');
Paul Lewis4b64b3f2020-01-23 11:41:20223 if (self.Common.settings.moduleSetting('preserveConsoleLog').get()) {
Blink Reformat4c46d092018-04-07 15:32:37224 messageElement.textContent = Common.UIString('console.clear() was prevented due to \'Preserve log\'');
Tim van der Lippe1d6e57a2019-09-30 11:55:34225 } else {
Blink Reformat4c46d092018-04-07 15:32:37226 messageElement.textContent = Common.UIString('Console was cleared');
Tim van der Lippe1d6e57a2019-09-30 11:55:34227 }
Blink Reformat4c46d092018-04-07 15:32:37228 messageElement.title =
Lorne Mitchell81a1a972019-03-06 18:13:13229 ls`Clear all messages with ${UI.shortcutRegistry.shortcutTitleForAction('console.clear')}`;
Blink Reformat4c46d092018-04-07 15:32:37230 break;
Blink Reformat4c46d092018-04-07 15:32:37231 case SDK.ConsoleMessage.MessageType.Dir: {
232 const obj = this._message.parameters ? this._message.parameters[0] : undefined;
233 const args = ['%O', obj];
234 messageElement = this._format(args);
235 break;
236 }
237 case SDK.ConsoleMessage.MessageType.Profile:
238 case SDK.ConsoleMessage.MessageType.ProfileEnd:
239 messageElement = this._format([messageText]);
240 break;
Pavel Feldman9f0f0a32018-12-18 02:09:13241 case SDK.ConsoleMessage.MessageType.Assert:
242 this._messagePrefix = ls`Assertion failed: `;
243 // Fall through.
Blink Reformat4c46d092018-04-07 15:32:37244 default: {
245 if (this._message.parameters && this._message.parameters.length === 1 &&
Tim van der Lippe1d6e57a2019-09-30 11:55:34246 this._message.parameters[0].type === 'string') {
Blink Reformat4c46d092018-04-07 15:32:37247 messageElement = this._tryFormatAsError(/** @type {string} */ (this._message.parameters[0].value));
Tim van der Lippe1d6e57a2019-09-30 11:55:34248 }
Blink Reformat4c46d092018-04-07 15:32:37249 const args = this._message.parameters || [messageText];
250 messageElement = messageElement || this._format(args);
251 }
252 }
253 } else {
Erik Luofc2214f2018-11-21 19:54:58254 if (this._message.source === SDK.ConsoleMessage.MessageSource.Network) {
255 messageElement = this._formatAsNetworkRequest() || this._format([messageText]);
256 } else {
Blink Reformat4c46d092018-04-07 15:32:37257 const messageInParameters =
258 this._message.parameters && messageText === /** @type {string} */ (this._message.parameters[0]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34259 if (this._message.source === SDK.ConsoleMessage.MessageSource.Violation) {
Blink Reformat4c46d092018-04-07 15:32:37260 messageText = Common.UIString('[Violation] %s', messageText);
Tim van der Lippe1d6e57a2019-09-30 11:55:34261 } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Intervention) {
Blink Reformat4c46d092018-04-07 15:32:37262 messageText = Common.UIString('[Intervention] %s', messageText);
Tim van der Lippe1d6e57a2019-09-30 11:55:34263 } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation) {
Blink Reformat4c46d092018-04-07 15:32:37264 messageText = Common.UIString('[Deprecation] %s', messageText);
Tim van der Lippe1d6e57a2019-09-30 11:55:34265 }
Blink Reformat4c46d092018-04-07 15:32:37266 const args = this._message.parameters || [messageText];
Tim van der Lippe1d6e57a2019-09-30 11:55:34267 if (messageInParameters) {
Blink Reformat4c46d092018-04-07 15:32:37268 args[0] = messageText;
Tim van der Lippe1d6e57a2019-09-30 11:55:34269 }
Blink Reformat4c46d092018-04-07 15:32:37270 messageElement = this._format(args);
271 }
272 }
273 messageElement.classList.add('console-message-text');
274
275 const formattedMessage = createElementWithClass('span', 'source-code');
Erik Luo5976c8c2018-07-24 02:03:09276 this._anchorElement = this._buildMessageAnchor();
Tim van der Lippe1d6e57a2019-09-30 11:55:34277 if (this._anchorElement) {
Erik Luo5976c8c2018-07-24 02:03:09278 formattedMessage.appendChild(this._anchorElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34279 }
Blink Reformat4c46d092018-04-07 15:32:37280 formattedMessage.appendChild(messageElement);
281 return formattedMessage;
282 }
283
284 /**
285 * @return {?Element}
286 */
Erik Luofc2214f2018-11-21 19:54:58287 _formatAsNetworkRequest() {
288 const request = SDK.NetworkLog.requestForConsoleMessage(this._message);
Tim van der Lippe1d6e57a2019-09-30 11:55:34289 if (!request) {
Erik Luofc2214f2018-11-21 19:54:58290 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34291 }
Erik Luofc2214f2018-11-21 19:54:58292 const messageElement = createElement('span');
293 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
294 messageElement.createTextChild(request.requestMethod + ' ');
Erik Luo182bece2018-11-29 03:15:22295 const linkElement = Components.Linkifier.linkifyRevealable(request, request.url(), request.url());
296 // Focus is handled by the viewport.
297 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:39298 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo182bece2018-11-29 03:15:22299 messageElement.appendChild(linkElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34300 if (request.failed) {
Erik Luofc2214f2018-11-21 19:54:58301 messageElement.createTextChildren(' ', request.localizedFailDescription);
Tim van der Lippe1d6e57a2019-09-30 11:55:34302 }
303 if (request.statusCode !== 0) {
Erik Luofc2214f2018-11-21 19:54:58304 messageElement.createTextChildren(' ', String(request.statusCode));
Tim van der Lippe1d6e57a2019-09-30 11:55:34305 }
306 if (request.statusText) {
Erik Luofc2214f2018-11-21 19:54:58307 messageElement.createTextChildren(' (', request.statusText, ')');
Tim van der Lippe1d6e57a2019-09-30 11:55:34308 }
Erik Luofc2214f2018-11-21 19:54:58309 } else {
Erik Luoad5f3942019-03-26 20:53:44310 const messageText = this._message.messageText;
311 const fragment = this._linkifyWithCustomLinkifier(messageText, (text, url, lineNumber, columnNumber) => {
312 let linkElement;
313 if (url === request.url()) {
314 linkElement = Components.Linkifier.linkifyRevealable(
315 /** @type {!SDK.NetworkRequest} */ (request), url, request.url());
316 } else {
317 linkElement = Components.Linkifier.linkifyURL(url, {text, lineNumber, columnNumber});
318 }
Erik Luo182bece2018-11-29 03:15:22319 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:39320 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo182bece2018-11-29 03:15:22321 return linkElement;
322 });
Erik Luofc2214f2018-11-21 19:54:58323 messageElement.appendChild(fragment);
324 }
325 return messageElement;
326 }
327
328 /**
329 * @return {?Element}
330 */
Blink Reformat4c46d092018-04-07 15:32:37331 _buildMessageAnchor() {
332 let anchorElement = null;
333 if (this._message.scriptId) {
334 anchorElement = this._linkifyScriptId(
335 this._message.scriptId, this._message.url || '', this._message.line, this._message.column);
336 } else if (this._message.stackTrace && this._message.stackTrace.callFrames.length) {
337 anchorElement = this._linkifyStackTraceTopFrame(this._message.stackTrace);
338 } else if (this._message.url && this._message.url !== 'undefined') {
339 anchorElement = this._linkifyLocation(this._message.url, this._message.line, this._message.column);
340 }
341
342 // Append a space to prevent the anchor text from being glued to the console message when the user selects and copies the console messages.
343 if (anchorElement) {
John Emauf7e30fb2019-10-04 19:12:32344 anchorElement.tabIndex = -1;
345 this._selectableChildren.push({
346 element: anchorElement,
347 forceSelect: () => anchorElement.focus(),
348 });
Blink Reformat4c46d092018-04-07 15:32:37349 const anchorWrapperElement = createElementWithClass('span', 'console-message-anchor');
350 anchorWrapperElement.appendChild(anchorElement);
351 anchorWrapperElement.createTextChild(' ');
352 return anchorWrapperElement;
353 }
354 return null;
355 }
356
357 /**
Blink Reformat4c46d092018-04-07 15:32:37358 * @return {!Element}
359 */
360 _buildMessageWithStackTrace() {
361 const toggleElement = createElementWithClass('div', 'console-message-stack-trace-toggle');
362 const contentElement = toggleElement.createChild('div', 'console-message-stack-trace-wrapper');
363
364 const messageElement = this._buildMessage();
365 const icon = UI.Icon.create('smallicon-triangle-right', 'console-message-expand-icon');
366 const clickableElement = contentElement.createChild('div');
367 clickableElement.appendChild(icon);
Erik Luob5bfff42018-09-20 02:52:39368 // Intercept focus to avoid highlight on click.
369 clickableElement.tabIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:37370
371 clickableElement.appendChild(messageElement);
372 const stackTraceElement = contentElement.createChild('div');
373 const stackTracePreview = Components.JSPresentationUtils.buildStackTracePreviewContents(
Jack Lynch7bc9bf22020-01-13 17:16:00374 this._message.runtimeModel().target(), this._linkifier, {stackTrace: this._message.stackTrace});
Erik Luo182bece2018-11-29 03:15:22375 stackTraceElement.appendChild(stackTracePreview.element);
376 for (const linkElement of stackTracePreview.links) {
Erik Luo31c21f62018-12-13 03:39:39377 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo182bece2018-11-29 03:15:22378 }
Blink Reformat4c46d092018-04-07 15:32:37379 stackTraceElement.classList.add('hidden');
Brandon Goddard04a5a762019-12-10 16:45:53380 UI.ARIAUtils.markAsTreeitem(this.element());
381 UI.ARIAUtils.setExpanded(this.element(), false);
Erik Luo8ef5d0c2018-09-25 21:16:00382 this._expandTrace = expand => {
Blink Reformat4c46d092018-04-07 15:32:37383 icon.setIconType(expand ? 'smallicon-triangle-down' : 'smallicon-triangle-right');
384 stackTraceElement.classList.toggle('hidden', !expand);
Brandon Goddard04a5a762019-12-10 16:45:53385 UI.ARIAUtils.setExpanded(this.element(), expand);
Erik Luo8ef5d0c2018-09-25 21:16:00386 this._traceExpanded = expand;
387 };
Blink Reformat4c46d092018-04-07 15:32:37388
389 /**
Tim van der Lippeeaacb722020-01-10 12:16:00390 * @this {!ConsoleViewMessage}
Blink Reformat4c46d092018-04-07 15:32:37391 * @param {?Event} event
392 */
393 function toggleStackTrace(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34394 if (UI.isEditing() || contentElement.hasSelection()) {
Blink Reformat4c46d092018-04-07 15:32:37395 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34396 }
Erik Luo8ef5d0c2018-09-25 21:16:00397 this._expandTrace(stackTraceElement.classList.contains('hidden'));
Blink Reformat4c46d092018-04-07 15:32:37398 event.consume();
399 }
400
Erik Luo8ef5d0c2018-09-25 21:16:00401 clickableElement.addEventListener('click', toggleStackTrace.bind(this), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34402 if (this._message.type === SDK.ConsoleMessage.MessageType.Trace) {
Erik Luo8ef5d0c2018-09-25 21:16:00403 this._expandTrace(true);
Tim van der Lippe1d6e57a2019-09-30 11:55:34404 }
Blink Reformat4c46d092018-04-07 15:32:37405
Erik Luo8ef5d0c2018-09-25 21:16:00406 toggleElement._expandStackTraceForTest = this._expandTrace.bind(this, true);
Blink Reformat4c46d092018-04-07 15:32:37407 return toggleElement;
408 }
409
410 /**
411 * @param {string} url
412 * @param {number} lineNumber
413 * @param {number} columnNumber
414 * @return {?Element}
415 */
416 _linkifyLocation(url, lineNumber, columnNumber) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34417 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37418 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34419 }
Blink Reformat4c46d092018-04-07 15:32:37420 return this._linkifier.linkifyScriptLocation(
Jack Lynch236e1d22020-01-07 20:33:51421 this._message.runtimeModel().target(), /* scriptId */ null, url, lineNumber, {columnNumber});
Blink Reformat4c46d092018-04-07 15:32:37422 }
423
424 /**
425 * @param {!Protocol.Runtime.StackTrace} stackTrace
426 * @return {?Element}
427 */
428 _linkifyStackTraceTopFrame(stackTrace) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34429 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37430 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34431 }
Blink Reformat4c46d092018-04-07 15:32:37432 return this._linkifier.linkifyStackTraceTopFrame(this._message.runtimeModel().target(), stackTrace);
433 }
434
435 /**
436 * @param {string} scriptId
437 * @param {string} url
438 * @param {number} lineNumber
439 * @param {number} columnNumber
440 * @return {?Element}
441 */
442 _linkifyScriptId(scriptId, url, lineNumber, columnNumber) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34443 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37444 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34445 }
Blink Reformat4c46d092018-04-07 15:32:37446 return this._linkifier.linkifyScriptLocation(
Jack Lynch236e1d22020-01-07 20:33:51447 this._message.runtimeModel().target(), scriptId, url, lineNumber, {columnNumber});
Blink Reformat4c46d092018-04-07 15:32:37448 }
449
450 /**
451 * @param {!SDK.RemoteObject|!Protocol.Runtime.RemoteObject|string} parameter
452 * @return {!SDK.RemoteObject}
453 */
454 _parameterToRemoteObject(parameter) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34455 if (parameter instanceof SDK.RemoteObject) {
Blink Reformat4c46d092018-04-07 15:32:37456 return parameter;
Tim van der Lippe1d6e57a2019-09-30 11:55:34457 }
Blink Reformat4c46d092018-04-07 15:32:37458 const runtimeModel = this._message.runtimeModel();
Tim van der Lippe1d6e57a2019-09-30 11:55:34459 if (!runtimeModel) {
Blink Reformat4c46d092018-04-07 15:32:37460 return SDK.RemoteObject.fromLocalObject(parameter);
Tim van der Lippe1d6e57a2019-09-30 11:55:34461 }
462 if (typeof parameter === 'object') {
Blink Reformat4c46d092018-04-07 15:32:37463 return runtimeModel.createRemoteObject(parameter);
Tim van der Lippe1d6e57a2019-09-30 11:55:34464 }
Blink Reformat4c46d092018-04-07 15:32:37465 return runtimeModel.createRemoteObjectFromPrimitiveValue(parameter);
466 }
467
468 /**
469 * @param {!Array.<!SDK.RemoteObject|string>} rawParameters
470 * @return {!Element}
471 */
472 _format(rawParameters) {
473 // This node is used like a Builder. Values are continually appended onto it.
474 const formattedResult = createElement('span');
Tim van der Lippe1d6e57a2019-09-30 11:55:34475 if (this._messagePrefix) {
Pavel Feldman9f0f0a32018-12-18 02:09:13476 formattedResult.createChild('span').textContent = this._messagePrefix;
Tim van der Lippe1d6e57a2019-09-30 11:55:34477 }
478 if (!rawParameters.length) {
Blink Reformat4c46d092018-04-07 15:32:37479 return formattedResult;
Tim van der Lippe1d6e57a2019-09-30 11:55:34480 }
Blink Reformat4c46d092018-04-07 15:32:37481
482 // Formatting code below assumes that parameters are all wrappers whereas frontend console
483 // API allows passing arbitrary values as messages (strings, numbers, etc.). Wrap them here.
484 // FIXME: Only pass runtime wrappers here.
485 let parameters = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:34486 for (let i = 0; i < rawParameters.length; ++i) {
Blink Reformat4c46d092018-04-07 15:32:37487 parameters[i] = this._parameterToRemoteObject(rawParameters[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34488 }
Blink Reformat4c46d092018-04-07 15:32:37489
490 // There can be string log and string eval result. We distinguish between them based on message type.
491 const shouldFormatMessage =
492 SDK.RemoteObject.type((/** @type {!Array.<!SDK.RemoteObject>} **/ (parameters))[0]) === 'string' &&
493 (this._message.type !== SDK.ConsoleMessage.MessageType.Result ||
494 this._message.level === SDK.ConsoleMessage.MessageLevel.Error);
495
496 // Multiple parameters with the first being a format string. Save unused substitutions.
497 if (shouldFormatMessage) {
498 const result = this._formatWithSubstitutionString(
499 /** @type {string} **/ (parameters[0].description), parameters.slice(1), formattedResult);
500 parameters = result.unusedSubstitutions;
Tim van der Lippe1d6e57a2019-09-30 11:55:34501 if (parameters.length) {
Blink Reformat4c46d092018-04-07 15:32:37502 formattedResult.createTextChild(' ');
Tim van der Lippe1d6e57a2019-09-30 11:55:34503 }
Blink Reformat4c46d092018-04-07 15:32:37504 }
505
506 // Single parameter, or unused substitutions from above.
507 for (let i = 0; i < parameters.length; ++i) {
508 // Inline strings when formatting.
Tim van der Lippe1d6e57a2019-09-30 11:55:34509 if (shouldFormatMessage && parameters[i].type === 'string') {
Erik Luo383f21d2018-11-07 23:16:37510 formattedResult.appendChild(this._linkifyStringAsFragment(parameters[i].description));
Tim van der Lippe1d6e57a2019-09-30 11:55:34511 } else {
Blink Reformat4c46d092018-04-07 15:32:37512 formattedResult.appendChild(this._formatParameter(parameters[i], false, true));
Tim van der Lippe1d6e57a2019-09-30 11:55:34513 }
514 if (i < parameters.length - 1) {
Blink Reformat4c46d092018-04-07 15:32:37515 formattedResult.createTextChild(' ');
Tim van der Lippe1d6e57a2019-09-30 11:55:34516 }
Blink Reformat4c46d092018-04-07 15:32:37517 }
518 return formattedResult;
519 }
520
521 /**
522 * @param {!SDK.RemoteObject} output
523 * @param {boolean=} forceObjectFormat
524 * @param {boolean=} includePreview
525 * @return {!Element}
526 */
527 _formatParameter(output, forceObjectFormat, includePreview) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34528 if (output.customPreview()) {
Blink Reformat4c46d092018-04-07 15:32:37529 return (new ObjectUI.CustomPreviewComponent(output)).element;
Tim van der Lippe1d6e57a2019-09-30 11:55:34530 }
Blink Reformat4c46d092018-04-07 15:32:37531
532 const type = forceObjectFormat ? 'object' : (output.subtype || output.type);
533 let element;
534 switch (type) {
535 case 'error':
536 element = this._formatParameterAsError(output);
537 break;
538 case 'function':
539 element = this._formatParameterAsFunction(output, includePreview);
540 break;
541 case 'array':
542 case 'arraybuffer':
543 case 'blob':
544 case 'dataview':
545 case 'generator':
546 case 'iterator':
547 case 'map':
548 case 'object':
549 case 'promise':
550 case 'proxy':
551 case 'set':
552 case 'typedarray':
553 case 'weakmap':
554 case 'weakset':
555 element = this._formatParameterAsObject(output, includePreview);
556 break;
557 case 'node':
558 element = output.isNode() ? this._formatParameterAsNode(output) : this._formatParameterAsObject(output, false);
559 break;
560 case 'string':
561 element = this._formatParameterAsString(output);
562 break;
563 case 'boolean':
564 case 'date':
565 case 'null':
566 case 'number':
567 case 'regexp':
568 case 'symbol':
569 case 'undefined':
570 case 'bigint':
571 element = this._formatParameterAsValue(output);
572 break;
573 default:
574 element = this._formatParameterAsValue(output);
575 console.error('Tried to format remote object of unknown type.');
576 }
577 element.classList.add('object-value-' + type);
578 element.classList.add('source-code');
579 return element;
580 }
581
582 /**
583 * @param {!SDK.RemoteObject} obj
584 * @return {!Element}
Tim van der Lippeeaacb722020-01-10 12:16:00585 * @suppress {accessControls}
Blink Reformat4c46d092018-04-07 15:32:37586 */
587 _formatParameterAsValue(obj) {
588 const result = createElement('span');
589 const description = obj.description || '';
Tim van der Lippe1d6e57a2019-09-30 11:55:34590 if (description.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Connor Moody1a5c0d32019-12-19 07:23:36591 const propertyValue = new ObjectUI.ExpandableTextPropertyValue(
592 createElement('span'), description, Console.ConsoleViewMessage._LongStringVisibleLength);
593 result.appendChild(propertyValue.element);
Tim van der Lippe1d6e57a2019-09-30 11:55:34594 } else {
Blink Reformat4c46d092018-04-07 15:32:37595 result.createTextChild(description);
Tim van der Lippe1d6e57a2019-09-30 11:55:34596 }
597 if (obj.objectId) {
Blink Reformat4c46d092018-04-07 15:32:37598 result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, obj), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34599 }
Blink Reformat4c46d092018-04-07 15:32:37600 return result;
601 }
602
603 /**
604 * @param {!SDK.RemoteObject} obj
605 * @param {boolean=} includePreview
606 * @return {!Element}
607 */
608 _formatParameterAsObject(obj, includePreview) {
609 const titleElement = createElementWithClass('span', 'console-object');
610 if (includePreview && obj.preview) {
611 titleElement.classList.add('console-object-preview');
612 this._previewFormatter.appendObjectPreview(titleElement, obj.preview, false /* isEntry */);
613 } else if (obj.type === 'function') {
614 const functionElement = titleElement.createChild('span');
615 ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(obj, functionElement, false);
616 titleElement.classList.add('object-value-function');
617 } else {
618 titleElement.createTextChild(obj.description || '');
619 }
620
Tim van der Lippe1d6e57a2019-09-30 11:55:34621 if (!obj.hasChildren || obj.customPreview()) {
Blink Reformat4c46d092018-04-07 15:32:37622 return titleElement;
Tim van der Lippe1d6e57a2019-09-30 11:55:34623 }
Blink Reformat4c46d092018-04-07 15:32:37624
625 const note = titleElement.createChild('span', 'object-state-note info-note');
Tim van der Lippe1d6e57a2019-09-30 11:55:34626 if (this._message.type === SDK.ConsoleMessage.MessageType.QueryObjectResult) {
Blink Reformat4c46d092018-04-07 15:32:37627 note.title = ls`This value will not be collected until console is cleared.`;
Tim van der Lippe1d6e57a2019-09-30 11:55:34628 } else {
Blink Reformat4c46d092018-04-07 15:32:37629 note.title = ls`Value below was evaluated just now.`;
Tim van der Lippe1d6e57a2019-09-30 11:55:34630 }
Blink Reformat4c46d092018-04-07 15:32:37631
632 const section = new ObjectUI.ObjectPropertiesSection(obj, titleElement, this._linkifier);
633 section.element.classList.add('console-view-object-properties-section');
634 section.enableContextMenu();
Erik Luocc14b812018-11-03 01:33:09635 section.setShowSelectionOnKeyboardFocus(true, true);
Erik Luo383f21d2018-11-07 23:16:37636 this._selectableChildren.push(section);
Erik Luo840be6b2018-12-03 20:54:27637 section.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
638 section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
639 section.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
Blink Reformat4c46d092018-04-07 15:32:37640 return section.element;
641 }
642
643 /**
644 * @param {!SDK.RemoteObject} func
645 * @param {boolean=} includePreview
646 * @return {!Element}
647 */
648 _formatParameterAsFunction(func, includePreview) {
649 const result = createElement('span');
650 SDK.RemoteFunction.objectAsFunction(func).targetFunction().then(formatTargetFunction.bind(this));
651 return result;
652
653 /**
654 * @param {!SDK.RemoteObject} targetFunction
Tim van der Lippeeaacb722020-01-10 12:16:00655 * @this {ConsoleViewMessage}
Blink Reformat4c46d092018-04-07 15:32:37656 */
657 function formatTargetFunction(targetFunction) {
658 const functionElement = createElement('span');
Joey Arhard78a58f2018-12-05 01:59:45659 const promise = ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(
660 targetFunction, functionElement, true, includePreview);
Blink Reformat4c46d092018-04-07 15:32:37661 result.appendChild(functionElement);
662 if (targetFunction !== func) {
663 const note = result.createChild('span', 'object-info-state-note');
664 note.title = Common.UIString('Function was resolved from bound function.');
665 }
666 result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, targetFunction), false);
Joey Arhard78a58f2018-12-05 01:59:45667 promise.then(() => this._formattedParameterAsFunctionForTest());
Blink Reformat4c46d092018-04-07 15:32:37668 }
669 }
670
Joey Arhard78a58f2018-12-05 01:59:45671 _formattedParameterAsFunctionForTest() {
672 }
673
Blink Reformat4c46d092018-04-07 15:32:37674 /**
675 * @param {!SDK.RemoteObject} obj
676 * @param {!Event} event
677 */
678 _contextMenuEventFired(obj, event) {
679 const contextMenu = new UI.ContextMenu(event);
680 contextMenu.appendApplicableItems(obj);
681 contextMenu.show();
682 }
683
684 /**
685 * @param {?SDK.RemoteObject} object
686 * @param {!Array.<!Protocol.Runtime.PropertyPreview>} propertyPath
687 * @return {!Element}
688 */
689 _renderPropertyPreviewOrAccessor(object, propertyPath) {
690 const property = propertyPath.peekLast();
Tim van der Lippe1d6e57a2019-09-30 11:55:34691 if (property.type === 'accessor') {
Blink Reformat4c46d092018-04-07 15:32:37692 return this._formatAsAccessorProperty(object, propertyPath.map(property => property.name), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34693 }
Blink Reformat4c46d092018-04-07 15:32:37694 return this._previewFormatter.renderPropertyPreview(
695 property.type, /** @type {string} */ (property.subtype), property.value);
696 }
697
698 /**
699 * @param {!SDK.RemoteObject} remoteObject
700 * @return {!Element}
701 */
702 _formatParameterAsNode(remoteObject) {
703 const result = createElement('span');
704
705 const domModel = remoteObject.runtimeModel().target().model(SDK.DOMModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34706 if (!domModel) {
Blink Reformat4c46d092018-04-07 15:32:37707 return result;
Tim van der Lippe1d6e57a2019-09-30 11:55:34708 }
Erik Luo54fdd912018-11-01 17:57:01709 domModel.pushObjectAsNodeToFrontend(remoteObject).then(async node => {
Blink Reformat4c46d092018-04-07 15:32:37710 if (!node) {
711 result.appendChild(this._formatParameterAsObject(remoteObject, false));
712 return;
713 }
Erik Luo54fdd912018-11-01 17:57:01714 const renderResult = await UI.Renderer.render(/** @type {!Object} */ (node));
Erik Luofc6a6302018-11-02 06:48:52715 if (renderResult) {
Erik Luo840be6b2018-12-03 20:54:27716 if (renderResult.tree) {
Erik Luo383f21d2018-11-07 23:16:37717 this._selectableChildren.push(renderResult.tree);
Erik Luo840be6b2018-12-03 20:54:27718 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
719 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
720 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
721 }
Erik Luofc6a6302018-11-02 06:48:52722 result.appendChild(renderResult.node);
723 } else {
724 result.appendChild(this._formatParameterAsObject(remoteObject, false));
725 }
Erik Luo54fdd912018-11-01 17:57:01726 this._formattedParameterAsNodeForTest();
Blink Reformat4c46d092018-04-07 15:32:37727 });
728
729 return result;
730 }
731
732 _formattedParameterAsNodeForTest() {
733 }
734
735 /**
736 * @param {!SDK.RemoteObject} output
737 * @return {!Element}
738 */
739 _formatParameterAsString(output) {
740 const span = createElement('span');
Erik Luo383f21d2018-11-07 23:16:37741 span.appendChild(this._linkifyStringAsFragment(output.description || ''));
Blink Reformat4c46d092018-04-07 15:32:37742
743 const result = createElement('span');
744 result.createChild('span', 'object-value-string-quote').textContent = '"';
745 result.appendChild(span);
746 result.createChild('span', 'object-value-string-quote').textContent = '"';
747 return result;
748 }
749
750 /**
751 * @param {!SDK.RemoteObject} output
752 * @return {!Element}
753 */
754 _formatParameterAsError(output) {
755 const result = createElement('span');
756 const errorSpan = this._tryFormatAsError(output.description || '');
Erik Luo383f21d2018-11-07 23:16:37757 result.appendChild(errorSpan ? errorSpan : this._linkifyStringAsFragment(output.description || ''));
Blink Reformat4c46d092018-04-07 15:32:37758 return result;
759 }
760
761 /**
762 * @param {!SDK.RemoteObject} output
763 * @return {!Element}
764 */
765 _formatAsArrayEntry(output) {
766 return this._previewFormatter.renderPropertyPreview(output.type, output.subtype, output.description);
767 }
768
769 /**
770 * @param {?SDK.RemoteObject} object
771 * @param {!Array.<string>} propertyPath
772 * @param {boolean} isArrayEntry
773 * @return {!Element}
774 */
775 _formatAsAccessorProperty(object, propertyPath, isArrayEntry) {
776 const rootElement = ObjectUI.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan(
777 object, propertyPath, onInvokeGetterClick.bind(this));
778
779 /**
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18780 * @param {!SDK.CallFunctionResult} result
Tim van der Lippeeaacb722020-01-10 12:16:00781 * @this {ConsoleViewMessage}
Blink Reformat4c46d092018-04-07 15:32:37782 */
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18783 function onInvokeGetterClick(result) {
784 const wasThrown = result.wasThrown;
785 const object = result.object;
Tim van der Lippe1d6e57a2019-09-30 11:55:34786 if (!object) {
Blink Reformat4c46d092018-04-07 15:32:37787 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34788 }
Blink Reformat4c46d092018-04-07 15:32:37789 rootElement.removeChildren();
790 if (wasThrown) {
791 const element = rootElement.createChild('span');
792 element.textContent = Common.UIString('<exception>');
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18793 element.title = /** @type {string} */ (object.description);
Blink Reformat4c46d092018-04-07 15:32:37794 } else if (isArrayEntry) {
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18795 rootElement.appendChild(this._formatAsArrayEntry(object));
Blink Reformat4c46d092018-04-07 15:32:37796 } else {
797 // Make a PropertyPreview from the RemoteObject similar to the backend logic.
798 const maxLength = 100;
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18799 const type = object.type;
800 const subtype = object.subtype;
Blink Reformat4c46d092018-04-07 15:32:37801 let description = '';
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18802 if (type !== 'function' && object.description) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34803 if (type === 'string' || subtype === 'regexp') {
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18804 description = object.description.trimMiddle(maxLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:34805 } else {
Tim van der Lippeffa78622019-09-16 12:07:12806 description = object.description.trimEndWithMaxLength(maxLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:34807 }
Blink Reformat4c46d092018-04-07 15:32:37808 }
809 rootElement.appendChild(this._previewFormatter.renderPropertyPreview(type, subtype, description));
810 }
811 }
812
813 return rootElement;
814 }
815
816 /**
817 * @param {string} format
818 * @param {!Array.<!SDK.RemoteObject>} parameters
819 * @param {!Element} formattedResult
820 */
821 _formatWithSubstitutionString(format, parameters, formattedResult) {
822 const formatters = {};
823
824 /**
825 * @param {boolean} force
826 * @param {boolean} includePreview
827 * @param {!SDK.RemoteObject} obj
828 * @return {!Element}
Tim van der Lippeeaacb722020-01-10 12:16:00829 * @this {ConsoleViewMessage}
Blink Reformat4c46d092018-04-07 15:32:37830 */
831 function parameterFormatter(force, includePreview, obj) {
832 return this._formatParameter(obj, force, includePreview);
833 }
834
835 function stringFormatter(obj) {
836 return obj.description;
837 }
838
839 function floatFormatter(obj) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34840 if (typeof obj.value !== 'number') {
Blink Reformat4c46d092018-04-07 15:32:37841 return 'NaN';
Tim van der Lippe1d6e57a2019-09-30 11:55:34842 }
Blink Reformat4c46d092018-04-07 15:32:37843 return obj.value;
844 }
845
846 function integerFormatter(obj) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34847 if (obj.type === 'bigint') {
Alexey Kozyatinskiybeb38de2018-08-10 18:54:19848 return obj.description;
Tim van der Lippe1d6e57a2019-09-30 11:55:34849 }
850 if (typeof obj.value !== 'number') {
Blink Reformat4c46d092018-04-07 15:32:37851 return 'NaN';
Tim van der Lippe1d6e57a2019-09-30 11:55:34852 }
Blink Reformat4c46d092018-04-07 15:32:37853 return Math.floor(obj.value);
854 }
855
856 function bypassFormatter(obj) {
857 return (obj instanceof Node) ? obj : '';
858 }
859
860 let currentStyle = null;
861 function styleFormatter(obj) {
862 currentStyle = {};
863 const buffer = createElement('span');
864 buffer.setAttribute('style', obj.description);
865 for (let i = 0; i < buffer.style.length; i++) {
866 const property = buffer.style[i];
Tim van der Lippe1d6e57a2019-09-30 11:55:34867 if (isWhitelistedProperty(property)) {
Blink Reformat4c46d092018-04-07 15:32:37868 currentStyle[property] = buffer.style[property];
Tim van der Lippe1d6e57a2019-09-30 11:55:34869 }
Blink Reformat4c46d092018-04-07 15:32:37870 }
871 }
872
873 function isWhitelistedProperty(property) {
874 // Make sure that allowed properties do not interfere with link visibility.
875 const prefixes = [
876 'background', 'border', 'color', 'font', 'line', 'margin', 'padding', 'text', '-webkit-background',
877 '-webkit-border', '-webkit-font', '-webkit-margin', '-webkit-padding', '-webkit-text'
878 ];
879 for (let i = 0; i < prefixes.length; i++) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34880 if (property.startsWith(prefixes[i])) {
Blink Reformat4c46d092018-04-07 15:32:37881 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:34882 }
Blink Reformat4c46d092018-04-07 15:32:37883 }
884 return false;
885 }
886
887 // Firebug uses %o for formatting objects.
888 formatters.o = parameterFormatter.bind(this, false /* force */, true /* includePreview */);
889 formatters.s = stringFormatter;
890 formatters.f = floatFormatter;
891 // Firebug allows both %i and %d for formatting integers.
892 formatters.i = integerFormatter;
893 formatters.d = integerFormatter;
894
895 // Firebug uses %c for styling the message.
896 formatters.c = styleFormatter;
897
898 // Support %O to force object formatting, instead of the type-based %o formatting.
899 formatters.O = parameterFormatter.bind(this, true /* force */, false /* includePreview */);
900
901 formatters._ = bypassFormatter;
902
903 /**
904 * @param {!Element} a
905 * @param {*} b
Tim van der Lippeeaacb722020-01-10 12:16:00906 * @this {!ConsoleViewMessage}
Erik Luo17926392018-05-17 22:06:12907 * @return {!Element}
Blink Reformat4c46d092018-04-07 15:32:37908 */
909 function append(a, b) {
910 if (b instanceof Node) {
911 a.appendChild(b);
Erik Luo17926392018-05-17 22:06:12912 return a;
913 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34914 if (typeof b === 'undefined') {
Erik Luo17926392018-05-17 22:06:12915 return a;
Tim van der Lippe1d6e57a2019-09-30 11:55:34916 }
Erik Luo17926392018-05-17 22:06:12917 if (!currentStyle) {
Erik Luo383f21d2018-11-07 23:16:37918 a.appendChild(this._linkifyStringAsFragment(String(b)));
Erik Luo17926392018-05-17 22:06:12919 return a;
920 }
921 const lines = String(b).split('\n');
922 for (let i = 0; i < lines.length; i++) {
923 const line = lines[i];
Erik Luo383f21d2018-11-07 23:16:37924 const lineFragment = this._linkifyStringAsFragment(line);
Erik Luo17926392018-05-17 22:06:12925 const wrapper = createElement('span');
926 wrapper.style.setProperty('contain', 'paint');
927 wrapper.style.setProperty('display', 'inline-block');
928 wrapper.style.setProperty('max-width', '100%');
929 wrapper.appendChild(lineFragment);
930 applyCurrentStyle(wrapper);
931 for (const child of wrapper.children) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34932 if (child.classList.contains('devtools-link')) {
Erik Luo17926392018-05-17 22:06:12933 this._applyForcedVisibleStyle(child);
Tim van der Lippe1d6e57a2019-09-30 11:55:34934 }
Blink Reformat4c46d092018-04-07 15:32:37935 }
Erik Luo17926392018-05-17 22:06:12936 a.appendChild(wrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34937 if (i < lines.length - 1) {
Erik Luo17926392018-05-17 22:06:12938 a.appendChild(createElement('br'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34939 }
Blink Reformat4c46d092018-04-07 15:32:37940 }
941 return a;
942 }
943
944 /**
945 * @param {!Element} element
946 */
947 function applyCurrentStyle(element) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34948 for (const key in currentStyle) {
Blink Reformat4c46d092018-04-07 15:32:37949 element.style[key] = currentStyle[key];
Tim van der Lippe1d6e57a2019-09-30 11:55:34950 }
Blink Reformat4c46d092018-04-07 15:32:37951 }
952
953 // String.format does treat formattedResult like a Builder, result is an object.
954 return String.format(format, parameters, formatters, formattedResult, append.bind(this));
955 }
956
957 /**
958 * @param {!Element} element
959 */
960 _applyForcedVisibleStyle(element) {
961 element.style.setProperty('-webkit-text-stroke', '0', 'important');
962 element.style.setProperty('text-decoration', 'underline', 'important');
963
964 const themedColor = UI.themeSupport.patchColorText('rgb(33%, 33%, 33%)', UI.ThemeSupport.ColorUsage.Foreground);
965 element.style.setProperty('color', themedColor, 'important');
966
967 let backgroundColor = 'hsl(0, 0%, 100%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:34968 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
Blink Reformat4c46d092018-04-07 15:32:37969 backgroundColor = 'hsl(0, 100%, 97%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:34970 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning || this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:37971 backgroundColor = 'hsl(50, 100%, 95%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:34972 }
Blink Reformat4c46d092018-04-07 15:32:37973 const themedBackgroundColor =
974 UI.themeSupport.patchColorText(backgroundColor, UI.ThemeSupport.ColorUsage.Background);
975 element.style.setProperty('background-color', themedBackgroundColor, 'important');
976 }
977
978 /**
979 * @return {boolean}
980 */
981 matchesFilterRegex(regexObject) {
982 regexObject.lastIndex = 0;
Erik Luo5976c8c2018-07-24 02:03:09983 const contentElement = this.contentElement();
984 const anchorText = this._anchorElement ? this._anchorElement.deepTextContent() : '';
985 return (anchorText && regexObject.test(anchorText.trim())) ||
986 regexObject.test(contentElement.deepTextContent().slice(anchorText.length));
Blink Reformat4c46d092018-04-07 15:32:37987 }
988
989 /**
990 * @param {string} filter
991 * @return {boolean}
992 */
993 matchesFilterText(filter) {
994 const text = this.contentElement().deepTextContent();
995 return text.toLowerCase().includes(filter.toLowerCase());
996 }
997
998 updateTimestamp() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34999 if (!this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371000 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341001 }
Blink Reformat4c46d092018-04-07 15:32:371002
Paul Lewis4b64b3f2020-01-23 11:41:201003 if (self.Common.settings.moduleSetting('consoleTimestampsEnabled').get()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341004 if (!this._timestampElement) {
Blink Reformat4c46d092018-04-07 15:32:371005 this._timestampElement = createElementWithClass('span', 'console-timestamp');
Tim van der Lippe1d6e57a2019-09-30 11:55:341006 }
Rayan Kansoaca06e72019-03-27 11:57:061007 this._timestampElement.textContent = UI.formatTimestamp(this._message.timestamp, false) + ' ';
1008 this._timestampElement.title = UI.formatTimestamp(this._message.timestamp, true);
Blink Reformat4c46d092018-04-07 15:32:371009 this._contentElement.insertBefore(this._timestampElement, this._contentElement.firstChild);
1010 } else if (this._timestampElement) {
1011 this._timestampElement.remove();
1012 delete this._timestampElement;
1013 }
Blink Reformat4c46d092018-04-07 15:32:371014 }
1015
1016 /**
1017 * @return {number}
1018 */
1019 nestingLevel() {
1020 return this._nestingLevel;
1021 }
1022
1023 /**
1024 * @param {boolean} inSimilarGroup
1025 * @param {boolean=} isLast
1026 */
1027 setInSimilarGroup(inSimilarGroup, isLast) {
1028 this._inSimilarGroup = inSimilarGroup;
1029 this._lastInSimilarGroup = inSimilarGroup && !!isLast;
1030 if (this._similarGroupMarker && !inSimilarGroup) {
1031 this._similarGroupMarker.remove();
1032 this._similarGroupMarker = null;
1033 } else if (this._element && !this._similarGroupMarker && inSimilarGroup) {
1034 this._similarGroupMarker = createElementWithClass('div', 'nesting-level-marker');
1035 this._element.insertBefore(this._similarGroupMarker, this._element.firstChild);
1036 this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
1037 }
1038 }
1039
1040 /**
1041 * @return {boolean}
1042 */
1043 isLastInSimilarGroup() {
1044 return this._inSimilarGroup && this._lastInSimilarGroup;
1045 }
1046
1047 resetCloseGroupDecorationCount() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341048 if (!this._closeGroupDecorationCount) {
Blink Reformat4c46d092018-04-07 15:32:371049 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341050 }
Blink Reformat4c46d092018-04-07 15:32:371051 this._closeGroupDecorationCount = 0;
1052 this._updateCloseGroupDecorations();
1053 }
1054
1055 incrementCloseGroupDecorationCount() {
1056 ++this._closeGroupDecorationCount;
1057 this._updateCloseGroupDecorations();
1058 }
1059
1060 _updateCloseGroupDecorations() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341061 if (!this._nestingLevelMarkers) {
Blink Reformat4c46d092018-04-07 15:32:371062 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341063 }
Blink Reformat4c46d092018-04-07 15:32:371064 for (let i = 0, n = this._nestingLevelMarkers.length; i < n; ++i) {
1065 const marker = this._nestingLevelMarkers[i];
1066 marker.classList.toggle('group-closed', n - i <= this._closeGroupDecorationCount);
1067 }
1068 }
1069
1070 /**
Erik Luo0b8282e2018-10-08 20:37:461071 * @return {number}
1072 */
1073 _focusedChildIndex() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341074 if (!this._selectableChildren.length) {
Erik Luo0b8282e2018-10-08 20:37:461075 return -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341076 }
Erik Luo383f21d2018-11-07 23:16:371077 return this._selectableChildren.findIndex(child => child.element.hasFocus());
Erik Luo0b8282e2018-10-08 20:37:461078 }
1079
1080 /**
Erik Luo8ef5d0c2018-09-25 21:16:001081 * @param {!Event} event
1082 */
1083 _onKeyDown(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341084 if (UI.isEditing() || !this._element.hasFocus() || this._element.hasSelection()) {
Erik Luo8ef5d0c2018-09-25 21:16:001085 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341086 }
1087 if (this.maybeHandleOnKeyDown(event)) {
Erik Luo8ef5d0c2018-09-25 21:16:001088 event.consume(true);
Tim van der Lippe1d6e57a2019-09-30 11:55:341089 }
Erik Luo8ef5d0c2018-09-25 21:16:001090 }
1091
1092 /**
1093 * @protected
1094 * @param {!Event} event
1095 */
1096 maybeHandleOnKeyDown(event) {
1097 // Handle trace expansion.
Erik Luo0b8282e2018-10-08 20:37:461098 const focusedChildIndex = this._focusedChildIndex();
1099 const isWrapperFocused = focusedChildIndex === -1;
1100 if (this._expandTrace && isWrapperFocused) {
Erik Luo8ef5d0c2018-09-25 21:16:001101 if ((event.key === 'ArrowLeft' && this._traceExpanded) || (event.key === 'ArrowRight' && !this._traceExpanded)) {
1102 this._expandTrace(!this._traceExpanded);
1103 return true;
1104 }
1105 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341106 if (!this._selectableChildren.length) {
Erik Luo0b8282e2018-10-08 20:37:461107 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:341108 }
Erik Luo0b8282e2018-10-08 20:37:461109
1110 if (event.key === 'ArrowLeft') {
1111 this._element.focus();
1112 return true;
1113 }
1114 if (event.key === 'ArrowRight') {
Tim van der Lippe1d6e57a2019-09-30 11:55:341115 if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
Erik Luo0b8282e2018-10-08 20:37:461116 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341117 }
Erik Luo0b8282e2018-10-08 20:37:461118 }
1119 if (event.key === 'ArrowUp') {
Erik Luo182bece2018-11-29 03:15:221120 const firstVisibleChild = this._nearestVisibleChild(0);
1121 if (this._selectableChildren[focusedChildIndex] === firstVisibleChild && firstVisibleChild) {
Erik Luo0b8282e2018-10-08 20:37:461122 this._element.focus();
1123 return true;
Erik Luo182bece2018-11-29 03:15:221124 } else if (this._selectNearestVisibleChild(focusedChildIndex - 1, true /* backwards */)) {
Erik Luo0b8282e2018-10-08 20:37:461125 return true;
1126 }
1127 }
1128 if (event.key === 'ArrowDown') {
Tim van der Lippe1d6e57a2019-09-30 11:55:341129 if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
Erik Luo0b8282e2018-10-08 20:37:461130 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341131 }
1132 if (!isWrapperFocused && this._selectNearestVisibleChild(focusedChildIndex + 1)) {
Erik Luo0b8282e2018-10-08 20:37:461133 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341134 }
Erik Luo0b8282e2018-10-08 20:37:461135 }
Erik Luo8ef5d0c2018-09-25 21:16:001136 return false;
1137 }
1138
Erik Luo182bece2018-11-29 03:15:221139 /**
1140 * @param {number} fromIndex
1141 * @param {boolean=} backwards
1142 * @return {boolean}
1143 */
1144 _selectNearestVisibleChild(fromIndex, backwards) {
1145 const nearestChild = this._nearestVisibleChild(fromIndex, backwards);
1146 if (nearestChild) {
Erik Luo31c21f62018-12-13 03:39:391147 nearestChild.forceSelect();
Erik Luo182bece2018-11-29 03:15:221148 return true;
1149 }
1150 return false;
1151 }
1152
1153 /**
1154 * @param {number} fromIndex
1155 * @param {boolean=} backwards
Erik Luo31c21f62018-12-13 03:39:391156 * @return {?{element: !Element, forceSelect: function()}}
Erik Luo182bece2018-11-29 03:15:221157 */
1158 _nearestVisibleChild(fromIndex, backwards) {
1159 const childCount = this._selectableChildren.length;
Tim van der Lippe1d6e57a2019-09-30 11:55:341160 if (fromIndex < 0 || fromIndex >= childCount) {
Erik Luo182bece2018-11-29 03:15:221161 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341162 }
Erik Luo182bece2018-11-29 03:15:221163 const direction = backwards ? -1 : 1;
1164 let index = fromIndex;
1165
1166 while (!this._selectableChildren[index].element.offsetParent) {
1167 index += direction;
Tim van der Lippe1d6e57a2019-09-30 11:55:341168 if (index < 0 || index >= childCount) {
Erik Luo182bece2018-11-29 03:15:221169 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341170 }
Erik Luo182bece2018-11-29 03:15:221171 }
1172 return this._selectableChildren[index];
1173 }
1174
Erik Luo0b8282e2018-10-08 20:37:461175 focusLastChildOrSelf() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341176 if (this._element && !this._selectNearestVisibleChild(this._selectableChildren.length - 1, true /* backwards */)) {
Erik Luo0b8282e2018-10-08 20:37:461177 this._element.focus();
Tim van der Lippe1d6e57a2019-09-30 11:55:341178 }
Erik Luo0b8282e2018-10-08 20:37:461179 }
1180
1181 /**
Blink Reformat4c46d092018-04-07 15:32:371182 * @return {!Element}
1183 */
1184 contentElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341185 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371186 return this._contentElement;
Tim van der Lippe1d6e57a2019-09-30 11:55:341187 }
Blink Reformat4c46d092018-04-07 15:32:371188
1189 const contentElement = createElementWithClass('div', 'console-message');
Tim van der Lippe1d6e57a2019-09-30 11:55:341190 if (this._messageLevelIcon) {
Blink Reformat4c46d092018-04-07 15:32:371191 contentElement.appendChild(this._messageLevelIcon);
Tim van der Lippe1d6e57a2019-09-30 11:55:341192 }
Blink Reformat4c46d092018-04-07 15:32:371193 this._contentElement = contentElement;
1194
1195 let formattedMessage;
1196 const shouldIncludeTrace = !!this._message.stackTrace &&
1197 (this._message.source === SDK.ConsoleMessage.MessageSource.Network ||
1198 this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
1199 this._message.level === SDK.ConsoleMessage.MessageLevel.Error ||
1200 this._message.level === SDK.ConsoleMessage.MessageLevel.Warning ||
1201 this._message.type === SDK.ConsoleMessage.MessageType.Trace);
Tim van der Lippe1d6e57a2019-09-30 11:55:341202 if (this._message.runtimeModel() && shouldIncludeTrace) {
Blink Reformat4c46d092018-04-07 15:32:371203 formattedMessage = this._buildMessageWithStackTrace();
Tim van der Lippe1d6e57a2019-09-30 11:55:341204 } else if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
Blink Reformat4c46d092018-04-07 15:32:371205 formattedMessage = this._buildTableMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:341206 } else {
Blink Reformat4c46d092018-04-07 15:32:371207 formattedMessage = this._buildMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:341208 }
Blink Reformat4c46d092018-04-07 15:32:371209 contentElement.appendChild(formattedMessage);
1210
1211 this.updateTimestamp();
1212 return this._contentElement;
1213 }
1214
1215 /**
1216 * @return {!Element}
1217 */
1218 toMessageElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341219 if (this._element) {
Blink Reformat4c46d092018-04-07 15:32:371220 return this._element;
Tim van der Lippe1d6e57a2019-09-30 11:55:341221 }
Blink Reformat4c46d092018-04-07 15:32:371222
1223 this._element = createElement('div');
Pavel Feldmandb310912019-01-30 00:31:201224 this._element.tabIndex = -1;
1225 this._element.addEventListener('keydown', this._onKeyDown.bind(this));
Blink Reformat4c46d092018-04-07 15:32:371226 this.updateMessageElement();
1227 return this._element;
1228 }
1229
1230 updateMessageElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341231 if (!this._element) {
Blink Reformat4c46d092018-04-07 15:32:371232 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341233 }
Blink Reformat4c46d092018-04-07 15:32:371234
1235 this._element.className = 'console-message-wrapper';
1236 this._element.removeChildren();
Tim van der Lippe1d6e57a2019-09-30 11:55:341237 if (this._message.isGroupStartMessage()) {
Blink Reformat4c46d092018-04-07 15:32:371238 this._element.classList.add('console-group-title');
Tim van der Lippe1d6e57a2019-09-30 11:55:341239 }
1240 if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
Blink Reformat4c46d092018-04-07 15:32:371241 this._element.classList.add('console-from-api');
Tim van der Lippe1d6e57a2019-09-30 11:55:341242 }
Blink Reformat4c46d092018-04-07 15:32:371243 if (this._inSimilarGroup) {
1244 this._similarGroupMarker = this._element.createChild('div', 'nesting-level-marker');
1245 this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
1246 }
1247
1248 this._nestingLevelMarkers = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341249 for (let i = 0; i < this._nestingLevel; ++i) {
Blink Reformat4c46d092018-04-07 15:32:371250 this._nestingLevelMarkers.push(this._element.createChild('div', 'nesting-level-marker'));
Tim van der Lippe1d6e57a2019-09-30 11:55:341251 }
Blink Reformat4c46d092018-04-07 15:32:371252 this._updateCloseGroupDecorations();
1253 this._element.message = this;
1254
1255 switch (this._message.level) {
1256 case SDK.ConsoleMessage.MessageLevel.Verbose:
1257 this._element.classList.add('console-verbose-level');
Blink Reformat4c46d092018-04-07 15:32:371258 break;
1259 case SDK.ConsoleMessage.MessageLevel.Info:
1260 this._element.classList.add('console-info-level');
Tim van der Lippe1d6e57a2019-09-30 11:55:341261 if (this._message.type === SDK.ConsoleMessage.MessageType.System) {
Blink Reformat4c46d092018-04-07 15:32:371262 this._element.classList.add('console-system-type');
Tim van der Lippe1d6e57a2019-09-30 11:55:341263 }
Blink Reformat4c46d092018-04-07 15:32:371264 break;
1265 case SDK.ConsoleMessage.MessageLevel.Warning:
1266 this._element.classList.add('console-warning-level');
Blink Reformat4c46d092018-04-07 15:32:371267 break;
1268 case SDK.ConsoleMessage.MessageLevel.Error:
1269 this._element.classList.add('console-error-level');
Blink Reformat4c46d092018-04-07 15:32:371270 break;
1271 }
Erik Luofd3e7d42018-09-25 02:12:351272 this._updateMessageLevelIcon();
Tim van der Lippe1d6e57a2019-09-30 11:55:341273 if (this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:371274 this._element.classList.add('console-warning-level');
Tim van der Lippe1d6e57a2019-09-30 11:55:341275 }
Blink Reformat4c46d092018-04-07 15:32:371276
1277 this._element.appendChild(this.contentElement());
Tim van der Lippe1d6e57a2019-09-30 11:55:341278 if (this._repeatCount > 1) {
Blink Reformat4c46d092018-04-07 15:32:371279 this._showRepeatCountElement();
Tim van der Lippe1d6e57a2019-09-30 11:55:341280 }
Blink Reformat4c46d092018-04-07 15:32:371281 }
1282
1283 /**
1284 * @return {boolean}
1285 */
1286 _shouldRenderAsWarning() {
1287 return (this._message.level === SDK.ConsoleMessage.MessageLevel.Verbose ||
1288 this._message.level === SDK.ConsoleMessage.MessageLevel.Info) &&
1289 (this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
1290 this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation ||
1291 this._message.source === SDK.ConsoleMessage.MessageSource.Intervention ||
1292 this._message.source === SDK.ConsoleMessage.MessageSource.Recommendation);
1293 }
1294
Erik Luofd3e7d42018-09-25 02:12:351295 _updateMessageLevelIcon() {
1296 let iconType = '';
1297 let accessibleName = '';
1298 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
1299 iconType = 'smallicon-warning';
1300 accessibleName = ls`Warning`;
1301 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
1302 iconType = 'smallicon-error';
1303 accessibleName = ls`Error`;
1304 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341305 if (!iconType && !this._messageLevelIcon) {
Blink Reformat4c46d092018-04-07 15:32:371306 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341307 }
Blink Reformat4c46d092018-04-07 15:32:371308 if (iconType && !this._messageLevelIcon) {
1309 this._messageLevelIcon = UI.Icon.create('', 'message-level-icon');
Tim van der Lippe1d6e57a2019-09-30 11:55:341310 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371311 this._contentElement.insertBefore(this._messageLevelIcon, this._contentElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341312 }
Blink Reformat4c46d092018-04-07 15:32:371313 }
1314 this._messageLevelIcon.setIconType(iconType);
Erik Luofd3e7d42018-09-25 02:12:351315 UI.ARIAUtils.setAccessibleName(this._messageLevelIcon, accessibleName);
Blink Reformat4c46d092018-04-07 15:32:371316 }
1317
1318 /**
1319 * @return {number}
1320 */
1321 repeatCount() {
1322 return this._repeatCount || 1;
1323 }
1324
1325 resetIncrementRepeatCount() {
1326 this._repeatCount = 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341327 if (!this._repeatCountElement) {
Blink Reformat4c46d092018-04-07 15:32:371328 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341329 }
Blink Reformat4c46d092018-04-07 15:32:371330
1331 this._repeatCountElement.remove();
Tim van der Lippe1d6e57a2019-09-30 11:55:341332 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371333 this._contentElement.classList.remove('repeated-message');
Tim van der Lippe1d6e57a2019-09-30 11:55:341334 }
Blink Reformat4c46d092018-04-07 15:32:371335 delete this._repeatCountElement;
1336 }
1337
1338 incrementRepeatCount() {
1339 this._repeatCount++;
1340 this._showRepeatCountElement();
1341 }
1342
1343 /**
1344 * @param {number} repeatCount
1345 */
1346 setRepeatCount(repeatCount) {
1347 this._repeatCount = repeatCount;
1348 this._showRepeatCountElement();
1349 }
1350
1351 _showRepeatCountElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341352 if (!this._element) {
Blink Reformat4c46d092018-04-07 15:32:371353 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341354 }
Blink Reformat4c46d092018-04-07 15:32:371355
1356 if (!this._repeatCountElement) {
Joel Einbinder7fbe24c2019-01-24 05:19:011357 this._repeatCountElement = createElementWithClass('span', 'console-message-repeat-count', 'dt-small-bubble');
Blink Reformat4c46d092018-04-07 15:32:371358 switch (this._message.level) {
1359 case SDK.ConsoleMessage.MessageLevel.Warning:
1360 this._repeatCountElement.type = 'warning';
1361 break;
1362 case SDK.ConsoleMessage.MessageLevel.Error:
1363 this._repeatCountElement.type = 'error';
1364 break;
1365 case SDK.ConsoleMessage.MessageLevel.Verbose:
1366 this._repeatCountElement.type = 'verbose';
1367 break;
1368 default:
1369 this._repeatCountElement.type = 'info';
1370 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341371 if (this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:371372 this._repeatCountElement.type = 'warning';
Tim van der Lippe1d6e57a2019-09-30 11:55:341373 }
Blink Reformat4c46d092018-04-07 15:32:371374
1375 this._element.insertBefore(this._repeatCountElement, this._contentElement);
1376 this._contentElement.classList.add('repeated-message');
1377 }
1378 this._repeatCountElement.textContent = this._repeatCount;
Erik Luofd3e7d42018-09-25 02:12:351379 let accessibleName = ls`Repeat ${this._repeatCount}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341380 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
Erik Luofd3e7d42018-09-25 02:12:351381 accessibleName = ls`Warning ${accessibleName}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341382 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
Erik Luofd3e7d42018-09-25 02:12:351383 accessibleName = ls`Error ${accessibleName}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341384 }
Erik Luofd3e7d42018-09-25 02:12:351385 UI.ARIAUtils.setAccessibleName(this._repeatCountElement, accessibleName);
Blink Reformat4c46d092018-04-07 15:32:371386 }
1387
1388 get text() {
1389 return this._message.messageText;
1390 }
1391
1392 /**
1393 * @return {string}
1394 */
1395 toExportString() {
1396 const lines = [];
1397 const nodes = this.contentElement().childTextNodes();
1398 const messageContent = nodes.map(Components.Linkifier.untruncatedNodeText).join('');
Tim van der Lippe1d6e57a2019-09-30 11:55:341399 for (let i = 0; i < this.repeatCount(); ++i) {
Blink Reformat4c46d092018-04-07 15:32:371400 lines.push(messageContent);
Tim van der Lippe1d6e57a2019-09-30 11:55:341401 }
Blink Reformat4c46d092018-04-07 15:32:371402 return lines.join('\n');
1403 }
1404
1405 /**
1406 * @param {?RegExp} regex
1407 */
1408 setSearchRegex(regex) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341409 if (this._searchHiglightNodeChanges && this._searchHiglightNodeChanges.length) {
Blink Reformat4c46d092018-04-07 15:32:371410 UI.revertDomChanges(this._searchHiglightNodeChanges);
Tim van der Lippe1d6e57a2019-09-30 11:55:341411 }
Blink Reformat4c46d092018-04-07 15:32:371412 this._searchRegex = regex;
1413 this._searchHighlightNodes = [];
1414 this._searchHiglightNodeChanges = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341415 if (!this._searchRegex) {
Blink Reformat4c46d092018-04-07 15:32:371416 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341417 }
Blink Reformat4c46d092018-04-07 15:32:371418
1419 const text = this.contentElement().deepTextContent();
1420 let match;
1421 this._searchRegex.lastIndex = 0;
1422 const sourceRanges = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341423 while ((match = this._searchRegex.exec(text)) && match[0]) {
Blink Reformat4c46d092018-04-07 15:32:371424 sourceRanges.push(new TextUtils.SourceRange(match.index, match[0].length));
Tim van der Lippe1d6e57a2019-09-30 11:55:341425 }
Blink Reformat4c46d092018-04-07 15:32:371426
1427 if (sourceRanges.length) {
1428 this._searchHighlightNodes =
1429 UI.highlightSearchResults(this.contentElement(), sourceRanges, this._searchHiglightNodeChanges);
1430 }
1431 }
1432
1433 /**
1434 * @return {?RegExp}
1435 */
1436 searchRegex() {
1437 return this._searchRegex;
1438 }
1439
1440 /**
1441 * @return {number}
1442 */
1443 searchCount() {
1444 return this._searchHighlightNodes.length;
1445 }
1446
1447 /**
1448 * @return {!Element}
1449 */
1450 searchHighlightNode(index) {
1451 return this._searchHighlightNodes[index];
1452 }
1453
1454 /**
1455 * @param {string} string
1456 * @return {?Element}
1457 */
1458 _tryFormatAsError(string) {
1459 /**
1460 * @param {string} prefix
1461 */
1462 function startsWith(prefix) {
1463 return string.startsWith(prefix);
1464 }
1465
1466 const errorPrefixes =
1467 ['EvalError', 'ReferenceError', 'SyntaxError', 'TypeError', 'RangeError', 'Error', 'URIError'];
Tim van der Lippe1d6e57a2019-09-30 11:55:341468 if (!this._message.runtimeModel() || !errorPrefixes.some(startsWith)) {
Blink Reformat4c46d092018-04-07 15:32:371469 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341470 }
Blink Reformat4c46d092018-04-07 15:32:371471 const debuggerModel = this._message.runtimeModel().debuggerModel();
1472 const baseURL = this._message.runtimeModel().target().inspectedURL();
1473
1474 const lines = string.split('\n');
1475 const links = [];
1476 let position = 0;
1477 for (let i = 0; i < lines.length; ++i) {
1478 position += i > 0 ? lines[i - 1].length + 1 : 0;
1479 const isCallFrameLine = /^\s*at\s/.test(lines[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341480 if (!isCallFrameLine && links.length) {
Blink Reformat4c46d092018-04-07 15:32:371481 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341482 }
Blink Reformat4c46d092018-04-07 15:32:371483
Tim van der Lippe1d6e57a2019-09-30 11:55:341484 if (!isCallFrameLine) {
Blink Reformat4c46d092018-04-07 15:32:371485 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341486 }
Blink Reformat4c46d092018-04-07 15:32:371487
1488 let openBracketIndex = -1;
1489 let closeBracketIndex = -1;
Yang Guo39256bd2019-07-18 06:02:251490 const inBracketsWithLineAndColumn = /\([^\)\(]+:\d+:\d+\)/g;
1491 const inBrackets = /\([^\)\(]+\)/g;
1492 let lastMatch = null;
1493 let currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341494 while ((currentMatch = inBracketsWithLineAndColumn.exec(lines[i]))) {
Yang Guo39256bd2019-07-18 06:02:251495 lastMatch = currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341496 }
Yang Guo39256bd2019-07-18 06:02:251497 if (!lastMatch) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341498 while ((currentMatch = inBrackets.exec(lines[i]))) {
Yang Guo39256bd2019-07-18 06:02:251499 lastMatch = currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341500 }
Yang Guo39256bd2019-07-18 06:02:251501 }
1502 if (lastMatch) {
1503 openBracketIndex = lastMatch.index;
1504 closeBracketIndex = lastMatch.index + lastMatch[0].length - 1;
Blink Reformat4c46d092018-04-07 15:32:371505 }
1506 const hasOpenBracket = openBracketIndex !== -1;
1507 const left = hasOpenBracket ? openBracketIndex + 1 : lines[i].indexOf('at') + 3;
1508 const right = hasOpenBracket ? closeBracketIndex : lines[i].length;
1509 const linkCandidate = lines[i].substring(left, right);
1510 const splitResult = Common.ParsedURL.splitLineAndColumn(linkCandidate);
Tim van der Lippe1d6e57a2019-09-30 11:55:341511 if (!splitResult) {
Blink Reformat4c46d092018-04-07 15:32:371512 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341513 }
Blink Reformat4c46d092018-04-07 15:32:371514
Tim van der Lippe1d6e57a2019-09-30 11:55:341515 if (splitResult.url === '<anonymous>') {
Blink Reformat4c46d092018-04-07 15:32:371516 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341517 }
Blink Reformat4c46d092018-04-07 15:32:371518 let url = parseOrScriptMatch(splitResult.url);
Tim van der Lippe1d6e57a2019-09-30 11:55:341519 if (!url && Common.ParsedURL.isRelativeURL(splitResult.url)) {
Blink Reformat4c46d092018-04-07 15:32:371520 url = parseOrScriptMatch(Common.ParsedURL.completeURL(baseURL, splitResult.url));
Tim van der Lippe1d6e57a2019-09-30 11:55:341521 }
1522 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:371523 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341524 }
Blink Reformat4c46d092018-04-07 15:32:371525
1526 links.push({
1527 url: url,
1528 positionLeft: position + left,
1529 positionRight: position + right,
1530 lineNumber: splitResult.lineNumber,
1531 columnNumber: splitResult.columnNumber
1532 });
1533 }
1534
Tim van der Lippe1d6e57a2019-09-30 11:55:341535 if (!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
1539 const formattedResult = createElement('span');
1540 let start = 0;
1541 for (let i = 0; i < links.length; ++i) {
Erik Luo383f21d2018-11-07 23:16:371542 formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start, links[i].positionLeft)));
Erik Luo182bece2018-11-29 03:15:221543 const scriptLocationLink = this._linkifier.linkifyScriptLocation(
Jack Lynch236e1d22020-01-07 20:33:511544 debuggerModel.target(), null, links[i].url, links[i].lineNumber, {columnNumber: links[i].columnNumber});
Erik Luo182bece2018-11-29 03:15:221545 scriptLocationLink.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:391546 this._selectableChildren.push({element: scriptLocationLink, forceSelect: () => scriptLocationLink.focus()});
Erik Luo182bece2018-11-29 03:15:221547 formattedResult.appendChild(scriptLocationLink);
Blink Reformat4c46d092018-04-07 15:32:371548 start = links[i].positionRight;
1549 }
1550
Tim van der Lippe1d6e57a2019-09-30 11:55:341551 if (start !== string.length) {
Erik Luo383f21d2018-11-07 23:16:371552 formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start)));
Tim van der Lippe1d6e57a2019-09-30 11:55:341553 }
Blink Reformat4c46d092018-04-07 15:32:371554
1555 return formattedResult;
1556
1557 /**
1558 * @param {?string} url
1559 * @return {?string}
1560 */
1561 function parseOrScriptMatch(url) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341562 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:371563 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341564 }
Peter Marshall3e4e5692019-12-09 16:48:041565 const parsedURL = Common.ParsedURL.fromString(url);
Tim van der Lippe1d6e57a2019-09-30 11:55:341566 if (parsedURL) {
Blink Reformat4c46d092018-04-07 15:32:371567 return parsedURL.url;
Tim van der Lippe1d6e57a2019-09-30 11:55:341568 }
1569 if (debuggerModel.scriptsForSourceURL(url).length) {
Blink Reformat4c46d092018-04-07 15:32:371570 return url;
Tim van der Lippe1d6e57a2019-09-30 11:55:341571 }
Blink Reformat4c46d092018-04-07 15:32:371572 return null;
1573 }
1574 }
1575
1576 /**
1577 * @param {string} string
1578 * @param {function(string,string,number=,number=):!Node} linkifier
1579 * @return {!DocumentFragment}
Tim van der Lippeeaacb722020-01-10 12:16:001580 * @suppress {accessControls}
Blink Reformat4c46d092018-04-07 15:32:371581 */
Erik Luofc2214f2018-11-21 19:54:581582 _linkifyWithCustomLinkifier(string, linkifier) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341583 if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Connor Moody1a5c0d32019-12-19 07:23:361584 const propertyValue = new ObjectUI.ExpandableTextPropertyValue(
1585 createElement('span'), string, Console.ConsoleViewMessage._LongStringVisibleLength);
1586 const fragment = createDocumentFragment();
1587 fragment.appendChild(propertyValue.element);
1588 return fragment;
Tim van der Lippe1d6e57a2019-09-30 11:55:341589 }
Blink Reformat4c46d092018-04-07 15:32:371590 const container = createDocumentFragment();
Tim van der Lippeeaacb722020-01-10 12:16:001591 const tokens = ConsoleViewMessage._tokenizeMessageText(string);
Blink Reformat4c46d092018-04-07 15:32:371592 for (const token of tokens) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341593 if (!token.text) {
Erik Luofc2214f2018-11-21 19:54:581594 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341595 }
Blink Reformat4c46d092018-04-07 15:32:371596 switch (token.type) {
1597 case 'url': {
1598 const realURL = (token.text.startsWith('www.') ? 'http://' + token.text : token.text);
1599 const splitResult = Common.ParsedURL.splitLineAndColumn(realURL);
1600 let linkNode;
Tim van der Lippe1d6e57a2019-09-30 11:55:341601 if (splitResult) {
Blink Reformat4c46d092018-04-07 15:32:371602 linkNode = linkifier(token.text, splitResult.url, splitResult.lineNumber, splitResult.columnNumber);
Tim van der Lippe1d6e57a2019-09-30 11:55:341603 } else {
Blink Reformat4c46d092018-04-07 15:32:371604 linkNode = linkifier(token.text, token.value);
Tim van der Lippe1d6e57a2019-09-30 11:55:341605 }
Blink Reformat4c46d092018-04-07 15:32:371606 container.appendChild(linkNode);
1607 break;
1608 }
1609 default:
1610 container.appendChild(createTextNode(token.text));
1611 break;
1612 }
1613 }
1614 return container;
1615 }
1616
1617 /**
Blink Reformat4c46d092018-04-07 15:32:371618 * @param {string} string
1619 * @return {!DocumentFragment}
1620 */
Erik Luo383f21d2018-11-07 23:16:371621 _linkifyStringAsFragment(string) {
Erik Luofc2214f2018-11-21 19:54:581622 return this._linkifyWithCustomLinkifier(string, (text, url, lineNumber, columnNumber) => {
Erik Luo383f21d2018-11-07 23:16:371623 const linkElement = Components.Linkifier.linkifyURL(url, {text, lineNumber, columnNumber});
1624 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:391625 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo383f21d2018-11-07 23:16:371626 return linkElement;
Blink Reformat4c46d092018-04-07 15:32:371627 });
1628 }
1629
1630 /**
1631 * @param {string} string
1632 * @return {!Array<{type: string, text: (string|undefined)}>}
Tim van der Lippeeaacb722020-01-10 12:16:001633 * @suppress {accessControls}
Blink Reformat4c46d092018-04-07 15:32:371634 */
1635 static _tokenizeMessageText(string) {
Tim van der Lippeeaacb722020-01-10 12:16:001636 if (!ConsoleViewMessage._tokenizerRegexes) {
Blink Reformat4c46d092018-04-07 15:32:371637 const controlCodes = '\\u0000-\\u0020\\u007f-\\u009f';
1638 const linkStringRegex = new RegExp(
1639 '(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|data:|www\\.)[^\\s' + controlCodes + '"]{2,}[^\\s' + controlCodes +
1640 '"\')}\\],:;.!?]',
1641 'u');
1642 const pathLineRegex = /(?:\/[\w\.-]*)+\:[\d]+/;
1643 const timeRegex = /took [\d]+ms/;
1644 const eventRegex = /'\w+' event/;
1645 const milestoneRegex = /\sM[6-7]\d/;
1646 const autofillRegex = /\(suggested: \"[\w-]+\"\)/;
1647 const handlers = new Map();
1648 handlers.set(linkStringRegex, 'url');
1649 handlers.set(pathLineRegex, 'url');
1650 handlers.set(timeRegex, 'time');
1651 handlers.set(eventRegex, 'event');
1652 handlers.set(milestoneRegex, 'milestone');
1653 handlers.set(autofillRegex, 'autofill');
Tim van der Lippeeaacb722020-01-10 12:16:001654 ConsoleViewMessage._tokenizerRegexes = Array.from(handlers.keys());
1655 ConsoleViewMessage._tokenizerTypes = Array.from(handlers.values());
Blink Reformat4c46d092018-04-07 15:32:371656 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341657 if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Blink Reformat4c46d092018-04-07 15:32:371658 return [{text: string, type: undefined}];
Tim van der Lippe1d6e57a2019-09-30 11:55:341659 }
Tim van der Lippeeaacb722020-01-10 12:16:001660 const results = TextUtils.TextUtils.splitStringByRegexes(string, ConsoleViewMessage._tokenizerRegexes);
1661 return results.map(result => ({text: result.value, type: ConsoleViewMessage._tokenizerTypes[result.regexIndex]}));
Blink Reformat4c46d092018-04-07 15:32:371662 }
1663
1664 /**
1665 * @return {string}
1666 */
1667 groupKey() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341668 if (!this._groupKey) {
Blink Reformat4c46d092018-04-07 15:32:371669 this._groupKey = this._message.groupCategoryKey() + ':' + this.groupTitle();
Tim van der Lippe1d6e57a2019-09-30 11:55:341670 }
Blink Reformat4c46d092018-04-07 15:32:371671 return this._groupKey;
1672 }
1673
1674 /**
1675 * @return {string}
1676 */
1677 groupTitle() {
Tim van der Lippeeaacb722020-01-10 12:16:001678 const tokens = ConsoleViewMessage._tokenizeMessageText(this._message.messageText);
Blink Reformat4c46d092018-04-07 15:32:371679 const result = tokens.reduce((acc, token) => {
1680 let text = token.text;
Tim van der Lippe1d6e57a2019-09-30 11:55:341681 if (token.type === 'url') {
Blink Reformat4c46d092018-04-07 15:32:371682 text = Common.UIString('<URL>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341683 } else if (token.type === 'time') {
Blink Reformat4c46d092018-04-07 15:32:371684 text = Common.UIString('took <N>ms');
Tim van der Lippe1d6e57a2019-09-30 11:55:341685 } else if (token.type === 'event') {
Blink Reformat4c46d092018-04-07 15:32:371686 text = Common.UIString('<some> event');
Tim van der Lippe1d6e57a2019-09-30 11:55:341687 } else if (token.type === 'milestone') {
Blink Reformat4c46d092018-04-07 15:32:371688 text = Common.UIString(' M<XX>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341689 } else if (token.type === 'autofill') {
Blink Reformat4c46d092018-04-07 15:32:371690 text = Common.UIString('<attribute>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341691 }
Blink Reformat4c46d092018-04-07 15:32:371692 return acc + text;
1693 }, '');
1694 return result.replace(/[%]o/g, '');
1695 }
Paul Lewisbf7aa3c2019-11-20 17:03:381696}
Blink Reformat4c46d092018-04-07 15:32:371697
1698/**
1699 * @unrestricted
1700 */
Paul Lewisbf7aa3c2019-11-20 17:03:381701export class ConsoleGroupViewMessage extends ConsoleViewMessage {
Blink Reformat4c46d092018-04-07 15:32:371702 /**
1703 * @param {!SDK.ConsoleMessage} consoleMessage
1704 * @param {!Components.Linkifier} linkifier
Blink Reformat4c46d092018-04-07 15:32:371705 * @param {number} nestingLevel
Erik Luo8ef5d0c2018-09-25 21:16:001706 * @param {function()} onToggle
Erik Luo840be6b2018-12-03 20:54:271707 * @param {function(!Common.Event)} onResize
Blink Reformat4c46d092018-04-07 15:32:371708 */
Tim van der Lippeb45d9a02019-11-05 17:24:411709 constructor(consoleMessage, linkifier, nestingLevel, onToggle, onResize) {
Blink Reformat4c46d092018-04-07 15:32:371710 console.assert(consoleMessage.isGroupStartMessage());
Tim van der Lippeb45d9a02019-11-05 17:24:411711 super(consoleMessage, linkifier, nestingLevel, onResize);
Blink Reformat4c46d092018-04-07 15:32:371712 this._collapsed = consoleMessage.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed;
1713 /** @type {?UI.Icon} */
1714 this._expandGroupIcon = null;
Erik Luo8ef5d0c2018-09-25 21:16:001715 this._onToggle = onToggle;
Blink Reformat4c46d092018-04-07 15:32:371716 }
1717
1718 /**
1719 * @param {boolean} collapsed
1720 */
Erik Luo8ef5d0c2018-09-25 21:16:001721 _setCollapsed(collapsed) {
Blink Reformat4c46d092018-04-07 15:32:371722 this._collapsed = collapsed;
Tim van der Lippe1d6e57a2019-09-30 11:55:341723 if (this._expandGroupIcon) {
Blink Reformat4c46d092018-04-07 15:32:371724 this._expandGroupIcon.setIconType(this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down');
Tim van der Lippe1d6e57a2019-09-30 11:55:341725 }
Erik Luo8ef5d0c2018-09-25 21:16:001726 this._onToggle.call(null);
Blink Reformat4c46d092018-04-07 15:32:371727 }
1728
1729 /**
1730 * @return {boolean}
1731 */
1732 collapsed() {
1733 return this._collapsed;
1734 }
1735
1736 /**
1737 * @override
Erik Luo8ef5d0c2018-09-25 21:16:001738 * @param {!Event} event
1739 */
1740 maybeHandleOnKeyDown(event) {
Erik Luo0b8282e2018-10-08 20:37:461741 const focusedChildIndex = this._focusedChildIndex();
1742 if (focusedChildIndex === -1) {
1743 if ((event.key === 'ArrowLeft' && !this._collapsed) || (event.key === 'ArrowRight' && this._collapsed)) {
1744 this._setCollapsed(!this._collapsed);
1745 return true;
1746 }
Erik Luo8ef5d0c2018-09-25 21:16:001747 }
1748 return super.maybeHandleOnKeyDown(event);
1749 }
1750
1751 /**
1752 * @override
Blink Reformat4c46d092018-04-07 15:32:371753 * @return {!Element}
1754 */
1755 toMessageElement() {
1756 if (!this._element) {
1757 super.toMessageElement();
Erik Luo8ef5d0c2018-09-25 21:16:001758 const iconType = this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down';
1759 this._expandGroupIcon = UI.Icon.create(iconType, 'expand-group-icon');
Erik Luob5bfff42018-09-20 02:52:391760 // Intercept focus to avoid highlight on click.
1761 this._contentElement.tabIndex = -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341762 if (this._repeatCountElement) {
Blink Reformat4c46d092018-04-07 15:32:371763 this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341764 } else {
Blink Reformat4c46d092018-04-07 15:32:371765 this._element.insertBefore(this._expandGroupIcon, this._contentElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:341766 }
Erik Luo8ef5d0c2018-09-25 21:16:001767 this._element.addEventListener('click', () => this._setCollapsed(!this._collapsed));
Blink Reformat4c46d092018-04-07 15:32:371768 }
1769 return this._element;
1770 }
1771
1772 /**
1773 * @override
1774 */
1775 _showRepeatCountElement() {
1776 super._showRepeatCountElement();
Tim van der Lippe1d6e57a2019-09-30 11:55:341777 if (this._repeatCountElement && this._expandGroupIcon) {
Blink Reformat4c46d092018-04-07 15:32:371778 this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341779 }
Blink Reformat4c46d092018-04-07 15:32:371780 }
Paul Lewisbf7aa3c2019-11-20 17:03:381781}
Blink Reformat4c46d092018-04-07 15:32:371782
1783/**
1784 * @const
1785 * @type {number}
1786 */
Paul Lewisbf7aa3c2019-11-20 17:03:381787export const MaxLengthForLinks = 40;
Blink Reformat4c46d092018-04-07 15:32:371788
Paul Lewisbf7aa3c2019-11-20 17:03:381789export const _MaxTokenizableStringLength = 10000;
1790export const _LongStringVisibleLength = 5000;