tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

builtin-modules.js (6735B)


      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/. */
      4 
      5 "use strict";
      6 
      7 /**
      8 * This module defines custom globals injected in all our modules and also
      9 * pseudo modules that aren't separate files but just dynamically set values.
     10 *
     11 * Note that some globals are being defined by base-loader.sys.mjs via wantGlobalProperties property.
     12 *
     13 * As it does so, the module itself doesn't have access to these globals,
     14 * nor the pseudo modules. Be careful to avoid loading any other js module as
     15 * they would also miss them.
     16 */
     17 
     18 const systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
     19 
     20 /**
     21 * Defines a getter on a specified object that will be created upon first use.
     22 *
     23 * @param object
     24 *        The object to define the lazy getter on.
     25 * @param name
     26 *        The name of the getter to define on object.
     27 * @param lambda
     28 *        A function that returns what the getter should return.  This will
     29 *        only ever be called once.
     30 */
     31 function defineLazyGetter(object, name, lambda) {
     32  Object.defineProperty(object, name, {
     33    get() {
     34      // Redefine this accessor property as a data property.
     35      // Delete it first, to rule out "too much recursion" in case object is
     36      // a proxy whose defineProperty handler might unwittingly trigger this
     37      // getter again.
     38      delete object[name];
     39      const value = lambda.apply(object);
     40      Object.defineProperty(object, name, {
     41        value,
     42        writable: true,
     43        configurable: true,
     44        enumerable: true,
     45      });
     46      return value;
     47    },
     48    configurable: true,
     49    enumerable: true,
     50  });
     51 }
     52 
     53 /**
     54 * Defines a getter on a specified object for a service.  The service will not
     55 * be obtained until first use.
     56 *
     57 * @param object
     58 *        The object to define the lazy getter on.
     59 * @param name
     60 *        The name of the getter to define on object for the service.
     61 * @param contract
     62 *        The contract used to obtain the service.
     63 * @param interfaceName
     64 *        The name of the interface to query the service to.
     65 */
     66 function defineLazyServiceGetter(object, name, contract, interfaceName) {
     67  defineLazyGetter(object, name, function () {
     68    return Cc[contract].getService(Ci[interfaceName]);
     69  });
     70 }
     71 
     72 /**
     73 * Define a getter property on the given object that requires the given
     74 * module. This enables delaying importing modules until the module is
     75 * actually used.
     76 *
     77 * Several getters can be defined at once by providing an array of
     78 * properties and enabling destructuring.
     79 *
     80 * @param {object} obj
     81 *    The object to define the property on.
     82 * @param {string | Array<string>} properties
     83 *    String: Name of the property for the getter.
     84 *    Array<String>: When destructure is true, properties can be an array of
     85 *    strings to create several getters at once.
     86 * @param {string} module
     87 *    The module path.
     88 * @param {boolean} destructure
     89 *    Pass true if the property name is a member of the module's exports.
     90 */
     91 function lazyRequireGetter(obj, properties, module, destructure) {
     92  if (Array.isArray(properties) && !destructure) {
     93    throw new Error(
     94      "Pass destructure=true to call lazyRequireGetter with an array of properties"
     95    );
     96  }
     97 
     98  if (!Array.isArray(properties)) {
     99    properties = [properties];
    100  }
    101 
    102  for (const property of properties) {
    103    defineLazyGetter(obj, property, () => {
    104      return destructure
    105        ? require(module)[property]
    106        : require(module || property);
    107    });
    108  }
    109 }
    110 
    111 // List of pseudo modules exposed to all devtools modules.
    112 exports.modules = {
    113  HeapSnapshot,
    114  // Expose "chrome" Promise, which aren't related to any document
    115  // and so are never frozen, even if the browser loader module which
    116  // pull it is destroyed. See bug 1402779.
    117  Promise,
    118 };
    119 
    120 defineLazyGetter(exports.modules, "Debugger", () => {
    121  const global = Cu.getGlobalForObject(this);
    122  // Debugger may already have been added.
    123  if (global.Debugger) {
    124    return global.Debugger;
    125  }
    126  const { addDebuggerToGlobal } = ChromeUtils.importESModule(
    127    "resource://gre/modules/jsdebugger.sys.mjs",
    128    { global: "contextual" }
    129  );
    130  addDebuggerToGlobal(global);
    131  return global.Debugger;
    132 });
    133 
    134 defineLazyGetter(exports.modules, "ChromeDebugger", () => {
    135  // Sandbox are memory expensive, so we should create as little as possible.
    136  const debuggerSandbox = Cu.Sandbox(systemPrincipal, {
    137    // This sandbox is used for the ChromeDebugger implementation.
    138    // As we want to load the `Debugger` API for debugging chrome contexts,
    139    // we have to ensure loading it in a distinct compartment from its debuggee.
    140    freshCompartment: true,
    141  });
    142 
    143  const { addDebuggerToGlobal } = ChromeUtils.importESModule(
    144    "resource://gre/modules/jsdebugger.sys.mjs",
    145    { global: "contextual" }
    146  );
    147  addDebuggerToGlobal(debuggerSandbox);
    148  return debuggerSandbox.Debugger;
    149 });
    150 
    151 defineLazyGetter(exports.modules, "xpcInspector", () => {
    152  return Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
    153 });
    154 
    155 // List of all custom globals exposed to devtools modules.
    156 // Changes here should be mirrored to devtools/.eslintrc.
    157 exports.globals = {
    158  isWorker: false,
    159  loader: {
    160    lazyGetter: defineLazyGetter,
    161    lazyServiceGetter: defineLazyServiceGetter,
    162    lazyRequireGetter,
    163    // Defined by Loader.sys.mjs
    164    id: null,
    165  },
    166 };
    167 // DevTools loader copy globals property descriptors on each module global
    168 // object so that we have to memoize them from here in order to instantiate each
    169 // global only once.
    170 // `globals` is a cache object on which we put all global values
    171 // and we set getters on `exports.globals` returning `globals` values.
    172 const globals = {};
    173 function lazyGlobal(name, getter) {
    174  defineLazyGetter(globals, name, getter);
    175  Object.defineProperty(exports.globals, name, {
    176    get() {
    177      return globals[name];
    178    },
    179    configurable: true,
    180    enumerable: true,
    181  });
    182 }
    183 
    184 // Lazily define a few things so that the corresponding modules are only loaded
    185 // when used.
    186 lazyGlobal("clearTimeout", () => {
    187  return ChromeUtils.importESModule("resource://gre/modules/Timer.sys.mjs", {
    188    global: "contextual",
    189  }).clearTimeout;
    190 });
    191 lazyGlobal("setTimeout", () => {
    192  return ChromeUtils.importESModule("resource://gre/modules/Timer.sys.mjs", {
    193    global: "contextual",
    194  }).setTimeout;
    195 });
    196 lazyGlobal("clearInterval", () => {
    197  return ChromeUtils.importESModule("resource://gre/modules/Timer.sys.mjs", {
    198    global: "contextual",
    199  }).clearInterval;
    200 });
    201 lazyGlobal("setInterval", () => {
    202  return ChromeUtils.importESModule("resource://gre/modules/Timer.sys.mjs", {
    203    global: "contextual",
    204  }).setInterval;
    205 });