Bug 1343583 - Adapt test framework to function toString revision draft
authorTomislav Jovanovic <tomica@gmail.com>
Thu, 02 Mar 2017 20:38:25 +0100
changeset 492076 9546394bbd577a4f76cd899103def6bd12a756c4
parent 491167 ec8ac10801d6c054a3e74f89fd1857c0bdac638b
child 492077 003aa40d8eb421d1a325612a9d385fef8c645756
push id47521
push userbmo:tomica@gmail.com
push dateThu, 02 Mar 2017 19:42:12 +0000
bugs1343583
milestone54.0a1
Bug 1343583 - Adapt test framework to function toString revision MozReview-Commit-ID: LHABSIrgpBi
testing/mochitest/tests/SimpleTest/ExtensionTestUtils.js
toolkit/components/extensions/ExtensionTestCommon.jsm
toolkit/components/extensions/test/mochitest/test_ext_clipboard.html
--- a/testing/mochitest/tests/SimpleTest/ExtensionTestUtils.js
+++ b/testing/mochitest/tests/SimpleTest/ExtensionTestUtils.js
@@ -1,10 +1,12 @@
 var ExtensionTestUtils = {};
 
+const {ExtensionTestCommon} = SpecialPowers.Cu.import("resource://testing-common/ExtensionTestCommon.jsm", {});
+
 ExtensionTestUtils.loadExtension = function(ext)
 {
   // Cleanup functions need to be registered differently depending on
   // whether we're in browser chrome or plain mochitests.
   var registerCleanup;
   if (typeof registerCleanupFunction != "undefined") {
     registerCleanup = registerCleanupFunction;
   } else {
@@ -86,23 +88,23 @@ ExtensionTestUtils.loadExtension = funct
   // Mimic serialization of functions as done in `Extension.generateXPI` and
   // `Extension.generateZipFile` because functions are dropped when `ext` object
   // is sent to the main process via the message manager.
   ext = Object.assign({}, ext);
   if (ext.files) {
     ext.files = Object.assign({}, ext.files);
     for (let filename of Object.keys(ext.files)) {
       let file = ext.files[filename];
-      if (typeof file == "function") {
-        ext.files[filename] = `(${file})();`
+      if (typeof file === "function" || Array.isArray(file)) {
+        ext.files[filename] = ExtensionTestCommon.serializeScript(file);
       }
     }
   }
-  if (typeof ext.background == "function") {
-    ext.background = `(${ext.background})();`
+  if ("background" in ext) {
+    ext.background = ExtensionTestCommon.serializeScript(ext.background);
   }
 
   var extension = SpecialPowers.loadExtension(ext, handler);
 
   registerCleanup(() => {
     if (extension.state == "pending" || extension.state == "running") {
       SimpleTest.ok(false, "Extension left running at test shutdown")
       return extension.unload();
--- a/toolkit/components/extensions/ExtensionTestCommon.jsm
+++ b/toolkit/components/extensions/ExtensionTestCommon.jsm
@@ -135,17 +135,17 @@ class MockExtension {
     return this._extensionPromise.then(extension => {
       return extension.broadcast("Extension:FlushJarCache", {path: this.file.path});
     }).then(() => {
       return OS.File.remove(this.file.path);
     });
   }
 }
 
-class ExtensionTestCommon {
+this.ExtensionTestCommon = class ExtensionTestCommon {
   /**
    * This code is designed to make it easy to test a WebExtension
    * without creating a bunch of files. Everything is contained in a
    * single JSON blob.
    *
    * Properties:
    *   "background": "<JS code>"
    *     A script to be loaded as the background script.
@@ -278,17 +278,17 @@ class ExtensionTestCommon {
           zipW.addEntryDirectory(path, time, false);
         }
       }
     }
 
     for (let filename in files) {
       let script = files[filename];
       if (typeof(script) == "function") {
-        script = "(" + script.toString() + ")()";
+        script = this.serializeScript(script);
       } else if (instanceOf(script, "Object") || instanceOf(script, "Array")) {
         script = JSON.stringify(script);
       }
 
       if (!instanceOf(script, "ArrayBuffer")) {
         script = new TextEncoder("utf-8").encode(script).buffer;
       }
 
@@ -300,16 +300,40 @@ class ExtensionTestCommon {
     }
 
     zipW.close();
 
     return file;
   }
 
   /**
+   * Properly serialize a script into eval-able code string.
+   *
+   * @param {string|function|Array} script
+   * @returns {string}
+   */
+  static serializeScript(script) {
+    if (Array.isArray(script)) {
+      return script.map(this.serializeScript).join(";");
+    }
+    if (typeof script !== "function") {
+      return script;
+    }
+    // Serialization of object methods doesn't include `function` anymore.
+    const method = /^(async )?(\w+)\(/;
+
+    let code = script.toString();
+    let match = code.match(method);
+    if (match && match[2] !== "function") {
+      code = code.replace(method, "$1function $2(");
+    }
+    return `(${code})();`;
+  }
+
+  /**
    * Generates a new extension using |Extension.generateXPI|, and initializes a
    * new |Extension| instance which will execute it.
    *
    * @param {object} data
    * @returns {Extension}
    */
   static generate(data) {
     let file = this.generateXPI(data);
@@ -338,9 +362,9 @@ class ExtensionTestCommon {
     }
 
     return new Extension({
       id,
       resourceURI: jarURI,
       cleanupFile: file,
     });
   }
-}
+};
--- a/toolkit/components/extensions/test/mochitest/test_ext_clipboard.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_clipboard.html
@@ -35,17 +35,17 @@ add_task(function* test_background_clipb
   function backgroundScript() {
     browser.test.assertEq(false, doCopy("whatever"),
       "copy should be denied without permission");
     browser.test.assertEq(false, doPaste(),
       "paste should be denied without permission");
     browser.test.sendMessage("ready");
   }
   let extensionData = {
-    background: `(${shared})();(${backgroundScript})();`,
+    background: [shared, backgroundScript],
   };
   let extension = ExtensionTestUtils.loadExtension(extensionData);
   yield extension.startup();
 
   yield extension.awaitMessage("ready");
 
   yield extension.unload();
 });
@@ -189,17 +189,17 @@ add_task(function* test_background_clipb
   function background() {
     browser.test.sendMessage("paste", doPaste());
   }
 
   const extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: ["clipboardRead"],
     },
-    background: `(${shared})();(${background})();`,
+    background: [shared, background],
   });
 
   const STRANGE = "Stranger Things";
   SpecialPowers.clipboardCopyString(STRANGE);
 
   yield extension.startup();
 
   const paste = yield extension.awaitMessage("paste");