Search code examples
javascriptfirefox-addonfirefox-addon-sdk

How do I use OS.File.open?


function write_text(filename, text) {
    let pfh = yield OS.File.open("/tmp/foo", {append: true});
    yield pfh.write(text);
    yield pfh.flush();
    yield pfh.close(); 
}

I tried without the yield which is the more natural form but that broke: In python i'd do yielded_object.next()

error: scribus-web-slurp: An exception occurred.
TypeError: pfh.write is not a function
resource://jid1-orxy9dnn8jbfeq-at-jetpack/scribus-web-slurp/lib/main.js 28
Traceback (most recent call last):

I know Javascript but it's the Firefox-extensions that are causing problems - are there any tutorials that can walk me through the process or bring me up to scratch?? The MDN documentation is too exhaustive and I don;t know where to start.


Solution

  • The async OS.File API returns Promises. It is best used with Task.jsm

    function write_text(filename, text) {
        var encoder = new TextEncoder();
        var data = encoder.encode(text);
        Task.spawn(function() {
            let pfh = yield OS.File.open("/tmp/foo", {write: true});
            yield pfh.write(data);
            yield pfh.close(); 
        });
    }
    

    The documentation has a some examples.

    Also, don't flush() if you don't have to (and flush() in the async API is only available in Firefox 27 anyway)

    Edit: Ah, you're using the SDK, I gather when re-reading the actual error of your question.

    • You need to import TextEncoder explicitly from some other module, as SDK modules lack the class.
    • append: is only supported in Firefox 27+
    • You write: true to write to a file.

    Here is a full, working example I tested in Firefox 25 (main.js)

    const {Cu} = require("chrome");
    const {TextEncoder, OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
    const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
    
    function write_text(filename, text) {
        var encoder = new TextEncoder();
        var data = encoder.encode(text);
        filename = OS.Path.join(OS.Constants.Path.tmpDir, filename);
        Task.spawn(function() {
           let file = yield OS.File.open(filename, {write: true});
           yield file.write(data);
           yield file.close(); 
           console.log("written to", filename);
        }).then(null, function(e) console.error(e));
    }
    
    write_text("foo", "some text");
    

    See also your other question for more commentary on using this stuff in the SDK.