Bug 1334876 - Go through the event loop to dispatch FontFaceSet events. r=bz, a=jcristau
authorCameron McCormack <cam@mcc.id.au>
Tue, 07 Feb 2017 18:49:28 +0800
changeset 378265 e41566424f2fee04c45e0a685ebd3cf41270e52e
parent 378264 5254b7f0b149e82b04a8d7fd027d4cd92b0c9448
child 378266 7c487eb9d8bed85aeb0101eb378e278665e2962f
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, jcristau
bugs1334876
milestone53.0a2
Bug 1334876 - Go through the event loop to dispatch FontFaceSet events. r=bz, a=jcristau MozReview-Commit-ID: 5L9JEtJoaxF
layout/style/FontFaceSet.cpp
layout/style/test/test_font_loading_api.html
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -1497,17 +1497,17 @@ FontFaceSet::CheckLoadingStarted()
   if (mStatus == FontFaceSetLoadStatus::Loading) {
     // We have already dispatched a loading event and replaced mReady
     // with a fresh, unresolved promise.
     return;
   }
 
   mStatus = FontFaceSetLoadStatus::Loading;
   (new AsyncEventDispatcher(this, NS_LITERAL_STRING("loading"),
-                            false))->RunDOMEventWhenSafe();
+                            false))->PostDOMEvent();
 
   if (PrefEnabled()) {
     if (mReady) {
       if (GetParentObject()) {
         ErrorResult rv;
         mReady = Promise::Create(GetParentObject(), rv);
       }
     }
@@ -1653,17 +1653,17 @@ FontFaceSet::DispatchLoadingFinishedEven
   OwningNonNull<FontFace>* elements =
     init.mFontfaces.AppendElements(aFontFaces.Length(), fallible);
   MOZ_ASSERT(elements);
   for (size_t i = 0; i < aFontFaces.Length(); i++) {
     elements[i] = aFontFaces[i];
   }
   RefPtr<FontFaceSetLoadEvent> event =
     FontFaceSetLoadEvent::Constructor(this, aType, init);
-  (new AsyncEventDispatcher(this, event))->RunDOMEventWhenSafe();
+  (new AsyncEventDispatcher(this, event))->PostDOMEvent();
 }
 
 // nsIDOMEventListener
 
 NS_IMETHODIMP
 FontFaceSet::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsString type;
--- a/layout/style/test/test_font_loading_api.html
+++ b/layout/style/test/test_font_loading_api.html
@@ -1119,24 +1119,28 @@ function runTest() {
   }).then(function() {
 
     // (TEST 37) Test that a FontFace only has one loadingdone event dispatched
     // at the FontFaceSet containing it.
 
     var p = Promise.resolve();
     sources.forEach(function({ win, doc, what}, i) {
       p = p.then(function() {
+        return setTimeoutZero();  // wait for any previous events to be dispatched
+      }).then(function() {
         var events = [], face, face2;
 
-        doc.fonts.onloadingdone = function(e) {
-          events.push(e);
-        };
-        doc.fonts.onloadingerror = function(e) {
-          events.push(e);
-        };
+        var awaitEvents = new Promise(function(aResolve, aReject) {
+          doc.fonts.onloadingdone = doc.fonts.onloadingerror = function(e) {
+            events.push(e);
+            if (events.length == 2) {
+              aResolve();
+            }
+          };
+        });
 
         is(doc.fonts.status, "loaded", "document.fonts.status should have status \"loaded\" (TEST 37) (" + what + ")");
 
         face = new win.FontFace("test", "url(BitPattern.woff?test37." + i + "a)");
         face.load();
         doc.fonts.add(face);
         is(doc.fonts.status, "loading", "document.fonts.status should have status \"loading\" after first font added (TEST 37) (" + what + ")");
 
@@ -1147,16 +1151,18 @@ function runTest() {
 
             face2 = new win.FontFace("test2", "url(BitPattern.woff?test37." + i + "b)");
             face2.load();
             doc.fonts.add(face2);
             is(doc.fonts.status, "loading", "document.fonts.status should have status \"loading\" after second font added (TEST 37) (" + what + ")");
 
             return doc.fonts.ready;
           }).then(function() {
+            return awaitEvents;
+          }).then(function() {
             is(doc.fonts.status, "loaded", "document.fonts.status should have status \"loaded\" after second font loaded (TEST 37) (" + what + ")");
             is(face2.status, "loaded", "second FontFace should have status \"loaded\" (TEST 37) (" + what + ")");
 
             is(events.length, 2, "should receive two events (TEST 37) (" + what + ")");
 
             is(events[0].type, "loadingdone", "first event should be \"loadingdone\" (TEST 37) (" + what + ")");
             is(events[0].fontfaces.length, 1, "first event should have 1 FontFace (TEST 37) (" + what + ")");
             is(events[0].fontfaces[0], face, "first event should have the first FontFace");
@@ -1177,24 +1183,28 @@ function runTest() {
   }).then(function() {
 
     // (TEST 38) Test that a FontFace only has one loadingerror event dispatched
     // at the FontFaceSet containing it.
 
     var p = Promise.resolve();
     sources.forEach(function({ win, doc, what }) {
       p = p.then(function() {
+        return setTimeoutZero();  // wait for any previous events to be dispatched
+      }).then(function() {
         var events = [], face, face2;
 
-        doc.fonts.onloadingdone = function(e) {
-          events.push(e);
-        };
-        doc.fonts.onloadingerror = function(e) {
-          events.push(e);
-        };
+        var awaitEvents = new Promise(function(aResolve, aReject) {
+          doc.fonts.onloadingdone = doc.fonts.onloadingerror = function(e) {
+            events.push(e);
+            if (events.length == 4) {
+              aResolve();
+            }
+          };
+        });
 
         is(doc.fonts.status, "loaded", "document.fonts.status should have status \"loaded\" (TEST 38) (" + what + ")");
 
         face = new win.FontFace("test", "url(x)");
         face.load();
         doc.fonts.add(face);
         is(doc.fonts.status, "loading", "document.fonts.status should have status \"loading\" after first font added (TEST 38) (" + what + ")");
 
@@ -1205,16 +1215,18 @@ function runTest() {
 
             face2 = new win.FontFace("test2", "url(x)");
             face2.load();
             doc.fonts.add(face2);
             is(doc.fonts.status, "loading", "document.fonts.status should have status \"loading\" after second font added (TEST 38) (" + what + ")");
 
             return doc.fonts.ready;
           }).then(function() {
+            return awaitEvents;
+          }).then(function() {
             is(doc.fonts.status, "loaded", "document.fonts.status should have status \"loaded\" after second font failed to load (TEST 38) (" + what + ")");
             is(face2.status, "error", "second FontFace should have status \"error\" (TEST 38) (" + what + ")");
 
             is(events.length, 4, "should receive four events (TEST 38) (" + what + ")");
 
             is(events[0].type, "loadingdone", "first event should be \"loadingdone\" (TEST 38) (" + what + ")");
             is(events[0].fontfaces.length, 0, "first event should have no FontFaces (TEST 38) (" + what + ")");
 
@@ -1238,48 +1250,56 @@ function runTest() {
     });
     return p;
 
   }).then(function() {
 
     // (TEST 39) Test that a FontFace for an @font-face rule only has one
     // loadingdone event dispatched at the FontFaceSet containing it.
 
-    var style = document.querySelector("style");
-    var ruleText = "@font-face { font-family: test; src: url(BitPattern.woff?test39a); } " +
-                   "@font-face { font-family: test2; src: url(BitPattern.woff?test39b); }";
+    var style, all, events, awaitEvents;
 
-    style.textContent = ruleText;
+    return setTimeoutZero()  // wait for any previous events to be dispatched
+      .then(function() {
+        style = document.querySelector("style");
+        var ruleText = "@font-face { font-family: test; src: url(BitPattern.woff?test39a); } " +
+                       "@font-face { font-family: test2; src: url(BitPattern.woff?test39b); }";
 
-    var all = Array.from(document.fonts);
-    var events = [];
+        style.textContent = ruleText;
+
+        all = Array.from(document.fonts);
+        events = [];
 
-    document.fonts.onloadingdone = function(e) {
-      events.push(e);
-    };
-    document.fonts.onloadingerror = function(e) {
-      events.push(e);
-    };
+        awaitEvents = new Promise(function(aResolve, aReject) {
+          document.fonts.onloadingdone = document.fonts.onloadingerror = function(e) {
+            events.push(e);
+            if (events.length == 2) {
+              aResolve();
+            }
+          };
+        });
 
-    is(document.fonts.status, "loaded", "document.fonts.status should have status \"loaded\" (TEST 39)");
+        is(document.fonts.status, "loaded", "document.fonts.status should have status \"loaded\" (TEST 39)");
 
-    all[0].load();
-    is(document.fonts.status, "loading", "document.fonts.status should have status \"loading\" after first font loading (TEST 39)");
+        all[0].load();
+        is(document.fonts.status, "loading", "document.fonts.status should have status \"loading\" after first font loading (TEST 39)");
 
-    return document.fonts.ready
-      .then(function() {
+        return document.fonts.ready
+      }).then(function() {
         is(document.fonts.status, "loaded", "document.fonts.status should have status \"loaded\" after first font loaded (TEST 39)");
         is(all[0].status, "loaded", "first FontFace should have status \"loaded\" (TEST 39)");
         is(all[1].status, "unloaded", "second FontFace should have status \"unloaded\" (TEST 39)");
 
         all[1].load();
         is(document.fonts.status, "loading", "document.fonts.status should have status \"loading\" after second font loading (TEST 39)");
 
         return document.fonts.ready;
       }).then(function() {
+        return awaitEvents;
+      }).then(function() {
         is(document.fonts.status, "loaded", "document.fonts.status should have status \"loaded\" after second font loaded (TEST 39)");
         is(all[1].status, "loaded", "second FontFace should have status \"loaded\" (TEST 39)");
 
         is(events.length, 2, "should receive two events (TEST 39)");
 
         is(events[0].type, "loadingdone", "first event should be \"loadingdone\" (TEST 39)");
         is(events[0].fontfaces.length, 1, "first event should have 1 FontFace (TEST 39)");
         is(events[0].fontfaces[0], all[0], "first event should have the first FontFace");