summaryrefslogtreecommitdiff
path: root/www/lib/localforage/src/utils
diff options
context:
space:
mode:
authorPliable Pixels <pliablepixels@gmail.com>2017-09-21 12:49:18 -0400
committerPliable Pixels <pliablepixels@gmail.com>2017-09-21 12:49:18 -0400
commitb28028ac4082842143b0f528d6bc539da6ccb419 (patch)
tree1e26ea969a781ed8e323fca4e3c76345113fc694 /www/lib/localforage/src/utils
parent676270d21beed31d767a06c89522198c77d5d865 (diff)
mega changes, including updates and X
Diffstat (limited to 'www/lib/localforage/src/utils')
-rw-r--r--www/lib/localforage/src/utils/createBlob.js29
-rw-r--r--www/lib/localforage/src/utils/executeCallback.js11
-rw-r--r--www/lib/localforage/src/utils/executeTwoCallbacks.js11
-rw-r--r--www/lib/localforage/src/utils/idb.js21
-rw-r--r--www/lib/localforage/src/utils/isIndexedDBValid.js37
-rw-r--r--www/lib/localforage/src/utils/isLocalStorageValid.js11
-rw-r--r--www/lib/localforage/src/utils/isWebSQLValid.js5
-rw-r--r--www/lib/localforage/src/utils/promise.js6
-rw-r--r--www/lib/localforage/src/utils/serializer.js233
9 files changed, 364 insertions, 0 deletions
diff --git a/www/lib/localforage/src/utils/createBlob.js b/www/lib/localforage/src/utils/createBlob.js
new file mode 100644
index 00000000..4d698551
--- /dev/null
+++ b/www/lib/localforage/src/utils/createBlob.js
@@ -0,0 +1,29 @@
+// Abstracts constructing a Blob object, so it also works in older
+// browsers that don't support the native Blob constructor. (i.e.
+// old QtWebKit versions, at least).
+// Abstracts constructing a Blob object, so it also works in older
+// browsers that don't support the native Blob constructor. (i.e.
+// old QtWebKit versions, at least).
+function createBlob(parts, properties) {
+ /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */
+ parts = parts || [];
+ properties = properties || {};
+ try {
+ return new Blob(parts, properties);
+ } catch (e) {
+ if (e.name !== 'TypeError') {
+ throw e;
+ }
+ var Builder = typeof BlobBuilder !== 'undefined' ? BlobBuilder :
+ typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder :
+ typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder :
+ WebKitBlobBuilder;
+ var builder = new Builder();
+ for (var i = 0; i < parts.length; i += 1) {
+ builder.append(parts[i]);
+ }
+ return builder.getBlob(properties.type);
+ }
+}
+
+export default createBlob;
diff --git a/www/lib/localforage/src/utils/executeCallback.js b/www/lib/localforage/src/utils/executeCallback.js
new file mode 100644
index 00000000..c6982d4a
--- /dev/null
+++ b/www/lib/localforage/src/utils/executeCallback.js
@@ -0,0 +1,11 @@
+function executeCallback(promise, callback) {
+ if (callback) {
+ promise.then(function(result) {
+ callback(null, result);
+ }, function(error) {
+ callback(error);
+ });
+ }
+}
+
+export default executeCallback;
diff --git a/www/lib/localforage/src/utils/executeTwoCallbacks.js b/www/lib/localforage/src/utils/executeTwoCallbacks.js
new file mode 100644
index 00000000..f98c7585
--- /dev/null
+++ b/www/lib/localforage/src/utils/executeTwoCallbacks.js
@@ -0,0 +1,11 @@
+function executeTwoCallbacks(promise, callback, errorCallback) {
+ if (typeof callback === 'function') {
+ promise.then(callback);
+ }
+
+ if (typeof errorCallback === 'function') {
+ promise.catch(errorCallback);
+ }
+}
+
+export default executeTwoCallbacks;
diff --git a/www/lib/localforage/src/utils/idb.js b/www/lib/localforage/src/utils/idb.js
new file mode 100644
index 00000000..47541f6a
--- /dev/null
+++ b/www/lib/localforage/src/utils/idb.js
@@ -0,0 +1,21 @@
+function getIDB() {
+ /* global indexedDB,webkitIndexedDB,mozIndexedDB,OIndexedDB,msIndexedDB */
+ if (typeof indexedDB !== 'undefined') {
+ return indexedDB;
+ }
+ if (typeof webkitIndexedDB !== 'undefined') {
+ return webkitIndexedDB;
+ }
+ if (typeof mozIndexedDB !== 'undefined') {
+ return mozIndexedDB;
+ }
+ if (typeof OIndexedDB !== 'undefined') {
+ return OIndexedDB;
+ }
+ if (typeof msIndexedDB !== 'undefined') {
+ return msIndexedDB;
+ }
+}
+
+var idb = getIDB();
+export default idb;
diff --git a/www/lib/localforage/src/utils/isIndexedDBValid.js b/www/lib/localforage/src/utils/isIndexedDBValid.js
new file mode 100644
index 00000000..aa14b6d8
--- /dev/null
+++ b/www/lib/localforage/src/utils/isIndexedDBValid.js
@@ -0,0 +1,37 @@
+import idb from './idb';
+
+function isIndexedDBValid() {
+ try {
+ // Initialize IndexedDB; fall back to vendor-prefixed versions
+ // if needed.
+ if (!idb) {
+ return false;
+ }
+ // We mimic PouchDB here; just UA test for Safari (which, as of
+ // iOS 8/Yosemite, doesn't properly support IndexedDB).
+ // IndexedDB support is broken and different from Blink's.
+ // This is faster than the test case (and it's sync), so we just
+ // do this. *SIGH*
+ // http://bl.ocks.org/nolanlawson/raw/c83e9039edf2278047e9/
+ //
+ // We test for openDatabase because IE Mobile identifies itself
+ // as Safari. Oh the lulz...
+ if (typeof openDatabase !== 'undefined' && typeof navigator !== 'undefined' &&
+ navigator.userAgent &&
+ /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent)) {
+ return false;
+ }
+
+ return idb &&
+ typeof idb.open === 'function' &&
+ // Some Samsung/HTC Android 4.0-4.3 devices
+ // have older IndexedDB specs; if this isn't available
+ // their IndexedDB is too old for us to use.
+ // (Replaces the onupgradeneeded test.)
+ typeof IDBKeyRange !== 'undefined';
+ } catch (e) {
+ return false;
+ }
+}
+
+export default isIndexedDBValid;
diff --git a/www/lib/localforage/src/utils/isLocalStorageValid.js b/www/lib/localforage/src/utils/isLocalStorageValid.js
new file mode 100644
index 00000000..0c7c1245
--- /dev/null
+++ b/www/lib/localforage/src/utils/isLocalStorageValid.js
@@ -0,0 +1,11 @@
+function isLocalStorageValid() {
+ try {
+ return typeof localStorage !== 'undefined' &&
+ ('setItem' in localStorage) &&
+ localStorage.setItem;
+ } catch (e) {
+ return false;
+ }
+}
+
+export default isLocalStorageValid;
diff --git a/www/lib/localforage/src/utils/isWebSQLValid.js b/www/lib/localforage/src/utils/isWebSQLValid.js
new file mode 100644
index 00000000..1a4386ac
--- /dev/null
+++ b/www/lib/localforage/src/utils/isWebSQLValid.js
@@ -0,0 +1,5 @@
+function isWebSQLValid() {
+ return typeof openDatabase === 'function';
+}
+
+export default isWebSQLValid;
diff --git a/www/lib/localforage/src/utils/promise.js b/www/lib/localforage/src/utils/promise.js
new file mode 100644
index 00000000..177a10d0
--- /dev/null
+++ b/www/lib/localforage/src/utils/promise.js
@@ -0,0 +1,6 @@
+// This is CommonJS because lie is an external dependency, so Rollup
+// can just ignore it.
+if (typeof Promise === 'undefined' && typeof require !== 'undefined') {
+ require('lie/polyfill');
+}
+export default Promise;
diff --git a/www/lib/localforage/src/utils/serializer.js b/www/lib/localforage/src/utils/serializer.js
new file mode 100644
index 00000000..08e5fc8f
--- /dev/null
+++ b/www/lib/localforage/src/utils/serializer.js
@@ -0,0 +1,233 @@
+import createBlob from './createBlob';
+
+// Sadly, the best way to save binary data in WebSQL/localStorage is serializing
+// it to Base64, so this is how we store it to prevent very strange errors with less
+// verbose ways of binary <-> string data storage.
+var BASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+
+var BLOB_TYPE_PREFIX = '~~local_forage_type~';
+var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
+
+var SERIALIZED_MARKER = '__lfsc__:';
+var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;
+
+// OMG the serializations!
+var TYPE_ARRAYBUFFER = 'arbf';
+var TYPE_BLOB = 'blob';
+var TYPE_INT8ARRAY = 'si08';
+var TYPE_UINT8ARRAY = 'ui08';
+var TYPE_UINT8CLAMPEDARRAY = 'uic8';
+var TYPE_INT16ARRAY = 'si16';
+var TYPE_INT32ARRAY = 'si32';
+var TYPE_UINT16ARRAY = 'ur16';
+var TYPE_UINT32ARRAY = 'ui32';
+var TYPE_FLOAT32ARRAY = 'fl32';
+var TYPE_FLOAT64ARRAY = 'fl64';
+var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH +
+ TYPE_ARRAYBUFFER.length;
+
+function stringToBuffer(serializedString) {
+ // Fill the string into a ArrayBuffer.
+ var bufferLength = serializedString.length * 0.75;
+ var len = serializedString.length;
+ var i;
+ var p = 0;
+ var encoded1, encoded2, encoded3, encoded4;
+
+ if (serializedString[serializedString.length - 1] === '=') {
+ bufferLength--;
+ if (serializedString[serializedString.length - 2] === '=') {
+ bufferLength--;
+ }
+ }
+
+ var buffer = new ArrayBuffer(bufferLength);
+ var bytes = new Uint8Array(buffer);
+
+ for (i = 0; i < len; i += 4) {
+ encoded1 = BASE_CHARS.indexOf(serializedString[i]);
+ encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);
+ encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);
+ encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);
+
+ /*jslint bitwise: true */
+ bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
+ bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
+ bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
+ }
+ return buffer;
+}
+
+// Converts a buffer to a string to store, serialized, in the backend
+// storage library.
+function bufferToString(buffer) {
+ // base64-arraybuffer
+ var bytes = new Uint8Array(buffer);
+ var base64String = '';
+ var i;
+
+ for (i = 0; i < bytes.length; i += 3) {
+ /*jslint bitwise: true */
+ base64String += BASE_CHARS[bytes[i] >> 2];
+ base64String += BASE_CHARS[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
+ base64String += BASE_CHARS[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
+ base64String += BASE_CHARS[bytes[i + 2] & 63];
+ }
+
+ if ((bytes.length % 3) === 2) {
+ base64String = base64String.substring(0, base64String.length - 1) + '=';
+ } else if (bytes.length % 3 === 1) {
+ base64String = base64String.substring(0, base64String.length - 2) + '==';
+ }
+
+ return base64String;
+}
+
+// Serialize a value, afterwards executing a callback (which usually
+// instructs the `setItem()` callback/promise to be executed). This is how
+// we store binary data with localStorage.
+function serialize(value, callback) {
+ var valueString = '';
+ if (value) {
+ valueString = value.toString();
+ }
+
+ // Cannot use `value instanceof ArrayBuffer` or such here, as these
+ // checks fail when running the tests using casper.js...
+ //
+ // TODO: See why those tests fail and use a better solution.
+ if (value && (value.toString() === '[object ArrayBuffer]' ||
+ value.buffer &&
+ value.buffer.toString() === '[object ArrayBuffer]')) {
+ // Convert binary arrays to a string and prefix the string with
+ // a special marker.
+ var buffer;
+ var marker = SERIALIZED_MARKER;
+
+ if (value instanceof ArrayBuffer) {
+ buffer = value;
+ marker += TYPE_ARRAYBUFFER;
+ } else {
+ buffer = value.buffer;
+
+ if (valueString === '[object Int8Array]') {
+ marker += TYPE_INT8ARRAY;
+ } else if (valueString === '[object Uint8Array]') {
+ marker += TYPE_UINT8ARRAY;
+ } else if (valueString === '[object Uint8ClampedArray]') {
+ marker += TYPE_UINT8CLAMPEDARRAY;
+ } else if (valueString === '[object Int16Array]') {
+ marker += TYPE_INT16ARRAY;
+ } else if (valueString === '[object Uint16Array]') {
+ marker += TYPE_UINT16ARRAY;
+ } else if (valueString === '[object Int32Array]') {
+ marker += TYPE_INT32ARRAY;
+ } else if (valueString === '[object Uint32Array]') {
+ marker += TYPE_UINT32ARRAY;
+ } else if (valueString === '[object Float32Array]') {
+ marker += TYPE_FLOAT32ARRAY;
+ } else if (valueString === '[object Float64Array]') {
+ marker += TYPE_FLOAT64ARRAY;
+ } else {
+ callback(new Error('Failed to get type for BinaryArray'));
+ }
+ }
+
+ callback(marker + bufferToString(buffer));
+ } else if (valueString === '[object Blob]') {
+ // Conver the blob to a binaryArray and then to a string.
+ var fileReader = new FileReader();
+
+ fileReader.onload = function() {
+ // Backwards-compatible prefix for the blob type.
+ var str = BLOB_TYPE_PREFIX + value.type + '~' +
+ bufferToString(this.result);
+
+ callback(SERIALIZED_MARKER + TYPE_BLOB + str);
+ };
+
+ fileReader.readAsArrayBuffer(value);
+ } else {
+ try {
+ callback(JSON.stringify(value));
+ } catch (e) {
+ console.error("Couldn't convert value into a JSON string: ",
+ value);
+
+ callback(null, e);
+ }
+ }
+}
+
+// Deserialize data we've inserted into a value column/field. We place
+// special markers into our strings to mark them as encoded; this isn't
+// as nice as a meta field, but it's the only sane thing we can do whilst
+// keeping localStorage support intact.
+//
+// Oftentimes this will just deserialize JSON content, but if we have a
+// special marker (SERIALIZED_MARKER, defined above), we will extract
+// some kind of arraybuffer/binary data/typed array out of the string.
+function deserialize(value) {
+ // If we haven't marked this string as being specially serialized (i.e.
+ // something other than serialized JSON), we can just return it and be
+ // done with it.
+ if (value.substring(0,
+ SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
+ return JSON.parse(value);
+ }
+
+ // The following code deals with deserializing some kind of Blob or
+ // TypedArray. First we separate out the type of data we're dealing
+ // with from the data itself.
+ var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
+ var type = value.substring(SERIALIZED_MARKER_LENGTH,
+ TYPE_SERIALIZED_MARKER_LENGTH);
+
+ var blobType;
+ // Backwards-compatible blob type serialization strategy.
+ // DBs created with older versions of localForage will simply not have the blob type.
+ if (type === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
+ var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
+ blobType = matcher[1];
+ serializedString = serializedString.substring(matcher[0].length);
+ }
+ var buffer = stringToBuffer(serializedString);
+
+ // Return the right type based on the code/type set during
+ // serialization.
+ switch (type) {
+ case TYPE_ARRAYBUFFER:
+ return buffer;
+ case TYPE_BLOB:
+ return createBlob([buffer], {type: blobType});
+ case TYPE_INT8ARRAY:
+ return new Int8Array(buffer);
+ case TYPE_UINT8ARRAY:
+ return new Uint8Array(buffer);
+ case TYPE_UINT8CLAMPEDARRAY:
+ return new Uint8ClampedArray(buffer);
+ case TYPE_INT16ARRAY:
+ return new Int16Array(buffer);
+ case TYPE_UINT16ARRAY:
+ return new Uint16Array(buffer);
+ case TYPE_INT32ARRAY:
+ return new Int32Array(buffer);
+ case TYPE_UINT32ARRAY:
+ return new Uint32Array(buffer);
+ case TYPE_FLOAT32ARRAY:
+ return new Float32Array(buffer);
+ case TYPE_FLOAT64ARRAY:
+ return new Float64Array(buffer);
+ default:
+ throw new Error('Unkown type: ' + type);
+ }
+}
+
+var localforageSerializer = {
+ serialize: serialize,
+ deserialize: deserialize,
+ stringToBuffer: stringToBuffer,
+ bufferToString: bufferToString
+};
+
+export default localforageSerializer;