1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2026-02-14 17:05:46 +01:00

Promises cleanup.

This commit is contained in:
Kris Maglione
2015-03-02 18:12:57 -08:00
parent c84c657d27
commit 7b2f821e04
10 changed files with 160 additions and 126 deletions

View File

@@ -182,7 +182,6 @@ defineModule("base", {
"Cr",
"Cs",
"Cu",
"DOMPromise",
"ErrorBase",
"Finished",
"JSMLoader",
@@ -762,12 +761,6 @@ function memoize(obj, key, getter) {
}
}
let sandbox = Cu.Sandbox(Cc["@mozilla.org/systemprincipal;1"].createInstance(),
{ wantGlobalProperties: ["TextDecoder", "TextEncoder"],
sandboxPrototype: this });
var { TextEncoder, TextDecoder, Promise: DOMPromise } = sandbox;
/**
* Updates an object with the properties of another object. Getters
* and setters are copied as expected. Moreover, any function

View File

@@ -15,6 +15,9 @@ this["import"] = function import_(obj) {
return res;
}
if (typeof TextEncoder == "undefined")
Components.utils.importGlobalProperties(["TextEncoder", "TextDecoder"]);
// Deal with subScriptLoader prepending crap to loaded URLs
Components.utils.import("resource://gre/modules/Services.jsm");
function loadSubScript() Services.scriptloader.loadSubScript.apply(null, arguments);

View File

@@ -86,26 +86,28 @@ var Buffer = Module("Buffer", {
* @param {string} pref The name of the preference to return.
* @returns {Promise<*>}
*/
get: promises.withCallbacks(function get([resolve, reject], pref) {
let val = services.contentPrefs.getCachedByDomainAndName(
self.uri.spec, pref, self.loadContext);
get: function get(pref) {
return new Promise((resolve, reject) => {
let val = services.contentPrefs.getCachedByDomainAndName(
self.uri.spec, pref, self.loadContext);
let found = false;
if (val)
resolve(val.value);
else
services.contentPrefs.getByDomainAndName(
self.uri.spec, pref, self.loadContext,
{ handleCompletion: () => {
if (!found)
resolve(undefined);
},
handleResult: (pref) => {
found = true;
resolve(pref.value);
},
handleError: reject });
}),
let found = false;
if (val)
resolve(val.value);
else
services.contentPrefs.getByDomainAndName(
self.uri.spec, pref, self.loadContext,
{ handleCompletion: () => {
if (!found)
resolve(undefined);
},
handleResult: (pref) => {
found = true;
resolve(pref.value);
},
handleError: reject });
});
},
/**
* Sets a content preference for the given buffer.
@@ -113,26 +115,30 @@ var Buffer = Module("Buffer", {
* @param {string} pref The preference to set.
* @param {string} value The value to store.
*/
set: promises.withCallbacks(function set([resolve, reject], pref, value) {
services.contentPrefs.set(
self.uri.spec, pref, value, self.loadContext,
{ handleCompletion: () => {},
handleResult: resolve,
handleError: reject });
}),
set: function set(pref, value) {
return new Promise((resolve, reject) => {
services.contentPrefs.set(
self.uri.spec, pref, value, self.loadContext,
{ handleCompletion: () => {},
handleResult: resolve,
handleError: reject });
});
},
/**
* Clear a content preference for the given buffer.
*
* @param {string} pref The preference to clear.
*/
clear: promises.withCallbacks(function clear([resolve, reject], pref) {
services.contentPrefs.removeByDomainAndName(
self.uri.spec, pref, self.loadContext,
{ handleCompletion: () => {},
handleResult: resolve,
handleError: reject });
})
clear: function clear(pref) {
return new Promise((resolve, reject) => {
services.contentPrefs.removeByDomainAndName(
self.uri.spec, pref, self.loadContext,
{ handleCompletion: () => {},
handleResult: resolve,
handleError: reject });
});
}
};
}),

View File

@@ -140,7 +140,7 @@ var ConfigBase = Class("ConfigBase", {
"options",
"overlay",
"prefs",
["promises", "Promise", "Task", "promises"],
["promises", "CancelablePromise", "Promise", "Task", "promises"],
"protocol",
"sanitizer",
"services",

View File

@@ -95,9 +95,9 @@ var Modules = function Modules(window) {
if (normal)
return create(proto);
sandbox = Components.utils.Sandbox(window, { sandboxPrototype: proto || modules,
sandboxName: name || ("Dactyl Sandbox " + ++_id),
wantXrays: true });
let sandbox = Components.utils.Sandbox(window, { sandboxPrototype: proto || modules,
sandboxName: name || ("Dactyl Sandbox " + ++_id),
wantXrays: true });
// Hack:
// sandbox.Object = jsmodules.Object;

View File

@@ -5,7 +5,7 @@
"use strict";
defineModule("promises", {
exports: ["Promise", "Task", "promises"],
exports: ["CancelablePromise", "Promise", "Task", "promises"],
require: []
});
@@ -24,6 +24,26 @@ function withCallbacks(fn) {
}
}
function CancelablePromise(executor, oncancel) {
let deferred = Promise.defer();
let canceled = new Promise((accept, reject) => {
promises.oncancel(deferred, accept);
});
try {
executor(deferred.resolve, deferred.reject, canceled);
}
catch (e) {
deferred.reject(e);
}
return Object.freeze(Object.create(deferred.promise, {
cancel: {
value: thing => promises.cancel(deferred.promise, thing)
}
}));
}
var Promises = Module("Promises", {
_cancel: new WeakMap,
@@ -38,7 +58,7 @@ var Promises = Module("Promises", {
let cleanup = this._cancel.get(promise);
if (cleanup) {
cleanup[0](promise);
cleanup[1].reject(reason);
cleanup[1](reason);
}
this._cancel.delete(promise);
},
@@ -50,16 +70,18 @@ var Promises = Module("Promises", {
* @param {function} fn The cleanup function.
*/
oncancel: function oncancel(deferred, fn) {
this._cancel.set(deferred.promise, [fn, deferred]);
this._cancel.set(deferred.promise, [fn, deferred.reject]);
},
/**
* Returns a promise which resolves after a brief delay.
*/
delay: withCallbacks(function delay([accept]) {
let { mainThread } = services.threading;
mainThread.dispatch(accept, mainThread.DISPATCH_NORMAL);
}),
delay: function delay([accept]) {
return new Promise(resolve => {
let { mainThread } = services.threading;
mainThread.dispatch(resolve, mainThread.DISPATCH_NORMAL);
});
},
/**
* Returns a promise which resolves after the given number of
@@ -67,9 +89,11 @@ var Promises = Module("Promises", {
*
* @param {number} delay The number of milliseconds to wait.
*/
sleep: withCallbacks(function sleep([callback], delay) {
this.timeout(callback, delay);
}),
sleep: function sleep(delay) {
return new Promise(resolve => {
this.timeout(resolve, delay);
});
},
/**
* Wraps the given function so that each call spawns a Task.
@@ -94,25 +118,27 @@ var Promises = Module("Promises", {
* @param {number} pollInterval The poll interval, in milliseconds.
* @default 10
*/
waitFor: withCallbacks(function waitFor([accept, reject], test, timeout=null, pollInterval=10) {
let end = timeout && Date.now() + timeout, result;
waitFor: function waitFor(test, timeout=null, pollInterval=10) {
return new Promise((resolve, reject) => {
let end = timeout && Date.now() + timeout, result;
let timer = services.Timer(
() => {
try {
var result = test();
}
catch (e) {
timer.cancel();
reject(e);
}
if (result) {
timer.cancel();
accept(result);
}
},
pollInterval, services.Timer.TYPE_REPEATING_SLACK);
}),
let timer = services.Timer(
() => {
try {
var result = test();
}
catch (e) {
timer.cancel();
reject(e);
}
if (result) {
timer.cancel();
resolve(result);
}
},
pollInterval, services.Timer.TYPE_REPEATING_SLACK);
});
},
/**
* Wraps the given function so that its first argument is an array

View File

@@ -828,14 +828,16 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
* @param {string} url The URL to fetch.
* @param {object} params Parameter object, as in #httpGet.
*/
fetchUrl: promises.withCallbacks(function fetchUrl([accept, reject, deferred], url, params) {
params = update({}, params);
params.onload = accept;
params.onerror = reject;
fetchUrl: function fetchUrl(url, params) {
return new CancelablePromise((accept, reject, canceled) => {
params = update({}, params);
params.onload = accept;
params.onerror = reject;
let req = this.httpGet(url, params);
promises.oncancel(deferred, req.cancel);
}),
let req = this.httpGet(url, params);
canceled.then(req.cancel);
});
},
/**
* The identity function.