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

Side by Side Diff: chrome/browser/resources/md_downloads/crisper.js

Issue 2324293002: Roll performance-oriented iron-list changes (Closed)
Patch Set: test fix courtesy of michaelpg@ Created 4 years, 3 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
« no previous file with comments | « no previous file | chrome/browser/resources/md_history/app.crisper.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 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 function assert(condition, opt_message) { 4 function assert(condition, opt_message) {
5 if (!condition) { 5 if (!condition) {
6 var message = 'Assertion failed'; 6 var message = 'Assertion failed';
7 if (opt_message) message = message + ': ' + opt_message; 7 if (opt_message) message = message + ': ' + opt_message;
8 var error = new Error(message); 8 var error = new Error(message);
9 var global = function() { 9 var global = function() {
10 return this; 10 return this;
(...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 726
727 function elide(original, maxLength) { 727 function elide(original, maxLength) {
728 if (original.length <= maxLength) return original; 728 if (original.length <= maxLength) return original;
729 return original.substring(0, maxLength - 1) + '…'; 729 return original.substring(0, maxLength - 1) + '…';
730 } 730 }
731 731
732 function quoteString(str) { 732 function quoteString(str) {
733 return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1'); 733 return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1');
734 } 734 }
735 735
736 function listenOnce(target, eventNames, callback) {
737 if (!Array.isArray(eventNames)) eventNames = eventNames.split(/ +/);
738 var removeAllAndCallCallback = function(event) {
739 eventNames.forEach(function(eventName) {
740 target.removeEventListener(eventName, removeAllAndCallCallback, false);
741 });
742 return callback(event);
743 };
744 eventNames.forEach(function(eventName) {
745 target.addEventListener(eventName, removeAllAndCallCallback, false);
746 });
747 }
748
736 // <if expr="is_ios"> 749 // <if expr="is_ios">
737 if (!('key' in KeyboardEvent.prototype)) { 750 if (!('key' in KeyboardEvent.prototype)) {
738 Object.defineProperty(KeyboardEvent.prototype, 'key', { 751 Object.defineProperty(KeyboardEvent.prototype, 'key', {
739 get: function() { 752 get: function() {
740 if (this.keyCode >= 48 && this.keyCode <= 57) return String.fromCharCode(t his.keyCode); 753 if (this.keyCode >= 48 && this.keyCode <= 57) return String.fromCharCode(t his.keyCode);
741 if (this.keyCode >= 65 && this.keyCode <= 90) { 754 if (this.keyCode >= 65 && this.keyCode <= 90) {
742 var result = String.fromCharCode(this.keyCode).toLowerCase(); 755 var result = String.fromCharCode(this.keyCode).toLowerCase();
743 if (this.shiftKey) result = result.toUpperCase(); 756 if (this.shiftKey) result = result.toUpperCase();
744 return result; 757 return result;
745 } 758 }
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 _physicalIndexForKey: null, 1409 _physicalIndexForKey: null,
1397 _estScrollHeight: 0, 1410 _estScrollHeight: 0,
1398 _scrollHeight: 0, 1411 _scrollHeight: 0,
1399 _viewportHeight: 0, 1412 _viewportHeight: 0,
1400 _viewportWidth: 0, 1413 _viewportWidth: 0,
1401 _physicalItems: null, 1414 _physicalItems: null,
1402 _physicalSizes: null, 1415 _physicalSizes: null,
1403 _firstVisibleIndexVal: null, 1416 _firstVisibleIndexVal: null,
1404 _lastVisibleIndexVal: null, 1417 _lastVisibleIndexVal: null,
1405 _collection: null, 1418 _collection: null,
1406 _itemsRendered: false,
1407 _lastPage: null,
1408 _maxPages: 3, 1419 _maxPages: 3,
1409 _focusedItem: null, 1420 _focusedItem: null,
1410 _focusedIndex: -1, 1421 _focusedIndex: -1,
1411 _offscreenFocusedItem: null, 1422 _offscreenFocusedItem: null,
1412 _focusBackfillItem: null, 1423 _focusBackfillItem: null,
1413 _itemsPerRow: 1, 1424 _itemsPerRow: 1,
1414 _itemWidth: 0, 1425 _itemWidth: 0,
1415 _rowHeight: 0, 1426 _rowHeight: 0,
1427 _templateCost: 0,
1416 get _physicalBottom() { 1428 get _physicalBottom() {
1417 return this._physicalTop + this._physicalSize; 1429 return this._physicalTop + this._physicalSize;
1418 }, 1430 },
1419 get _scrollBottom() { 1431 get _scrollBottom() {
1420 return this._scrollPosition + this._viewportHeight; 1432 return this._scrollPosition + this._viewportHeight;
1421 }, 1433 },
1422 get _virtualEnd() { 1434 get _virtualEnd() {
1423 return this._virtualStart + this._physicalCount - 1; 1435 return this._virtualStart + this._physicalCount - 1;
1424 }, 1436 },
1425 get _hiddenContentSize() { 1437 get _hiddenContentSize() {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1463 get _optPhysicalSize() { 1475 get _optPhysicalSize() {
1464 if (this.grid) { 1476 if (this.grid) {
1465 return this._estRowsInView * this._rowHeight * this._maxPages; 1477 return this._estRowsInView * this._rowHeight * this._maxPages;
1466 } 1478 }
1467 return this._viewportHeight * this._maxPages; 1479 return this._viewportHeight * this._maxPages;
1468 }, 1480 },
1469 get _optPhysicalCount() { 1481 get _optPhysicalCount() {
1470 return this._estRowsInView * this._itemsPerRow * this._maxPages; 1482 return this._estRowsInView * this._itemsPerRow * this._maxPages;
1471 }, 1483 },
1472 get _isVisible() { 1484 get _isVisible() {
1473 return this.scrollTarget && Boolean(this.scrollTarget.offsetWidth || this. scrollTarget.offsetHeight); 1485 return Boolean(this.offsetWidth || this.offsetHeight);
1474 }, 1486 },
1475 get firstVisibleIndex() { 1487 get firstVisibleIndex() {
1476 if (this._firstVisibleIndexVal === null) { 1488 if (this._firstVisibleIndexVal === null) {
1477 var physicalOffset = Math.floor(this._physicalTop + this._scrollerPaddin gTop); 1489 var physicalOffset = Math.floor(this._physicalTop + this._scrollerPaddin gTop);
1478 this._firstVisibleIndexVal = this._iterateItems(function(pidx, vidx) { 1490 this._firstVisibleIndexVal = this._iterateItems(function(pidx, vidx) {
1479 physicalOffset += this._getPhysicalSizeIncrement(pidx); 1491 physicalOffset += this._getPhysicalSizeIncrement(pidx);
1480 if (physicalOffset > this._scrollPosition) { 1492 if (physicalOffset > this._scrollPosition) {
1481 return this.grid ? vidx - vidx % this._itemsPerRow : vidx; 1493 return this.grid ? vidx - vidx % this._itemsPerRow : vidx;
1482 } 1494 }
1483 if (this.grid && this._virtualCount - 1 === vidx) { 1495 if (this.grid && this._virtualCount - 1 === vidx) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 return Math.ceil(this._viewportHeight / this._rowHeight); 1528 return Math.ceil(this._viewportHeight / this._rowHeight);
1517 }, 1529 },
1518 get _physicalRows() { 1530 get _physicalRows() {
1519 return Math.ceil(this._physicalCount / this._itemsPerRow); 1531 return Math.ceil(this._physicalCount / this._itemsPerRow);
1520 }, 1532 },
1521 ready: function() { 1533 ready: function() {
1522 this.addEventListener('focus', this._didFocus.bind(this), true); 1534 this.addEventListener('focus', this._didFocus.bind(this), true);
1523 }, 1535 },
1524 attached: function() { 1536 attached: function() {
1525 this.updateViewportBoundaries(); 1537 this.updateViewportBoundaries();
1526 this._render(); 1538 if (this._physicalCount === 0) {
1539 this._debounceTemplate(this._render);
1540 }
1527 this.listen(this, 'iron-resize', '_resizeHandler'); 1541 this.listen(this, 'iron-resize', '_resizeHandler');
1528 }, 1542 },
1529 detached: function() { 1543 detached: function() {
1530 this._itemsRendered = false;
1531 this.unlisten(this, 'iron-resize', '_resizeHandler'); 1544 this.unlisten(this, 'iron-resize', '_resizeHandler');
1532 }, 1545 },
1533 _setOverflow: function(scrollTarget) { 1546 _setOverflow: function(scrollTarget) {
1534 this.style.webkitOverflowScrolling = scrollTarget === this ? 'touch' : ''; 1547 this.style.webkitOverflowScrolling = scrollTarget === this ? 'touch' : '';
1535 this.style.overflow = scrollTarget === this ? 'auto' : ''; 1548 this.style.overflow = scrollTarget === this ? 'auto' : '';
1536 }, 1549 },
1537 updateViewportBoundaries: function() { 1550 updateViewportBoundaries: function() {
1538 this._scrollerPaddingTop = this.scrollTarget === this ? 0 : parseInt(windo w.getComputedStyle(this)['padding-top'], 10); 1551 this._scrollerPaddingTop = this.scrollTarget === this ? 0 : parseInt(windo w.getComputedStyle(this)['padding-top'], 10);
1539 this._viewportHeight = this._scrollTargetHeight; 1552 this._viewportHeight = this._scrollTargetHeight;
1540 if (this.grid) { 1553 if (this.grid) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1621 var inst = this.stamp(null); 1634 var inst = this.stamp(null);
1622 physicalItems[i] = inst.root.querySelector('*'); 1635 physicalItems[i] = inst.root.querySelector('*');
1623 Polymer.dom(this).appendChild(inst.root); 1636 Polymer.dom(this).appendChild(inst.root);
1624 } 1637 }
1625 return physicalItems; 1638 return physicalItems;
1626 }, 1639 },
1627 _increasePoolIfNeeded: function() { 1640 _increasePoolIfNeeded: function() {
1628 if (this._viewportHeight === 0) { 1641 if (this._viewportHeight === 0) {
1629 return false; 1642 return false;
1630 } 1643 }
1631 var isClientHeightFull = this._physicalBottom >= this._scrollBottom && thi s._physicalTop <= this._scrollPosition; 1644 var self = this;
1632 if (this._physicalSize >= this._optPhysicalSize && isClientHeightFull) { 1645 var isClientFull = this._physicalBottom >= this._scrollBottom && this._phy sicalTop <= this._scrollPosition;
1646 if (this._physicalSize >= this._optPhysicalSize && isClientFull) {
1633 return false; 1647 return false;
1634 } 1648 }
1635 var currentPage = Math.floor(this._physicalSize / this._viewportHeight); 1649 var maxPoolSize = Math.round(this._physicalCount * .5);
1636 if (currentPage === 0) { 1650 if (!isClientFull) {
1637 this._debounceTemplate(this._increasePool.bind(this, Math.round(this._ph ysicalCount * .5))); 1651 this._debounceTemplate(this._increasePool.bind(this, maxPoolSize));
1638 } else if (this._lastPage !== currentPage && isClientHeightFull) { 1652 return true;
1639 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', this._increa sePool.bind(this, this._itemsPerRow), 16));
1640 } else {
1641 this._debounceTemplate(this._increasePool.bind(this, this._itemsPerRow)) ;
1642 } 1653 }
1643 this._lastPage = currentPage; 1654 this._yield(function() {
1655 self._increasePool(Math.min(maxPoolSize, Math.max(1, Math.round(50 / sel f._templateCost))));
1656 });
1644 return true; 1657 return true;
1645 }, 1658 },
1659 _yield: function(cb) {
1660 var g = window;
1661 var handle = g.requestIdleCallback ? g.requestIdleCallback(cb) : g.setTime out(cb, 16);
1662 Polymer.dom.addDebouncer({
1663 complete: function() {
1664 g.cancelIdleCallback ? g.cancelIdleCallback(handle) : g.clearTimeout(h andle);
1665 cb();
1666 }
1667 });
1668 },
1646 _increasePool: function(missingItems) { 1669 _increasePool: function(missingItems) {
1647 var nextPhysicalCount = Math.min(this._physicalCount + missingItems, this. _virtualCount - this._virtualStart, Math.max(this.maxPhysicalCount, DEFAULT_PHYS ICAL_COUNT)); 1670 var nextPhysicalCount = Math.min(this._physicalCount + missingItems, this. _virtualCount - this._virtualStart, Math.max(this.maxPhysicalCount, DEFAULT_PHYS ICAL_COUNT));
1648 var prevPhysicalCount = this._physicalCount; 1671 var prevPhysicalCount = this._physicalCount;
1649 var delta = nextPhysicalCount - prevPhysicalCount; 1672 var delta = nextPhysicalCount - prevPhysicalCount;
1673 var ts = window.performance.now();
1650 if (delta <= 0) { 1674 if (delta <= 0) {
1651 return; 1675 return;
1652 } 1676 }
1653 [].push.apply(this._physicalItems, this._createPool(delta)); 1677 [].push.apply(this._physicalItems, this._createPool(delta));
1654 [].push.apply(this._physicalSizes, new Array(delta)); 1678 [].push.apply(this._physicalSizes, new Array(delta));
1655 this._physicalCount = prevPhysicalCount + delta; 1679 this._physicalCount = prevPhysicalCount + delta;
1656 if (this._physicalStart > this._physicalEnd && this._isIndexRendered(this. _focusedIndex) && this._getPhysicalIndex(this._focusedIndex) < this._physicalEnd ) { 1680 if (this._physicalStart > this._physicalEnd && this._isIndexRendered(this. _focusedIndex) && this._getPhysicalIndex(this._focusedIndex) < this._physicalEnd ) {
1657 this._physicalStart = this._physicalStart + delta; 1681 this._physicalStart = this._physicalStart + delta;
1658 } 1682 }
1659 this._update(); 1683 this._update();
1684 this._templateCost = (window.performance.now() - ts) / delta;
1660 }, 1685 },
1661 _render: function() { 1686 _render: function() {
1662 var requiresUpdate = this._virtualCount > 0 || this._physicalCount > 0; 1687 if (this.isAttached && this._isVisible) {
1663 if (this.isAttached && !this._itemsRendered && this._isVisible && requires Update) { 1688 if (this._physicalCount === 0) {
1664 this._lastPage = 0; 1689 this._increasePool(DEFAULT_PHYSICAL_COUNT);
1665 this._update(); 1690 } else {
1666 this._itemsRendered = true; 1691 this._update();
1692 }
1667 } 1693 }
1668 }, 1694 },
1669 _ensureTemplatized: function() { 1695 _ensureTemplatized: function() {
1670 if (!this.ctor) { 1696 if (!this.ctor) {
1671 var props = {}; 1697 var props = {};
1672 props.__key__ = true; 1698 props.__key__ = true;
1673 props[this.as] = true; 1699 props[this.as] = true;
1674 props[this.indexAs] = true; 1700 props[this.indexAs] = true;
1675 props[this.selectedAs] = true; 1701 props[this.selectedAs] = true;
1676 props.tabIndex = true; 1702 props.tabIndex = true;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1737 }, 1763 },
1738 _itemsChanged: function(change) { 1764 _itemsChanged: function(change) {
1739 if (change.path === 'items') { 1765 if (change.path === 'items') {
1740 this._virtualStart = 0; 1766 this._virtualStart = 0;
1741 this._physicalTop = 0; 1767 this._physicalTop = 0;
1742 this._virtualCount = this.items ? this.items.length : 0; 1768 this._virtualCount = this.items ? this.items.length : 0;
1743 this._collection = this.items ? Polymer.Collection.get(this.items) : nul l; 1769 this._collection = this.items ? Polymer.Collection.get(this.items) : nul l;
1744 this._physicalIndexForKey = {}; 1770 this._physicalIndexForKey = {};
1745 this._firstVisibleIndexVal = null; 1771 this._firstVisibleIndexVal = null;
1746 this._lastVisibleIndexVal = null; 1772 this._lastVisibleIndexVal = null;
1773 this._physicalCount = this._physicalCount || 0;
1774 this._physicalItems = this._physicalItems || [];
1775 this._physicalSizes = this._physicalSizes || [];
1776 this._physicalStart = 0;
1747 this._resetScrollPosition(0); 1777 this._resetScrollPosition(0);
1748 this._removeFocusedItem(); 1778 this._removeFocusedItem();
1749 if (!this._physicalItems) { 1779 this._debounceTemplate(this._render);
1750 this._physicalCount = Math.max(1, Math.min(DEFAULT_PHYSICAL_COUNT, thi s._virtualCount));
1751 this._physicalItems = this._createPool(this._physicalCount);
1752 this._physicalSizes = new Array(this._physicalCount);
1753 }
1754 this._physicalStart = 0;
1755 } else if (change.path === 'items.splices') { 1780 } else if (change.path === 'items.splices') {
1756 this._adjustVirtualIndex(change.value.indexSplices); 1781 this._adjustVirtualIndex(change.value.indexSplices);
1757 this._virtualCount = this.items ? this.items.length : 0; 1782 this._virtualCount = this.items ? this.items.length : 0;
1783 this._debounceTemplate(this._render);
1758 } else { 1784 } else {
1759 this._forwardItemPath(change.path.split('.').slice(1).join('.'), change. value); 1785 this._forwardItemPath(change.path.split('.').slice(1).join('.'), change. value);
1760 return;
1761 } 1786 }
1762 this._itemsRendered = false;
1763 this._debounceTemplate(this._render);
1764 }, 1787 },
1765 _adjustVirtualIndex: function(splices) { 1788 _adjustVirtualIndex: function(splices) {
1766 splices.forEach(function(splice) { 1789 splices.forEach(function(splice) {
1767 splice.removed.forEach(this._removeItem, this); 1790 splice.removed.forEach(this._removeItem, this);
1768 if (splice.index < this._virtualStart) { 1791 if (splice.index < this._virtualStart) {
1769 var delta = Math.max(splice.addedCount - splice.removed.length, splice .index - this._virtualStart); 1792 var delta = Math.max(splice.addedCount - splice.removed.length, splice .index - this._virtualStart);
1770 this._virtualStart = this._virtualStart + delta; 1793 this._virtualStart = this._virtualStart + delta;
1771 if (this._focusedIndex >= 0) { 1794 if (this._focusedIndex >= 0) {
1772 this._focusedIndex = this._focusedIndex + delta; 1795 this._focusedIndex = this._focusedIndex + delta;
1773 } 1796 }
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1922 } 1945 }
1923 }, 1946 },
1924 scrollToItem: function(item) { 1947 scrollToItem: function(item) {
1925 return this.scrollToIndex(this.items.indexOf(item)); 1948 return this.scrollToIndex(this.items.indexOf(item));
1926 }, 1949 },
1927 scrollToIndex: function(idx) { 1950 scrollToIndex: function(idx) {
1928 if (typeof idx !== 'number' || idx < 0 || idx > this.items.length - 1) { 1951 if (typeof idx !== 'number' || idx < 0 || idx > this.items.length - 1) {
1929 return; 1952 return;
1930 } 1953 }
1931 Polymer.dom.flush(); 1954 Polymer.dom.flush();
1932 if (!this._itemsRendered) { 1955 if (this._physicalCount === 0) {
1933 return; 1956 return;
1934 } 1957 }
1935 idx = Math.min(Math.max(idx, 0), this._virtualCount - 1); 1958 idx = Math.min(Math.max(idx, 0), this._virtualCount - 1);
1936 if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) { 1959 if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) {
1937 this._virtualStart = this.grid ? idx - this._itemsPerRow * 2 : idx - 1; 1960 this._virtualStart = this.grid ? idx - this._itemsPerRow * 2 : idx - 1;
1938 } 1961 }
1939 this._manageFocus(); 1962 this._manageFocus();
1940 this._assignModels(); 1963 this._assignModels();
1941 this._updateMetrics(); 1964 this._updateMetrics();
1942 this._physicalTop = Math.floor(this._virtualStart / this._itemsPerRow) * t his._physicalAverage; 1965 this._physicalTop = Math.floor(this._virtualStart / this._itemsPerRow) * t his._physicalAverage;
(...skipping 17 matching lines...) Expand all
1960 this._physicalAverage = 0; 1983 this._physicalAverage = 0;
1961 this._physicalAverageCount = 0; 1984 this._physicalAverageCount = 0;
1962 }, 1985 },
1963 _resizeHandler: function() { 1986 _resizeHandler: function() {
1964 if (IOS && Math.abs(this._viewportHeight - this._scrollTargetHeight) < 100 ) { 1987 if (IOS && Math.abs(this._viewportHeight - this._scrollTargetHeight) < 100 ) {
1965 return; 1988 return;
1966 } 1989 }
1967 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', function() { 1990 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', function() {
1968 this.updateViewportBoundaries(); 1991 this.updateViewportBoundaries();
1969 this._render(); 1992 this._render();
1970 if (this._itemsRendered && this._physicalItems && this._isVisible) { 1993 if (this._physicalCount > 0 && this._isVisible) {
1971 this._resetAverage(); 1994 this._resetAverage();
1972 this.scrollToIndex(this.firstVisibleIndex); 1995 this.scrollToIndex(this.firstVisibleIndex);
1973 } 1996 }
1974 }.bind(this), 1)); 1997 }.bind(this), 1));
1975 }, 1998 },
1976 _getModelFromItem: function(item) { 1999 _getModelFromItem: function(item) {
1977 var key = this._collection.getKey(item); 2000 var key = this._collection.getKey(item);
1978 var pidx = this._physicalIndexForKey[key]; 2001 var pidx = this._physicalIndexForKey[key];
1979 if (pidx != null) { 2002 if (pidx != null) {
1980 return this._physicalItems[pidx]._templateInstance; 2003 return this._physicalItems[pidx]._templateInstance;
(...skipping 4976 matching lines...) Expand 10 before | Expand all | Expand 10 after
6957 }; 6980 };
6958 return { 6981 return {
6959 Manager: Manager 6982 Manager: Manager
6960 }; 6983 };
6961 }); 6984 });
6962 6985
6963 // Copyright 2015 The Chromium Authors. All rights reserved. 6986 // Copyright 2015 The Chromium Authors. All rights reserved.
6964 // Use of this source code is governed by a BSD-style license that can be 6987 // Use of this source code is governed by a BSD-style license that can be
6965 // found in the LICENSE file. 6988 // found in the LICENSE file.
6966 window.addEventListener('load', downloads.Manager.onLoad); 6989 window.addEventListener('load', downloads.Manager.onLoad);
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/resources/md_history/app.crisper.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698