Firefox Web Extension "Can't access dead object" error
Asked Answered
W

1

6

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;
        });
    });
};
Whallon answered 3/10, 2018 at 1:12 Comment(0)
W
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)));

Whallon answered 3/10, 2018 at 1:13 Comment(5)
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()Lase
@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.Whallon
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.Lase
@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!Whallon
Thanks for the tipLase

© 2022 - 2024 — McMap. All rights reserved.