jakearchibald / idb

IndexedDB, but with promises
https://www.npmjs.com/package/idb
ISC License
6.22k stars 348 forks source link

Fix IE11 getAll() issue on v3.0.2 #218

Open Scoottykun opened 3 years ago

Scoottykun commented 3 years ago

Hello,

I'd just like to share to the community the fix to an issue i had today.

I'm using the version 3.0.2 that allow me to make the library works on IE11 (new versions don't support IE11). As i wanted to fetch all the keys of one of my table, i used the getAll() method, so i did :

let results = await (await dbPromise).transaction(store).objectStore(store).getAll();

It works well on all modern browsers, but on IE11, where the polyfill for getAll() is being used, and the following (breaking) error showed up in console :

[object DOMException]{ABORT_ERR: 20, code: 0, constructor: DOMException {...}, DATA_CLONE_ERR: 25, DOMSTRING_SIZE_ERR: 2, HIERARCHY_REQUEST_ERR: 3, INDEX_SIZE_ERR: 1, INUSE_ATTRIBUTE_ERR: 10, INVALID_ACCESS_ERR: 15, INVALID_CHARACTER_ERR: 5, INVALID_MODIFICATION_ERR: 13, INVALID_NODE_TYPE_ERR: 24, INVALID_STATE_ERR: 11, message: "DataError", name: "DataError", NAMESPACE_ERR: 14, NETWORK_ERR: 19, NO_DATA_ALLOWED_ERR: 6, NO_MODIFICATION_ALLOWED_ERR: 7, NOT_FOUND_ERR: 8, NOT_SUPPORTED_ERR: 9 ...}

After some search within the library i found the getAll() polyfill codebase, which is :

// polyfill getAll
[Index, ObjectStore].forEach(function(Constructor) {
  if (Constructor.prototype.getAll) return;
  Constructor.prototype.getAll = function(query, count) {
    var instance = this;
    var items = [];

    return new Promise(function(resolve) {
      instance.iterateCursor(query, function(cursor) {
        if (!cursor) {
          resolve(items);
          return;
        }
        items.push(cursor.value);

        if (count !== undefined && items.length == count) {
          resolve(items);
          return;
        }
        cursor.continue();
      });
    });
  };
});

Where the 'query' parameter is equal to 'undefined' when testing my script.

And if i look the native iterateCursor function, we have :

iterateCursor(range: IDBKeyRange | IDBValidKey | null, callback: (c: Cursor<TValue, TKey>) => void): void;

We can see here that 'undefined' is not being handled as a possible value for this parameter.

So, what i just did is modify my 'getAll()' call by 'getAll(null)', like so :

let results = await (await dbPromise).transaction(store).objectStore(store).getAll(null);

And it's now working like a charm :partying_face: :partying_face: :partying_face:

Hope it can help any one with similar issues !

======

TLDR : Just use getAll(null) instead of getAll() to avoid any issue on IE 11 when using v3.0.2

jakearchibald commented 3 years ago

Thanks for providing details on this! I'll look at releasing a new 3.x version that avoids this gotcha.