blob: 9e96df3276bdff5ca01ca86d896fd8d006b146cd [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 */
Paul Lewisbf7aa3c2019-11-20 17:03:3834export default class ConsoleViewMessage {
Blink Reformat4c46d092018-04-07 15:32:3735 /**
36 * @param {!SDK.ConsoleMessage} consoleMessage
37 * @param {!Components.Linkifier} linkifier
Blink Reformat4c46d092018-04-07 15:32:3738 * @param {number} nestingLevel
Erik Luo840be6b2018-12-03 20:54:2739 * @param {function(!Common.Event)} onResize
Blink Reformat4c46d092018-04-07 15:32:3740 */
Tim van der Lippeb45d9a02019-11-05 17:24:4141 constructor(consoleMessage, linkifier, nestingLevel, onResize) {
Blink Reformat4c46d092018-04-07 15:32:3742 this._message = consoleMessage;
43 this._linkifier = linkifier;
Blink Reformat4c46d092018-04-07 15:32:3744 this._repeatCount = 1;
45 this._closeGroupDecorationCount = 0;
46 this._nestingLevel = nestingLevel;
Erik Luo31c21f62018-12-13 03:39:3947 /** @type {!Array<{element: !Element, forceSelect: function()}>} */
Erik Luo383f21d2018-11-07 23:16:3748 this._selectableChildren = [];
Erik Luo840be6b2018-12-03 20:54:2749 this._messageResized = onResize;
Blink Reformat4c46d092018-04-07 15:32:3750
51 /** @type {?DataGrid.DataGrid} */
52 this._dataGrid = null;
53 this._previewFormatter = new ObjectUI.RemoteObjectPreviewFormatter();
54 this._searchRegex = null;
55 /** @type {?UI.Icon} */
56 this._messageLevelIcon = null;
Erik Luo8ef5d0c2018-09-25 21:16:0057 this._traceExpanded = false;
58 /** @type {?function(boolean)} */
59 this._expandTrace = null;
John Emaubb2897a2019-10-04 17:37:3260 /** @type {?Element} */
61 this._anchorElement = null;
Blink Reformat4c46d092018-04-07 15:32:3762 }
63
64 /**
65 * @override
66 * @return {!Element}
67 */
68 element() {
69 return this.toMessageElement();
70 }
71
72 /**
Blink Reformat4c46d092018-04-07 15:32:3773 * @override
74 */
75 wasShown() {
Tim van der Lippe1d6e57a2019-09-30 11:55:3476 if (this._dataGrid) {
Blink Reformat4c46d092018-04-07 15:32:3777 this._dataGrid.updateWidths();
Tim van der Lippe1d6e57a2019-09-30 11:55:3478 }
Blink Reformat4c46d092018-04-07 15:32:3779 this._isVisible = true;
80 }
81
82 onResize() {
Tim van der Lippe1d6e57a2019-09-30 11:55:3483 if (!this._isVisible) {
Blink Reformat4c46d092018-04-07 15:32:3784 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:3485 }
86 if (this._dataGrid) {
Blink Reformat4c46d092018-04-07 15:32:3787 this._dataGrid.onResize();
Tim van der Lippe1d6e57a2019-09-30 11:55:3488 }
Blink Reformat4c46d092018-04-07 15:32:3789 }
90
91 /**
92 * @override
93 */
94 willHide() {
95 this._isVisible = false;
Erik Luo4b002322018-07-30 21:23:3196 this._cachedHeight = this.element().offsetHeight;
Blink Reformat4c46d092018-04-07 15:32:3797 }
98
99 /**
100 * @return {number}
101 */
102 fastHeight() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34103 if (this._cachedHeight) {
Blink Reformat4c46d092018-04-07 15:32:37104 return this._cachedHeight;
Tim van der Lippe1d6e57a2019-09-30 11:55:34105 }
Blink Reformat4c46d092018-04-07 15:32:37106 // This value reflects the 18px min-height of .console-message, plus the
107 // 1px border of .console-message-wrapper. Keep in sync with consoleView.css.
108 const defaultConsoleRowHeight = 19;
109 if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
110 const table = this._message.parameters[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34111 if (table && table.preview) {
Blink Reformat4c46d092018-04-07 15:32:37112 return defaultConsoleRowHeight * table.preview.properties.length;
Tim van der Lippe1d6e57a2019-09-30 11:55:34113 }
Blink Reformat4c46d092018-04-07 15:32:37114 }
115 return defaultConsoleRowHeight;
116 }
117
118 /**
119 * @return {!SDK.ConsoleMessage}
120 */
121 consoleMessage() {
122 return this._message;
123 }
124
125 /**
126 * @return {!Element}
127 */
128 _buildTableMessage() {
129 const formattedMessage = createElementWithClass('span', 'source-code');
Erik Luo5976c8c2018-07-24 02:03:09130 this._anchorElement = this._buildMessageAnchor();
Tim van der Lippe1d6e57a2019-09-30 11:55:34131 if (this._anchorElement) {
Erik Luo5976c8c2018-07-24 02:03:09132 formattedMessage.appendChild(this._anchorElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34133 }
Blink Reformat4c46d092018-04-07 15:32:37134
135 let table = this._message.parameters && this._message.parameters.length ? this._message.parameters[0] : null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34136 if (table) {
Blink Reformat4c46d092018-04-07 15:32:37137 table = this._parameterToRemoteObject(table);
Tim van der Lippe1d6e57a2019-09-30 11:55:34138 }
139 if (!table || !table.preview) {
Erik Luo16e3e382018-11-09 02:56:01140 return this._buildMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:34141 }
Blink Reformat4c46d092018-04-07 15:32:37142
143 const rawValueColumnSymbol = Symbol('rawValueColumn');
144 const columnNames = [];
145 const preview = table.preview;
146 const rows = [];
147 for (let i = 0; i < preview.properties.length; ++i) {
148 const rowProperty = preview.properties[i];
149 let rowSubProperties;
Tim van der Lippe1d6e57a2019-09-30 11:55:34150 if (rowProperty.valuePreview) {
Blink Reformat4c46d092018-04-07 15:32:37151 rowSubProperties = rowProperty.valuePreview.properties;
Tim van der Lippe1d6e57a2019-09-30 11:55:34152 } else if (rowProperty.value) {
Blink Reformat4c46d092018-04-07 15:32:37153 rowSubProperties = [{name: rawValueColumnSymbol, type: rowProperty.type, value: rowProperty.value}];
Tim van der Lippe1d6e57a2019-09-30 11:55:34154 } else {
Blink Reformat4c46d092018-04-07 15:32:37155 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34156 }
Blink Reformat4c46d092018-04-07 15:32:37157
158 const rowValue = {};
159 const maxColumnsToRender = 20;
160 for (let j = 0; j < rowSubProperties.length; ++j) {
161 const cellProperty = rowSubProperties[j];
162 let columnRendered = columnNames.indexOf(cellProperty.name) !== -1;
163 if (!columnRendered) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34164 if (columnNames.length === maxColumnsToRender) {
Blink Reformat4c46d092018-04-07 15:32:37165 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34166 }
Blink Reformat4c46d092018-04-07 15:32:37167 columnRendered = true;
168 columnNames.push(cellProperty.name);
169 }
170
171 if (columnRendered) {
172 const cellElement = this._renderPropertyPreviewOrAccessor(table, [rowProperty, cellProperty]);
173 cellElement.classList.add('console-message-nowrap-below');
174 rowValue[cellProperty.name] = cellElement;
175 }
176 }
177 rows.push([rowProperty.name, rowValue]);
178 }
179
180 const flatValues = [];
181 for (let i = 0; i < rows.length; ++i) {
182 const rowName = rows[i][0];
183 const rowValue = rows[i][1];
184 flatValues.push(rowName);
Tim van der Lippe1d6e57a2019-09-30 11:55:34185 for (let j = 0; j < columnNames.length; ++j) {
Blink Reformat4c46d092018-04-07 15:32:37186 flatValues.push(rowValue[columnNames[j]]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34187 }
Blink Reformat4c46d092018-04-07 15:32:37188 }
189 columnNames.unshift(Common.UIString('(index)'));
190 const columnDisplayNames = columnNames.map(name => name === rawValueColumnSymbol ? Common.UIString('Value') : name);
191
192 if (flatValues.length) {
193 this._dataGrid = DataGrid.SortableDataGrid.create(columnDisplayNames, flatValues);
194 this._dataGrid.setStriped(true);
Anubha Mathurfbacf4e2019-10-28 19:08:03195 this._dataGrid.setFocusable(false);
Blink Reformat4c46d092018-04-07 15:32:37196
197 const formattedResult = createElementWithClass('span', 'console-message-text');
198 const tableElement = formattedResult.createChild('div', 'console-message-formatted-table');
199 const dataGridContainer = tableElement.createChild('span');
200 tableElement.appendChild(this._formatParameter(table, true, false));
201 dataGridContainer.appendChild(this._dataGrid.element);
202 formattedMessage.appendChild(formattedResult);
203 this._dataGrid.renderInline();
204 }
205 return formattedMessage;
206 }
207
208 /**
209 * @return {!Element}
210 */
211 _buildMessage() {
212 let messageElement;
213 let messageText = this._message.messageText;
214 if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
215 switch (this._message.type) {
216 case SDK.ConsoleMessage.MessageType.Trace:
217 messageElement = this._format(this._message.parameters || ['console.trace']);
218 break;
219 case SDK.ConsoleMessage.MessageType.Clear:
220 messageElement = createElementWithClass('span', 'console-info');
Tim van der Lippe1d6e57a2019-09-30 11:55:34221 if (Common.moduleSetting('preserveConsoleLog').get()) {
Blink Reformat4c46d092018-04-07 15:32:37222 messageElement.textContent = Common.UIString('console.clear() was prevented due to \'Preserve log\'');
Tim van der Lippe1d6e57a2019-09-30 11:55:34223 } else {
Blink Reformat4c46d092018-04-07 15:32:37224 messageElement.textContent = Common.UIString('Console was cleared');
Tim van der Lippe1d6e57a2019-09-30 11:55:34225 }
Blink Reformat4c46d092018-04-07 15:32:37226 messageElement.title =
Lorne Mitchell81a1a972019-03-06 18:13:13227 ls`Clear all messages with ${UI.shortcutRegistry.shortcutTitleForAction('console.clear')}`;
Blink Reformat4c46d092018-04-07 15:32:37228 break;
Blink Reformat4c46d092018-04-07 15:32:37229 case SDK.ConsoleMessage.MessageType.Dir: {
230 const obj = this._message.parameters ? this._message.parameters[0] : undefined;
231 const args = ['%O', obj];
232 messageElement = this._format(args);
233 break;
234 }
235 case SDK.ConsoleMessage.MessageType.Profile:
236 case SDK.ConsoleMessage.MessageType.ProfileEnd:
237 messageElement = this._format([messageText]);
238 break;
Pavel Feldman9f0f0a32018-12-18 02:09:13239 case SDK.ConsoleMessage.MessageType.Assert:
240 this._messagePrefix = ls`Assertion failed: `;
241 // Fall through.
Blink Reformat4c46d092018-04-07 15:32:37242 default: {
243 if (this._message.parameters && this._message.parameters.length === 1 &&
Tim van der Lippe1d6e57a2019-09-30 11:55:34244 this._message.parameters[0].type === 'string') {
Blink Reformat4c46d092018-04-07 15:32:37245 messageElement = this._tryFormatAsError(/** @type {string} */ (this._message.parameters[0].value));
Tim van der Lippe1d6e57a2019-09-30 11:55:34246 }
Blink Reformat4c46d092018-04-07 15:32:37247 const args = this._message.parameters || [messageText];
248 messageElement = messageElement || this._format(args);
249 }
250 }
251 } else {
Erik Luofc2214f2018-11-21 19:54:58252 if (this._message.source === SDK.ConsoleMessage.MessageSource.Network) {
253 messageElement = this._formatAsNetworkRequest() || this._format([messageText]);
254 } else {
Blink Reformat4c46d092018-04-07 15:32:37255 const messageInParameters =
256 this._message.parameters && messageText === /** @type {string} */ (this._message.parameters[0]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34257 if (this._message.source === SDK.ConsoleMessage.MessageSource.Violation) {
Blink Reformat4c46d092018-04-07 15:32:37258 messageText = Common.UIString('[Violation] %s', messageText);
Tim van der Lippe1d6e57a2019-09-30 11:55:34259 } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Intervention) {
Blink Reformat4c46d092018-04-07 15:32:37260 messageText = Common.UIString('[Intervention] %s', messageText);
Tim van der Lippe1d6e57a2019-09-30 11:55:34261 } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation) {
Blink Reformat4c46d092018-04-07 15:32:37262 messageText = Common.UIString('[Deprecation] %s', messageText);
Tim van der Lippe1d6e57a2019-09-30 11:55:34263 }
Blink Reformat4c46d092018-04-07 15:32:37264 const args = this._message.parameters || [messageText];
Tim van der Lippe1d6e57a2019-09-30 11:55:34265 if (messageInParameters) {
Blink Reformat4c46d092018-04-07 15:32:37266 args[0] = messageText;
Tim van der Lippe1d6e57a2019-09-30 11:55:34267 }
Blink Reformat4c46d092018-04-07 15:32:37268 messageElement = this._format(args);
269 }
270 }
271 messageElement.classList.add('console-message-text');
272
273 const formattedMessage = createElementWithClass('span', 'source-code');
Erik Luo5976c8c2018-07-24 02:03:09274 this._anchorElement = this._buildMessageAnchor();
Tim van der Lippe1d6e57a2019-09-30 11:55:34275 if (this._anchorElement) {
Erik Luo5976c8c2018-07-24 02:03:09276 formattedMessage.appendChild(this._anchorElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34277 }
Blink Reformat4c46d092018-04-07 15:32:37278 formattedMessage.appendChild(messageElement);
279 return formattedMessage;
280 }
281
282 /**
283 * @return {?Element}
284 */
Erik Luofc2214f2018-11-21 19:54:58285 _formatAsNetworkRequest() {
286 const request = SDK.NetworkLog.requestForConsoleMessage(this._message);
Tim van der Lippe1d6e57a2019-09-30 11:55:34287 if (!request) {
Erik Luofc2214f2018-11-21 19:54:58288 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34289 }
Erik Luofc2214f2018-11-21 19:54:58290 const messageElement = createElement('span');
291 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
292 messageElement.createTextChild(request.requestMethod + ' ');
Erik Luo182bece2018-11-29 03:15:22293 const linkElement = Components.Linkifier.linkifyRevealable(request, request.url(), request.url());
294 // Focus is handled by the viewport.
295 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:39296 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo182bece2018-11-29 03:15:22297 messageElement.appendChild(linkElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34298 if (request.failed) {
Erik Luofc2214f2018-11-21 19:54:58299 messageElement.createTextChildren(' ', request.localizedFailDescription);
Tim van der Lippe1d6e57a2019-09-30 11:55:34300 }
301 if (request.statusCode !== 0) {
Erik Luofc2214f2018-11-21 19:54:58302 messageElement.createTextChildren(' ', String(request.statusCode));
Tim van der Lippe1d6e57a2019-09-30 11:55:34303 }
304 if (request.statusText) {
Erik Luofc2214f2018-11-21 19:54:58305 messageElement.createTextChildren(' (', request.statusText, ')');
Tim van der Lippe1d6e57a2019-09-30 11:55:34306 }
Erik Luofc2214f2018-11-21 19:54:58307 } else {
Erik Luoad5f3942019-03-26 20:53:44308 const messageText = this._message.messageText;
309 const fragment = this._linkifyWithCustomLinkifier(messageText, (text, url, lineNumber, columnNumber) => {
310 let linkElement;
311 if (url === request.url()) {
312 linkElement = Components.Linkifier.linkifyRevealable(
313 /** @type {!SDK.NetworkRequest} */ (request), url, request.url());
314 } else {
315 linkElement = Components.Linkifier.linkifyURL(url, {text, lineNumber, columnNumber});
316 }
Erik Luo182bece2018-11-29 03:15:22317 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:39318 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo182bece2018-11-29 03:15:22319 return linkElement;
320 });
Erik Luofc2214f2018-11-21 19:54:58321 messageElement.appendChild(fragment);
322 }
323 return messageElement;
324 }
325
326 /**
327 * @return {?Element}
328 */
Blink Reformat4c46d092018-04-07 15:32:37329 _buildMessageAnchor() {
330 let anchorElement = null;
331 if (this._message.scriptId) {
332 anchorElement = this._linkifyScriptId(
333 this._message.scriptId, this._message.url || '', this._message.line, this._message.column);
334 } else if (this._message.stackTrace && this._message.stackTrace.callFrames.length) {
335 anchorElement = this._linkifyStackTraceTopFrame(this._message.stackTrace);
336 } else if (this._message.url && this._message.url !== 'undefined') {
337 anchorElement = this._linkifyLocation(this._message.url, this._message.line, this._message.column);
338 }
339
340 // Append a space to prevent the anchor text from being glued to the console message when the user selects and copies the console messages.
341 if (anchorElement) {
John Emauf7e30fb2019-10-04 19:12:32342 anchorElement.tabIndex = -1;
343 this._selectableChildren.push({
344 element: anchorElement,
345 forceSelect: () => anchorElement.focus(),
346 });
Blink Reformat4c46d092018-04-07 15:32:37347 const anchorWrapperElement = createElementWithClass('span', 'console-message-anchor');
348 anchorWrapperElement.appendChild(anchorElement);
349 anchorWrapperElement.createTextChild(' ');
350 return anchorWrapperElement;
351 }
352 return null;
353 }
354
355 /**
Blink Reformat4c46d092018-04-07 15:32:37356 * @return {!Element}
357 */
358 _buildMessageWithStackTrace() {
359 const toggleElement = createElementWithClass('div', 'console-message-stack-trace-toggle');
360 const contentElement = toggleElement.createChild('div', 'console-message-stack-trace-wrapper');
361
362 const messageElement = this._buildMessage();
363 const icon = UI.Icon.create('smallicon-triangle-right', 'console-message-expand-icon');
364 const clickableElement = contentElement.createChild('div');
365 clickableElement.appendChild(icon);
Erik Luob5bfff42018-09-20 02:52:39366 // Intercept focus to avoid highlight on click.
367 clickableElement.tabIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:37368
369 clickableElement.appendChild(messageElement);
370 const stackTraceElement = contentElement.createChild('div');
371 const stackTracePreview = Components.JSPresentationUtils.buildStackTracePreviewContents(
372 this._message.runtimeModel().target(), this._linkifier, this._message.stackTrace);
Erik Luo182bece2018-11-29 03:15:22373 stackTraceElement.appendChild(stackTracePreview.element);
374 for (const linkElement of stackTracePreview.links) {
375 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:39376 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo182bece2018-11-29 03:15:22377 }
Blink Reformat4c46d092018-04-07 15:32:37378 stackTraceElement.classList.add('hidden');
Brandon Goddard04a5a762019-12-10 16:45:53379 UI.ARIAUtils.markAsTreeitem(this.element());
380 UI.ARIAUtils.setExpanded(this.element(), false);
Erik Luo8ef5d0c2018-09-25 21:16:00381 this._expandTrace = expand => {
Blink Reformat4c46d092018-04-07 15:32:37382 icon.setIconType(expand ? 'smallicon-triangle-down' : 'smallicon-triangle-right');
383 stackTraceElement.classList.toggle('hidden', !expand);
Brandon Goddard04a5a762019-12-10 16:45:53384 UI.ARIAUtils.setExpanded(this.element(), expand);
Erik Luo8ef5d0c2018-09-25 21:16:00385 this._traceExpanded = expand;
386 };
Blink Reformat4c46d092018-04-07 15:32:37387
388 /**
Erik Luo8ef5d0c2018-09-25 21:16:00389 * @this {!Console.ConsoleViewMessage}
Blink Reformat4c46d092018-04-07 15:32:37390 * @param {?Event} event
391 */
392 function toggleStackTrace(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34393 if (UI.isEditing() || contentElement.hasSelection()) {
Blink Reformat4c46d092018-04-07 15:32:37394 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34395 }
Erik Luo8ef5d0c2018-09-25 21:16:00396 this._expandTrace(stackTraceElement.classList.contains('hidden'));
Blink Reformat4c46d092018-04-07 15:32:37397 event.consume();
398 }
399
Erik Luo8ef5d0c2018-09-25 21:16:00400 clickableElement.addEventListener('click', toggleStackTrace.bind(this), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34401 if (this._message.type === SDK.ConsoleMessage.MessageType.Trace) {
Erik Luo8ef5d0c2018-09-25 21:16:00402 this._expandTrace(true);
Tim van der Lippe1d6e57a2019-09-30 11:55:34403 }
Blink Reformat4c46d092018-04-07 15:32:37404
Erik Luo8ef5d0c2018-09-25 21:16:00405 toggleElement._expandStackTraceForTest = this._expandTrace.bind(this, true);
Blink Reformat4c46d092018-04-07 15:32:37406 return toggleElement;
407 }
408
409 /**
410 * @param {string} url
411 * @param {number} lineNumber
412 * @param {number} columnNumber
413 * @return {?Element}
414 */
415 _linkifyLocation(url, lineNumber, columnNumber) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34416 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37417 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34418 }
Blink Reformat4c46d092018-04-07 15:32:37419 return this._linkifier.linkifyScriptLocation(
420 this._message.runtimeModel().target(), null, url, lineNumber, columnNumber);
421 }
422
423 /**
424 * @param {!Protocol.Runtime.StackTrace} stackTrace
425 * @return {?Element}
426 */
427 _linkifyStackTraceTopFrame(stackTrace) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34428 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37429 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34430 }
Blink Reformat4c46d092018-04-07 15:32:37431 return this._linkifier.linkifyStackTraceTopFrame(this._message.runtimeModel().target(), stackTrace);
432 }
433
434 /**
435 * @param {string} scriptId
436 * @param {string} url
437 * @param {number} lineNumber
438 * @param {number} columnNumber
439 * @return {?Element}
440 */
441 _linkifyScriptId(scriptId, url, lineNumber, columnNumber) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34442 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37443 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34444 }
Blink Reformat4c46d092018-04-07 15:32:37445 return this._linkifier.linkifyScriptLocation(
446 this._message.runtimeModel().target(), scriptId, url, lineNumber, columnNumber);
447 }
448
449 /**
450 * @param {!SDK.RemoteObject|!Protocol.Runtime.RemoteObject|string} parameter
451 * @return {!SDK.RemoteObject}
452 */
453 _parameterToRemoteObject(parameter) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34454 if (parameter instanceof SDK.RemoteObject) {
Blink Reformat4c46d092018-04-07 15:32:37455 return parameter;
Tim van der Lippe1d6e57a2019-09-30 11:55:34456 }
Blink Reformat4c46d092018-04-07 15:32:37457 const runtimeModel = this._message.runtimeModel();
Tim van der Lippe1d6e57a2019-09-30 11:55:34458 if (!runtimeModel) {
Blink Reformat4c46d092018-04-07 15:32:37459 return SDK.RemoteObject.fromLocalObject(parameter);
Tim van der Lippe1d6e57a2019-09-30 11:55:34460 }
461 if (typeof parameter === 'object') {
Blink Reformat4c46d092018-04-07 15:32:37462 return runtimeModel.createRemoteObject(parameter);
Tim van der Lippe1d6e57a2019-09-30 11:55:34463 }
Blink Reformat4c46d092018-04-07 15:32:37464 return runtimeModel.createRemoteObjectFromPrimitiveValue(parameter);
465 }
466
467 /**
468 * @param {!Array.<!SDK.RemoteObject|string>} rawParameters
469 * @return {!Element}
470 */
471 _format(rawParameters) {
472 // This node is used like a Builder. Values are continually appended onto it.
473 const formattedResult = createElement('span');
Tim van der Lippe1d6e57a2019-09-30 11:55:34474 if (this._messagePrefix) {
Pavel Feldman9f0f0a32018-12-18 02:09:13475 formattedResult.createChild('span').textContent = this._messagePrefix;
Tim van der Lippe1d6e57a2019-09-30 11:55:34476 }
477 if (!rawParameters.length) {
Blink Reformat4c46d092018-04-07 15:32:37478 return formattedResult;
Tim van der Lippe1d6e57a2019-09-30 11:55:34479 }
Blink Reformat4c46d092018-04-07 15:32:37480
481 // Formatting code below assumes that parameters are all wrappers whereas frontend console
482 // API allows passing arbitrary values as messages (strings, numbers, etc.). Wrap them here.
483 // FIXME: Only pass runtime wrappers here.
484 let parameters = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:34485 for (let i = 0; i < rawParameters.length; ++i) {
Blink Reformat4c46d092018-04-07 15:32:37486 parameters[i] = this._parameterToRemoteObject(rawParameters[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34487 }
Blink Reformat4c46d092018-04-07 15:32:37488
489 // There can be string log and string eval result. We distinguish between them based on message type.
490 const shouldFormatMessage =
491 SDK.RemoteObject.type((/** @type {!Array.<!SDK.RemoteObject>} **/ (parameters))[0]) === 'string' &&
492 (this._message.type !== SDK.ConsoleMessage.MessageType.Result ||
493 this._message.level === SDK.ConsoleMessage.MessageLevel.Error);
494
495 // Multiple parameters with the first being a format string. Save unused substitutions.
496 if (shouldFormatMessage) {
497 const result = this._formatWithSubstitutionString(
498 /** @type {string} **/ (parameters[0].description), parameters.slice(1), formattedResult);
499 parameters = result.unusedSubstitutions;
Tim van der Lippe1d6e57a2019-09-30 11:55:34500 if (parameters.length) {
Blink Reformat4c46d092018-04-07 15:32:37501 formattedResult.createTextChild(' ');
Tim van der Lippe1d6e57a2019-09-30 11:55:34502 }
Blink Reformat4c46d092018-04-07 15:32:37503 }
504
505 // Single parameter, or unused substitutions from above.
506 for (let i = 0; i < parameters.length; ++i) {
507 // Inline strings when formatting.
Tim van der Lippe1d6e57a2019-09-30 11:55:34508 if (shouldFormatMessage && parameters[i].type === 'string') {
Erik Luo383f21d2018-11-07 23:16:37509 formattedResult.appendChild(this._linkifyStringAsFragment(parameters[i].description));
Tim van der Lippe1d6e57a2019-09-30 11:55:34510 } else {
Blink Reformat4c46d092018-04-07 15:32:37511 formattedResult.appendChild(this._formatParameter(parameters[i], false, true));
Tim van der Lippe1d6e57a2019-09-30 11:55:34512 }
513 if (i < parameters.length - 1) {
Blink Reformat4c46d092018-04-07 15:32:37514 formattedResult.createTextChild(' ');
Tim van der Lippe1d6e57a2019-09-30 11:55:34515 }
Blink Reformat4c46d092018-04-07 15:32:37516 }
517 return formattedResult;
518 }
519
520 /**
521 * @param {!SDK.RemoteObject} output
522 * @param {boolean=} forceObjectFormat
523 * @param {boolean=} includePreview
524 * @return {!Element}
525 */
526 _formatParameter(output, forceObjectFormat, includePreview) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34527 if (output.customPreview()) {
Blink Reformat4c46d092018-04-07 15:32:37528 return (new ObjectUI.CustomPreviewComponent(output)).element;
Tim van der Lippe1d6e57a2019-09-30 11:55:34529 }
Blink Reformat4c46d092018-04-07 15:32:37530
531 const type = forceObjectFormat ? 'object' : (output.subtype || output.type);
532 let element;
533 switch (type) {
534 case 'error':
535 element = this._formatParameterAsError(output);
536 break;
537 case 'function':
538 element = this._formatParameterAsFunction(output, includePreview);
539 break;
540 case 'array':
541 case 'arraybuffer':
542 case 'blob':
543 case 'dataview':
544 case 'generator':
545 case 'iterator':
546 case 'map':
547 case 'object':
548 case 'promise':
549 case 'proxy':
550 case 'set':
551 case 'typedarray':
552 case 'weakmap':
553 case 'weakset':
554 element = this._formatParameterAsObject(output, includePreview);
555 break;
556 case 'node':
557 element = output.isNode() ? this._formatParameterAsNode(output) : this._formatParameterAsObject(output, false);
558 break;
559 case 'string':
560 element = this._formatParameterAsString(output);
561 break;
562 case 'boolean':
563 case 'date':
564 case 'null':
565 case 'number':
566 case 'regexp':
567 case 'symbol':
568 case 'undefined':
569 case 'bigint':
570 element = this._formatParameterAsValue(output);
571 break;
572 default:
573 element = this._formatParameterAsValue(output);
574 console.error('Tried to format remote object of unknown type.');
575 }
576 element.classList.add('object-value-' + type);
577 element.classList.add('source-code');
578 return element;
579 }
580
581 /**
582 * @param {!SDK.RemoteObject} obj
583 * @return {!Element}
584 */
585 _formatParameterAsValue(obj) {
586 const result = createElement('span');
587 const description = obj.description || '';
Tim van der Lippe1d6e57a2019-09-30 11:55:34588 if (description.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Erik Luo5fb33bd2018-06-04 23:23:52589 result.appendChild(UI.createExpandableText(description, Console.ConsoleViewMessage._LongStringVisibleLength));
Tim van der Lippe1d6e57a2019-09-30 11:55:34590 } else {
Blink Reformat4c46d092018-04-07 15:32:37591 result.createTextChild(description);
Tim van der Lippe1d6e57a2019-09-30 11:55:34592 }
593 if (obj.objectId) {
Blink Reformat4c46d092018-04-07 15:32:37594 result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, obj), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34595 }
Blink Reformat4c46d092018-04-07 15:32:37596 return result;
597 }
598
599 /**
600 * @param {!SDK.RemoteObject} obj
601 * @param {boolean=} includePreview
602 * @return {!Element}
603 */
604 _formatParameterAsObject(obj, includePreview) {
605 const titleElement = createElementWithClass('span', 'console-object');
606 if (includePreview && obj.preview) {
607 titleElement.classList.add('console-object-preview');
608 this._previewFormatter.appendObjectPreview(titleElement, obj.preview, false /* isEntry */);
609 } else if (obj.type === 'function') {
610 const functionElement = titleElement.createChild('span');
611 ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(obj, functionElement, false);
612 titleElement.classList.add('object-value-function');
613 } else {
614 titleElement.createTextChild(obj.description || '');
615 }
616
Tim van der Lippe1d6e57a2019-09-30 11:55:34617 if (!obj.hasChildren || obj.customPreview()) {
Blink Reformat4c46d092018-04-07 15:32:37618 return titleElement;
Tim van der Lippe1d6e57a2019-09-30 11:55:34619 }
Blink Reformat4c46d092018-04-07 15:32:37620
621 const note = titleElement.createChild('span', 'object-state-note info-note');
Tim van der Lippe1d6e57a2019-09-30 11:55:34622 if (this._message.type === SDK.ConsoleMessage.MessageType.QueryObjectResult) {
Blink Reformat4c46d092018-04-07 15:32:37623 note.title = ls`This value will not be collected until console is cleared.`;
Tim van der Lippe1d6e57a2019-09-30 11:55:34624 } else {
Blink Reformat4c46d092018-04-07 15:32:37625 note.title = ls`Value below was evaluated just now.`;
Tim van der Lippe1d6e57a2019-09-30 11:55:34626 }
Blink Reformat4c46d092018-04-07 15:32:37627
628 const section = new ObjectUI.ObjectPropertiesSection(obj, titleElement, this._linkifier);
629 section.element.classList.add('console-view-object-properties-section');
630 section.enableContextMenu();
Erik Luocc14b812018-11-03 01:33:09631 section.setShowSelectionOnKeyboardFocus(true, true);
Erik Luo383f21d2018-11-07 23:16:37632 this._selectableChildren.push(section);
Erik Luo840be6b2018-12-03 20:54:27633 section.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
634 section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
635 section.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
Blink Reformat4c46d092018-04-07 15:32:37636 return section.element;
637 }
638
639 /**
640 * @param {!SDK.RemoteObject} func
641 * @param {boolean=} includePreview
642 * @return {!Element}
643 */
644 _formatParameterAsFunction(func, includePreview) {
645 const result = createElement('span');
646 SDK.RemoteFunction.objectAsFunction(func).targetFunction().then(formatTargetFunction.bind(this));
647 return result;
648
649 /**
650 * @param {!SDK.RemoteObject} targetFunction
651 * @this {Console.ConsoleViewMessage}
652 */
653 function formatTargetFunction(targetFunction) {
654 const functionElement = createElement('span');
Joey Arhard78a58f2018-12-05 01:59:45655 const promise = ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(
656 targetFunction, functionElement, true, includePreview);
Blink Reformat4c46d092018-04-07 15:32:37657 result.appendChild(functionElement);
658 if (targetFunction !== func) {
659 const note = result.createChild('span', 'object-info-state-note');
660 note.title = Common.UIString('Function was resolved from bound function.');
661 }
662 result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, targetFunction), false);
Joey Arhard78a58f2018-12-05 01:59:45663 promise.then(() => this._formattedParameterAsFunctionForTest());
Blink Reformat4c46d092018-04-07 15:32:37664 }
665 }
666
Joey Arhard78a58f2018-12-05 01:59:45667 _formattedParameterAsFunctionForTest() {
668 }
669
Blink Reformat4c46d092018-04-07 15:32:37670 /**
671 * @param {!SDK.RemoteObject} obj
672 * @param {!Event} event
673 */
674 _contextMenuEventFired(obj, event) {
675 const contextMenu = new UI.ContextMenu(event);
676 contextMenu.appendApplicableItems(obj);
677 contextMenu.show();
678 }
679
680 /**
681 * @param {?SDK.RemoteObject} object
682 * @param {!Array.<!Protocol.Runtime.PropertyPreview>} propertyPath
683 * @return {!Element}
684 */
685 _renderPropertyPreviewOrAccessor(object, propertyPath) {
686 const property = propertyPath.peekLast();
Tim van der Lippe1d6e57a2019-09-30 11:55:34687 if (property.type === 'accessor') {
Blink Reformat4c46d092018-04-07 15:32:37688 return this._formatAsAccessorProperty(object, propertyPath.map(property => property.name), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34689 }
Blink Reformat4c46d092018-04-07 15:32:37690 return this._previewFormatter.renderPropertyPreview(
691 property.type, /** @type {string} */ (property.subtype), property.value);
692 }
693
694 /**
695 * @param {!SDK.RemoteObject} remoteObject
696 * @return {!Element}
697 */
698 _formatParameterAsNode(remoteObject) {
699 const result = createElement('span');
700
701 const domModel = remoteObject.runtimeModel().target().model(SDK.DOMModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34702 if (!domModel) {
Blink Reformat4c46d092018-04-07 15:32:37703 return result;
Tim van der Lippe1d6e57a2019-09-30 11:55:34704 }
Erik Luo54fdd912018-11-01 17:57:01705 domModel.pushObjectAsNodeToFrontend(remoteObject).then(async node => {
Blink Reformat4c46d092018-04-07 15:32:37706 if (!node) {
707 result.appendChild(this._formatParameterAsObject(remoteObject, false));
708 return;
709 }
Erik Luo54fdd912018-11-01 17:57:01710 const renderResult = await UI.Renderer.render(/** @type {!Object} */ (node));
Erik Luofc6a6302018-11-02 06:48:52711 if (renderResult) {
Erik Luo840be6b2018-12-03 20:54:27712 if (renderResult.tree) {
Erik Luo383f21d2018-11-07 23:16:37713 this._selectableChildren.push(renderResult.tree);
Erik Luo840be6b2018-12-03 20:54:27714 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
715 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
716 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
717 }
Erik Luofc6a6302018-11-02 06:48:52718 result.appendChild(renderResult.node);
719 } else {
720 result.appendChild(this._formatParameterAsObject(remoteObject, false));
721 }
Erik Luo54fdd912018-11-01 17:57:01722 this._formattedParameterAsNodeForTest();
Blink Reformat4c46d092018-04-07 15:32:37723 });
724
725 return result;
726 }
727
728 _formattedParameterAsNodeForTest() {
729 }
730
731 /**
732 * @param {!SDK.RemoteObject} output
733 * @return {!Element}
734 */
735 _formatParameterAsString(output) {
736 const span = createElement('span');
Erik Luo383f21d2018-11-07 23:16:37737 span.appendChild(this._linkifyStringAsFragment(output.description || ''));
Blink Reformat4c46d092018-04-07 15:32:37738
739 const result = createElement('span');
740 result.createChild('span', 'object-value-string-quote').textContent = '"';
741 result.appendChild(span);
742 result.createChild('span', 'object-value-string-quote').textContent = '"';
743 return result;
744 }
745
746 /**
747 * @param {!SDK.RemoteObject} output
748 * @return {!Element}
749 */
750 _formatParameterAsError(output) {
751 const result = createElement('span');
752 const errorSpan = this._tryFormatAsError(output.description || '');
Erik Luo383f21d2018-11-07 23:16:37753 result.appendChild(errorSpan ? errorSpan : this._linkifyStringAsFragment(output.description || ''));
Blink Reformat4c46d092018-04-07 15:32:37754 return result;
755 }
756
757 /**
758 * @param {!SDK.RemoteObject} output
759 * @return {!Element}
760 */
761 _formatAsArrayEntry(output) {
762 return this._previewFormatter.renderPropertyPreview(output.type, output.subtype, output.description);
763 }
764
765 /**
766 * @param {?SDK.RemoteObject} object
767 * @param {!Array.<string>} propertyPath
768 * @param {boolean} isArrayEntry
769 * @return {!Element}
770 */
771 _formatAsAccessorProperty(object, propertyPath, isArrayEntry) {
772 const rootElement = ObjectUI.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan(
773 object, propertyPath, onInvokeGetterClick.bind(this));
774
775 /**
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18776 * @param {!SDK.CallFunctionResult} result
Blink Reformat4c46d092018-04-07 15:32:37777 * @this {Console.ConsoleViewMessage}
778 */
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18779 function onInvokeGetterClick(result) {
780 const wasThrown = result.wasThrown;
781 const object = result.object;
Tim van der Lippe1d6e57a2019-09-30 11:55:34782 if (!object) {
Blink Reformat4c46d092018-04-07 15:32:37783 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34784 }
Blink Reformat4c46d092018-04-07 15:32:37785 rootElement.removeChildren();
786 if (wasThrown) {
787 const element = rootElement.createChild('span');
788 element.textContent = Common.UIString('<exception>');
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18789 element.title = /** @type {string} */ (object.description);
Blink Reformat4c46d092018-04-07 15:32:37790 } else if (isArrayEntry) {
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18791 rootElement.appendChild(this._formatAsArrayEntry(object));
Blink Reformat4c46d092018-04-07 15:32:37792 } else {
793 // Make a PropertyPreview from the RemoteObject similar to the backend logic.
794 const maxLength = 100;
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18795 const type = object.type;
796 const subtype = object.subtype;
Blink Reformat4c46d092018-04-07 15:32:37797 let description = '';
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18798 if (type !== 'function' && object.description) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34799 if (type === 'string' || subtype === 'regexp') {
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18800 description = object.description.trimMiddle(maxLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:34801 } else {
Tim van der Lippeffa78622019-09-16 12:07:12802 description = object.description.trimEndWithMaxLength(maxLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:34803 }
Blink Reformat4c46d092018-04-07 15:32:37804 }
805 rootElement.appendChild(this._previewFormatter.renderPropertyPreview(type, subtype, description));
806 }
807 }
808
809 return rootElement;
810 }
811
812 /**
813 * @param {string} format
814 * @param {!Array.<!SDK.RemoteObject>} parameters
815 * @param {!Element} formattedResult
816 */
817 _formatWithSubstitutionString(format, parameters, formattedResult) {
818 const formatters = {};
819
820 /**
821 * @param {boolean} force
822 * @param {boolean} includePreview
823 * @param {!SDK.RemoteObject} obj
824 * @return {!Element}
825 * @this {Console.ConsoleViewMessage}
826 */
827 function parameterFormatter(force, includePreview, obj) {
828 return this._formatParameter(obj, force, includePreview);
829 }
830
831 function stringFormatter(obj) {
832 return obj.description;
833 }
834
835 function floatFormatter(obj) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34836 if (typeof obj.value !== 'number') {
Blink Reformat4c46d092018-04-07 15:32:37837 return 'NaN';
Tim van der Lippe1d6e57a2019-09-30 11:55:34838 }
Blink Reformat4c46d092018-04-07 15:32:37839 return obj.value;
840 }
841
842 function integerFormatter(obj) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34843 if (obj.type === 'bigint') {
Alexey Kozyatinskiybeb38de2018-08-10 18:54:19844 return obj.description;
Tim van der Lippe1d6e57a2019-09-30 11:55:34845 }
846 if (typeof obj.value !== 'number') {
Blink Reformat4c46d092018-04-07 15:32:37847 return 'NaN';
Tim van der Lippe1d6e57a2019-09-30 11:55:34848 }
Blink Reformat4c46d092018-04-07 15:32:37849 return Math.floor(obj.value);
850 }
851
852 function bypassFormatter(obj) {
853 return (obj instanceof Node) ? obj : '';
854 }
855
856 let currentStyle = null;
857 function styleFormatter(obj) {
858 currentStyle = {};
859 const buffer = createElement('span');
860 buffer.setAttribute('style', obj.description);
861 for (let i = 0; i < buffer.style.length; i++) {
862 const property = buffer.style[i];
Tim van der Lippe1d6e57a2019-09-30 11:55:34863 if (isWhitelistedProperty(property)) {
Blink Reformat4c46d092018-04-07 15:32:37864 currentStyle[property] = buffer.style[property];
Tim van der Lippe1d6e57a2019-09-30 11:55:34865 }
Blink Reformat4c46d092018-04-07 15:32:37866 }
867 }
868
869 function isWhitelistedProperty(property) {
870 // Make sure that allowed properties do not interfere with link visibility.
871 const prefixes = [
872 'background', 'border', 'color', 'font', 'line', 'margin', 'padding', 'text', '-webkit-background',
873 '-webkit-border', '-webkit-font', '-webkit-margin', '-webkit-padding', '-webkit-text'
874 ];
875 for (let i = 0; i < prefixes.length; i++) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34876 if (property.startsWith(prefixes[i])) {
Blink Reformat4c46d092018-04-07 15:32:37877 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:34878 }
Blink Reformat4c46d092018-04-07 15:32:37879 }
880 return false;
881 }
882
883 // Firebug uses %o for formatting objects.
884 formatters.o = parameterFormatter.bind(this, false /* force */, true /* includePreview */);
885 formatters.s = stringFormatter;
886 formatters.f = floatFormatter;
887 // Firebug allows both %i and %d for formatting integers.
888 formatters.i = integerFormatter;
889 formatters.d = integerFormatter;
890
891 // Firebug uses %c for styling the message.
892 formatters.c = styleFormatter;
893
894 // Support %O to force object formatting, instead of the type-based %o formatting.
895 formatters.O = parameterFormatter.bind(this, true /* force */, false /* includePreview */);
896
897 formatters._ = bypassFormatter;
898
899 /**
900 * @param {!Element} a
901 * @param {*} b
902 * @this {!Console.ConsoleViewMessage}
Erik Luo17926392018-05-17 22:06:12903 * @return {!Element}
Blink Reformat4c46d092018-04-07 15:32:37904 */
905 function append(a, b) {
906 if (b instanceof Node) {
907 a.appendChild(b);
Erik Luo17926392018-05-17 22:06:12908 return a;
909 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34910 if (typeof b === 'undefined') {
Erik Luo17926392018-05-17 22:06:12911 return a;
Tim van der Lippe1d6e57a2019-09-30 11:55:34912 }
Erik Luo17926392018-05-17 22:06:12913 if (!currentStyle) {
Erik Luo383f21d2018-11-07 23:16:37914 a.appendChild(this._linkifyStringAsFragment(String(b)));
Erik Luo17926392018-05-17 22:06:12915 return a;
916 }
917 const lines = String(b).split('\n');
918 for (let i = 0; i < lines.length; i++) {
919 const line = lines[i];
Erik Luo383f21d2018-11-07 23:16:37920 const lineFragment = this._linkifyStringAsFragment(line);
Erik Luo17926392018-05-17 22:06:12921 const wrapper = createElement('span');
922 wrapper.style.setProperty('contain', 'paint');
923 wrapper.style.setProperty('display', 'inline-block');
924 wrapper.style.setProperty('max-width', '100%');
925 wrapper.appendChild(lineFragment);
926 applyCurrentStyle(wrapper);
927 for (const child of wrapper.children) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34928 if (child.classList.contains('devtools-link')) {
Erik Luo17926392018-05-17 22:06:12929 this._applyForcedVisibleStyle(child);
Tim van der Lippe1d6e57a2019-09-30 11:55:34930 }
Blink Reformat4c46d092018-04-07 15:32:37931 }
Erik Luo17926392018-05-17 22:06:12932 a.appendChild(wrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34933 if (i < lines.length - 1) {
Erik Luo17926392018-05-17 22:06:12934 a.appendChild(createElement('br'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34935 }
Blink Reformat4c46d092018-04-07 15:32:37936 }
937 return a;
938 }
939
940 /**
941 * @param {!Element} element
942 */
943 function applyCurrentStyle(element) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34944 for (const key in currentStyle) {
Blink Reformat4c46d092018-04-07 15:32:37945 element.style[key] = currentStyle[key];
Tim van der Lippe1d6e57a2019-09-30 11:55:34946 }
Blink Reformat4c46d092018-04-07 15:32:37947 }
948
949 // String.format does treat formattedResult like a Builder, result is an object.
950 return String.format(format, parameters, formatters, formattedResult, append.bind(this));
951 }
952
953 /**
954 * @param {!Element} element
955 */
956 _applyForcedVisibleStyle(element) {
957 element.style.setProperty('-webkit-text-stroke', '0', 'important');
958 element.style.setProperty('text-decoration', 'underline', 'important');
959
960 const themedColor = UI.themeSupport.patchColorText('rgb(33%, 33%, 33%)', UI.ThemeSupport.ColorUsage.Foreground);
961 element.style.setProperty('color', themedColor, 'important');
962
963 let backgroundColor = 'hsl(0, 0%, 100%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:34964 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
Blink Reformat4c46d092018-04-07 15:32:37965 backgroundColor = 'hsl(0, 100%, 97%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:34966 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning || this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:37967 backgroundColor = 'hsl(50, 100%, 95%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:34968 }
Blink Reformat4c46d092018-04-07 15:32:37969 const themedBackgroundColor =
970 UI.themeSupport.patchColorText(backgroundColor, UI.ThemeSupport.ColorUsage.Background);
971 element.style.setProperty('background-color', themedBackgroundColor, 'important');
972 }
973
974 /**
975 * @return {boolean}
976 */
977 matchesFilterRegex(regexObject) {
978 regexObject.lastIndex = 0;
Erik Luo5976c8c2018-07-24 02:03:09979 const contentElement = this.contentElement();
980 const anchorText = this._anchorElement ? this._anchorElement.deepTextContent() : '';
981 return (anchorText && regexObject.test(anchorText.trim())) ||
982 regexObject.test(contentElement.deepTextContent().slice(anchorText.length));
Blink Reformat4c46d092018-04-07 15:32:37983 }
984
985 /**
986 * @param {string} filter
987 * @return {boolean}
988 */
989 matchesFilterText(filter) {
990 const text = this.contentElement().deepTextContent();
991 return text.toLowerCase().includes(filter.toLowerCase());
992 }
993
994 updateTimestamp() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34995 if (!this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:37996 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34997 }
Blink Reformat4c46d092018-04-07 15:32:37998
999 if (Common.moduleSetting('consoleTimestampsEnabled').get()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341000 if (!this._timestampElement) {
Blink Reformat4c46d092018-04-07 15:32:371001 this._timestampElement = createElementWithClass('span', 'console-timestamp');
Tim van der Lippe1d6e57a2019-09-30 11:55:341002 }
Rayan Kansoaca06e72019-03-27 11:57:061003 this._timestampElement.textContent = UI.formatTimestamp(this._message.timestamp, false) + ' ';
1004 this._timestampElement.title = UI.formatTimestamp(this._message.timestamp, true);
Blink Reformat4c46d092018-04-07 15:32:371005 this._contentElement.insertBefore(this._timestampElement, this._contentElement.firstChild);
1006 } else if (this._timestampElement) {
1007 this._timestampElement.remove();
1008 delete this._timestampElement;
1009 }
Blink Reformat4c46d092018-04-07 15:32:371010 }
1011
1012 /**
1013 * @return {number}
1014 */
1015 nestingLevel() {
1016 return this._nestingLevel;
1017 }
1018
1019 /**
1020 * @param {boolean} inSimilarGroup
1021 * @param {boolean=} isLast
1022 */
1023 setInSimilarGroup(inSimilarGroup, isLast) {
1024 this._inSimilarGroup = inSimilarGroup;
1025 this._lastInSimilarGroup = inSimilarGroup && !!isLast;
1026 if (this._similarGroupMarker && !inSimilarGroup) {
1027 this._similarGroupMarker.remove();
1028 this._similarGroupMarker = null;
1029 } else if (this._element && !this._similarGroupMarker && inSimilarGroup) {
1030 this._similarGroupMarker = createElementWithClass('div', 'nesting-level-marker');
1031 this._element.insertBefore(this._similarGroupMarker, this._element.firstChild);
1032 this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
1033 }
1034 }
1035
1036 /**
1037 * @return {boolean}
1038 */
1039 isLastInSimilarGroup() {
1040 return this._inSimilarGroup && this._lastInSimilarGroup;
1041 }
1042
1043 resetCloseGroupDecorationCount() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341044 if (!this._closeGroupDecorationCount) {
Blink Reformat4c46d092018-04-07 15:32:371045 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341046 }
Blink Reformat4c46d092018-04-07 15:32:371047 this._closeGroupDecorationCount = 0;
1048 this._updateCloseGroupDecorations();
1049 }
1050
1051 incrementCloseGroupDecorationCount() {
1052 ++this._closeGroupDecorationCount;
1053 this._updateCloseGroupDecorations();
1054 }
1055
1056 _updateCloseGroupDecorations() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341057 if (!this._nestingLevelMarkers) {
Blink Reformat4c46d092018-04-07 15:32:371058 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341059 }
Blink Reformat4c46d092018-04-07 15:32:371060 for (let i = 0, n = this._nestingLevelMarkers.length; i < n; ++i) {
1061 const marker = this._nestingLevelMarkers[i];
1062 marker.classList.toggle('group-closed', n - i <= this._closeGroupDecorationCount);
1063 }
1064 }
1065
1066 /**
Erik Luo0b8282e2018-10-08 20:37:461067 * @return {number}
1068 */
1069 _focusedChildIndex() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341070 if (!this._selectableChildren.length) {
Erik Luo0b8282e2018-10-08 20:37:461071 return -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341072 }
Erik Luo383f21d2018-11-07 23:16:371073 return this._selectableChildren.findIndex(child => child.element.hasFocus());
Erik Luo0b8282e2018-10-08 20:37:461074 }
1075
1076 /**
Erik Luo8ef5d0c2018-09-25 21:16:001077 * @param {!Event} event
1078 */
1079 _onKeyDown(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341080 if (UI.isEditing() || !this._element.hasFocus() || this._element.hasSelection()) {
Erik Luo8ef5d0c2018-09-25 21:16:001081 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341082 }
1083 if (this.maybeHandleOnKeyDown(event)) {
Erik Luo8ef5d0c2018-09-25 21:16:001084 event.consume(true);
Tim van der Lippe1d6e57a2019-09-30 11:55:341085 }
Erik Luo8ef5d0c2018-09-25 21:16:001086 }
1087
1088 /**
1089 * @protected
1090 * @param {!Event} event
1091 */
1092 maybeHandleOnKeyDown(event) {
1093 // Handle trace expansion.
Erik Luo0b8282e2018-10-08 20:37:461094 const focusedChildIndex = this._focusedChildIndex();
1095 const isWrapperFocused = focusedChildIndex === -1;
1096 if (this._expandTrace && isWrapperFocused) {
Erik Luo8ef5d0c2018-09-25 21:16:001097 if ((event.key === 'ArrowLeft' && this._traceExpanded) || (event.key === 'ArrowRight' && !this._traceExpanded)) {
1098 this._expandTrace(!this._traceExpanded);
1099 return true;
1100 }
1101 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341102 if (!this._selectableChildren.length) {
Erik Luo0b8282e2018-10-08 20:37:461103 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:341104 }
Erik Luo0b8282e2018-10-08 20:37:461105
1106 if (event.key === 'ArrowLeft') {
1107 this._element.focus();
1108 return true;
1109 }
1110 if (event.key === 'ArrowRight') {
Tim van der Lippe1d6e57a2019-09-30 11:55:341111 if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
Erik Luo0b8282e2018-10-08 20:37:461112 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341113 }
Erik Luo0b8282e2018-10-08 20:37:461114 }
1115 if (event.key === 'ArrowUp') {
Erik Luo182bece2018-11-29 03:15:221116 const firstVisibleChild = this._nearestVisibleChild(0);
1117 if (this._selectableChildren[focusedChildIndex] === firstVisibleChild && firstVisibleChild) {
Erik Luo0b8282e2018-10-08 20:37:461118 this._element.focus();
1119 return true;
Erik Luo182bece2018-11-29 03:15:221120 } else if (this._selectNearestVisibleChild(focusedChildIndex - 1, true /* backwards */)) {
Erik Luo0b8282e2018-10-08 20:37:461121 return true;
1122 }
1123 }
1124 if (event.key === 'ArrowDown') {
Tim van der Lippe1d6e57a2019-09-30 11:55:341125 if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
Erik Luo0b8282e2018-10-08 20:37:461126 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341127 }
1128 if (!isWrapperFocused && this._selectNearestVisibleChild(focusedChildIndex + 1)) {
Erik Luo0b8282e2018-10-08 20:37:461129 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341130 }
Erik Luo0b8282e2018-10-08 20:37:461131 }
Erik Luo8ef5d0c2018-09-25 21:16:001132 return false;
1133 }
1134
Erik Luo182bece2018-11-29 03:15:221135 /**
1136 * @param {number} fromIndex
1137 * @param {boolean=} backwards
1138 * @return {boolean}
1139 */
1140 _selectNearestVisibleChild(fromIndex, backwards) {
1141 const nearestChild = this._nearestVisibleChild(fromIndex, backwards);
1142 if (nearestChild) {
Erik Luo31c21f62018-12-13 03:39:391143 nearestChild.forceSelect();
Erik Luo182bece2018-11-29 03:15:221144 return true;
1145 }
1146 return false;
1147 }
1148
1149 /**
1150 * @param {number} fromIndex
1151 * @param {boolean=} backwards
Erik Luo31c21f62018-12-13 03:39:391152 * @return {?{element: !Element, forceSelect: function()}}
Erik Luo182bece2018-11-29 03:15:221153 */
1154 _nearestVisibleChild(fromIndex, backwards) {
1155 const childCount = this._selectableChildren.length;
Tim van der Lippe1d6e57a2019-09-30 11:55:341156 if (fromIndex < 0 || fromIndex >= childCount) {
Erik Luo182bece2018-11-29 03:15:221157 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341158 }
Erik Luo182bece2018-11-29 03:15:221159 const direction = backwards ? -1 : 1;
1160 let index = fromIndex;
1161
1162 while (!this._selectableChildren[index].element.offsetParent) {
1163 index += direction;
Tim van der Lippe1d6e57a2019-09-30 11:55:341164 if (index < 0 || index >= childCount) {
Erik Luo182bece2018-11-29 03:15:221165 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341166 }
Erik Luo182bece2018-11-29 03:15:221167 }
1168 return this._selectableChildren[index];
1169 }
1170
Erik Luo0b8282e2018-10-08 20:37:461171 focusLastChildOrSelf() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341172 if (this._element && !this._selectNearestVisibleChild(this._selectableChildren.length - 1, true /* backwards */)) {
Erik Luo0b8282e2018-10-08 20:37:461173 this._element.focus();
Tim van der Lippe1d6e57a2019-09-30 11:55:341174 }
Erik Luo0b8282e2018-10-08 20:37:461175 }
1176
1177 /**
Blink Reformat4c46d092018-04-07 15:32:371178 * @return {!Element}
1179 */
1180 contentElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341181 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371182 return this._contentElement;
Tim van der Lippe1d6e57a2019-09-30 11:55:341183 }
Blink Reformat4c46d092018-04-07 15:32:371184
1185 const contentElement = createElementWithClass('div', 'console-message');
Tim van der Lippe1d6e57a2019-09-30 11:55:341186 if (this._messageLevelIcon) {
Blink Reformat4c46d092018-04-07 15:32:371187 contentElement.appendChild(this._messageLevelIcon);
Tim van der Lippe1d6e57a2019-09-30 11:55:341188 }
Blink Reformat4c46d092018-04-07 15:32:371189 this._contentElement = contentElement;
1190
1191 let formattedMessage;
1192 const shouldIncludeTrace = !!this._message.stackTrace &&
1193 (this._message.source === SDK.ConsoleMessage.MessageSource.Network ||
1194 this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
1195 this._message.level === SDK.ConsoleMessage.MessageLevel.Error ||
1196 this._message.level === SDK.ConsoleMessage.MessageLevel.Warning ||
1197 this._message.type === SDK.ConsoleMessage.MessageType.Trace);
Tim van der Lippe1d6e57a2019-09-30 11:55:341198 if (this._message.runtimeModel() && shouldIncludeTrace) {
Blink Reformat4c46d092018-04-07 15:32:371199 formattedMessage = this._buildMessageWithStackTrace();
Tim van der Lippe1d6e57a2019-09-30 11:55:341200 } else if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
Blink Reformat4c46d092018-04-07 15:32:371201 formattedMessage = this._buildTableMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:341202 } else {
Blink Reformat4c46d092018-04-07 15:32:371203 formattedMessage = this._buildMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:341204 }
Blink Reformat4c46d092018-04-07 15:32:371205 contentElement.appendChild(formattedMessage);
1206
1207 this.updateTimestamp();
1208 return this._contentElement;
1209 }
1210
1211 /**
1212 * @return {!Element}
1213 */
1214 toMessageElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341215 if (this._element) {
Blink Reformat4c46d092018-04-07 15:32:371216 return this._element;
Tim van der Lippe1d6e57a2019-09-30 11:55:341217 }
Blink Reformat4c46d092018-04-07 15:32:371218
1219 this._element = createElement('div');
Pavel Feldmandb310912019-01-30 00:31:201220 this._element.tabIndex = -1;
1221 this._element.addEventListener('keydown', this._onKeyDown.bind(this));
Blink Reformat4c46d092018-04-07 15:32:371222 this.updateMessageElement();
1223 return this._element;
1224 }
1225
1226 updateMessageElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341227 if (!this._element) {
Blink Reformat4c46d092018-04-07 15:32:371228 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341229 }
Blink Reformat4c46d092018-04-07 15:32:371230
1231 this._element.className = 'console-message-wrapper';
1232 this._element.removeChildren();
Tim van der Lippe1d6e57a2019-09-30 11:55:341233 if (this._message.isGroupStartMessage()) {
Blink Reformat4c46d092018-04-07 15:32:371234 this._element.classList.add('console-group-title');
Tim van der Lippe1d6e57a2019-09-30 11:55:341235 }
1236 if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
Blink Reformat4c46d092018-04-07 15:32:371237 this._element.classList.add('console-from-api');
Tim van der Lippe1d6e57a2019-09-30 11:55:341238 }
Blink Reformat4c46d092018-04-07 15:32:371239 if (this._inSimilarGroup) {
1240 this._similarGroupMarker = this._element.createChild('div', 'nesting-level-marker');
1241 this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
1242 }
1243
1244 this._nestingLevelMarkers = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341245 for (let i = 0; i < this._nestingLevel; ++i) {
Blink Reformat4c46d092018-04-07 15:32:371246 this._nestingLevelMarkers.push(this._element.createChild('div', 'nesting-level-marker'));
Tim van der Lippe1d6e57a2019-09-30 11:55:341247 }
Blink Reformat4c46d092018-04-07 15:32:371248 this._updateCloseGroupDecorations();
1249 this._element.message = this;
1250
1251 switch (this._message.level) {
1252 case SDK.ConsoleMessage.MessageLevel.Verbose:
1253 this._element.classList.add('console-verbose-level');
Blink Reformat4c46d092018-04-07 15:32:371254 break;
1255 case SDK.ConsoleMessage.MessageLevel.Info:
1256 this._element.classList.add('console-info-level');
Tim van der Lippe1d6e57a2019-09-30 11:55:341257 if (this._message.type === SDK.ConsoleMessage.MessageType.System) {
Blink Reformat4c46d092018-04-07 15:32:371258 this._element.classList.add('console-system-type');
Tim van der Lippe1d6e57a2019-09-30 11:55:341259 }
Blink Reformat4c46d092018-04-07 15:32:371260 break;
1261 case SDK.ConsoleMessage.MessageLevel.Warning:
1262 this._element.classList.add('console-warning-level');
Blink Reformat4c46d092018-04-07 15:32:371263 break;
1264 case SDK.ConsoleMessage.MessageLevel.Error:
1265 this._element.classList.add('console-error-level');
Blink Reformat4c46d092018-04-07 15:32:371266 break;
1267 }
Erik Luofd3e7d42018-09-25 02:12:351268 this._updateMessageLevelIcon();
Tim van der Lippe1d6e57a2019-09-30 11:55:341269 if (this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:371270 this._element.classList.add('console-warning-level');
Tim van der Lippe1d6e57a2019-09-30 11:55:341271 }
Blink Reformat4c46d092018-04-07 15:32:371272
1273 this._element.appendChild(this.contentElement());
Tim van der Lippe1d6e57a2019-09-30 11:55:341274 if (this._repeatCount > 1) {
Blink Reformat4c46d092018-04-07 15:32:371275 this._showRepeatCountElement();
Tim van der Lippe1d6e57a2019-09-30 11:55:341276 }
Blink Reformat4c46d092018-04-07 15:32:371277 }
1278
1279 /**
1280 * @return {boolean}
1281 */
1282 _shouldRenderAsWarning() {
1283 return (this._message.level === SDK.ConsoleMessage.MessageLevel.Verbose ||
1284 this._message.level === SDK.ConsoleMessage.MessageLevel.Info) &&
1285 (this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
1286 this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation ||
1287 this._message.source === SDK.ConsoleMessage.MessageSource.Intervention ||
1288 this._message.source === SDK.ConsoleMessage.MessageSource.Recommendation);
1289 }
1290
Erik Luofd3e7d42018-09-25 02:12:351291 _updateMessageLevelIcon() {
1292 let iconType = '';
1293 let accessibleName = '';
1294 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
1295 iconType = 'smallicon-warning';
1296 accessibleName = ls`Warning`;
1297 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
1298 iconType = 'smallicon-error';
1299 accessibleName = ls`Error`;
1300 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341301 if (!iconType && !this._messageLevelIcon) {
Blink Reformat4c46d092018-04-07 15:32:371302 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341303 }
Blink Reformat4c46d092018-04-07 15:32:371304 if (iconType && !this._messageLevelIcon) {
1305 this._messageLevelIcon = UI.Icon.create('', 'message-level-icon');
Tim van der Lippe1d6e57a2019-09-30 11:55:341306 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371307 this._contentElement.insertBefore(this._messageLevelIcon, this._contentElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341308 }
Blink Reformat4c46d092018-04-07 15:32:371309 }
1310 this._messageLevelIcon.setIconType(iconType);
Erik Luofd3e7d42018-09-25 02:12:351311 UI.ARIAUtils.setAccessibleName(this._messageLevelIcon, accessibleName);
Blink Reformat4c46d092018-04-07 15:32:371312 }
1313
1314 /**
1315 * @return {number}
1316 */
1317 repeatCount() {
1318 return this._repeatCount || 1;
1319 }
1320
1321 resetIncrementRepeatCount() {
1322 this._repeatCount = 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341323 if (!this._repeatCountElement) {
Blink Reformat4c46d092018-04-07 15:32:371324 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341325 }
Blink Reformat4c46d092018-04-07 15:32:371326
1327 this._repeatCountElement.remove();
Tim van der Lippe1d6e57a2019-09-30 11:55:341328 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371329 this._contentElement.classList.remove('repeated-message');
Tim van der Lippe1d6e57a2019-09-30 11:55:341330 }
Blink Reformat4c46d092018-04-07 15:32:371331 delete this._repeatCountElement;
1332 }
1333
1334 incrementRepeatCount() {
1335 this._repeatCount++;
1336 this._showRepeatCountElement();
1337 }
1338
1339 /**
1340 * @param {number} repeatCount
1341 */
1342 setRepeatCount(repeatCount) {
1343 this._repeatCount = repeatCount;
1344 this._showRepeatCountElement();
1345 }
1346
1347 _showRepeatCountElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341348 if (!this._element) {
Blink Reformat4c46d092018-04-07 15:32:371349 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341350 }
Blink Reformat4c46d092018-04-07 15:32:371351
1352 if (!this._repeatCountElement) {
Joel Einbinder7fbe24c2019-01-24 05:19:011353 this._repeatCountElement = createElementWithClass('span', 'console-message-repeat-count', 'dt-small-bubble');
Blink Reformat4c46d092018-04-07 15:32:371354 switch (this._message.level) {
1355 case SDK.ConsoleMessage.MessageLevel.Warning:
1356 this._repeatCountElement.type = 'warning';
1357 break;
1358 case SDK.ConsoleMessage.MessageLevel.Error:
1359 this._repeatCountElement.type = 'error';
1360 break;
1361 case SDK.ConsoleMessage.MessageLevel.Verbose:
1362 this._repeatCountElement.type = 'verbose';
1363 break;
1364 default:
1365 this._repeatCountElement.type = 'info';
1366 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341367 if (this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:371368 this._repeatCountElement.type = 'warning';
Tim van der Lippe1d6e57a2019-09-30 11:55:341369 }
Blink Reformat4c46d092018-04-07 15:32:371370
1371 this._element.insertBefore(this._repeatCountElement, this._contentElement);
1372 this._contentElement.classList.add('repeated-message');
1373 }
1374 this._repeatCountElement.textContent = this._repeatCount;
Erik Luofd3e7d42018-09-25 02:12:351375 let accessibleName = ls`Repeat ${this._repeatCount}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341376 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
Erik Luofd3e7d42018-09-25 02:12:351377 accessibleName = ls`Warning ${accessibleName}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341378 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
Erik Luofd3e7d42018-09-25 02:12:351379 accessibleName = ls`Error ${accessibleName}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341380 }
Erik Luofd3e7d42018-09-25 02:12:351381 UI.ARIAUtils.setAccessibleName(this._repeatCountElement, accessibleName);
Blink Reformat4c46d092018-04-07 15:32:371382 }
1383
1384 get text() {
1385 return this._message.messageText;
1386 }
1387
1388 /**
1389 * @return {string}
1390 */
1391 toExportString() {
1392 const lines = [];
1393 const nodes = this.contentElement().childTextNodes();
1394 const messageContent = nodes.map(Components.Linkifier.untruncatedNodeText).join('');
Tim van der Lippe1d6e57a2019-09-30 11:55:341395 for (let i = 0; i < this.repeatCount(); ++i) {
Blink Reformat4c46d092018-04-07 15:32:371396 lines.push(messageContent);
Tim van der Lippe1d6e57a2019-09-30 11:55:341397 }
Blink Reformat4c46d092018-04-07 15:32:371398 return lines.join('\n');
1399 }
1400
1401 /**
1402 * @param {?RegExp} regex
1403 */
1404 setSearchRegex(regex) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341405 if (this._searchHiglightNodeChanges && this._searchHiglightNodeChanges.length) {
Blink Reformat4c46d092018-04-07 15:32:371406 UI.revertDomChanges(this._searchHiglightNodeChanges);
Tim van der Lippe1d6e57a2019-09-30 11:55:341407 }
Blink Reformat4c46d092018-04-07 15:32:371408 this._searchRegex = regex;
1409 this._searchHighlightNodes = [];
1410 this._searchHiglightNodeChanges = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341411 if (!this._searchRegex) {
Blink Reformat4c46d092018-04-07 15:32:371412 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341413 }
Blink Reformat4c46d092018-04-07 15:32:371414
1415 const text = this.contentElement().deepTextContent();
1416 let match;
1417 this._searchRegex.lastIndex = 0;
1418 const sourceRanges = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341419 while ((match = this._searchRegex.exec(text)) && match[0]) {
Blink Reformat4c46d092018-04-07 15:32:371420 sourceRanges.push(new TextUtils.SourceRange(match.index, match[0].length));
Tim van der Lippe1d6e57a2019-09-30 11:55:341421 }
Blink Reformat4c46d092018-04-07 15:32:371422
1423 if (sourceRanges.length) {
1424 this._searchHighlightNodes =
1425 UI.highlightSearchResults(this.contentElement(), sourceRanges, this._searchHiglightNodeChanges);
1426 }
1427 }
1428
1429 /**
1430 * @return {?RegExp}
1431 */
1432 searchRegex() {
1433 return this._searchRegex;
1434 }
1435
1436 /**
1437 * @return {number}
1438 */
1439 searchCount() {
1440 return this._searchHighlightNodes.length;
1441 }
1442
1443 /**
1444 * @return {!Element}
1445 */
1446 searchHighlightNode(index) {
1447 return this._searchHighlightNodes[index];
1448 }
1449
1450 /**
1451 * @param {string} string
1452 * @return {?Element}
1453 */
1454 _tryFormatAsError(string) {
1455 /**
1456 * @param {string} prefix
1457 */
1458 function startsWith(prefix) {
1459 return string.startsWith(prefix);
1460 }
1461
1462 const errorPrefixes =
1463 ['EvalError', 'ReferenceError', 'SyntaxError', 'TypeError', 'RangeError', 'Error', 'URIError'];
Tim van der Lippe1d6e57a2019-09-30 11:55:341464 if (!this._message.runtimeModel() || !errorPrefixes.some(startsWith)) {
Blink Reformat4c46d092018-04-07 15:32:371465 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341466 }
Blink Reformat4c46d092018-04-07 15:32:371467 const debuggerModel = this._message.runtimeModel().debuggerModel();
1468 const baseURL = this._message.runtimeModel().target().inspectedURL();
1469
1470 const lines = string.split('\n');
1471 const links = [];
1472 let position = 0;
1473 for (let i = 0; i < lines.length; ++i) {
1474 position += i > 0 ? lines[i - 1].length + 1 : 0;
1475 const isCallFrameLine = /^\s*at\s/.test(lines[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341476 if (!isCallFrameLine && links.length) {
Blink Reformat4c46d092018-04-07 15:32:371477 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341478 }
Blink Reformat4c46d092018-04-07 15:32:371479
Tim van der Lippe1d6e57a2019-09-30 11:55:341480 if (!isCallFrameLine) {
Blink Reformat4c46d092018-04-07 15:32:371481 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341482 }
Blink Reformat4c46d092018-04-07 15:32:371483
1484 let openBracketIndex = -1;
1485 let closeBracketIndex = -1;
Yang Guo39256bd2019-07-18 06:02:251486 const inBracketsWithLineAndColumn = /\([^\)\(]+:\d+:\d+\)/g;
1487 const inBrackets = /\([^\)\(]+\)/g;
1488 let lastMatch = null;
1489 let currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341490 while ((currentMatch = inBracketsWithLineAndColumn.exec(lines[i]))) {
Yang Guo39256bd2019-07-18 06:02:251491 lastMatch = currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341492 }
Yang Guo39256bd2019-07-18 06:02:251493 if (!lastMatch) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341494 while ((currentMatch = inBrackets.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 }
1498 if (lastMatch) {
1499 openBracketIndex = lastMatch.index;
1500 closeBracketIndex = lastMatch.index + lastMatch[0].length - 1;
Blink Reformat4c46d092018-04-07 15:32:371501 }
1502 const hasOpenBracket = openBracketIndex !== -1;
1503 const left = hasOpenBracket ? openBracketIndex + 1 : lines[i].indexOf('at') + 3;
1504 const right = hasOpenBracket ? closeBracketIndex : lines[i].length;
1505 const linkCandidate = lines[i].substring(left, right);
1506 const splitResult = Common.ParsedURL.splitLineAndColumn(linkCandidate);
Tim van der Lippe1d6e57a2019-09-30 11:55:341507 if (!splitResult) {
Blink Reformat4c46d092018-04-07 15:32:371508 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341509 }
Blink Reformat4c46d092018-04-07 15:32:371510
Tim van der Lippe1d6e57a2019-09-30 11:55:341511 if (splitResult.url === '<anonymous>') {
Blink Reformat4c46d092018-04-07 15:32:371512 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341513 }
Blink Reformat4c46d092018-04-07 15:32:371514 let url = parseOrScriptMatch(splitResult.url);
Tim van der Lippe1d6e57a2019-09-30 11:55:341515 if (!url && Common.ParsedURL.isRelativeURL(splitResult.url)) {
Blink Reformat4c46d092018-04-07 15:32:371516 url = parseOrScriptMatch(Common.ParsedURL.completeURL(baseURL, splitResult.url));
Tim van der Lippe1d6e57a2019-09-30 11:55:341517 }
1518 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:371519 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341520 }
Blink Reformat4c46d092018-04-07 15:32:371521
1522 links.push({
1523 url: url,
1524 positionLeft: position + left,
1525 positionRight: position + right,
1526 lineNumber: splitResult.lineNumber,
1527 columnNumber: splitResult.columnNumber
1528 });
1529 }
1530
Tim van der Lippe1d6e57a2019-09-30 11:55:341531 if (!links.length) {
Blink Reformat4c46d092018-04-07 15:32:371532 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341533 }
Blink Reformat4c46d092018-04-07 15:32:371534
1535 const formattedResult = createElement('span');
1536 let start = 0;
1537 for (let i = 0; i < links.length; ++i) {
Erik Luo383f21d2018-11-07 23:16:371538 formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start, links[i].positionLeft)));
Erik Luo182bece2018-11-29 03:15:221539 const scriptLocationLink = this._linkifier.linkifyScriptLocation(
1540 debuggerModel.target(), null, links[i].url, links[i].lineNumber, links[i].columnNumber);
1541 scriptLocationLink.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:391542 this._selectableChildren.push({element: scriptLocationLink, forceSelect: () => scriptLocationLink.focus()});
Erik Luo182bece2018-11-29 03:15:221543 formattedResult.appendChild(scriptLocationLink);
Blink Reformat4c46d092018-04-07 15:32:371544 start = links[i].positionRight;
1545 }
1546
Tim van der Lippe1d6e57a2019-09-30 11:55:341547 if (start !== string.length) {
Erik Luo383f21d2018-11-07 23:16:371548 formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start)));
Tim van der Lippe1d6e57a2019-09-30 11:55:341549 }
Blink Reformat4c46d092018-04-07 15:32:371550
1551 return formattedResult;
1552
1553 /**
1554 * @param {?string} url
1555 * @return {?string}
1556 */
1557 function parseOrScriptMatch(url) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341558 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:371559 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341560 }
Peter Marshall3e4e5692019-12-09 16:48:041561 const parsedURL = Common.ParsedURL.fromString(url);
Tim van der Lippe1d6e57a2019-09-30 11:55:341562 if (parsedURL) {
Blink Reformat4c46d092018-04-07 15:32:371563 return parsedURL.url;
Tim van der Lippe1d6e57a2019-09-30 11:55:341564 }
1565 if (debuggerModel.scriptsForSourceURL(url).length) {
Blink Reformat4c46d092018-04-07 15:32:371566 return url;
Tim van der Lippe1d6e57a2019-09-30 11:55:341567 }
Blink Reformat4c46d092018-04-07 15:32:371568 return null;
1569 }
1570 }
1571
1572 /**
1573 * @param {string} string
1574 * @param {function(string,string,number=,number=):!Node} linkifier
1575 * @return {!DocumentFragment}
1576 */
Erik Luofc2214f2018-11-21 19:54:581577 _linkifyWithCustomLinkifier(string, linkifier) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341578 if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Erik Luo5fb33bd2018-06-04 23:23:521579 return UI.createExpandableText(string, Console.ConsoleViewMessage._LongStringVisibleLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:341580 }
Blink Reformat4c46d092018-04-07 15:32:371581 const container = createDocumentFragment();
Erik Luofc2214f2018-11-21 19:54:581582 const tokens = Console.ConsoleViewMessage._tokenizeMessageText(string);
Blink Reformat4c46d092018-04-07 15:32:371583 for (const token of tokens) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341584 if (!token.text) {
Erik Luofc2214f2018-11-21 19:54:581585 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341586 }
Blink Reformat4c46d092018-04-07 15:32:371587 switch (token.type) {
1588 case 'url': {
1589 const realURL = (token.text.startsWith('www.') ? 'http://' + token.text : token.text);
1590 const splitResult = Common.ParsedURL.splitLineAndColumn(realURL);
1591 let linkNode;
Tim van der Lippe1d6e57a2019-09-30 11:55:341592 if (splitResult) {
Blink Reformat4c46d092018-04-07 15:32:371593 linkNode = linkifier(token.text, splitResult.url, splitResult.lineNumber, splitResult.columnNumber);
Tim van der Lippe1d6e57a2019-09-30 11:55:341594 } else {
Blink Reformat4c46d092018-04-07 15:32:371595 linkNode = linkifier(token.text, token.value);
Tim van der Lippe1d6e57a2019-09-30 11:55:341596 }
Blink Reformat4c46d092018-04-07 15:32:371597 container.appendChild(linkNode);
1598 break;
1599 }
1600 default:
1601 container.appendChild(createTextNode(token.text));
1602 break;
1603 }
1604 }
1605 return container;
1606 }
1607
1608 /**
Blink Reformat4c46d092018-04-07 15:32:371609 * @param {string} string
1610 * @return {!DocumentFragment}
1611 */
Erik Luo383f21d2018-11-07 23:16:371612 _linkifyStringAsFragment(string) {
Erik Luofc2214f2018-11-21 19:54:581613 return this._linkifyWithCustomLinkifier(string, (text, url, lineNumber, columnNumber) => {
Erik Luo383f21d2018-11-07 23:16:371614 const linkElement = Components.Linkifier.linkifyURL(url, {text, lineNumber, columnNumber});
1615 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:391616 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo383f21d2018-11-07 23:16:371617 return linkElement;
Blink Reformat4c46d092018-04-07 15:32:371618 });
1619 }
1620
1621 /**
1622 * @param {string} string
1623 * @return {!Array<{type: string, text: (string|undefined)}>}
1624 */
1625 static _tokenizeMessageText(string) {
1626 if (!Console.ConsoleViewMessage._tokenizerRegexes) {
1627 const controlCodes = '\\u0000-\\u0020\\u007f-\\u009f';
1628 const linkStringRegex = new RegExp(
1629 '(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|data:|www\\.)[^\\s' + controlCodes + '"]{2,}[^\\s' + controlCodes +
1630 '"\')}\\],:;.!?]',
1631 'u');
1632 const pathLineRegex = /(?:\/[\w\.-]*)+\:[\d]+/;
1633 const timeRegex = /took [\d]+ms/;
1634 const eventRegex = /'\w+' event/;
1635 const milestoneRegex = /\sM[6-7]\d/;
1636 const autofillRegex = /\(suggested: \"[\w-]+\"\)/;
1637 const handlers = new Map();
1638 handlers.set(linkStringRegex, 'url');
1639 handlers.set(pathLineRegex, 'url');
1640 handlers.set(timeRegex, 'time');
1641 handlers.set(eventRegex, 'event');
1642 handlers.set(milestoneRegex, 'milestone');
1643 handlers.set(autofillRegex, 'autofill');
1644 Console.ConsoleViewMessage._tokenizerRegexes = Array.from(handlers.keys());
1645 Console.ConsoleViewMessage._tokenizerTypes = Array.from(handlers.values());
1646 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341647 if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Blink Reformat4c46d092018-04-07 15:32:371648 return [{text: string, type: undefined}];
Tim van der Lippe1d6e57a2019-09-30 11:55:341649 }
Blink Reformat4c46d092018-04-07 15:32:371650 const results = TextUtils.TextUtils.splitStringByRegexes(string, Console.ConsoleViewMessage._tokenizerRegexes);
1651 return results.map(
1652 result => ({text: result.value, type: Console.ConsoleViewMessage._tokenizerTypes[result.regexIndex]}));
1653 }
1654
1655 /**
1656 * @return {string}
1657 */
1658 groupKey() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341659 if (!this._groupKey) {
Blink Reformat4c46d092018-04-07 15:32:371660 this._groupKey = this._message.groupCategoryKey() + ':' + this.groupTitle();
Tim van der Lippe1d6e57a2019-09-30 11:55:341661 }
Blink Reformat4c46d092018-04-07 15:32:371662 return this._groupKey;
1663 }
1664
1665 /**
1666 * @return {string}
1667 */
1668 groupTitle() {
1669 const tokens = Console.ConsoleViewMessage._tokenizeMessageText(this._message.messageText);
1670 const result = tokens.reduce((acc, token) => {
1671 let text = token.text;
Tim van der Lippe1d6e57a2019-09-30 11:55:341672 if (token.type === 'url') {
Blink Reformat4c46d092018-04-07 15:32:371673 text = Common.UIString('<URL>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341674 } else if (token.type === 'time') {
Blink Reformat4c46d092018-04-07 15:32:371675 text = Common.UIString('took <N>ms');
Tim van der Lippe1d6e57a2019-09-30 11:55:341676 } else if (token.type === 'event') {
Blink Reformat4c46d092018-04-07 15:32:371677 text = Common.UIString('<some> event');
Tim van der Lippe1d6e57a2019-09-30 11:55:341678 } else if (token.type === 'milestone') {
Blink Reformat4c46d092018-04-07 15:32:371679 text = Common.UIString(' M<XX>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341680 } else if (token.type === 'autofill') {
Blink Reformat4c46d092018-04-07 15:32:371681 text = Common.UIString('<attribute>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341682 }
Blink Reformat4c46d092018-04-07 15:32:371683 return acc + text;
1684 }, '');
1685 return result.replace(/[%]o/g, '');
1686 }
Paul Lewisbf7aa3c2019-11-20 17:03:381687}
Blink Reformat4c46d092018-04-07 15:32:371688
1689/**
1690 * @unrestricted
1691 */
Paul Lewisbf7aa3c2019-11-20 17:03:381692export class ConsoleGroupViewMessage extends ConsoleViewMessage {
Blink Reformat4c46d092018-04-07 15:32:371693 /**
1694 * @param {!SDK.ConsoleMessage} consoleMessage
1695 * @param {!Components.Linkifier} linkifier
Blink Reformat4c46d092018-04-07 15:32:371696 * @param {number} nestingLevel
Erik Luo8ef5d0c2018-09-25 21:16:001697 * @param {function()} onToggle
Erik Luo840be6b2018-12-03 20:54:271698 * @param {function(!Common.Event)} onResize
Blink Reformat4c46d092018-04-07 15:32:371699 */
Tim van der Lippeb45d9a02019-11-05 17:24:411700 constructor(consoleMessage, linkifier, nestingLevel, onToggle, onResize) {
Blink Reformat4c46d092018-04-07 15:32:371701 console.assert(consoleMessage.isGroupStartMessage());
Tim van der Lippeb45d9a02019-11-05 17:24:411702 super(consoleMessage, linkifier, nestingLevel, onResize);
Blink Reformat4c46d092018-04-07 15:32:371703 this._collapsed = consoleMessage.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed;
1704 /** @type {?UI.Icon} */
1705 this._expandGroupIcon = null;
Erik Luo8ef5d0c2018-09-25 21:16:001706 this._onToggle = onToggle;
Blink Reformat4c46d092018-04-07 15:32:371707 }
1708
1709 /**
1710 * @param {boolean} collapsed
1711 */
Erik Luo8ef5d0c2018-09-25 21:16:001712 _setCollapsed(collapsed) {
Blink Reformat4c46d092018-04-07 15:32:371713 this._collapsed = collapsed;
Tim van der Lippe1d6e57a2019-09-30 11:55:341714 if (this._expandGroupIcon) {
Blink Reformat4c46d092018-04-07 15:32:371715 this._expandGroupIcon.setIconType(this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down');
Tim van der Lippe1d6e57a2019-09-30 11:55:341716 }
Erik Luo8ef5d0c2018-09-25 21:16:001717 this._onToggle.call(null);
Blink Reformat4c46d092018-04-07 15:32:371718 }
1719
1720 /**
1721 * @return {boolean}
1722 */
1723 collapsed() {
1724 return this._collapsed;
1725 }
1726
1727 /**
1728 * @override
Erik Luo8ef5d0c2018-09-25 21:16:001729 * @param {!Event} event
1730 */
1731 maybeHandleOnKeyDown(event) {
Erik Luo0b8282e2018-10-08 20:37:461732 const focusedChildIndex = this._focusedChildIndex();
1733 if (focusedChildIndex === -1) {
1734 if ((event.key === 'ArrowLeft' && !this._collapsed) || (event.key === 'ArrowRight' && this._collapsed)) {
1735 this._setCollapsed(!this._collapsed);
1736 return true;
1737 }
Erik Luo8ef5d0c2018-09-25 21:16:001738 }
1739 return super.maybeHandleOnKeyDown(event);
1740 }
1741
1742 /**
1743 * @override
Blink Reformat4c46d092018-04-07 15:32:371744 * @return {!Element}
1745 */
1746 toMessageElement() {
1747 if (!this._element) {
1748 super.toMessageElement();
Erik Luo8ef5d0c2018-09-25 21:16:001749 const iconType = this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down';
1750 this._expandGroupIcon = UI.Icon.create(iconType, 'expand-group-icon');
Erik Luob5bfff42018-09-20 02:52:391751 // Intercept focus to avoid highlight on click.
1752 this._contentElement.tabIndex = -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341753 if (this._repeatCountElement) {
Blink Reformat4c46d092018-04-07 15:32:371754 this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341755 } else {
Blink Reformat4c46d092018-04-07 15:32:371756 this._element.insertBefore(this._expandGroupIcon, this._contentElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:341757 }
Erik Luo8ef5d0c2018-09-25 21:16:001758 this._element.addEventListener('click', () => this._setCollapsed(!this._collapsed));
Blink Reformat4c46d092018-04-07 15:32:371759 }
1760 return this._element;
1761 }
1762
1763 /**
1764 * @override
1765 */
1766 _showRepeatCountElement() {
1767 super._showRepeatCountElement();
Tim van der Lippe1d6e57a2019-09-30 11:55:341768 if (this._repeatCountElement && this._expandGroupIcon) {
Blink Reformat4c46d092018-04-07 15:32:371769 this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341770 }
Blink Reformat4c46d092018-04-07 15:32:371771 }
Paul Lewisbf7aa3c2019-11-20 17:03:381772}
Blink Reformat4c46d092018-04-07 15:32:371773
1774/**
1775 * @const
1776 * @type {number}
1777 */
Paul Lewisbf7aa3c2019-11-20 17:03:381778export const MaxLengthForLinks = 40;
Blink Reformat4c46d092018-04-07 15:32:371779
Paul Lewisbf7aa3c2019-11-20 17:03:381780export const _MaxTokenizableStringLength = 10000;
1781export const _LongStringVisibleLength = 5000;
Blink Reformat4c46d092018-04-07 15:32:371782
Paul Lewisbf7aa3c2019-11-20 17:03:381783/* Legacy exported object */
1784self.Console = self.Console || {};
1785
1786/* Legacy exported object */
1787Console = Console || {};
1788
1789/**
1790 * @implements {Console.ConsoleViewportElement}
1791 * @unrestricted
1792 * @constructor
1793 */
1794Console.ConsoleViewMessage = ConsoleViewMessage;
1795
1796/**
1797 * @constructor
1798 */
1799Console.ConsoleGroupViewMessage = ConsoleGroupViewMessage;
1800
1801/**
1802 * @const
1803 * @type {number}
1804 */
1805Console.ConsoleViewMessage.MaxLengthForLinks = MaxLengthForLinks;
1806Console.ConsoleViewMessage._MaxTokenizableStringLength = _MaxTokenizableStringLength;
1807Console.ConsoleViewMessage._LongStringVisibleLength = _LongStringVisibleLength;