Bug 1298436 - Don't get caught in an endless loop when narrating last paragraph. r=jaws
authorEitan Isaacson <eitan@monotonous.org>
Sat, 27 Aug 2016 14:42:51 -0700
changeset 311981 830b1dcd83591a6e09c915aff426dbb1d2ec3f81
parent 311980 18f8a36a4ed226f73dc8fd0baeee8dc7458f3474
child 311982 b8771e81cc6ee8c95ba3e6f251ca94a732eef5ad
push id30628
push userryanvm@gmail.com
push dateWed, 31 Aug 2016 13:53:01 +0000
treeherdermozilla-central@b38f935eb811 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1298436
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1298436 - Don't get caught in an endless loop when narrating last paragraph. r=jaws MozReview-Commit-ID: 7SMh0MGusgM
toolkit/components/narrate/Narrator.jsm
toolkit/components/narrate/test/browser_narrate.js
--- a/toolkit/components/narrate/Narrator.jsm
+++ b/toolkit/components/narrate/Narrator.jsm
@@ -139,18 +139,18 @@ Narrator.prototype = {
     win.dispatchEvent(new win.CustomEvent(eventType,
       { detail: Cu.cloneInto(detail, win.document) }));
   },
 
   _speakInner: function() {
     this._win.speechSynthesis.cancel();
     let tw = this._treeWalker;
     let paragraph = tw.currentNode;
-    if (!paragraph) {
-      tw.currentNode = tw.root;
+    if (paragraph == tw.root) {
+      this._sendTestEvent("paragraphsdone", {});
       return Promise.resolve();
     }
 
     let utterance = new this._win.SpeechSynthesisUtterance(
       paragraph.textContent);
     utterance.rate = this._speechOptions.rate;
     if (this._speechOptions.voice) {
       utterance.voice = this._speechOptions.voice;
@@ -188,17 +188,17 @@ Narrator.prototype = {
         if (this._inTest) {
           this._sendTestEvent("paragraphend", {});
         }
 
         if (this._stopped) {
           // User pressed stopped.
           resolve();
         } else {
-          tw.nextNode();
+          tw.currentNode = tw.nextNode() || tw.root;
           this._speakInner().then(resolve, reject);
         }
       });
 
       utterance.addEventListener("error", () => {
         reject("speech synthesis failed");
       });
 
--- a/toolkit/components/narrate/test/browser_narrate.js
+++ b/toolkit/components/narrate/test/browser_narrate.js
@@ -113,16 +113,22 @@ add_task(function* testNarrate() {
     content.scrollBy(0, -10);
     yield promiseEvent;
     ok(NarrateTestUtils.isVisible(popup), "popup stays visible after scroll");
 
     toggle.click();
     ok(!NarrateTestUtils.isVisible(popup), "popup is dismissed while speaking");
     NarrateTestUtils.isStartedState(content, ok);
 
-    promiseEvent = ContentTaskUtils.waitForEvent(content, "paragraphend");
-    $(NarrateTestUtils.STOP).click();
-    yield promiseEvent;
+    // Go forward all the way to the end of the article. We should eventually
+    // stop.
+    do {
+      promiseEvent = Promise.race([
+        ContentTaskUtils.waitForEvent(content, "paragraphstart"),
+        ContentTaskUtils.waitForEvent(content, "paragraphsdone")]);
+      $(NarrateTestUtils.FORWARD).click();
+    } while ((yield promiseEvent).type == "paragraphstart");
+
     yield ContentTaskUtils.waitForCondition(
       () => !$(NarrateTestUtils.STOP), "transitioned to stopped state");
     NarrateTestUtils.isStoppedState(content, ok);
   });
 });