Merge pull request #370 from humphd/fix-indexeddb-transactions

Use transaction per operation in indexeddb.js, fix broken async tests in fs.stats.spec.js
This commit is contained in:
David Humphrey 2017-05-25 10:08:54 -04:00 committed by GitHub
commit 2a4674d11f
9 changed files with 240 additions and 227 deletions

75
dist/buffer.js vendored
View File

@ -15,6 +15,7 @@ exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50 exports.INSPECT_MAX_BYTES = 50
Buffer.poolSize = 8192 // not used by this implementation Buffer.poolSize = 8192 // not used by this implementation
var kMaxLength = 0x3fffffff
var rootParent = {} var rootParent = {}
/** /**
@ -40,14 +41,11 @@ var rootParent = {}
* get the Object implementation, which is slower but will work correctly. * get the Object implementation, which is slower but will work correctly.
*/ */
Buffer.TYPED_ARRAY_SUPPORT = (function () { Buffer.TYPED_ARRAY_SUPPORT = (function () {
function Foo () {}
try { try {
var buf = new ArrayBuffer(0) var buf = new ArrayBuffer(0)
var arr = new Uint8Array(buf) var arr = new Uint8Array(buf)
arr.foo = function () { return 42 } arr.foo = function () { return 42 }
arr.constructor = Foo
return arr.foo() === 42 && // typed array instances can be augmented return arr.foo() === 42 && // typed array instances can be augmented
arr.constructor === Foo && // constructor can be set
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
} catch (e) { } catch (e) {
@ -55,12 +53,6 @@ Buffer.TYPED_ARRAY_SUPPORT = (function () {
} }
})() })()
function kMaxLength () {
return Buffer.TYPED_ARRAY_SUPPORT
? 0x7fffffff
: 0x3fffffff
}
/** /**
* Class: Buffer * Class: Buffer
* ============= * =============
@ -211,9 +203,9 @@ function allocate (that, length) {
function checked (length) { function checked (length) {
// Note: cannot use `length < kMaxLength` here because that fails when // Note: cannot use `length < kMaxLength` here because that fails when
// length is NaN (which is otherwise coerced to zero.) // length is NaN (which is otherwise coerced to zero.)
if (length >= kMaxLength()) { if (length >= kMaxLength) {
throw new RangeError('Attempt to allocate Buffer larger than maximum ' + throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
'size: 0x' + kMaxLength().toString(16) + ' bytes') 'size: 0x' + kMaxLength.toString(16) + ' bytes')
} }
return length | 0 return length | 0
} }
@ -305,38 +297,29 @@ Buffer.concat = function concat (list, length) {
} }
function byteLength (string, encoding) { function byteLength (string, encoding) {
if (typeof string !== 'string') string = '' + string if (typeof string !== 'string') string = String(string)
var len = string.length if (string.length === 0) return 0
if (len === 0) return 0
// Use a for loop to avoid recursion switch (encoding || 'utf8') {
var loweredCase = false case 'ascii':
for (;;) { case 'binary':
switch (encoding) { case 'raw':
case 'ascii': return string.length
case 'binary': case 'ucs2':
// Deprecated case 'ucs-2':
case 'raw': case 'utf16le':
case 'raws': case 'utf-16le':
return len return string.length * 2
case 'utf8': case 'hex':
case 'utf-8': return string.length >>> 1
return utf8ToBytes(string).length case 'utf8':
case 'ucs2': case 'utf-8':
case 'ucs-2': return utf8ToBytes(string).length
case 'utf16le': case 'base64':
case 'utf-16le': return base64ToBytes(string).length
return len * 2 default:
case 'hex': return string.length
return len >>> 1
case 'base64':
return base64ToBytes(string).length
default:
if (loweredCase) return utf8ToBytes(string).length // assume utf8
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
} }
} }
Buffer.byteLength = byteLength Buffer.byteLength = byteLength
@ -345,7 +328,8 @@ Buffer.byteLength = byteLength
Buffer.prototype.length = undefined Buffer.prototype.length = undefined
Buffer.prototype.parent = undefined Buffer.prototype.parent = undefined
function slowToString (encoding, start, end) { // toString(encoding, start=0, end=buffer.length)
Buffer.prototype.toString = function toString (encoding, start, end) {
var loweredCase = false var loweredCase = false
start = start | 0 start = start | 0
@ -388,13 +372,6 @@ function slowToString (encoding, start, end) {
} }
} }
Buffer.prototype.toString = function toString () {
var length = this.length | 0
if (length === 0) return ''
if (arguments.length === 0) return utf8Slice(this, 0, length)
return slowToString.apply(this, arguments)
}
Buffer.prototype.equals = function equals (b) { Buffer.prototype.equals = function equals (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
if (this === b) return true if (this === b) return true

4
dist/buffer.min.js vendored

File diff suppressed because one or more lines are too long

196
dist/filer.js vendored
View File

@ -657,6 +657,7 @@ exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50 exports.INSPECT_MAX_BYTES = 50
Buffer.poolSize = 8192 // not used by this implementation Buffer.poolSize = 8192 // not used by this implementation
var kMaxLength = 0x3fffffff
var rootParent = {} var rootParent = {}
/** /**
@ -682,14 +683,11 @@ var rootParent = {}
* get the Object implementation, which is slower but will work correctly. * get the Object implementation, which is slower but will work correctly.
*/ */
Buffer.TYPED_ARRAY_SUPPORT = (function () { Buffer.TYPED_ARRAY_SUPPORT = (function () {
function Foo () {}
try { try {
var buf = new ArrayBuffer(0) var buf = new ArrayBuffer(0)
var arr = new Uint8Array(buf) var arr = new Uint8Array(buf)
arr.foo = function () { return 42 } arr.foo = function () { return 42 }
arr.constructor = Foo
return arr.foo() === 42 && // typed array instances can be augmented return arr.foo() === 42 && // typed array instances can be augmented
arr.constructor === Foo && // constructor can be set
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
} catch (e) { } catch (e) {
@ -697,12 +695,6 @@ Buffer.TYPED_ARRAY_SUPPORT = (function () {
} }
})() })()
function kMaxLength () {
return Buffer.TYPED_ARRAY_SUPPORT
? 0x7fffffff
: 0x3fffffff
}
/** /**
* Class: Buffer * Class: Buffer
* ============= * =============
@ -853,9 +845,9 @@ function allocate (that, length) {
function checked (length) { function checked (length) {
// Note: cannot use `length < kMaxLength` here because that fails when // Note: cannot use `length < kMaxLength` here because that fails when
// length is NaN (which is otherwise coerced to zero.) // length is NaN (which is otherwise coerced to zero.)
if (length >= kMaxLength()) { if (length >= kMaxLength) {
throw new RangeError('Attempt to allocate Buffer larger than maximum ' + throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
'size: 0x' + kMaxLength().toString(16) + ' bytes') 'size: 0x' + kMaxLength.toString(16) + ' bytes')
} }
return length | 0 return length | 0
} }
@ -947,38 +939,29 @@ Buffer.concat = function concat (list, length) {
} }
function byteLength (string, encoding) { function byteLength (string, encoding) {
if (typeof string !== 'string') string = '' + string if (typeof string !== 'string') string = String(string)
var len = string.length if (string.length === 0) return 0
if (len === 0) return 0
// Use a for loop to avoid recursion switch (encoding || 'utf8') {
var loweredCase = false case 'ascii':
for (;;) { case 'binary':
switch (encoding) { case 'raw':
case 'ascii': return string.length
case 'binary': case 'ucs2':
// Deprecated case 'ucs-2':
case 'raw': case 'utf16le':
case 'raws': case 'utf-16le':
return len return string.length * 2
case 'utf8': case 'hex':
case 'utf-8': return string.length >>> 1
return utf8ToBytes(string).length case 'utf8':
case 'ucs2': case 'utf-8':
case 'ucs-2': return utf8ToBytes(string).length
case 'utf16le': case 'base64':
case 'utf-16le': return base64ToBytes(string).length
return len * 2 default:
case 'hex': return string.length
return len >>> 1
case 'base64':
return base64ToBytes(string).length
default:
if (loweredCase) return utf8ToBytes(string).length // assume utf8
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
} }
} }
Buffer.byteLength = byteLength Buffer.byteLength = byteLength
@ -987,7 +970,8 @@ Buffer.byteLength = byteLength
Buffer.prototype.length = undefined Buffer.prototype.length = undefined
Buffer.prototype.parent = undefined Buffer.prototype.parent = undefined
function slowToString (encoding, start, end) { // toString(encoding, start=0, end=buffer.length)
Buffer.prototype.toString = function toString (encoding, start, end) {
var loweredCase = false var loweredCase = false
start = start | 0 start = start | 0
@ -1030,13 +1014,6 @@ function slowToString (encoding, start, end) {
} }
} }
Buffer.prototype.toString = function toString () {
var length = this.length | 0
if (length === 0) return ''
if (arguments.length === 0) return utf8Slice(this, 0, length)
return slowToString.apply(this, arguments)
}
Buffer.prototype.equals = function equals (b) { Buffer.prototype.equals = function equals (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
if (this === b) return true if (this === b) return true
@ -7161,43 +7138,57 @@ var indexedDB = global.indexedDB ||
global.msIndexedDB; global.msIndexedDB;
function IndexedDBContext(db, mode) { function IndexedDBContext(db, mode) {
var transaction = db.transaction(FILE_STORE_NAME, mode); this.db = db;
this.objectStore = transaction.objectStore(FILE_STORE_NAME); this.mode = mode;
} }
IndexedDBContext.prototype._getObjectStore = function() {
if(this.objectStore) {
return this.objectStore;
}
var transaction = this.db.transaction(FILE_STORE_NAME, this.mode);
this.objectStore = transaction.objectStore(FILE_STORE_NAME);
return this.objectStore;
};
IndexedDBContext.prototype.clear = function(callback) { IndexedDBContext.prototype.clear = function(callback) {
try { try {
var request = this.objectStore.clear(); var objectStore = this._getObjectStore();
request.onsuccess = function(event) { var request = objectStore.clear();
request.onsuccess = function() {
callback(); callback();
}; };
request.onerror = function(error) { request.onerror = function(event) {
callback(error); event.preventDefault();
callback(event.error);
}; };
} catch(e) { } catch(err) {
callback(e); callback(err);
} }
}; };
function _get(objectStore, key, callback) { IndexedDBContext.prototype._get = function(key, callback) {
try { try {
var objectStore = this._getObjectStore();
var request = objectStore.get(key); var request = objectStore.get(key);
request.onsuccess = function onsuccess(event) { request.onsuccess = function onsuccess(event) {
var result = event.target.result; var result = event.target.result;
callback(null, result); callback(null, result);
}; };
request.onerror = function onerror(error) { request.onerror = function(event) {
callback(error); event.preventDefault();
callback(event.error);
}; };
} catch(e) { } catch(err) {
callback(e); callback(err);
} }
} };
IndexedDBContext.prototype.getObject = function(key, callback) { IndexedDBContext.prototype.getObject = function(key, callback) {
_get(this.objectStore, key, callback); this._get(key, callback);
}; };
IndexedDBContext.prototype.getBuffer = function(key, callback) { IndexedDBContext.prototype.getBuffer = function(key, callback) {
_get(this.objectStore, key, function(err, arrayBuffer) { this._get(key, function(err, arrayBuffer) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
@ -7205,22 +7196,24 @@ IndexedDBContext.prototype.getBuffer = function(key, callback) {
}); });
}; };
function _put(objectStore, key, value, callback) { IndexedDBContext.prototype._put = function(key, value, callback) {
try { try {
var objectStore = this._getObjectStore();
var request = objectStore.put(value, key); var request = objectStore.put(value, key);
request.onsuccess = function onsuccess(event) { request.onsuccess = function onsuccess(event) {
var result = event.target.result; var result = event.target.result;
callback(null, result); callback(null, result);
}; };
request.onerror = function onerror(error) { request.onerror = function(event) {
callback(error); event.preventDefault();
callback(event.error);
}; };
} catch(e) { } catch(err) {
callback(e); callback(err);
} }
} };
IndexedDBContext.prototype.putObject = function(key, value, callback) { IndexedDBContext.prototype.putObject = function(key, value, callback) {
_put(this.objectStore, key, value, callback); this._put(key, value, callback);
}; };
IndexedDBContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback) { IndexedDBContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback) {
var buf; var buf;
@ -7229,21 +7222,23 @@ IndexedDBContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback
} else { } else {
buf = uint8BackedBuffer.buffer; buf = uint8BackedBuffer.buffer;
} }
_put(this.objectStore, key, buf, callback); this._put(key, buf, callback);
}; };
IndexedDBContext.prototype.delete = function(key, callback) { IndexedDBContext.prototype.delete = function(key, callback) {
try { try {
var request = this.objectStore.delete(key); var objectStore = this._getObjectStore();
var request = objectStore.delete(key);
request.onsuccess = function onsuccess(event) { request.onsuccess = function onsuccess(event) {
var result = event.target.result; var result = event.target.result;
callback(null, result); callback(null, result);
}; };
request.onerror = function(error) { request.onerror = function(event) {
callback(error); event.preventDefault();
callback(event.error);
}; };
} catch(e) { } catch(err) {
callback(e); callback(err);
} }
}; };
@ -7264,32 +7259,35 @@ IndexedDB.prototype.open = function(callback) {
return callback(); return callback();
} }
// NOTE: we're not using versioned databases. try {
var openRequest = indexedDB.open(that.name); // NOTE: we're not using versioned databases.
var openRequest = indexedDB.open(that.name);
// If the db doesn't exist, we'll create it // If the db doesn't exist, we'll create it
openRequest.onupgradeneeded = function onupgradeneeded(event) { openRequest.onupgradeneeded = function onupgradeneeded(event) {
var db = event.target.result; var db = event.target.result;
if(db.objectStoreNames.contains(FILE_STORE_NAME)) { if(db.objectStoreNames.contains(FILE_STORE_NAME)) {
db.deleteObjectStore(FILE_STORE_NAME); db.deleteObjectStore(FILE_STORE_NAME);
} }
db.createObjectStore(FILE_STORE_NAME); db.createObjectStore(FILE_STORE_NAME);
}; };
openRequest.onsuccess = function onsuccess(event) { openRequest.onsuccess = function onsuccess(event) {
that.db = event.target.result; that.db = event.target.result;
callback(); callback();
}; };
openRequest.onerror = function onerror(error) { openRequest.onerror = function onerror(event) {
callback(new Errors.EINVAL('IndexedDB cannot be accessed. If private browsing is enabled, disable it.')); event.preventDefault();
}; callback(event.error);
};
} catch(err) {
callback(err);
}
}; };
IndexedDB.prototype.getReadOnlyContext = function() { IndexedDB.prototype.getReadOnlyContext = function() {
// Due to timing issues in Chrome with readwrite vs. readonly indexeddb transactions return new IndexedDBContext(this.db, IDB_RO);
// always use readwrite so we can make sure pending commits finish before callbacks.
// See https://github.com/js-platform/filer/issues/128
return new IndexedDBContext(this.db, IDB_RW);
}; };
IndexedDB.prototype.getReadWriteContext = function() { IndexedDB.prototype.getReadWriteContext = function() {
return new IndexedDBContext(this.db, IDB_RW); return new IndexedDBContext(this.db, IDB_RW);

8
dist/filer.min.js vendored

File diff suppressed because one or more lines are too long

2
dist/path.min.js vendored
View File

@ -1,2 +1,2 @@
/*! filer 0.0.43 2015-07-21 */ /*! filer 0.0.44 2017-05-25 */
!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Path=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){function d(a,b){for(var c=0,d=a.length-1;d>=0;d--){var e=a[d];"."===e?a.splice(d,1):".."===e?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c--;c)a.unshift("..");return a}function e(){for(var a="",b=!1,c=arguments.length-1;c>=-1&&!b;c--){var e=c>=0?arguments[c]:"/";"string"==typeof e&&e&&(a=e+"/"+a,b="/"===e.charAt(0))}return a=d(a.split("/").filter(function(a){return!!a}),!b).join("/"),(b?"/":"")+a||"."}function f(a){var b="/"===a.charAt(0);"/"===a.substr(-1);return a=d(a.split("/").filter(function(a){return!!a}),!b).join("/"),a||b||(a="."),(b?"/":"")+a}function g(){var a=Array.prototype.slice.call(arguments,0);return f(a.filter(function(a,b){return a&&"string"==typeof a}).join("/"))}function h(a,b){function c(a){for(var b=0;b<a.length&&""===a[b];b++);for(var c=a.length-1;c>=0&&""===a[c];c--);return b>c?[]:a.slice(b,c-b+1)}a=e(a).substr(1),b=e(b).substr(1);for(var d=c(a.split("/")),f=c(b.split("/")),g=Math.min(d.length,f.length),h=g,i=0;g>i;i++)if(d[i]!==f[i]){h=i;break}for(var j=[],i=h;i<d.length;i++)j.push("..");return j=j.concat(f.slice(h)),j.join("/")}function i(a){var b=q(a),c=b[0],d=b[1];return c||d?(d&&(d=d.substr(0,d.length-1)),c+d):"."}function j(a,b){var c=q(a)[2];return b&&c.substr(-1*b.length)===b&&(c=c.substr(0,c.length-b.length)),""===c?"/":c}function k(a){return q(a)[3]}function l(a){return"/"===a.charAt(0)?!0:!1}function m(a){return-1!==(""+a).indexOf("\x00")?!0:!1}function n(a){return a.replace(/\/*$/,"/")}function o(a){return a=a.replace(/\/*$/,""),""===a?"/":a}var p=/^(\/?)([\s\S]+\/(?!$)|\/)?((?:\.{1,2}$|[\s\S]+?)?(\.[^.\/]*)?)$/,q=function(a){var b=p.exec(a);return[b[1]||"",b[2]||"",b[3]||"",b[4]||""]};b.exports={normalize:f,resolve:e,join:g,relative:h,sep:"/",delimiter:":",dirname:i,basename:j,extname:k,isAbsolute:l,isNull:m,addTrailing:n,removeTrailing:o}},{}]},{},[1])(1)}); !function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Path=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){function d(a,b){for(var c=0,d=a.length-1;d>=0;d--){var e=a[d];"."===e?a.splice(d,1):".."===e?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c--;c)a.unshift("..");return a}function e(){for(var a="",b=!1,c=arguments.length-1;c>=-1&&!b;c--){var e=c>=0?arguments[c]:"/";"string"==typeof e&&e&&(a=e+"/"+a,b="/"===e.charAt(0))}return a=d(a.split("/").filter(function(a){return!!a}),!b).join("/"),(b?"/":"")+a||"."}function f(a){var b="/"===a.charAt(0);"/"===a.substr(-1);return a=d(a.split("/").filter(function(a){return!!a}),!b).join("/"),a||b||(a="."),(b?"/":"")+a}function g(){var a=Array.prototype.slice.call(arguments,0);return f(a.filter(function(a,b){return a&&"string"==typeof a}).join("/"))}function h(a,b){function c(a){for(var b=0;b<a.length&&""===a[b];b++);for(var c=a.length-1;c>=0&&""===a[c];c--);return b>c?[]:a.slice(b,c-b+1)}a=e(a).substr(1),b=e(b).substr(1);for(var d=c(a.split("/")),f=c(b.split("/")),g=Math.min(d.length,f.length),h=g,i=0;g>i;i++)if(d[i]!==f[i]){h=i;break}for(var j=[],i=h;i<d.length;i++)j.push("..");return j=j.concat(f.slice(h)),j.join("/")}function i(a){var b=q(a),c=b[0],d=b[1];return c||d?(d&&(d=d.substr(0,d.length-1)),c+d):"."}function j(a,b){var c=q(a)[2];return b&&c.substr(-1*b.length)===b&&(c=c.substr(0,c.length-b.length)),""===c?"/":c}function k(a){return q(a)[3]}function l(a){return"/"===a.charAt(0)?!0:!1}function m(a){return-1!==(""+a).indexOf("\x00")?!0:!1}function n(a){return a.replace(/\/*$/,"/")}function o(a){return a=a.replace(/\/*$/,""),""===a?"/":a}var p=/^(\/?)([\s\S]+\/(?!$)|\/)?((?:\.{1,2}$|[\s\S]+?)?(\.[^.\/]*)?)$/,q=function(a){var b=p.exec(a);return[b[1]||"",b[2]||"",b[3]||"",b[4]||""]};b.exports={normalize:f,resolve:e,join:g,relative:h,sep:"/",delimiter:":",dirname:i,basename:j,extname:k,isAbsolute:l,isNull:m,addTrailing:n,removeTrailing:o}},{}]},{},[1])(1)});

View File

@ -11,43 +11,57 @@ var indexedDB = global.indexedDB ||
global.msIndexedDB; global.msIndexedDB;
function IndexedDBContext(db, mode) { function IndexedDBContext(db, mode) {
var transaction = db.transaction(FILE_STORE_NAME, mode); this.db = db;
this.objectStore = transaction.objectStore(FILE_STORE_NAME); this.mode = mode;
} }
IndexedDBContext.prototype._getObjectStore = function() {
if(this.objectStore) {
return this.objectStore;
}
var transaction = this.db.transaction(FILE_STORE_NAME, this.mode);
this.objectStore = transaction.objectStore(FILE_STORE_NAME);
return this.objectStore;
};
IndexedDBContext.prototype.clear = function(callback) { IndexedDBContext.prototype.clear = function(callback) {
try { try {
var request = this.objectStore.clear(); var objectStore = this._getObjectStore();
request.onsuccess = function(event) { var request = objectStore.clear();
request.onsuccess = function() {
callback(); callback();
}; };
request.onerror = function(error) { request.onerror = function(event) {
callback(error); event.preventDefault();
callback(event.error);
}; };
} catch(e) { } catch(err) {
callback(e); callback(err);
} }
}; };
function _get(objectStore, key, callback) { IndexedDBContext.prototype._get = function(key, callback) {
try { try {
var objectStore = this._getObjectStore();
var request = objectStore.get(key); var request = objectStore.get(key);
request.onsuccess = function onsuccess(event) { request.onsuccess = function onsuccess(event) {
var result = event.target.result; var result = event.target.result;
callback(null, result); callback(null, result);
}; };
request.onerror = function onerror(error) { request.onerror = function(event) {
callback(error); event.preventDefault();
callback(event.error);
}; };
} catch(e) { } catch(err) {
callback(e); callback(err);
} }
} };
IndexedDBContext.prototype.getObject = function(key, callback) { IndexedDBContext.prototype.getObject = function(key, callback) {
_get(this.objectStore, key, callback); this._get(key, callback);
}; };
IndexedDBContext.prototype.getBuffer = function(key, callback) { IndexedDBContext.prototype.getBuffer = function(key, callback) {
_get(this.objectStore, key, function(err, arrayBuffer) { this._get(key, function(err, arrayBuffer) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
@ -55,22 +69,24 @@ IndexedDBContext.prototype.getBuffer = function(key, callback) {
}); });
}; };
function _put(objectStore, key, value, callback) { IndexedDBContext.prototype._put = function(key, value, callback) {
try { try {
var objectStore = this._getObjectStore();
var request = objectStore.put(value, key); var request = objectStore.put(value, key);
request.onsuccess = function onsuccess(event) { request.onsuccess = function onsuccess(event) {
var result = event.target.result; var result = event.target.result;
callback(null, result); callback(null, result);
}; };
request.onerror = function onerror(error) { request.onerror = function(event) {
callback(error); event.preventDefault();
callback(event.error);
}; };
} catch(e) { } catch(err) {
callback(e); callback(err);
} }
} };
IndexedDBContext.prototype.putObject = function(key, value, callback) { IndexedDBContext.prototype.putObject = function(key, value, callback) {
_put(this.objectStore, key, value, callback); this._put(key, value, callback);
}; };
IndexedDBContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback) { IndexedDBContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback) {
var buf; var buf;
@ -79,21 +95,23 @@ IndexedDBContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback
} else { } else {
buf = uint8BackedBuffer.buffer; buf = uint8BackedBuffer.buffer;
} }
_put(this.objectStore, key, buf, callback); this._put(key, buf, callback);
}; };
IndexedDBContext.prototype.delete = function(key, callback) { IndexedDBContext.prototype.delete = function(key, callback) {
try { try {
var request = this.objectStore.delete(key); var objectStore = this._getObjectStore();
var request = objectStore.delete(key);
request.onsuccess = function onsuccess(event) { request.onsuccess = function onsuccess(event) {
var result = event.target.result; var result = event.target.result;
callback(null, result); callback(null, result);
}; };
request.onerror = function(error) { request.onerror = function(event) {
callback(error); event.preventDefault();
callback(event.error);
}; };
} catch(e) { } catch(err) {
callback(e); callback(err);
} }
}; };
@ -114,32 +132,35 @@ IndexedDB.prototype.open = function(callback) {
return callback(); return callback();
} }
// NOTE: we're not using versioned databases. try {
var openRequest = indexedDB.open(that.name); // NOTE: we're not using versioned databases.
var openRequest = indexedDB.open(that.name);
// If the db doesn't exist, we'll create it // If the db doesn't exist, we'll create it
openRequest.onupgradeneeded = function onupgradeneeded(event) { openRequest.onupgradeneeded = function onupgradeneeded(event) {
var db = event.target.result; var db = event.target.result;
if(db.objectStoreNames.contains(FILE_STORE_NAME)) { if(db.objectStoreNames.contains(FILE_STORE_NAME)) {
db.deleteObjectStore(FILE_STORE_NAME); db.deleteObjectStore(FILE_STORE_NAME);
} }
db.createObjectStore(FILE_STORE_NAME); db.createObjectStore(FILE_STORE_NAME);
}; };
openRequest.onsuccess = function onsuccess(event) { openRequest.onsuccess = function onsuccess(event) {
that.db = event.target.result; that.db = event.target.result;
callback(); callback();
}; };
openRequest.onerror = function onerror(error) { openRequest.onerror = function onerror(event) {
callback(new Errors.EINVAL('IndexedDB cannot be accessed. If private browsing is enabled, disable it.')); event.preventDefault();
}; callback(event.error);
};
} catch(err) {
callback(err);
}
}; };
IndexedDB.prototype.getReadOnlyContext = function() { IndexedDB.prototype.getReadOnlyContext = function() {
// Due to timing issues in Chrome with readwrite vs. readonly indexeddb transactions return new IndexedDBContext(this.db, IDB_RO);
// always use readwrite so we can make sure pending commits finish before callbacks.
// See https://github.com/js-platform/filer/issues/128
return new IndexedDBContext(this.db, IDB_RW);
}; };
IndexedDB.prototype.getReadWriteContext = function() { IndexedDB.prototype.getReadWriteContext = function() {
return new IndexedDBContext(this.db, IDB_RW); return new IndexedDBContext(this.db, IDB_RW);

View File

@ -25,7 +25,7 @@ describe('sh.ls and deep directory trees', function() {
done(); done();
}); });
}); });
}); }).timeout(15000);
it('should not crash when calling sh.ls() on wide directory layouts', function(done) { it('should not crash when calling sh.ls() on wide directory layouts', function(done) {
var fs = util.fs(); var fs = util.fs();
@ -55,5 +55,5 @@ describe('sh.ls and deep directory trees', function() {
}); });
}); });
}); });
}); }).timeout(15000);
}); });

View File

@ -23,20 +23,26 @@ function IndexedDBTestProvider(name) {
return callback(); return callback();
} }
// We have to force any other connections to close
// before we can delete a db.
if(that.provider.db) {
that.provider.db.close();
}
var request = indexedDB.deleteDatabase(name);
function finished() { function finished() {
that.provider = null; that.provider = null;
_done = true; _done = true;
callback(); callback();
} }
request.onsuccess = finished;
request.onerror = finished; try {
// We have to force any other connections to close
// before we can delete a db.
if(that.provider.db) {
that.provider.db.close();
}
var request = indexedDB.deleteDatabase(name);
request.onsuccess = finished;
request.onerror = finished;
} catch(e) {
console.log("Failed to delete test database", e);
finished();
}
} }
function init() { function init() {

View File

@ -7,11 +7,12 @@ describe('fs.stats', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isFile).to.be.a('function'); expect(stats.isFile).to.be.a('function');
done();
}); });
}); });
@ -60,11 +61,12 @@ describe('fs.stats', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isDirectory).to.be.a('function'); expect(stats.isDirectory).to.be.a('function');
done();
}); });
}); });
@ -113,19 +115,21 @@ describe('fs.stats', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isBlockDevice).to.be.a('function'); expect(stats.isBlockDevice).to.be.a('function');
done();
}); });
}); });
it('should return false', function() { it('should return false', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isBlockDevice()).to.be.false; expect(stats.isBlockDevice()).to.be.false;
done();
}); });
}); });
}); });
@ -134,19 +138,21 @@ describe('fs.stats', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isCharacterDevice).to.be.a('function'); expect(stats.isCharacterDevice).to.be.a('function');
done();
}); });
}); });
it('should return false', function() { it('should return false', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isCharacterDevice()).to.be.false; expect(stats.isCharacterDevice()).to.be.false;
done();
}); });
}); });
}); });
@ -155,11 +161,12 @@ describe('fs.stats', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isSymbolicLink).to.be.a('function'); expect(stats.isSymbolicLink).to.be.a('function');
done();
}); });
}); });
@ -208,19 +215,21 @@ describe('fs.stats', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isFIFO).to.be.a('function'); expect(stats.isFIFO).to.be.a('function');
done();
}); });
}); });
it('should return false', function() { it('should return false', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isFIFO()).to.be.false; expect(stats.isFIFO()).to.be.false;
done();
}); });
}); });
}); });
@ -229,19 +238,21 @@ describe('fs.stats', function() {
beforeEach(util.setup); beforeEach(util.setup);
afterEach(util.cleanup); afterEach(util.cleanup);
it('should be a function', function() { it('should be a function', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isSocket).to.be.a('function'); expect(stats.isSocket).to.be.a('function');
done();
}); });
}); });
it('should return false', function() { it('should return false', function(done) {
var fs = util.fs(); var fs = util.fs();
fs.stat('/', function(error, stats) { fs.stat('/', function(error, stats) {
if(error) throw error; if(error) throw error;
expect(stats.isSocket()).to.be.false; expect(stats.isSocket()).to.be.false;
done();
}); });
}); });
}); });