Search code examples
indexeddbdexie

NotFoundError : DOM IDVDatabase Exception 8 - while using dexie on ipad (working on desktop chrome & safari))


I am working on application which uses IndexedDB with wrapper dexie.js. It's working fine on desktop Chrome & Safari but showing the following error:

NotFoundError : DOM IDVDatabase Exception 8" on iPad (iOS 9.3.5).

On latest iOS iPad it's working without an error. I need a fix which makes it work on all iOS version.

I have tried to apply the fixes available on github & stackoverflow but didn't work.

Thank you. Any help will be appreciated.


Solution

  • Did some research and reproduction of your issue. This wasn't an easy one, as IndexedDBShim 3.7.0 seems not to do its job correctly. Luckily, we have the 2.x version of the shim that behaves as expected on iOS 9 :-)

    Ok, so I have really made some hours of research about this now, testing it out on Browserstack etc, and found a solution that should really work. Beware thought that IndexedDBShim itself comes with some issues too, but the basic stuff in Dexie should work way better than the native IndexedDB on iOS 8 and 9.

    Insert the following snippet to the top of your HTML page serving your application, preferably as one of the first script tags in your HEAD tag:

    <script>
        //
        // Download & use the shim if on buggy Safari (internal version no below 602)
        //
        (function(){
    
          //
          // Check if we are on Safari
          //
          var isSafari = typeof navigator !== 'undefined' &&
            /Safari/.test(navigator.userAgent) &&
            !/(Chrome\/|Edge\/)/.test(navigator.userAgent);
    
          if (isSafari) {
    
            //
            // Check Internal Safari Version
            //
            var safariInternalVersion = [].concat(navigator.userAgent.match(/Safari\/(\d*)/))[1];
    
            if (safariInternalVersion < 602) {
    
              //
              // Download and apply the shim now!
              //
    
              // IMPORTANT: Use 2.x version of the shim, as 3.x latest (3.7.0 as of 2018-06-14) does NOT work on iOS 9!
              document.write('<script src="https://unpkg.com/[email protected]/dist/indexeddbshim.js">\x3C/script>');
              // IMPORTANT: Force the shim to be used, as itself do not inforce automatically for certain buggy versions.
              document.write('<script> shimIndexedDB.__useShim(); \x3C/script>');
            }
          }
        })()
    </script>
    

    IMPORTANT: This script must precede the inclusion of dexie.js (or your webpack bundle).

    The above snippet is enough for supporting Safari 9. Safari 8 requires yet another little JS-code in addition to the script above. The snippet should execute after including Dexie (no matter include strategy), but before using Dexie first time:

      //
      // Also support Safari 8, where indexedDB is non-configurable on
      // window object, making the shim unable to do its work.
      // 
      // What we do here is to manually connect Dexie with the shim
      // in case the shim has been included by the script described at:
      // https://stackoverflow.com/posts/50855488
      //
      // This snippet should execute after including Dexie (no matter 
      // include strategy), but before using Dexie first time:
      //
      if (typeof shimIndexedDB !== 'undefined') {
        Dexie.dependencies.indexedDB = shimIndexedDB.modules.shimIndexedDB;
        Dexie.dependencies.IDBKeyRange = shimIndexedDB.modules.IDBKeyRange;
      }
    

    The nice thing with including the shim like this, is that it won't hurt performance for browsers not needing it.

    BEWARE: When your users update their device and get a newer version of Safari, Dexie will start using the native IndexedDB, which will be empty of course. If this is not desired, you will need to do some more advanced checks or migrate the database into indexedDB, that is not part of this response. Normally though, applications should always take into account that databases can be lost (like if the user clears it) and be able to repopulate them from server if so.