Skip to content

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

Closed

Description

@Kyza

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

Activity

  1. KeithHenry commented on Aug 31, 2018

    @KeithHenry
    Owner

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

  2. KeithHenry commented on Aug 31, 2018

    @KeithHenry
    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');
    
  3. self-assigned this
    on Aug 31, 2018
  4. Kyza commented on Sep 1, 2018

    @Kyza
    Author

    @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?

  5. Kyza commented on Sep 1, 2018

    @Kyza
    Author

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

  6. KeithHenry commented on Sep 4, 2018

    @KeithHenry
    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.

  7. xcv58 commented on Oct 19, 2018

    @xcv58

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

    It only happens on Windows machine.

  8. xcv58 commented on Oct 22, 2018

    @xcv58

    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)

  9. KeithHenry commented on Dec 3, 2018

    @KeithHenry
    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.

  10. jenda commented on Dec 3, 2018

    @jenda

    @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

  11. amfr commented on Dec 4, 2018

    @amfr
    Contributor

    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.

  12. KeithHenry commented on Dec 17, 2018

    @KeithHenry
    Owner

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

  13. bigandy commented on Jan 10, 2019

    @bigandy

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

  14. KeithHenry commented on Feb 5, 2019

    @KeithHenry
    Owner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions