bug 1592781 auto-finish TaskRunner Tasks created from async functions r=jgraham
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 07 Nov 2019 00:47:33 +0000
changeset 502537 8ac99aff562c3065c7ad806e4ee54f1f85134668
parent 502536 4f9bb3fd99208bbf178a0e2623faaf05eee18a02
child 502538 b5c5ba07d3dbd0d07b66fa42a103f4df2c27d3a2
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgraham
bugs1592781
milestone72.0a1
bug 1592781 auto-finish TaskRunner Tasks created from async functions r=jgraham Differential Revision: https://phabricator.services.mozilla.com/D51567
testing/web-platform/tests/webaudio/resources/audit.js
testing/web-platform/tests/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-suspend.https.html
--- a/testing/web-platform/tests/webaudio/resources/audit.js
+++ b/testing/web-platform/tests/webaudio/resources/audit.js
@@ -1184,19 +1184,20 @@ window.Audit = (function() {
       this._harnessTest = harnessTest;
       // Print out the task entry with label and description.
       _logPassed(
           '> [' + this._label + '] ' +
           (this._description ? this._description : ''));
 
       return new Promise((resolve, reject) => {
         this._resolve = resolve;
+        this._reject = reject;
         let result = this._taskFunction(this, this.should.bind(this));
         if (result && typeof result.then === "function") {
-          result.then(undefined, reject);
+          result.then(() => this.done()).catch(reject);
         }
       });
     }
 
     // Update the task success based on the individual assertion/test inside.
     update(subTask) {
       // After one of tests fails within a task, the result is irreversible.
       if (subTask.result === false) {
@@ -1224,19 +1225,31 @@ window.Audit = (function() {
         _logFailed(message);
       }
 
       this._resolve();
     }
 
     // Runs |subTask| |time| milliseconds later. |setTimeout| is not allowed in
     // WPT linter, so a thin wrapper around the harness's |step_timeout| is
-    // used here.
+    // used here.  Returns a Promise which is resolved after |subTask| runs.
     timeout(subTask, time) {
-      this._harnessTest.step_timeout(subTask, time);
+      return new Promise(resolve => {
+        this._harnessTest.step_timeout(() => {
+          let result = subTask();
+          if (result && typeof result.then === "function") {
+            // Chain rejection directly to the harness test Promise, to report
+            // the rejection against the subtest even when the caller of
+            // timeout does not handle the rejection.
+            result.then(resolve, this._reject());
+          } else {
+            resolve();
+          }
+        }, time);
+      });
     }
 
     isPassed() {
       return this._state === TaskState.FINISHED && this._result;
     }
 
     toString() {
       return '"' + this._label + '": ' + this._description;
@@ -1273,17 +1286,19 @@ window.Audit = (function() {
         _logPassed(
             prefix + this._taskSequence.length + ' tasks ran successfully.');
       }
 
       return Promise.resolve();
     }
 
     // |taskLabel| can be either a string or a dictionary. See Task constructor
-    // for the detail.
+    // for the detail.  If |taskFunction| returns a thenable, then the task
+    // is considered complete when the thenable is fulfilled; otherwise the
+    // task must be completed with an explicit call to |task.done()|.
     define(taskLabel, taskFunction) {
       let task = new Task(this, taskLabel, taskFunction);
       if (this._tasks.hasOwnProperty(task.label)) {
         _throwException('Audit.define:: Duplicate task definition.');
         return;
       }
       this._tasks[task.label] = task;
       this._taskSequence.push(task.label);
--- a/testing/web-platform/tests/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-suspend.https.html
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-suspend.https.html
@@ -20,21 +20,20 @@
       // time must not advance since the context is suspended.
       audit.define(
           {label: 'load-worklet-and-suspend'},
           async (task, should) => {
             await context.audioWorklet.addModule(filePath);
             const suspendTime = context.currentTime;
             const dummy = new AudioWorkletNode(context, 'dummy');
             dummy.connect(context.destination);
-            task.timeout(() => {
+            return task.timeout(() => {
               should(context.currentTime === suspendTime,
                      'context.currentTime did not change after worklet started')
                   .beTrue();
               should(context.state, 'context.state').beEqualTo('suspended');
-              task.done();
             }, 500);
           });
 
       audit.run();
     </script>
   </body>
 </html>