Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncaught (in promise) TypeError: Illegal invocation: Function must be called on an object of type StorageArea #10

Closed
Kyza opened this issue Aug 28, 2018 · 13 comments
Assignees

Comments

@Kyza
Copy link

Kyza commented Aug 28, 2018

I made an extension which works fine, but not on my friend's computer. It throws 3 errors.

Uncaught (in promise) TypeError: Illegal invocation: Function must be called on an object of type StorageArea
    at Promise (chrome-extension-async.js:34)
    at new Promise (<anonymous>)
    at Object.args [as get] (chrome-extension-async.js:31)
    at backgroundimage.js:74

chrome-extension-async.js:34 Uncaught (in promise) TypeError: Illegal invocation: Function must be called on an object of type StorageArea
    at Promise (chrome-extension-async.js:34)
    at new Promise (<anonymous>)
    at Object.args [as get] (chrome-extension-async.js:31)
    at initializeOnlineBackgroundSettings (backgroundimage.js:171)
    at backgroundimage.js:71

chrome-extension-async.js:34 Uncaught (in promise) TypeError: Illegal invocation: Function must be called on an object of type StorageArea
    at Promise (chrome-extension-async.js:34)
    at new Promise (<anonymous>)
    at Object.args [as get] (chrome-extension-async.js:31)
    at main.js:14
    at cbArgs (chrome-extension-async.js:39)

I have no idea why it is doing this, it works perfectly fine for me. We are both using the same version of Chrome, Chrome 70.

I attached the extension.
Hypt.zip

@KeithHenry
Copy link
Owner

I've currently only tested this up to 68.0.3440.106, which is the current release.

@KeithHenry
Copy link
Owner

@KyzaGitHub I think the problem might be when you load in the script - I recommend putting your project into GitHub (rather than a ZIP) as we could then work on a PR to fix.

Basically, it looks like you run this script in newtab.html (line 146), then call it in backgroundimage.js.

I think the issue might be timing related because you're still using microtasks for callbacks from chrome.storage.local, something like:

chrome.storage.local.get('key', async function(item) {
    ... 
    await ...
})

In this context the callback function itself returns a promise, which in turn means anthing after the await runs after the current code.

I think this may be fixed by changing this to:

const item = await chrome.storage.local.get('key');

@KeithHenry KeithHenry self-assigned this Aug 31, 2018
@Kyza
Copy link
Author

Kyza commented Sep 1, 2018

@KeithHenry In order to load the extension faster, I do want some things to run synchronously. I only needed chrome-extension-async.js in order to make sure that some things load in the proper order so the extension does not break, but anything that is not order specific I run synchronously to speed up the loading time.

If I understand what you are saying, you mean that by using chrome-extension-async.js I can no longer use callbacks from Chrome APIs like chrome.storage.local?

@Kyza
Copy link
Author

Kyza commented Sep 1, 2018

Or did you mean that I cannot make a callback asynchronous?

@KeithHenry
Copy link
Owner

@KyzaGitHub You can make a callback asynchronous, but it makes it a little hard to predict when the script after any await inside that actually fires. When the native chrome.storage.local.get ultimately calls the callback it fires-n-forgets - it assumes that the function is synchronous.

I'm not sure what you mean here:

anything that is not order specific I run synchronously to speed up the loading time

JS cannot go from asynchronous back to synchronous execution - when you call those without an await what you're really doing is starting the call, and then moving on without waiting for it to come back.

If you want to do that there are two ways to better catch the result, both using Promise:

// Use promise syntax to chain synchronous callbacks
chrome.storage.local.get('key').
    then(item => { ... }).
    then(followUp => { ... }).
    catch(x => console.error(x));

Or:

// Get the promise, but don't await for it
const dontBlock = chrome.storage.local.get('key');

// Do other urgent stuff
...

// Now urgent stuff is done, await the result
const item = await dontBlock;
const followUp = await someOtherAsyncCall(item);
...

I'd also add that if you're getting performance issues from lots of chrome.storage.local.get calls you could try joining all those together into a single settings object, as unless that gets very large it is much quicker to set/get a single object with 100 properties than it is to set/get 100 primitive items.

@xcv58
Copy link

xcv58 commented Oct 19, 2018

The same here: xcv58/Tab-Manager-v2#235

It only happens on Windows machine.

@xcv58
Copy link

xcv58 commented Oct 22, 2018

Some updates:

The functionality works on below versions with Windows 10 OS:
Version 70.0.3538.67 (Official Build) (64-bit)
Version 72.0.3587.0 (Official Build) canary (64-bit)

does NOT work on the beta and dev versions:
Version 70.0.3538.67 (Official Build) beta (64-bit)
Version 71.0.3578.10 (Official Build) dev (64-bit)

@KeithHenry
Copy link
Owner

@xcv58 I don't think think the cause is this, as it's used in other extensions in the same way without error, and I'be been unable to reproduce either your or @KyzaGitHub's issues.

All this library does is wrap chrome.storage.local.get in a promise, and chrome-extension-async.js is at the top of the stack because it's wrapping that call, but I don't think it's the cause.

In both cases this now appears to be resolved, but if it reoccurs could you do me a favour? Try the problem code with the Chrome API without this library, and see if that has the same problem occurs. Either way please let me know, but if it works with the API but doesn't with this wrapper please reopen this issue (or open a new one) with the reproducible details. Thanks.

@jenda
Copy link

jenda commented Dec 3, 2018

@KeithHenry, I just hit this issue too. I have been playing with Chromium Version 72.0.3617.0 (Developer Build) (64-bit) Mac (I assume that it's because it's a dev build)

anyways, I was able to track it down to (step-by-step):
const m = api[funcName];

basically using the fc pointer instead of calling the method directly on the object throws the above mentioned error (never seen it before - maybe it's a new thing).
api[funcName]('a', function(x) { console.log(x)}) succeeds
but m('a', function(x) { console.log(x)}) throws

See the screenshot:
screenshot 2018-12-03 00 43 53

@amfr
Copy link
Contributor

amfr commented Dec 4, 2018

It looks like this isn't being bound properly. Not sure why this would have changed with new versions of Chrome, but I think I have a fix. If you change api[funcName] = promisify(m, funcDef.cb); to api[funcName] = promisify(m.bind(api), funcDef.cb);, everything should be back to normal. I'll submit a pull request shortly.

@KeithHenry
Copy link
Owner

@amfr Thanks, will get a new release out with this applied soon.

@bigandy
Copy link

bigandy commented Jan 10, 2019

@KeithHenry can you please release a bumped version? I'm running into this on MacOS 10.14.2 Chrome Version 71.0.3578.98

@KeithHenry
Copy link
Owner

Release: Scraper 0.5.1

zoracon pushed a commit to EFForg/https-everywhere that referenced this issue Apr 11, 2019
At least on Chromium 73 when opening the extension options window an
exception
"TypeError: Illegal invocation: Function must be called on an object of type StorageArea"
is thrown, which results in empty update channels page.

It looks like chrome.storage.local methods need to be called while bound to
the chrome.storage.local object.

According to
KeithHenry/chromeExtensionAsync#10
wtetsu/mouse-dictionary#16 this Chromium change
has been introduced probably around version 70 or 72.

Automatic ruleset updates might have been affected by this, too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants