123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- (function() {
- 'use strict';
-
- var dummyStorage = {};
-
- // Config the localStorage backend, using options set in the config.
- function _initStorage(options) {
- var self = this;
-
- var dbInfo = {};
- if (options) {
- for (var i in options) {
- dbInfo[i] = options[i];
- }
- }
-
- dummyStorage[dbInfo.name] = dbInfo.db = {};
-
- self._dbInfo = dbInfo;
- return Promise.resolve();
- }
-
- 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 clear(callback) {
- var self = this;
- var promise = new Promise(function(resolve, reject) {
- self.ready().then(function() {
- var db = self._dbInfo.db;
-
- for (var key in db) {
- if (db.hasOwnProperty(key)) {
- delete db[key];
- // db[key] = undefined;
- }
- }
-
- resolve();
- }).catch(reject);
- });
-
- executeCallback(promise, callback);
- return promise;
- }
-
- function getItem(key, callback) {
- var self = this;
-
- // Cast the key to a string, as that's all we can set as a key.
- if (typeof key !== 'string') {
- window.console.warn(key +
- ' used as a key, but it is not a string.');
- key = String(key);
- }
-
- var promise = new Promise(function(resolve, reject) {
- self.ready().then(function() {
- try {
- var db = self._dbInfo.db;
- var result = db[key];
-
- if (result) {
- result = _deserialize(result);
- }
-
- resolve(result);
- } catch (e) {
- reject(e);
- }
- }).catch(reject);
- });
-
- executeCallback(promise, callback);
- return promise;
- }
-
- function iterate(callback) {
- var self = this;
-
- var promise = new Promise(function(resolve, reject) {
- self.ready().then(function() {
- try {
- var db = self._dbInfo.db;
-
- for (var key in db) {
- var result = db[key];
-
- if (result) {
- result = _deserialize(result);
- }
-
- callback(result, key);
- }
-
- resolve();
- } catch (e) {
- reject(e);
- }
- }).catch(reject);
- });
-
- executeCallback(promise, callback);
- return promise;
- }
-
- function key(n, callback) {
- var self = this;
- var promise = new Promise(function(resolve, reject) {
- self.ready().then(function() {
- var db = self._dbInfo.db;
- var result = null;
- var index = 0;
-
- for (var key in db) {
- if (db.hasOwnProperty(key) && db[key] !== undefined) {
- if (n === index) {
- result = key;
- break;
- }
- index++;
- }
- }
-
- resolve(result);
- }).catch(reject);
- });
-
- executeCallback(promise, callback);
- return promise;
- }
-
- function keys(callback) {
- var self = this;
- var promise = new Promise(function(resolve, reject) {
- self.ready().then(function() {
- var db = self._dbInfo.db;
- var keys = [];
-
- for (var key in db) {
- if (db.hasOwnProperty(key)) {
- keys.push(key);
- }
- }
-
- resolve(keys);
- }).catch(reject);
- });
-
- executeCallback(promise, callback);
- return promise;
- }
-
- function length(callback) {
- var self = this;
- var promise = new Promise(function(resolve, reject) {
- self.keys().then(function(keys) {
- resolve(keys.length);
- }).catch(reject);
- });
-
- executeCallback(promise, callback);
- return promise;
- }
-
- function removeItem(key, callback) {
- var self = this;
-
- // Cast the key to a string, as that's all we can set as a key.
- if (typeof key !== 'string') {
- window.console.warn(key +
- ' used as a key, but it is not a string.');
- key = String(key);
- }
-
- var promise = new Promise(function(resolve, reject) {
- self.ready().then(function() {
- var db = self._dbInfo.db;
- if (db.hasOwnProperty(key)) {
- delete db[key];
- // db[key] = undefined;
- }
-
- resolve();
- }).catch(reject);
- });
-
- executeCallback(promise, callback);
- return promise;
- }
-
- function setItem(key, value, callback) {
- var self = this;
-
- // Cast the key to a string, as that's all we can set as a key.
- if (typeof key !== 'string') {
- window.console.warn(key +
- ' used as a key, but it is not a string.');
- key = String(key);
- }
-
- var promise = new Promise(function(resolve, reject) {
- self.ready().then(function() {
- // Convert undefined values to null.
- // https://github.com/mozilla/localForage/pull/42
- if (value === undefined) {
- value = null;
- }
-
- // Save the original value to pass to the callback.
- var originalValue = value;
-
- _serialize(value, function(value, error) {
- if (error) {
- reject(error);
- } else {
- try {
- var db = self._dbInfo.db;
- db[key] = value;
- resolve(originalValue);
- } catch (e) {
- reject(e);
- }
- }
- });
- }).catch(reject);
- });
-
- executeCallback(promise, callback);
- return promise;
- }
-
- // _serialize just like in 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() {
- var str = _bufferToString(this.result);
-
- callback(SERIALIZED_MARKER + TYPE_BLOB + str);
- };
-
- fileReader.readAsArrayBuffer(value);
- } else {
- try {
- callback(JSON.stringify(value));
- } catch (e) {
- window.console.error("Couldn't convert value into a JSON " +
- 'string: ', value);
-
- callback(e);
- }
- }
- }
-
- // _deserialize just like in LocalStorage
- 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);
-
- // Fill the string into a ArrayBuffer.
- // 2 bytes for each char.
- var buffer = new ArrayBuffer(serializedString.length * 2);
- var bufferView = new Uint16Array(buffer);
- for (var i = serializedString.length - 1; i >= 0; i--) {
- bufferView[i] = serializedString.charCodeAt(i);
- }
-
- // Return the right type based on the code/type set during
- // serialization.
- switch (type) {
- case TYPE_ARRAYBUFFER:
- return buffer;
- case TYPE_BLOB:
- return new Blob([buffer]);
- 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);
- }
- }
-
- // _bufferToString just like in LocalStorage
- function _bufferToString(buffer) {
- var str = '';
- var uint16Array = new Uint16Array(buffer);
-
- try {
- str = String.fromCharCode.apply(null, uint16Array);
- } catch (e) {
- // This is a fallback implementation in case the first one does
- // not work. This is required to get the phantomjs passing...
- for (var i = 0; i < uint16Array.length; i++) {
- str += String.fromCharCode(uint16Array[i]);
- }
- }
-
- return str;
- }
-
- function executeCallback(promise, callback) {
- if (callback) {
- promise.then(function(result) {
- callback(null, result);
- }, function(error) {
- callback(error);
- });
- }
- }
-
- var dummyStorageDriver = {
- _driver: 'dummyStorageDriver',
- _initStorage: _initStorage,
- // _supports: function() { return true; }
- iterate: iterate,
- getItem: getItem,
- setItem: setItem,
- removeItem: removeItem,
- clear: clear,
- length: length,
- key: key,
- keys: keys
- };
-
- if (typeof define === 'function' && define.amd) {
- define('dummyStorageDriver', function() {
- return dummyStorageDriver;
- });
- } else if (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined') {
- module.exports = dummyStorageDriver;
- } else {
- this.dummyStorageDriver = dummyStorageDriver;
- }
- }).call(window);
|