Bug 801176 - part4-v2: Mochitest for adding 2d offscreen. r=mtseng
authorvincentliu <vliu@mozilla.com>
Fri, 04 Mar 2016 15:23:20 +0800
changeset 336835 c090dc98c670430e2dd99bd139fabe1b094f8582
parent 336834 fc509e59a0cd5a3537914158fada88c9cd1033a6
child 336836 0fb279e041e14f05a1a1dd9fed8eb00b46f16d90
push id12189
push usercku@mozilla.com
push dateFri, 04 Mar 2016 07:52:22 +0000
reviewersmtseng
bugs801176, 100644
milestone47.0a1
Bug 801176 - part4-v2: Mochitest for adding 2d offscreen. r=mtseng --- dom/canvas/test/mochitest.ini | 2 +- dom/canvas/test/offscreencanvas.js | 155 ++++++++++++--------- .../test/offscreencanvas_serviceworker_inner.html | 52 +++++-- .../test_offscreencanvas_basic_operations.html | 80 +++++++++++ .../test/test_offscreencanvas_basic_webgl.html | 62 --------- .../test_offscreencanvas_dynamic_fallback.html | 72 ++++++---- dom/canvas/test/test_offscreencanvas_many.html | 40 +++++- dom/canvas/test/test_offscreencanvas_neuter.html | 42 +++--- .../test/test_offscreencanvas_serviceworker.html | 8 +- .../test/test_offscreencanvas_sharedworker.html | 40 ++++-- .../test/test_offscreencanvas_sizechange.html | 67 +++++++-- .../test/test_offscreencanvas_subworker.html | 98 +++++++------ dom/canvas/test/test_offscreencanvas_toblob.html | 52 ++++--- .../test/test_offscreencanvas_toimagebitmap.html | 77 +++++----- 14 files changed, 530 insertions(+), 317 deletions(-) create mode 100644 dom/canvas/test/test_offscreencanvas_basic_operations.html delete mode 100644 dom/canvas/test/test_offscreencanvas_basic_webgl.html
dom/canvas/test/mochitest.ini
dom/canvas/test/offscreencanvas.js
dom/canvas/test/offscreencanvas_serviceworker_inner.html
dom/canvas/test/test_offscreencanvas_basic_operations.html
dom/canvas/test/test_offscreencanvas_basic_webgl.html
dom/canvas/test/test_offscreencanvas_dynamic_fallback.html
dom/canvas/test/test_offscreencanvas_many.html
dom/canvas/test/test_offscreencanvas_neuter.html
dom/canvas/test/test_offscreencanvas_serviceworker.html
dom/canvas/test/test_offscreencanvas_sharedworker.html
dom/canvas/test/test_offscreencanvas_sizechange.html
dom/canvas/test/test_offscreencanvas_subworker.html
dom/canvas/test/test_offscreencanvas_toblob.html
dom/canvas/test/test_offscreencanvas_toimagebitmap.html
--- a/dom/canvas/test/mochitest.ini
+++ b/dom/canvas/test/mochitest.ini
@@ -288,17 +288,17 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_createPattern_broken.html]
 [test_setlinedash.html]
 skip-if = (e10s && debug && os == 'win')
 [test_filter.html]
 [test_offscreencanvas_toblob.html]
 tags = offscreencanvas
 [test_offscreencanvas_toimagebitmap.html]
 tags = offscreencanvas
-[test_offscreencanvas_basic_webgl.html]
+[test_offscreencanvas_basic_operations.html]
 tags = offscreencanvas
 [test_offscreencanvas_dynamic_fallback.html]
 tags = offscreencanvas
 skip-if = (os == 'mac' && os_version == '10.6')
 [test_offscreencanvas_sharedworker.html]
 tags = offscreencanvas
 skip-if = (os == 'mac' && os_version == '10.6')
 [test_offscreencanvas_serviceworker.html]
--- a/dom/canvas/test/offscreencanvas.js
+++ b/dom/canvas/test/offscreencanvas.js
@@ -1,12 +1,14 @@
 /* WebWorker for test_offscreencanvas_*.html */
 (function(){
 
 var port = null;
+var INIT_CONST_CANVAS_SIZE = 64;
+var COUNT_FOR_SIZE_CHANGE = 3;
 
 function isInWorker() {
   try {
     return !(self instanceof Window);
   } catch (e) {
     return true;
   }
 }
@@ -30,28 +32,63 @@ function ok(expect, msg) {
 function finish() {
   postMessageGeneral({type: "finish"});
 }
 
 function drawCount(count) {
   postMessageGeneral({type: "draw", count: count});
 }
 
-function sendBlob(blob) {
-  postMessageGeneral({type: "blob", blob: blob});
+function sendBlob(canvasType, blob) {
+  postMessageGeneral({type: "blob", canvasType: canvasType, blob: blob});
 }
 
 function sendImageBitmap(img) {
   if (port) {
     port.postMessage({type: "imagebitmap", bitmap: img});
   } else {
     postMessage({type: "imagebitmap", bitmap: img});
   }
 }
 
+function sendImageBitmapWithSize(img, size) {
+  postMessage({type: "imagebitmapwithsize", bitmap: img, size: size});
+}
+//--------------------------------------------------------------------
+// Canvas 2D Drawing Functions
+//--------------------------------------------------------------------
+function createDrawFunc2D(canvas) {
+  var context2d;
+
+  try {
+    context2d = canvas.getContext("2d");
+  } catch (e) {}
+
+  if (!context2d) {
+    ok(false, "Canvas 2D is unavailable");
+    return null;
+  }
+
+  return function(prefix, needCommitFrame) {
+    if (prefix) {
+      prefix = "[" + prefix + "] ";
+    } else {
+      prefix = "";
+    }
+
+    context2d.rect(0, 0, canvas.width, canvas.height);
+    context2d.fillStyle = "#00FF00";
+    context2d.fill();
+    if (needCommitFrame) {
+      context2d.commit();
+      ok(true, prefix + 'Frame is committed');
+    }
+  };
+}
+
 //--------------------------------------------------------------------
 // WebGL Drawing Functions
 //--------------------------------------------------------------------
 function createDrawFunc(canvas) {
   var gl;
 
   try {
     gl = canvas.getContext("experimental-webgl");
@@ -177,134 +214,116 @@ function createDrawFunc(canvas) {
     if (needCommitFrame) {
       gl.commit();
     }
     checkGLError(prefix);
   };
 }
 
 /* entry point */
-function entryFunction(testStr, subtests, offscreenCanvas) {
-  var test = testStr;
+function entryFunction(canvasTypeStr, testTypeStr, subtests, offscreenCanvas) {
+  var canvasType = canvasTypeStr;
+  var testType = testTypeStr;
   var canvas = offscreenCanvas;
-  if (test == "webgl_imagebitmap") {
-    canvas = new OffscreenCanvas(64, 64);
+  if ((testType == "imagebitmap") || (testType == "changesize")) {
+    canvas = new OffscreenCanvas(INIT_CONST_CANVAS_SIZE, INIT_CONST_CANVAS_SIZE);
   }
 
-  if (test != "subworker") {
+  if (testType != "subworker") {
     ok(canvas, "Canvas successfully transfered to worker");
     ok(canvas.getContext, "Canvas has getContext");
 
-    ok(canvas.width == 64, "OffscreenCanvas width should be 64");
-    ok(canvas.height == 64, "OffscreenCanvas height should be 64");
+    ok(canvas.width == INIT_CONST_CANVAS_SIZE,
+       "OffscreenCanvas width should be " + INIT_CONST_CANVAS_SIZE);
+    ok(canvas.height == INIT_CONST_CANVAS_SIZE,
+       "OffscreenCanvas height should be " + INIT_CONST_CANVAS_SIZE);
   }
 
   var draw;
+  if (testType != "subworker") {
+    if (canvasType == "2d") {
+      draw = createDrawFunc2D(canvas);
+    } else if (canvasType == "webgl") {
+      draw = createDrawFunc(canvas);
+    } else {
+      ok(false, "Unexpected canvasType");
+    }
 
-  //------------------------------------------------------------------------
-  // Basic WebGL test
-  //------------------------------------------------------------------------
-  if (test == "webgl") {
-    draw = createDrawFunc(canvas);
     if (!draw) {
       finish();
       return;
     }
-
+  }
+  //------------------------------------------------------------------------
+  // Basic test
+  //------------------------------------------------------------------------
+  if (testType == "basic") {
     var count = 0;
     var iid = setInterval(function() {
       if (count++ > 20) {
         clearInterval(iid);
         ok(true, "Worker is done");
         finish();
         return;
       }
       draw("loop " +count, true);
     }, 0);
   }
   //------------------------------------------------------------------------
   // Test dynamic fallback
   //------------------------------------------------------------------------
-  else if (test == "webgl_fallback") {
-    draw = createDrawFunc(canvas);
-    if (!draw) {
-      return;
-    }
-
+  else if (testType == "fallback") {
     var count = 0;
     var iid = setInterval(function() {
       ++count;
       draw("loop " + count, true);
       drawCount(count);
     }, 0);
   }
   //------------------------------------------------------------------------
   // Test toBlob
   //------------------------------------------------------------------------
-  else if (test == "webgl_toblob") {
-    draw = createDrawFunc(canvas);
-    if (!draw) {
-      return;
-    }
-
+  else if (testType == "toblob") {
     draw("", false);
     canvas.toBlob().then(function(blob) {
-      sendBlob(blob);
+      sendBlob(canvasType, blob);
     });
   }
   //------------------------------------------------------------------------
   // Test toImageBitmap
   //------------------------------------------------------------------------
-  else if (test == "webgl_imagebitmap") {
-    draw = createDrawFunc(canvas);
-    if (!draw) {
-      return;
-    }
-
+  else if (testType == "imagebitmap") {
     draw("", false);
     var imgBitmap = canvas.transferToImageBitmap();
     sendImageBitmap(imgBitmap);
+    finish();
   }
   //------------------------------------------------------------------------
   // Canvas Size Change from Worker
   //------------------------------------------------------------------------
-  else if (test == "webgl_changesize") {
-    draw = createDrawFunc(canvas);
-    if (!draw) {
-      finish();
-      return;
-    }
-
-    draw("64x64", true);
-
-    setTimeout(function() {
-      canvas.width = 128;
-      canvas.height = 128;
-      draw("Increased to 128x128", true);
+  else if (testType == "changesize") {
+    var count = 0;
+    var iid = setInterval(function() {
+      if (count++ > COUNT_FOR_SIZE_CHANGE) {
+        finish();
+        clearInterval(iid);
+        return;
+      }
 
-      setTimeout(function() {
-        canvas.width = 32;
-        canvas.width = 32;
-        draw("Decreased to 32x32", true);
-
-        setTimeout(function() {
-          canvas.width = 64;
-          canvas.height = 64;
-          draw("Increased to 64x64", true);
-
-          ok(true, "Worker is done");
-          finish();
-        }, 0);
-      }, 0);
+      canvas.width = INIT_CONST_CANVAS_SIZE * count;
+      canvas.height = INIT_CONST_CANVAS_SIZE * count;
+      draw("loop " + count, true);
+      var imgBitmap = canvas.transferToImageBitmap();
+      sendImageBitmapWithSize(imgBitmap, INIT_CONST_CANVAS_SIZE * count);
     }, 0);
   }
   //------------------------------------------------------------------------
   // Using OffscreenCanvas from sub workers
   //------------------------------------------------------------------------
-  else if (test == "subworker") {
+  else if (testType == "subworker") {
     /* subworker tests take a list of tests to run on children */
     var stillRunning = 0;
     subtests.forEach(function (subtest) {
       ++stillRunning;
       var subworker = new Worker('offscreencanvas.js');
       subworker.onmessage = function(evt) {
         /* report finish to parent when all children are finished */
         if (evt.data.type == "finish") {
@@ -315,43 +334,45 @@ function entryFunction(testStr, subtests
           }
           return;
         }
         /* relay all other messages to parent */
         postMessage(evt.data);
       };
 
       var findTransferables = function(t) {
-        if (t.test == "subworker") {
+        if (t.testType == "subworker") {
           var result = [];
-          t.subtests.forEach(function(test) {
-            result = result.concat(findTransferables(test));
+          t.subtests.forEach(function(testType) {
+            result = result.concat(findTransferables(testType));
           });
 
           return result;
         } else {
           return [t.canvas];
         }
       };
 
       subworker.postMessage(subtest, findTransferables(subtest));
     });
   }
 };
 
 onmessage = function(evt) {
   port = evt.ports[0];
-  entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas);
+  entryFunction(evt.data.canvasType, evt.data.testType, evt.data.subtests,
+                evt.data.canvas);
 };
 
 onconnect = function(evt) {
   port = evt.ports[0];
 
   port.addEventListener('message', function(evt) {
-    entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas);
+    entryFunction(evt.data.canvasType,  evt.data.testType, evt.data.subtests,
+                  evt.data.canvas);
   });
 
   port.start();
 };
 
 if (!isInWorker()) {
   window.entryFunction = entryFunction;
 }
--- a/dom/canvas/test/offscreencanvas_serviceworker_inner.html
+++ b/dom/canvas/test/offscreencanvas_serviceworker_inner.html
@@ -1,32 +1,62 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <title>WebGL in OffscreenCanvas</title>
 </head>
 <body>
-<canvas id="c" width="64" height="64"></canvas>
 <script>
 function ok(expect, msg) {
   parent.postMessage({type: "test", result: !!expect, name: msg}, "*");
 }
-
-var htmlCanvas = document.getElementById("c");
+function countTest(count) {
+  parent.postMessage({type: "countTest", count: count}, "*");
+}
 
-ok(htmlCanvas, "Should have HTML canvas element");
+function createCanvas() {
+  countTest(1);
+  var htmlCanvas = document.createElement('canvas');
+  ok(htmlCanvas, "Should have HTML canvas element");
+  ok(htmlCanvas.transferControlToOffscreen,
+     "HTMLCanvasElement has transferControlToOffscreen function");
+  htmlCanvas.width = 64;
+  htmlCanvas.height = 64;
+  document.body.appendChild(htmlCanvas);
+  return htmlCanvas;
+}
 
-var messageChannel = new MessageChannel();
-messageChannel.port1.onmessage = function(evt) {
-  parent.postMessage(evt.data, "*");
+function transferCtrlToOffscreen(canvas) {
+  var offscreencanvas = canvas.transferControlToOffscreen();
+  ok(offscreencanvas, "Expected transferControlToOffscreen to succeed");
+  return offscreencanvas;
 }
 
-ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
+function CreateMessagChannel () {
+  var msgChannel = new MessageChannel();
+  msgChannel.port1.onmessage = function(evt) {
+    parent.postMessage(evt.data, "*");
+  }
+  return msgChannel;
+}
 
-var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
+var offscreen2dCanvas = transferCtrlToOffscreen(createCanvas());
+var msgChannel2d = CreateMessagChannel();
+var offscreenWebGLCanvas = transferCtrlToOffscreen(createCanvas());
+var msgChannelwebgl = CreateMessagChannel();
 
 navigator.serviceWorker.ready.then(function() {
-  navigator.serviceWorker.controller.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas, messageChannel.port2]);
+  navigator.serviceWorker.controller.postMessage({canvasType: '2d',
+                                                  testType: 'basic',
+                                                  canvas: offscreen2dCanvas},
+                                                  [offscreen2dCanvas,
+                                                   msgChannel2d.port2]);
+});
+navigator.serviceWorker.ready.then(function() {
+  navigator.serviceWorker.controller.postMessage({canvasType: 'webgl',
+                                                  testType: 'basic',
+                                                  canvas: offscreenWebGLCanvas},
+                                                  [offscreenWebGLCanvas,
+                                                   msgChannelwebgl.port2]);
 });
 </script>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/test_offscreencanvas_basic_operations.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>WebGL in OffscreenCanvas</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<canvas id="c-ref" width="64" height="64"></canvas>
+<script>
+
+SimpleTest.waitForExplicitFinish();
+
+function createCanvas() {
+  var htmlCanvas = document.createElement('canvas');
+  htmlCanvas.width = 64;
+  htmlCanvas.height = 64;
+  document.body.appendChild(htmlCanvas);
+  return htmlCanvas;
+}
+
+function testToDataURL(canvas, test) {
+  // testing toDataURL
+  // Fill c-ref with green color.
+  var c = document.getElementById("c-ref");
+  var ctx = c.getContext("2d");
+  ctx.rect(0, 0, 64, 64);
+  ctx.fillStyle = "#00FF00";
+  ctx.fill();
+  ok(c.toDataURL() == canvas.toDataURL(), "[" + test + "]" +
+     "toDataURL should return a 64x64 green square");
+}
+
+function runTest() {
+  var stillRunning = 0;
+
+  var startWorker = function(canvas, canvasType) {
+    stillRunning++;
+    var worker = new Worker("offscreencanvas.js");
+
+    ok(canvas, "[" + canvasType + "]" + "Should have HTML canvas element");
+    ok(worker, "[" + canvasType + "]" + "Web worker successfully created");
+
+    worker.onmessage = function(evt) {
+      var msg = evt.data || {};
+      if (msg.type == "test") {
+        ok(msg.result, "[" + canvasType + "]" + msg.name);
+      }
+      if (msg.type == "finish") {
+        testToDataURL(canvas, canvasType);
+        worker.terminate();
+        if (--stillRunning == 0) {
+          SimpleTest.finish();
+        }
+      }
+    }
+
+    ok(canvas.transferControlToOffscreen, "[" + canvasType + "]" +
+       "HTMLCanvasElement has transferControlToOffscreen function");
+
+    var offscreenCanvas = canvas.transferControlToOffscreen();
+    ok(offscreenCanvas, "[" + canvasType + "]" +
+       "Expected transferControlToOffscreen to succeed");
+
+    worker.postMessage({canvasType: canvasType, testType: 'basic',
+                        canvas: offscreenCanvas}, [offscreenCanvas]);
+  }
+
+  startWorker(createCanvas(), '2d');
+  startWorker(createCanvas(), 'webgl');
+}
+
+SpecialPowers.pushPrefEnv({'set': [
+  ['gfx.offscreencanvas.enabled', true],
+  ['webgl.force-enabled', true],
+]}, runTest);
+
+</script>
+</body>
+</html>
deleted file mode 100644
--- a/dom/canvas/test/test_offscreencanvas_basic_webgl.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>WebGL in OffscreenCanvas</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<canvas id="c" width="64" height="64"></canvas>
-<canvas id="c-ref" width="64" height="64"></canvas>
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-function testToDataURL() {
-  // testing toDataURL
-  // Fill c-ref with green color.
-  var c = document.getElementById("c-ref");
-  var ctx = c.getContext("2d");
-  ctx.rect(0, 0, 64, 64);
-  ctx.fillStyle = "#00FF00";
-  ctx.fill();
-  var htmlCanvas = document.getElementById("c");
-  ok(c.toDataURL() == htmlCanvas.toDataURL(), "toDataURL should return a 64x64 green square");
-}
-
-function runTest() {
-
-  var htmlCanvas = document.getElementById("c");
-  var worker = new Worker("offscreencanvas.js");
-
-  ok(htmlCanvas, "Should have HTML canvas element");
-  ok(worker, "Web worker successfully created");
-
-  worker.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "test") {
-      ok(msg.result, msg.name);
-    }
-    if (msg.type == "finish") {
-      testToDataURL();
-      worker.terminate();
-      SimpleTest.finish();
-    }
-  }
-
-  ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
-
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-  ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
-
-  worker.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas]);
-}
-
-SpecialPowers.pushPrefEnv({'set': [
-  ['gfx.offscreencanvas.enabled', true],
-  ['webgl.force-enabled', true],
-]}, runTest);
-
-</script>
-</body>
-</html>
--- a/dom/canvas/test/test_offscreencanvas_dynamic_fallback.html
+++ b/dom/canvas/test/test_offscreencanvas_dynamic_fallback.html
@@ -29,52 +29,70 @@ function getRefSnapshot(initWithMask) {
   ctx.rect(0, 0, 64, 64);
   ctx.fillStyle = "#00FF00";
   ctx.fill();
   var result = snapshotWindow(window);
   document.body.removeChild(refCanvas);
   return result;
 }
 
-function runTest(initWithMask) {
-  var htmlCanvas = createCanvas(initWithMask);
-  var worker = new Worker("offscreencanvas.js");
+function runTest() {
+  var startWorker = function(canvas, canvasType, testType, initWithMask) {
+    var canvas = createCanvas(initWithMask);
+    var worker = new Worker("offscreencanvas.js");
+
+    ok(canvas.transferControlToOffscreen, "[" + canvasType + "]" +
+       "HTMLCanvasElement has transferControlToOffscreen function");
+
+    var offscreenCanvas = canvas.transferControlToOffscreen();
+    ok(offscreenCanvas, "[" + canvasType + "]" +
+       "Expected transferControlToOffscreen to succeed");
+
+    worker.postMessage({canvasType: canvasType, testType: testType,
+                        canvas: offscreenCanvas}, [offscreenCanvas]);
 
-  worker.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "draw") {
-      if (msg.count === 10) {
-        // Change the fallback state dynamically when drawing count reaches 10.
-        if (initWithMask) {
-          htmlCanvas.style.mask = "";
-        } else {
-          htmlCanvas.style.mask = "url('offscreencanvas_mask.svg#fade_mask_both')";
+    return new Promise(function(resolved) {
+      worker.onmessage = function(evt) {
+        var msg = evt.data || {};
+        if (msg.type == "test") {
+          ok(msg.result, "[" + canvasType + "]" + msg.name);
         }
-      } else if (msg.count === 20) {
-        var snapshotFallback = snapshotWindow(window);
-        worker.terminate();
-        document.body.removeChild(htmlCanvas);
+        if (msg.type == "draw") {
+          if (msg.count === 10) {
+            // Change the fallback state dynamically when drawing count reaches 10.
+            if (initWithMask) {
+              canvas.style.mask = "";
+            } else {
+              canvas.style.mask = "url('offscreencanvas_mask.svg#fade_mask_both')";
+            }
+          } else if (msg.count === 20) {
+            var snapshotFallback = snapshotWindow(window);
+            worker.terminate();
+            document.body.removeChild(canvas);
 
-        var results = compareSnapshots(snapshotFallback, getRefSnapshot(initWithMask), true);
-        ok(results[0], "after dynamic fallback, screenshots should be the same");
+            var results = compareSnapshots(snapshotFallback,
+                          getRefSnapshot(initWithMask), true);
+            ok(results[0], "[" + canvasType + "]" +
+               "after dynamic fallback, screenshots should be the same");
 
-        if (initWithMask) {
-          SimpleTest.finish();
-        } else {
-          runTest(true);
+            resolved();
+          }
         }
       }
-    }
+    });
   }
 
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-
-  worker.postMessage({test: 'webgl_fallback', canvas: offscreenCanvas}, [offscreenCanvas]);
+  startWorker(createCanvas(false), '2d', 'fallback', false).then(function () {
+    startWorker(createCanvas(true), '2d', 'fallback', true).then(function () {
+      startWorker(createCanvas(false), 'webgl', 'fallback', false).then(function () {
+        startWorker(createCanvas(true), 'webgl', 'fallback', true).then(function () {
+          SimpleTest.finish();
+  })})})});
 }
 
 SpecialPowers.pushPrefEnv({'set': [
   ['gfx.offscreencanvas.enabled', true],
   ['webgl.force-enabled', true],
-]}, runTest.bind(false));
+]}, runTest);
 
 </script>
 </body>
 </html>
--- a/dom/canvas/test/test_offscreencanvas_many.html
+++ b/dom/canvas/test/test_offscreencanvas_many.html
@@ -6,59 +6,87 @@
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 </head>
 <body>
 <!--
   This test needs several workers run offscreen canvas simultaneously.
   So we choose 8 workers, 4 of them run basic webgl drawing test and
   others run size changing test.
 -->
+<canvas id="c1" width="64" height="64"></canvas>
+<canvas id="c-ref" width="64" height="64"></canvas>
 <script>
 
 SimpleTest.waitForExplicitFinish();
 
 function createCanvas() {
   var htmlCanvas = document.createElement('canvas');
   htmlCanvas.width = 64;
   htmlCanvas.height = 64;
   document.body.appendChild(htmlCanvas);
   return htmlCanvas;
 }
 
 function runTest() {
   var stillRunning = 0;
 
-  var startWorker = function(canvas, test) {
+  var startWorker = function(canvas, canvasType, testType) {
     stillRunning++;
     var worker = new Worker("offscreencanvas.js");
 
     worker.onmessage = function(evt) {
       var msg = evt.data || {};
       if (msg.type == "test") {
-        ok(msg.result, msg.name);
+        ok(msg.result, "[" + canvasType + "]" + msg.name);
+      }
+      if (msg.type == "imagebitmapwithsize") {
+        // Fill c-ref with green color.
+        var c = document.getElementById("c-ref");
+        var ctx = c.getContext("2d");
+        c.width = msg.size;
+        c.height = msg.size;
+        ctx.rect(0, 0, c.width, c.height);
+        ctx.fillStyle = "#00FF00";
+        ctx.fill();
+
+        // The ownership of msg.bitmap should be transferred to canvas when we
+        // called transferImageBitmap. So we test if the ownership is actually
+        // transferred here.
+        var htmlCanvas = document.getElementById("c1");
+        htmlCanvas.width = msg.size;
+        htmlCanvas.height = msg.size;
+        var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
+        bitmapRenderer.transferImageBitmap(msg.bitmap);
+        ok(c.toDataURL() == htmlCanvas.toDataURL(), "[" + canvasType + "]" +
+           "toDataURL should return a " + msg.size + "x" + msg.size +
+           " green square");
       }
       if (msg.type == "finish") {
         worker.terminate();
-        if (--stillRunning == 0)
+        if (--stillRunning == 0) {
           SimpleTest.finish();
+        }
       }
     }
 
     var offscreenCanvas = canvas.transferControlToOffscreen();
-    worker.postMessage({test: test, canvas: offscreenCanvas}, [offscreenCanvas]);
+    worker.postMessage({canvasType: canvasType, testType: testType,
+                        canvas: offscreenCanvas}, [offscreenCanvas]);
   }
 
   /* create 4 workers that do the regular drawing test and 4 workers
      that do the size change test */
   for (var i = 0; i < 4; i++) {
-    startWorker(createCanvas(), 'webgl');
+    startWorker(createCanvas(), '2d', 'basic');
+    startWorker(createCanvas(), 'webgl', 'basic');
   }
 
   for (var i = 0; i < 4; i++) {
-    startWorker(createCanvas(), 'webgl_changesize');
+    startWorker(createCanvas(), '2d', 'changesize');
+    startWorker(createCanvas(), 'webgl', 'changesize');
   }
 }
 
 SpecialPowers.pushPrefEnv({'set': [
   ['gfx.offscreencanvas.enabled', true],
   ['webgl.force-enabled', true]
 ]}, runTest);
 
--- a/dom/canvas/test/test_offscreencanvas_neuter.html
+++ b/dom/canvas/test/test_offscreencanvas_neuter.html
@@ -29,42 +29,48 @@ function runTest() {
   SimpleTest.doesThrow(
     function() { htmlCanvas.width = 128; },
     "Can't change html canvas' width after transferControlToOffscreen");
 
   SimpleTest.doesThrow(
     function() { htmlCanvas.height = 128; },
     "Can't change html canvas' height after transferControlToOffscreen");
 
-  ok(!htmlCanvas.getContext("2d"), "Can't getContext after transferControlToOffscreen");
-  ok(!htmlCanvas.getContext("webgl"), "Can't getContext after transferControlToOffscreen");
-  ok(!htmlCanvas.getContext("webgl2"), "Can't getContext after transferControlToOffscreen");
+  ok(!htmlCanvas.getContext("2d"), "Can't get 2d Context after transferControlToOffscreen");
+  ok(!htmlCanvas.getContext("webgl"), "Can't get webgl Context after transferControlToOffscreen");
+  ok(!htmlCanvas.getContext("webgl2"), "Can't get webgl2 Context after transferControlToOffscreen");
+  ok(!htmlCanvas.getContext("bitmaprenderer"),
+                            "Can't get bitmaprenderer Context after transferControlToOffscreen");
 
   worker.postMessage(offscreenCanvas, [offscreenCanvas]);
 
   /* check parent offscreencanvas is neutered after being transfered */
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.width = 128; },
-    "Can't change transfered worker canvas width");
+  SimpleTest.doesThrow(function() {
+    offscreenCanvas.width = 128;
+  }, "Can't change transfered worker canvas width");
 
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.height = 128; },
-    "Can't change transfered worker canvas height");
+  SimpleTest.doesThrow(function() {
+    offscreenCanvas.height = 128;
+  }, "Can't change transfered worker canvas height");
+
+  SimpleTest.doesThrow(function() {
+    offscreenCanvas.getContext("2d");
+  }, "Can't get 2d Context on transfered worker canvas");
 
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.getContext("2d") },
-    "Can't getContext on transfered worker canvas");
+  SimpleTest.doesThrow(function() {
+    offscreenCanvas.getContext("webgl");
+  }, "Can't get webgl Context on transfered worker canvas");
 
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.getContext("webgl") },
-    "Can't getContext on transfered worker canvas");
+  SimpleTest.doesThrow(function() {
+    offscreenCanvas.getContext("webgl2");
+  }, "Can't get webgl2 Context on transfered worker canvas");
 
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.getContext("webgl2") },
-    "Can't getContext on transfered worker canvas");
+  SimpleTest.doesThrow(function() {
+    offscreenCanvas.getContext("bitmaprenderer");
+  }, "Can't get bitmaprenderer Context on transfered worker canvas");
 
   // Transfer a neutered offscreencanvas should be ok.
   worker.postMessage(offscreenCanvas, [offscreenCanvas]);
 
   worker.terminate();
   SimpleTest.finish();
 }
 
--- a/dom/canvas/test/test_offscreencanvas_serviceworker.html
+++ b/dom/canvas/test/test_offscreencanvas_serviceworker.html
@@ -6,26 +6,32 @@
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 </head>
 <body>
 <script>
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
+  var stillRunning = 0;
   var registration;
 
   window.onmessage = function(evt) {
     var msg = evt.data || {};
     if (msg.type == "test") {
       ok(msg.result, msg.name);
     }
+    if (msg.type == "countTest") {
+      stillRunning++;
+    }
     if (msg.type == "finish") {
       registration.unregister().then(function() {
-        SimpleTest.finish();
+        if (--stillRunning == 0) {
+          SimpleTest.finish();
+        }
       });
     }
   }
 
   navigator.serviceWorker.register('offscreencanvas.js', { scope: "."})
     // Wait until the service worker is active.
     .then(function(swr) {
       registration = swr;
--- a/dom/canvas/test/test_offscreencanvas_sharedworker.html
+++ b/dom/canvas/test/test_offscreencanvas_sharedworker.html
@@ -1,43 +1,57 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <title>WebGL in OffscreenCanvas</title>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 </head>
 <body>
-<canvas id="c" width="64" height="64"></canvas>
 <script>
 
 SimpleTest.waitForExplicitFinish();
 
-function runTest() {
-
-  var htmlCanvas = document.getElementById("c");
-  var worker = new SharedWorker("offscreencanvas.js");
-
+function createCanvas() {
+  var htmlCanvas = document.createElement('canvas');
   ok(htmlCanvas, "Should have HTML canvas element");
-  ok(worker, "Web worker successfully created");
-
-  ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
+  ok(htmlCanvas.transferControlToOffscreen,
+     "HTMLCanvasElement has transferControlToOffscreen function");
+  htmlCanvas.width = 64;
+  htmlCanvas.height = 64;
+  document.body.appendChild(htmlCanvas);
+  return htmlCanvas;
+}
 
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-  ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
+function transferCtrlToOffscreen(canvas) {
+  var offscreencanvas = canvas.transferControlToOffscreen();
+  ok(offscreencanvas, "Expected transferControlToOffscreen to succeed");
+  return offscreencanvas;
+}
 
-  worker.port.start();
+function testShareWorker(worker, canvasType) {
+  var offscreenCanvas = transferCtrlToOffscreen(createCanvas());
 
   // We don't support transferring OffscreenCanvas via shared worker.
   SimpleTest.doesThrow(
     function() {
-      worker.port.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas]);
+      worker.port.postMessage({canvasType: canvasType, testType: 'basic',
+                               canvas: offscreenCanvas}, [offscreenCanvas]);
     },
     "OffscreenCanvas cannot transfer to shared worker"
   );
+}
+
+function runTest() {
+  var worker = new SharedWorker("offscreencanvas.js");
+  ok(worker, "Web worker successfully created");
+  worker.port.start();
+
+  testShareWorker(worker, '2d');
+  testShareWorker(worker, 'webgl');
 
   SimpleTest.finish();
 }
 
 SpecialPowers.pushPrefEnv({'set': [
   ['gfx.offscreencanvas.enabled', true],
   ['webgl.force-enabled', true],
 ]}, runTest);
--- a/dom/canvas/test/test_offscreencanvas_sizechange.html
+++ b/dom/canvas/test/test_offscreencanvas_sizechange.html
@@ -1,39 +1,80 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <title>WebGL in OffscreenCanvas</title>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 </head>
 <body>
-<canvas id="c" width="64" height="64"></canvas>
+<canvas id="c1" width="64" height="64"></canvas>
+<canvas id="c-ref" width="64" height="64"></canvas>
 <script>
 
 SimpleTest.waitForExplicitFinish();
 
-function runTest() {
+function createCanvas() {
+  var htmlCanvas = document.createElement('canvas');
+  htmlCanvas.width = 64;
+  htmlCanvas.height = 64;
+  document.body.appendChild(htmlCanvas);
+  return htmlCanvas;
+}
 
-  var htmlCanvas = document.getElementById("c");
-  var worker = new Worker("offscreencanvas.js");
+function runTest() {
+  var stillRunning = 0;
+
+  var startWorker = function(canvasType) {
+    stillRunning++;
+    var worker = new Worker("offscreencanvas.js");
+    ok(worker, "[" + canvasType + "]" + "Web worker successfully created");
 
-  worker.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "test") {
-      ok(msg.result, msg.name);
+    worker.onmessage = function(evt) {
+      var msg = evt.data || {};
+      if (msg.type == "test") {
+        ok(msg.result, "[" + canvasType + "]" + msg.name);
+      }
+      if (msg.type == "imagebitmapwithsize") {
+        // Fill c-ref with green color.
+        var c = document.getElementById("c-ref");
+        var ctx = c.getContext("2d");
+        c.width = msg.size;
+        c.height = msg.size;
+        ctx.rect(0, 0, c.width, c.height);
+        ctx.fillStyle = "#00FF00";
+        ctx.fill();
+
+        // The ownership of msg.bitmap should be transferred to canvas when we
+        // called transferImageBitmap. So we test if the ownership is actually
+        // transferred here.
+        var htmlCanvas = document.getElementById("c1");
+        htmlCanvas.width = msg.size;
+        htmlCanvas.height = msg.size;
+        var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
+        bitmapRenderer.transferImageBitmap(msg.bitmap);
+        console.log("rawm = " + c.toDataURL());
+        console.log("raww = " + htmlCanvas.toDataURL());
+        ok(c.toDataURL() == htmlCanvas.toDataURL(), "[" + canvasType + "]" +
+           "toDataURL should return a " + msg.size + "x" + msg.size +
+           " green square");
+      }
+      if (msg.type == "finish") {
+        worker.terminate();
+        if (--stillRunning == 0) {
+          SimpleTest.finish();
+        }
+      }
     }
-    if (msg.type == "finish") {
-      worker.terminate();
-      SimpleTest.finish();
-    }
+
+    worker.postMessage({canvasType: canvasType, testType: 'changesize'});
   }
 
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-  worker.postMessage({test: 'webgl_changesize', canvas: offscreenCanvas}, [offscreenCanvas]);
+  startWorker('2d');
+  startWorker('webgl');
 }
 
 SpecialPowers.pushPrefEnv({'set': [
   ['gfx.offscreencanvas.enabled', true],
   ['webgl.force-enabled', true],
 ]}, runTest);
 
 </script>
--- a/dom/canvas/test/test_offscreencanvas_subworker.html
+++ b/dom/canvas/test/test_offscreencanvas_subworker.html
@@ -19,70 +19,78 @@ function createCanvas() {
   var htmlCanvas = document.createElement('canvas');
   htmlCanvas.width = 64;
   htmlCanvas.height = 64;
   document.body.appendChild(htmlCanvas);
   return htmlCanvas.transferControlToOffscreen();
 }
 
 function runTest() {
+  var subworkerRunning = 0;
 
-  var worker = new Worker("offscreencanvas.js");
+  var startWorker = function(canvasType) {
+    subworkerRunning++;
+    var worker = new Worker("offscreencanvas.js");
+
+    worker.onmessage = function(evt) {
+      var msg = evt.data || {};
+      if (msg.type == "test") {
+        ok(msg.result, "[" + canvasType + "]" + msg.name);
+      }
+      if (msg.type == "finish") {
+        worker.terminate();
+        if (--subworkerRunning == 0) {
+          SimpleTest.finish();
+        }
+      }
+    }
+
+    var findTransferables = function(t) {
+      if (t.testType == "subworker") {
+        var result = [];
+        t.subtests.forEach(function(testType) {
+          result = result.concat(findTransferables(testType));
+        });
 
-  worker.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "test") {
-      ok(msg.result, msg.name);
-    }
-    if (msg.type == "finish") {
-      worker.terminate();
-      SimpleTest.finish();
-    }
+        return result;
+      } else {
+        return [t.canvas];
+      }
+    };
+
+    var testData =
+      {canvasType: canvasType, testType: 'subworker', subtests: [
+        {canvasType: canvasType, testType: 'basic', canvas: createCanvas()},
+        {canvasType: canvasType, testType: 'subworker', subtests: [
+          {canvasType: canvasType, testType: 'basic', canvas: createCanvas()},
+          {canvasType: canvasType, testType: 'changesize', canvas: createCanvas()},
+          {canvasType: canvasType, testType: 'basic', canvas: createCanvas()}
+        ]},
+        {canvasType: canvasType, testType: 'subworker', subtests: [
+          {canvasType: canvasType, testType: 'basic', canvas: createCanvas()},
+          {canvasType: canvasType, testType: 'changesize', canvas: createCanvas()},
+          {canvasType: canvasType, testType: 'subworker', subtests: [
+            {canvasType: canvasType, testType: 'changesize', canvas: createCanvas()},
+            {canvasType: canvasType, testType: 'basic', canvas: createCanvas()}
+          ]},
+          {canvasType: canvasType, testType: 'subworker', subtests: [
+            {canvasType: canvasType, testType: 'changesize', canvas: createCanvas()},
+            {canvasType: canvasType, testType: 'subworker', subtests: [
+              {canvasType: canvasType, testType: 'subworker', subtests: [
+                {canvasType: canvasType, testType: 'changesize', canvas: createCanvas()}
+              ]}
+            ]}
+          ]},
+        ]}
+      ]};
+    worker.postMessage(testData, findTransferables(testData));
   }
 
-  var findTransferables = function(t) {
-    if (t.test == "subworker") {
-      var result = [];
-      t.subtests.forEach(function(test) {
-        result = result.concat(findTransferables(test));
-      });
-
-      return result;
-    } else {
-      return [t.canvas];
-    }
-  };
-
-  var testData =
-    {test: 'subworker', subtests: [
-      {test: 'webgl', canvas: createCanvas()},
-      {test: 'subworker', subtests: [
-        {test: 'webgl', canvas: createCanvas()},
-        {test: 'webgl_changesize', canvas: createCanvas()},
-        {test: 'webgl', canvas: createCanvas()}
-      ]},
-      {test: 'subworker', subtests: [
-        {test: 'webgl', canvas: createCanvas()},
-        {test: 'webgl_changesize', canvas: createCanvas()},
-        {test: 'subworker', subtests: [
-          {test: 'webgl_changesize', canvas: createCanvas()},
-          {test: 'webgl', canvas: createCanvas()}
-        ]},
-        {test: 'subworker', subtests: [
-          {test: 'webgl_changesize', canvas: createCanvas()},
-          {test: 'subworker', subtests: [
-            {test: 'subworker', subtests: [
-              {test: 'webgl_changesize', canvas: createCanvas()}
-            ]}
-          ]}
-        ]},
-      ]}
-    ]};
-
-  worker.postMessage(testData, findTransferables(testData));
+  startWorker('2d');
+  startWorker('webgl');
 }
 
 SpecialPowers.pushPrefEnv({'set': [
   ['gfx.offscreencanvas.enabled', true],
   ['webgl.force-enabled', true],
 ]}, runTest);
 
 </script>
--- a/dom/canvas/test/test_offscreencanvas_toblob.html
+++ b/dom/canvas/test/test_offscreencanvas_toblob.html
@@ -2,88 +2,102 @@
 <html>
 <head>
 <title>WebGL in OffscreenCanvas</title>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
 <script src="offscreencanvas.js"></script>
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 </head>
 <body>
-<canvas id="c" width="64" height="64"></canvas>
-<canvas id="c-mt" width="64" height="64"></canvas>
 <canvas id="c-ref" width="64" height="64"></canvas>
 <script>
 
 SimpleTest.waitForExplicitFinish();
 
+function createCanvas() {
+  var htmlCanvas = document.createElement('canvas');
+  htmlCanvas.width = 64;
+  htmlCanvas.height = 64;
+  document.body.appendChild(htmlCanvas);
+  return htmlCanvas;
+}
+
+function TransferCtrlToOffscreen(canvas) {
+  ok(canvas, "Should have HTML canvas element");
+  ok(canvas.transferControlToOffscreen,
+     "HTMLCanvasElement has transferControlToOffscreen function");
+  return canvas.transferControlToOffscreen();
+}
+
 function testBlob(blob, callback) {
   // testing toBlob
   // Fill c-ref with green color.
   var c = document.getElementById("c-ref");
   var ctx = c.getContext("2d");
   ctx.rect(0, 0, 64, 64);
   ctx.fillStyle = "#00FF00";
   ctx.fill();
   var reader = new FileReader();
   reader.onload = function(e) {
-    ok(c.toDataURL() == e.target.result, "toBlob should return a 64x64 green square");
+    ok(c.toDataURL() == e.target.result,
+       "toBlob should return a 64x64 green square");
     callback();
   };
   reader.readAsDataURL(blob);
 }
 
 function runTestOnMainThread() {
-  var htmlCanvas = document.getElementById("c-mt");
-  ok(htmlCanvas, "Should have HTML canvas element");
 
   window.onmessage = function(evt) {
     var msg = evt.data || {};
     if (msg.type == "test") {
       ok(msg.result, msg.name);
     }
     if (msg.type == "blob") {
       testBlob(msg.blob, SimpleTest.finish);
     }
   }
 
-  ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
-
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
+  var offscreenCanvas = TransferCtrlToOffscreen(createCanvas());
   ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
-
-  entryFunction('webgl_toblob', '', offscreenCanvas);
+  entryFunction('webgl', 'toblob', '', offscreenCanvas);
 }
 
 function runTest() {
 
-  var htmlCanvas = document.getElementById("c");
   var worker = new Worker("offscreencanvas.js");
 
-  ok(htmlCanvas, "Should have HTML canvas element");
-  ok(worker, "Web worker successfully created");
-
   worker.onmessage = function(evt) {
     var msg = evt.data || {};
     if (msg.type == "test") {
       ok(msg.result, msg.name);
     }
     if (msg.type == "blob") {
       testBlob(msg.blob, function() {
-        worker.terminate();
-        runTestOnMainThread();
+        if (msg.canvasType == "webgl") {
+          worker.terminate();
+          runTestOnMainThread();
+        } else {
+          // Start to test toblob for webgl
+          offscreenCanvas = TransferCtrlToOffscreen(createCanvas());
+          worker.postMessage({canvasType: 'webgl', testType: 'toblob',
+                              canvas: offscreenCanvas}, [offscreenCanvas]);
+        }
       });
     }
   }
 
-  ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
+  ok(worker, "Web worker successfully created");
 
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
+  var offscreenCanvas = TransferCtrlToOffscreen(createCanvas());
   ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
 
-  worker.postMessage({test: 'webgl_toblob', canvas: offscreenCanvas}, [offscreenCanvas]);
+  // Start to test toblob for 2d
+  worker.postMessage({canvasType: '2d', testType: 'toblob',
+                      canvas: offscreenCanvas}, [offscreenCanvas]);
 }
 
 SpecialPowers.pushPrefEnv({'set': [
   ['gfx.offscreencanvas.enabled', true],
   ['webgl.force-enabled', true],
 ]}, runTest);
 
 </script>
--- a/dom/canvas/test/test_offscreencanvas_toimagebitmap.html
+++ b/dom/canvas/test/test_offscreencanvas_toimagebitmap.html
@@ -9,59 +9,68 @@
 <canvas id="c" width="64" height="64"></canvas>
 <canvas id="c2" width="64" height="64"></canvas>
 <canvas id="c-ref" width="64" height="64"></canvas>
 <script>
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
+  var startWorker = function(canvasType) {
+    var worker = new Worker("offscreencanvas.js");
 
-  var worker = new Worker("offscreencanvas.js");
+    ok(worker, "Web worker successfully created");
 
-  ok(worker, "Web worker successfully created");
+    worker.postMessage({canvasType: canvasType, testType: 'imagebitmap'});
 
-  worker.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "test") {
-      ok(msg.result, msg.name);
-    }
-    if (msg.type == "imagebitmap") {
-      // testing toBlob
-      // Fill c-ref with green color.
-      var c = document.getElementById("c-ref");
-      var ctx = c.getContext("2d");
-      ctx.rect(0, 0, 64, 64);
-      ctx.fillStyle = "#00FF00";
-      ctx.fill();
+    return new Promise(function(resolved) {
+      worker.onmessage = function(evt) {
+        var msg = evt.data || {};
+        if (msg.type == "test") {
+          ok(msg.result, msg.name);
+        }
+        if (msg.type == "imagebitmap") {
+          // testing toBlob
+          // Fill c-ref with green color.
+          var c = document.getElementById("c-ref");
+          var ctx = c.getContext("2d");
+          ctx.rect(0, 0, 64, 64);
+          ctx.fillStyle = "#00FF00";
+          ctx.fill();
 
-      var htmlCanvas = document.getElementById("c");
-      var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
-      bitmapRenderer.transferImageBitmap(msg.bitmap);
+          var htmlCanvas = document.getElementById("c");
+          var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
+          bitmapRenderer.transferImageBitmap(msg.bitmap);
 
-      ok(c.toDataURL() == htmlCanvas.toDataURL(),
-         "imagebitmap should return a 64x64 green square");
+          ok(c.toDataURL() == htmlCanvas.toDataURL(),
+             "imagebitmap should return a 64x64 green square");
 
-      // The ownership of msg.bitmap should be transferred to canvas "c" when
-      // we called transferImageBitmap. So we test if the ownership is actually
-      // transferred here.
-      var htmlCanvas = document.getElementById("c2");
-      var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
-      bitmapRenderer.transferImageBitmap(msg.bitmap);
+          // The ownership of msg.bitmap should be transferred to canvas "c" when
+          // we called transferImageBitmap. So we test if the ownership is actually
+          // transferred here.
+          var htmlCanvas = document.getElementById("c2");
+          var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
+          bitmapRenderer.transferImageBitmap(msg.bitmap);
 
-      SimpleTest.doesThrow(
-        function() { c2.toDataURL(); },
-        "ImageBitmap has been transferred, toDataURL will throw.");
-
-      worker.terminate();
-      SimpleTest.finish();
-    }
+          SimpleTest.doesThrow(
+            function() { c2.toDataURL(); },
+            "ImageBitmap has been transferred, toDataURL will throw.");
+        }
+        if (msg.type == "finish") {
+          worker.terminate();
+          resolved();
+        }
+      }
+    });
   }
 
-  worker.postMessage({test: 'webgl_imagebitmap'});
+  startWorker('2d').then(function () {
+    startWorker('webgl').then(function () {
+      SimpleTest.finish();
+  })});
 }
 
 SpecialPowers.pushPrefEnv({'set': [
   ['gfx.offscreencanvas.enabled', true],
   ['webgl.force-enabled', true],
 ]}, runTest);
 
 </script>