put utility functions in an object to avoid namespace pollution

This commit is contained in:
Dan Mills 2008-02-13 14:30:44 -08:00
parent e81f3184d4
commit 907f537607
7 changed files with 297 additions and 296 deletions

View File

@ -46,7 +46,7 @@ Cu.import("resource://weave/log4moz.js");
Cu.import("resource://weave/constants.js");
Cu.import("resource://weave/util.js");
Function.prototype.async = generatorAsync;
Function.prototype.async = Utils.generatorAsync;
function WeaveCrypto() {
this._init();
@ -131,7 +131,7 @@ WeaveCrypto.prototype = {
PBEencrypt: function Crypto_PBEencrypt(onComplete, data, identity, algorithm) {
let [self, cont] = yield;
let listener = new EventListener(cont);
let listener = new Utils.EventListener(cont);
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
let ret;
@ -179,7 +179,7 @@ WeaveCrypto.prototype = {
} finally {
timer = null;
generatorDone(this, self, onComplete, ret);
Utils.generatorDone(this, self, onComplete, ret);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -187,7 +187,7 @@ WeaveCrypto.prototype = {
PBEdecrypt: function Crypto_PBEdecrypt(onComplete, data, identity, algorithm) {
let [self, cont] = yield;
let listener = new EventListener(cont);
let listener = new Utils.EventListener(cont);
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
let ret;
@ -235,7 +235,7 @@ WeaveCrypto.prototype = {
} finally {
timer = null;
generatorDone(this, self, onComplete, ret);
Utils.generatorDone(this, self, onComplete, ret);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -268,24 +268,24 @@ function openssl(op, algorithm, input, password) {
throw "encryption not supported on this platform: " + os;
}
let inputFile = getTmp("input");
let [inputFOS] = open(inputFile, ">");
let inputFile = Utils.getTmp("input");
let [inputFOS] = Utils.open(inputFile, ">");
inputFOS.write(input, input.length);
inputFOS.close();
let outputFile = getTmp("output");
let outputFile = Utils.getTmp("output");
if (outputFile.exists())
outputFile.remove(false);
// nsIProcess doesn't support stdin, so we write a file instead
let passFile = getTmp("pass");
let [passFOS] = open(passFile, ">", PERMS_PASSFILE);
let passFile = Utils.getTmp("pass");
let [passFOS] = Utils.open(passFile, ">", PERMS_PASSFILE);
passFOS.write(password, password.length);
passFOS.close();
try {
runCmd(wrap, getTmp().path, bin, algorithm, op, "-a", "-salt",
"-in", "input", "-out", "output", "-pass", "file:pass");
Utils.runCmd(wrap, Utils.getTmp().path, bin, algorithm, op, "-a", "-salt",
"-in", "input", "-out", "output", "-pass", "file:pass");
} catch (e) {
throw e;
} finally {
@ -293,8 +293,8 @@ function openssl(op, algorithm, input, password) {
inputFile.remove(false);
}
let [outputFIS] = open(outputFile, "<");
let ret = readStream(outputFIS);
let [outputFIS] = Utils.open(outputFile, "<");
let ret = Utils.readStream(outputFIS);
outputFIS.close();
outputFile.remove(false);

View File

@ -45,7 +45,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://weave/log4moz.js");
Cu.import("resource://weave/util.js");
Function.prototype.async = generatorAsync;
Function.prototype.async = Utils.generatorAsync;
/*
* DAV object
@ -90,8 +90,8 @@ DAVCollection.prototype = {
let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
request = request.QueryInterface(Ci.nsIDOMEventTarget);
request.addEventListener("load", new EventListener(cont, "load"), false);
request.addEventListener("error", new EventListener(cont, "error"), false);
request.addEventListener("load", new Utils.EventListener(cont, "load"), false);
request.addEventListener("error", new Utils.EventListener(cont, "error"), false);
request = request.QueryInterface(Ci.nsIXMLHttpRequest);
request.open(op, this._baseURL + path, true);
@ -128,7 +128,7 @@ DAVCollection.prototype = {
this._log.error("Exception caught: " + (e.message? e.message : e));
} finally {
generatorDone(this, self, onComplete, ret);
Utils.generatorDone(this, self, onComplete, ret);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -184,7 +184,7 @@ DAVCollection.prototype = {
this._log.error("Exception caught: " + (e.message? e.message : e));
} finally {
generatorDone(this, self, onComplete, ret);
Utils.generatorDone(this, self, onComplete, ret);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -244,7 +244,7 @@ DAVCollection.prototype = {
this._log.info("Logging in");
let URI = makeURI(this._baseURL);
let URI = Utils.makeURI(this._baseURL);
this._auth = "Basic " + btoa(username + ":" + password);
// Make a call to make sure it's working
@ -260,7 +260,7 @@ DAVCollection.prototype = {
this._log.error("Exception caught: " + (e.message? e.message : e));
} finally {
generatorDone(this, self, onComplete, this._loggedIn);
Utils.generatorDone(this, self, onComplete, this._loggedIn);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -290,7 +290,7 @@ DAVCollection.prototype = {
if (this._authProvider._authFailed || resp.status < 200 || resp.status >= 300)
return;
let tokens = xpath(resp.responseXML, '//D:locktoken/D:href');
let tokens = Utils.xpath(resp.responseXML, '//D:locktoken/D:href');
let token = tokens.iterateNext();
ret = token.textContent;
@ -302,7 +302,7 @@ DAVCollection.prototype = {
this._log.debug("Found an active lock token");
else
this._log.debug("No active lock token found");
generatorDone(this, self, onComplete, ret);
Utils.generatorDone(this, self, onComplete, ret);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -331,7 +331,7 @@ DAVCollection.prototype = {
if (this._authProvider._authFailed || resp.status < 200 || resp.status >= 300)
return;
let tokens = xpath(resp.responseXML, '//D:locktoken/D:href');
let tokens = Utils.xpath(resp.responseXML, '//D:locktoken/D:href');
let token = tokens.iterateNext();
if (token)
this._token = token.textContent;
@ -344,7 +344,7 @@ DAVCollection.prototype = {
this._log.info("Lock acquired");
else
this._log.warn("Could not acquire lock");
generatorDone(this, self, onComplete, this._token);
Utils.generatorDone(this, self, onComplete, this._token);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -374,10 +374,10 @@ DAVCollection.prototype = {
} finally {
if (this._token) {
this._log.info("Could not release lock");
generatorDone(this, self, onComplete, false);
Utils.generatorDone(this, self, onComplete, false);
} else {
this._log.info("Lock released (or we didn't have one)");
generatorDone(this, self, onComplete, true);
Utils.generatorDone(this, self, onComplete, true);
}
yield; // onComplete is responsible for closing the generator
}
@ -411,7 +411,7 @@ DAVCollection.prototype = {
this._log.debug("Lock released");
else
this._log.debug("No lock released");
generatorDone(this, self, onComplete, unlocked);
Utils.generatorDone(this, self, onComplete, unlocked);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -434,7 +434,7 @@ DAVCollection.prototype = {
this._log.error("Exception caught: " + (e.message? e.message : e));
} finally {
generatorDone(this, self, onComplete, stolen);
Utils.generatorDone(this, self, onComplete, stolen);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");

View File

@ -49,7 +49,7 @@ Cu.import("resource://weave/crypto.js");
Cu.import("resource://weave/stores.js");
Cu.import("resource://weave/syncCores.js");
Function.prototype.async = generatorAsync;
Function.prototype.async = Utils.generatorAsync;
let Crypto = new WeaveCrypto();
function Engine(davCollection, cryptoId) {
@ -171,7 +171,7 @@ Engine.prototype = {
this._log.debug("Server reset failed");
this._os.notifyObservers(null, this._osPrefix + "reset-server:error", "");
}
generatorDone(this, self, onComplete, done)
Utils.generatorDone(this, self, onComplete, done)
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -200,7 +200,7 @@ Engine.prototype = {
this._log.debug("Client reset failed");
this._os.notifyObservers(null, this._osPrefix + "reset-client:error", "");
}
generatorDone(this, self, onComplete, done);
Utils.generatorDone(this, self, onComplete, done);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -366,7 +366,7 @@ Engine.prototype = {
// Log an error if not the same
if (!(serverConflicts.length ||
deepEquals(serverChanges, serverDelta)))
Utils.deepEquals(serverChanges, serverDelta)))
this._log.warn("Predicted server changes differ from " +
"actual server->client diff (can be ignored in many cases)");
@ -437,10 +437,10 @@ Engine.prototype = {
}
if (ok && synced) {
this._os.notifyObservers(null, this._osPrefix + "sync:success", "");
generatorDone(this, self, onComplete, true);
Utils.generatorDone(this, self, onComplete, true);
} else {
this._os.notifyObservers(null, this._osPrefix + "sync:error", "");
generatorDone(this, self, onComplete, false);
Utils.generatorDone(this, self, onComplete, false);
}
yield; // onComplete is responsible for closing the generator
}
@ -496,7 +496,7 @@ Engine.prototype = {
if (status.formatVersion > STORAGE_FORMAT_VERSION) {
this._log.error("Server uses storage format v" + status.formatVersion +
", this client understands up to v" + STORAGE_FORMAT_VERSION);
generatorDone(this, self, onComplete, ret)
Utils.generatorDone(this, self, onComplete, ret)
return;
}
@ -634,7 +634,7 @@ Engine.prototype = {
this._log.error("Exception caught: " + (e.message? e.message : e));
} finally {
generatorDone(this, self, onComplete, ret)
Utils.generatorDone(this, self, onComplete, ret)
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -680,7 +680,7 @@ Engine.prototype = {
this._log.error("Exception caught: " + (e.message? e.message : e));
} finally {
generatorDone(this, self, onComplete, ret)
Utils.generatorDone(this, self, onComplete, ret)
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");

View File

@ -51,7 +51,7 @@ Cu.import("resource://weave/dav.js");
Cu.import("resource://weave/identity.js");
Function.prototype.async = generatorAsync;
Function.prototype.async = Utils.generatorAsync;
/*
* Service singleton
@ -61,6 +61,14 @@ Function.prototype.async = generatorAsync;
function WeaveSyncService() { this._init(); }
WeaveSyncService.prototype = {
__prefs: null,
get _prefs() {
if (!this.__prefs)
this.__prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
return this.__prefs;
},
__os: null,
get _os() {
if (!this.__os)
@ -122,17 +130,13 @@ WeaveSyncService.prototype = {
},
get username() {
let branch = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
return branch.getCharPref("extensions.weave.username");
return this._prefs.getCharPref("extensions.weave.username");
},
set username(value) {
let branch = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
if (value)
branch.setCharPref("extensions.weave.username", value);
this._prefs.setCharPref("extensions.weave.username", value);
else
branch.clearUserPref("extensions.weave.username");
this._prefs.clearUserPref("extensions.weave.username");
// fixme - need to loop over all Identity objects - needs some rethinking...
this._mozId.username = value;
@ -185,13 +189,11 @@ WeaveSyncService.prototype = {
let enabled = false;
let schedule = 0;
try {
let branch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
this._serverURL = branch.getCharPref("extensions.weave.serverURL");
enabled = branch.getBoolPref("extensions.weave.enabled");
schedule = branch.getIntPref("extensions.weave.schedule");
this._serverURL = this._prefs.getCharPref("extensions.weave.serverURL");
enabled = this._prefs.getBoolPref("extensions.weave.enabled");
schedule = this._prefs.getIntPref("extensions.weave.schedule");
branch.addObserver("extensions.weave", this, false);
this._prefs.addObserver("extensions.weave", this, false);
}
catch (ex) { /* use defaults */ }
@ -215,10 +217,13 @@ WeaveSyncService.prototype = {
}
},
_scheduleChanged: function WeaveSync__scheduleChanged() {
},
_enableSchedule: function WeaveSync__enableSchedule() {
this._scheduleTimer = Cc["@mozilla.org/timer;1"].
createInstance(Ci.nsITimer);
let listener = new EventListener(bind2(this, this._onSchedule));
let listener = new Utils.EventListener(Utils.bind2(this, this._onSchedule));
this._scheduleTimer.initWithCallback(listener, 1800000, // 30 min
this._scheduleTimer.TYPE_REPEATING_SLACK);
},
@ -345,7 +350,7 @@ WeaveSyncService.prototype = {
//this._log.debug("Login error");
this._os.notifyObservers(null, "weave:service-login:error", "");
}
generatorDone(this, self, onComplete, success);
Utils.generatorDone(this, self, onComplete, success);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -373,7 +378,7 @@ WeaveSyncService.prototype = {
this._log.debug("Server lock reset failed");
this._os.notifyObservers(null, "weave:server-lock-reset:error", "");
}
generatorDone(this, self, onComplete, success);
Utils.generatorDone(this, self, onComplete, success);
yield; // generatorDone is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -405,7 +410,7 @@ WeaveSyncService.prototype = {
this._os.notifyObservers(null, "weave:service:sync:success", "");
else
this._os.notifyObservers(null, "weave:service:sync:error", "");
generatorDone(this, self);
Utils.generatorDone(this, self);
yield; // generatorDone is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -427,7 +432,7 @@ WeaveSyncService.prototype = {
this._log.error("Exception caught: " + (e.message? e.message : e));
} finally {
generatorDone(this, self);
Utils.generatorDone(this, self);
yield; // generatorDone is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -449,7 +454,7 @@ WeaveSyncService.prototype = {
this._log.error("Exception caught: " + (e.message? e.message : e));
} finally {
generatorDone(this, self);
Utils.generatorDone(this, self);
yield; // generatorDone is responsible for closing the generator
}
this._log.warn("generator not properly closed");

View File

@ -360,7 +360,7 @@ BookmarksStore.prototype = {
item.title = node.title;
}
item.URI = node.uri;
item.tags = this._ts.getTagsForURI(makeURI(node.uri), {});
item.tags = this._ts.getTagsForURI(Utils.makeURI(node.uri), {});
item.keyword = this._bms.getKeywordForBookmark(node.itemId);
} else if (node.type == node.RESULT_TYPE_SEPARATOR) {
item.type = "separator";
@ -404,7 +404,7 @@ BookmarksStore.prototype = {
case "bookmark":
case "microsummary": {
this._log.info(" -> creating bookmark \"" + command.data.title + "\"");
let URI = makeURI(command.data.URI);
let URI = Utils.makeURI(command.data.URI);
newId = this._bms.insertBookmark(parentId,
URI,
command.data.index,
@ -415,7 +415,7 @@ BookmarksStore.prototype = {
if (command.data.type == "microsummary") {
this._log.info(" \-> is a microsummary");
let genURI = makeURI(command.data.generatorURI);
let genURI = Utils.makeURI(command.data.generatorURI);
try {
let micsum = this._ms.createMicrosummary(URI, genURI);
this._ms.setMicrosummary(newId, micsum);
@ -433,8 +433,8 @@ BookmarksStore.prototype = {
this._log.info(" -> creating livemark \"" + command.data.title + "\"");
newId = this._ls.createLivemark(parentId,
command.data.title,
makeURI(command.data.siteURI),
makeURI(command.data.feedURI),
Utils.makeURI(command.data.siteURI),
Utils.makeURI(command.data.feedURI),
command.data.index);
break;
case "separator":
@ -498,7 +498,7 @@ BookmarksStore.prototype = {
this._bms.setItemTitle(itemId, command.data.title);
break;
case "URI":
this._bms.changeBookmarkURI(itemId, makeURI(command.data.URI));
this._bms.changeBookmarkURI(itemId, Utils.makeURI(command.data.URI));
break;
case "index":
this._bms.moveItem(itemId, this._bms.getFolderIdForItem(itemId),
@ -520,16 +520,16 @@ BookmarksStore.prototype = {
this._bms.setKeywordForBookmark(itemId, command.data.keyword);
break;
case "generatorURI": {
let micsumURI = makeURI(this._bms.getBookmarkURI(itemId));
let genURI = makeURI(command.data.generatorURI);
let micsumURI = Utils.makeURI(this._bms.getBookmarkURI(itemId));
let genURI = Utils.makeURI(command.data.generatorURI);
let micsum = this._ms.createMicrosummary(micsumURI, genURI);
this._ms.setMicrosummary(itemId, micsum);
} break;
case "siteURI":
this._ls.setSiteURI(itemId, makeURI(command.data.siteURI));
this._ls.setSiteURI(itemId, Utils.makeURI(command.data.siteURI));
break;
case "feedURI":
this._ls.setFeedURI(itemId, makeURI(command.data.feedURI));
this._ls.setFeedURI(itemId, Utils.makeURI(command.data.feedURI));
break;
default:
this._log.warn("Can't change item property: " + key);
@ -595,10 +595,10 @@ HistoryStore.prototype = {
_createCommand: function HistStore__createCommand(command) {
this._log.info(" -> creating history entry: " + command.GUID);
try {
this._browserHist.addPageWithDetails(makeURI(command.GUID),
this._browserHist.addPageWithDetails(Utils.makeURI(command.GUID),
command.data.title,
command.data.time);
this._hsvc.setPageDetails(makeURI(command.GUID), command.data.title,
this._hsvc.setPageDetails(Utils.makeURI(command.GUID), command.data.title,
command.data.accessCount, false, false);
} catch (e) {
this._log.error("Exception caught: " + (e.message? e.message : e));

View File

@ -46,7 +46,7 @@ Cu.import("resource://weave/log4moz.js");
Cu.import("resource://weave/constants.js");
Cu.import("resource://weave/util.js");
Function.prototype.async = generatorAsync;
Function.prototype.async = Utils.generatorAsync;
/*
* SyncCore objects
@ -70,7 +70,7 @@ SyncCore.prototype = {
_getEdits: function SC__getEdits(a, b) {
let ret = {numProps: 0, props: {}};
for (prop in a) {
if (!deepEquals(a[prop], b[prop])) {
if (!Utils.deepEquals(a[prop], b[prop])) {
ret.numProps++;
ret.props[prop] = b[prop];
}
@ -91,7 +91,7 @@ SyncCore.prototype = {
_detectUpdates: function SC__detectUpdates(onComplete, a, b) {
let [self, cont] = yield;
let listener = new EventListener(cont);
let listener = new Utils.EventListener(cont);
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
let cmds = [];
@ -145,7 +145,7 @@ SyncCore.prototype = {
} finally {
timer = null;
generatorDone(this, self, onComplete, cmds);
Utils.generatorDone(this, self, onComplete, cmds);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");
@ -162,11 +162,11 @@ SyncCore.prototype = {
// Check that all other properties are the same
// FIXME: could be optimized...
for (let key in a) {
if (key != "GUID" && !deepEquals(a[key], b[key]))
if (key != "GUID" && !Utils.deepEquals(a[key], b[key]))
return false;
}
for (let key in b) {
if (key != "GUID" && !deepEquals(a[key], b[key]))
if (key != "GUID" && !Utils.deepEquals(a[key], b[key]))
return false;
}
return true;
@ -189,7 +189,7 @@ SyncCore.prototype = {
},
_conflicts: function SC__conflicts(a, b) {
if ((a.GUID == b.GUID) && !deepEquals(a, b))
if ((a.GUID == b.GUID) && !Utils.deepEquals(a, b))
return true;
return false;
},
@ -218,7 +218,7 @@ SyncCore.prototype = {
_reconcile: function SC__reconcile(onComplete, listA, listB) {
let [self, cont] = yield;
let listener = new EventListener(cont);
let listener = new Utils.EventListener(cont);
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
let propagations = [[], []];
@ -242,7 +242,7 @@ SyncCore.prototype = {
if (skip)
return true;
if (deepEquals(a, b)) {
if (Utils.deepEquals(a, b)) {
delete listA[i]; // a
skip = true;
return false; // b
@ -301,7 +301,7 @@ SyncCore.prototype = {
} finally {
timer = null;
generatorDone(this, self, onComplete, ret);
Utils.generatorDone(this, self, onComplete, ret);
yield; // onComplete is responsible for closing the generator
}
this._log.warn("generator not properly closed");

View File

@ -34,10 +34,7 @@
*
* ***** END LICENSE BLOCK ***** */
const EXPORTED_SYMBOLS = ['deepEquals', 'makeFile', 'makeURI', 'xpath',
'bind2', 'generatorAsync', 'generatorDone',
'EventListener',
'runCmd', 'getTmp', 'open', 'readStream'];
const EXPORTED_SYMBOLS = ['Utils'];
const Cc = Components.classes;
const Ci = Components.interfaces;
@ -52,132 +49,223 @@ Cu.import("resource://weave/log4moz.js");
* Utility functions
*/
function deepEquals(a, b) {
if (!a && !b)
let Utils = {
deepEquals: function Weave_deepEquals(a, b) {
if (!a && !b)
return true;
if (!a || !b)
return false;
if (typeof(a) != "object" && typeof(b) != "object")
return a == b;
if (typeof(a) != "object" || typeof(b) != "object")
return false;
for (let key in a) {
if (typeof(a[key]) == "object") {
if (!typeof(b[key]) == "object")
return false;
if (!Utils.deepEquals(a[key], b[key]))
return false;
} else {
if (a[key] != b[key])
return false;
}
}
return true;
if (!a || !b)
return false;
},
if (typeof(a) != "object" && typeof(b) != "object")
return a == b;
if (typeof(a) != "object" || typeof(b) != "object")
return false;
for (let key in a) {
if (typeof(a[key]) == "object") {
if (!typeof(b[key]) == "object")
return false;
if (!deepEquals(a[key], b[key]))
return false;
} else {
if (a[key] != b[key])
return false;
}
}
return true;
}
function makeFile(path) {
var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
file.initWithPath(path);
return file;
}
function makeURI(URIString) {
if (URIString === null || URIString == "")
return null;
let ioservice = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
return ioservice.newURI(URIString, null, null);
}
function xpath(xmlDoc, xpathString) {
let root = xmlDoc.ownerDocument == null ?
xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement
let nsResolver = xmlDoc.createNSResolver(root);
return xmlDoc.evaluate(xpathString, xmlDoc, nsResolver,
Ci.nsIDOMXPathResult.ANY_TYPE, null);
}
function bind2(object, method) {
return function innerBind() { return method.apply(object, arguments); }
}
// Meant to be used like this in code that imports this file:
//
// Function.prototype.async = generatorAsync;
//
// So that you can do:
//
// gen = fooGen.async(...);
// ret = yield;
//
// where fooGen is a generator function, and gen is the running generator.
// ret is whatever the generator 'returns' via generatorDone().
function generatorAsync(self, extra_args) {
try {
let args = Array.prototype.slice.call(arguments, 1);
let gen = this.apply(self, args);
gen.next(); // must initialize before sending
gen.send([gen, function(data) {continueGenerator(gen, data);}]);
return gen;
} catch (e) {
if (e instanceof StopIteration) {
dump("async warning: generator stopped unexpectedly");
makeURI: function Weave_makeURI(URIString) {
if (URIString === null || URIString == "")
return null;
} else {
dump("Exception caught: " + e.message);
let ioservice = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
return ioservice.newURI(URIString, null, null);
},
xpath: function Weave_xpath(xmlDoc, xpathString) {
let root = xmlDoc.ownerDocument == null ?
xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement
let nsResolver = xmlDoc.createNSResolver(root);
return xmlDoc.evaluate(xpathString, xmlDoc, nsResolver,
Ci.nsIDOMXPathResult.ANY_TYPE, null);
},
bind2: function Weave_bind2(object, method) {
return function innerBind() { return method.apply(object, arguments); }
},
// Meant to be used like this in code that imports this file:
//
// Function.prototype.async = generatorAsync;
//
// So that you can do:
//
// gen = fooGen.async(...);
// ret = yield;
//
// where fooGen is a generator function, and gen is the running generator.
// ret is whatever the generator 'returns' via generatorDone().
generatorAsync: function Weave_generatorAsync(self, extra_args) {
try {
let args = Array.prototype.slice.call(arguments, 1);
let gen = this.apply(self, args);
gen.next(); // must initialize before sending
gen.send([gen, function(data) {Utils.continueGenerator(gen, data);}]);
return gen;
} catch (e) {
if (e instanceof StopIteration) {
dump("async warning: generator stopped unexpectedly");
return null;
} else {
dump("Exception caught: " + e.message);
}
}
},
continueGenerator: function Weave_continueGenerator(generator, data) {
try { generator.send(data); }
catch (e) {
if (e instanceof StopIteration)
dump("continueGenerator warning: generator stopped unexpectedly");
else
dump("Exception caught: " + e.message);
}
},
// generators created using Function.async can't simply call the
// callback with the return value, since that would cause the calling
// function to end up running (after the yield) from inside the
// generator. Instead, generators can call this method which sets up
// a timer to call the callback from a timer (and cleans up the timer
// to avoid leaks). It also closes generators after the timeout, to
// keep things clean.
generatorDone: function Weave_generatorDone(object, generator, callback, retval) {
if (object._timer)
throw "Called generatorDone when there is a timer already set."
let cb = Utils.bind2(object, function(event) {
generator.close();
generator = null;
object._timer = null;
if (callback)
callback(retval);
});
object._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
object._timer.initWithCallback(new Utils.EventListener(cb),
0, object._timer.TYPE_ONE_SHOT);
},
runCmd: function Weave_runCmd() {
var binary;
var args = [];
for (let i = 0; i < arguments.length; ++i) {
args.push(arguments[i]);
}
if (args[0] instanceof Ci.nsIFile) {
binary = args.shift();
} else {
binary = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
binary.initWithPath(args.shift());
}
var p = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
p.init(binary);
p.run(true, args, args.length);
return p.exitValue;
},
getTmp: function Weave_getTmp(name) {
let ds = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
let tmp = ds.get("ProfD", Ci.nsIFile);
tmp.QueryInterface(Ci.nsILocalFile);
tmp.append("weave");
tmp.append("tmp");
if (!tmp.exists())
tmp.create(tmp.DIRECTORY_TYPE, PERMS_DIRECTORY);
if (name)
tmp.append(name);
return tmp;
},
open: function open(pathOrFile, mode, perms) {
let stream, file;
if (pathOrFile instanceof Ci.nsIFile) {
file = pathOrFile;
} else {
file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
dump("PATH IS" + pathOrFile + "\n");
file.initWithPath(pathOrFile);
}
if (!perms)
perms = PERMS_FILE;
switch(mode) {
case "<": {
if (!file.exists())
throw "Cannot open file for reading, file does not exist";
stream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
stream.init(file, MODE_RDONLY, perms, 0);
stream.QueryInterface(Ci.nsILineInputStream);
} break;
case ">": {
stream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
stream.init(file, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, perms, 0);
} break;
case ">>": {
stream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
stream.init(file, MODE_WRONLY | MODE_CREATE | MODE_APPEND, perms, 0);
} break;
default:
throw "Illegal mode to open(): " + mode;
}
return [stream, file];
},
readStream: function Weave_readStream(fis) {
let data = "";
while (fis.available()) {
let ret = {};
fis.readLine(ret);
data += ret.value;
}
return data;
},
/*
* Event listener object
* Used to handle XMLHttpRequest and nsITimer callbacks
*/
EventListener: function Weave_EventListener(handler, eventName) {
this._handler = handler;
this._eventName = eventName;
this._log = Log4Moz.Service.getLogger("Service.EventHandler");
}
}
};
function continueGenerator(generator, data) {
try { generator.send(data); }
catch (e) {
if (e instanceof StopIteration)
dump("continueGenerator warning: generator stopped unexpectedly");
else
dump("Exception caught: " + e.message);
}
}
// generators created using Function.async can't simply call the
// callback with the return value, since that would cause the calling
// function to end up running (after the yield) from inside the
// generator. Instead, generators can call this method which sets up
// a timer to call the callback from a timer (and cleans up the timer
// to avoid leaks). It also closes generators after the timeout, to
// keep things clean.
function generatorDone(object, generator, callback, retval) {
if (object._timer)
throw "Called generatorDone when there is a timer already set."
let cb = bind2(object, function(event) {
generator.close();
generator = null;
object._timer = null;
if (callback)
callback(retval);
});
object._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
object._timer.initWithCallback(new EventListener(cb),
0, object._timer.TYPE_ONE_SHOT);
}
/*
* Event listener object
* Used to handle XMLHttpRequest and nsITimer callbacks
*/
function EventListener(handler, eventName) {
this._handler = handler;
this._eventName = eventName;
this._log = Log4Moz.Service.getLogger("Service.EventHandler");
}
EventListener.prototype = {
Utils.EventListener.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback, Ci.nsISupports]),
// DOM event listener
@ -191,96 +279,4 @@ EventListener.prototype = {
this._log.trace("Timer fired");
this._handler(timer);
}
};
function runCmd() {
var binary;
var args = [];
for (let i = 0; i < arguments.length; ++i) {
args.push(arguments[i]);
}
if (args[0] instanceof Ci.nsIFile) {
binary = args.shift();
} else {
binary = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
binary.initWithPath(args.shift());
}
var p = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
p.init(binary);
p.run(true, args, args.length);
return p.exitValue;
}
function getTmp(name) {
let ds = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
let tmp = ds.get("ProfD", Ci.nsIFile);
tmp.QueryInterface(Ci.nsILocalFile);
tmp.append("weave");
tmp.append("tmp");
if (!tmp.exists())
tmp.create(tmp.DIRECTORY_TYPE, PERMS_DIRECTORY);
if (name)
tmp.append(name);
return tmp;
}
function open(pathOrFile, mode, perms) {
let stream, file;
if (pathOrFile instanceof Ci.nsIFile) {
file = pathOrFile;
} else {
file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
file.initWithPath(pathOrFile);
}
if (!perms)
perms = PERMS_FILE;
switch(mode) {
case "<": {
if (!file.exists())
throw "Cannot open file for reading, file does not exist";
stream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
stream.init(file, MODE_RDONLY, perms, 0);
stream.QueryInterface(Ci.nsILineInputStream);
} break;
case ">": {
stream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
stream.init(file, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, perms, 0);
} break;
case ">>": {
stream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
stream.init(file, MODE_WRONLY | MODE_CREATE | MODE_APPEND, perms, 0);
} break;
default:
throw "Illegal mode to open(): " + mode;
}
return [stream, file];
}
function readStream(fis) {
let data = "";
while (fis.available()) {
let ret = {};
fis.readLine(ret);
data += ret.value;
}
return data;
}