blob: b2b1e8ab2a7decaf4d9c3053a322357273b47fb2 [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');
Erik Luo8ef5d0c2018-09-25 21:16:00379 this._expandTrace = expand => {
Blink Reformat4c46d092018-04-07 15:32:37380 icon.setIconType(expand ? 'smallicon-triangle-down' : 'smallicon-triangle-right');
381 stackTraceElement.classList.toggle('hidden', !expand);
Erik Luo8ef5d0c2018-09-25 21:16:00382 this._traceExpanded = expand;
383 };
Blink Reformat4c46d092018-04-07 15:32:37384
385 /**
Erik Luo8ef5d0c2018-09-25 21:16:00386 * @this {!Console.ConsoleViewMessage}
Blink Reformat4c46d092018-04-07 15:32:37387 * @param {?Event} event
388 */
389 function toggleStackTrace(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34390 if (UI.isEditing() || contentElement.hasSelection()) {
Blink Reformat4c46d092018-04-07 15:32:37391 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34392 }
Erik Luo8ef5d0c2018-09-25 21:16:00393 this._expandTrace(stackTraceElement.classList.contains('hidden'));
Blink Reformat4c46d092018-04-07 15:32:37394 event.consume();
395 }
396
Erik Luo8ef5d0c2018-09-25 21:16:00397 clickableElement.addEventListener('click', toggleStackTrace.bind(this), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34398 if (this._message.type === SDK.ConsoleMessage.MessageType.Trace) {
Erik Luo8ef5d0c2018-09-25 21:16:00399 this._expandTrace(true);
Tim van der Lippe1d6e57a2019-09-30 11:55:34400 }
Blink Reformat4c46d092018-04-07 15:32:37401
Erik Luo8ef5d0c2018-09-25 21:16:00402 toggleElement._expandStackTraceForTest = this._expandTrace.bind(this, true);
Blink Reformat4c46d092018-04-07 15:32:37403 return toggleElement;
404 }
405
406 /**
407 * @param {string} url
408 * @param {number} lineNumber
409 * @param {number} columnNumber
410 * @return {?Element}
411 */
412 _linkifyLocation(url, lineNumber, columnNumber) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34413 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37414 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34415 }
Blink Reformat4c46d092018-04-07 15:32:37416 return this._linkifier.linkifyScriptLocation(
417 this._message.runtimeModel().target(), null, url, lineNumber, columnNumber);
418 }
419
420 /**
421 * @param {!Protocol.Runtime.StackTrace} stackTrace
422 * @return {?Element}
423 */
424 _linkifyStackTraceTopFrame(stackTrace) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34425 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37426 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34427 }
Blink Reformat4c46d092018-04-07 15:32:37428 return this._linkifier.linkifyStackTraceTopFrame(this._message.runtimeModel().target(), stackTrace);
429 }
430
431 /**
432 * @param {string} scriptId
433 * @param {string} url
434 * @param {number} lineNumber
435 * @param {number} columnNumber
436 * @return {?Element}
437 */
438 _linkifyScriptId(scriptId, url, lineNumber, columnNumber) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34439 if (!this._message.runtimeModel()) {
Blink Reformat4c46d092018-04-07 15:32:37440 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34441 }
Blink Reformat4c46d092018-04-07 15:32:37442 return this._linkifier.linkifyScriptLocation(
443 this._message.runtimeModel().target(), scriptId, url, lineNumber, columnNumber);
444 }
445
446 /**
447 * @param {!SDK.RemoteObject|!Protocol.Runtime.RemoteObject|string} parameter
448 * @return {!SDK.RemoteObject}
449 */
450 _parameterToRemoteObject(parameter) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34451 if (parameter instanceof SDK.RemoteObject) {
Blink Reformat4c46d092018-04-07 15:32:37452 return parameter;
Tim van der Lippe1d6e57a2019-09-30 11:55:34453 }
Blink Reformat4c46d092018-04-07 15:32:37454 const runtimeModel = this._message.runtimeModel();
Tim van der Lippe1d6e57a2019-09-30 11:55:34455 if (!runtimeModel) {
Blink Reformat4c46d092018-04-07 15:32:37456 return SDK.RemoteObject.fromLocalObject(parameter);
Tim van der Lippe1d6e57a2019-09-30 11:55:34457 }
458 if (typeof parameter === 'object') {
Blink Reformat4c46d092018-04-07 15:32:37459 return runtimeModel.createRemoteObject(parameter);
Tim van der Lippe1d6e57a2019-09-30 11:55:34460 }
Blink Reformat4c46d092018-04-07 15:32:37461 return runtimeModel.createRemoteObjectFromPrimitiveValue(parameter);
462 }
463
464 /**
465 * @param {!Array.<!SDK.RemoteObject|string>} rawParameters
466 * @return {!Element}
467 */
468 _format(rawParameters) {
469 // This node is used like a Builder. Values are continually appended onto it.
470 const formattedResult = createElement('span');
Tim van der Lippe1d6e57a2019-09-30 11:55:34471 if (this._messagePrefix) {
Pavel Feldman9f0f0a32018-12-18 02:09:13472 formattedResult.createChild('span').textContent = this._messagePrefix;
Tim van der Lippe1d6e57a2019-09-30 11:55:34473 }
474 if (!rawParameters.length) {
Blink Reformat4c46d092018-04-07 15:32:37475 return formattedResult;
Tim van der Lippe1d6e57a2019-09-30 11:55:34476 }
Blink Reformat4c46d092018-04-07 15:32:37477
478 // Formatting code below assumes that parameters are all wrappers whereas frontend console
479 // API allows passing arbitrary values as messages (strings, numbers, etc.). Wrap them here.
480 // FIXME: Only pass runtime wrappers here.
481 let parameters = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:34482 for (let i = 0; i < rawParameters.length; ++i) {
Blink Reformat4c46d092018-04-07 15:32:37483 parameters[i] = this._parameterToRemoteObject(rawParameters[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34484 }
Blink Reformat4c46d092018-04-07 15:32:37485
486 // There can be string log and string eval result. We distinguish between them based on message type.
487 const shouldFormatMessage =
488 SDK.RemoteObject.type((/** @type {!Array.<!SDK.RemoteObject>} **/ (parameters))[0]) === 'string' &&
489 (this._message.type !== SDK.ConsoleMessage.MessageType.Result ||
490 this._message.level === SDK.ConsoleMessage.MessageLevel.Error);
491
492 // Multiple parameters with the first being a format string. Save unused substitutions.
493 if (shouldFormatMessage) {
494 const result = this._formatWithSubstitutionString(
495 /** @type {string} **/ (parameters[0].description), parameters.slice(1), formattedResult);
496 parameters = result.unusedSubstitutions;
Tim van der Lippe1d6e57a2019-09-30 11:55:34497 if (parameters.length) {
Blink Reformat4c46d092018-04-07 15:32:37498 formattedResult.createTextChild(' ');
Tim van der Lippe1d6e57a2019-09-30 11:55:34499 }
Blink Reformat4c46d092018-04-07 15:32:37500 }
501
502 // Single parameter, or unused substitutions from above.
503 for (let i = 0; i < parameters.length; ++i) {
504 // Inline strings when formatting.
Tim van der Lippe1d6e57a2019-09-30 11:55:34505 if (shouldFormatMessage && parameters[i].type === 'string') {
Erik Luo383f21d2018-11-07 23:16:37506 formattedResult.appendChild(this._linkifyStringAsFragment(parameters[i].description));
Tim van der Lippe1d6e57a2019-09-30 11:55:34507 } else {
Blink Reformat4c46d092018-04-07 15:32:37508 formattedResult.appendChild(this._formatParameter(parameters[i], false, true));
Tim van der Lippe1d6e57a2019-09-30 11:55:34509 }
510 if (i < parameters.length - 1) {
Blink Reformat4c46d092018-04-07 15:32:37511 formattedResult.createTextChild(' ');
Tim van der Lippe1d6e57a2019-09-30 11:55:34512 }
Blink Reformat4c46d092018-04-07 15:32:37513 }
514 return formattedResult;
515 }
516
517 /**
518 * @param {!SDK.RemoteObject} output
519 * @param {boolean=} forceObjectFormat
520 * @param {boolean=} includePreview
521 * @return {!Element}
522 */
523 _formatParameter(output, forceObjectFormat, includePreview) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34524 if (output.customPreview()) {
Blink Reformat4c46d092018-04-07 15:32:37525 return (new ObjectUI.CustomPreviewComponent(output)).element;
Tim van der Lippe1d6e57a2019-09-30 11:55:34526 }
Blink Reformat4c46d092018-04-07 15:32:37527
528 const type = forceObjectFormat ? 'object' : (output.subtype || output.type);
529 let element;
530 switch (type) {
531 case 'error':
532 element = this._formatParameterAsError(output);
533 break;
534 case 'function':
535 element = this._formatParameterAsFunction(output, includePreview);
536 break;
537 case 'array':
538 case 'arraybuffer':
539 case 'blob':
540 case 'dataview':
541 case 'generator':
542 case 'iterator':
543 case 'map':
544 case 'object':
545 case 'promise':
546 case 'proxy':
547 case 'set':
548 case 'typedarray':
549 case 'weakmap':
550 case 'weakset':
551 element = this._formatParameterAsObject(output, includePreview);
552 break;
553 case 'node':
554 element = output.isNode() ? this._formatParameterAsNode(output) : this._formatParameterAsObject(output, false);
555 break;
556 case 'string':
557 element = this._formatParameterAsString(output);
558 break;
559 case 'boolean':
560 case 'date':
561 case 'null':
562 case 'number':
563 case 'regexp':
564 case 'symbol':
565 case 'undefined':
566 case 'bigint':
567 element = this._formatParameterAsValue(output);
568 break;
569 default:
570 element = this._formatParameterAsValue(output);
571 console.error('Tried to format remote object of unknown type.');
572 }
573 element.classList.add('object-value-' + type);
574 element.classList.add('source-code');
575 return element;
576 }
577
578 /**
579 * @param {!SDK.RemoteObject} obj
580 * @return {!Element}
581 */
582 _formatParameterAsValue(obj) {
583 const result = createElement('span');
584 const description = obj.description || '';
Tim van der Lippe1d6e57a2019-09-30 11:55:34585 if (description.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Erik Luo5fb33bd2018-06-04 23:23:52586 result.appendChild(UI.createExpandableText(description, Console.ConsoleViewMessage._LongStringVisibleLength));
Tim van der Lippe1d6e57a2019-09-30 11:55:34587 } else {
Blink Reformat4c46d092018-04-07 15:32:37588 result.createTextChild(description);
Tim van der Lippe1d6e57a2019-09-30 11:55:34589 }
590 if (obj.objectId) {
Blink Reformat4c46d092018-04-07 15:32:37591 result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, obj), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34592 }
Blink Reformat4c46d092018-04-07 15:32:37593 return result;
594 }
595
596 /**
597 * @param {!SDK.RemoteObject} obj
598 * @param {boolean=} includePreview
599 * @return {!Element}
600 */
601 _formatParameterAsObject(obj, includePreview) {
602 const titleElement = createElementWithClass('span', 'console-object');
603 if (includePreview && obj.preview) {
604 titleElement.classList.add('console-object-preview');
605 this._previewFormatter.appendObjectPreview(titleElement, obj.preview, false /* isEntry */);
606 } else if (obj.type === 'function') {
607 const functionElement = titleElement.createChild('span');
608 ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(obj, functionElement, false);
609 titleElement.classList.add('object-value-function');
610 } else {
611 titleElement.createTextChild(obj.description || '');
612 }
613
Tim van der Lippe1d6e57a2019-09-30 11:55:34614 if (!obj.hasChildren || obj.customPreview()) {
Blink Reformat4c46d092018-04-07 15:32:37615 return titleElement;
Tim van der Lippe1d6e57a2019-09-30 11:55:34616 }
Blink Reformat4c46d092018-04-07 15:32:37617
618 const note = titleElement.createChild('span', 'object-state-note info-note');
Tim van der Lippe1d6e57a2019-09-30 11:55:34619 if (this._message.type === SDK.ConsoleMessage.MessageType.QueryObjectResult) {
Blink Reformat4c46d092018-04-07 15:32:37620 note.title = ls`This value will not be collected until console is cleared.`;
Tim van der Lippe1d6e57a2019-09-30 11:55:34621 } else {
Blink Reformat4c46d092018-04-07 15:32:37622 note.title = ls`Value below was evaluated just now.`;
Tim van der Lippe1d6e57a2019-09-30 11:55:34623 }
Blink Reformat4c46d092018-04-07 15:32:37624
625 const section = new ObjectUI.ObjectPropertiesSection(obj, titleElement, this._linkifier);
626 section.element.classList.add('console-view-object-properties-section');
627 section.enableContextMenu();
Erik Luocc14b812018-11-03 01:33:09628 section.setShowSelectionOnKeyboardFocus(true, true);
Erik Luo383f21d2018-11-07 23:16:37629 this._selectableChildren.push(section);
Erik Luo840be6b2018-12-03 20:54:27630 section.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
631 section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
632 section.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
Blink Reformat4c46d092018-04-07 15:32:37633 return section.element;
634 }
635
636 /**
637 * @param {!SDK.RemoteObject} func
638 * @param {boolean=} includePreview
639 * @return {!Element}
640 */
641 _formatParameterAsFunction(func, includePreview) {
642 const result = createElement('span');
643 SDK.RemoteFunction.objectAsFunction(func).targetFunction().then(formatTargetFunction.bind(this));
644 return result;
645
646 /**
647 * @param {!SDK.RemoteObject} targetFunction
648 * @this {Console.ConsoleViewMessage}
649 */
650 function formatTargetFunction(targetFunction) {
651 const functionElement = createElement('span');
Joey Arhard78a58f2018-12-05 01:59:45652 const promise = ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(
653 targetFunction, functionElement, true, includePreview);
Blink Reformat4c46d092018-04-07 15:32:37654 result.appendChild(functionElement);
655 if (targetFunction !== func) {
656 const note = result.createChild('span', 'object-info-state-note');
657 note.title = Common.UIString('Function was resolved from bound function.');
658 }
659 result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, targetFunction), false);
Joey Arhard78a58f2018-12-05 01:59:45660 promise.then(() => this._formattedParameterAsFunctionForTest());
Blink Reformat4c46d092018-04-07 15:32:37661 }
662 }
663
Joey Arhard78a58f2018-12-05 01:59:45664 _formattedParameterAsFunctionForTest() {
665 }
666
Blink Reformat4c46d092018-04-07 15:32:37667 /**
668 * @param {!SDK.RemoteObject} obj
669 * @param {!Event} event
670 */
671 _contextMenuEventFired(obj, event) {
672 const contextMenu = new UI.ContextMenu(event);
673 contextMenu.appendApplicableItems(obj);
674 contextMenu.show();
675 }
676
677 /**
678 * @param {?SDK.RemoteObject} object
679 * @param {!Array.<!Protocol.Runtime.PropertyPreview>} propertyPath
680 * @return {!Element}
681 */
682 _renderPropertyPreviewOrAccessor(object, propertyPath) {
683 const property = propertyPath.peekLast();
Tim van der Lippe1d6e57a2019-09-30 11:55:34684 if (property.type === 'accessor') {
Blink Reformat4c46d092018-04-07 15:32:37685 return this._formatAsAccessorProperty(object, propertyPath.map(property => property.name), false);
Tim van der Lippe1d6e57a2019-09-30 11:55:34686 }
Blink Reformat4c46d092018-04-07 15:32:37687 return this._previewFormatter.renderPropertyPreview(
688 property.type, /** @type {string} */ (property.subtype), property.value);
689 }
690
691 /**
692 * @param {!SDK.RemoteObject} remoteObject
693 * @return {!Element}
694 */
695 _formatParameterAsNode(remoteObject) {
696 const result = createElement('span');
697
698 const domModel = remoteObject.runtimeModel().target().model(SDK.DOMModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34699 if (!domModel) {
Blink Reformat4c46d092018-04-07 15:32:37700 return result;
Tim van der Lippe1d6e57a2019-09-30 11:55:34701 }
Erik Luo54fdd912018-11-01 17:57:01702 domModel.pushObjectAsNodeToFrontend(remoteObject).then(async node => {
Blink Reformat4c46d092018-04-07 15:32:37703 if (!node) {
704 result.appendChild(this._formatParameterAsObject(remoteObject, false));
705 return;
706 }
Erik Luo54fdd912018-11-01 17:57:01707 const renderResult = await UI.Renderer.render(/** @type {!Object} */ (node));
Erik Luofc6a6302018-11-02 06:48:52708 if (renderResult) {
Erik Luo840be6b2018-12-03 20:54:27709 if (renderResult.tree) {
Erik Luo383f21d2018-11-07 23:16:37710 this._selectableChildren.push(renderResult.tree);
Erik Luo840be6b2018-12-03 20:54:27711 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
712 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
713 renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
714 }
Erik Luofc6a6302018-11-02 06:48:52715 result.appendChild(renderResult.node);
716 } else {
717 result.appendChild(this._formatParameterAsObject(remoteObject, false));
718 }
Erik Luo54fdd912018-11-01 17:57:01719 this._formattedParameterAsNodeForTest();
Blink Reformat4c46d092018-04-07 15:32:37720 });
721
722 return result;
723 }
724
725 _formattedParameterAsNodeForTest() {
726 }
727
728 /**
729 * @param {!SDK.RemoteObject} output
730 * @return {!Element}
731 */
732 _formatParameterAsString(output) {
733 const span = createElement('span');
Erik Luo383f21d2018-11-07 23:16:37734 span.appendChild(this._linkifyStringAsFragment(output.description || ''));
Blink Reformat4c46d092018-04-07 15:32:37735
736 const result = createElement('span');
737 result.createChild('span', 'object-value-string-quote').textContent = '"';
738 result.appendChild(span);
739 result.createChild('span', 'object-value-string-quote').textContent = '"';
740 return result;
741 }
742
743 /**
744 * @param {!SDK.RemoteObject} output
745 * @return {!Element}
746 */
747 _formatParameterAsError(output) {
748 const result = createElement('span');
749 const errorSpan = this._tryFormatAsError(output.description || '');
Erik Luo383f21d2018-11-07 23:16:37750 result.appendChild(errorSpan ? errorSpan : this._linkifyStringAsFragment(output.description || ''));
Blink Reformat4c46d092018-04-07 15:32:37751 return result;
752 }
753
754 /**
755 * @param {!SDK.RemoteObject} output
756 * @return {!Element}
757 */
758 _formatAsArrayEntry(output) {
759 return this._previewFormatter.renderPropertyPreview(output.type, output.subtype, output.description);
760 }
761
762 /**
763 * @param {?SDK.RemoteObject} object
764 * @param {!Array.<string>} propertyPath
765 * @param {boolean} isArrayEntry
766 * @return {!Element}
767 */
768 _formatAsAccessorProperty(object, propertyPath, isArrayEntry) {
769 const rootElement = ObjectUI.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan(
770 object, propertyPath, onInvokeGetterClick.bind(this));
771
772 /**
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18773 * @param {!SDK.CallFunctionResult} result
Blink Reformat4c46d092018-04-07 15:32:37774 * @this {Console.ConsoleViewMessage}
775 */
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18776 function onInvokeGetterClick(result) {
777 const wasThrown = result.wasThrown;
778 const object = result.object;
Tim van der Lippe1d6e57a2019-09-30 11:55:34779 if (!object) {
Blink Reformat4c46d092018-04-07 15:32:37780 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34781 }
Blink Reformat4c46d092018-04-07 15:32:37782 rootElement.removeChildren();
783 if (wasThrown) {
784 const element = rootElement.createChild('span');
785 element.textContent = Common.UIString('<exception>');
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18786 element.title = /** @type {string} */ (object.description);
Blink Reformat4c46d092018-04-07 15:32:37787 } else if (isArrayEntry) {
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18788 rootElement.appendChild(this._formatAsArrayEntry(object));
Blink Reformat4c46d092018-04-07 15:32:37789 } else {
790 // Make a PropertyPreview from the RemoteObject similar to the backend logic.
791 const maxLength = 100;
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18792 const type = object.type;
793 const subtype = object.subtype;
Blink Reformat4c46d092018-04-07 15:32:37794 let description = '';
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18795 if (type !== 'function' && object.description) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34796 if (type === 'string' || subtype === 'regexp') {
Alexey Kozyatinskiy330bffb2018-09-21 19:20:18797 description = object.description.trimMiddle(maxLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:34798 } else {
Tim van der Lippeffa78622019-09-16 12:07:12799 description = object.description.trimEndWithMaxLength(maxLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:34800 }
Blink Reformat4c46d092018-04-07 15:32:37801 }
802 rootElement.appendChild(this._previewFormatter.renderPropertyPreview(type, subtype, description));
803 }
804 }
805
806 return rootElement;
807 }
808
809 /**
810 * @param {string} format
811 * @param {!Array.<!SDK.RemoteObject>} parameters
812 * @param {!Element} formattedResult
813 */
814 _formatWithSubstitutionString(format, parameters, formattedResult) {
815 const formatters = {};
816
817 /**
818 * @param {boolean} force
819 * @param {boolean} includePreview
820 * @param {!SDK.RemoteObject} obj
821 * @return {!Element}
822 * @this {Console.ConsoleViewMessage}
823 */
824 function parameterFormatter(force, includePreview, obj) {
825 return this._formatParameter(obj, force, includePreview);
826 }
827
828 function stringFormatter(obj) {
829 return obj.description;
830 }
831
832 function floatFormatter(obj) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34833 if (typeof obj.value !== 'number') {
Blink Reformat4c46d092018-04-07 15:32:37834 return 'NaN';
Tim van der Lippe1d6e57a2019-09-30 11:55:34835 }
Blink Reformat4c46d092018-04-07 15:32:37836 return obj.value;
837 }
838
839 function integerFormatter(obj) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34840 if (obj.type === 'bigint') {
Alexey Kozyatinskiybeb38de2018-08-10 18:54:19841 return obj.description;
Tim van der Lippe1d6e57a2019-09-30 11:55:34842 }
843 if (typeof obj.value !== 'number') {
Blink Reformat4c46d092018-04-07 15:32:37844 return 'NaN';
Tim van der Lippe1d6e57a2019-09-30 11:55:34845 }
Blink Reformat4c46d092018-04-07 15:32:37846 return Math.floor(obj.value);
847 }
848
849 function bypassFormatter(obj) {
850 return (obj instanceof Node) ? obj : '';
851 }
852
853 let currentStyle = null;
854 function styleFormatter(obj) {
855 currentStyle = {};
856 const buffer = createElement('span');
857 buffer.setAttribute('style', obj.description);
858 for (let i = 0; i < buffer.style.length; i++) {
859 const property = buffer.style[i];
Tim van der Lippe1d6e57a2019-09-30 11:55:34860 if (isWhitelistedProperty(property)) {
Blink Reformat4c46d092018-04-07 15:32:37861 currentStyle[property] = buffer.style[property];
Tim van der Lippe1d6e57a2019-09-30 11:55:34862 }
Blink Reformat4c46d092018-04-07 15:32:37863 }
864 }
865
866 function isWhitelistedProperty(property) {
867 // Make sure that allowed properties do not interfere with link visibility.
868 const prefixes = [
869 'background', 'border', 'color', 'font', 'line', 'margin', 'padding', 'text', '-webkit-background',
870 '-webkit-border', '-webkit-font', '-webkit-margin', '-webkit-padding', '-webkit-text'
871 ];
872 for (let i = 0; i < prefixes.length; i++) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34873 if (property.startsWith(prefixes[i])) {
Blink Reformat4c46d092018-04-07 15:32:37874 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:34875 }
Blink Reformat4c46d092018-04-07 15:32:37876 }
877 return false;
878 }
879
880 // Firebug uses %o for formatting objects.
881 formatters.o = parameterFormatter.bind(this, false /* force */, true /* includePreview */);
882 formatters.s = stringFormatter;
883 formatters.f = floatFormatter;
884 // Firebug allows both %i and %d for formatting integers.
885 formatters.i = integerFormatter;
886 formatters.d = integerFormatter;
887
888 // Firebug uses %c for styling the message.
889 formatters.c = styleFormatter;
890
891 // Support %O to force object formatting, instead of the type-based %o formatting.
892 formatters.O = parameterFormatter.bind(this, true /* force */, false /* includePreview */);
893
894 formatters._ = bypassFormatter;
895
896 /**
897 * @param {!Element} a
898 * @param {*} b
899 * @this {!Console.ConsoleViewMessage}
Erik Luo17926392018-05-17 22:06:12900 * @return {!Element}
Blink Reformat4c46d092018-04-07 15:32:37901 */
902 function append(a, b) {
903 if (b instanceof Node) {
904 a.appendChild(b);
Erik Luo17926392018-05-17 22:06:12905 return a;
906 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34907 if (typeof b === 'undefined') {
Erik Luo17926392018-05-17 22:06:12908 return a;
Tim van der Lippe1d6e57a2019-09-30 11:55:34909 }
Erik Luo17926392018-05-17 22:06:12910 if (!currentStyle) {
Erik Luo383f21d2018-11-07 23:16:37911 a.appendChild(this._linkifyStringAsFragment(String(b)));
Erik Luo17926392018-05-17 22:06:12912 return a;
913 }
914 const lines = String(b).split('\n');
915 for (let i = 0; i < lines.length; i++) {
916 const line = lines[i];
Erik Luo383f21d2018-11-07 23:16:37917 const lineFragment = this._linkifyStringAsFragment(line);
Erik Luo17926392018-05-17 22:06:12918 const wrapper = createElement('span');
919 wrapper.style.setProperty('contain', 'paint');
920 wrapper.style.setProperty('display', 'inline-block');
921 wrapper.style.setProperty('max-width', '100%');
922 wrapper.appendChild(lineFragment);
923 applyCurrentStyle(wrapper);
924 for (const child of wrapper.children) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34925 if (child.classList.contains('devtools-link')) {
Erik Luo17926392018-05-17 22:06:12926 this._applyForcedVisibleStyle(child);
Tim van der Lippe1d6e57a2019-09-30 11:55:34927 }
Blink Reformat4c46d092018-04-07 15:32:37928 }
Erik Luo17926392018-05-17 22:06:12929 a.appendChild(wrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34930 if (i < lines.length - 1) {
Erik Luo17926392018-05-17 22:06:12931 a.appendChild(createElement('br'));
Tim van der Lippe1d6e57a2019-09-30 11:55:34932 }
Blink Reformat4c46d092018-04-07 15:32:37933 }
934 return a;
935 }
936
937 /**
938 * @param {!Element} element
939 */
940 function applyCurrentStyle(element) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34941 for (const key in currentStyle) {
Blink Reformat4c46d092018-04-07 15:32:37942 element.style[key] = currentStyle[key];
Tim van der Lippe1d6e57a2019-09-30 11:55:34943 }
Blink Reformat4c46d092018-04-07 15:32:37944 }
945
946 // String.format does treat formattedResult like a Builder, result is an object.
947 return String.format(format, parameters, formatters, formattedResult, append.bind(this));
948 }
949
950 /**
951 * @param {!Element} element
952 */
953 _applyForcedVisibleStyle(element) {
954 element.style.setProperty('-webkit-text-stroke', '0', 'important');
955 element.style.setProperty('text-decoration', 'underline', 'important');
956
957 const themedColor = UI.themeSupport.patchColorText('rgb(33%, 33%, 33%)', UI.ThemeSupport.ColorUsage.Foreground);
958 element.style.setProperty('color', themedColor, 'important');
959
960 let backgroundColor = 'hsl(0, 0%, 100%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:34961 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
Blink Reformat4c46d092018-04-07 15:32:37962 backgroundColor = 'hsl(0, 100%, 97%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:34963 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning || this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:37964 backgroundColor = 'hsl(50, 100%, 95%)';
Tim van der Lippe1d6e57a2019-09-30 11:55:34965 }
Blink Reformat4c46d092018-04-07 15:32:37966 const themedBackgroundColor =
967 UI.themeSupport.patchColorText(backgroundColor, UI.ThemeSupport.ColorUsage.Background);
968 element.style.setProperty('background-color', themedBackgroundColor, 'important');
969 }
970
971 /**
972 * @return {boolean}
973 */
974 matchesFilterRegex(regexObject) {
975 regexObject.lastIndex = 0;
Erik Luo5976c8c2018-07-24 02:03:09976 const contentElement = this.contentElement();
977 const anchorText = this._anchorElement ? this._anchorElement.deepTextContent() : '';
978 return (anchorText && regexObject.test(anchorText.trim())) ||
979 regexObject.test(contentElement.deepTextContent().slice(anchorText.length));
Blink Reformat4c46d092018-04-07 15:32:37980 }
981
982 /**
983 * @param {string} filter
984 * @return {boolean}
985 */
986 matchesFilterText(filter) {
987 const text = this.contentElement().deepTextContent();
988 return text.toLowerCase().includes(filter.toLowerCase());
989 }
990
991 updateTimestamp() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34992 if (!this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:37993 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34994 }
Blink Reformat4c46d092018-04-07 15:32:37995
996 if (Common.moduleSetting('consoleTimestampsEnabled').get()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34997 if (!this._timestampElement) {
Blink Reformat4c46d092018-04-07 15:32:37998 this._timestampElement = createElementWithClass('span', 'console-timestamp');
Tim van der Lippe1d6e57a2019-09-30 11:55:34999 }
Rayan Kansoaca06e72019-03-27 11:57:061000 this._timestampElement.textContent = UI.formatTimestamp(this._message.timestamp, false) + ' ';
1001 this._timestampElement.title = UI.formatTimestamp(this._message.timestamp, true);
Blink Reformat4c46d092018-04-07 15:32:371002 this._contentElement.insertBefore(this._timestampElement, this._contentElement.firstChild);
1003 } else if (this._timestampElement) {
1004 this._timestampElement.remove();
1005 delete this._timestampElement;
1006 }
Blink Reformat4c46d092018-04-07 15:32:371007 }
1008
1009 /**
1010 * @return {number}
1011 */
1012 nestingLevel() {
1013 return this._nestingLevel;
1014 }
1015
1016 /**
1017 * @param {boolean} inSimilarGroup
1018 * @param {boolean=} isLast
1019 */
1020 setInSimilarGroup(inSimilarGroup, isLast) {
1021 this._inSimilarGroup = inSimilarGroup;
1022 this._lastInSimilarGroup = inSimilarGroup && !!isLast;
1023 if (this._similarGroupMarker && !inSimilarGroup) {
1024 this._similarGroupMarker.remove();
1025 this._similarGroupMarker = null;
1026 } else if (this._element && !this._similarGroupMarker && inSimilarGroup) {
1027 this._similarGroupMarker = createElementWithClass('div', 'nesting-level-marker');
1028 this._element.insertBefore(this._similarGroupMarker, this._element.firstChild);
1029 this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
1030 }
1031 }
1032
1033 /**
1034 * @return {boolean}
1035 */
1036 isLastInSimilarGroup() {
1037 return this._inSimilarGroup && this._lastInSimilarGroup;
1038 }
1039
1040 resetCloseGroupDecorationCount() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341041 if (!this._closeGroupDecorationCount) {
Blink Reformat4c46d092018-04-07 15:32:371042 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341043 }
Blink Reformat4c46d092018-04-07 15:32:371044 this._closeGroupDecorationCount = 0;
1045 this._updateCloseGroupDecorations();
1046 }
1047
1048 incrementCloseGroupDecorationCount() {
1049 ++this._closeGroupDecorationCount;
1050 this._updateCloseGroupDecorations();
1051 }
1052
1053 _updateCloseGroupDecorations() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341054 if (!this._nestingLevelMarkers) {
Blink Reformat4c46d092018-04-07 15:32:371055 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341056 }
Blink Reformat4c46d092018-04-07 15:32:371057 for (let i = 0, n = this._nestingLevelMarkers.length; i < n; ++i) {
1058 const marker = this._nestingLevelMarkers[i];
1059 marker.classList.toggle('group-closed', n - i <= this._closeGroupDecorationCount);
1060 }
1061 }
1062
1063 /**
Erik Luo0b8282e2018-10-08 20:37:461064 * @return {number}
1065 */
1066 _focusedChildIndex() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341067 if (!this._selectableChildren.length) {
Erik Luo0b8282e2018-10-08 20:37:461068 return -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341069 }
Erik Luo383f21d2018-11-07 23:16:371070 return this._selectableChildren.findIndex(child => child.element.hasFocus());
Erik Luo0b8282e2018-10-08 20:37:461071 }
1072
1073 /**
Erik Luo8ef5d0c2018-09-25 21:16:001074 * @param {!Event} event
1075 */
1076 _onKeyDown(event) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341077 if (UI.isEditing() || !this._element.hasFocus() || this._element.hasSelection()) {
Erik Luo8ef5d0c2018-09-25 21:16:001078 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341079 }
1080 if (this.maybeHandleOnKeyDown(event)) {
Erik Luo8ef5d0c2018-09-25 21:16:001081 event.consume(true);
Tim van der Lippe1d6e57a2019-09-30 11:55:341082 }
Erik Luo8ef5d0c2018-09-25 21:16:001083 }
1084
1085 /**
1086 * @protected
1087 * @param {!Event} event
1088 */
1089 maybeHandleOnKeyDown(event) {
1090 // Handle trace expansion.
Erik Luo0b8282e2018-10-08 20:37:461091 const focusedChildIndex = this._focusedChildIndex();
1092 const isWrapperFocused = focusedChildIndex === -1;
1093 if (this._expandTrace && isWrapperFocused) {
Erik Luo8ef5d0c2018-09-25 21:16:001094 if ((event.key === 'ArrowLeft' && this._traceExpanded) || (event.key === 'ArrowRight' && !this._traceExpanded)) {
1095 this._expandTrace(!this._traceExpanded);
1096 return true;
1097 }
1098 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341099 if (!this._selectableChildren.length) {
Erik Luo0b8282e2018-10-08 20:37:461100 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:341101 }
Erik Luo0b8282e2018-10-08 20:37:461102
1103 if (event.key === 'ArrowLeft') {
1104 this._element.focus();
1105 return true;
1106 }
1107 if (event.key === 'ArrowRight') {
Tim van der Lippe1d6e57a2019-09-30 11:55:341108 if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
Erik Luo0b8282e2018-10-08 20:37:461109 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341110 }
Erik Luo0b8282e2018-10-08 20:37:461111 }
1112 if (event.key === 'ArrowUp') {
Erik Luo182bece2018-11-29 03:15:221113 const firstVisibleChild = this._nearestVisibleChild(0);
1114 if (this._selectableChildren[focusedChildIndex] === firstVisibleChild && firstVisibleChild) {
Erik Luo0b8282e2018-10-08 20:37:461115 this._element.focus();
1116 return true;
Erik Luo182bece2018-11-29 03:15:221117 } else if (this._selectNearestVisibleChild(focusedChildIndex - 1, true /* backwards */)) {
Erik Luo0b8282e2018-10-08 20:37:461118 return true;
1119 }
1120 }
1121 if (event.key === 'ArrowDown') {
Tim van der Lippe1d6e57a2019-09-30 11:55:341122 if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
Erik Luo0b8282e2018-10-08 20:37:461123 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341124 }
1125 if (!isWrapperFocused && this._selectNearestVisibleChild(focusedChildIndex + 1)) {
Erik Luo0b8282e2018-10-08 20:37:461126 return true;
Tim van der Lippe1d6e57a2019-09-30 11:55:341127 }
Erik Luo0b8282e2018-10-08 20:37:461128 }
Erik Luo8ef5d0c2018-09-25 21:16:001129 return false;
1130 }
1131
Erik Luo182bece2018-11-29 03:15:221132 /**
1133 * @param {number} fromIndex
1134 * @param {boolean=} backwards
1135 * @return {boolean}
1136 */
1137 _selectNearestVisibleChild(fromIndex, backwards) {
1138 const nearestChild = this._nearestVisibleChild(fromIndex, backwards);
1139 if (nearestChild) {
Erik Luo31c21f62018-12-13 03:39:391140 nearestChild.forceSelect();
Erik Luo182bece2018-11-29 03:15:221141 return true;
1142 }
1143 return false;
1144 }
1145
1146 /**
1147 * @param {number} fromIndex
1148 * @param {boolean=} backwards
Erik Luo31c21f62018-12-13 03:39:391149 * @return {?{element: !Element, forceSelect: function()}}
Erik Luo182bece2018-11-29 03:15:221150 */
1151 _nearestVisibleChild(fromIndex, backwards) {
1152 const childCount = this._selectableChildren.length;
Tim van der Lippe1d6e57a2019-09-30 11:55:341153 if (fromIndex < 0 || fromIndex >= childCount) {
Erik Luo182bece2018-11-29 03:15:221154 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341155 }
Erik Luo182bece2018-11-29 03:15:221156 const direction = backwards ? -1 : 1;
1157 let index = fromIndex;
1158
1159 while (!this._selectableChildren[index].element.offsetParent) {
1160 index += direction;
Tim van der Lippe1d6e57a2019-09-30 11:55:341161 if (index < 0 || index >= childCount) {
Erik Luo182bece2018-11-29 03:15:221162 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341163 }
Erik Luo182bece2018-11-29 03:15:221164 }
1165 return this._selectableChildren[index];
1166 }
1167
Erik Luo0b8282e2018-10-08 20:37:461168 focusLastChildOrSelf() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341169 if (this._element && !this._selectNearestVisibleChild(this._selectableChildren.length - 1, true /* backwards */)) {
Erik Luo0b8282e2018-10-08 20:37:461170 this._element.focus();
Tim van der Lippe1d6e57a2019-09-30 11:55:341171 }
Erik Luo0b8282e2018-10-08 20:37:461172 }
1173
1174 /**
Blink Reformat4c46d092018-04-07 15:32:371175 * @return {!Element}
1176 */
1177 contentElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341178 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371179 return this._contentElement;
Tim van der Lippe1d6e57a2019-09-30 11:55:341180 }
Blink Reformat4c46d092018-04-07 15:32:371181
1182 const contentElement = createElementWithClass('div', 'console-message');
Tim van der Lippe1d6e57a2019-09-30 11:55:341183 if (this._messageLevelIcon) {
Blink Reformat4c46d092018-04-07 15:32:371184 contentElement.appendChild(this._messageLevelIcon);
Tim van der Lippe1d6e57a2019-09-30 11:55:341185 }
Blink Reformat4c46d092018-04-07 15:32:371186 this._contentElement = contentElement;
1187
1188 let formattedMessage;
1189 const shouldIncludeTrace = !!this._message.stackTrace &&
1190 (this._message.source === SDK.ConsoleMessage.MessageSource.Network ||
1191 this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
1192 this._message.level === SDK.ConsoleMessage.MessageLevel.Error ||
1193 this._message.level === SDK.ConsoleMessage.MessageLevel.Warning ||
1194 this._message.type === SDK.ConsoleMessage.MessageType.Trace);
Tim van der Lippe1d6e57a2019-09-30 11:55:341195 if (this._message.runtimeModel() && shouldIncludeTrace) {
Blink Reformat4c46d092018-04-07 15:32:371196 formattedMessage = this._buildMessageWithStackTrace();
Tim van der Lippe1d6e57a2019-09-30 11:55:341197 } else if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
Blink Reformat4c46d092018-04-07 15:32:371198 formattedMessage = this._buildTableMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:341199 } else {
Blink Reformat4c46d092018-04-07 15:32:371200 formattedMessage = this._buildMessage();
Tim van der Lippe1d6e57a2019-09-30 11:55:341201 }
Blink Reformat4c46d092018-04-07 15:32:371202 contentElement.appendChild(formattedMessage);
1203
1204 this.updateTimestamp();
1205 return this._contentElement;
1206 }
1207
1208 /**
1209 * @return {!Element}
1210 */
1211 toMessageElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341212 if (this._element) {
Blink Reformat4c46d092018-04-07 15:32:371213 return this._element;
Tim van der Lippe1d6e57a2019-09-30 11:55:341214 }
Blink Reformat4c46d092018-04-07 15:32:371215
1216 this._element = createElement('div');
Pavel Feldmandb310912019-01-30 00:31:201217 this._element.tabIndex = -1;
1218 this._element.addEventListener('keydown', this._onKeyDown.bind(this));
Blink Reformat4c46d092018-04-07 15:32:371219 this.updateMessageElement();
1220 return this._element;
1221 }
1222
1223 updateMessageElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341224 if (!this._element) {
Blink Reformat4c46d092018-04-07 15:32:371225 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341226 }
Blink Reformat4c46d092018-04-07 15:32:371227
1228 this._element.className = 'console-message-wrapper';
1229 this._element.removeChildren();
Tim van der Lippe1d6e57a2019-09-30 11:55:341230 if (this._message.isGroupStartMessage()) {
Blink Reformat4c46d092018-04-07 15:32:371231 this._element.classList.add('console-group-title');
Tim van der Lippe1d6e57a2019-09-30 11:55:341232 }
1233 if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
Blink Reformat4c46d092018-04-07 15:32:371234 this._element.classList.add('console-from-api');
Tim van der Lippe1d6e57a2019-09-30 11:55:341235 }
Blink Reformat4c46d092018-04-07 15:32:371236 if (this._inSimilarGroup) {
1237 this._similarGroupMarker = this._element.createChild('div', 'nesting-level-marker');
1238 this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
1239 }
1240
1241 this._nestingLevelMarkers = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341242 for (let i = 0; i < this._nestingLevel; ++i) {
Blink Reformat4c46d092018-04-07 15:32:371243 this._nestingLevelMarkers.push(this._element.createChild('div', 'nesting-level-marker'));
Tim van der Lippe1d6e57a2019-09-30 11:55:341244 }
Blink Reformat4c46d092018-04-07 15:32:371245 this._updateCloseGroupDecorations();
1246 this._element.message = this;
1247
1248 switch (this._message.level) {
1249 case SDK.ConsoleMessage.MessageLevel.Verbose:
1250 this._element.classList.add('console-verbose-level');
Blink Reformat4c46d092018-04-07 15:32:371251 break;
1252 case SDK.ConsoleMessage.MessageLevel.Info:
1253 this._element.classList.add('console-info-level');
Tim van der Lippe1d6e57a2019-09-30 11:55:341254 if (this._message.type === SDK.ConsoleMessage.MessageType.System) {
Blink Reformat4c46d092018-04-07 15:32:371255 this._element.classList.add('console-system-type');
Tim van der Lippe1d6e57a2019-09-30 11:55:341256 }
Blink Reformat4c46d092018-04-07 15:32:371257 break;
1258 case SDK.ConsoleMessage.MessageLevel.Warning:
1259 this._element.classList.add('console-warning-level');
Blink Reformat4c46d092018-04-07 15:32:371260 break;
1261 case SDK.ConsoleMessage.MessageLevel.Error:
1262 this._element.classList.add('console-error-level');
Blink Reformat4c46d092018-04-07 15:32:371263 break;
1264 }
Erik Luofd3e7d42018-09-25 02:12:351265 this._updateMessageLevelIcon();
Tim van der Lippe1d6e57a2019-09-30 11:55:341266 if (this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:371267 this._element.classList.add('console-warning-level');
Tim van der Lippe1d6e57a2019-09-30 11:55:341268 }
Blink Reformat4c46d092018-04-07 15:32:371269
1270 this._element.appendChild(this.contentElement());
Tim van der Lippe1d6e57a2019-09-30 11:55:341271 if (this._repeatCount > 1) {
Blink Reformat4c46d092018-04-07 15:32:371272 this._showRepeatCountElement();
Tim van der Lippe1d6e57a2019-09-30 11:55:341273 }
Blink Reformat4c46d092018-04-07 15:32:371274 }
1275
1276 /**
1277 * @return {boolean}
1278 */
1279 _shouldRenderAsWarning() {
1280 return (this._message.level === SDK.ConsoleMessage.MessageLevel.Verbose ||
1281 this._message.level === SDK.ConsoleMessage.MessageLevel.Info) &&
1282 (this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
1283 this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation ||
1284 this._message.source === SDK.ConsoleMessage.MessageSource.Intervention ||
1285 this._message.source === SDK.ConsoleMessage.MessageSource.Recommendation);
1286 }
1287
Erik Luofd3e7d42018-09-25 02:12:351288 _updateMessageLevelIcon() {
1289 let iconType = '';
1290 let accessibleName = '';
1291 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
1292 iconType = 'smallicon-warning';
1293 accessibleName = ls`Warning`;
1294 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
1295 iconType = 'smallicon-error';
1296 accessibleName = ls`Error`;
1297 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341298 if (!iconType && !this._messageLevelIcon) {
Blink Reformat4c46d092018-04-07 15:32:371299 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341300 }
Blink Reformat4c46d092018-04-07 15:32:371301 if (iconType && !this._messageLevelIcon) {
1302 this._messageLevelIcon = UI.Icon.create('', 'message-level-icon');
Tim van der Lippe1d6e57a2019-09-30 11:55:341303 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371304 this._contentElement.insertBefore(this._messageLevelIcon, this._contentElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341305 }
Blink Reformat4c46d092018-04-07 15:32:371306 }
1307 this._messageLevelIcon.setIconType(iconType);
Erik Luofd3e7d42018-09-25 02:12:351308 UI.ARIAUtils.setAccessibleName(this._messageLevelIcon, accessibleName);
Blink Reformat4c46d092018-04-07 15:32:371309 }
1310
1311 /**
1312 * @return {number}
1313 */
1314 repeatCount() {
1315 return this._repeatCount || 1;
1316 }
1317
1318 resetIncrementRepeatCount() {
1319 this._repeatCount = 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341320 if (!this._repeatCountElement) {
Blink Reformat4c46d092018-04-07 15:32:371321 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341322 }
Blink Reformat4c46d092018-04-07 15:32:371323
1324 this._repeatCountElement.remove();
Tim van der Lippe1d6e57a2019-09-30 11:55:341325 if (this._contentElement) {
Blink Reformat4c46d092018-04-07 15:32:371326 this._contentElement.classList.remove('repeated-message');
Tim van der Lippe1d6e57a2019-09-30 11:55:341327 }
Blink Reformat4c46d092018-04-07 15:32:371328 delete this._repeatCountElement;
1329 }
1330
1331 incrementRepeatCount() {
1332 this._repeatCount++;
1333 this._showRepeatCountElement();
1334 }
1335
1336 /**
1337 * @param {number} repeatCount
1338 */
1339 setRepeatCount(repeatCount) {
1340 this._repeatCount = repeatCount;
1341 this._showRepeatCountElement();
1342 }
1343
1344 _showRepeatCountElement() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341345 if (!this._element) {
Blink Reformat4c46d092018-04-07 15:32:371346 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341347 }
Blink Reformat4c46d092018-04-07 15:32:371348
1349 if (!this._repeatCountElement) {
Joel Einbinder7fbe24c2019-01-24 05:19:011350 this._repeatCountElement = createElementWithClass('span', 'console-message-repeat-count', 'dt-small-bubble');
Blink Reformat4c46d092018-04-07 15:32:371351 switch (this._message.level) {
1352 case SDK.ConsoleMessage.MessageLevel.Warning:
1353 this._repeatCountElement.type = 'warning';
1354 break;
1355 case SDK.ConsoleMessage.MessageLevel.Error:
1356 this._repeatCountElement.type = 'error';
1357 break;
1358 case SDK.ConsoleMessage.MessageLevel.Verbose:
1359 this._repeatCountElement.type = 'verbose';
1360 break;
1361 default:
1362 this._repeatCountElement.type = 'info';
1363 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341364 if (this._shouldRenderAsWarning()) {
Blink Reformat4c46d092018-04-07 15:32:371365 this._repeatCountElement.type = 'warning';
Tim van der Lippe1d6e57a2019-09-30 11:55:341366 }
Blink Reformat4c46d092018-04-07 15:32:371367
1368 this._element.insertBefore(this._repeatCountElement, this._contentElement);
1369 this._contentElement.classList.add('repeated-message');
1370 }
1371 this._repeatCountElement.textContent = this._repeatCount;
Erik Luofd3e7d42018-09-25 02:12:351372 let accessibleName = ls`Repeat ${this._repeatCount}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341373 if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
Erik Luofd3e7d42018-09-25 02:12:351374 accessibleName = ls`Warning ${accessibleName}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341375 } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
Erik Luofd3e7d42018-09-25 02:12:351376 accessibleName = ls`Error ${accessibleName}`;
Tim van der Lippe1d6e57a2019-09-30 11:55:341377 }
Erik Luofd3e7d42018-09-25 02:12:351378 UI.ARIAUtils.setAccessibleName(this._repeatCountElement, accessibleName);
Blink Reformat4c46d092018-04-07 15:32:371379 }
1380
1381 get text() {
1382 return this._message.messageText;
1383 }
1384
1385 /**
1386 * @return {string}
1387 */
1388 toExportString() {
1389 const lines = [];
1390 const nodes = this.contentElement().childTextNodes();
1391 const messageContent = nodes.map(Components.Linkifier.untruncatedNodeText).join('');
Tim van der Lippe1d6e57a2019-09-30 11:55:341392 for (let i = 0; i < this.repeatCount(); ++i) {
Blink Reformat4c46d092018-04-07 15:32:371393 lines.push(messageContent);
Tim van der Lippe1d6e57a2019-09-30 11:55:341394 }
Blink Reformat4c46d092018-04-07 15:32:371395 return lines.join('\n');
1396 }
1397
1398 /**
1399 * @param {?RegExp} regex
1400 */
1401 setSearchRegex(regex) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341402 if (this._searchHiglightNodeChanges && this._searchHiglightNodeChanges.length) {
Blink Reformat4c46d092018-04-07 15:32:371403 UI.revertDomChanges(this._searchHiglightNodeChanges);
Tim van der Lippe1d6e57a2019-09-30 11:55:341404 }
Blink Reformat4c46d092018-04-07 15:32:371405 this._searchRegex = regex;
1406 this._searchHighlightNodes = [];
1407 this._searchHiglightNodeChanges = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341408 if (!this._searchRegex) {
Blink Reformat4c46d092018-04-07 15:32:371409 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341410 }
Blink Reformat4c46d092018-04-07 15:32:371411
1412 const text = this.contentElement().deepTextContent();
1413 let match;
1414 this._searchRegex.lastIndex = 0;
1415 const sourceRanges = [];
Tim van der Lippe1d6e57a2019-09-30 11:55:341416 while ((match = this._searchRegex.exec(text)) && match[0]) {
Blink Reformat4c46d092018-04-07 15:32:371417 sourceRanges.push(new TextUtils.SourceRange(match.index, match[0].length));
Tim van der Lippe1d6e57a2019-09-30 11:55:341418 }
Blink Reformat4c46d092018-04-07 15:32:371419
1420 if (sourceRanges.length) {
1421 this._searchHighlightNodes =
1422 UI.highlightSearchResults(this.contentElement(), sourceRanges, this._searchHiglightNodeChanges);
1423 }
1424 }
1425
1426 /**
1427 * @return {?RegExp}
1428 */
1429 searchRegex() {
1430 return this._searchRegex;
1431 }
1432
1433 /**
1434 * @return {number}
1435 */
1436 searchCount() {
1437 return this._searchHighlightNodes.length;
1438 }
1439
1440 /**
1441 * @return {!Element}
1442 */
1443 searchHighlightNode(index) {
1444 return this._searchHighlightNodes[index];
1445 }
1446
1447 /**
1448 * @param {string} string
1449 * @return {?Element}
1450 */
1451 _tryFormatAsError(string) {
1452 /**
1453 * @param {string} prefix
1454 */
1455 function startsWith(prefix) {
1456 return string.startsWith(prefix);
1457 }
1458
1459 const errorPrefixes =
1460 ['EvalError', 'ReferenceError', 'SyntaxError', 'TypeError', 'RangeError', 'Error', 'URIError'];
Tim van der Lippe1d6e57a2019-09-30 11:55:341461 if (!this._message.runtimeModel() || !errorPrefixes.some(startsWith)) {
Blink Reformat4c46d092018-04-07 15:32:371462 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341463 }
Blink Reformat4c46d092018-04-07 15:32:371464 const debuggerModel = this._message.runtimeModel().debuggerModel();
1465 const baseURL = this._message.runtimeModel().target().inspectedURL();
1466
1467 const lines = string.split('\n');
1468 const links = [];
1469 let position = 0;
1470 for (let i = 0; i < lines.length; ++i) {
1471 position += i > 0 ? lines[i - 1].length + 1 : 0;
1472 const isCallFrameLine = /^\s*at\s/.test(lines[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341473 if (!isCallFrameLine && links.length) {
Blink Reformat4c46d092018-04-07 15:32:371474 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341475 }
Blink Reformat4c46d092018-04-07 15:32:371476
Tim van der Lippe1d6e57a2019-09-30 11:55:341477 if (!isCallFrameLine) {
Blink Reformat4c46d092018-04-07 15:32:371478 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341479 }
Blink Reformat4c46d092018-04-07 15:32:371480
1481 let openBracketIndex = -1;
1482 let closeBracketIndex = -1;
Yang Guo39256bd2019-07-18 06:02:251483 const inBracketsWithLineAndColumn = /\([^\)\(]+:\d+:\d+\)/g;
1484 const inBrackets = /\([^\)\(]+\)/g;
1485 let lastMatch = null;
1486 let currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341487 while ((currentMatch = inBracketsWithLineAndColumn.exec(lines[i]))) {
Yang Guo39256bd2019-07-18 06:02:251488 lastMatch = currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341489 }
Yang Guo39256bd2019-07-18 06:02:251490 if (!lastMatch) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341491 while ((currentMatch = inBrackets.exec(lines[i]))) {
Yang Guo39256bd2019-07-18 06:02:251492 lastMatch = currentMatch;
Tim van der Lippe1d6e57a2019-09-30 11:55:341493 }
Yang Guo39256bd2019-07-18 06:02:251494 }
1495 if (lastMatch) {
1496 openBracketIndex = lastMatch.index;
1497 closeBracketIndex = lastMatch.index + lastMatch[0].length - 1;
Blink Reformat4c46d092018-04-07 15:32:371498 }
1499 const hasOpenBracket = openBracketIndex !== -1;
1500 const left = hasOpenBracket ? openBracketIndex + 1 : lines[i].indexOf('at') + 3;
1501 const right = hasOpenBracket ? closeBracketIndex : lines[i].length;
1502 const linkCandidate = lines[i].substring(left, right);
1503 const splitResult = Common.ParsedURL.splitLineAndColumn(linkCandidate);
Tim van der Lippe1d6e57a2019-09-30 11:55:341504 if (!splitResult) {
Blink Reformat4c46d092018-04-07 15:32:371505 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341506 }
Blink Reformat4c46d092018-04-07 15:32:371507
Tim van der Lippe1d6e57a2019-09-30 11:55:341508 if (splitResult.url === '<anonymous>') {
Blink Reformat4c46d092018-04-07 15:32:371509 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341510 }
Blink Reformat4c46d092018-04-07 15:32:371511 let url = parseOrScriptMatch(splitResult.url);
Tim van der Lippe1d6e57a2019-09-30 11:55:341512 if (!url && Common.ParsedURL.isRelativeURL(splitResult.url)) {
Blink Reformat4c46d092018-04-07 15:32:371513 url = parseOrScriptMatch(Common.ParsedURL.completeURL(baseURL, splitResult.url));
Tim van der Lippe1d6e57a2019-09-30 11:55:341514 }
1515 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:371516 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341517 }
Blink Reformat4c46d092018-04-07 15:32:371518
1519 links.push({
1520 url: url,
1521 positionLeft: position + left,
1522 positionRight: position + right,
1523 lineNumber: splitResult.lineNumber,
1524 columnNumber: splitResult.columnNumber
1525 });
1526 }
1527
Tim van der Lippe1d6e57a2019-09-30 11:55:341528 if (!links.length) {
Blink Reformat4c46d092018-04-07 15:32:371529 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341530 }
Blink Reformat4c46d092018-04-07 15:32:371531
1532 const formattedResult = createElement('span');
1533 let start = 0;
1534 for (let i = 0; i < links.length; ++i) {
Erik Luo383f21d2018-11-07 23:16:371535 formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start, links[i].positionLeft)));
Erik Luo182bece2018-11-29 03:15:221536 const scriptLocationLink = this._linkifier.linkifyScriptLocation(
1537 debuggerModel.target(), null, links[i].url, links[i].lineNumber, links[i].columnNumber);
1538 scriptLocationLink.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:391539 this._selectableChildren.push({element: scriptLocationLink, forceSelect: () => scriptLocationLink.focus()});
Erik Luo182bece2018-11-29 03:15:221540 formattedResult.appendChild(scriptLocationLink);
Blink Reformat4c46d092018-04-07 15:32:371541 start = links[i].positionRight;
1542 }
1543
Tim van der Lippe1d6e57a2019-09-30 11:55:341544 if (start !== string.length) {
Erik Luo383f21d2018-11-07 23:16:371545 formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start)));
Tim van der Lippe1d6e57a2019-09-30 11:55:341546 }
Blink Reformat4c46d092018-04-07 15:32:371547
1548 return formattedResult;
1549
1550 /**
1551 * @param {?string} url
1552 * @return {?string}
1553 */
1554 function parseOrScriptMatch(url) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341555 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:371556 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341557 }
Peter Marshall3e4e5692019-12-09 16:48:041558 const parsedURL = Common.ParsedURL.fromString(url);
Tim van der Lippe1d6e57a2019-09-30 11:55:341559 if (parsedURL) {
Blink Reformat4c46d092018-04-07 15:32:371560 return parsedURL.url;
Tim van der Lippe1d6e57a2019-09-30 11:55:341561 }
1562 if (debuggerModel.scriptsForSourceURL(url).length) {
Blink Reformat4c46d092018-04-07 15:32:371563 return url;
Tim van der Lippe1d6e57a2019-09-30 11:55:341564 }
Blink Reformat4c46d092018-04-07 15:32:371565 return null;
1566 }
1567 }
1568
1569 /**
1570 * @param {string} string
1571 * @param {function(string,string,number=,number=):!Node} linkifier
1572 * @return {!DocumentFragment}
1573 */
Erik Luofc2214f2018-11-21 19:54:581574 _linkifyWithCustomLinkifier(string, linkifier) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341575 if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Erik Luo5fb33bd2018-06-04 23:23:521576 return UI.createExpandableText(string, Console.ConsoleViewMessage._LongStringVisibleLength);
Tim van der Lippe1d6e57a2019-09-30 11:55:341577 }
Blink Reformat4c46d092018-04-07 15:32:371578 const container = createDocumentFragment();
Erik Luofc2214f2018-11-21 19:54:581579 const tokens = Console.ConsoleViewMessage._tokenizeMessageText(string);
Blink Reformat4c46d092018-04-07 15:32:371580 for (const token of tokens) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341581 if (!token.text) {
Erik Luofc2214f2018-11-21 19:54:581582 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341583 }
Blink Reformat4c46d092018-04-07 15:32:371584 switch (token.type) {
1585 case 'url': {
1586 const realURL = (token.text.startsWith('www.') ? 'http://' + token.text : token.text);
1587 const splitResult = Common.ParsedURL.splitLineAndColumn(realURL);
1588 let linkNode;
Tim van der Lippe1d6e57a2019-09-30 11:55:341589 if (splitResult) {
Blink Reformat4c46d092018-04-07 15:32:371590 linkNode = linkifier(token.text, splitResult.url, splitResult.lineNumber, splitResult.columnNumber);
Tim van der Lippe1d6e57a2019-09-30 11:55:341591 } else {
Blink Reformat4c46d092018-04-07 15:32:371592 linkNode = linkifier(token.text, token.value);
Tim van der Lippe1d6e57a2019-09-30 11:55:341593 }
Blink Reformat4c46d092018-04-07 15:32:371594 container.appendChild(linkNode);
1595 break;
1596 }
1597 default:
1598 container.appendChild(createTextNode(token.text));
1599 break;
1600 }
1601 }
1602 return container;
1603 }
1604
1605 /**
Blink Reformat4c46d092018-04-07 15:32:371606 * @param {string} string
1607 * @return {!DocumentFragment}
1608 */
Erik Luo383f21d2018-11-07 23:16:371609 _linkifyStringAsFragment(string) {
Erik Luofc2214f2018-11-21 19:54:581610 return this._linkifyWithCustomLinkifier(string, (text, url, lineNumber, columnNumber) => {
Erik Luo383f21d2018-11-07 23:16:371611 const linkElement = Components.Linkifier.linkifyURL(url, {text, lineNumber, columnNumber});
1612 linkElement.tabIndex = -1;
Erik Luo31c21f62018-12-13 03:39:391613 this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
Erik Luo383f21d2018-11-07 23:16:371614 return linkElement;
Blink Reformat4c46d092018-04-07 15:32:371615 });
1616 }
1617
1618 /**
1619 * @param {string} string
1620 * @return {!Array<{type: string, text: (string|undefined)}>}
1621 */
1622 static _tokenizeMessageText(string) {
1623 if (!Console.ConsoleViewMessage._tokenizerRegexes) {
1624 const controlCodes = '\\u0000-\\u0020\\u007f-\\u009f';
1625 const linkStringRegex = new RegExp(
1626 '(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|data:|www\\.)[^\\s' + controlCodes + '"]{2,}[^\\s' + controlCodes +
1627 '"\')}\\],:;.!?]',
1628 'u');
1629 const pathLineRegex = /(?:\/[\w\.-]*)+\:[\d]+/;
1630 const timeRegex = /took [\d]+ms/;
1631 const eventRegex = /'\w+' event/;
1632 const milestoneRegex = /\sM[6-7]\d/;
1633 const autofillRegex = /\(suggested: \"[\w-]+\"\)/;
1634 const handlers = new Map();
1635 handlers.set(linkStringRegex, 'url');
1636 handlers.set(pathLineRegex, 'url');
1637 handlers.set(timeRegex, 'time');
1638 handlers.set(eventRegex, 'event');
1639 handlers.set(milestoneRegex, 'milestone');
1640 handlers.set(autofillRegex, 'autofill');
1641 Console.ConsoleViewMessage._tokenizerRegexes = Array.from(handlers.keys());
1642 Console.ConsoleViewMessage._tokenizerTypes = Array.from(handlers.values());
1643 }
Tim van der Lippe1d6e57a2019-09-30 11:55:341644 if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
Blink Reformat4c46d092018-04-07 15:32:371645 return [{text: string, type: undefined}];
Tim van der Lippe1d6e57a2019-09-30 11:55:341646 }
Blink Reformat4c46d092018-04-07 15:32:371647 const results = TextUtils.TextUtils.splitStringByRegexes(string, Console.ConsoleViewMessage._tokenizerRegexes);
1648 return results.map(
1649 result => ({text: result.value, type: Console.ConsoleViewMessage._tokenizerTypes[result.regexIndex]}));
1650 }
1651
1652 /**
1653 * @return {string}
1654 */
1655 groupKey() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341656 if (!this._groupKey) {
Blink Reformat4c46d092018-04-07 15:32:371657 this._groupKey = this._message.groupCategoryKey() + ':' + this.groupTitle();
Tim van der Lippe1d6e57a2019-09-30 11:55:341658 }
Blink Reformat4c46d092018-04-07 15:32:371659 return this._groupKey;
1660 }
1661
1662 /**
1663 * @return {string}
1664 */
1665 groupTitle() {
1666 const tokens = Console.ConsoleViewMessage._tokenizeMessageText(this._message.messageText);
1667 const result = tokens.reduce((acc, token) => {
1668 let text = token.text;
Tim van der Lippe1d6e57a2019-09-30 11:55:341669 if (token.type === 'url') {
Blink Reformat4c46d092018-04-07 15:32:371670 text = Common.UIString('<URL>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341671 } else if (token.type === 'time') {
Blink Reformat4c46d092018-04-07 15:32:371672 text = Common.UIString('took <N>ms');
Tim van der Lippe1d6e57a2019-09-30 11:55:341673 } else if (token.type === 'event') {
Blink Reformat4c46d092018-04-07 15:32:371674 text = Common.UIString('<some> event');
Tim van der Lippe1d6e57a2019-09-30 11:55:341675 } else if (token.type === 'milestone') {
Blink Reformat4c46d092018-04-07 15:32:371676 text = Common.UIString(' M<XX>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341677 } else if (token.type === 'autofill') {
Blink Reformat4c46d092018-04-07 15:32:371678 text = Common.UIString('<attribute>');
Tim van der Lippe1d6e57a2019-09-30 11:55:341679 }
Blink Reformat4c46d092018-04-07 15:32:371680 return acc + text;
1681 }, '');
1682 return result.replace(/[%]o/g, '');
1683 }
Paul Lewisbf7aa3c2019-11-20 17:03:381684}
Blink Reformat4c46d092018-04-07 15:32:371685
1686/**
1687 * @unrestricted
1688 */
Paul Lewisbf7aa3c2019-11-20 17:03:381689export class ConsoleGroupViewMessage extends ConsoleViewMessage {
Blink Reformat4c46d092018-04-07 15:32:371690 /**
1691 * @param {!SDK.ConsoleMessage} consoleMessage
1692 * @param {!Components.Linkifier} linkifier
Blink Reformat4c46d092018-04-07 15:32:371693 * @param {number} nestingLevel
Erik Luo8ef5d0c2018-09-25 21:16:001694 * @param {function()} onToggle
Erik Luo840be6b2018-12-03 20:54:271695 * @param {function(!Common.Event)} onResize
Blink Reformat4c46d092018-04-07 15:32:371696 */
Tim van der Lippeb45d9a02019-11-05 17:24:411697 constructor(consoleMessage, linkifier, nestingLevel, onToggle, onResize) {
Blink Reformat4c46d092018-04-07 15:32:371698 console.assert(consoleMessage.isGroupStartMessage());
Tim van der Lippeb45d9a02019-11-05 17:24:411699 super(consoleMessage, linkifier, nestingLevel, onResize);
Blink Reformat4c46d092018-04-07 15:32:371700 this._collapsed = consoleMessage.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed;
1701 /** @type {?UI.Icon} */
1702 this._expandGroupIcon = null;
Erik Luo8ef5d0c2018-09-25 21:16:001703 this._onToggle = onToggle;
Blink Reformat4c46d092018-04-07 15:32:371704 }
1705
1706 /**
1707 * @param {boolean} collapsed
1708 */
Erik Luo8ef5d0c2018-09-25 21:16:001709 _setCollapsed(collapsed) {
Blink Reformat4c46d092018-04-07 15:32:371710 this._collapsed = collapsed;
Tim van der Lippe1d6e57a2019-09-30 11:55:341711 if (this._expandGroupIcon) {
Blink Reformat4c46d092018-04-07 15:32:371712 this._expandGroupIcon.setIconType(this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down');
Tim van der Lippe1d6e57a2019-09-30 11:55:341713 }
Erik Luo8ef5d0c2018-09-25 21:16:001714 this._onToggle.call(null);
Blink Reformat4c46d092018-04-07 15:32:371715 }
1716
1717 /**
1718 * @return {boolean}
1719 */
1720 collapsed() {
1721 return this._collapsed;
1722 }
1723
1724 /**
1725 * @override
Erik Luo8ef5d0c2018-09-25 21:16:001726 * @param {!Event} event
1727 */
1728 maybeHandleOnKeyDown(event) {
Erik Luo0b8282e2018-10-08 20:37:461729 const focusedChildIndex = this._focusedChildIndex();
1730 if (focusedChildIndex === -1) {
1731 if ((event.key === 'ArrowLeft' && !this._collapsed) || (event.key === 'ArrowRight' && this._collapsed)) {
1732 this._setCollapsed(!this._collapsed);
1733 return true;
1734 }
Erik Luo8ef5d0c2018-09-25 21:16:001735 }
1736 return super.maybeHandleOnKeyDown(event);
1737 }
1738
1739 /**
1740 * @override
Blink Reformat4c46d092018-04-07 15:32:371741 * @return {!Element}
1742 */
1743 toMessageElement() {
1744 if (!this._element) {
1745 super.toMessageElement();
Erik Luo8ef5d0c2018-09-25 21:16:001746 const iconType = this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down';
1747 this._expandGroupIcon = UI.Icon.create(iconType, 'expand-group-icon');
Erik Luob5bfff42018-09-20 02:52:391748 // Intercept focus to avoid highlight on click.
1749 this._contentElement.tabIndex = -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341750 if (this._repeatCountElement) {
Blink Reformat4c46d092018-04-07 15:32:371751 this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341752 } else {
Blink Reformat4c46d092018-04-07 15:32:371753 this._element.insertBefore(this._expandGroupIcon, this._contentElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:341754 }
Erik Luo8ef5d0c2018-09-25 21:16:001755 this._element.addEventListener('click', () => this._setCollapsed(!this._collapsed));
Blink Reformat4c46d092018-04-07 15:32:371756 }
1757 return this._element;
1758 }
1759
1760 /**
1761 * @override
1762 */
1763 _showRepeatCountElement() {
1764 super._showRepeatCountElement();
Tim van der Lippe1d6e57a2019-09-30 11:55:341765 if (this._repeatCountElement && this._expandGroupIcon) {
Blink Reformat4c46d092018-04-07 15:32:371766 this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
Tim van der Lippe1d6e57a2019-09-30 11:55:341767 }
Blink Reformat4c46d092018-04-07 15:32:371768 }
Paul Lewisbf7aa3c2019-11-20 17:03:381769}
Blink Reformat4c46d092018-04-07 15:32:371770
1771/**
1772 * @const
1773 * @type {number}
1774 */
Paul Lewisbf7aa3c2019-11-20 17:03:381775export const MaxLengthForLinks = 40;
Blink Reformat4c46d092018-04-07 15:32:371776
Paul Lewisbf7aa3c2019-11-20 17:03:381777export const _MaxTokenizableStringLength = 10000;
1778export const _LongStringVisibleLength = 5000;
Blink Reformat4c46d092018-04-07 15:32:371779
Paul Lewisbf7aa3c2019-11-20 17:03:381780/* Legacy exported object */
1781self.Console = self.Console || {};
1782
1783/* Legacy exported object */
1784Console = Console || {};
1785
1786/**
1787 * @implements {Console.ConsoleViewportElement}
1788 * @unrestricted
1789 * @constructor
1790 */
1791Console.ConsoleViewMessage = ConsoleViewMessage;
1792
1793/**
1794 * @constructor
1795 */
1796Console.ConsoleGroupViewMessage = ConsoleGroupViewMessage;
1797
1798/**
1799 * @const
1800 * @type {number}
1801 */
1802Console.ConsoleViewMessage.MaxLengthForLinks = MaxLengthForLinks;
1803Console.ConsoleViewMessage._MaxTokenizableStringLength = _MaxTokenizableStringLength;
1804Console.ConsoleViewMessage._LongStringVisibleLength = _LongStringVisibleLength;