Index: lib/io.js |
=================================================================== |
--- a/lib/io.js |
+++ b/lib/io.js |
@@ -50,125 +50,183 @@ function callWebExt(method, ...args) |
{ |
let id = ++messageID; |
messageCallbacks.set(id, {resolve, reject}); |
port.postMessage({id, method, args}); |
}); |
}); |
} |
-function attachCallback(promise, callback, fallback) |
+function callLegacy(method, ...args) |
{ |
- promise.then(result => |
+ return new Promise((resolve, reject) => |
{ |
- callback(null, result); |
- }).catch(error => |
- { |
- if (fallback && error == "NoSuchFile") |
- fallback(); |
- else |
- callback(error); |
+ LegacyIO[method](...args, (error, result) => |
+ { |
+ if (error) |
+ reject(error); |
+ else |
+ resolve(result); |
+ }); |
}); |
} |
+function legacyFile(fileName) |
+{ |
+ let file = LegacyIO.resolveFilePath("adblockplus"); |
+ file.append(fileName); |
+ return file; |
+} |
+ |
exports.IO = |
{ |
- resolveFilePath: LegacyIO.resolveFilePath, |
+ /** |
+ * @callback TextSink |
+ * @param {string} line |
+ */ |
/** |
- * Reads strings from a file asynchronously, calls listener.process() with |
- * each line read and with a null parameter once the read operation is done. |
- * The callback will be called when the operation is done. |
+ * Reads text lines from a file. |
+ * @param {string} fileName |
+ * Name of the file to be read |
+ * @param {TextSink} listener |
+ * Function that will be called for each line in the file |
+ * @return {Promise} |
+ * Promise to be resolved or rejected once the operation is completed |
*/ |
- readFromFile(/**nsIFile*/ file, /**Object*/ listener, /**Function*/ callback) |
+ readFromFile(fileName, listener) |
{ |
- attachCallback( |
- callWebExt("readFromFile", file.leafName).then(contents => |
+ return callWebExt("readFromFile", fileName).then(contents => |
+ { |
+ return new Promise((resolve, reject) => |
{ |
- return new Promise((resolve, reject) => |
+ let lineIndex = 0; |
+ |
+ function processBatch() |
{ |
- let lineIndex = 0; |
- |
- function processBatch() |
+ while (lineIndex < contents.length) |
{ |
- while (lineIndex < contents.length) |
+ listener(contents[lineIndex++]); |
+ if (lineIndex % 1000 == 0) |
{ |
- listener.process(contents[lineIndex++]); |
- if (lineIndex % 1000 == 0) |
- { |
- Utils.runAsync(processBatch); |
- return; |
- } |
+ Utils.runAsync(processBatch); |
+ return; |
} |
+ } |
+ resolve(); |
+ } |
- listener.process(null); |
- resolve(); |
+ processBatch(); |
+ }); |
+ }).catch(error => |
+ { |
+ if (error == "NoSuchFile") |
+ { |
+ let wrapper = { |
+ process(line) |
+ { |
+ if (line !== null) |
+ listener(line); |
} |
- |
- processBatch(); |
- }); |
- }), |
- callback, |
- () => LegacyIO.readFromFile(file, listener, callback) |
- ); |
+ }; |
+ return callLegacy("readFromFile", legacyFile(fileName), wrapper); |
+ } |
+ throw error; |
+ }); |
}, |
/** |
- * Writes string data to a file in UTF-8 format asynchronously. The callback |
- * will be called when the write operation is done. |
+ * Writes text lines to a file. |
+ * @param {string} fileName |
+ * Name of the file to be written |
+ * @param {Iterable.<string>} data |
+ * An array-like or iterable object containing the lines (without line |
+ * endings) |
+ * @return {Promise} |
+ * Promise to be resolved or rejected once the operation is completed |
*/ |
- writeToFile(/**nsIFile*/ file, /**Iterator*/ data, /**Function*/ callback) |
+ writeToFile(fileName, data) |
{ |
- attachCallback( |
- callWebExt("writeToFile", file.leafName, Array.from(data)), |
- callback |
- ); |
- }, |
- |
- /** |
- * Copies a file asynchronously. The callback will be called when the copy |
- * operation is done. |
- */ |
- copyFile(/**nsIFile*/ fromFile, /**nsIFile*/ toFile, /**Function*/ callback) |
- { |
- attachCallback( |
- callWebExt("copyFile", fromFile.leafName, toFile.leafName), |
- callback, |
- () => LegacyIO.copyFile(fromFile, toFile, callback) |
- ); |
+ return callWebExt("writeToFile", fileName, Array.from(data)); |
}, |
/** |
- * Renames a file within the same directory, will call callback when done. |
+ * Copies a file. |
+ * @param {string} fromFile |
+ * Name of the file to be copied |
+ * @param {string} toFile |
+ * Name of the file to be written, will be overwritten if exists |
+ * @return {Promise} |
+ * Promise to be resolved or rejected once the operation is completed |
*/ |
- renameFile(/**nsIFile*/ fromFile, /**String*/ newName, /**Function*/ callback) |
+ copyFile(fromFile, toFile) |
{ |
- attachCallback( |
- callWebExt("renameFile", fromFile.leafName, newName), |
- callback, |
- () => LegacyIO.renameFile(fromFile, newName, callback) |
- ); |
+ return callWebExt("copyFile", fromFile, toFile).catch(error => |
+ { |
+ if (error == "NoSuchFile") |
kzar
2017/04/20 10:25:07
It seems like this pattern is repeated quite a bit
Wladimir Palant
2017/04/20 12:02:06
I thought about it but couldn't see a way requirin
kzar
2017/04/20 12:11:59
Hmm I guess not. I didn't realise the arguments pa
|
+ return callLegacy("copyFile", legacyFile(fromFile), legacyFile(toFile)); |
+ throw error; |
+ }); |
}, |
/** |
- * Removes a file, will call callback when done. |
+ * Renames a file. |
+ * @param {string} fromFile |
+ * Name of the file to be renamed |
+ * @param {string} newName |
+ * New file name, will be overwritten if exists |
+ * @return {Promise} |
+ * Promise to be resolved or rejected once the operation is completed |
*/ |
- removeFile(/**nsIFile*/ file, /**Function*/ callback) |
+ renameFile(fromFile, newName) |
{ |
- attachCallback( |
- callWebExt("removeFile", file.leafName), |
- callback, |
- () => LegacyIO.removeFile(file, callback) |
- ); |
+ return callWebExt("renameFile", fromFile, newName).catch(error => |
+ { |
+ if (error == "NoSuchFile") |
+ return callLegacy("renameFile", legacyFile(fromFile), newName); |
+ throw error; |
+ }); |
}, |
/** |
- * Gets file information such as whether the file exists. |
+ * Removes a file. |
+ * @param {string} fileName |
+ * Name of the file to be removed |
+ * @return {Promise} |
+ * Promise to be resolved or rejected once the operation is completed |
*/ |
- statFile(/**nsIFile*/ file, /**Function*/ callback) |
+ removeFile(fileName) |
{ |
- attachCallback( |
- callWebExt("statFile", file.leafName), |
- callback, |
- () => LegacyIO.statFile(file, callback) |
- ); |
+ return callWebExt("removeFile", fileName).catch(error => |
+ { |
+ if (error == "NoSuchFile") |
+ return callLegacy("removeFile", legacyFile(fileName)); |
+ throw error; |
+ }); |
+ }, |
+ |
+ /** |
+ * @typedef StatData |
+ * @type {object} |
+ * @property {boolean} exists |
+ * true if the file exists |
+ * @property {number} lastModified |
+ * file modification time in milliseconds |
+ */ |
+ |
+ /** |
+ * Retrieves file metadata. |
+ * @param {string} fileName |
+ * Name of the file to be looked up |
+ * @return {Promise.<StatData>} |
+ * Promise to be resolved with file metadata once the operation is |
+ * completed |
+ */ |
+ statFile(fileName) |
+ { |
+ return callWebExt("statFile", fileName).catch(error => |
+ { |
+ if (error == "NoSuchFile") |
+ return callLegacy("statFile", legacyFile(fileName)); |
+ throw error; |
+ }); |
} |
}; |