1 | (function() {
|
2 | 'use strict';
|
3 |
|
4 | var dummyStorage = {};
|
5 |
|
6 |
|
7 | function _initStorage(options) {
|
8 | var self = this;
|
9 |
|
10 | var dbInfo = {};
|
11 | if (options) {
|
12 | for (var i in options) {
|
13 | dbInfo[i] = options[i];
|
14 | }
|
15 | }
|
16 |
|
17 | dummyStorage[dbInfo.name] = dbInfo.db = {};
|
18 |
|
19 | self._dbInfo = dbInfo;
|
20 | return Promise.resolve();
|
21 | }
|
22 |
|
23 | var SERIALIZED_MARKER = '__lfsc__:';
|
24 | var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;
|
25 |
|
26 |
|
27 | var TYPE_ARRAYBUFFER = 'arbf';
|
28 | var TYPE_BLOB = 'blob';
|
29 | var TYPE_INT8ARRAY = 'si08';
|
30 | var TYPE_UINT8ARRAY = 'ui08';
|
31 | var TYPE_UINT8CLAMPEDARRAY = 'uic8';
|
32 | var TYPE_INT16ARRAY = 'si16';
|
33 | var TYPE_INT32ARRAY = 'si32';
|
34 | var TYPE_UINT16ARRAY = 'ur16';
|
35 | var TYPE_UINT32ARRAY = 'ui32';
|
36 | var TYPE_FLOAT32ARRAY = 'fl32';
|
37 | var TYPE_FLOAT64ARRAY = 'fl64';
|
38 | var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH +
|
39 | TYPE_ARRAYBUFFER.length;
|
40 |
|
41 | function clear(callback) {
|
42 | var self = this;
|
43 | var promise = new Promise(function(resolve, reject) {
|
44 | self.ready().then(function() {
|
45 | var db = self._dbInfo.db;
|
46 |
|
47 | for (var key in db) {
|
48 | if (db.hasOwnProperty(key)) {
|
49 | delete db[key];
|
50 |
|
51 | }
|
52 | }
|
53 |
|
54 | resolve();
|
55 | }).catch(reject);
|
56 | });
|
57 |
|
58 | executeCallback(promise, callback);
|
59 | return promise;
|
60 | }
|
61 |
|
62 | function getItem(key, callback) {
|
63 | var self = this;
|
64 |
|
65 |
|
66 | if (typeof key !== 'string') {
|
67 | window.console.warn(key +
|
68 | ' used as a key, but it is not a string.');
|
69 | key = String(key);
|
70 | }
|
71 |
|
72 | var promise = new Promise(function(resolve, reject) {
|
73 | self.ready().then(function() {
|
74 | try {
|
75 | var db = self._dbInfo.db;
|
76 | var result = db[key];
|
77 |
|
78 | if (result) {
|
79 | result = _deserialize(result);
|
80 | }
|
81 |
|
82 | resolve(result);
|
83 | } catch (e) {
|
84 | reject(e);
|
85 | }
|
86 | }).catch(reject);
|
87 | });
|
88 |
|
89 | executeCallback(promise, callback);
|
90 | return promise;
|
91 | }
|
92 |
|
93 | function iterate(callback) {
|
94 | var self = this;
|
95 |
|
96 | var promise = new Promise(function(resolve, reject) {
|
97 | self.ready().then(function() {
|
98 | try {
|
99 | var db = self._dbInfo.db;
|
100 |
|
101 | for (var key in db) {
|
102 | var result = db[key];
|
103 |
|
104 | if (result) {
|
105 | result = _deserialize(result);
|
106 | }
|
107 |
|
108 | callback(result, key);
|
109 | }
|
110 |
|
111 | resolve();
|
112 | } catch (e) {
|
113 | reject(e);
|
114 | }
|
115 | }).catch(reject);
|
116 | });
|
117 |
|
118 | executeCallback(promise, callback);
|
119 | return promise;
|
120 | }
|
121 |
|
122 | function key(n, callback) {
|
123 | var self = this;
|
124 | var promise = new Promise(function(resolve, reject) {
|
125 | self.ready().then(function() {
|
126 | var db = self._dbInfo.db;
|
127 | var result = null;
|
128 | var index = 0;
|
129 |
|
130 | for (var key in db) {
|
131 | if (db.hasOwnProperty(key) && db[key] !== undefined) {
|
132 | if (n === index) {
|
133 | result = key;
|
134 | break;
|
135 | }
|
136 | index++;
|
137 | }
|
138 | }
|
139 |
|
140 | resolve(result);
|
141 | }).catch(reject);
|
142 | });
|
143 |
|
144 | executeCallback(promise, callback);
|
145 | return promise;
|
146 | }
|
147 |
|
148 | function keys(callback) {
|
149 | var self = this;
|
150 | var promise = new Promise(function(resolve, reject) {
|
151 | self.ready().then(function() {
|
152 | var db = self._dbInfo.db;
|
153 | var keys = [];
|
154 |
|
155 | for (var key in db) {
|
156 | if (db.hasOwnProperty(key)) {
|
157 | keys.push(key);
|
158 | }
|
159 | }
|
160 |
|
161 | resolve(keys);
|
162 | }).catch(reject);
|
163 | });
|
164 |
|
165 | executeCallback(promise, callback);
|
166 | return promise;
|
167 | }
|
168 |
|
169 | function length(callback) {
|
170 | var self = this;
|
171 | var promise = new Promise(function(resolve, reject) {
|
172 | self.keys().then(function(keys) {
|
173 | resolve(keys.length);
|
174 | }).catch(reject);
|
175 | });
|
176 |
|
177 | executeCallback(promise, callback);
|
178 | return promise;
|
179 | }
|
180 |
|
181 | function removeItem(key, callback) {
|
182 | var self = this;
|
183 |
|
184 |
|
185 | if (typeof key !== 'string') {
|
186 | window.console.warn(key +
|
187 | ' used as a key, but it is not a string.');
|
188 | key = String(key);
|
189 | }
|
190 |
|
191 | var promise = new Promise(function(resolve, reject) {
|
192 | self.ready().then(function() {
|
193 | var db = self._dbInfo.db;
|
194 | if (db.hasOwnProperty(key)) {
|
195 | delete db[key];
|
196 |
|
197 | }
|
198 |
|
199 | resolve();
|
200 | }).catch(reject);
|
201 | });
|
202 |
|
203 | executeCallback(promise, callback);
|
204 | return promise;
|
205 | }
|
206 |
|
207 | function setItem(key, value, callback) {
|
208 | var self = this;
|
209 |
|
210 |
|
211 | if (typeof key !== 'string') {
|
212 | window.console.warn(key +
|
213 | ' used as a key, but it is not a string.');
|
214 | key = String(key);
|
215 | }
|
216 |
|
217 | var promise = new Promise(function(resolve, reject) {
|
218 | self.ready().then(function() {
|
219 |
|
220 |
|
221 | if (value === undefined) {
|
222 | value = null;
|
223 | }
|
224 |
|
225 |
|
226 | var originalValue = value;
|
227 |
|
228 | _serialize(value, function(value, error) {
|
229 | if (error) {
|
230 | reject(error);
|
231 | } else {
|
232 | try {
|
233 | var db = self._dbInfo.db;
|
234 | db[key] = value;
|
235 | resolve(originalValue);
|
236 | } catch (e) {
|
237 | reject(e);
|
238 | }
|
239 | }
|
240 | });
|
241 | }).catch(reject);
|
242 | });
|
243 |
|
244 | executeCallback(promise, callback);
|
245 | return promise;
|
246 | }
|
247 |
|
248 |
|
249 | function _serialize(value, callback) {
|
250 | var valueString = '';
|
251 | if (value) {
|
252 | valueString = value.toString();
|
253 | }
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 | if (value && (value.toString() === '[object ArrayBuffer]' ||
|
260 | value.buffer &&
|
261 | value.buffer.toString() === '[object ArrayBuffer]')) {
|
262 |
|
263 |
|
264 | var buffer;
|
265 | var marker = SERIALIZED_MARKER;
|
266 |
|
267 | if (value instanceof ArrayBuffer) {
|
268 | buffer = value;
|
269 | marker += TYPE_ARRAYBUFFER;
|
270 | } else {
|
271 | buffer = value.buffer;
|
272 |
|
273 | if (valueString === '[object Int8Array]') {
|
274 | marker += TYPE_INT8ARRAY;
|
275 | } else if (valueString === '[object Uint8Array]') {
|
276 | marker += TYPE_UINT8ARRAY;
|
277 | } else if (valueString === '[object Uint8ClampedArray]') {
|
278 | marker += TYPE_UINT8CLAMPEDARRAY;
|
279 | } else if (valueString === '[object Int16Array]') {
|
280 | marker += TYPE_INT16ARRAY;
|
281 | } else if (valueString === '[object Uint16Array]') {
|
282 | marker += TYPE_UINT16ARRAY;
|
283 | } else if (valueString === '[object Int32Array]') {
|
284 | marker += TYPE_INT32ARRAY;
|
285 | } else if (valueString === '[object Uint32Array]') {
|
286 | marker += TYPE_UINT32ARRAY;
|
287 | } else if (valueString === '[object Float32Array]') {
|
288 | marker += TYPE_FLOAT32ARRAY;
|
289 | } else if (valueString === '[object Float64Array]') {
|
290 | marker += TYPE_FLOAT64ARRAY;
|
291 | } else {
|
292 | callback(new Error('Failed to get type for BinaryArray'));
|
293 | }
|
294 | }
|
295 |
|
296 | callback(marker + _bufferToString(buffer));
|
297 | } else if (valueString === '[object Blob]') {
|
298 |
|
299 | var fileReader = new FileReader();
|
300 |
|
301 | fileReader.onload = function() {
|
302 | var str = _bufferToString(this.result);
|
303 |
|
304 | callback(SERIALIZED_MARKER + TYPE_BLOB + str);
|
305 | };
|
306 |
|
307 | fileReader.readAsArrayBuffer(value);
|
308 | } else {
|
309 | try {
|
310 | callback(JSON.stringify(value));
|
311 | } catch (e) {
|
312 | window.console.error("Couldn't convert value into a JSON " +
|
313 | 'string: ', value);
|
314 |
|
315 | callback(e);
|
316 | }
|
317 | }
|
318 | }
|
319 |
|
320 |
|
321 | function _deserialize(value) {
|
322 |
|
323 |
|
324 |
|
325 | if (value.substring(0,
|
326 | SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
|
327 | return JSON.parse(value);
|
328 | }
|
329 |
|
330 |
|
331 |
|
332 |
|
333 | var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
|
334 | var type = value.substring(SERIALIZED_MARKER_LENGTH,
|
335 | TYPE_SERIALIZED_MARKER_LENGTH);
|
336 |
|
337 |
|
338 |
|
339 | var buffer = new ArrayBuffer(serializedString.length * 2);
|
340 | var bufferView = new Uint16Array(buffer);
|
341 | for (var i = serializedString.length - 1; i >= 0; i--) {
|
342 | bufferView[i] = serializedString.charCodeAt(i);
|
343 | }
|
344 |
|
345 |
|
346 |
|
347 | switch (type) {
|
348 | case TYPE_ARRAYBUFFER:
|
349 | return buffer;
|
350 | case TYPE_BLOB:
|
351 | return new Blob([buffer]);
|
352 | case TYPE_INT8ARRAY:
|
353 | return new Int8Array(buffer);
|
354 | case TYPE_UINT8ARRAY:
|
355 | return new Uint8Array(buffer);
|
356 | case TYPE_UINT8CLAMPEDARRAY:
|
357 | return new Uint8ClampedArray(buffer);
|
358 | case TYPE_INT16ARRAY:
|
359 | return new Int16Array(buffer);
|
360 | case TYPE_UINT16ARRAY:
|
361 | return new Uint16Array(buffer);
|
362 | case TYPE_INT32ARRAY:
|
363 | return new Int32Array(buffer);
|
364 | case TYPE_UINT32ARRAY:
|
365 | return new Uint32Array(buffer);
|
366 | case TYPE_FLOAT32ARRAY:
|
367 | return new Float32Array(buffer);
|
368 | case TYPE_FLOAT64ARRAY:
|
369 | return new Float64Array(buffer);
|
370 | default:
|
371 | throw new Error('Unkown type: ' + type);
|
372 | }
|
373 | }
|
374 |
|
375 |
|
376 | function _bufferToString(buffer) {
|
377 | var str = '';
|
378 | var uint16Array = new Uint16Array(buffer);
|
379 |
|
380 | try {
|
381 | str = String.fromCharCode.apply(null, uint16Array);
|
382 | } catch (e) {
|
383 |
|
384 |
|
385 | for (var i = 0; i < uint16Array.length; i++) {
|
386 | str += String.fromCharCode(uint16Array[i]);
|
387 | }
|
388 | }
|
389 |
|
390 | return str;
|
391 | }
|
392 |
|
393 | function executeCallback(promise, callback) {
|
394 | if (callback) {
|
395 | promise.then(function(result) {
|
396 | callback(null, result);
|
397 | }, function(error) {
|
398 | callback(error);
|
399 | });
|
400 | }
|
401 | }
|
402 |
|
403 | var dummyStorageDriver = {
|
404 | _driver: 'dummyStorageDriver',
|
405 | _initStorage: _initStorage,
|
406 |
|
407 | iterate: iterate,
|
408 | getItem: getItem,
|
409 | setItem: setItem,
|
410 | removeItem: removeItem,
|
411 | clear: clear,
|
412 | length: length,
|
413 | key: key,
|
414 | keys: keys
|
415 | };
|
416 |
|
417 | if (typeof define === 'function' && define.amd) {
|
418 | define('dummyStorageDriver', function() {
|
419 | return dummyStorageDriver;
|
420 | });
|
421 | } else if (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined') {
|
422 | module.exports = dummyStorageDriver;
|
423 | } else {
|
424 | this.dummyStorageDriver = dummyStorageDriver;
|
425 | }
|
426 | }).call(window);
|