[Pkg-mozext-commits] [jpm.sh] 01/43: v0.0.1

Hema Prathaban hemaprathaban-guest at moszumanska.debian.org
Thu Aug 17 07:52:33 UTC 2017


This is an automated email from the git hooks/post-receive script.

hemaprathaban-guest pushed a commit to branch master
in repository jpm.sh.

commit 8d137cbc2ea35d90ce9856ae93fab30229d22200
Author: Erik Vold <evold at mozilla.com>
Date:   Wed Oct 1 11:04:41 2014 +0100

    v0.0.1
---
 data/bootstrap.js | 384 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/index.js      |   0
 package.json      |  16 +++
 3 files changed, 400 insertions(+)

diff --git a/data/bootstrap.js b/data/bootstrap.js
new file mode 100644
index 0000000..45320a9
--- /dev/null
+++ b/data/bootstrap.js
@@ -0,0 +1,384 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// @see http://mxr.mozilla.org/mozilla-central/source/js/src/xpconnect/loader/mozJSComponentLoader.cpp
+
+'use strict';
+
+// IMPORTANT: Avoid adding any initialization tasks here, if you need to do
+// something before add-on is loaded consider addon/runner module instead!
+
+const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu,
+        results: Cr, manager: Cm } = Components;
+const ioService = Cc['@mozilla.org/network/io-service;1'].
+                  getService(Ci.nsIIOService);
+const resourceHandler = ioService.getProtocolHandler('resource').
+                        QueryInterface(Ci.nsIResProtocolHandler);
+const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
+const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1'].
+                     getService(Ci.mozIJSSubScriptLoader);
+const prefService = Cc['@mozilla.org/preferences-service;1'].
+                    getService(Ci.nsIPrefService).
+                    QueryInterface(Ci.nsIPrefBranch);
+const { get, exists } = Cc['@mozilla.org/process/environment;1'].
+                        getService(Ci.nsIEnvironment);
+
+const prefSvc = Cc["@mozilla.org/preferences-service;1"].
+                getService(Ci.nsIPrefService).getBranch(null);
+
+const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
+const { Promise: { defer } } = Cu.import("resource://gre/modules/Promise.jsm", {});
+const { Task: { spawn } } = Cu.import("resource://gre/modules/Task.jsm", {});
+// load below now, so that it can be used by sdk/addon/runner
+// see bug https://bugzilla.mozilla.org/show_bug.cgi?id=1042239
+const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
+
+const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable',
+                 'install', 'uninstall', 'upgrade', 'downgrade' ];
+
+const bind = Function.call.bind(Function.bind);
+
+let loader = null;
+let unload = null;
+let loaderSandbox = null;
+let nukeTimer = null;
+
+function getPref(name, defaultValue) {
+  defaultValue = defaultValue || null;
+  switch (prefSvc.getPrefType(name)) {
+  case Ci.nsIPrefBranch.PREF_STRING:
+    return prefSvc.getComplexValue(name, Ci.nsISupportsString).data;
+
+  case Ci.nsIPrefBranch.PREF_INT:
+    return prefSvc.getIntPref(name);
+
+  case Ci.nsIPrefBranch.PREF_BOOL:
+    return prefSvc.getBoolPref(name);
+
+  default:
+    return defaultValue;
+  }
+}
+
+// Utility function reads URI async. Returns promise for the read
+// content.
+const readURI = (uri, charset="utf-8") => {
+  const channel = NetUtil.newChannel(uri, charset, null);
+  const { promise, resolve, reject } = defer();
+
+  try {
+    NetUtil.asyncFetch(channel, (stream, result) => {
+      if (Components.isSuccessCode(result)) {
+        const count = stream.available();
+        const data = NetUtil.readInputStreamToString(stream, count, {charset : charset});
+
+        resolve(data);
+      } else {
+        reject(Error("Failed to read: '" + uri + "' (Error Code: " + result + ")"));
+      }
+    });
+  }
+  catch ({message}) {
+    reject(Error("Failed to read: '" + uri + "' (Error: " + message + ")"));
+  }
+
+  return promise;
+}
+
+
+// We don't do anything on install & uninstall yet, but in a future
+// we should allow add-ons to cleanup after uninstall.
+const install = (data, reason) => {}
+const uninstall = (data, reason) => {}
+
+// Reads run configuration asynchronously, returns promise
+// for the config JSON.
+const readConfig = (rootURI) => {
+  const { resolve, reject, promise } = defer();
+  spawn(function () {
+    let config = null;
+    try {
+      const options = JSON.parse(yield (readURI(rootURI + "./harness-options.json")));
+      config = {
+        options: options,
+        metadata: options.metadata[options.name],
+        isNative: false
+      };
+    }
+    catch (_) {
+      try {
+        config = {
+          isNative: true,
+          options: {},
+          metadata: JSON.parse(yield readURI(rootURI + './package.json'))
+        };
+      }
+      catch(_) {}
+    }
+    resolve(config);
+  });
+
+  return promise;
+}
+
+const UUID_PATTERN = /^\{([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\}$/;
+// Takes add-on ID and normalizes it to a domain name so that add-on
+// can be mapped to resource://domain/
+const readDomain = id =>
+  // If only `@` character is the first one, than just substract it,
+  // otherwise fallback to legacy normalization code path. Note: `.`
+  // is valid character for resource substitutaiton & we intend to
+  // make add-on URIs intuitive, so it's best to just stick to an
+  // add-on author typed input.
+  id.lastIndexOf("@") === 0 ? id.substr(1).toLowerCase() :
+  id.toLowerCase().
+     replace(/@/g, "-at-").
+     replace(/\./g, "-dot-").
+     replace(UUID_PATTERN, "$1");
+
+const readPaths = (options, id, name, domain, baseURI, isNative=false) => {
+  let paths = {
+    "": "resource://gre/modules/commonjs/",
+    "./": isNative ? baseURI : baseURI + name + '/lib/',
+    "./tests/": isNative ? baseURI : baseURI + name + '/tests/'
+  };
+
+  Object.keys(options.manifest || {}).reduce((paths, prefix) => {
+    paths[prefix + "/"] = baseURI + prefix + "/lib/";
+    paths[prefix + "tests/"] = baseURI + prefix + "/tests/";
+    return paths;
+  }, paths);
+
+  if (name == "addon-sdk")
+    paths["tests/"] = baseURI + "addon-sdk/tests/";
+
+
+  // If SDK is bundled and it is required to use bundled version
+  // of the SDK setup paths to do so.
+  const isSDKBundled = options["is-sdk-bundled"];
+  const useBundledSDK = options["force-use-bundled-sdk"] ||
+                        getPref("extensions.addon-sdk.useBundledSDK");
+
+  if (isSDKBundled && useBundledSDK) {
+    paths[""] = baseURI + "addon-sdk/lib/";
+    paths["test"] = baseURI + "addon-sdk/lib/sdk/test.js";
+  }
+
+  const branch = prefService.getBranch("extensions.modules." + id + ".path");
+  branch.getChildList("", {}).reduce((paths, name) => {
+    const path = name.substr(1).split(".").join("/");
+    const prefix = path.length ? path + "/" : path;
+    const value = branch.getCharPref(name);
+    const fileURI = value[value.length - 1] === "/" ? value :
+                    value + "/";
+    const key = "extensions.modules." + domain + ".commonjs.path" + name;
+    const uri = ioService.newURI(fileURI, null, null);
+    resourceHandler.setSubstitution(key, uri);
+
+    paths[prefix] = "resource://" + key + "/";
+    return paths;
+  }, paths);
+
+  return paths;
+}
+
+// Takes JSON `options` and sets prefs for each key under
+// the given `root`. Given `options` may contain nested
+// objects.
+const setPrefs = (root, options) =>
+  void Object.keys(options).forEach(id => {
+    const key = root + "." + id;
+    const value = options[id]
+    const type = typeof(value);
+
+    value === null ? void(0) :
+    value === undefined ? void(0) :
+    type === "boolean" ? prefService.setBoolPref(key, value) :
+    type === "string" ? prefService.setCharPref(key, value) :
+    type === "number" ? prefService.setIntPref(key, parseInt(value)) :
+    type === "object" ? setPrefs(key, value) :
+    void(0);
+  });
+
+const startup = (addon, reasonCode) => {
+  const reason = REASON[reasonCode];
+  const { id, version, resourceURI: { spec: rootURI } } = addon;
+  const loadCommand = exists("CFX_COMMAND") ?
+                        get("CFX_COMMAND") :
+                        getPref("extensions." + id + ".sdk.load.command", undefined);
+
+  spawn(function() {
+    try {
+      const config = readConfig(rootURI);
+      const { metadata, options, isNative } = (yield config);
+      const permissions = Object.freeze(metadata.permissions || {});
+      const domain = readDomain(id);
+      const name = metadata.name;
+
+      const baseURI = "resource://" + domain + "/";
+
+      const prefsURI = baseURI + "defaults/preferences/prefs.js";
+
+      const mappedURI = isNative ? rootURI + '/' : rootURI + '/resources/';
+      resourceHandler.setSubstitution(domain, ioService.newURI(mappedURI, null, null));
+
+      const paths = readPaths(options, id, name, domain, baseURI, isNative);
+
+      const loaderID = isNative ? "toolkit/loader" : "sdk/loader/cuddlefish";
+      const loaderURI = paths[""] + loaderID + ".js";
+
+      loaderSandbox = loadSandbox(loaderURI);
+
+      const loaderModule = loaderSandbox.exports;
+
+      unload = loaderModule.unload;
+
+      setPrefs("extensions." + id + ".sdk", {
+        id: id,
+        version: version,
+        domain: domain,
+        mainPath: options.mainPath,
+        baseURI: baseURI,
+        rootURI: rootURI,
+        load: {
+          reason: reason,
+          command: loadCommand
+        },
+        input: {
+          staticArgs: JSON.stringify(options.staticArgs)
+        },
+        output: {
+          resultFile: options.resultFile,
+          style: options.parseable ? "tbpl" : null,
+          logLevel: options.verbose ? "verbose" : null,
+        },
+        test: {
+          stop: options.stopOnError ? 1 : null,
+          filter: options.filter,
+          iterations: options.iterations,
+        },
+        profile: {
+          memory: options.profileMemory,
+          leaks: options.check_memory ? "refcount" : null
+        }
+      });
+
+      const modules = {};
+
+      // Manually set the loader's module cache to include itself;
+      // which otherwise fails due to lack of `Components`.
+      modules[loaderID] = loaderModule;
+      modules["@test/options"] = Object.freeze({});
+
+      loader = loaderModule.Loader({
+        id: id,
+        isNative: isNative,
+        prefixURI: baseURI,
+        rootURI: baseURI,
+        name: name,
+        paths: paths,
+        manifest: options.manifest || metadata,
+        metadata: metadata,
+        modules: modules
+      });
+
+      const module = loaderModule.Module(loaderID, loaderURI);
+      const require = loaderModule.Require(loader, module);
+      const mainPath = (loadCommand == "test") ? "sdk/test/runner" : options.mainPath;
+
+      require("sdk/addon/runner").startup(reason, {
+        loader: loader,
+        prefsURI: prefsURI,
+        main: mainPath
+      });
+    }
+    catch (error) {
+      console.error("Failed to bootstrap addon: ", id, error);
+      throw error;
+    }
+  });
+};
+
+const loadSandbox = (uri) => {
+  let proto = {
+    sandboxPrototype: {
+      loadSandbox: loadSandbox,
+      ChromeWorker: ChromeWorker
+    }
+  };
+  let sandbox = Cu.Sandbox(systemPrincipal, proto);
+  // Create a fake commonjs environnement just to enable loading loader.js
+  // correctly
+  sandbox.exports = {};
+  sandbox.module = { uri: uri, exports: sandbox.exports };
+  sandbox.require = function (id) {
+    if (id !== "chrome")
+      throw new Error("Bootstrap sandbox `require` method isn't implemented.");
+
+    return Object.freeze({ Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm,
+      CC: bind(CC, Components), components: Components,
+      ChromeWorker: ChromeWorker });
+  };
+  scriptLoader.loadSubScript(uri, sandbox, 'UTF-8');
+  return sandbox;
+}
+
+const unloadSandbox = sandbox =>
+  Cu.nukeSandbox && sandbox && Cu.nukeSandbox(sandbox);
+
+const setTimeout = (callback, delay=0) => {
+  const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+  timer.initWithCallback({ notify: callback },
+                         delay,
+                         Ci.nsITimer.TYPE_ONE_SHOT);
+  return timer;
+}
+
+const shutdown = (data, reasonCode) => {
+  let reason = REASON[reasonCode];
+  if (loader) {
+    unload(loader, reason);
+    unload = null;
+
+    // Don't waste time cleaning up if the application is shutting down
+    if (reason != "shutdown") {
+      // Avoid leaking all modules when something goes wrong with one particular
+      // module. Do not clean it up immediatly in order to allow executing some
+      // actions on addon disabling.
+      // We need to keep a reference to the timer, otherwise it is collected
+      // and won't ever fire.
+      nukeTimer = setTimeout(nukeModules, 1000);
+    }
+  }
+};
+
+function nukeModules() {
+  nukeTimer = null;
+  // module objects store `exports` which comes from sandboxes
+  // We should avoid keeping link to these object to avoid leaking sandboxes
+  for (let id in loader.modules) {
+    delete loader.modules[id];
+  }
+
+  // Direct links to sandboxes should be removed too
+  for (let id in loader.sandboxes) {
+    let sandbox = loader.sandboxes[id];
+    delete loader.sandboxes[id];
+    // Bug 775067: From FF17 we can kill all CCW from a given sandbox
+    unloadSandbox(sandbox);
+  }
+  loader = null;
+
+  // both `toolkit/loader` and `system/xul-app` are loaded as JSM's via
+  // `cuddlefish.js`, and needs to be unloaded to avoid memory leaks, when
+  // the addon is unload.
+
+  unloadSandbox(loaderSandbox.loaderSandbox);
+  unloadSandbox(loaderSandbox.xulappSandbox);
+
+  // Bug 764840: We need to unload cuddlefish otherwise it will stay alive
+  // and keep a reference to this compartment.
+  unloadSandbox(loaderSandbox);
+  loaderSandbox = null;
+}
diff --git a/lib/index.js b/lib/index.js
new file mode 100644
index 0000000..e69de29
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b462e82
--- /dev/null
+++ b/package.json
@@ -0,0 +1,16 @@
+{
+  "name": "jpm-core",
+  "version": "0.0.1",
+  "description": "Cross platform components for building Firefox add-ons",
+  "main": "./lib/index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "keywords": [
+    "jpm",
+    "jetpack",
+    "firefox"
+  ],
+  "author": "Erik Vold <evold at mozilla.com> (http://work.erikvold.com/)",
+  "license": "MPL v2.0"
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/jpm.sh.git



More information about the Pkg-mozext-commits mailing list