Merge "Replace this.async() with setTimeout()"
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
index 1b85e21..34572c5 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
@@ -141,7 +141,7 @@
 
     // NOTE: This method may be called before attachment. Fire title-change
     // in an async so that attachment to the DOM can take place first.
-    this.async(() => fireTitleChange(this, this._query));
+    setTimeout(() => fireTitleChange(this, this._query));
 
     this.restApiService
       .getPreferences()
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
index 147ebc3..dcd1d93 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
@@ -2081,7 +2081,7 @@
             }
 
             if (attemptsRemaining) {
-              this.async(check, AWAIT_CHANGE_TIMEOUT_MS);
+              setTimeout(check, AWAIT_CHANGE_TIMEOUT_MS);
             } else {
               resolve(false);
             }
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index 6d49eb1..aded3b9 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -1376,7 +1376,7 @@
 
     this._sendShowChangeEvent();
 
-    this.async(() => {
+    setTimeout(() => {
       if (this.viewState.scrollTop) {
         document.documentElement.scrollTop = document.body.scrollTop = this.viewState.scrollTop;
       } else {
@@ -1488,10 +1488,10 @@
       if (this.viewState.showReplyDialog) {
         this._openReplyDialog(this.$.replyDialog.FocusTarget.ANY);
         // TODO(kaspern@): Find a better signal for when to call center.
-        this.async(() => {
+        setTimeout(() => {
           this.$.replyOverlay.center();
         }, 100);
-        this.async(() => {
+        setTimeout(() => {
           this.$.replyOverlay.center();
         }, 1000);
         this.set('viewState.showReplyDialog', false);
@@ -2589,7 +2589,7 @@
       return;
     }
 
-    this._updateCheckTimerHandle = this.async(() => {
+    this._updateCheckTimerHandle = window.setTimeout(() => {
       assertIsDefined(this._change, '_change');
       const change = this._change;
       fetchChangeUpdates(change, this.restApiService).then(result => {
@@ -2645,7 +2645,7 @@
 
   _cancelUpdateCheckTimer() {
     if (this._updateCheckTimerHandle) {
-      this.cancelAsync(this._updateCheckTimerHandle);
+      window.clearTimeout(this._updateCheckTimerHandle);
     }
     this._updateCheckTimerHandle = null;
   }
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
index 8898eb7..b4e39f5 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
@@ -2325,18 +2325,11 @@
     });
 
     suite('update checks', () => {
+      let clock: SinonFakeTimers;
       let startUpdateCheckTimerSpy: SinonSpyMember<typeof element._startUpdateCheckTimer>;
-      let asyncStub: SinonStubbedMember<typeof element.async>;
       setup(() => {
+        clock = sinon.useFakeTimers();
         startUpdateCheckTimerSpy = sinon.spy(element, '_startUpdateCheckTimer');
-        asyncStub = sinon.stub(element, 'async').callsFake(f => {
-          // Only fire the async callback one time.
-          if (asyncStub.callCount > 1) {
-            return 1;
-          }
-          f.call(element);
-          return 1;
-        });
         element._change = {
           ...createChange(),
           revisions: createRevisions(1),
@@ -2380,14 +2373,14 @@
           ...createServerInfo(),
           change: {...createChangeConfig(), update_delay: 12345},
         };
+        clock.tick(12345 * 1000);
         await flush();
 
         assert.equal(startUpdateCheckTimerSpy.callCount, 2);
         assert.isTrue(getChangeDetailStub.called);
-        assert.equal(asyncStub.lastCall.args[1], 12345 * 1000);
       });
 
-      test('_startUpdateCheckTimer out-of-date shows an alert', done => {
+      test('_startUpdateCheckTimer out-of-date shows an alert', async () => {
         stubRestApi('getChangeDetail').callsFake(() =>
           Promise.resolve({
             ...createChange(),
@@ -2398,15 +2391,18 @@
           })
         );
 
+        let alertMessage = 'alert not fired';
         element.addEventListener('show-alert', e => {
-          assert.equal(e.detail.message, 'A newer patch set has been uploaded');
-          done();
+          alertMessage = e.detail.message;
         });
         element._serverConfig = {
           ...createServerInfo(),
           change: {...createChangeConfig(), update_delay: 12345},
         };
+        clock.tick(12345 * 1000);
+        await flush();
 
+        assert.equal(alertMessage, 'A newer patch set has been uploaded');
         assert.equal(startUpdateCheckTimerSpy.callCount, 1);
       });
 
@@ -2426,13 +2422,14 @@
           ...createServerInfo(),
           change: {...createChangeConfig(), update_delay: 12345},
         };
+        clock.tick(12345 * 1000 * 2);
         await flush();
 
         // No toast, instead a second call to _startUpdateCheckTimer().
         assert.equal(startUpdateCheckTimerSpy.callCount, 2);
       });
 
-      test('_startUpdateCheckTimer new status shows an alert', done => {
+      test('_startUpdateCheckTimer new status shows an alert', async () => {
         stubRestApi('getChangeDetail').callsFake(() =>
           Promise.resolve({
             ...createChange(),
@@ -2444,17 +2441,21 @@
           })
         );
 
+        let alertMessage = 'alert not fired';
         element.addEventListener('show-alert', e => {
-          assert.equal(e.detail.message, 'This change has been merged');
-          done();
+          alertMessage = e.detail.message;
         });
         element._serverConfig = {
           ...createServerInfo(),
           change: {...createChangeConfig(), update_delay: 12345},
         };
+        clock.tick(12345 * 1000);
+        await flush();
+
+        assert.equal(alertMessage, 'This change has been merged');
       });
 
-      test('_startUpdateCheckTimer new messages shows an alert', done => {
+      test('_startUpdateCheckTimer new messages shows an alert', async () => {
         stubRestApi('getChangeDetail').callsFake(() =>
           Promise.resolve({
             ...createChange(),
@@ -2464,17 +2465,19 @@
             current_revision: 'rev1' as CommitId,
           })
         );
+
+        let alertMessage = 'alert not fired';
         element.addEventListener('show-alert', e => {
-          assert.equal(
-            e.detail.message,
-            'There are new messages on this change'
-          );
-          done();
+          alertMessage = e.detail.message;
         });
         element._serverConfig = {
           ...createServerInfo(),
           change: {...createChangeConfig(), update_delay: 12345},
         };
+        clock.tick(12345 * 1000);
+        await flush();
+
+        assert.equal(alertMessage, 'There are new messages on this change');
       });
     });
 
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
index 0f20c48..1292b26 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
@@ -1777,7 +1777,7 @@
    */
   _reportRenderedRow(index: number) {
     if (index === this._shownFiles.length - 1) {
-      this.async(() => {
+      setTimeout(() => {
         this.reporting.timeEndWithAverage(
           RENDER_TIMING_LABEL,
           RENDER_AVG_TIMING_LABEL,
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts
index 9a652df..b02dfa2 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts
@@ -321,7 +321,7 @@
       // Persist alert until navigation.
       this.listen(document, 'location-change', '_hideAlert');
     } else {
-      this._hideAlertHandle = this.async(
+      this._hideAlertHandle = window.setTimeout(
         this._hideAlert,
         HIDE_ALERT_TIMEOUT_MS
       );
@@ -347,7 +347,7 @@
 
   _clearHideAlertHandle() {
     if (this._hideAlertHandle !== null) {
-      this.cancelAsync(this._hideAlertHandle);
+      window.clearTimeout(this._hideAlertHandle);
       this._hideAlertHandle = null;
     }
   }
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
index 46e972a..0513a37 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -880,7 +880,7 @@
 
       // Fire asynchronously so that the URL is changed by the time the event
       // is processed.
-      this.async(() => {
+      setTimeout(() => {
         const detail: LocationChangeEventDetail = {
           hash: window.location.hash,
           pathname: window.location.pathname,
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts
index ae82036..4c10d5c 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts
@@ -326,7 +326,7 @@
       sectionEl.parentNode.removeChild(sectionEl);
     }
 
-    this.async(() => fireEvent(this, 'render-content'), 1);
+    setTimeout(() => fireEvent(this, 'render-content'), 1);
   }
 
   cancel() {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.ts b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.ts
index c13092f..1f0c246 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.ts
@@ -173,7 +173,7 @@
         let currentBatch = 0;
         const nextStep = () => {
           if (this._isScrolling) {
-            this._nextStepHandle = this.async(nextStep, 100);
+            this._nextStepHandle = window.setTimeout(nextStep, 100);
             return;
           }
           // If we are done, resolve the promise.
@@ -196,7 +196,7 @@
           state.chunkIndex = stateUpdate.newChunkIndex;
           if (currentBatch >= this._asyncThreshold) {
             currentBatch = 0;
-            this._nextStepHandle = this.async(nextStep, 1);
+            this._nextStepHandle = window.setTimeout(nextStep, 1);
           } else {
             nextStep.call(this);
           }
@@ -215,7 +215,7 @@
    */
   cancel() {
     if (this._nextStepHandle !== null) {
-      this.cancelAsync(this._nextStepHandle);
+      window.clearTimeout(this._nextStepHandle);
       this._nextStepHandle = null;
     }
     if (this._processPromise) {
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts
index e9dc40c..c8f91cc 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts
@@ -164,7 +164,7 @@
       if (autocomplete) {
         autocomplete.focus();
       }
-      this.async(() => {
+      setTimeout(() => {
         this.$.overlay.center();
       }, 1);
     });
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
index b273af7..86dd5b6 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
@@ -179,7 +179,7 @@
     // NOTE: This may be called before attachment (e.g. while parentElement is
     // null). Fire title-change in an async so that, if attachment to the DOM
     // has been queued, the event can bubble up to the handler in gr-app.
-    this.async(() => {
+    setTimeout(() => {
       const title = `Editing ${computeTruncatedPath(value.path)}`;
       fireTitleChange(this, title);
     });
diff --git a/polygerrit-ui/app/elements/gr-app-element.ts b/polygerrit-ui/app/elements/gr-app-element.ts
index 009e9a6..f33ed8b 100644
--- a/polygerrit-ui/app/elements/gr-app-element.ts
+++ b/polygerrit-ui/app/elements/gr-app-element.ts
@@ -485,7 +485,7 @@
     // because _showPluginScreen value does not change. To force restamp,
     // change _showPluginScreen value between true and false.
     if (isPluginScreen) {
-      this.async(() => this.set('_showPluginScreen', true), 1);
+      setTimeout(() => this.set('_showPluginScreen', true), 1);
     }
     this.set(
       '_showDocumentationSearch',
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
index 1673b2e..06144dc 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
@@ -521,7 +521,7 @@
 
     if (!isEditing) {
       // Allow the reply to render in the dom-repeat.
-      this.async(() => {
+      setTimeout(() => {
         const commentEl = this._commentElWithDraftID(reply.__draftID);
         if (commentEl) commentEl.save();
       }, 1);
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
index 3692108..2807730 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
@@ -587,7 +587,7 @@
       this._fireUpdate();
     }
     if (editing) {
-      this.async(() => {
+      setTimeout(() => {
         flush();
         this.textarea && this.textarea.putCursorAtEnd();
       }, 1);
diff --git a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.ts b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.ts
index 979ed02..b47925b 100644
--- a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.ts
+++ b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.ts
@@ -84,7 +84,7 @@
       this.$.input.style.display = 'none';
     }
     this.$.icon.icon = 'gr-icons:check';
-    this.async(
+    setTimeout(
       () => (this.$.icon.icon = 'gr-icons:content-copy'),
       COPY_TIMEOUT_MS
     );
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
index 006a8de..28336cf 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
@@ -100,7 +100,7 @@
   _handleDropdownClick() {
     // async is needed so that that the click event is fired before the
     // dropdown closes (This was a bug for touch devices).
-    this.async(() => {
+    setTimeout(() => {
       this.$.dropdown.close();
     }, 1);
   }
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.ts b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.ts
index 9918456..f0b6959 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.ts
@@ -219,7 +219,7 @@
   _close() {
     // async is needed so that that the click event is fired before the
     // dropdown closes (This was a bug for touch devices).
-    this.async(() => {
+    setTimeout(() => {
       this.$.dropdown.close();
     }, 1);
   }
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
index c84828c..db70e3c 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
+++ b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
@@ -158,7 +158,7 @@
   _awaitOpen(fn: () => void) {
     let iters = 0;
     const step = () => {
-      this.async(() => {
+      setTimeout(() => {
         if (this.$.dropdown.style.display !== 'none') {
           fn.call(this);
         } else if (iters++ < AWAIT_MAX_ITERS) {
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
index 402263d9..a89e051 100644
--- a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
+++ b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
@@ -135,7 +135,7 @@
   _awaitOpen(fn: (this: GrOverlay) => void, reject: (error: Error) => void) {
     let iters = 0;
     const step = () => {
-      this.async(() => {
+      setTimeout(() => {
         if (this.style.display !== 'none') {
           fn.call(this);
         } else if (iters++ < AWAIT_MAX_ITERS) {
diff --git a/polygerrit-ui/app/elements/shared/gr-select/gr-select.ts b/polygerrit-ui/app/elements/shared/gr-select/gr-select.ts
index e08dab2..27f6cb1 100644
--- a/polygerrit-ui/app/elements/shared/gr-select/gr-select.ts
+++ b/polygerrit-ui/app/elements/shared/gr-select/gr-select.ts
@@ -54,7 +54,7 @@
       // Async needed for firefox to populate value. It was trying to do it
       // before options from a dom-repeat were rendered previously.
       // See https://bugs.chromium.org/p/gerrit/issues/detail?id=7735
-      this.async(() => {
+      setTimeout(() => {
         // TODO(TS): maybe should check for undefined before assigning
         // or fallback to ''
         this.nativeSelect.value = this.bindValue!;
diff --git a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.ts b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.ts
index 45e0b9a..3bc4c84 100644
--- a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.ts
+++ b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.ts
@@ -185,7 +185,7 @@
     // Put the cursor at the end always.
     textarea.selectionStart = textarea.value.length;
     textarea.selectionEnd = textarea.selectionStart;
-    this.async(() => {
+    setTimeout(() => {
       textarea.focus();
     });
   }