From 52c41e6960a8b9261a23209796bef744347522a2 Mon Sep 17 00:00:00 2001 From: Kevin Schaaf Date: Wed, 27 Feb 2019 18:15:38 -0800 Subject: [PATCH] Fix order of flushed debouncers to match 1.x --- lib/utils/debounce.html | 20 +++++++++----- test/unit/debounce.html | 58 ++++++++++++++++------------------------- 2 files changed, 35 insertions(+), 43 deletions(-) diff --git a/lib/utils/debounce.html b/lib/utils/debounce.html index 54fc859623..01142cbd95 100644 --- a/lib/utils/debounce.html +++ b/lib/utils/debounce.html @@ -50,10 +50,19 @@ */ cancel() { if (this.isActive()) { - this._asyncModule.cancel(this._timer); + this._cancelAsync(); this._timer = null; + debouncerQueue.delete(this); } } + /** + * Cancels a debouncer's async callback. + * + * @return {void} + */ + _cancelAsync() { + this._asyncModule.cancel(/** @type {number} */(this._timer)); + } /** * Flushes an active debouncer and returns a reference to itself. * @@ -105,7 +114,9 @@ */ static debounce(debouncer, asyncModule, callback) { if (debouncer instanceof Debouncer) { - debouncer.cancel(); + // Cancel the async callback, but leave in debouncerQueue if it was + // enqueued, to maintain 1.x flush order + debouncer._cancelAsync(); } else { debouncer = new Debouncer(); } @@ -127,11 +138,6 @@ * @return {void} */ Polymer.enqueueDebouncer = function(debouncer) { - // Re-enqueued debouncers are put at the end of the queue; for Set, this - // means removing and re-adding, since forEach traverses insertion order - if (debouncerQueue.has(debouncer)) { - debouncerQueue.delete(debouncer); - } debouncerQueue.add(debouncer); }; diff --git a/test/unit/debounce.html b/test/unit/debounce.html index f2fbc81935..fbb330753c 100644 --- a/test/unit/debounce.html +++ b/test/unit/debounce.html @@ -211,47 +211,33 @@ }); suite('enqueueDebouncer & flush', function() { - function testEnqueue(shouldFlush, done) { - // Longer-running debouncer - const timeoutCallback = sinon.spy(() => actualCallbacks.push(timeoutCallback)); - Polymer.enqueueDebouncer(Polymer.Debouncer.debounce(null, Polymer.Async.timeOut, timeoutCallback)); - // Set of short-running debouncers enqueued in the middle of first set - const nestedCallbacks = []; - for (let i=0; i<150; i++) { - nestedCallbacks.push(sinon.spy(() => - actualCallbacks.push(nestedCallbacks[i]))); - } - // First set of short-running debouncers - const microtaskCallbacks = []; - for (let i=0; i<150; i++) { - microtaskCallbacks.push(sinon.spy(() => { - actualCallbacks.push(microtaskCallbacks[i]); - if (i === 125) { - nestedCallbacks.forEach(cb => - Polymer.enqueueDebouncer(Polymer.Debouncer.debounce(null, Polymer.Async.microTask, cb))); - } - })); - } - microtaskCallbacks.forEach(cb => - Polymer.enqueueDebouncer(Polymer.Debouncer.debounce(null, Polymer.Async.microTask, cb))); - // Expect short before long - let expectedCallbacks; - const actualCallbacks = []; - const verify = () => { - actualCallbacks.forEach(cb => assert.isTrue(cb.calledOnce)); - assert.deepEqual(expectedCallbacks, actualCallbacks); - done(); + + const testEnqueue = (shouldFlush, done) => { + const actualOrder = []; + let i=1; + const enqueue = (type, {db, cb} = {}) => { + cb = cb || (() => actualOrder.push(cb)); + db = Polymer.Debouncer.debounce(db, type, cb); + Polymer.enqueueDebouncer(db); + return {db, cb}; }; + const db1 = enqueue(Polymer.Async.microTask); + const db2 = enqueue(Polymer.Async.microTask); + const db3 = enqueue(Polymer.Async.timeOut); + const db4 = enqueue(Polymer.Async.microTask); + enqueue(Polymer.Async.microTask, db2); + enqueue(Polymer.Async.microTask, db1); if (shouldFlush) { - expectedCallbacks = [timeoutCallback, ...microtaskCallbacks, ...nestedCallbacks]; Polymer.flush(); - // When flushing, order is order of enqueing - verify(); + assert.deepEqual(actualOrder, [db1.cb, db2.cb, db3.cb, db4.cb]); + done(); } else { - expectedCallbacks = [...microtaskCallbacks, ...nestedCallbacks, timeoutCallback]; - Polymer.Async.timeOut.run(verify); + Polymer.Async.timeOut.run(() => { + assert.deepEqual(actualOrder, [db4.cb, db2.cb, db1.cb, db3.cb]); + done(); + }); } - } + }; test('non-flushed', function(done) { testEnqueue(false, done);