mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-21 22:37:58 +01:00
Fix some startup bottlenecks.
This commit is contained in:
15
common/bootstrap.js
vendored
15
common/bootstrap.js
vendored
@@ -46,6 +46,11 @@ function debug(...args) {
|
|||||||
dump(name + ": " + args.join(", ") + "\n");
|
dump(name + ": " + args.join(", ") + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function* entries(obj) {
|
||||||
|
for (let key of Object.keys(obj))
|
||||||
|
yield [key, obj[key]]
|
||||||
|
}
|
||||||
|
|
||||||
function httpGet(uri) {
|
function httpGet(uri) {
|
||||||
let xmlhttp = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
let xmlhttp = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
||||||
xmlhttp.overrideMimeType("text/plain");
|
xmlhttp.overrideMimeType("text/plain");
|
||||||
@@ -57,8 +62,8 @@ function httpGet(uri) {
|
|||||||
let moduleName;
|
let moduleName;
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
var addon = null;
|
var addon = null;
|
||||||
let addonData = null;
|
var addonData = null;
|
||||||
let basePath = null;
|
var basePath = null;
|
||||||
let bootstrap;
|
let bootstrap;
|
||||||
let bootstrap_jsm;
|
let bootstrap_jsm;
|
||||||
let components = {};
|
let components = {};
|
||||||
@@ -239,10 +244,10 @@ function init() {
|
|||||||
if (!manifest.categories)
|
if (!manifest.categories)
|
||||||
manifest.categories = [];
|
manifest.categories = [];
|
||||||
|
|
||||||
for (let [classID, { contract, path, categories }] of Iterator(manifest.components || {})) {
|
for (let [classID, { contract, path, categories }] of entries(manifest.components || {})) {
|
||||||
components[classID] = new FactoryProxy(getURI(path).spec, classID, contract);
|
components[classID] = new FactoryProxy(getURI(path).spec, classID, contract);
|
||||||
if (categories)
|
if (categories)
|
||||||
for (let [category, id] in Iterator(categories))
|
for (let [category, id] of entries(categories))
|
||||||
manifest.categories.push([category, id, contract]);
|
manifest.categories.push([category, id, contract]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +255,7 @@ function init() {
|
|||||||
categoryManager.addCategoryEntry(category, id, value,
|
categoryManager.addCategoryEntry(category, id, value,
|
||||||
false, true);
|
false, true);
|
||||||
|
|
||||||
for (let [pkg, path] in Iterator(manifest.resources || {})) {
|
for (let [pkg, path] of entries(manifest.resources || {})) {
|
||||||
moduleName = moduleName || pkg;
|
moduleName = moduleName || pkg;
|
||||||
resourceProto.setSubstitution(pkg, getURI(path));
|
resourceProto.setSubstitution(pkg, getURI(path));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,8 +317,11 @@ var CommandWidgets = Class("CommandWidgets", {
|
|||||||
return document.getElementById("dactyl-contextmenu");
|
return document.getElementById("dactyl-contextmenu");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
multilineOutputReady: false,
|
||||||
|
|
||||||
multilineOutput: Class.Memoize(function () {
|
multilineOutput: Class.Memoize(function () {
|
||||||
return this._whenReady("dactyl-multiline-output", elem => {
|
return this._whenReady("dactyl-multiline-output", elem => {
|
||||||
|
this.multilineOutputReady = true;
|
||||||
highlight.highlightNode(elem.contentDocument.body, "MOW");
|
highlight.highlightNode(elem.contentDocument.body, "MOW");
|
||||||
});
|
});
|
||||||
}, true),
|
}, true),
|
||||||
|
|||||||
@@ -18,15 +18,14 @@ var ProcessorStack = Class("ProcessorStack", {
|
|||||||
events.dbg("STACK " + mode);
|
events.dbg("STACK " + mode);
|
||||||
|
|
||||||
let main = { __proto__: mode.main, params: mode.params };
|
let main = { __proto__: mode.main, params: mode.params };
|
||||||
this.modes = Ary([mode.params.keyModes,
|
this.modes = [...(mode.params.keyModes || []),
|
||||||
main,
|
main,
|
||||||
mode.main.allBases.slice(1)]).flatten().compact();
|
...mode.main.allBases.slice(1)];
|
||||||
|
|
||||||
if (builtin)
|
if (builtin)
|
||||||
hives = hives.filter(h => h.name === "builtin");
|
hives = hives.filter(h => h.name === "builtin");
|
||||||
|
|
||||||
this.processors = this.modes.map(m => hives.map(h => KeyProcessor(m, h)))
|
this.processors = this.modes.flatMap(mode => hives.map(hive => KeyProcessor(mode, hive)))
|
||||||
.flatten().array;
|
|
||||||
this.ownsBuffer = !this.processors.some(p => p.main.ownsBuffer);
|
this.ownsBuffer = !this.processors.some(p => p.main.ownsBuffer);
|
||||||
|
|
||||||
for (let input of this.processors) {
|
for (let input of this.processors) {
|
||||||
@@ -83,7 +82,7 @@ var ProcessorStack = Class("ProcessorStack", {
|
|||||||
if (this.ownsBuffer)
|
if (this.ownsBuffer)
|
||||||
statusline.inputBuffer = this.processors.length ? this.buffer : "";
|
statusline.inputBuffer = this.processors.length ? this.buffer : "";
|
||||||
|
|
||||||
if (!this.processors.some(p => !p.extended) && this.actions.length) {
|
if (this.processors.every(p => p.extended) && this.actions.length) {
|
||||||
// We have matching actions and no processors other than
|
// We have matching actions and no processors other than
|
||||||
// those waiting on further arguments. Execute actions as
|
// those waiting on further arguments. Execute actions as
|
||||||
// long as they continue to return PASS.
|
// long as they continue to return PASS.
|
||||||
@@ -115,9 +114,8 @@ var ProcessorStack = Class("ProcessorStack", {
|
|||||||
}
|
}
|
||||||
else if (result !== Events.KILL && !this.actions.length &&
|
else if (result !== Events.KILL && !this.actions.length &&
|
||||||
!(this.events[0].isReplay || this.passUnknown ||
|
!(this.events[0].isReplay || this.passUnknown ||
|
||||||
this.modes.some(function (m) {
|
this.modes.some(mode => mode.passEvent(this.events[0])))) {
|
||||||
return m.passEvent(this);
|
|
||||||
}, this.events[0]))) {
|
|
||||||
// No patching processors, this isn't a fake, pass-through
|
// No patching processors, this isn't a fake, pass-through
|
||||||
// event, we're not in pass-through mode, and we're not
|
// event, we're not in pass-through mode, and we're not
|
||||||
// choosing to pass unknown keys. Kill the event and beep.
|
// choosing to pass unknown keys. Kill the event and beep.
|
||||||
|
|||||||
@@ -306,6 +306,11 @@ var MOW = Module("mow", {
|
|||||||
set: function set_mowVisible(value) {
|
set: function set_mowVisible(value) {
|
||||||
this.widgets.mowContainer.collapsed = !value;
|
this.widgets.mowContainer.collapsed = !value;
|
||||||
|
|
||||||
|
// Don't block on the MOW iframe loading if we don't
|
||||||
|
// actually need it.
|
||||||
|
if (!value && !commandline.multilineOutputReady)
|
||||||
|
return;
|
||||||
|
|
||||||
let elem = this.widget;
|
let elem = this.widget;
|
||||||
if (!value && elem && elem.contentWindow == document.commandDispatcher.focusedWindow) {
|
if (!value && elem && elem.contentWindow == document.commandDispatcher.focusedWindow) {
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,33 @@ var ConfigBase = Class("ConfigBase", {
|
|||||||
"resource://dactyl-content/")));
|
"resource://dactyl-content/")));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.VCSPath) {
|
||||||
|
this.branch = new Promise(resolve => {
|
||||||
|
this.timeout(() => {
|
||||||
|
io.system(["hg", "-R", this.VCSPath, "branch"], "", true)
|
||||||
|
.then(result => {
|
||||||
|
resolve(result.output);
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._version = new Promise(resolve => {
|
||||||
|
this.timeout(() => {
|
||||||
|
io.system(["hg", "-R", this.VCSPath, "log", "-r.",
|
||||||
|
"--template=hg{rev}-{branch}"], "", true)
|
||||||
|
.then(result => {
|
||||||
|
this.version = result.output;
|
||||||
|
resolve(this.version);
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.branch = Promise.resolve((/pre-hg\d+-(\S*)/.exec(this.version) || [])[1]);
|
||||||
|
this._version = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.protocolLoaded = true;
|
this.protocolLoaded = true;
|
||||||
this.timeout(function () {
|
this.timeout(function () {
|
||||||
cache.register("config.dtd", () => util.makeDTD(config.dtd),
|
cache.register("config.dtd", () => util.makeDTD(config.dtd),
|
||||||
@@ -208,8 +235,19 @@ var ConfigBase = Class("ConfigBase", {
|
|||||||
get addonID() { return this.name + "@dactyl.googlecode.com"; },
|
get addonID() { return this.name + "@dactyl.googlecode.com"; },
|
||||||
|
|
||||||
addon: Class.Memoize(function () {
|
addon: Class.Memoize(function () {
|
||||||
return (JSMLoader.bootstrap || {}).addon ||
|
return (JSMLoader.bootstrap || {}).addon;
|
||||||
AddonManager.getAddonByID(this.addonID);
|
}),
|
||||||
|
|
||||||
|
addonData: Class.Memoize(function () {
|
||||||
|
return (JSMLoader.bootstrap || {}).addonData;
|
||||||
|
}),
|
||||||
|
|
||||||
|
basePath: Class.Memoize(function () {
|
||||||
|
return (JSMLoader.bootstrap || {}).basePath;
|
||||||
|
}),
|
||||||
|
|
||||||
|
resourceURI: Class.Memoize(function () {
|
||||||
|
return this.addonData.resourceURI;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
get styleableChrome() { return Object.keys(this.overlays); },
|
get styleableChrome() { return Object.keys(this.overlays); },
|
||||||
@@ -379,8 +417,10 @@ var ConfigBase = Class("ConfigBase", {
|
|||||||
* proxy file.
|
* proxy file.
|
||||||
*/
|
*/
|
||||||
VCSPath: Class.Memoize(function () {
|
VCSPath: Class.Memoize(function () {
|
||||||
if (/pre$/.test(this.addon.version)) {
|
if (/pre$/.test(this.addonData.version)) {
|
||||||
let uri = util.newURI(this.addon.getResourceURI("").spec + "../.hg");
|
// XXX: Sync.
|
||||||
|
let uri = util.newURI("../.hg", null, this.resourceURI);
|
||||||
|
|
||||||
if (uri instanceof Ci.nsIFileURL &&
|
if (uri instanceof Ci.nsIFileURL &&
|
||||||
uri.file.exists() &&
|
uri.file.exists() &&
|
||||||
io.pathSearch("hg"))
|
io.pathSearch("hg"))
|
||||||
@@ -389,17 +429,6 @@ var ConfigBase = Class("ConfigBase", {
|
|||||||
return null;
|
return null;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
/**
|
|
||||||
* @property {string} The name of the VCS branch that the application is
|
|
||||||
* running from if using an extension proxy file or was built from if
|
|
||||||
* installed as an XPI.
|
|
||||||
*/
|
|
||||||
branch: Class.Memoize(function () {
|
|
||||||
if (this.VCSPath)
|
|
||||||
return io.system(["hg", "-R", this.VCSPath, "branch"]).output;
|
|
||||||
return (/pre-hg\d+-(\S*)/.exec(this.version) || [])[1];
|
|
||||||
}),
|
|
||||||
|
|
||||||
/** @property {string} The name of the current user profile. */
|
/** @property {string} The name of the current user profile. */
|
||||||
profileName: Class.Memoize(function () {
|
profileName: Class.Memoize(function () {
|
||||||
// NOTE: services.profile.selectedProfile.name doesn't return
|
// NOTE: services.profile.selectedProfile.name doesn't return
|
||||||
@@ -417,10 +446,6 @@ var ConfigBase = Class("ConfigBase", {
|
|||||||
|
|
||||||
/** @property {string} The Dactyl version string. */
|
/** @property {string} The Dactyl version string. */
|
||||||
version: Class.Memoize(function () {
|
version: Class.Memoize(function () {
|
||||||
if (this.VCSPath)
|
|
||||||
return io.system(["hg", "-R", this.VCSPath, "log", "-r.",
|
|
||||||
"--template=hg{rev}-{branch}"]).output;
|
|
||||||
|
|
||||||
return this.addon.version;
|
return this.addon.version;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -659,10 +684,13 @@ config.INIT = update(Object.create(config.INIT), config.INIT, {
|
|||||||
load: function load(dactyl, modules, window) {
|
load: function load(dactyl, modules, window) {
|
||||||
load.superapply(this, arguments);
|
load.superapply(this, arguments);
|
||||||
|
|
||||||
this.timeout(function () {
|
this.timeout(() => {
|
||||||
if (this.branch && this.branch !== "default" &&
|
let list = modules.yes_i_know_i_should_not_report_errors_in_these_branches_thanks;
|
||||||
modules.yes_i_know_i_should_not_report_errors_in_these_branches_thanks.indexOf(this.branch) === -1)
|
|
||||||
dactyl.warn(_("warn.notDefaultBranch", config.appName, this.branch));
|
this.branch.then(branch => {
|
||||||
|
if (branch && branch !== "default" && !list.includes(branch))
|
||||||
|
dactyl.warn(_("warn.notDefaultBranch", config.appName, branch));
|
||||||
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -219,6 +219,20 @@ var IO = Module("io", {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
shell: Class.Memoize(() => {
|
||||||
|
if (config.OS.isWindows)
|
||||||
|
return "cmd.exe";
|
||||||
|
else
|
||||||
|
return services.environment.get("SHELL") || "sh";
|
||||||
|
}),
|
||||||
|
|
||||||
|
shellcmdflag: Class.Memoize(() => {
|
||||||
|
if (config.OS.isWindows)
|
||||||
|
return "/c";
|
||||||
|
else
|
||||||
|
return "-c";
|
||||||
|
}),
|
||||||
|
|
||||||
charsets: Class.Memoize(function () {
|
charsets: Class.Memoize(function () {
|
||||||
const BASE = "@mozilla.org/intl/unicode/decoder;1?charset=";
|
const BASE = "@mozilla.org/intl/unicode/decoder;1?charset=";
|
||||||
return Object.keys(Cc).filter(k.startsWith(BASE))
|
return Object.keys(Cc).filter(k.startsWith(BASE))
|
||||||
@@ -513,12 +527,14 @@ var IO = Module("io", {
|
|||||||
* command string or an array of strings (a command and arguments)
|
* command string or an array of strings (a command and arguments)
|
||||||
* which will be escaped and concatenated.
|
* which will be escaped and concatenated.
|
||||||
* @param {string} input Any input to be provided to the command on stdin.
|
* @param {string} input Any input to be provided to the command on stdin.
|
||||||
* @param {function(object)} callback A callback to be called when
|
* @param {function(object) | boolean} async A callback to be called when
|
||||||
* the command completes. @optional
|
* the command completes, or a boolean indicating that a
|
||||||
|
* promise should be returned. @optional
|
||||||
* @returns {object|null}
|
* @returns {object|null}
|
||||||
*/
|
*/
|
||||||
system: function system(command, input, callback) {
|
system: function system(command, input = "", async = false) {
|
||||||
util.dactyl.echomsg(_("io.callingShell", command), 4);
|
if (loaded.overlay)
|
||||||
|
util.dactyl.echomsg(_("io.callingShell", command), 4);
|
||||||
|
|
||||||
let { shellEscape } = util.bound;
|
let { shellEscape } = util.bound;
|
||||||
|
|
||||||
@@ -545,16 +561,28 @@ var IO = Module("io", {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function async(status) {
|
let deferred;
|
||||||
let output = stdout.read();
|
let promise = new Promise((resolve, reject) => {
|
||||||
for (let f of [stdin, stdout, cmd])
|
deferred = { resolve, reject };
|
||||||
if (f.exists())
|
});
|
||||||
f.remove(false);
|
if (callable(async))
|
||||||
callback(result(status, output));
|
promise.then(async);
|
||||||
|
|
||||||
|
function handleResult(status) {
|
||||||
|
stdout.async.read().then(output => {
|
||||||
|
deferred.resolve(result(status, output));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let shell = io.pathSearch(storage["options"].get("shell").value);
|
if (!storage["options"])
|
||||||
let shcf = storage["options"].get("shellcmdflag").value;
|
var { shell, shellcmdflag } = this;
|
||||||
|
else {
|
||||||
|
shell = storage["options"].get("shell").value;
|
||||||
|
shellcmdflag = storage["options"].get("shellcmdflag").value;
|
||||||
|
}
|
||||||
|
|
||||||
|
shell = io.pathSearch(shell);
|
||||||
|
|
||||||
util.assert(shell, _("error.invalid", "'shell'"));
|
util.assert(shell, _("error.invalid", "'shell'"));
|
||||||
|
|
||||||
if (isArray(command))
|
if (isArray(command))
|
||||||
@@ -563,16 +591,18 @@ var IO = Module("io", {
|
|||||||
// TODO: implement 'shellredir'
|
// TODO: implement 'shellredir'
|
||||||
if (config.OS.isWindows && !/sh/.test(shell.leafName)) {
|
if (config.OS.isWindows && !/sh/.test(shell.leafName)) {
|
||||||
command = "cd /D " + this.cwd.path + " && " + command + " > " + stdout.path + " 2>&1" + " < " + stdin.path;
|
command = "cd /D " + this.cwd.path + " && " + command + " > " + stdout.path + " 2>&1" + " < " + stdin.path;
|
||||||
var res = this.run(shell, shcf.split(/\s+/).concat(command), callback ? async : true);
|
var res = this.run(shell, shellcmdflag.split(/\s+/).concat(command), async ? handleResult : true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cmd.write("cd " + shellEscape(this.cwd.path) + "\n" +
|
cmd.write("cd " + shellEscape(this.cwd.path) + "\n" +
|
||||||
["exec", ">" + shellEscape(stdout.path), "2>&1", "<" + shellEscape(stdin.path),
|
["exec", ">" + shellEscape(stdout.path), "2>&1", "<" + shellEscape(stdin.path),
|
||||||
shellEscape(shell.path), shcf, shellEscape(command)].join(" "));
|
shellEscape(shell.path), shellcmdflag, shellEscape(command)].join(" "));
|
||||||
res = this.run("/bin/sh", ["-e", cmd.path], callback ? async : true);
|
res = this.run("/bin/sh", ["-e", cmd.path], async ? handleResult : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return callback ? true : result(res, stdout.read());
|
if (async)
|
||||||
|
return promise;
|
||||||
|
return result(res, stdout.read());
|
||||||
}, this, true);
|
}, this, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -591,6 +621,11 @@ var IO = Module("io", {
|
|||||||
let args = Array.from(util.range(0, func.length),
|
let args = Array.from(util.range(0, func.length),
|
||||||
() => this.createTempFile(ext, label));
|
() => this.createTempFile(ext, label));
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
// XXX: Sync.
|
||||||
|
args.forEach(f => { f.remove(false); });
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!args.every(identity))
|
if (!args.every(identity))
|
||||||
return false;
|
return false;
|
||||||
@@ -598,8 +633,10 @@ var IO = Module("io", {
|
|||||||
var res = func.apply(self || this, args);
|
var res = func.apply(self || this, args);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (!checked || res !== true)
|
if (res && typeof res === "object" && "then" in res && callable(res.then))
|
||||||
args.forEach(f => { f.remove(false); });
|
res.then(cleanup, cleanup);
|
||||||
|
else if (!checked || res !== true)
|
||||||
|
cleanup();
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -1180,15 +1217,7 @@ unlet s:cpo_save
|
|||||||
options: function initOptions(dactyl, modules, window) {
|
options: function initOptions(dactyl, modules, window) {
|
||||||
const { completion, options } = modules;
|
const { completion, options } = modules;
|
||||||
|
|
||||||
var shell, shellcmdflag;
|
let { shell, shellcmdflag } = io;
|
||||||
if (config.OS.isWindows) {
|
|
||||||
shell = "cmd.exe";
|
|
||||||
shellcmdflag = "/c";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
shell = services.environment.get("SHELL") || "sh";
|
|
||||||
shellcmdflag = "-c";
|
|
||||||
}
|
|
||||||
|
|
||||||
options.add(["banghist", "bh"],
|
options.add(["banghist", "bh"],
|
||||||
"Replace occurrences of ! with the previous command when executing external commands",
|
"Replace occurrences of ! with the previous command when executing external commands",
|
||||||
|
|||||||
@@ -920,9 +920,9 @@ var AsyncFile = Class("AsyncFile", File, {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
_setEncoding: function _setEncoding(options) {
|
_setEncoding: function _setEncoding(options) {
|
||||||
if (this.encoding != null && !("encoding" in options))
|
if (this.charset != null && !("encoding" in options))
|
||||||
options = update({}, options,
|
options = update({}, options,
|
||||||
{ encoding: this.encoding });
|
{ encoding: this.charset });
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -122,15 +122,14 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
|||||||
global = Class.objectGlobal(obj);
|
global = Class.objectGlobal(obj);
|
||||||
|
|
||||||
return (global && global.dactyl ||
|
return (global && global.dactyl ||
|
||||||
overlay.activeWindow && overlay.activeWindow.dactyl ||
|
loaded.overlay && overlay.activeWindow && overlay.activeWindow.dactyl ||
|
||||||
anythingObjectHack);
|
anythingObjectHack);
|
||||||
}, {
|
}, {
|
||||||
get(target, prop) {
|
get(target, prop) {
|
||||||
if (prop in target)
|
if (prop in target)
|
||||||
return target[prop];
|
return target[prop];
|
||||||
|
|
||||||
if (loaded.overlay)
|
return target()[prop];
|
||||||
return target()[prop];
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user