diff --git a/lib/elements/dom-repeat.html b/lib/elements/dom-repeat.html
index 0cbc10f219..17a1401588 100644
--- a/lib/elements/dom-repeat.html
+++ b/lib/elements/dom-repeat.html
@@ -265,32 +265,6 @@
_targetFrameTime: {
type: Number,
computed: '__computeFrameTime(targetFramerate)'
- },
-
- /**
- * When `restamp` is true, template instances are never reused with
- * different items. Instances mapping to current items are moved
- * to their new location, new instances are created for any new
- * items, and instances for removed items are discarded. This mode is
- * generally more expensive than `restamp: false` as it results in
- * more instances to be created and discarded during updates and
- * disconnection/reconnection churn. By default, object identity is
- * used for mapping instances to items. Set `restampKey` to provide
- * key based identity.
- */
- restamp: {
- type: Boolean
- },
-
- /**
- * When `restamp: true` is used, `restampKey` can be used to provide
- * a path into the item object that serves as a unique key for the
- * item, for purposes of mapping instances to items. Instances for
- * items with the same key will be reused, while all others will be
- * either restamped or discarded.
- */
- restampKey: {
- type: String
}
}
@@ -305,6 +279,7 @@
super();
this.__instances = [];
this.__limit = Infinity;
+ this.__pool = [];
this.__renderDebouncer = null;
this.__itemsIdxToInstIdx = {};
this.__chunkCount = null;
@@ -320,9 +295,8 @@
disconnectedCallback() {
super.disconnectedCallback();
this.__isDetached = true;
- let instances = this.__instances;
- for (let i=0; i
- this.__filterFn(items[i], idx, array));
- }
- // Apply user sort
- if (this.__sortFn) {
- inst2items.sort((a, b) => this.__sortFn(items[a], items[b]));
- }
-
- // items->inst map kept for item path forwarding
- const items2inst = this.__itemsIdxToInstIdx = {};
- const instances = this.__instances;
- const limit = Math.max(Math.min(inst2items.length, this.__limit), 0);
- // Generate instances and assign items
- if (this.restamp) {
- this.__renderRestamp(items, instances, limit, inst2items, items2inst);
- } else {
- this.__renderRefresh(items, instances, limit, inst2items, items2inst);
- }
- // Remove any extra instances from previous state
- while (this.__instances.length > limit) {
- this.__detachAndRemoveInstanceAt(limit);
- }
+ this.__applyFullRefresh();
+ // Reset the pool
+ // TODO(kschaaf): Reuse pool across turns and nested templates
+ // Now that objects/arrays are re-evaluated when set, we can safely
+ // reuse pooled instances across turns, however we still need to decide
+ // semantics regarding how long to hold, how many to hold, etc.
+ this.__pool.length = 0;
// Set rendered item count
this._setRenderedItemCount(this.__instances.length);
// Notify users
@@ -563,90 +515,65 @@
this.__tryRenderChunk();
}
- __renderRestamp(items, instances, limit, inst2items, items2inst) {
- let keyPath = this.restampKey;
- const instCache = new Map();
- nextItem: for (let i=0; i cache.forEach(inst => this.__detachInstance(inst)));
- }
-
- __renderRefresh(items, instances, limit, inst2items, items2inst) {
- for (let i=0; i
+ this.__filterFn(items[i], idx, array));
+ }
+ // Apply user sort
+ if (this.__sortFn) {
+ isntIdxToItemsIdx.sort((a, b) => this.__sortFn(items[a], items[b]));
+ }
+ // items->inst map kept for item path forwarding
+ const itemsIdxToInstIdx = this.__itemsIdxToInstIdx = {};
+ let instIdx = 0;
+ // Generate instances and assign items
+ const limit = Math.min(isntIdxToItemsIdx.length, this.__limit);
+ for (; instIdx=instIdx; i--) {
+ this.__detachAndRemoveInstance(i);
}
}
- __detachInstance(inst) {
+ __detachInstance(idx) {
+ let inst = this.__instances[idx];
for (let i=0; ix-repeat-chunked
stamped[38] .. 3-3-3
*/
- function setupFixture(fixtureName) {
- var el = fixture(fixtureName);
- if (document.location.search.indexOf('restamp') >= 0) {
- el.restamp = true;
- }
- return el;
- }
-
function arrayDelete(el, path, item) {
var array = el.get(path);
var idx = array.indexOf(item);
@@ -178,7 +170,7 @@ x-repeat-chunked
let configured;
setup(function() {
- configured = setupFixture('configured');
+ configured = fixture('configured');
Polymer.flush();
});
@@ -310,7 +302,6 @@ x-repeat-chunked
// reset sort fn
configured.$.repeater.sort = null;
configured.$.repeater.render();
- stamped = configured.root.querySelectorAll('*:not(template):not(dom-repeat)');
assert.equal(stamped.length, 3 + 3*3 + 3*3*3, 'total stamped count incorrect');
assert.equal(stamped[0].itemaProp, 'prop-1');
assert.equal(stamped[0].indexa, 0);
@@ -337,7 +328,6 @@ x-repeat-chunked
// reset sort fn
configured.$.repeater.sort = null;
configured.$.repeater.render();
- stamped = configured.root.querySelectorAll('*:not(template):not(dom-repeat)');
assert.equal(stamped.length, 3 + 3*3 + 3*3*3, 'total stamped count incorrect');
assert.equal(stamped[0].itemaProp, 'prop-1');
assert.equal(stamped[0].indexa, 0);
@@ -654,7 +644,7 @@ x-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured');
+ unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
unconfigured.$.el1.prop = 'outer';
unconfigured.$.el1.item = {prop: 'outerItem'};
@@ -787,7 +777,7 @@ x-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured');
+ unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
Polymer.flush();
});
@@ -875,7 +865,7 @@ x-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured');
+ unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
Polymer.flush();
unconfigured.$.el1.domUpdateHandlerCount = 0;
@@ -1128,7 +1118,7 @@ x-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured');
+ unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
unconfigured.$.el1.$.repeater.filter = function(o) {
return o.prop.indexOf('2') < 0;
@@ -1338,7 +1328,7 @@ x-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured');
+ unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
unconfigured.$.el1.$.repeater.sort = function(a, b) {
return b.prop == a.prop ? 0 : b.prop < a.prop ? -1 : 1;
@@ -1547,7 +1537,7 @@ x-repeat-chunked
var unconfigured
setup(function() {
- unconfigured = setupFixture('unconfigured');
+ unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
unconfigured.$.el1.$.repeater.sort = function(a, b) {
return b.prop == a.prop ? 0 : b.prop < a.prop ? -1 : 1;
@@ -1746,7 +1736,7 @@ x-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured-mutable');
+ unconfigured = fixture('unconfigured-mutable');
unconfigured.items = window.getData();
Polymer.flush();
});
@@ -2046,7 +2036,7 @@ x-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured-mutable');
+ unconfigured = fixture('unconfigured-mutable');
unconfigured.items = window.getData();
unconfigured.$.el1.$.repeater.filter = function(o) {
return o.prop.indexOf('2') < 0;
@@ -2263,7 +2253,7 @@ x-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured-mutable');
+ unconfigured = fixture('unconfigured-mutable');
unconfigured.items = window.getData();
unconfigured.$.el1.$.repeater.sort = function(a, b) {
return b.prop == a.prop ? 0 : b.prop < a.prop ? -1 : 1;
@@ -2479,7 +2469,7 @@ x-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured-mutable');
+ unconfigured = fixture('unconfigured-mutable');
unconfigured.items = window.getData();
unconfigured.$.el1.$.repeater.sort = function(a, b) {
return b.prop == a.prop ? 0 : b.prop < a.prop ? -1 : 1;
@@ -2685,7 +2675,7 @@ x-repeat-chunked
let primitive;
setup(function() {
- primitive = setupFixture('primitive');
+ primitive = fixture('primitive');
Polymer.flush();
});
@@ -3231,7 +3221,7 @@ x-repeat-chunked
let primitive;
setup(function() {
- primitive = setupFixture('primitive');
+ primitive = fixture('primitive');
Polymer.flush();
});
@@ -3288,7 +3278,7 @@ x-repeat-chunked
});
test('structured values - initial stamping', function() {
- let unconfigured = setupFixture('unconfigured');
+ let unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
Polymer.flush();
var stamped1 = unconfigured.$.el1.root.querySelectorAll('*:not(template):not(dom-repeat)');
@@ -3298,7 +3288,7 @@ x-repeat-chunked
});
test('structured values - change from inside', function() {
- let unconfigured = setupFixture('unconfigured');
+ let unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
Polymer.flush();
var stamped1 = unconfigured.$.el1.root.querySelectorAll('*:not(template):not(dom-repeat)');
@@ -3315,7 +3305,7 @@ x-repeat-chunked
});
test('structured values - sorted', function() {
- let unconfigured = setupFixture('unconfigured');
+ let unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
Polymer.flush();
unconfigured.$.el1.$.repeater.sort = function(a, b) {
@@ -3351,7 +3341,7 @@ x-repeat-chunked
836, 564, 721, 540, 372,
244, 145, 525, 958, 595,
207, 103, 602, 769, 190];
- let primitive = setupFixture('primitive');
+ let primitive = fixture('primitive');
primitive.items = items;
setTimeout(function() {
var stamped1 = primitive.$.container1.querySelectorAll('*:not(template):not(dom-repeat)');
@@ -3361,7 +3351,10 @@ x-repeat-chunked
var prev = items.slice();
items.sort();
var splices = Polymer.ArraySplice.calculateSplices(items, prev);
- primitive.notifySplices('items', splices);
+ var change = {
+ indexSplices: splices
+ };
+ primitive.set('items.splices', change);
setTimeout(function() {
var stamped1 = primitive.$.container1.querySelectorAll('*:not(template):not(dom-repeat)');
for (var i=0; ix-repeat-chunked
let unconfigured;
setup(function() {
- unconfigured = setupFixture('unconfigured');
+ unconfigured = fixture('unconfigured');
unconfigured.items = window.getData();
Polymer.flush();
});
@@ -3487,7 +3480,7 @@ x-repeat-chunked
});
test('renderedItemCount', function() {
- let primitive = setupFixture('primitive');
+ let primitive = fixture('primitive');
Polymer.flush();
var repeater1 = primitive.$.repeater1;
primitive.items = [ 'a', 'b', 'c', 'd', 'e' ];
@@ -3507,7 +3500,7 @@ x-repeat-chunked
test('_showHideChildren', function() {
// Initially all showing
- let primitive = setupFixture('primitive');
+ let primitive = fixture('primitive');
Polymer.flush();
var stamped1 = primitive.$.container1.querySelectorAll('*:not(template):not(dom-repeat)');
assert.equal(getComputedStyle(stamped1[0]).display, 'block');
@@ -4050,7 +4043,7 @@ x-repeat-chunked
suite('misc', function() {
test('large splice', function(done) {
- let primitiveLarge = setupFixture('primitiveLarge');
+ let primitiveLarge = fixture('primitiveLarge');
Polymer.flush();
primitiveLarge.splice('items', 0, 10);
setTimeout(function() {
@@ -4066,7 +4059,7 @@ x-repeat-chunked
if (!window.ShadyDOM) {
this.skip();
}
- let simple = setupFixture('simple');
+ let simple = fixture('simple');
Polymer.flush();
var removed;
// Confirm initial scoping
@@ -4097,7 +4090,7 @@ x-repeat-chunked
});
test('paths update on observed properties', function() {
- let simple = setupFixture('simple');
+ let simple = fixture('simple');
Polymer.flush();
//debugger;
var stamped = simple.root.querySelectorAll('*:not(template):not(dom-repeat)');
@@ -4127,7 +4120,7 @@ x-repeat-chunked
suite('dom-change composed', function() {
test('dom-change event composed, bubbles outside dom-if scope', function() {
- var el = setupFixture('simple');
+ var el = fixture('simple');
var domChangeFired = 0;
el.addEventListener('dom-change', function() {
domChangeFired++;