Search code examples
javascriptfirefox-addonfirefox-addon-sdk

FileReaderSync undefined inside Web Worker in Firefox extension using Add-on SDK


I managed to get a Web Worker (not a content/worker) in my Firefox add-on using the Add-on SDK. I followed Wladimir's advice here to get the Worker class working: Concurrency with Firefox add-on script and content script

Now, I can launch a worker in my code and can talk to it by sending/receiving messages.

This is my main.js file:

// spawn our log reader worker
var worker = new Worker(data.url('log-reader.js'));

// send and respond to some dummy messages
worker.postMessage('halo');
worker.onmessage = function(event) {
    console.log('received msg from worker: ' + event.data);
};

This is my log-reader.js file:

// this function gets called when main.js sends a msg to this worker
// using the postMessage call

onmessage = function(event) {
    var info = event.data;

    // reply back
    postMessage('hey addon, i got your message: ' + info);
    if (!!FileReaderSync) {
        postMessage('ERROR: FileReaderSync is not supported');
    } else {
        postMessage('FileReaderSync is supported');
    }

//    var reader = new FileReaderSync();
//    postMessage('File contents: ' + reader.readAsText('/tmp/hello.txt'));
};

My problem is that the FileReaderSync class is not defined inside the log-reader.js file, and as a result I get the error message back. If I uncomment the last lines where FileReaderSync is actually used, I will never get the message back in my addon.

I tried using the same trick I used for Worker, by creating a dummy.jsm file and importing in main.js, but FileReaderSync will only be available in main.js and not in log-reader.js:

// In dummy.jsm
var EXPORTED_SYMBOLS=["Worker"];
var EXPORTED_SYMBOLS=["FileReaderSync"];

// In main.js
var { Worker, FileReaderSync } = Cu.import(data.url('workers.jsm'));
Cu.unload(data.url("workers.jsm"));

I figure there has to be a solution since the documentation here seems to indicate that the FileReaderSync class should be available to a Web Worker in Firefox:

This interface is only available in workers as it enables synchronous I/O that could potentially block.

So, is there a way to make FileReaderSync available and usable in the my Web Worker code?


Solution

  • Actually, your worker sends "ERROR" if FileReaderSync is defined since you negated it twice. Change !!FileReaderSync to !FileReaderSync and it will work correctly.

    I guess that you tried to find the issue with the code you commented out. The problem is, reader.readAsText('/tmp/hello.txt') won't work - this method expects a blob (or file). The worker itself cannot construct a file but you can create it in your extension and send to the worker with a message:

    worker.postMessage(new File("/tmp/hello.txt"));
    

    Note: I'm not sure whether the Add-on SDK defines the File constructor, you likely have to use the same trick as for the Worker constructor.

    The worker can then read the data from this file:

    onmessage = function(event)
    {
        var reader = new FileReaderSync();
        postMessage("File contents: " + reader.readAsText(event.data));
    }