0

For a Manifest 3 browser extension I need to implement local storage logic. This is because there is a lot of code that are shared between different projects that uses localStorage. To change and test all this code on different platforms will be quite a big job.

So I am trying to make a proxy of an object that implement the normal functions of the localStorage object. In the extension I need to use async functions like chrome.storage.local.get.

This gives me a lot of problems with the Promise logic in different ways as getItem return a promise (not intended) or I get runtime errors like "await is only valid in async functions and the top level bodies of modules" etc.

The code below is one such try:

var localStorageTarget = {};

localStorageTarget.getItem = async function(keyname)
{
  const internalGetItem = async () =>
  {
    return new Promise((resolve, reject) => 
    {
      chrome.storage.local.get([keyname], function (result) 
      {
        if (result[keyname] === undefined) 
        {
          reject();
        } 
        else 
        {
          resolve(result[keyname]);
        }
      });
    });
  }

  return await internalGetItem();
};

localStorageTarget.setItem = function(keyname, keyvalue)
{
    chrome.storage.local.set({keyname: keyvalue});
    return true;    
};

localStorageTarget.removeItem = function(keyname)
{
    chrome.storage.local.remove([keyname]);
    return true; // deleteProperty need this    
};

const localStorage = new Proxy(localStorageTarget, 
{
  get: function(obj, name) 
  {
      //console.log('Read request to ' + name + ' property with ' + obj[name] + ' value');
      
      return obj.getItem(name);
  },
  set: function(obj, name, value) 
  {
      //console.log('Write request to ' + name + ' property with ' + value + ' value');
      
      return obj.setItem(name, value);
  },
  deleteProperty(obj, name) 
  {
    //console.log('Delete request to ' + name + ' property with ' + obj[name] + ' value');
    
    return obj.removeItem(name);
  } 
});

localStorage['qqqq'] = 'test2';
console.log(localStorage.getItem('qqqq'));
console.log(localStorage['qqqq']);
delete localStorage['qqqq'];

In advance thank you for for any hint or help

/Benny

Beast
  • 271
  • 2
  • 5
  • 15
  • Read the state from storage at the start of the environment creation, then you can access the variable directly and synchronously, see [this example](https://stackoverflow.com/a/73090402). – wOxxOm Sep 19 '22 at 16:15

1 Answers1

0

You're not going to get around the fact that if the getter returns a Promise, you have to await that promise at the top level:

console.log(await localStorage['qqqq']);

Since chrome.storage.local.get() returns a promise if you don't pass a callback, you can simplify your code:

localStorageTarget.getItem = function(keyname) {
  return chrome.storage.local.get([ keyname ]);
}

And lastly, I think that you want expand keyname into a property name:

chrome.storage.local.set({ [ keyname ]: keyvalue });
robertklep
  • 198,204
  • 35
  • 394
  • 381