| Index: lib/io.js |
| =================================================================== |
| --- a/lib/io.js |
| +++ b/lib/io.js |
| @@ -20,16 +20,17 @@ |
| */ |
| Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
| Cu.import("resource://gre/modules/Services.jsm"); |
| Cu.import("resource://gre/modules/FileUtils.jsm"); |
| Cu.import("resource://gre/modules/NetUtil.jsm"); |
| let {TimeLine} = require("timeline"); |
| +let {Utils} = require("utils"); |
| let IO = exports.IO = |
| { |
| /** |
| * Retrieves the platform-dependent line break string. |
| */ |
| get lineBreak() |
| { |
| @@ -67,33 +68,32 @@ let IO = exports.IO = |
| * The callback will be called when the operation is done. |
| */ |
| readFromFile: function(/**nsIFile|nsIURI*/ file, /**Boolean*/ decode, /**Object*/ listener, /**Function*/ callback, /**String*/ timeLineID) |
| { |
| try |
| { |
| let processing = false; |
| let buffer = ""; |
| - let loadEvent = null; |
| - let errorEvent = null; |
| + let loaded = false; |
| + let error = Cr.NS_OK; |
| let uri = file instanceof Ci.nsIFile ? Services.io.newFileURI(file) : file; |
| let request = new XMLHttpRequest(); |
| request.mozBackgroundRequest = true; |
| request.open("GET", uri.spec); |
| request.responseType = "moz-chunked-text"; |
| request.overrideMimeType("text/plain" + (decode ? "? charset=utf-8" : "")); |
| - let onProgress = function(event) |
| + let onProgress = function(data) |
| { |
| if (timeLineID) |
| { |
| TimeLine.asyncStart(timeLineID); |
| } |
| - let data = event.target.response; |
| let index = (processing ? -1 : Math.max(data.lastIndexOf("\n"), data.lastIndexOf("\r"))); |
| if (index >= 0) |
| { |
| // Protect against reentrance in case the listener processes events. |
| processing = true; |
| try |
| { |
| let oldBuffer = buffer; |
| @@ -103,52 +103,49 @@ let IO = exports.IO = |
| lines.pop(); |
| lines[0] = oldBuffer + lines[0]; |
| for (let i = 0; i < lines.length; i++) |
| listener.process(lines[i]); |
| } |
| finally |
| { |
| processing = false; |
| - let e = { |
| - target: {response: buffer} |
| - }; |
| + data = buffer; |
| buffer = ""; |
| - onProgress(e); |
| + onProgress(data); |
| - if (loadEvent) |
| + if (loaded) |
| { |
| - let event = loadEvent; |
| - loadEvent = null; |
| - onLoad(event); |
| + loaded = false; |
| + onLoad(); |
| } |
| - if (errorEvent) |
| + if (error != Cr.NS_OK) |
| { |
| - let event = errorEvent; |
| - errorEvent = null; |
| - onError(event); |
| + let param = error; |
| + error = Cr.NS_OK; |
| + onError(param); |
| } |
| } |
| } |
| else |
| buffer += data; |
| if (timeLineID) |
| { |
| TimeLine.asyncEnd(timeLineID); |
| } |
| }; |
| - let onLoad = function(event) |
| + let onLoad = function() |
| { |
| if (processing) |
| { |
| // Still processing data, delay processing this event. |
| - loadEvent = event; |
| + loaded = true; |
| return; |
| } |
| if (timeLineID) |
| { |
| TimeLine.asyncStart(timeLineID); |
| } |
| @@ -160,38 +157,47 @@ let IO = exports.IO = |
| { |
| TimeLine.asyncEnd(timeLineID); |
| TimeLine.asyncDone(timeLineID); |
| } |
| callback(null); |
| }; |
| - let onError = function(event) |
| + let onError = function(status) |
| { |
| if (processing) |
| { |
| // Still processing data, delay processing this event. |
| - errorEvent = event; |
| + error = status; |
| return; |
| } |
| let e = Cc["@mozilla.org/js/xpc/Exception;1"].createInstance(Ci.nsIXPCException); |
| - e.initialize("File read operation failed", result, null, Components.stack, file, null); |
| + e.initialize("File read operation failed", status, null, Components.stack, file, null); |
| callback(e); |
| if (timeLineID) |
| { |
| TimeLine.asyncDone(timeLineID); |
| } |
| }; |
| - request.addEventListener("progress", onProgress, false); |
| - request.addEventListener("load", onLoad, false); |
| - request.addEventListener("error", onError, false); |
| + request.addEventListener("progress", function(event) |
| + { |
| + Utils.runAsync(onProgress.bind(this, event.target.response)); |
| + }, false); |
| + request.addEventListener("load", function(event) |
| + { |
| + Utils.runAsync(onLoad.bind(this)); |
| + }, false); |
| + request.addEventListener("error", function(event) |
| + { |
| + Utils.runAsync(onError.bind(this, event.target.channel.status)); |
| + }, false); |
| request.send(null); |
| } |
| catch (e) |
| { |
| callback(e); |
| } |
| }, |