toolkit/components/workerloader/require.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /**
     7  * Implementation of a CommonJS module loader for workers.
     8  *
     9  * Use:
    10  * // in the .js file loaded by the constructor of the worker
    11  * importScripts("resource://gre/modules/workers/require.js");
    12  * let module = require("resource://gre/modules/worker/myModule.js");
    13  *
    14  * // in myModule.js
    15  * // Load dependencies
    16  * let SimpleTest = require("resource://gre/modules/workers/SimpleTest.js");
    17  * let Logger = require("resource://gre/modules/workers/Logger.js");
    18  *
    19  * // Define things that will not be exported
    20  * let someValue = // ...
    21  *
    22  * // Export symbols
    23  * exports.foo = // ...
    24  * exports.bar = // ...
    25  *
    26  *
    27  * Note #1:
    28  * Properties |fileName| and |stack| of errors triggered from a module
    29  * contain file names that do not correspond to human-readable module paths.
    30  * Human readers should rather use properties |moduleName| and |moduleStack|.
    31  *
    32  * Note #2:
    33  * The current version of |require()| only accepts absolute URIs.
    34  *
    35  * Note #3:
    36  * By opposition to some other module loader implementations, this module
    37  * loader does not enforce separation of global objects. Consequently, if
    38  * a module modifies a global object (e.g. |String.prototype|), all other
    39  * modules in the same worker may be affected.
    40  */
    43 (function(exports) {
    44   "use strict";
    46   if (exports.require) {
    47     // Avoid double-imports
    48     return;
    49   }
    51   // Simple implementation of |require|
    52   let require = (function() {
    54     /**
    55      * Mapping from module paths to module exports.
    56      *
    57      * @keys {string} The absolute path to a module.
    58      * @values {object} The |exports| objects for that module.
    59      */
    60     let modules = new Map();
    62     /**
    63      * Mapping from object urls to module paths.
    64      */
    65     let paths = {
    66       /**
    67        * @keys {string} The object url holding a module.
    68        * @values {string} The absolute path to that module.
    69        */
    70       _map: new Map(),
    71       /**
    72        * A regexp that may be used to search for all mapped paths.
    73        */
    74       get regexp() {
    75         if (this._regexp) {
    76           return this._regexp;
    77         }
    78         let objectURLs = [];
    79         for (let [objectURL, _] of this._map) {
    80           objectURLs.push(objectURL);
    81         }
    82         return this._regexp = new RegExp(objectURLs.join("|"), "g");
    83       },
    84       _regexp: null,
    85       /**
    86        * Add a mapping from an object url to a path.
    87        */
    88       set: function(url, path) {
    89         this._regexp = null; // invalidate regexp
    90         this._map.set(url, path);
    91       },
    92       /**
    93        * Get a mapping from an object url to a path.
    94        */
    95       get: function(url) {
    96         return this._map.get(url);
    97       },
    98       /**
    99        * Transform a string by replacing all the instances of objectURLs
   100        * appearing in that string with the corresponding module path.
   101        *
   102        * This is used typically to translate exception stacks.
   103        *
   104        * @param {string} source A source string.
   105        * @return {string} The same string as |source|, in which every occurrence
   106        * of an objectURL registered in this object has been replaced with the
   107        * corresponding module path.
   108        */
   109       substitute: function(source) {
   110         let map = this._map;
   111         return source.replace(this.regexp, function(url) {
   112           return map.get(url) || url;
   113         }, "g");
   114       }
   115     };
   117     /**
   118      * A human-readable version of |stack|.
   119      *
   120      * @type {string}
   121      */
   122     Object.defineProperty(Error.prototype, "moduleStack",
   123     {
   124       get: function() {
   125         return paths.substitute(this.stack);
   126       }
   127     });
   128     /**
   129      * A human-readable version of |fileName|.
   130      *
   131      * @type {string}
   132      */
   133     Object.defineProperty(Error.prototype, "moduleName",
   134     {
   135       get: function() {
   136         return paths.substitute(this.fileName);
   137       }
   138     });
   140     /**
   141      * Import a module
   142      *
   143      * @param {string} path The path to the module.
   144      * @return {*} An object containing the properties exported by the module.
   145      */
   146     return function require(path) {
   147       if (typeof path != "string" || path.indexOf("://") == -1) {
   148         throw new TypeError("The argument to require() must be a string uri, got " + path);
   149       }
   150       // Automatically add ".js" if there is no extension
   151       let uri;
   152       if (path.lastIndexOf(".") <= path.lastIndexOf("/")) {
   153         uri = path + ".js";
   154       } else {
   155         uri = path;
   156       }
   158       // Exports provided by the module
   159       let exports = Object.create(null);
   161       // Identification of the module
   162       let module = {
   163         id: path,
   164         uri: uri,
   165         exports: exports
   166       };
   168       // Make module available immediately
   169       // (necessary in case of circular dependencies)
   170       if (modules.has(path)) {
   171         return modules.get(path).exports;
   172       }
   173       modules.set(path, module);
   175       let name = ":" + path;
   176       let objectURL;
   177       try {
   178         // Load source of module, synchronously
   179         let xhr = new XMLHttpRequest();
   180         xhr.open("GET", uri, false);
   181         xhr.responseType = "text";
   182         xhr.send();
   185         let source = xhr.responseText;
   186         if (source == "") {
   187           // There doesn't seem to be a better way to detect that the file couldn't be found
   188           throw new Error("Could not find module " + path);
   189         }
   190         // From the source, build a function and an object URL. We
   191         // avoid any newline at the start of the file to ensure that
   192         // we do not mess up with line numbers. However, using object URLs
   193         // messes up with stack traces in instances of Error().
   194         source = "require._tmpModules[\"" + name + "\"] = " +
   195           "function(exports, require, module) {" +
   196           source +
   197         "\n}\n";
   198         let blob = new Blob(
   199           [
   200             (new TextEncoder()).encode(source)
   201           ], {
   202             type: "application/javascript"
   203           });
   204         objectURL = URL.createObjectURL(blob);
   205         paths.set(objectURL, path);
   206         importScripts(objectURL);
   207         require._tmpModules[name].call(null, exports, require, module);
   209       } catch (ex) {
   210         // Module loading has failed, exports should not be made available
   211         // after all.
   212         modules.delete(path);
   213         throw ex;
   214       } finally {
   215         if (objectURL) {
   216           // Clean up the object url as soon as possible. It will not be needed.
   217           URL.revokeObjectURL(objectURL);
   218         }
   219         delete require._tmpModules[name];
   220       }
   222       Object.freeze(module.exports);
   223       Object.freeze(module);
   224       return module.exports;
   225     };
   226   })();
   228   /**
   229    * An object used to hold temporarily the module constructors
   230    * while they are being loaded.
   231    *
   232    * @keys {string} The path to the module, prefixed with ":".
   233    * @values {function} A function wrapping the module.
   234    */
   235   require._tmpModules = Object.create(null);
   236   Object.freeze(require);
   238   Object.defineProperty(exports, "require", {
   239     value: require,
   240     enumerable: true,
   241     configurable: false
   242   });
   243 })(this);

mercurial