318 lines
9.1 KiB
JavaScript
318 lines
9.1 KiB
JavaScript
// Generated by CoffeeScript 1.10.0
|
|
(function() {
|
|
var JSONStorage, KEY_FOR_EMPTY_STRING, LocalStorage, MetaKey, QUOTA_EXCEEDED_ERR, StorageEvent, _emptyDirectory, _escapeKey, _rm, createMap, events, fs, path, writeSync,
|
|
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
|
hasProp = {}.hasOwnProperty;
|
|
|
|
path = require('path');
|
|
|
|
fs = require('fs');
|
|
|
|
events = require('events');
|
|
|
|
writeSync = require('write-file-atomic').sync;
|
|
|
|
KEY_FOR_EMPTY_STRING = '---.EMPTY_STRING.---';
|
|
|
|
_emptyDirectory = function(target) {
|
|
var i, len, p, ref, results;
|
|
ref = fs.readdirSync(target);
|
|
results = [];
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
p = ref[i];
|
|
results.push(_rm(path.join(target, p)));
|
|
}
|
|
return results;
|
|
};
|
|
|
|
_rm = function(target) {
|
|
if (fs.statSync(target).isDirectory()) {
|
|
_emptyDirectory(target);
|
|
return fs.rmdirSync(target);
|
|
} else {
|
|
return fs.unlinkSync(target);
|
|
}
|
|
};
|
|
|
|
_escapeKey = function(key) {
|
|
var newKey;
|
|
if (key === '') {
|
|
newKey = KEY_FOR_EMPTY_STRING;
|
|
} else {
|
|
newKey = key.toString();
|
|
}
|
|
return newKey;
|
|
};
|
|
|
|
QUOTA_EXCEEDED_ERR = (function(superClass) {
|
|
extend(QUOTA_EXCEEDED_ERR, superClass);
|
|
|
|
function QUOTA_EXCEEDED_ERR(message) {
|
|
this.message = message != null ? message : 'Unknown error.';
|
|
if (Error.captureStackTrace != null) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
}
|
|
this.name = this.constructor.name;
|
|
}
|
|
|
|
QUOTA_EXCEEDED_ERR.prototype.toString = function() {
|
|
return this.name + ": " + this.message;
|
|
};
|
|
|
|
return QUOTA_EXCEEDED_ERR;
|
|
|
|
})(Error);
|
|
|
|
StorageEvent = (function() {
|
|
function StorageEvent(key1, oldValue1, newValue1, url, storageArea) {
|
|
this.key = key1;
|
|
this.oldValue = oldValue1;
|
|
this.newValue = newValue1;
|
|
this.url = url;
|
|
this.storageArea = storageArea != null ? storageArea : 'localStorage';
|
|
}
|
|
|
|
return StorageEvent;
|
|
|
|
})();
|
|
|
|
MetaKey = (function() {
|
|
function MetaKey(key1, index1) {
|
|
this.key = key1;
|
|
this.index = index1;
|
|
if (!(this instanceof MetaKey)) {
|
|
return new MetaKey(this.key, this.index);
|
|
}
|
|
}
|
|
|
|
return MetaKey;
|
|
|
|
})();
|
|
|
|
createMap = function() {
|
|
var Map;
|
|
Map = function() {};
|
|
Map.prototype = Object.create(null);
|
|
return new Map();
|
|
};
|
|
|
|
LocalStorage = (function(superClass) {
|
|
var instanceMap;
|
|
|
|
extend(LocalStorage, superClass);
|
|
|
|
instanceMap = {};
|
|
|
|
function LocalStorage(_location, quota) {
|
|
this._location = _location;
|
|
this.quota = quota != null ? quota : 5 * 1024 * 1024;
|
|
if (!(this instanceof LocalStorage)) {
|
|
return new LocalStorage(this._location, this.quota);
|
|
}
|
|
this._location = path.resolve(this._location);
|
|
if (instanceMap[this._location] != null) {
|
|
return instanceMap[this._location];
|
|
}
|
|
this.length = 0;
|
|
this._bytesInUse = 0;
|
|
this._keys = [];
|
|
this._metaKeyMap = createMap();
|
|
this._eventUrl = "pid:" + process.pid;
|
|
this._init();
|
|
this._QUOTA_EXCEEDED_ERR = QUOTA_EXCEEDED_ERR;
|
|
instanceMap[this._location] = this;
|
|
return instanceMap[this._location];
|
|
}
|
|
|
|
LocalStorage.prototype._init = function() {
|
|
var _MetaKey, _decodedKey, _keys, e, error, error1, i, index, k, len, stat;
|
|
try {
|
|
stat = fs.statSync(this._location);
|
|
if ((stat != null) && !stat.isDirectory()) {
|
|
throw new Error("A file exists at the location '" + this._location + "' when trying to create/open localStorage");
|
|
}
|
|
this._bytesInUse = 0;
|
|
this.length = 0;
|
|
_keys = fs.readdirSync(this._location);
|
|
for (index = i = 0, len = _keys.length; i < len; index = ++i) {
|
|
k = _keys[index];
|
|
_decodedKey = decodeURIComponent(k);
|
|
this._keys.push(_decodedKey);
|
|
_MetaKey = new MetaKey(k, index);
|
|
this._metaKeyMap[_decodedKey] = _MetaKey;
|
|
stat = this._getStat(k);
|
|
if ((stat != null ? stat.size : void 0) != null) {
|
|
_MetaKey.size = stat.size;
|
|
this._bytesInUse += stat.size;
|
|
}
|
|
}
|
|
this.length = _keys.length;
|
|
} catch (error) {
|
|
e = error;
|
|
if (e.code !== "ENOENT") {
|
|
throw e;
|
|
}
|
|
try {
|
|
fs.mkdirSync(this._location);
|
|
} catch (error1) {
|
|
e = error1;
|
|
if (e.code !== "EEXIST") {
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
LocalStorage.prototype.setItem = function(key, value) {
|
|
var encodedKey, evnt, existsBeforeSet, filename, hasListeners, metaKey, oldLength, oldValue, valueString, valueStringLength;
|
|
hasListeners = events.EventEmitter.listenerCount(this, 'storage');
|
|
oldValue = null;
|
|
if (hasListeners) {
|
|
oldValue = this.getItem(key);
|
|
}
|
|
key = _escapeKey(key);
|
|
encodedKey = encodeURIComponent(key);
|
|
filename = path.join(this._location, encodedKey);
|
|
valueString = value.toString();
|
|
valueStringLength = valueString.length;
|
|
metaKey = this._metaKeyMap[key];
|
|
existsBeforeSet = !!metaKey;
|
|
if (existsBeforeSet) {
|
|
oldLength = metaKey.size;
|
|
} else {
|
|
oldLength = 0;
|
|
}
|
|
if (this._bytesInUse - oldLength + valueStringLength > this.quota) {
|
|
throw new QUOTA_EXCEEDED_ERR();
|
|
}
|
|
writeSync(filename, valueString, 'utf8');
|
|
if (!existsBeforeSet) {
|
|
metaKey = new MetaKey(encodedKey, (this._keys.push(key)) - 1);
|
|
metaKey.size = valueStringLength;
|
|
this._metaKeyMap[key] = metaKey;
|
|
this.length += 1;
|
|
this._bytesInUse += valueStringLength;
|
|
}
|
|
if (hasListeners) {
|
|
evnt = new StorageEvent(key, oldValue, value, this._eventUrl);
|
|
return this.emit('storage', evnt);
|
|
}
|
|
};
|
|
|
|
LocalStorage.prototype.getItem = function(key) {
|
|
var filename, metaKey;
|
|
key = _escapeKey(key);
|
|
metaKey = this._metaKeyMap[key];
|
|
if (!!metaKey) {
|
|
filename = path.join(this._location, metaKey.key);
|
|
return fs.readFileSync(filename, 'utf8');
|
|
} else {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
LocalStorage.prototype._getStat = function(key) {
|
|
var error, filename;
|
|
key = _escapeKey(key);
|
|
filename = path.join(this._location, encodeURIComponent(key));
|
|
try {
|
|
return fs.statSync(filename);
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
LocalStorage.prototype.removeItem = function(key) {
|
|
var evnt, filename, hasListeners, k, meta, metaKey, oldValue, ref, v;
|
|
key = _escapeKey(key);
|
|
metaKey = this._metaKeyMap[key];
|
|
if (!!metaKey) {
|
|
hasListeners = events.EventEmitter.listenerCount(this, 'storage');
|
|
oldValue = null;
|
|
if (hasListeners) {
|
|
oldValue = this.getItem(key);
|
|
}
|
|
delete this._metaKeyMap[key];
|
|
this.length -= 1;
|
|
this._bytesInUse -= metaKey.size;
|
|
filename = path.join(this._location, metaKey.key);
|
|
this._keys.splice(metaKey.index, 1);
|
|
ref = this._metaKeyMap;
|
|
for (k in ref) {
|
|
v = ref[k];
|
|
meta = this._metaKeyMap[k];
|
|
if (meta.index > metaKey.index) {
|
|
meta.index -= 1;
|
|
}
|
|
}
|
|
_rm(filename);
|
|
if (hasListeners) {
|
|
evnt = new StorageEvent(key, oldValue, null, this._eventUrl);
|
|
return this.emit('storage', evnt);
|
|
}
|
|
}
|
|
};
|
|
|
|
LocalStorage.prototype.key = function(n) {
|
|
return this._keys[n];
|
|
};
|
|
|
|
LocalStorage.prototype.clear = function() {
|
|
var evnt;
|
|
_emptyDirectory(this._location);
|
|
this._metaKeyMap = createMap();
|
|
this._keys = [];
|
|
this.length = 0;
|
|
this._bytesInUse = 0;
|
|
if (events.EventEmitter.listenerCount(this, 'storage')) {
|
|
evnt = new StorageEvent(null, null, null, this._eventUrl);
|
|
return this.emit('storage', evnt);
|
|
}
|
|
};
|
|
|
|
LocalStorage.prototype._getBytesInUse = function() {
|
|
return this._bytesInUse;
|
|
};
|
|
|
|
LocalStorage.prototype._deleteLocation = function() {
|
|
delete instanceMap[this._location];
|
|
_rm(this._location);
|
|
this._metaKeyMap = {};
|
|
this._keys = [];
|
|
this.length = 0;
|
|
return this._bytesInUse = 0;
|
|
};
|
|
|
|
return LocalStorage;
|
|
|
|
})(events.EventEmitter);
|
|
|
|
JSONStorage = (function(superClass) {
|
|
extend(JSONStorage, superClass);
|
|
|
|
function JSONStorage() {
|
|
return JSONStorage.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
JSONStorage.prototype.setItem = function(key, value) {
|
|
var newValue;
|
|
newValue = JSON.stringify(value);
|
|
return JSONStorage.__super__.setItem.call(this, key, newValue);
|
|
};
|
|
|
|
JSONStorage.prototype.getItem = function(key) {
|
|
return JSON.parse(JSONStorage.__super__.getItem.call(this, key));
|
|
};
|
|
|
|
return JSONStorage;
|
|
|
|
})(LocalStorage);
|
|
|
|
exports.LocalStorage = LocalStorage;
|
|
|
|
exports.JSONStorage = JSONStorage;
|
|
|
|
exports.QUOTA_EXCEEDED_ERR = QUOTA_EXCEEDED_ERR;
|
|
|
|
}).call(this);
|