1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2026-03-11 08:25:47 +01:00

Allow loading plugins globally.

This commit is contained in:
Kris Maglione
2011-10-01 22:49:32 -04:00
parent 36fac82035
commit c9583ac72f
3 changed files with 118 additions and 15 deletions

View File

@@ -128,6 +128,8 @@ let jsmodules = {
memoize(target || this, name, function (name) require(module)[name]); memoize(target || this, name, function (name) require(module)[name]);
} }
}; };
jsmodules.jsmodules = jsmodules;
let use = {}; let use = {};
let loaded = {}; let loaded = {};
let currentModule; let currentModule;

View File

@@ -8,9 +8,12 @@ try {
Components.utils.import("resource://dactyl/bootstrap.jsm"); Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("contexts", { defineModule("contexts", {
exports: ["Contexts", "Group", "contexts"] exports: ["Contexts", "Group", "contexts"],
require: ["services", "util"]
}, this); }, this);
this.lazyRequire("overlay", ["overlay"]);
var Const = function Const(val) Class.Property({ enumerable: true, value: val }); var Const = function Const(val) Class.Property({ enumerable: true, value: val });
var Group = Class("Group", { var Group = Class("Group", {
@@ -85,6 +88,17 @@ var Group = Class("Group", {
}); });
var Contexts = Module("contexts", { var Contexts = Module("contexts", {
init: function () {
this.pluginModules = {};
},
cleanup: function () {
for each (let module in this.pluginModules)
util.trapErrors("cleanup", module);
this.pluginModules = {};
},
Local: function Local(dactyl, modules, window) ({ Local: function Local(dactyl, modules, window) ({
init: function () { init: function () {
const contexts = this; const contexts = this;
@@ -195,7 +209,7 @@ var Contexts = Module("contexts", {
let name = isPlugin ? file.getRelativeDescriptor(isPlugin).replace(File.PATH_SEP, "-") let name = isPlugin ? file.getRelativeDescriptor(isPlugin).replace(File.PATH_SEP, "-")
: file.leafName; : file.leafName;
let id = name.replace(/\.[^.]*$/, "").replace(/-([a-z])/g, function (m, n1) n1.toUpperCase()); let id = util.camelCase(name.replace(/\.[^.]*$/, ""));
let contextPath = file.path; let contextPath = file.path;
let self = Set.has(plugins, contextPath) && plugins.contexts[contextPath]; let self = Set.has(plugins, contextPath) && plugins.contexts[contextPath];
@@ -205,7 +219,7 @@ var Contexts = Module("contexts", {
if (self) { if (self) {
if (Set.has(self, "onUnload")) if (Set.has(self, "onUnload"))
self.onUnload(); util.trapErrors("onUnload", self);
} }
else { else {
self = args && !isArray(args) ? args : newContext.apply(null, args || [userContext]); self = args && !isArray(args) ? args : newContext.apply(null, args || [userContext]);
@@ -216,10 +230,16 @@ var Contexts = Module("contexts", {
CONTEXT: Const(self), CONTEXT: Const(self),
set isGlobalModule(val) {
// Hack.
if (val)
throw Contexts;
},
unload: Const(function unload() { unload: Const(function unload() {
if (plugins[this.NAME] === this || plugins[this.PATH] === this) if (plugins[this.NAME] === this || plugins[this.PATH] === this)
if (this.onUnload) if (this.onUnload)
this.onUnload(); util.trapErrors("onUnload", this);
if (plugins[this.NAME] === this) if (plugins[this.NAME] === this)
delete plugins[this.NAME]; delete plugins[this.NAME];
@@ -270,6 +290,74 @@ var Contexts = Module("contexts", {
return this.Context(file, group, [this.modules.userContext, true]); return this.Context(file, group, [this.modules.userContext, true]);
}, },
Module: function Module(uri, isPlugin) {
const { io, plugins } = this.modules;
let canonical = uri.spec;
if (uri.scheme == "resource")
canonical = services["resource:"].resolveURI(uri);
if (uri instanceof Ci.nsIFileURL)
var file = File(uri.file);
let isPlugin = array.nth(io.getRuntimeDirectories("plugins"),
function (dir) dir.contains(file, true),
0);
let name = isPlugin && file && file.getRelativeDescriptor(isPlugin)
.replace(File.PATH_SEP, "-");
let id = util.camelCase(name.replace(/\.[^.]*$/, ""));
let self = Set.has(this.pluginModules, canonical) && this.pluginModules[canonical];
if (!self) {
self = Object.create(jsmodules);
update(self, {
NAME: Const(id),
PATH: Const(file && file.path),
CONTEXT: Const(self),
get isGlobalModule() true,
set isGlobalModule(val) {
util.assert(val, "Loading non-global module as global",
false);
},
unload: Const(function unload() {
if (contexts.pluginModules[canonical] == this) {
if (this.onUnload)
util.trapErrors("onUnload", this);
delete contexts.pluginModules[canonical];
}
for each (let { plugins } in overlay.modules)
if (plugins[this.NAME] == this)
delete plugins[this.name];
})
});
JSMLoader.loadSubScript(uri.spec, self, File.defaultEncoding);
this.pluginModules[canonical] = self;
}
// This belongs elsewhere
if (isPlugin)
Object.defineProperty(plugins, self.NAME, {
configurable: true,
enumerable: true,
get: function () self,
set: function (val) {
util.dactyl(val).reportError(FailedAssertion(_("plugin.notReplacingContext", self.NAME), 3, false), true);
}
});
return self;
},
context: null, context: null,
/** /**

View File

@@ -16,6 +16,7 @@ defineModule("io", {
}, this); }, this);
this.lazyRequire("config", ["config"]); this.lazyRequire("config", ["config"]);
this.lazyRequire("contexts", ["Contexts", "contexts"]);
// TODO: why are we passing around strings rather than file objects? // TODO: why are we passing around strings rather than file objects?
/** /**
@@ -167,8 +168,14 @@ var IO = Module("io", {
let uri = services.io.newFileURI(file); let uri = services.io.newFileURI(file);
// handle pure JavaScript files specially let sourceJSM = function sourceJSM() {
if (/\.js$/.test(filename)) { context = contexts.Module(uri);
dactyl.triggerObserver("io.source", context, file, file.lastModifiedTime);
}
if (/\.js,$/.test(filename))
sourceJSM();
else if (/\.js$/.test(filename)) {
try { try {
var context = contexts.Script(file, params.group); var context = contexts.Script(file, params.group);
if (Set.has(this._scriptNames, file.path)) if (Set.has(this._scriptNames, file.path))
@@ -178,15 +185,21 @@ var IO = Module("io", {
dactyl.triggerObserver("io.source", context, file, file.lastModifiedTime); dactyl.triggerObserver("io.source", context, file, file.lastModifiedTime);
} }
catch (e) { catch (e) {
if (e.fileName && !(e instanceof FailedAssertion)) if (e == Contexts) { // Hack;
try { context.unload();
e.fileName = util.fixURI(e.fileName); sourceJSM();
if (e.fileName == uri.spec) }
e.fileName = filename; else {
e.echoerr = <>{e.fileName}:{e.lineNumber}: {e}</>; if (e.fileName && !(e instanceof FailedAssertion))
} try {
catch (e) {} e.fileName = util.fixURI(e.fileName);
throw e; if (e.fileName == uri.spec)
e.fileName = filename;
e.echoerr = <>{e.fileName}:{e.lineNumber}: {e}</>;
}
catch (e) {}
throw e;
}
} }
} }
else if (/\.css$/.test(filename)) else if (/\.css$/.test(filename))