Search code examples
javascriptfirefoxfirefox-addon-sdklocalforage

How to develop Firefox Add-on SDK extension using localforage


I am trying to develop a Firefox Add-on SDK extension that saves data using the localforage library, but I am getting the following error:

Full message: ReferenceError: self is not defined
Full stack: polyfill@resource://browser-journey/node_modules/localforage/dist/localforage.js:259:9
@resource://browser-journey/node_modules/localforage/dist/localforage.js:689:1
@resource://browser-journey/node_modules/localforage/dist/localforage.js:7:2
@resource://browser-journey/index.js:6:19
run@resource://gre/modules/commonjs/sdk/addon/runner.js:147:19

I installed localforage using npm.

I think the problem might be because of this issue in localforage. Is there a workaround?


Solution

  • Authors of localforage don't intend to support Firefox Addons, but it doesn't mean it is impossible. Here is the related issue: https://github.com/mozilla/localForage/issues/584

    You could write a custom driver for localforage: https://github.com/mozilla/localForage/pull/282

    Or add this code at the top of the dist/localforage.min.js file before including it in your addon:

    /**
     * Detect Firefox SDK Addon environment and prepare some globals
     *
     * @author Dumitru Uzun (DUzun.Me)
     */
    (function (window, undefined) {
        if (typeof exports != "object" || typeof module == "undefined") return;
    
        if ( window && window.Array === Array ) try {
            window.window = window;
    
            // Timers
            if ( typeof setTimeout == 'undefined' ) {
                expo(
                    require("sdk/timers")
                  , [
                        'setTimeout'  , 'clearTimeout',
                        'setImmediate', 'clearImmediate'
                    ]
                );
            }
    
            // Blob, FileReader
            var Cu = require("chrome").Cu;
            var Services = Cu['import']("resource://gre/modules/Services.jsm", {});
            expo(
                Services
              , ['Blob', 'FileReader']
            );
            expo(
                Services.appShell && Services.appShell.hiddenDOMWindow
              , ['Blob', 'FileReader']
            );
    
            // IndexedDB
            expo(require('sdk/indexed-db'));
    
        } catch(err) {
            console.log('error', err);
        }
    
        function expo(ctx, props) {
            if ( !ctx ) return;
            if ( !props ) props = Object.keys(ctx);
            for(var i=props.length,p; i--;) {
                p = props[i];
                if ( ctx[p] != undefined && !(p in window) ) {
                  window[p] = ctx[p];
                }
            }
            return ctx;
        }
    }(this));