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

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
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)
pfeldman 2014/01/23 16:19:02 This only runs for preview, right? Could you name
aandrey 2014/01/24 06:22:04 not only for preview: from _printArray also.
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);
pfeldman 2014/01/23 16:19:02 Why sorting properties? They should come in sorted
aandrey 2014/01/24 06:22:04 They are sorted according to the index in the prot
439 var isFlatArray = isArray && (arrayLength <= maxFlatArrayLength);
pfeldman 2014/01/23 16:19:02 So we only render as flat when < 100 actual values
aandrey 2014/01/24 06:22:04 Yes. This has been the case up to now - I didn't c
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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 { 597 {
506 if (this.useArrayPreviewInFormatter(array)) { 598 if (this.useArrayPreviewInFormatter(array)) {
507 this._formatParameterAsArrayOrObject(array, "", elem, true); 599 this._formatParameterAsArrayOrObject(array, "", elem, true);
508 return; 600 return;
509 } 601 }
510 602
511 const maxFlatArrayLength = 100; 603 const maxFlatArrayLength = 100;
512 if (this._isOutdated || array.arrayLength() > maxFlatArrayLength) 604 if (this._isOutdated || array.arrayLength() > maxFlatArrayLength)
513 this._formatParameterAsObject(array, elem, false); 605 this._formatParameterAsObject(array, elem, false);
514 else 606 else
515 array.getOwnProperties(this._printArray.bind(this, array, elem)); 607 array.getAllProperties(false, this._printArray.bind(this, array, ele m));
516 }, 608 },
517 609
518 /** 610 /**
519 * @param {!Array.<!WebInspector.RemoteObject>} parameters 611 * @param {!Array.<!WebInspector.RemoteObject>} parameters
520 * @return {!Element} 612 * @return {!Element}
521 */ 613 */
522 _formatParameterAsTable: function(parameters) 614 _formatParameterAsTable: function(parameters)
523 { 615 {
524 var element = document.createElement("span"); 616 var element = document.createElement("span");
525 var table = parameters[0]; 617 var table = parameters[0];
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 elem.appendChild(document.createTextNode("\"")); 680 elem.appendChild(document.createTextNode("\""));
589 }, 681 },
590 682
591 /** 683 /**
592 * @param {!WebInspector.RemoteObject} array 684 * @param {!WebInspector.RemoteObject} array
593 * @param {!Element} elem 685 * @param {!Element} elem
594 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties 686 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties
595 */ 687 */
596 _printArray: function(array, elem, properties) 688 _printArray: function(array, elem, properties)
597 { 689 {
598 if (!properties) 690 if (!properties) {
691 // Fall back to object formatting.
692 this._formatParameterAsObject(array, elem, false);
599 return; 693 return;
694 }
695 const maxNonIndexElements = 5;
696 var arrayLength = array.arrayLength();
600 697
601 var elements = []; 698 var elements = [];
699 var nonIndexElements = 0;
602 for (var i = 0; i < properties.length; ++i) { 700 for (var i = 0; i < properties.length; ++i) {
603 var property = properties[i]; 701 var property = properties[i];
604 var name = property.name; 702 var name = property.name;
605 if (isNaN(name)) 703 if (!String.isArrayIndexPropertyName(name, arrayLength)) {
606 continue; 704 if (name === "length" || !property.enumerable)
705 continue;
706 if (++nonIndexElements > maxNonIndexElements)
707 continue;
708 }
709 var element = null;
607 if (property.getter) 710 if (property.getter)
608 elements[name] = this._formatAsAccessorProperty(array, [name], t rue); 711 element = this._formatAsAccessorProperty(array, [name], true);
609 else if (property.value) 712 else if (property.value)
610 elements[name] = this._formatAsArrayEntry(property.value); 713 element = this._formatAsArrayEntry(property.value);
714 if (element)
715 elements.push({ name: name, element: element });
611 } 716 }
612 717
613 elem.appendChild(document.createTextNode("[")); 718 var overflow = (nonIndexElements > maxNonIndexElements);
614 var lastNonEmptyIndex = -1; 719 this._appendArrayOrObjectPropertyElements(elem, elements, overflow, arra yLength);
615
616 function appendUndefined(elem, index)
617 {
618 if (index - lastNonEmptyIndex <= 1)
619 return;
620 var span = elem.createChild("span", "console-formatted-undefined");
621 span.textContent = WebInspector.UIString("undefined × %d", index - l astNonEmptyIndex - 1);
622 }
623
624 var length = array.arrayLength();
625 for (var i = 0; i < length; ++i) {
626 var element = elements[i];
627 if (!element)
628 continue;
629
630 if (i - lastNonEmptyIndex > 1) {
631 appendUndefined(elem, i);
632 elem.appendChild(document.createTextNode(", "));
633 }
634
635 elem.appendChild(element);
636 lastNonEmptyIndex = i;
637 if (i < length - 1)
638 elem.appendChild(document.createTextNode(", "));
639 }
640 appendUndefined(elem, length);
641
642 elem.appendChild(document.createTextNode("]"));
643 }, 720 },
644 721
645 /** 722 /**
646 * @param {!WebInspector.RemoteObject} output 723 * @param {!WebInspector.RemoteObject} output
647 * @return {!Element} 724 * @return {!Element}
648 */ 725 */
649 _formatAsArrayEntry: function(output) 726 _formatAsArrayEntry: function(output)
650 { 727 {
651 // Prevent infinite expansion of cross-referencing arrays. 728 // Prevent infinite expansion of cross-referencing arrays.
652 return this._formatParameter(output, output.subtype === "array", false); 729 return this._formatParameter(output, output.subtype === "array", false);
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 /** 1161 /**
1085 * @return {!WebInspector.ConsoleMessage} 1162 * @return {!WebInspector.ConsoleMessage}
1086 */ 1163 */
1087 clone: function() 1164 clone: function()
1088 { 1165 {
1089 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); 1166 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);
1090 }, 1167 },
1091 1168
1092 __proto__: WebInspector.ConsoleMessage.prototype 1169 __proto__: WebInspector.ConsoleMessage.prototype
1093 } 1170 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698