5

I was having trouble finding an up-to-date answer for this issue, and don't often have time to answer questions here so thought I'd post this so I can answer my own question since I figured out a solution.

I'm making a Web Extension for Chrome and Firefox. Firefox has this issue that when I call a background function that sets some data to a var in the background page from the options page JS, and then close the options page, I get the error "Can't access dead object" when the background code later tries to access the variable that was set. Here's the code:

options.js

formInOptions.addEventListener('submit', function(e){
    e.preventDefault();
    chrome.extension.getBackgroundPage().defaults({
        keyname:  e.target['form-field'].value
    }, function(){
        // data saved cb
    });
});

background.js

function defaults(oNewDefaults) {
    // Global oDefaults already exists, and trying to access this after the options page is closed causes the error.
    chrome.storage.local.get({
        config: {}
    }, function(data) {
        let config = data.config;
        config.defaults = config.defaults || {};
        config.defaults = Object.assign(config.defaults, oNewDefaults); // Merge incoming obj into existing obj
        chrome.storage.local.set({
            config: config
        }, function() {
            oDefaults = config.defaults;
        });
    });
};
tripRev
  • 830
  • 3
  • 12
  • 27

1 Answers1

2

To prevent the error, my solution was to stringify and then re-parse the incoming JS obj, like this: config.defaults = Object.assign(JSON.parse(JSON.stringify(config.defaults)), JSON.parse(JSON.stringify(oNewDefaults)));

tripRev
  • 830
  • 3
  • 12
  • 27
  • On FF 73.0 even doing this gives me a dead object error. I also just saw a note on MDN that says `runtime.getBackgroundPage()` does not work in private windows. Which makes it pretty useless for anything really. I'm going to resort to `runtime.sendMessage()` – Pouria P Apr 08 '20 at 20:35
  • @PouriaP Yep I've since moved away from `getBackgroundPage()` completely, `sendMessage()` works pretty nicely once you get all the parts being able to communicate with the background. – tripRev Apr 27 '20 at 00:29
  • Unfortunately with messaging you can only pass strings, which means you can only pass a JSON object, and if your object has methods in it they will be lost and you'll have to find a way to create a new instance. – Pouria P Apr 27 '20 at 09:20
  • @PouriaP I've been in a situation like that before. I ended up making a system that accepted the name of a function to be called on the receiving end and an array of arguments. It called the function and then sent back the result with a callback. Messy but kind of worked. Eventually had enough space to refactor the whole extension being more careful laying everything out. Dispatching data to a shared state store helped somewhat, but brings its own complexity. Good luck! – tripRev Apr 29 '20 at 01:05
  • Thanks for the tip – Pouria P Apr 29 '20 at 16:06