· 5 years ago · Nov 16, 2020, 09:24 PM
1/**
2 * @name WebpackTest
3 */
4
5/******/ (() => { // webpackBootstrap
6/******/ var __webpack_modules__ = ({
7
8/***/ 900:
9/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
10
11(function (global, factory) {
12 true ? factory(exports, __webpack_require__(483)) :
13 0;
14}(this, (function (exports,localforage) { 'use strict';
15
16localforage = 'default' in localforage ? localforage['default'] : localforage;
17
18function getSerializerPromise(localForageInstance) {
19 if (getSerializerPromise.result) {
20 return getSerializerPromise.result;
21 }
22 if (!localForageInstance || typeof localForageInstance.getSerializer !== 'function') {
23 return Promise.reject(new Error('localforage.getSerializer() was not available! ' + 'localforage v1.4+ is required!'));
24 }
25 getSerializerPromise.result = localForageInstance.getSerializer();
26 return getSerializerPromise.result;
27}
28
29
30
31function executeCallback(promise, callback) {
32 if (callback) {
33 promise.then(function (result) {
34 callback(null, result);
35 }, function (error) {
36 callback(error);
37 });
38 }
39}
40
41function getItemKeyValue(key, callback) {
42 var localforageInstance = this;
43 var promise = localforageInstance.getItem(key).then(function (value) {
44 return {
45 key: key,
46 value: value
47 };
48 });
49 executeCallback(promise, callback);
50 return promise;
51}
52
53function getIDBKeyRange() {
54 /* global IDBKeyRange, webkitIDBKeyRange, mozIDBKeyRange */
55 if (typeof IDBKeyRange !== 'undefined') {
56 return IDBKeyRange;
57 }
58 if (typeof webkitIDBKeyRange !== 'undefined') {
59 return webkitIDBKeyRange;
60 }
61 if (typeof mozIDBKeyRange !== 'undefined') {
62 return mozIDBKeyRange;
63 }
64}
65
66var idbKeyRange = getIDBKeyRange();
67
68function startsWith(prefix, callback) {
69 var localforageInstance = this;
70 var promise = new Promise(function (resolve, reject) {
71 localforageInstance.ready().then(function () {
72 // Thanks https://hacks.mozilla.org/2014/06/breaking-the-borders-of-indexeddb/
73 var dbInfo = localforageInstance._dbInfo;
74 var store = dbInfo.db.transaction(dbInfo.storeName, 'readonly').objectStore(dbInfo.storeName);
75
76 var keyRangeValue = idbKeyRange.bound(prefix, prefix + 'uffff', false, false);
77
78 var result = {};
79 var req = store.openCursor(keyRangeValue);
80 req.onsuccess = function () /*event*/{
81 var cursor = req.result; // event.target.result;
82
83 if (cursor) {
84 var value = cursor.value;
85 if (value === undefined) {
86 value = null;
87 }
88
89 result[cursor.key] = value;
90
91 cursor.continue();
92 } else {
93 resolve(result);
94 }
95 };
96
97 req.onerror = function () /*event*/{
98 reject(req.error);
99 };
100 }).catch(reject);
101 });
102 executeCallback(promise, callback);
103 return promise;
104}
105
106function keysStartingWith(prefix, callback) {
107 var localforageInstance = this;
108 var promise = new Promise(function (resolve, reject) {
109 localforageInstance.ready().then(function () {
110 // Thanks https://hacks.mozilla.org/2014/06/breaking-the-borders-of-indexeddb/
111 var dbInfo = localforageInstance._dbInfo;
112 var store = dbInfo.db.transaction(dbInfo.storeName, 'readonly').objectStore(dbInfo.storeName);
113
114 var keyRangeValue = idbKeyRange.bound(prefix, prefix + 'uffff', false, false);
115
116 var result = [];
117
118 if (typeof store.getAllKeys === 'function') {
119 var req = store.getAllKeys(keyRangeValue);
120 req.onsuccess = function () /*event*/{
121 resolve(req.result);
122 };
123
124 req.onerror = function () /*event*/{
125 reject(req.error);
126 };
127 } else {
128 var _req = store.openCursor(keyRangeValue);
129 _req.onsuccess = function () /*event*/{
130 var cursor = _req.result; // event.target.result;
131
132 if (cursor) {
133 result.push(cursor.key);
134
135 cursor.continue();
136 } else {
137 resolve(result);
138 }
139 };
140
141 _req.onerror = function () /*event*/{
142 reject(_req.error);
143 };
144 }
145 }).catch(reject);
146 });
147 executeCallback(promise, callback);
148 return promise;
149}
150
151function startsWith$1(prefix, callback) {
152 var localforageInstance = this;
153 var promise = new Promise(function (resolve, reject) {
154 localforageInstance.ready().then(function () {
155 return getSerializerPromise(localforageInstance);
156 }).then(function (serializer) {
157 var dbInfo = localforageInstance._dbInfo;
158 dbInfo.db.transaction(function (t) {
159 t.executeSql('SELECT * FROM ' + dbInfo.storeName + ' WHERE (key LIKE ?)', [prefix + '%'], function (t, results) {
160
161 var result = {};
162
163 var rows = results.rows;
164 for (var i = 0, len = rows.length; i < len; i++) {
165 var item = rows.item(i);
166 var value = item.value;
167
168 // Check to see if this is serialized content we need to
169 // unpack.
170 if (value) {
171 value = serializer.deserialize(value);
172 }
173
174 result[item.key] = value;
175 }
176
177 resolve(result);
178 }, function (t, error) {
179 reject(error);
180 });
181 });
182 }).catch(reject);
183 });
184 executeCallback(promise, callback);
185 return promise;
186}
187
188function keysStartingWith$1(prefix, callback) {
189 var localforageInstance = this;
190 var promise = new Promise(function (resolve, reject) {
191 localforageInstance.ready().then(function () {
192 var dbInfo = localforageInstance._dbInfo;
193 dbInfo.db.transaction(function (t) {
194 t.executeSql('SELECT key FROM ' + dbInfo.storeName + ' WHERE (key LIKE ?)', [prefix + '%'], function (t, results) {
195
196 var result = [];
197
198 var rows = results.rows;
199 for (var i = 0, len = rows.length; i < len; i++) {
200 var item = rows.item(i);
201
202 result.push(item.key);
203 }
204
205 resolve(result);
206 }, function (t, error) {
207 reject(error);
208 });
209 });
210 }).catch(reject);
211 });
212 executeCallback(promise, callback);
213 return promise;
214}
215
216function startsWith$2(prefix, callback) {
217 var localforageInstance = this;
218 var promise = new Promise(function (resolve, reject) {
219 localforageInstance.keys().then(function (keys) {
220
221 var itemPromises = [];
222
223 var prefixLength = prefix.length;
224 for (var i = 0, len = keys.length; i < len; i++) {
225 var key = keys[i];
226
227 if (key.slice(0, prefixLength) === prefix) {
228 itemPromises.push(getItemKeyValue.call(localforageInstance, key));
229 }
230 }
231
232 Promise.all(itemPromises).then(function (keyValuePairs) {
233 var result = {};
234 for (var i = 0, len = keyValuePairs.length; i < len; i++) {
235 var keyValuePair = keyValuePairs[i];
236
237 result[keyValuePair.key] = keyValuePair.value;
238 }
239 resolve(result);
240 }).catch(reject);
241 }).catch(reject);
242 });
243 executeCallback(promise, callback);
244 return promise;
245}
246
247function keysStartingWith$2(prefix, callback) {
248 var localforageInstance = this;
249 var promise = new Promise(function (resolve, reject) {
250 localforageInstance.keys().then(function (keys) {
251
252 var result = [];
253
254 var prefixLength = prefix.length;
255 for (var i = 0, len = keys.length; i < len; i++) {
256 var key = keys[i];
257
258 if (key.slice(0, prefixLength) === prefix) {
259 result.push(key);
260 }
261 }
262
263 resolve(result);
264 }).catch(reject);
265 });
266 executeCallback(promise, callback);
267 return promise;
268}
269
270function localforageStartsWith(prefix, callback) {
271 var localforageInstance = this;
272 var currentDriver = localforageInstance.driver();
273
274 if (currentDriver === localforageInstance.INDEXEDDB) {
275 return startsWith.call(localforageInstance, prefix, callback);
276 } else if (currentDriver === localforageInstance.WEBSQL) {
277 return startsWith$1.call(localforageInstance, prefix, callback);
278 } else {
279 return startsWith$2.call(localforageInstance, prefix, callback);
280 }
281}
282
283function localforageKeysStartingWith(prefix, callback) {
284 var localforageInstance = this;
285 var currentDriver = localforageInstance.driver();
286
287 if (currentDriver === localforageInstance.INDEXEDDB) {
288 return keysStartingWith.call(localforageInstance, prefix, callback);
289 } else if (currentDriver === localforageInstance.WEBSQL) {
290 return keysStartingWith$1.call(localforageInstance, prefix, callback);
291 } else {
292 return keysStartingWith$2.call(localforageInstance, prefix, callback);
293 }
294}
295
296function extendPrototype(localforage$$1) {
297 var localforagePrototype = Object.getPrototypeOf(localforage$$1);
298 if (localforagePrototype) {
299 localforagePrototype.startsWith = localforageStartsWith;
300 localforagePrototype.keysStartingWith = localforageKeysStartingWith;
301 }
302}
303
304var extendPrototypeResult = extendPrototype(localforage);
305
306exports.localforageStartsWith = localforageStartsWith;
307exports.localforageKeysStartingWith = localforageKeysStartingWith;
308exports.extendPrototype = extendPrototype;
309exports.extendPrototypeResult = extendPrototypeResult;
310exports.startsWithGeneric = startsWith$2;
311exports.keysStartingWithGeneric = keysStartingWith$2;
312
313Object.defineProperty(exports, '__esModule', { value: true });
314
315})));
316
317
318/***/ }),
319
320/***/ 483:
321/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
322
323/*!
324 localForage -- Offline Storage, Improved
325 Version 1.9.0
326 https://localforage.github.io/localForage
327 (c) 2013-2017 Mozilla, Apache License 2.0
328*/
329(function(f){if(true){module.exports=f()}else { var g; }})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=undefined;if(!u&&a)return require(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw (f.code="MODULE_NOT_FOUND", f)}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=undefined;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
330(function (global){
331'use strict';
332var Mutation = global.MutationObserver || global.WebKitMutationObserver;
333
334var scheduleDrain;
335
336{
337 if (Mutation) {
338 var called = 0;
339 var observer = new Mutation(nextTick);
340 var element = global.document.createTextNode('');
341 observer.observe(element, {
342 characterData: true
343 });
344 scheduleDrain = function () {
345 element.data = (called = ++called % 2);
346 };
347 } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') {
348 var channel = new global.MessageChannel();
349 channel.port1.onmessage = nextTick;
350 scheduleDrain = function () {
351 channel.port2.postMessage(0);
352 };
353 } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) {
354 scheduleDrain = function () {
355
356 // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
357 // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
358 var scriptEl = global.document.createElement('script');
359 scriptEl.onreadystatechange = function () {
360 nextTick();
361
362 scriptEl.onreadystatechange = null;
363 scriptEl.parentNode.removeChild(scriptEl);
364 scriptEl = null;
365 };
366 global.document.documentElement.appendChild(scriptEl);
367 };
368 } else {
369 scheduleDrain = function () {
370 setTimeout(nextTick, 0);
371 };
372 }
373}
374
375var draining;
376var queue = [];
377//named nextTick for less confusing stack traces
378function nextTick() {
379 draining = true;
380 var i, oldQueue;
381 var len = queue.length;
382 while (len) {
383 oldQueue = queue;
384 queue = [];
385 i = -1;
386 while (++i < len) {
387 oldQueue[i]();
388 }
389 len = queue.length;
390 }
391 draining = false;
392}
393
394module.exports = immediate;
395function immediate(task) {
396 if (queue.push(task) === 1 && !draining) {
397 scheduleDrain();
398 }
399}
400
401}).call(this,typeof __webpack_require__.g !== "undefined" ? __webpack_require__.g : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
402},{}],2:[function(_dereq_,module,exports){
403'use strict';
404var immediate = _dereq_(1);
405
406/* istanbul ignore next */
407function INTERNAL() {}
408
409var handlers = {};
410
411var REJECTED = ['REJECTED'];
412var FULFILLED = ['FULFILLED'];
413var PENDING = ['PENDING'];
414
415module.exports = Promise;
416
417function Promise(resolver) {
418 if (typeof resolver !== 'function') {
419 throw new TypeError('resolver must be a function');
420 }
421 this.state = PENDING;
422 this.queue = [];
423 this.outcome = void 0;
424 if (resolver !== INTERNAL) {
425 safelyResolveThenable(this, resolver);
426 }
427}
428
429Promise.prototype["catch"] = function (onRejected) {
430 return this.then(null, onRejected);
431};
432Promise.prototype.then = function (onFulfilled, onRejected) {
433 if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||
434 typeof onRejected !== 'function' && this.state === REJECTED) {
435 return this;
436 }
437 var promise = new this.constructor(INTERNAL);
438 if (this.state !== PENDING) {
439 var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
440 unwrap(promise, resolver, this.outcome);
441 } else {
442 this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
443 }
444
445 return promise;
446};
447function QueueItem(promise, onFulfilled, onRejected) {
448 this.promise = promise;
449 if (typeof onFulfilled === 'function') {
450 this.onFulfilled = onFulfilled;
451 this.callFulfilled = this.otherCallFulfilled;
452 }
453 if (typeof onRejected === 'function') {
454 this.onRejected = onRejected;
455 this.callRejected = this.otherCallRejected;
456 }
457}
458QueueItem.prototype.callFulfilled = function (value) {
459 handlers.resolve(this.promise, value);
460};
461QueueItem.prototype.otherCallFulfilled = function (value) {
462 unwrap(this.promise, this.onFulfilled, value);
463};
464QueueItem.prototype.callRejected = function (value) {
465 handlers.reject(this.promise, value);
466};
467QueueItem.prototype.otherCallRejected = function (value) {
468 unwrap(this.promise, this.onRejected, value);
469};
470
471function unwrap(promise, func, value) {
472 immediate(function () {
473 var returnValue;
474 try {
475 returnValue = func(value);
476 } catch (e) {
477 return handlers.reject(promise, e);
478 }
479 if (returnValue === promise) {
480 handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
481 } else {
482 handlers.resolve(promise, returnValue);
483 }
484 });
485}
486
487handlers.resolve = function (self, value) {
488 var result = tryCatch(getThen, value);
489 if (result.status === 'error') {
490 return handlers.reject(self, result.value);
491 }
492 var thenable = result.value;
493
494 if (thenable) {
495 safelyResolveThenable(self, thenable);
496 } else {
497 self.state = FULFILLED;
498 self.outcome = value;
499 var i = -1;
500 var len = self.queue.length;
501 while (++i < len) {
502 self.queue[i].callFulfilled(value);
503 }
504 }
505 return self;
506};
507handlers.reject = function (self, error) {
508 self.state = REJECTED;
509 self.outcome = error;
510 var i = -1;
511 var len = self.queue.length;
512 while (++i < len) {
513 self.queue[i].callRejected(error);
514 }
515 return self;
516};
517
518function getThen(obj) {
519 // Make sure we only access the accessor once as required by the spec
520 var then = obj && obj.then;
521 if (obj && (typeof obj === 'object' || typeof obj === 'function') && typeof then === 'function') {
522 return function appyThen() {
523 then.apply(obj, arguments);
524 };
525 }
526}
527
528function safelyResolveThenable(self, thenable) {
529 // Either fulfill, reject or reject with error
530 var called = false;
531 function onError(value) {
532 if (called) {
533 return;
534 }
535 called = true;
536 handlers.reject(self, value);
537 }
538
539 function onSuccess(value) {
540 if (called) {
541 return;
542 }
543 called = true;
544 handlers.resolve(self, value);
545 }
546
547 function tryToUnwrap() {
548 thenable(onSuccess, onError);
549 }
550
551 var result = tryCatch(tryToUnwrap);
552 if (result.status === 'error') {
553 onError(result.value);
554 }
555}
556
557function tryCatch(func, value) {
558 var out = {};
559 try {
560 out.value = func(value);
561 out.status = 'success';
562 } catch (e) {
563 out.status = 'error';
564 out.value = e;
565 }
566 return out;
567}
568
569Promise.resolve = resolve;
570function resolve(value) {
571 if (value instanceof this) {
572 return value;
573 }
574 return handlers.resolve(new this(INTERNAL), value);
575}
576
577Promise.reject = reject;
578function reject(reason) {
579 var promise = new this(INTERNAL);
580 return handlers.reject(promise, reason);
581}
582
583Promise.all = all;
584function all(iterable) {
585 var self = this;
586 if (Object.prototype.toString.call(iterable) !== '[object Array]') {
587 return this.reject(new TypeError('must be an array'));
588 }
589
590 var len = iterable.length;
591 var called = false;
592 if (!len) {
593 return this.resolve([]);
594 }
595
596 var values = new Array(len);
597 var resolved = 0;
598 var i = -1;
599 var promise = new this(INTERNAL);
600
601 while (++i < len) {
602 allResolver(iterable[i], i);
603 }
604 return promise;
605 function allResolver(value, i) {
606 self.resolve(value).then(resolveFromAll, function (error) {
607 if (!called) {
608 called = true;
609 handlers.reject(promise, error);
610 }
611 });
612 function resolveFromAll(outValue) {
613 values[i] = outValue;
614 if (++resolved === len && !called) {
615 called = true;
616 handlers.resolve(promise, values);
617 }
618 }
619 }
620}
621
622Promise.race = race;
623function race(iterable) {
624 var self = this;
625 if (Object.prototype.toString.call(iterable) !== '[object Array]') {
626 return this.reject(new TypeError('must be an array'));
627 }
628
629 var len = iterable.length;
630 var called = false;
631 if (!len) {
632 return this.resolve([]);
633 }
634
635 var i = -1;
636 var promise = new this(INTERNAL);
637
638 while (++i < len) {
639 resolver(iterable[i]);
640 }
641 return promise;
642 function resolver(value) {
643 self.resolve(value).then(function (response) {
644 if (!called) {
645 called = true;
646 handlers.resolve(promise, response);
647 }
648 }, function (error) {
649 if (!called) {
650 called = true;
651 handlers.reject(promise, error);
652 }
653 });
654 }
655}
656
657},{"1":1}],3:[function(_dereq_,module,exports){
658(function (global){
659'use strict';
660if (typeof global.Promise !== 'function') {
661 global.Promise = _dereq_(2);
662}
663
664}).call(this,typeof __webpack_require__.g !== "undefined" ? __webpack_require__.g : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
665},{"2":2}],4:[function(_dereq_,module,exports){
666'use strict';
667
668var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
669
670function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
671
672function getIDB() {
673 /* global indexedDB,webkitIndexedDB,mozIndexedDB,OIndexedDB,msIndexedDB */
674 try {
675 if (typeof indexedDB !== 'undefined') {
676 return indexedDB;
677 }
678 if (typeof webkitIndexedDB !== 'undefined') {
679 return webkitIndexedDB;
680 }
681 if (typeof mozIndexedDB !== 'undefined') {
682 return mozIndexedDB;
683 }
684 if (typeof OIndexedDB !== 'undefined') {
685 return OIndexedDB;
686 }
687 if (typeof msIndexedDB !== 'undefined') {
688 return msIndexedDB;
689 }
690 } catch (e) {
691 return;
692 }
693}
694
695var idb = getIDB();
696
697function isIndexedDBValid() {
698 try {
699 // Initialize IndexedDB; fall back to vendor-prefixed versions
700 // if needed.
701 if (!idb || !idb.open) {
702 return false;
703 }
704 // We mimic PouchDB here;
705 //
706 // We test for openDatabase because IE Mobile identifies itself
707 // as Safari. Oh the lulz...
708 var isSafari = typeof openDatabase !== 'undefined' && /(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent) && !/BlackBerry/.test(navigator.platform);
709
710 var hasFetch = typeof fetch === 'function' && fetch.toString().indexOf('[native code') !== -1;
711
712 // Safari <10.1 does not meet our requirements for IDB support
713 // (see: https://github.com/pouchdb/pouchdb/issues/5572).
714 // Safari 10.1 shipped with fetch, we can use that to detect it.
715 // Note: this creates issues with `window.fetch` polyfills and
716 // overrides; see:
717 // https://github.com/localForage/localForage/issues/856
718 return (!isSafari || hasFetch) && typeof indexedDB !== 'undefined' &&
719 // some outdated implementations of IDB that appear on Samsung
720 // and HTC Android devices <4.4 are missing IDBKeyRange
721 // See: https://github.com/mozilla/localForage/issues/128
722 // See: https://github.com/mozilla/localForage/issues/272
723 typeof IDBKeyRange !== 'undefined';
724 } catch (e) {
725 return false;
726 }
727}
728
729// Abstracts constructing a Blob object, so it also works in older
730// browsers that don't support the native Blob constructor. (i.e.
731// old QtWebKit versions, at least).
732// Abstracts constructing a Blob object, so it also works in older
733// browsers that don't support the native Blob constructor. (i.e.
734// old QtWebKit versions, at least).
735function createBlob(parts, properties) {
736 /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */
737 parts = parts || [];
738 properties = properties || {};
739 try {
740 return new Blob(parts, properties);
741 } catch (e) {
742 if (e.name !== 'TypeError') {
743 throw e;
744 }
745 var Builder = typeof BlobBuilder !== 'undefined' ? BlobBuilder : typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder : typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder : WebKitBlobBuilder;
746 var builder = new Builder();
747 for (var i = 0; i < parts.length; i += 1) {
748 builder.append(parts[i]);
749 }
750 return builder.getBlob(properties.type);
751 }
752}
753
754// This is CommonJS because lie is an external dependency, so Rollup
755// can just ignore it.
756if (typeof Promise === 'undefined') {
757 // In the "nopromises" build this will just throw if you don't have
758 // a global promise object, but it would throw anyway later.
759 _dereq_(3);
760}
761var Promise$1 = Promise;
762
763function executeCallback(promise, callback) {
764 if (callback) {
765 promise.then(function (result) {
766 callback(null, result);
767 }, function (error) {
768 callback(error);
769 });
770 }
771}
772
773function executeTwoCallbacks(promise, callback, errorCallback) {
774 if (typeof callback === 'function') {
775 promise.then(callback);
776 }
777
778 if (typeof errorCallback === 'function') {
779 promise["catch"](errorCallback);
780 }
781}
782
783function normalizeKey(key) {
784 // Cast the key to a string, as that's all we can set as a key.
785 if (typeof key !== 'string') {
786 console.warn(key + ' used as a key, but it is not a string.');
787 key = String(key);
788 }
789
790 return key;
791}
792
793function getCallback() {
794 if (arguments.length && typeof arguments[arguments.length - 1] === 'function') {
795 return arguments[arguments.length - 1];
796 }
797}
798
799// Some code originally from async_storage.js in
800// [Gaia](https://github.com/mozilla-b2g/gaia).
801
802var DETECT_BLOB_SUPPORT_STORE = 'local-forage-detect-blob-support';
803var supportsBlobs = void 0;
804var dbContexts = {};
805var toString = Object.prototype.toString;
806
807// Transaction Modes
808var READ_ONLY = 'readonly';
809var READ_WRITE = 'readwrite';
810
811// Transform a binary string to an array buffer, because otherwise
812// weird stuff happens when you try to work with the binary string directly.
813// It is known.
814// From http://stackoverflow.com/questions/14967647/ (continues on next line)
815// encode-decode-image-with-base64-breaks-image (2013-04-21)
816function _binStringToArrayBuffer(bin) {
817 var length = bin.length;
818 var buf = new ArrayBuffer(length);
819 var arr = new Uint8Array(buf);
820 for (var i = 0; i < length; i++) {
821 arr[i] = bin.charCodeAt(i);
822 }
823 return buf;
824}
825
826//
827// Blobs are not supported in all versions of IndexedDB, notably
828// Chrome <37 and Android <5. In those versions, storing a blob will throw.
829//
830// Various other blob bugs exist in Chrome v37-42 (inclusive).
831// Detecting them is expensive and confusing to users, and Chrome 37-42
832// is at very low usage worldwide, so we do a hacky userAgent check instead.
833//
834// content-type bug: https://code.google.com/p/chromium/issues/detail?id=408120
835// 404 bug: https://code.google.com/p/chromium/issues/detail?id=447916
836// FileReader bug: https://code.google.com/p/chromium/issues/detail?id=447836
837//
838// Code borrowed from PouchDB. See:
839// https://github.com/pouchdb/pouchdb/blob/master/packages/node_modules/pouchdb-adapter-idb/src/blobSupport.js
840//
841function _checkBlobSupportWithoutCaching(idb) {
842 return new Promise$1(function (resolve) {
843 var txn = idb.transaction(DETECT_BLOB_SUPPORT_STORE, READ_WRITE);
844 var blob = createBlob(['']);
845 txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, 'key');
846
847 txn.onabort = function (e) {
848 // If the transaction aborts now its due to not being able to
849 // write to the database, likely due to the disk being full
850 e.preventDefault();
851 e.stopPropagation();
852 resolve(false);
853 };
854
855 txn.oncomplete = function () {
856 var matchedChrome = navigator.userAgent.match(/Chrome\/(\d+)/);
857 var matchedEdge = navigator.userAgent.match(/Edge\//);
858 // MS Edge pretends to be Chrome 42:
859 // https://msdn.microsoft.com/en-us/library/hh869301%28v=vs.85%29.aspx
860 resolve(matchedEdge || !matchedChrome || parseInt(matchedChrome[1], 10) >= 43);
861 };
862 })["catch"](function () {
863 return false; // error, so assume unsupported
864 });
865}
866
867function _checkBlobSupport(idb) {
868 if (typeof supportsBlobs === 'boolean') {
869 return Promise$1.resolve(supportsBlobs);
870 }
871 return _checkBlobSupportWithoutCaching(idb).then(function (value) {
872 supportsBlobs = value;
873 return supportsBlobs;
874 });
875}
876
877function _deferReadiness(dbInfo) {
878 var dbContext = dbContexts[dbInfo.name];
879
880 // Create a deferred object representing the current database operation.
881 var deferredOperation = {};
882
883 deferredOperation.promise = new Promise$1(function (resolve, reject) {
884 deferredOperation.resolve = resolve;
885 deferredOperation.reject = reject;
886 });
887
888 // Enqueue the deferred operation.
889 dbContext.deferredOperations.push(deferredOperation);
890
891 // Chain its promise to the database readiness.
892 if (!dbContext.dbReady) {
893 dbContext.dbReady = deferredOperation.promise;
894 } else {
895 dbContext.dbReady = dbContext.dbReady.then(function () {
896 return deferredOperation.promise;
897 });
898 }
899}
900
901function _advanceReadiness(dbInfo) {
902 var dbContext = dbContexts[dbInfo.name];
903
904 // Dequeue a deferred operation.
905 var deferredOperation = dbContext.deferredOperations.pop();
906
907 // Resolve its promise (which is part of the database readiness
908 // chain of promises).
909 if (deferredOperation) {
910 deferredOperation.resolve();
911 return deferredOperation.promise;
912 }
913}
914
915function _rejectReadiness(dbInfo, err) {
916 var dbContext = dbContexts[dbInfo.name];
917
918 // Dequeue a deferred operation.
919 var deferredOperation = dbContext.deferredOperations.pop();
920
921 // Reject its promise (which is part of the database readiness
922 // chain of promises).
923 if (deferredOperation) {
924 deferredOperation.reject(err);
925 return deferredOperation.promise;
926 }
927}
928
929function _getConnection(dbInfo, upgradeNeeded) {
930 return new Promise$1(function (resolve, reject) {
931 dbContexts[dbInfo.name] = dbContexts[dbInfo.name] || createDbContext();
932
933 if (dbInfo.db) {
934 if (upgradeNeeded) {
935 _deferReadiness(dbInfo);
936 dbInfo.db.close();
937 } else {
938 return resolve(dbInfo.db);
939 }
940 }
941
942 var dbArgs = [dbInfo.name];
943
944 if (upgradeNeeded) {
945 dbArgs.push(dbInfo.version);
946 }
947
948 var openreq = idb.open.apply(idb, dbArgs);
949
950 if (upgradeNeeded) {
951 openreq.onupgradeneeded = function (e) {
952 var db = openreq.result;
953 try {
954 db.createObjectStore(dbInfo.storeName);
955 if (e.oldVersion <= 1) {
956 // Added when support for blob shims was added
957 db.createObjectStore(DETECT_BLOB_SUPPORT_STORE);
958 }
959 } catch (ex) {
960 if (ex.name === 'ConstraintError') {
961 console.warn('The database "' + dbInfo.name + '"' + ' has been upgraded from version ' + e.oldVersion + ' to version ' + e.newVersion + ', but the storage "' + dbInfo.storeName + '" already exists.');
962 } else {
963 throw ex;
964 }
965 }
966 };
967 }
968
969 openreq.onerror = function (e) {
970 e.preventDefault();
971 reject(openreq.error);
972 };
973
974 openreq.onsuccess = function () {
975 resolve(openreq.result);
976 _advanceReadiness(dbInfo);
977 };
978 });
979}
980
981function _getOriginalConnection(dbInfo) {
982 return _getConnection(dbInfo, false);
983}
984
985function _getUpgradedConnection(dbInfo) {
986 return _getConnection(dbInfo, true);
987}
988
989function _isUpgradeNeeded(dbInfo, defaultVersion) {
990 if (!dbInfo.db) {
991 return true;
992 }
993
994 var isNewStore = !dbInfo.db.objectStoreNames.contains(dbInfo.storeName);
995 var isDowngrade = dbInfo.version < dbInfo.db.version;
996 var isUpgrade = dbInfo.version > dbInfo.db.version;
997
998 if (isDowngrade) {
999 // If the version is not the default one
1000 // then warn for impossible downgrade.
1001 if (dbInfo.version !== defaultVersion) {
1002 console.warn('The database "' + dbInfo.name + '"' + " can't be downgraded from version " + dbInfo.db.version + ' to version ' + dbInfo.version + '.');
1003 }
1004 // Align the versions to prevent errors.
1005 dbInfo.version = dbInfo.db.version;
1006 }
1007
1008 if (isUpgrade || isNewStore) {
1009 // If the store is new then increment the version (if needed).
1010 // This will trigger an "upgradeneeded" event which is required
1011 // for creating a store.
1012 if (isNewStore) {
1013 var incVersion = dbInfo.db.version + 1;
1014 if (incVersion > dbInfo.version) {
1015 dbInfo.version = incVersion;
1016 }
1017 }
1018
1019 return true;
1020 }
1021
1022 return false;
1023}
1024
1025// encode a blob for indexeddb engines that don't support blobs
1026function _encodeBlob(blob) {
1027 return new Promise$1(function (resolve, reject) {
1028 var reader = new FileReader();
1029 reader.onerror = reject;
1030 reader.onloadend = function (e) {
1031 var base64 = btoa(e.target.result || '');
1032 resolve({
1033 __local_forage_encoded_blob: true,
1034 data: base64,
1035 type: blob.type
1036 });
1037 };
1038 reader.readAsBinaryString(blob);
1039 });
1040}
1041
1042// decode an encoded blob
1043function _decodeBlob(encodedBlob) {
1044 var arrayBuff = _binStringToArrayBuffer(atob(encodedBlob.data));
1045 return createBlob([arrayBuff], { type: encodedBlob.type });
1046}
1047
1048// is this one of our fancy encoded blobs?
1049function _isEncodedBlob(value) {
1050 return value && value.__local_forage_encoded_blob;
1051}
1052
1053// Specialize the default `ready()` function by making it dependent
1054// on the current database operations. Thus, the driver will be actually
1055// ready when it's been initialized (default) *and* there are no pending
1056// operations on the database (initiated by some other instances).
1057function _fullyReady(callback) {
1058 var self = this;
1059
1060 var promise = self._initReady().then(function () {
1061 var dbContext = dbContexts[self._dbInfo.name];
1062
1063 if (dbContext && dbContext.dbReady) {
1064 return dbContext.dbReady;
1065 }
1066 });
1067
1068 executeTwoCallbacks(promise, callback, callback);
1069 return promise;
1070}
1071
1072// Try to establish a new db connection to replace the
1073// current one which is broken (i.e. experiencing
1074// InvalidStateError while creating a transaction).
1075function _tryReconnect(dbInfo) {
1076 _deferReadiness(dbInfo);
1077
1078 var dbContext = dbContexts[dbInfo.name];
1079 var forages = dbContext.forages;
1080
1081 for (var i = 0; i < forages.length; i++) {
1082 var forage = forages[i];
1083 if (forage._dbInfo.db) {
1084 forage._dbInfo.db.close();
1085 forage._dbInfo.db = null;
1086 }
1087 }
1088 dbInfo.db = null;
1089
1090 return _getOriginalConnection(dbInfo).then(function (db) {
1091 dbInfo.db = db;
1092 if (_isUpgradeNeeded(dbInfo)) {
1093 // Reopen the database for upgrading.
1094 return _getUpgradedConnection(dbInfo);
1095 }
1096 return db;
1097 }).then(function (db) {
1098 // store the latest db reference
1099 // in case the db was upgraded
1100 dbInfo.db = dbContext.db = db;
1101 for (var i = 0; i < forages.length; i++) {
1102 forages[i]._dbInfo.db = db;
1103 }
1104 })["catch"](function (err) {
1105 _rejectReadiness(dbInfo, err);
1106 throw err;
1107 });
1108}
1109
1110// FF doesn't like Promises (micro-tasks) and IDDB store operations,
1111// so we have to do it with callbacks
1112function createTransaction(dbInfo, mode, callback, retries) {
1113 if (retries === undefined) {
1114 retries = 1;
1115 }
1116
1117 try {
1118 var tx = dbInfo.db.transaction(dbInfo.storeName, mode);
1119 callback(null, tx);
1120 } catch (err) {
1121 if (retries > 0 && (!dbInfo.db || err.name === 'InvalidStateError' || err.name === 'NotFoundError')) {
1122 return Promise$1.resolve().then(function () {
1123 if (!dbInfo.db || err.name === 'NotFoundError' && !dbInfo.db.objectStoreNames.contains(dbInfo.storeName) && dbInfo.version <= dbInfo.db.version) {
1124 // increase the db version, to create the new ObjectStore
1125 if (dbInfo.db) {
1126 dbInfo.version = dbInfo.db.version + 1;
1127 }
1128 // Reopen the database for upgrading.
1129 return _getUpgradedConnection(dbInfo);
1130 }
1131 }).then(function () {
1132 return _tryReconnect(dbInfo).then(function () {
1133 createTransaction(dbInfo, mode, callback, retries - 1);
1134 });
1135 })["catch"](callback);
1136 }
1137
1138 callback(err);
1139 }
1140}
1141
1142function createDbContext() {
1143 return {
1144 // Running localForages sharing a database.
1145 forages: [],
1146 // Shared database.
1147 db: null,
1148 // Database readiness (promise).
1149 dbReady: null,
1150 // Deferred operations on the database.
1151 deferredOperations: []
1152 };
1153}
1154
1155// Open the IndexedDB database (automatically creates one if one didn't
1156// previously exist), using any options set in the config.
1157function _initStorage(options) {
1158 var self = this;
1159 var dbInfo = {
1160 db: null
1161 };
1162
1163 if (options) {
1164 for (var i in options) {
1165 dbInfo[i] = options[i];
1166 }
1167 }
1168
1169 // Get the current context of the database;
1170 var dbContext = dbContexts[dbInfo.name];
1171
1172 // ...or create a new context.
1173 if (!dbContext) {
1174 dbContext = createDbContext();
1175 // Register the new context in the global container.
1176 dbContexts[dbInfo.name] = dbContext;
1177 }
1178
1179 // Register itself as a running localForage in the current context.
1180 dbContext.forages.push(self);
1181
1182 // Replace the default `ready()` function with the specialized one.
1183 if (!self._initReady) {
1184 self._initReady = self.ready;
1185 self.ready = _fullyReady;
1186 }
1187
1188 // Create an array of initialization states of the related localForages.
1189 var initPromises = [];
1190
1191 function ignoreErrors() {
1192 // Don't handle errors here,
1193 // just makes sure related localForages aren't pending.
1194 return Promise$1.resolve();
1195 }
1196
1197 for (var j = 0; j < dbContext.forages.length; j++) {
1198 var forage = dbContext.forages[j];
1199 if (forage !== self) {
1200 // Don't wait for itself...
1201 initPromises.push(forage._initReady()["catch"](ignoreErrors));
1202 }
1203 }
1204
1205 // Take a snapshot of the related localForages.
1206 var forages = dbContext.forages.slice(0);
1207
1208 // Initialize the connection process only when
1209 // all the related localForages aren't pending.
1210 return Promise$1.all(initPromises).then(function () {
1211 dbInfo.db = dbContext.db;
1212 // Get the connection or open a new one without upgrade.
1213 return _getOriginalConnection(dbInfo);
1214 }).then(function (db) {
1215 dbInfo.db = db;
1216 if (_isUpgradeNeeded(dbInfo, self._defaultConfig.version)) {
1217 // Reopen the database for upgrading.
1218 return _getUpgradedConnection(dbInfo);
1219 }
1220 return db;
1221 }).then(function (db) {
1222 dbInfo.db = dbContext.db = db;
1223 self._dbInfo = dbInfo;
1224 // Share the final connection amongst related localForages.
1225 for (var k = 0; k < forages.length; k++) {
1226 var forage = forages[k];
1227 if (forage !== self) {
1228 // Self is already up-to-date.
1229 forage._dbInfo.db = dbInfo.db;
1230 forage._dbInfo.version = dbInfo.version;
1231 }
1232 }
1233 });
1234}
1235
1236function getItem(key, callback) {
1237 var self = this;
1238
1239 key = normalizeKey(key);
1240
1241 var promise = new Promise$1(function (resolve, reject) {
1242 self.ready().then(function () {
1243 createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
1244 if (err) {
1245 return reject(err);
1246 }
1247
1248 try {
1249 var store = transaction.objectStore(self._dbInfo.storeName);
1250 var req = store.get(key);
1251
1252 req.onsuccess = function () {
1253 var value = req.result;
1254 if (value === undefined) {
1255 value = null;
1256 }
1257 if (_isEncodedBlob(value)) {
1258 value = _decodeBlob(value);
1259 }
1260 resolve(value);
1261 };
1262
1263 req.onerror = function () {
1264 reject(req.error);
1265 };
1266 } catch (e) {
1267 reject(e);
1268 }
1269 });
1270 })["catch"](reject);
1271 });
1272
1273 executeCallback(promise, callback);
1274 return promise;
1275}
1276
1277// Iterate over all items stored in database.
1278function iterate(iterator, callback) {
1279 var self = this;
1280
1281 var promise = new Promise$1(function (resolve, reject) {
1282 self.ready().then(function () {
1283 createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
1284 if (err) {
1285 return reject(err);
1286 }
1287
1288 try {
1289 var store = transaction.objectStore(self._dbInfo.storeName);
1290 var req = store.openCursor();
1291 var iterationNumber = 1;
1292
1293 req.onsuccess = function () {
1294 var cursor = req.result;
1295
1296 if (cursor) {
1297 var value = cursor.value;
1298 if (_isEncodedBlob(value)) {
1299 value = _decodeBlob(value);
1300 }
1301 var result = iterator(value, cursor.key, iterationNumber++);
1302
1303 // when the iterator callback returns any
1304 // (non-`undefined`) value, then we stop
1305 // the iteration immediately
1306 if (result !== void 0) {
1307 resolve(result);
1308 } else {
1309 cursor["continue"]();
1310 }
1311 } else {
1312 resolve();
1313 }
1314 };
1315
1316 req.onerror = function () {
1317 reject(req.error);
1318 };
1319 } catch (e) {
1320 reject(e);
1321 }
1322 });
1323 })["catch"](reject);
1324 });
1325
1326 executeCallback(promise, callback);
1327
1328 return promise;
1329}
1330
1331function setItem(key, value, callback) {
1332 var self = this;
1333
1334 key = normalizeKey(key);
1335
1336 var promise = new Promise$1(function (resolve, reject) {
1337 var dbInfo;
1338 self.ready().then(function () {
1339 dbInfo = self._dbInfo;
1340 if (toString.call(value) === '[object Blob]') {
1341 return _checkBlobSupport(dbInfo.db).then(function (blobSupport) {
1342 if (blobSupport) {
1343 return value;
1344 }
1345 return _encodeBlob(value);
1346 });
1347 }
1348 return value;
1349 }).then(function (value) {
1350 createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {
1351 if (err) {
1352 return reject(err);
1353 }
1354
1355 try {
1356 var store = transaction.objectStore(self._dbInfo.storeName);
1357
1358 // The reason we don't _save_ null is because IE 10 does
1359 // not support saving the `null` type in IndexedDB. How
1360 // ironic, given the bug below!
1361 // See: https://github.com/mozilla/localForage/issues/161
1362 if (value === null) {
1363 value = undefined;
1364 }
1365
1366 var req = store.put(value, key);
1367
1368 transaction.oncomplete = function () {
1369 // Cast to undefined so the value passed to
1370 // callback/promise is the same as what one would get out
1371 // of `getItem()` later. This leads to some weirdness
1372 // (setItem('foo', undefined) will return `null`), but
1373 // it's not my fault localStorage is our baseline and that
1374 // it's weird.
1375 if (value === undefined) {
1376 value = null;
1377 }
1378
1379 resolve(value);
1380 };
1381 transaction.onabort = transaction.onerror = function () {
1382 var err = req.error ? req.error : req.transaction.error;
1383 reject(err);
1384 };
1385 } catch (e) {
1386 reject(e);
1387 }
1388 });
1389 })["catch"](reject);
1390 });
1391
1392 executeCallback(promise, callback);
1393 return promise;
1394}
1395
1396function removeItem(key, callback) {
1397 var self = this;
1398
1399 key = normalizeKey(key);
1400
1401 var promise = new Promise$1(function (resolve, reject) {
1402 self.ready().then(function () {
1403 createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {
1404 if (err) {
1405 return reject(err);
1406 }
1407
1408 try {
1409 var store = transaction.objectStore(self._dbInfo.storeName);
1410 // We use a Grunt task to make this safe for IE and some
1411 // versions of Android (including those used by Cordova).
1412 // Normally IE won't like `.delete()` and will insist on
1413 // using `['delete']()`, but we have a build step that
1414 // fixes this for us now.
1415 var req = store["delete"](key);
1416 transaction.oncomplete = function () {
1417 resolve();
1418 };
1419
1420 transaction.onerror = function () {
1421 reject(req.error);
1422 };
1423
1424 // The request will be also be aborted if we've exceeded our storage
1425 // space.
1426 transaction.onabort = function () {
1427 var err = req.error ? req.error : req.transaction.error;
1428 reject(err);
1429 };
1430 } catch (e) {
1431 reject(e);
1432 }
1433 });
1434 })["catch"](reject);
1435 });
1436
1437 executeCallback(promise, callback);
1438 return promise;
1439}
1440
1441function clear(callback) {
1442 var self = this;
1443
1444 var promise = new Promise$1(function (resolve, reject) {
1445 self.ready().then(function () {
1446 createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {
1447 if (err) {
1448 return reject(err);
1449 }
1450
1451 try {
1452 var store = transaction.objectStore(self._dbInfo.storeName);
1453 var req = store.clear();
1454
1455 transaction.oncomplete = function () {
1456 resolve();
1457 };
1458
1459 transaction.onabort = transaction.onerror = function () {
1460 var err = req.error ? req.error : req.transaction.error;
1461 reject(err);
1462 };
1463 } catch (e) {
1464 reject(e);
1465 }
1466 });
1467 })["catch"](reject);
1468 });
1469
1470 executeCallback(promise, callback);
1471 return promise;
1472}
1473
1474function length(callback) {
1475 var self = this;
1476
1477 var promise = new Promise$1(function (resolve, reject) {
1478 self.ready().then(function () {
1479 createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
1480 if (err) {
1481 return reject(err);
1482 }
1483
1484 try {
1485 var store = transaction.objectStore(self._dbInfo.storeName);
1486 var req = store.count();
1487
1488 req.onsuccess = function () {
1489 resolve(req.result);
1490 };
1491
1492 req.onerror = function () {
1493 reject(req.error);
1494 };
1495 } catch (e) {
1496 reject(e);
1497 }
1498 });
1499 })["catch"](reject);
1500 });
1501
1502 executeCallback(promise, callback);
1503 return promise;
1504}
1505
1506function key(n, callback) {
1507 var self = this;
1508
1509 var promise = new Promise$1(function (resolve, reject) {
1510 if (n < 0) {
1511 resolve(null);
1512
1513 return;
1514 }
1515
1516 self.ready().then(function () {
1517 createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
1518 if (err) {
1519 return reject(err);
1520 }
1521
1522 try {
1523 var store = transaction.objectStore(self._dbInfo.storeName);
1524 var advanced = false;
1525 var req = store.openKeyCursor();
1526
1527 req.onsuccess = function () {
1528 var cursor = req.result;
1529 if (!cursor) {
1530 // this means there weren't enough keys
1531 resolve(null);
1532
1533 return;
1534 }
1535
1536 if (n === 0) {
1537 // We have the first key, return it if that's what they
1538 // wanted.
1539 resolve(cursor.key);
1540 } else {
1541 if (!advanced) {
1542 // Otherwise, ask the cursor to skip ahead n
1543 // records.
1544 advanced = true;
1545 cursor.advance(n);
1546 } else {
1547 // When we get here, we've got the nth key.
1548 resolve(cursor.key);
1549 }
1550 }
1551 };
1552
1553 req.onerror = function () {
1554 reject(req.error);
1555 };
1556 } catch (e) {
1557 reject(e);
1558 }
1559 });
1560 })["catch"](reject);
1561 });
1562
1563 executeCallback(promise, callback);
1564 return promise;
1565}
1566
1567function keys(callback) {
1568 var self = this;
1569
1570 var promise = new Promise$1(function (resolve, reject) {
1571 self.ready().then(function () {
1572 createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
1573 if (err) {
1574 return reject(err);
1575 }
1576
1577 try {
1578 var store = transaction.objectStore(self._dbInfo.storeName);
1579 var req = store.openKeyCursor();
1580 var keys = [];
1581
1582 req.onsuccess = function () {
1583 var cursor = req.result;
1584
1585 if (!cursor) {
1586 resolve(keys);
1587 return;
1588 }
1589
1590 keys.push(cursor.key);
1591 cursor["continue"]();
1592 };
1593
1594 req.onerror = function () {
1595 reject(req.error);
1596 };
1597 } catch (e) {
1598 reject(e);
1599 }
1600 });
1601 })["catch"](reject);
1602 });
1603
1604 executeCallback(promise, callback);
1605 return promise;
1606}
1607
1608function dropInstance(options, callback) {
1609 callback = getCallback.apply(this, arguments);
1610
1611 var currentConfig = this.config();
1612 options = typeof options !== 'function' && options || {};
1613 if (!options.name) {
1614 options.name = options.name || currentConfig.name;
1615 options.storeName = options.storeName || currentConfig.storeName;
1616 }
1617
1618 var self = this;
1619 var promise;
1620 if (!options.name) {
1621 promise = Promise$1.reject('Invalid arguments');
1622 } else {
1623 var isCurrentDb = options.name === currentConfig.name && self._dbInfo.db;
1624
1625 var dbPromise = isCurrentDb ? Promise$1.resolve(self._dbInfo.db) : _getOriginalConnection(options).then(function (db) {
1626 var dbContext = dbContexts[options.name];
1627 var forages = dbContext.forages;
1628 dbContext.db = db;
1629 for (var i = 0; i < forages.length; i++) {
1630 forages[i]._dbInfo.db = db;
1631 }
1632 return db;
1633 });
1634
1635 if (!options.storeName) {
1636 promise = dbPromise.then(function (db) {
1637 _deferReadiness(options);
1638
1639 var dbContext = dbContexts[options.name];
1640 var forages = dbContext.forages;
1641
1642 db.close();
1643 for (var i = 0; i < forages.length; i++) {
1644 var forage = forages[i];
1645 forage._dbInfo.db = null;
1646 }
1647
1648 var dropDBPromise = new Promise$1(function (resolve, reject) {
1649 var req = idb.deleteDatabase(options.name);
1650
1651 req.onerror = req.onblocked = function (err) {
1652 var db = req.result;
1653 if (db) {
1654 db.close();
1655 }
1656 reject(err);
1657 };
1658
1659 req.onsuccess = function () {
1660 var db = req.result;
1661 if (db) {
1662 db.close();
1663 }
1664 resolve(db);
1665 };
1666 });
1667
1668 return dropDBPromise.then(function (db) {
1669 dbContext.db = db;
1670 for (var i = 0; i < forages.length; i++) {
1671 var _forage = forages[i];
1672 _advanceReadiness(_forage._dbInfo);
1673 }
1674 })["catch"](function (err) {
1675 (_rejectReadiness(options, err) || Promise$1.resolve())["catch"](function () {});
1676 throw err;
1677 });
1678 });
1679 } else {
1680 promise = dbPromise.then(function (db) {
1681 if (!db.objectStoreNames.contains(options.storeName)) {
1682 return;
1683 }
1684
1685 var newVersion = db.version + 1;
1686
1687 _deferReadiness(options);
1688
1689 var dbContext = dbContexts[options.name];
1690 var forages = dbContext.forages;
1691
1692 db.close();
1693 for (var i = 0; i < forages.length; i++) {
1694 var forage = forages[i];
1695 forage._dbInfo.db = null;
1696 forage._dbInfo.version = newVersion;
1697 }
1698
1699 var dropObjectPromise = new Promise$1(function (resolve, reject) {
1700 var req = idb.open(options.name, newVersion);
1701
1702 req.onerror = function (err) {
1703 var db = req.result;
1704 db.close();
1705 reject(err);
1706 };
1707
1708 req.onupgradeneeded = function () {
1709 var db = req.result;
1710 db.deleteObjectStore(options.storeName);
1711 };
1712
1713 req.onsuccess = function () {
1714 var db = req.result;
1715 db.close();
1716 resolve(db);
1717 };
1718 });
1719
1720 return dropObjectPromise.then(function (db) {
1721 dbContext.db = db;
1722 for (var j = 0; j < forages.length; j++) {
1723 var _forage2 = forages[j];
1724 _forage2._dbInfo.db = db;
1725 _advanceReadiness(_forage2._dbInfo);
1726 }
1727 })["catch"](function (err) {
1728 (_rejectReadiness(options, err) || Promise$1.resolve())["catch"](function () {});
1729 throw err;
1730 });
1731 });
1732 }
1733 }
1734
1735 executeCallback(promise, callback);
1736 return promise;
1737}
1738
1739var asyncStorage = {
1740 _driver: 'asyncStorage',
1741 _initStorage: _initStorage,
1742 _support: isIndexedDBValid(),
1743 iterate: iterate,
1744 getItem: getItem,
1745 setItem: setItem,
1746 removeItem: removeItem,
1747 clear: clear,
1748 length: length,
1749 key: key,
1750 keys: keys,
1751 dropInstance: dropInstance
1752};
1753
1754function isWebSQLValid() {
1755 return typeof openDatabase === 'function';
1756}
1757
1758// Sadly, the best way to save binary data in WebSQL/localStorage is serializing
1759// it to Base64, so this is how we store it to prevent very strange errors with less
1760// verbose ways of binary <-> string data storage.
1761var BASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
1762
1763var BLOB_TYPE_PREFIX = '~~local_forage_type~';
1764var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
1765
1766var SERIALIZED_MARKER = '__lfsc__:';
1767var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;
1768
1769// OMG the serializations!
1770var TYPE_ARRAYBUFFER = 'arbf';
1771var TYPE_BLOB = 'blob';
1772var TYPE_INT8ARRAY = 'si08';
1773var TYPE_UINT8ARRAY = 'ui08';
1774var TYPE_UINT8CLAMPEDARRAY = 'uic8';
1775var TYPE_INT16ARRAY = 'si16';
1776var TYPE_INT32ARRAY = 'si32';
1777var TYPE_UINT16ARRAY = 'ur16';
1778var TYPE_UINT32ARRAY = 'ui32';
1779var TYPE_FLOAT32ARRAY = 'fl32';
1780var TYPE_FLOAT64ARRAY = 'fl64';
1781var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + TYPE_ARRAYBUFFER.length;
1782
1783var toString$1 = Object.prototype.toString;
1784
1785function stringToBuffer(serializedString) {
1786 // Fill the string into a ArrayBuffer.
1787 var bufferLength = serializedString.length * 0.75;
1788 var len = serializedString.length;
1789 var i;
1790 var p = 0;
1791 var encoded1, encoded2, encoded3, encoded4;
1792
1793 if (serializedString[serializedString.length - 1] === '=') {
1794 bufferLength--;
1795 if (serializedString[serializedString.length - 2] === '=') {
1796 bufferLength--;
1797 }
1798 }
1799
1800 var buffer = new ArrayBuffer(bufferLength);
1801 var bytes = new Uint8Array(buffer);
1802
1803 for (i = 0; i < len; i += 4) {
1804 encoded1 = BASE_CHARS.indexOf(serializedString[i]);
1805 encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);
1806 encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);
1807 encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);
1808
1809 /*jslint bitwise: true */
1810 bytes[p++] = encoded1 << 2 | encoded2 >> 4;
1811 bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;
1812 bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;
1813 }
1814 return buffer;
1815}
1816
1817// Converts a buffer to a string to store, serialized, in the backend
1818// storage library.
1819function bufferToString(buffer) {
1820 // base64-arraybuffer
1821 var bytes = new Uint8Array(buffer);
1822 var base64String = '';
1823 var i;
1824
1825 for (i = 0; i < bytes.length; i += 3) {
1826 /*jslint bitwise: true */
1827 base64String += BASE_CHARS[bytes[i] >> 2];
1828 base64String += BASE_CHARS[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];
1829 base64String += BASE_CHARS[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];
1830 base64String += BASE_CHARS[bytes[i + 2] & 63];
1831 }
1832
1833 if (bytes.length % 3 === 2) {
1834 base64String = base64String.substring(0, base64String.length - 1) + '=';
1835 } else if (bytes.length % 3 === 1) {
1836 base64String = base64String.substring(0, base64String.length - 2) + '==';
1837 }
1838
1839 return base64String;
1840}
1841
1842// Serialize a value, afterwards executing a callback (which usually
1843// instructs the `setItem()` callback/promise to be executed). This is how
1844// we store binary data with localStorage.
1845function serialize(value, callback) {
1846 var valueType = '';
1847 if (value) {
1848 valueType = toString$1.call(value);
1849 }
1850
1851 // Cannot use `value instanceof ArrayBuffer` or such here, as these
1852 // checks fail when running the tests using casper.js...
1853 //
1854 // TODO: See why those tests fail and use a better solution.
1855 if (value && (valueType === '[object ArrayBuffer]' || value.buffer && toString$1.call(value.buffer) === '[object ArrayBuffer]')) {
1856 // Convert binary arrays to a string and prefix the string with
1857 // a special marker.
1858 var buffer;
1859 var marker = SERIALIZED_MARKER;
1860
1861 if (value instanceof ArrayBuffer) {
1862 buffer = value;
1863 marker += TYPE_ARRAYBUFFER;
1864 } else {
1865 buffer = value.buffer;
1866
1867 if (valueType === '[object Int8Array]') {
1868 marker += TYPE_INT8ARRAY;
1869 } else if (valueType === '[object Uint8Array]') {
1870 marker += TYPE_UINT8ARRAY;
1871 } else if (valueType === '[object Uint8ClampedArray]') {
1872 marker += TYPE_UINT8CLAMPEDARRAY;
1873 } else if (valueType === '[object Int16Array]') {
1874 marker += TYPE_INT16ARRAY;
1875 } else if (valueType === '[object Uint16Array]') {
1876 marker += TYPE_UINT16ARRAY;
1877 } else if (valueType === '[object Int32Array]') {
1878 marker += TYPE_INT32ARRAY;
1879 } else if (valueType === '[object Uint32Array]') {
1880 marker += TYPE_UINT32ARRAY;
1881 } else if (valueType === '[object Float32Array]') {
1882 marker += TYPE_FLOAT32ARRAY;
1883 } else if (valueType === '[object Float64Array]') {
1884 marker += TYPE_FLOAT64ARRAY;
1885 } else {
1886 callback(new Error('Failed to get type for BinaryArray'));
1887 }
1888 }
1889
1890 callback(marker + bufferToString(buffer));
1891 } else if (valueType === '[object Blob]') {
1892 // Conver the blob to a binaryArray and then to a string.
1893 var fileReader = new FileReader();
1894
1895 fileReader.onload = function () {
1896 // Backwards-compatible prefix for the blob type.
1897 var str = BLOB_TYPE_PREFIX + value.type + '~' + bufferToString(this.result);
1898
1899 callback(SERIALIZED_MARKER + TYPE_BLOB + str);
1900 };
1901
1902 fileReader.readAsArrayBuffer(value);
1903 } else {
1904 try {
1905 callback(JSON.stringify(value));
1906 } catch (e) {
1907 console.error("Couldn't convert value into a JSON string: ", value);
1908
1909 callback(null, e);
1910 }
1911 }
1912}
1913
1914// Deserialize data we've inserted into a value column/field. We place
1915// special markers into our strings to mark them as encoded; this isn't
1916// as nice as a meta field, but it's the only sane thing we can do whilst
1917// keeping localStorage support intact.
1918//
1919// Oftentimes this will just deserialize JSON content, but if we have a
1920// special marker (SERIALIZED_MARKER, defined above), we will extract
1921// some kind of arraybuffer/binary data/typed array out of the string.
1922function deserialize(value) {
1923 // If we haven't marked this string as being specially serialized (i.e.
1924 // something other than serialized JSON), we can just return it and be
1925 // done with it.
1926 if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
1927 return JSON.parse(value);
1928 }
1929
1930 // The following code deals with deserializing some kind of Blob or
1931 // TypedArray. First we separate out the type of data we're dealing
1932 // with from the data itself.
1933 var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
1934 var type = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);
1935
1936 var blobType;
1937 // Backwards-compatible blob type serialization strategy.
1938 // DBs created with older versions of localForage will simply not have the blob type.
1939 if (type === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
1940 var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
1941 blobType = matcher[1];
1942 serializedString = serializedString.substring(matcher[0].length);
1943 }
1944 var buffer = stringToBuffer(serializedString);
1945
1946 // Return the right type based on the code/type set during
1947 // serialization.
1948 switch (type) {
1949 case TYPE_ARRAYBUFFER:
1950 return buffer;
1951 case TYPE_BLOB:
1952 return createBlob([buffer], { type: blobType });
1953 case TYPE_INT8ARRAY:
1954 return new Int8Array(buffer);
1955 case TYPE_UINT8ARRAY:
1956 return new Uint8Array(buffer);
1957 case TYPE_UINT8CLAMPEDARRAY:
1958 return new Uint8ClampedArray(buffer);
1959 case TYPE_INT16ARRAY:
1960 return new Int16Array(buffer);
1961 case TYPE_UINT16ARRAY:
1962 return new Uint16Array(buffer);
1963 case TYPE_INT32ARRAY:
1964 return new Int32Array(buffer);
1965 case TYPE_UINT32ARRAY:
1966 return new Uint32Array(buffer);
1967 case TYPE_FLOAT32ARRAY:
1968 return new Float32Array(buffer);
1969 case TYPE_FLOAT64ARRAY:
1970 return new Float64Array(buffer);
1971 default:
1972 throw new Error('Unkown type: ' + type);
1973 }
1974}
1975
1976var localforageSerializer = {
1977 serialize: serialize,
1978 deserialize: deserialize,
1979 stringToBuffer: stringToBuffer,
1980 bufferToString: bufferToString
1981};
1982
1983/*
1984 * Includes code from:
1985 *
1986 * base64-arraybuffer
1987 * https://github.com/niklasvh/base64-arraybuffer
1988 *
1989 * Copyright (c) 2012 Niklas von Hertzen
1990 * Licensed under the MIT license.
1991 */
1992
1993function createDbTable(t, dbInfo, callback, errorCallback) {
1994 t.executeSql('CREATE TABLE IF NOT EXISTS ' + dbInfo.storeName + ' ' + '(id INTEGER PRIMARY KEY, key unique, value)', [], callback, errorCallback);
1995}
1996
1997// Open the WebSQL database (automatically creates one if one didn't
1998// previously exist), using any options set in the config.
1999function _initStorage$1(options) {
2000 var self = this;
2001 var dbInfo = {
2002 db: null
2003 };
2004
2005 if (options) {
2006 for (var i in options) {
2007 dbInfo[i] = typeof options[i] !== 'string' ? options[i].toString() : options[i];
2008 }
2009 }
2010
2011 var dbInfoPromise = new Promise$1(function (resolve, reject) {
2012 // Open the database; the openDatabase API will automatically
2013 // create it for us if it doesn't exist.
2014 try {
2015 dbInfo.db = openDatabase(dbInfo.name, String(dbInfo.version), dbInfo.description, dbInfo.size);
2016 } catch (e) {
2017 return reject(e);
2018 }
2019
2020 // Create our key/value table if it doesn't exist.
2021 dbInfo.db.transaction(function (t) {
2022 createDbTable(t, dbInfo, function () {
2023 self._dbInfo = dbInfo;
2024 resolve();
2025 }, function (t, error) {
2026 reject(error);
2027 });
2028 }, reject);
2029 });
2030
2031 dbInfo.serializer = localforageSerializer;
2032 return dbInfoPromise;
2033}
2034
2035function tryExecuteSql(t, dbInfo, sqlStatement, args, callback, errorCallback) {
2036 t.executeSql(sqlStatement, args, callback, function (t, error) {
2037 if (error.code === error.SYNTAX_ERR) {
2038 t.executeSql('SELECT name FROM sqlite_master ' + "WHERE type='table' AND name = ?", [dbInfo.storeName], function (t, results) {
2039 if (!results.rows.length) {
2040 // if the table is missing (was deleted)
2041 // re-create it table and retry
2042 createDbTable(t, dbInfo, function () {
2043 t.executeSql(sqlStatement, args, callback, errorCallback);
2044 }, errorCallback);
2045 } else {
2046 errorCallback(t, error);
2047 }
2048 }, errorCallback);
2049 } else {
2050 errorCallback(t, error);
2051 }
2052 }, errorCallback);
2053}
2054
2055function getItem$1(key, callback) {
2056 var self = this;
2057
2058 key = normalizeKey(key);
2059
2060 var promise = new Promise$1(function (resolve, reject) {
2061 self.ready().then(function () {
2062 var dbInfo = self._dbInfo;
2063 dbInfo.db.transaction(function (t) {
2064 tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName + ' WHERE key = ? LIMIT 1', [key], function (t, results) {
2065 var result = results.rows.length ? results.rows.item(0).value : null;
2066
2067 // Check to see if this is serialized content we need to
2068 // unpack.
2069 if (result) {
2070 result = dbInfo.serializer.deserialize(result);
2071 }
2072
2073 resolve(result);
2074 }, function (t, error) {
2075 reject(error);
2076 });
2077 });
2078 })["catch"](reject);
2079 });
2080
2081 executeCallback(promise, callback);
2082 return promise;
2083}
2084
2085function iterate$1(iterator, callback) {
2086 var self = this;
2087
2088 var promise = new Promise$1(function (resolve, reject) {
2089 self.ready().then(function () {
2090 var dbInfo = self._dbInfo;
2091
2092 dbInfo.db.transaction(function (t) {
2093 tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName, [], function (t, results) {
2094 var rows = results.rows;
2095 var length = rows.length;
2096
2097 for (var i = 0; i < length; i++) {
2098 var item = rows.item(i);
2099 var result = item.value;
2100
2101 // Check to see if this is serialized content
2102 // we need to unpack.
2103 if (result) {
2104 result = dbInfo.serializer.deserialize(result);
2105 }
2106
2107 result = iterator(result, item.key, i + 1);
2108
2109 // void(0) prevents problems with redefinition
2110 // of `undefined`.
2111 if (result !== void 0) {
2112 resolve(result);
2113 return;
2114 }
2115 }
2116
2117 resolve();
2118 }, function (t, error) {
2119 reject(error);
2120 });
2121 });
2122 })["catch"](reject);
2123 });
2124
2125 executeCallback(promise, callback);
2126 return promise;
2127}
2128
2129function _setItem(key, value, callback, retriesLeft) {
2130 var self = this;
2131
2132 key = normalizeKey(key);
2133
2134 var promise = new Promise$1(function (resolve, reject) {
2135 self.ready().then(function () {
2136 // The localStorage API doesn't return undefined values in an
2137 // "expected" way, so undefined is always cast to null in all
2138 // drivers. See: https://github.com/mozilla/localForage/pull/42
2139 if (value === undefined) {
2140 value = null;
2141 }
2142
2143 // Save the original value to pass to the callback.
2144 var originalValue = value;
2145
2146 var dbInfo = self._dbInfo;
2147 dbInfo.serializer.serialize(value, function (value, error) {
2148 if (error) {
2149 reject(error);
2150 } else {
2151 dbInfo.db.transaction(function (t) {
2152 tryExecuteSql(t, dbInfo, 'INSERT OR REPLACE INTO ' + dbInfo.storeName + ' ' + '(key, value) VALUES (?, ?)', [key, value], function () {
2153 resolve(originalValue);
2154 }, function (t, error) {
2155 reject(error);
2156 });
2157 }, function (sqlError) {
2158 // The transaction failed; check
2159 // to see if it's a quota error.
2160 if (sqlError.code === sqlError.QUOTA_ERR) {
2161 // We reject the callback outright for now, but
2162 // it's worth trying to re-run the transaction.
2163 // Even if the user accepts the prompt to use
2164 // more storage on Safari, this error will
2165 // be called.
2166 //
2167 // Try to re-run the transaction.
2168 if (retriesLeft > 0) {
2169 resolve(_setItem.apply(self, [key, originalValue, callback, retriesLeft - 1]));
2170 return;
2171 }
2172 reject(sqlError);
2173 }
2174 });
2175 }
2176 });
2177 })["catch"](reject);
2178 });
2179
2180 executeCallback(promise, callback);
2181 return promise;
2182}
2183
2184function setItem$1(key, value, callback) {
2185 return _setItem.apply(this, [key, value, callback, 1]);
2186}
2187
2188function removeItem$1(key, callback) {
2189 var self = this;
2190
2191 key = normalizeKey(key);
2192
2193 var promise = new Promise$1(function (resolve, reject) {
2194 self.ready().then(function () {
2195 var dbInfo = self._dbInfo;
2196 dbInfo.db.transaction(function (t) {
2197 tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName + ' WHERE key = ?', [key], function () {
2198 resolve();
2199 }, function (t, error) {
2200 reject(error);
2201 });
2202 });
2203 })["catch"](reject);
2204 });
2205
2206 executeCallback(promise, callback);
2207 return promise;
2208}
2209
2210// Deletes every item in the table.
2211// TODO: Find out if this resets the AUTO_INCREMENT number.
2212function clear$1(callback) {
2213 var self = this;
2214
2215 var promise = new Promise$1(function (resolve, reject) {
2216 self.ready().then(function () {
2217 var dbInfo = self._dbInfo;
2218 dbInfo.db.transaction(function (t) {
2219 tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName, [], function () {
2220 resolve();
2221 }, function (t, error) {
2222 reject(error);
2223 });
2224 });
2225 })["catch"](reject);
2226 });
2227
2228 executeCallback(promise, callback);
2229 return promise;
2230}
2231
2232// Does a simple `COUNT(key)` to get the number of items stored in
2233// localForage.
2234function length$1(callback) {
2235 var self = this;
2236
2237 var promise = new Promise$1(function (resolve, reject) {
2238 self.ready().then(function () {
2239 var dbInfo = self._dbInfo;
2240 dbInfo.db.transaction(function (t) {
2241 // Ahhh, SQL makes this one soooooo easy.
2242 tryExecuteSql(t, dbInfo, 'SELECT COUNT(key) as c FROM ' + dbInfo.storeName, [], function (t, results) {
2243 var result = results.rows.item(0).c;
2244 resolve(result);
2245 }, function (t, error) {
2246 reject(error);
2247 });
2248 });
2249 })["catch"](reject);
2250 });
2251
2252 executeCallback(promise, callback);
2253 return promise;
2254}
2255
2256// Return the key located at key index X; essentially gets the key from a
2257// `WHERE id = ?`. This is the most efficient way I can think to implement
2258// this rarely-used (in my experience) part of the API, but it can seem
2259// inconsistent, because we do `INSERT OR REPLACE INTO` on `setItem()`, so
2260// the ID of each key will change every time it's updated. Perhaps a stored
2261// procedure for the `setItem()` SQL would solve this problem?
2262// TODO: Don't change ID on `setItem()`.
2263function key$1(n, callback) {
2264 var self = this;
2265
2266 var promise = new Promise$1(function (resolve, reject) {
2267 self.ready().then(function () {
2268 var dbInfo = self._dbInfo;
2269 dbInfo.db.transaction(function (t) {
2270 tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName + ' WHERE id = ? LIMIT 1', [n + 1], function (t, results) {
2271 var result = results.rows.length ? results.rows.item(0).key : null;
2272 resolve(result);
2273 }, function (t, error) {
2274 reject(error);
2275 });
2276 });
2277 })["catch"](reject);
2278 });
2279
2280 executeCallback(promise, callback);
2281 return promise;
2282}
2283
2284function keys$1(callback) {
2285 var self = this;
2286
2287 var promise = new Promise$1(function (resolve, reject) {
2288 self.ready().then(function () {
2289 var dbInfo = self._dbInfo;
2290 dbInfo.db.transaction(function (t) {
2291 tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName, [], function (t, results) {
2292 var keys = [];
2293
2294 for (var i = 0; i < results.rows.length; i++) {
2295 keys.push(results.rows.item(i).key);
2296 }
2297
2298 resolve(keys);
2299 }, function (t, error) {
2300 reject(error);
2301 });
2302 });
2303 })["catch"](reject);
2304 });
2305
2306 executeCallback(promise, callback);
2307 return promise;
2308}
2309
2310// https://www.w3.org/TR/webdatabase/#databases
2311// > There is no way to enumerate or delete the databases available for an origin from this API.
2312function getAllStoreNames(db) {
2313 return new Promise$1(function (resolve, reject) {
2314 db.transaction(function (t) {
2315 t.executeSql('SELECT name FROM sqlite_master ' + "WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'", [], function (t, results) {
2316 var storeNames = [];
2317
2318 for (var i = 0; i < results.rows.length; i++) {
2319 storeNames.push(results.rows.item(i).name);
2320 }
2321
2322 resolve({
2323 db: db,
2324 storeNames: storeNames
2325 });
2326 }, function (t, error) {
2327 reject(error);
2328 });
2329 }, function (sqlError) {
2330 reject(sqlError);
2331 });
2332 });
2333}
2334
2335function dropInstance$1(options, callback) {
2336 callback = getCallback.apply(this, arguments);
2337
2338 var currentConfig = this.config();
2339 options = typeof options !== 'function' && options || {};
2340 if (!options.name) {
2341 options.name = options.name || currentConfig.name;
2342 options.storeName = options.storeName || currentConfig.storeName;
2343 }
2344
2345 var self = this;
2346 var promise;
2347 if (!options.name) {
2348 promise = Promise$1.reject('Invalid arguments');
2349 } else {
2350 promise = new Promise$1(function (resolve) {
2351 var db;
2352 if (options.name === currentConfig.name) {
2353 // use the db reference of the current instance
2354 db = self._dbInfo.db;
2355 } else {
2356 db = openDatabase(options.name, '', '', 0);
2357 }
2358
2359 if (!options.storeName) {
2360 // drop all database tables
2361 resolve(getAllStoreNames(db));
2362 } else {
2363 resolve({
2364 db: db,
2365 storeNames: [options.storeName]
2366 });
2367 }
2368 }).then(function (operationInfo) {
2369 return new Promise$1(function (resolve, reject) {
2370 operationInfo.db.transaction(function (t) {
2371 function dropTable(storeName) {
2372 return new Promise$1(function (resolve, reject) {
2373 t.executeSql('DROP TABLE IF EXISTS ' + storeName, [], function () {
2374 resolve();
2375 }, function (t, error) {
2376 reject(error);
2377 });
2378 });
2379 }
2380
2381 var operations = [];
2382 for (var i = 0, len = operationInfo.storeNames.length; i < len; i++) {
2383 operations.push(dropTable(operationInfo.storeNames[i]));
2384 }
2385
2386 Promise$1.all(operations).then(function () {
2387 resolve();
2388 })["catch"](function (e) {
2389 reject(e);
2390 });
2391 }, function (sqlError) {
2392 reject(sqlError);
2393 });
2394 });
2395 });
2396 }
2397
2398 executeCallback(promise, callback);
2399 return promise;
2400}
2401
2402var webSQLStorage = {
2403 _driver: 'webSQLStorage',
2404 _initStorage: _initStorage$1,
2405 _support: isWebSQLValid(),
2406 iterate: iterate$1,
2407 getItem: getItem$1,
2408 setItem: setItem$1,
2409 removeItem: removeItem$1,
2410 clear: clear$1,
2411 length: length$1,
2412 key: key$1,
2413 keys: keys$1,
2414 dropInstance: dropInstance$1
2415};
2416
2417function isLocalStorageValid() {
2418 try {
2419 return typeof localStorage !== 'undefined' && 'setItem' in localStorage &&
2420 // in IE8 typeof localStorage.setItem === 'object'
2421 !!localStorage.setItem;
2422 } catch (e) {
2423 return false;
2424 }
2425}
2426
2427function _getKeyPrefix(options, defaultConfig) {
2428 var keyPrefix = options.name + '/';
2429
2430 if (options.storeName !== defaultConfig.storeName) {
2431 keyPrefix += options.storeName + '/';
2432 }
2433 return keyPrefix;
2434}
2435
2436// Check if localStorage throws when saving an item
2437function checkIfLocalStorageThrows() {
2438 var localStorageTestKey = '_localforage_support_test';
2439
2440 try {
2441 localStorage.setItem(localStorageTestKey, true);
2442 localStorage.removeItem(localStorageTestKey);
2443
2444 return false;
2445 } catch (e) {
2446 return true;
2447 }
2448}
2449
2450// Check if localStorage is usable and allows to save an item
2451// This method checks if localStorage is usable in Safari Private Browsing
2452// mode, or in any other case where the available quota for localStorage
2453// is 0 and there wasn't any saved items yet.
2454function _isLocalStorageUsable() {
2455 return !checkIfLocalStorageThrows() || localStorage.length > 0;
2456}
2457
2458// Config the localStorage backend, using options set in the config.
2459function _initStorage$2(options) {
2460 var self = this;
2461 var dbInfo = {};
2462 if (options) {
2463 for (var i in options) {
2464 dbInfo[i] = options[i];
2465 }
2466 }
2467
2468 dbInfo.keyPrefix = _getKeyPrefix(options, self._defaultConfig);
2469
2470 if (!_isLocalStorageUsable()) {
2471 return Promise$1.reject();
2472 }
2473
2474 self._dbInfo = dbInfo;
2475 dbInfo.serializer = localforageSerializer;
2476
2477 return Promise$1.resolve();
2478}
2479
2480// Remove all keys from the datastore, effectively destroying all data in
2481// the app's key/value store!
2482function clear$2(callback) {
2483 var self = this;
2484 var promise = self.ready().then(function () {
2485 var keyPrefix = self._dbInfo.keyPrefix;
2486
2487 for (var i = localStorage.length - 1; i >= 0; i--) {
2488 var key = localStorage.key(i);
2489
2490 if (key.indexOf(keyPrefix) === 0) {
2491 localStorage.removeItem(key);
2492 }
2493 }
2494 });
2495
2496 executeCallback(promise, callback);
2497 return promise;
2498}
2499
2500// Retrieve an item from the store. Unlike the original async_storage
2501// library in Gaia, we don't modify return values at all. If a key's value
2502// is `undefined`, we pass that value to the callback function.
2503function getItem$2(key, callback) {
2504 var self = this;
2505
2506 key = normalizeKey(key);
2507
2508 var promise = self.ready().then(function () {
2509 var dbInfo = self._dbInfo;
2510 var result = localStorage.getItem(dbInfo.keyPrefix + key);
2511
2512 // If a result was found, parse it from the serialized
2513 // string into a JS object. If result isn't truthy, the key
2514 // is likely undefined and we'll pass it straight to the
2515 // callback.
2516 if (result) {
2517 result = dbInfo.serializer.deserialize(result);
2518 }
2519
2520 return result;
2521 });
2522
2523 executeCallback(promise, callback);
2524 return promise;
2525}
2526
2527// Iterate over all items in the store.
2528function iterate$2(iterator, callback) {
2529 var self = this;
2530
2531 var promise = self.ready().then(function () {
2532 var dbInfo = self._dbInfo;
2533 var keyPrefix = dbInfo.keyPrefix;
2534 var keyPrefixLength = keyPrefix.length;
2535 var length = localStorage.length;
2536
2537 // We use a dedicated iterator instead of the `i` variable below
2538 // so other keys we fetch in localStorage aren't counted in
2539 // the `iterationNumber` argument passed to the `iterate()`
2540 // callback.
2541 //
2542 // See: github.com/mozilla/localForage/pull/435#discussion_r38061530
2543 var iterationNumber = 1;
2544
2545 for (var i = 0; i < length; i++) {
2546 var key = localStorage.key(i);
2547 if (key.indexOf(keyPrefix) !== 0) {
2548 continue;
2549 }
2550 var value = localStorage.getItem(key);
2551
2552 // If a result was found, parse it from the serialized
2553 // string into a JS object. If result isn't truthy, the
2554 // key is likely undefined and we'll pass it straight
2555 // to the iterator.
2556 if (value) {
2557 value = dbInfo.serializer.deserialize(value);
2558 }
2559
2560 value = iterator(value, key.substring(keyPrefixLength), iterationNumber++);
2561
2562 if (value !== void 0) {
2563 return value;
2564 }
2565 }
2566 });
2567
2568 executeCallback(promise, callback);
2569 return promise;
2570}
2571
2572// Same as localStorage's key() method, except takes a callback.
2573function key$2(n, callback) {
2574 var self = this;
2575 var promise = self.ready().then(function () {
2576 var dbInfo = self._dbInfo;
2577 var result;
2578 try {
2579 result = localStorage.key(n);
2580 } catch (error) {
2581 result = null;
2582 }
2583
2584 // Remove the prefix from the key, if a key is found.
2585 if (result) {
2586 result = result.substring(dbInfo.keyPrefix.length);
2587 }
2588
2589 return result;
2590 });
2591
2592 executeCallback(promise, callback);
2593 return promise;
2594}
2595
2596function keys$2(callback) {
2597 var self = this;
2598 var promise = self.ready().then(function () {
2599 var dbInfo = self._dbInfo;
2600 var length = localStorage.length;
2601 var keys = [];
2602
2603 for (var i = 0; i < length; i++) {
2604 var itemKey = localStorage.key(i);
2605 if (itemKey.indexOf(dbInfo.keyPrefix) === 0) {
2606 keys.push(itemKey.substring(dbInfo.keyPrefix.length));
2607 }
2608 }
2609
2610 return keys;
2611 });
2612
2613 executeCallback(promise, callback);
2614 return promise;
2615}
2616
2617// Supply the number of keys in the datastore to the callback function.
2618function length$2(callback) {
2619 var self = this;
2620 var promise = self.keys().then(function (keys) {
2621 return keys.length;
2622 });
2623
2624 executeCallback(promise, callback);
2625 return promise;
2626}
2627
2628// Remove an item from the store, nice and simple.
2629function removeItem$2(key, callback) {
2630 var self = this;
2631
2632 key = normalizeKey(key);
2633
2634 var promise = self.ready().then(function () {
2635 var dbInfo = self._dbInfo;
2636 localStorage.removeItem(dbInfo.keyPrefix + key);
2637 });
2638
2639 executeCallback(promise, callback);
2640 return promise;
2641}
2642
2643// Set a key's value and run an optional callback once the value is set.
2644// Unlike Gaia's implementation, the callback function is passed the value,
2645// in case you want to operate on that value only after you're sure it
2646// saved, or something like that.
2647function setItem$2(key, value, callback) {
2648 var self = this;
2649
2650 key = normalizeKey(key);
2651
2652 var promise = self.ready().then(function () {
2653 // Convert undefined values to null.
2654 // https://github.com/mozilla/localForage/pull/42
2655 if (value === undefined) {
2656 value = null;
2657 }
2658
2659 // Save the original value to pass to the callback.
2660 var originalValue = value;
2661
2662 return new Promise$1(function (resolve, reject) {
2663 var dbInfo = self._dbInfo;
2664 dbInfo.serializer.serialize(value, function (value, error) {
2665 if (error) {
2666 reject(error);
2667 } else {
2668 try {
2669 localStorage.setItem(dbInfo.keyPrefix + key, value);
2670 resolve(originalValue);
2671 } catch (e) {
2672 // localStorage capacity exceeded.
2673 // TODO: Make this a specific error/event.
2674 if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
2675 reject(e);
2676 }
2677 reject(e);
2678 }
2679 }
2680 });
2681 });
2682 });
2683
2684 executeCallback(promise, callback);
2685 return promise;
2686}
2687
2688function dropInstance$2(options, callback) {
2689 callback = getCallback.apply(this, arguments);
2690
2691 options = typeof options !== 'function' && options || {};
2692 if (!options.name) {
2693 var currentConfig = this.config();
2694 options.name = options.name || currentConfig.name;
2695 options.storeName = options.storeName || currentConfig.storeName;
2696 }
2697
2698 var self = this;
2699 var promise;
2700 if (!options.name) {
2701 promise = Promise$1.reject('Invalid arguments');
2702 } else {
2703 promise = new Promise$1(function (resolve) {
2704 if (!options.storeName) {
2705 resolve(options.name + '/');
2706 } else {
2707 resolve(_getKeyPrefix(options, self._defaultConfig));
2708 }
2709 }).then(function (keyPrefix) {
2710 for (var i = localStorage.length - 1; i >= 0; i--) {
2711 var key = localStorage.key(i);
2712
2713 if (key.indexOf(keyPrefix) === 0) {
2714 localStorage.removeItem(key);
2715 }
2716 }
2717 });
2718 }
2719
2720 executeCallback(promise, callback);
2721 return promise;
2722}
2723
2724var localStorageWrapper = {
2725 _driver: 'localStorageWrapper',
2726 _initStorage: _initStorage$2,
2727 _support: isLocalStorageValid(),
2728 iterate: iterate$2,
2729 getItem: getItem$2,
2730 setItem: setItem$2,
2731 removeItem: removeItem$2,
2732 clear: clear$2,
2733 length: length$2,
2734 key: key$2,
2735 keys: keys$2,
2736 dropInstance: dropInstance$2
2737};
2738
2739var sameValue = function sameValue(x, y) {
2740 return x === y || typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y);
2741};
2742
2743var includes = function includes(array, searchElement) {
2744 var len = array.length;
2745 var i = 0;
2746 while (i < len) {
2747 if (sameValue(array[i], searchElement)) {
2748 return true;
2749 }
2750 i++;
2751 }
2752
2753 return false;
2754};
2755
2756var isArray = Array.isArray || function (arg) {
2757 return Object.prototype.toString.call(arg) === '[object Array]';
2758};
2759
2760// Drivers are stored here when `defineDriver()` is called.
2761// They are shared across all instances of localForage.
2762var DefinedDrivers = {};
2763
2764var DriverSupport = {};
2765
2766var DefaultDrivers = {
2767 INDEXEDDB: asyncStorage,
2768 WEBSQL: webSQLStorage,
2769 LOCALSTORAGE: localStorageWrapper
2770};
2771
2772var DefaultDriverOrder = [DefaultDrivers.INDEXEDDB._driver, DefaultDrivers.WEBSQL._driver, DefaultDrivers.LOCALSTORAGE._driver];
2773
2774var OptionalDriverMethods = ['dropInstance'];
2775
2776var LibraryMethods = ['clear', 'getItem', 'iterate', 'key', 'keys', 'length', 'removeItem', 'setItem'].concat(OptionalDriverMethods);
2777
2778var DefaultConfig = {
2779 description: '',
2780 driver: DefaultDriverOrder.slice(),
2781 name: 'localforage',
2782 // Default DB size is _JUST UNDER_ 5MB, as it's the highest size
2783 // we can use without a prompt.
2784 size: 4980736,
2785 storeName: 'keyvaluepairs',
2786 version: 1.0
2787};
2788
2789function callWhenReady(localForageInstance, libraryMethod) {
2790 localForageInstance[libraryMethod] = function () {
2791 var _args = arguments;
2792 return localForageInstance.ready().then(function () {
2793 return localForageInstance[libraryMethod].apply(localForageInstance, _args);
2794 });
2795 };
2796}
2797
2798function extend() {
2799 for (var i = 1; i < arguments.length; i++) {
2800 var arg = arguments[i];
2801
2802 if (arg) {
2803 for (var _key in arg) {
2804 if (arg.hasOwnProperty(_key)) {
2805 if (isArray(arg[_key])) {
2806 arguments[0][_key] = arg[_key].slice();
2807 } else {
2808 arguments[0][_key] = arg[_key];
2809 }
2810 }
2811 }
2812 }
2813 }
2814
2815 return arguments[0];
2816}
2817
2818var LocalForage = function () {
2819 function LocalForage(options) {
2820 _classCallCheck(this, LocalForage);
2821
2822 for (var driverTypeKey in DefaultDrivers) {
2823 if (DefaultDrivers.hasOwnProperty(driverTypeKey)) {
2824 var driver = DefaultDrivers[driverTypeKey];
2825 var driverName = driver._driver;
2826 this[driverTypeKey] = driverName;
2827
2828 if (!DefinedDrivers[driverName]) {
2829 // we don't need to wait for the promise,
2830 // since the default drivers can be defined
2831 // in a blocking manner
2832 this.defineDriver(driver);
2833 }
2834 }
2835 }
2836
2837 this._defaultConfig = extend({}, DefaultConfig);
2838 this._config = extend({}, this._defaultConfig, options);
2839 this._driverSet = null;
2840 this._initDriver = null;
2841 this._ready = false;
2842 this._dbInfo = null;
2843
2844 this._wrapLibraryMethodsWithReady();
2845 this.setDriver(this._config.driver)["catch"](function () {});
2846 }
2847
2848 // Set any config values for localForage; can be called anytime before
2849 // the first API call (e.g. `getItem`, `setItem`).
2850 // We loop through options so we don't overwrite existing config
2851 // values.
2852
2853
2854 LocalForage.prototype.config = function config(options) {
2855 // If the options argument is an object, we use it to set values.
2856 // Otherwise, we return either a specified config value or all
2857 // config values.
2858 if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {
2859 // If localforage is ready and fully initialized, we can't set
2860 // any new configuration values. Instead, we return an error.
2861 if (this._ready) {
2862 return new Error("Can't call config() after localforage " + 'has been used.');
2863 }
2864
2865 for (var i in options) {
2866 if (i === 'storeName') {
2867 options[i] = options[i].replace(/\W/g, '_');
2868 }
2869
2870 if (i === 'version' && typeof options[i] !== 'number') {
2871 return new Error('Database version must be a number.');
2872 }
2873
2874 this._config[i] = options[i];
2875 }
2876
2877 // after all config options are set and
2878 // the driver option is used, try setting it
2879 if ('driver' in options && options.driver) {
2880 return this.setDriver(this._config.driver);
2881 }
2882
2883 return true;
2884 } else if (typeof options === 'string') {
2885 return this._config[options];
2886 } else {
2887 return this._config;
2888 }
2889 };
2890
2891 // Used to define a custom driver, shared across all instances of
2892 // localForage.
2893
2894
2895 LocalForage.prototype.defineDriver = function defineDriver(driverObject, callback, errorCallback) {
2896 var promise = new Promise$1(function (resolve, reject) {
2897 try {
2898 var driverName = driverObject._driver;
2899 var complianceError = new Error('Custom driver not compliant; see ' + 'https://mozilla.github.io/localForage/#definedriver');
2900
2901 // A driver name should be defined and not overlap with the
2902 // library-defined, default drivers.
2903 if (!driverObject._driver) {
2904 reject(complianceError);
2905 return;
2906 }
2907
2908 var driverMethods = LibraryMethods.concat('_initStorage');
2909 for (var i = 0, len = driverMethods.length; i < len; i++) {
2910 var driverMethodName = driverMethods[i];
2911
2912 // when the property is there,
2913 // it should be a method even when optional
2914 var isRequired = !includes(OptionalDriverMethods, driverMethodName);
2915 if ((isRequired || driverObject[driverMethodName]) && typeof driverObject[driverMethodName] !== 'function') {
2916 reject(complianceError);
2917 return;
2918 }
2919 }
2920
2921 var configureMissingMethods = function configureMissingMethods() {
2922 var methodNotImplementedFactory = function methodNotImplementedFactory(methodName) {
2923 return function () {
2924 var error = new Error('Method ' + methodName + ' is not implemented by the current driver');
2925 var promise = Promise$1.reject(error);
2926 executeCallback(promise, arguments[arguments.length - 1]);
2927 return promise;
2928 };
2929 };
2930
2931 for (var _i = 0, _len = OptionalDriverMethods.length; _i < _len; _i++) {
2932 var optionalDriverMethod = OptionalDriverMethods[_i];
2933 if (!driverObject[optionalDriverMethod]) {
2934 driverObject[optionalDriverMethod] = methodNotImplementedFactory(optionalDriverMethod);
2935 }
2936 }
2937 };
2938
2939 configureMissingMethods();
2940
2941 var setDriverSupport = function setDriverSupport(support) {
2942 if (DefinedDrivers[driverName]) {
2943 console.info('Redefining LocalForage driver: ' + driverName);
2944 }
2945 DefinedDrivers[driverName] = driverObject;
2946 DriverSupport[driverName] = support;
2947 // don't use a then, so that we can define
2948 // drivers that have simple _support methods
2949 // in a blocking manner
2950 resolve();
2951 };
2952
2953 if ('_support' in driverObject) {
2954 if (driverObject._support && typeof driverObject._support === 'function') {
2955 driverObject._support().then(setDriverSupport, reject);
2956 } else {
2957 setDriverSupport(!!driverObject._support);
2958 }
2959 } else {
2960 setDriverSupport(true);
2961 }
2962 } catch (e) {
2963 reject(e);
2964 }
2965 });
2966
2967 executeTwoCallbacks(promise, callback, errorCallback);
2968 return promise;
2969 };
2970
2971 LocalForage.prototype.driver = function driver() {
2972 return this._driver || null;
2973 };
2974
2975 LocalForage.prototype.getDriver = function getDriver(driverName, callback, errorCallback) {
2976 var getDriverPromise = DefinedDrivers[driverName] ? Promise$1.resolve(DefinedDrivers[driverName]) : Promise$1.reject(new Error('Driver not found.'));
2977
2978 executeTwoCallbacks(getDriverPromise, callback, errorCallback);
2979 return getDriverPromise;
2980 };
2981
2982 LocalForage.prototype.getSerializer = function getSerializer(callback) {
2983 var serializerPromise = Promise$1.resolve(localforageSerializer);
2984 executeTwoCallbacks(serializerPromise, callback);
2985 return serializerPromise;
2986 };
2987
2988 LocalForage.prototype.ready = function ready(callback) {
2989 var self = this;
2990
2991 var promise = self._driverSet.then(function () {
2992 if (self._ready === null) {
2993 self._ready = self._initDriver();
2994 }
2995
2996 return self._ready;
2997 });
2998
2999 executeTwoCallbacks(promise, callback, callback);
3000 return promise;
3001 };
3002
3003 LocalForage.prototype.setDriver = function setDriver(drivers, callback, errorCallback) {
3004 var self = this;
3005
3006 if (!isArray(drivers)) {
3007 drivers = [drivers];
3008 }
3009
3010 var supportedDrivers = this._getSupportedDrivers(drivers);
3011
3012 function setDriverToConfig() {
3013 self._config.driver = self.driver();
3014 }
3015
3016 function extendSelfWithDriver(driver) {
3017 self._extend(driver);
3018 setDriverToConfig();
3019
3020 self._ready = self._initStorage(self._config);
3021 return self._ready;
3022 }
3023
3024 function initDriver(supportedDrivers) {
3025 return function () {
3026 var currentDriverIndex = 0;
3027
3028 function driverPromiseLoop() {
3029 while (currentDriverIndex < supportedDrivers.length) {
3030 var driverName = supportedDrivers[currentDriverIndex];
3031 currentDriverIndex++;
3032
3033 self._dbInfo = null;
3034 self._ready = null;
3035
3036 return self.getDriver(driverName).then(extendSelfWithDriver)["catch"](driverPromiseLoop);
3037 }
3038
3039 setDriverToConfig();
3040 var error = new Error('No available storage method found.');
3041 self._driverSet = Promise$1.reject(error);
3042 return self._driverSet;
3043 }
3044
3045 return driverPromiseLoop();
3046 };
3047 }
3048
3049 // There might be a driver initialization in progress
3050 // so wait for it to finish in order to avoid a possible
3051 // race condition to set _dbInfo
3052 var oldDriverSetDone = this._driverSet !== null ? this._driverSet["catch"](function () {
3053 return Promise$1.resolve();
3054 }) : Promise$1.resolve();
3055
3056 this._driverSet = oldDriverSetDone.then(function () {
3057 var driverName = supportedDrivers[0];
3058 self._dbInfo = null;
3059 self._ready = null;
3060
3061 return self.getDriver(driverName).then(function (driver) {
3062 self._driver = driver._driver;
3063 setDriverToConfig();
3064 self._wrapLibraryMethodsWithReady();
3065 self._initDriver = initDriver(supportedDrivers);
3066 });
3067 })["catch"](function () {
3068 setDriverToConfig();
3069 var error = new Error('No available storage method found.');
3070 self._driverSet = Promise$1.reject(error);
3071 return self._driverSet;
3072 });
3073
3074 executeTwoCallbacks(this._driverSet, callback, errorCallback);
3075 return this._driverSet;
3076 };
3077
3078 LocalForage.prototype.supports = function supports(driverName) {
3079 return !!DriverSupport[driverName];
3080 };
3081
3082 LocalForage.prototype._extend = function _extend(libraryMethodsAndProperties) {
3083 extend(this, libraryMethodsAndProperties);
3084 };
3085
3086 LocalForage.prototype._getSupportedDrivers = function _getSupportedDrivers(drivers) {
3087 var supportedDrivers = [];
3088 for (var i = 0, len = drivers.length; i < len; i++) {
3089 var driverName = drivers[i];
3090 if (this.supports(driverName)) {
3091 supportedDrivers.push(driverName);
3092 }
3093 }
3094 return supportedDrivers;
3095 };
3096
3097 LocalForage.prototype._wrapLibraryMethodsWithReady = function _wrapLibraryMethodsWithReady() {
3098 // Add a stub for each driver API method that delays the call to the
3099 // corresponding driver method until localForage is ready. These stubs
3100 // will be replaced by the driver methods as soon as the driver is
3101 // loaded, so there is no performance impact.
3102 for (var i = 0, len = LibraryMethods.length; i < len; i++) {
3103 callWhenReady(this, LibraryMethods[i]);
3104 }
3105 };
3106
3107 LocalForage.prototype.createInstance = function createInstance(options) {
3108 return new LocalForage(options);
3109 };
3110
3111 return LocalForage;
3112}();
3113
3114// The actual localForage object that we expose as a module or via a
3115// global. It's extended by pulling in one of our other libraries.
3116
3117
3118var localforage_js = new LocalForage();
3119
3120module.exports = localforage_js;
3121
3122},{"3":3}]},{},[4])(4)
3123});
3124
3125
3126/***/ })
3127
3128/******/ });
3129/************************************************************************/
3130/******/ // The module cache
3131/******/ var __webpack_module_cache__ = {};
3132/******/
3133/******/ // The require function
3134/******/ function __webpack_require__(moduleId) {
3135/******/ // Check if module is in cache
3136/******/ if(__webpack_module_cache__[moduleId]) {
3137/******/ return __webpack_module_cache__[moduleId].exports;
3138/******/ }
3139/******/ // Create a new module (and put it into the cache)
3140/******/ var module = __webpack_module_cache__[moduleId] = {
3141/******/ // no module.id needed
3142/******/ // no module.loaded needed
3143/******/ exports: {}
3144/******/ };
3145/******/
3146/******/ // Execute the module function
3147/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
3148/******/
3149/******/ // Return the exports of the module
3150/******/ return module.exports;
3151/******/ }
3152/******/
3153/************************************************************************/
3154/******/ /* webpack/runtime/compat get default export */
3155/******/ (() => {
3156/******/ // getDefaultExport function for compatibility with non-harmony modules
3157/******/ __webpack_require__.n = (module) => {
3158/******/ var getter = module && module.__esModule ?
3159/******/ () => module['default'] :
3160/******/ () => module;
3161/******/ __webpack_require__.d(getter, { a: getter });
3162/******/ return getter;
3163/******/ };
3164/******/ })();
3165/******/
3166/******/ /* webpack/runtime/define property getters */
3167/******/ (() => {
3168/******/ // define getter functions for harmony exports
3169/******/ __webpack_require__.d = (exports, definition) => {
3170/******/ for(var key in definition) {
3171/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
3172/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
3173/******/ }
3174/******/ }
3175/******/ };
3176/******/ })();
3177/******/
3178/******/ /* webpack/runtime/global */
3179/******/ (() => {
3180/******/ __webpack_require__.g = (function() {
3181/******/ if (typeof globalThis === 'object') return globalThis;
3182/******/ try {
3183/******/ return this || new Function('return this')();
3184/******/ } catch (e) {
3185/******/ if (typeof window === 'object') return window;
3186/******/ }
3187/******/ })();
3188/******/ })();
3189/******/
3190/******/ /* webpack/runtime/hasOwnProperty shorthand */
3191/******/ (() => {
3192/******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
3193/******/ })();
3194/******/
3195/************************************************************************/
3196(() => {
3197"use strict";
3198/* harmony import */ var localforage__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(483);
3199/* harmony import */ var localforage__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(localforage__WEBPACK_IMPORTED_MODULE_0__);
3200/* harmony import */ var localforage_startswith__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(900);
3201/* harmony import */ var localforage_startswith__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(localforage_startswith__WEBPACK_IMPORTED_MODULE_1__);
3202;
3203
3204(0,localforage_startswith__WEBPACK_IMPORTED_MODULE_1__.extendPrototype)((localforage__WEBPACK_IMPORTED_MODULE_0___default()));
3205
3206class WebpackTest {
3207 start() {
3208 localForage.setItem('test', 'value').then(() => {
3209 localForage.keysStartingWith('t').then((results) => {
3210 console.log(results);
3211 });
3212 });
3213 }
3214
3215 stop() {}
3216}
3217
3218/* unused harmony default export */ var __WEBPACK_DEFAULT_EXPORT__ = ((/* unused pure expression or super */ null && (WebpackTest)));
3219})();
3220
3221/******/ })()
3222;