Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(731)

Side by Side Diff: Source/devtools/front_end/ConsoleMessage.js

Issue 143263003: DevTools: Fix console.log for arrays in some corner cases. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/inspector/InjectedScriptSource.js ('k') | Source/devtools/front_end/utilities.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2009 Joseph Pecoraro 4 * Copyright (C) 2009 Joseph Pecoraro
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 9 *
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 * @param {!Element} elem 356 * @param {!Element} elem
357 * @param {boolean} includePreview 357 * @param {boolean} includePreview
358 */ 358 */
359 _formatParameterAsArrayOrObject: function(obj, description, elem, includePre view) 359 _formatParameterAsArrayOrObject: function(obj, description, elem, includePre view)
360 { 360 {
361 var titleElement = document.createElement("span"); 361 var titleElement = document.createElement("span");
362 if (description) 362 if (description)
363 titleElement.createTextChild(description); 363 titleElement.createTextChild(description);
364 if (includePreview && obj.preview) { 364 if (includePreview && obj.preview) {
365 titleElement.classList.add("console-object-preview"); 365 titleElement.classList.add("console-object-preview");
366 var lossless = this._appendObjectPreview(obj, description, titleElem ent); 366 if (description)
367 titleElement.createTextChild(" ");
368 var lossless = this._appendObjectPreview(obj, titleElement);
367 if (lossless) { 369 if (lossless) {
368 elem.appendChild(titleElement); 370 elem.appendChild(titleElement);
369 return; 371 return;
370 } 372 }
371 } 373 }
372 var section = new WebInspector.ObjectPropertiesSection(obj, titleElement ); 374 var section = new WebInspector.ObjectPropertiesSection(obj, titleElement );
373 section.enableContextMenu(); 375 section.enableContextMenu();
374 elem.appendChild(section.element); 376 elem.appendChild(section.element);
375 377
376 var note = section.titleElement.createChild("span", "object-info-state-n ote"); 378 var note = section.titleElement.createChild("span", "object-info-state-n ote");
377 note.title = WebInspector.UIString("Object state below is captured upon first expansion"); 379 note.title = WebInspector.UIString("Object state below is captured upon first expansion");
378 }, 380 },
379 381
380 /** 382 /**
381 * @param {!WebInspector.RemoteObject} obj 383 * @param {!WebInspector.RemoteObject} obj
382 * @param {string} description
383 * @param {!Element} titleElement 384 * @param {!Element} titleElement
384 * @return {boolean} true iff preview captured all information. 385 * @return {boolean} true iff preview captured all information.
385 */ 386 */
386 _appendObjectPreview: function(obj, description, titleElement) 387 _appendObjectPreview: function(obj, titleElement)
387 { 388 {
388 var preview = obj.preview; 389 var preview = obj.preview;
389 var isArray = obj.subtype === "array"; 390 var isArray = obj.subtype === "array";
391 var arrayLength = isArray ? obj.arrayLength() : undefined;
392 var properties = preview.properties;
390 393
391 if (description) 394 var elements = [];
392 titleElement.createTextChild(" "); 395 for (var i = 0; i < properties.length; ++i) {
393 titleElement.createTextChild(isArray ? "[" : "{"); 396 var property = properties[i];
394 for (var i = 0; i < preview.properties.length; ++i) { 397 var name = property.name;
395 if (i > 0) 398 elements.push({
396 titleElement.createTextChild(", "); 399 name: name,
400 element: this._renderPropertyPreviewOrAccessor(obj, [property])
401 });
402 }
397 403
398 var property = preview.properties[i]; 404 this._appendArrayOrObjectPropertyElements(titleElement, elements, previe w.overflow, arrayLength);
399 var name = property.name;
400 if (!isArray || name != i) {
401 if (/^\s|\s$|^$|\n/.test(name))
402 name = "\"" + name.replace(/\n/g, "\u21B5") + "\"";
403 titleElement.createChild("span", "name").textContent = name;
404 titleElement.createTextChild(": ");
405 }
406
407 titleElement.appendChild(this._renderPropertyPreviewOrAccessor(obj, [property]));
408 }
409 if (preview.overflow)
410 titleElement.createChild("span").textContent = "\u2026";
411 titleElement.createTextChild(isArray ? "]" : "}");
412 return preview.lossless; 405 return preview.lossless;
413 }, 406 },
414 407
415 /** 408 /**
409 * @param {!Element} parent
410 * @param {!Array.<{name: string, element: !Element}>} propertyElements
411 * @param {boolean} overflow
412 * @param {number=} arrayLength
413 */
414 _appendArrayOrObjectPropertyElements: function(parent, propertyElements, ove rflow, arrayLength)
415 {
416 const maxFlatArrayLength = 100;
417
418 /**
419 * @param {{name: string, element: !Element}} a
420 * @param {{name: string, element: !Element}} b
421 * @return {number}
422 */
423 function comparator(a, b)
424 {
425 var isIndex1 = String.isArrayIndexPropertyName(a.name, arrayLength);
426 var isIndex2 = String.isArrayIndexPropertyName(b.name, arrayLength);
427 if (isIndex1 && isIndex2)
428 return Number(a.name) - Number(b.name);
429 if (isIndex1)
430 return -1;
431 if (isIndex2)
432 return 1;
433 return 0;
434 }
435
436 var isArray = typeof arrayLength === "number";
437 if (isArray)
438 propertyElements.stableSort(comparator);
439 var isFlatArray = isArray && (arrayLength <= maxFlatArrayLength);
440
441 parent.createTextChild(isArray ? "[" : "{");
442 var firstElement = true;
443 var lastNonEmptyArrayIndex = -1;
444
445 function appendCommaIfNeeded()
446 {
447 if (firstElement)
448 firstElement = false;
449 else
450 parent.createTextChild(", ");
451 }
452
453 /**
454 * @param {number=} index
455 */
456 function appendUndefinedArrayElements(index)
457 {
458 if (typeof index !== "number")
459 return;
460 var undefinedRange = index - lastNonEmptyArrayIndex - 1;
461 lastNonEmptyArrayIndex = index;
462 if (undefinedRange < 1)
463 return;
464 appendCommaIfNeeded();
465 var span = parent.createChild("span", "console-formatted-undefined") ;
466 span.textContent = WebInspector.UIString("undefined × %d", undefined Range);
467 }
468
469 /**
470 * @param {string} name
471 */
472 function appendPropertyName(name)
473 {
474 if (/^\s|\s$|^$|\n/.test(name))
475 name = "\"" + name.replace(/\n/g, "\u21B5") + "\"";
476 parent.createChild("span", "name").textContent = name;
477 parent.createTextChild(": ");
478 }
479
480 for (var i = 0, n = propertyElements.length; i < n; ++i) {
481 var name = propertyElements[i].name;
482 var element = propertyElements[i].element;
483 var isIndex = String.isArrayIndexPropertyName(name, arrayLength);
484 var index = isIndex ? Number(name) : 0;
485
486 if (isFlatArray) {
487 appendUndefinedArrayElements(isIndex ? index : arrayLength);
488 appendCommaIfNeeded();
489 if (!isIndex)
490 appendPropertyName(name);
491 } else {
492 appendCommaIfNeeded();
493 if (!isArray || !isIndex || index !== i)
494 appendPropertyName(name);
495 }
496
497 parent.appendChild(element);
498 }
499 if (isFlatArray)
500 appendUndefinedArrayElements(arrayLength);
501
502 if (overflow)
503 parent.createChild("span").textContent = "\u2026";
504 parent.createTextChild(isArray ? "]" : "}");
505 },
506
507 /**
416 * @param {!WebInspector.RemoteObject} object 508 * @param {!WebInspector.RemoteObject} object
417 * @param {!Array.<!RuntimeAgent.PropertyPreview>} propertyPath 509 * @param {!Array.<!RuntimeAgent.PropertyPreview>} propertyPath
418 * @return {!Element} 510 * @return {!Element}
419 */ 511 */
420 _renderPropertyPreviewOrAccessor: function(object, propertyPath) 512 _renderPropertyPreviewOrAccessor: function(object, propertyPath)
421 { 513 {
422 var property = propertyPath.peekLast(); 514 var property = propertyPath.peekLast();
423 if (property.type === "accessor") 515 if (property.type === "accessor")
424 return this._formatAsAccessorProperty(object, propertyPath.select("n ame"), false); 516 return this._formatAsAccessorProperty(object, propertyPath.select("n ame"), false);
425 return this._renderPropertyPreview(property.type, /** @type {string} */ (property.subtype), property.value); 517 return this._renderPropertyPreview(property.type, /** @type {string} */ (property.subtype), property.value);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 { 595 {
504 if (this.useArrayPreviewInFormatter(array)) { 596 if (this.useArrayPreviewInFormatter(array)) {
505 this._formatParameterAsArrayOrObject(array, "", elem, true); 597 this._formatParameterAsArrayOrObject(array, "", elem, true);
506 return; 598 return;
507 } 599 }
508 600
509 const maxFlatArrayLength = 100; 601 const maxFlatArrayLength = 100;
510 if (this._isOutdated || array.arrayLength() > maxFlatArrayLength) 602 if (this._isOutdated || array.arrayLength() > maxFlatArrayLength)
511 this._formatParameterAsObject(array, elem, false); 603 this._formatParameterAsObject(array, elem, false);
512 else 604 else
513 array.getOwnProperties(this._printArray.bind(this, array, elem)); 605 array.getAllProperties(false, this._printArray.bind(this, array, ele m));
514 }, 606 },
515 607
516 /** 608 /**
517 * @param {!Array.<!WebInspector.RemoteObject>} parameters 609 * @param {!Array.<!WebInspector.RemoteObject>} parameters
518 * @return {!Element} 610 * @return {!Element}
519 */ 611 */
520 _formatParameterAsTable: function(parameters) 612 _formatParameterAsTable: function(parameters)
521 { 613 {
522 var element = document.createElement("span"); 614 var element = document.createElement("span");
523 var table = parameters[0]; 615 var table = parameters[0];
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 elem.appendChild(document.createTextNode("\"")); 678 elem.appendChild(document.createTextNode("\""));
587 }, 679 },
588 680
589 /** 681 /**
590 * @param {!WebInspector.RemoteObject} array 682 * @param {!WebInspector.RemoteObject} array
591 * @param {!Element} elem 683 * @param {!Element} elem
592 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties 684 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties
593 */ 685 */
594 _printArray: function(array, elem, properties) 686 _printArray: function(array, elem, properties)
595 { 687 {
596 if (!properties) 688 if (!properties) {
689 // Fall back to object formatting.
690 this._formatParameterAsObject(array, elem, false);
597 return; 691 return;
692 }
693 const maxNonIndexElements = 5;
694 var arrayLength = array.arrayLength();
598 695
599 var elements = []; 696 var elements = [];
697 var nonIndexElements = 0;
600 for (var i = 0; i < properties.length; ++i) { 698 for (var i = 0; i < properties.length; ++i) {
601 var property = properties[i]; 699 var property = properties[i];
602 var name = property.name; 700 var name = property.name;
603 if (isNaN(name)) 701 if (!String.isArrayIndexPropertyName(name, arrayLength)) {
604 continue; 702 if (name === "length" || !property.enumerable)
703 continue;
704 if (++nonIndexElements > maxNonIndexElements)
705 continue;
706 }
707 var element = null;
605 if (property.getter) 708 if (property.getter)
606 elements[name] = this._formatAsAccessorProperty(array, [name], t rue); 709 element = this._formatAsAccessorProperty(array, [name], true);
607 else if (property.value) 710 else if (property.value)
608 elements[name] = this._formatAsArrayEntry(property.value); 711 element = this._formatAsArrayEntry(property.value);
712 if (element)
713 elements.push({ name: name, element: element });
609 } 714 }
610 715
611 elem.appendChild(document.createTextNode("[")); 716 var overflow = (nonIndexElements > maxNonIndexElements);
612 var lastNonEmptyIndex = -1; 717 this._appendArrayOrObjectPropertyElements(elem, elements, overflow, arra yLength);
613
614 function appendUndefined(elem, index)
615 {
616 if (index - lastNonEmptyIndex <= 1)
617 return;
618 var span = elem.createChild("span", "console-formatted-undefined");
619 span.textContent = WebInspector.UIString("undefined × %d", index - l astNonEmptyIndex - 1);
620 }
621
622 var length = array.arrayLength();
623 for (var i = 0; i < length; ++i) {
624 var element = elements[i];
625 if (!element)
626 continue;
627
628 if (i - lastNonEmptyIndex > 1) {
629 appendUndefined(elem, i);
630 elem.appendChild(document.createTextNode(", "));
631 }
632
633 elem.appendChild(element);
634 lastNonEmptyIndex = i;
635 if (i < length - 1)
636 elem.appendChild(document.createTextNode(", "));
637 }
638 appendUndefined(elem, length);
639
640 elem.appendChild(document.createTextNode("]"));
641 }, 718 },
642 719
643 /** 720 /**
644 * @param {!WebInspector.RemoteObject} output 721 * @param {!WebInspector.RemoteObject} output
645 * @return {!Element} 722 * @return {!Element}
646 */ 723 */
647 _formatAsArrayEntry: function(output) 724 _formatAsArrayEntry: function(output)
648 { 725 {
649 // Prevent infinite expansion of cross-referencing arrays. 726 // Prevent infinite expansion of cross-referencing arrays.
650 return this._formatParameter(output, output.subtype === "array", false); 727 return this._formatParameter(output, output.subtype === "array", false);
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
1082 /** 1159 /**
1083 * @return {!WebInspector.ConsoleMessage} 1160 * @return {!WebInspector.ConsoleMessage}
1084 */ 1161 */
1085 clone: function() 1162 clone: function()
1086 { 1163 {
1087 return WebInspector.ConsoleMessage.create(this.source, this.level, this. _messageText, this.type, this.url, this.line, this.column, this.repeatCount, thi s._parameters, this._stackTrace, this._request ? this._request.requestId : undef ined, this._isOutdated); 1164 return WebInspector.ConsoleMessage.create(this.source, this.level, this. _messageText, this.type, this.url, this.line, this.column, this.repeatCount, thi s._parameters, this._stackTrace, this._request ? this._request.requestId : undef ined, this._isOutdated);
1088 }, 1165 },
1089 1166
1090 __proto__: WebInspector.ConsoleMessage.prototype 1167 __proto__: WebInspector.ConsoleMessage.prototype
1091 } 1168 }
OLDNEW
« no previous file with comments | « Source/core/inspector/InjectedScriptSource.js ('k') | Source/devtools/front_end/utilities.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698