diff --git a/dist/idbfs.js b/dist/idbfs.js index ac8cde8..14032ab 100644 --- a/dist/idbfs.js +++ b/dist/idbfs.js @@ -6185,7 +6185,15 @@ define('src/file-system',['require','lodash','when','src/path','src/path','src/p var fileNode; var fileData; - find_node(objectStore, parentPath, read_directory_data); + if(ROOT_DIRECTORY_NAME == name) { + if(_(flags).contains(O_WRITE)) { + callback(new EIsDirectory('the named file is a directory and O_WRITE is set')) + } else { + find_node(objectStore, path, set_file_node); + } + } else { + find_node(objectStore, parentPath, read_directory_data); + } function read_directory_data(error, result) { if(error) { @@ -6241,7 +6249,7 @@ define('src/file-system',['require','lodash','when','src/path','src/path','src/p if(error) { callback(error); } else { - fileData = {}; + fileData = new Uint8Array(0); write_object(objectStore, fileData, fileNode.data, update_directory_data); } }; @@ -6299,7 +6307,7 @@ define('src/file-system',['require','lodash','when','src/path','src/path','src/p fileNode.mtime = Date.now(); fileNode.version += 1; - write_object(objectStore, fileNode.data, update_file_node); + write_object(objectStore, newData, fileNode.data, update_file_node); } }; @@ -6307,7 +6315,7 @@ define('src/file-system',['require','lodash','when','src/path','src/path','src/p if(error) { callback(error); } else { - write_object(objectStore, fileNode.id, return_nbytes); + write_object(objectStore, fileNode, fileNode.id, return_nbytes); } }; @@ -6315,7 +6323,7 @@ define('src/file-system',['require','lodash','when','src/path','src/path','src/p if(error) { callback(error); } else { - callback(undefined, nbytes); + callback(undefined, length); } }; }; @@ -6343,6 +6351,7 @@ define('src/file-system',['require','lodash','when','src/path','src/path','src/p var _position = (undefined !== position) ? position : ofd.position; length = (_position + length > buffer.length) ? length - _position : length; var dataView = fileData.subarray(_position, _position + length); + buffer.set(dataView, offset); if(undefined === position) { ofd.position += length; } @@ -6624,67 +6633,93 @@ define('src/file-system',['require','lodash','when','src/path','src/path','src/p }; FileSystem.prototype.read = function read(fd, buffer, offset, length, position, callback) { - var deferred = when.defer(); - var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW); - var files = transaction.objectStore(FILE_STORE_NAME); + var that = this; + this.promise.then( + function() { + var deferred = when.defer(); + var transaction = that.db.transaction([FILE_STORE_NAME], IDB_RW); + var files = transaction.objectStore(FILE_STORE_NAME); - offset = (undefined === offset) ? 0 : offset; - length = (undefined === length) ? buffer.length - offset : length; + offset = (undefined === offset) ? 0 : offset; + length = (undefined === length) ? buffer.length - offset : length; - function check_result(error, nbytes) { - if(error) { - // if(transaction.error) transaction.abort(); - deferred.reject(error); - } else { - deferred.resolve(nbytes); + function check_result(error, nbytes) { + if(error) { + // if(transaction.error) transaction.abort(); + deferred.reject(error); + } else { + deferred.resolve(nbytes); + } + }; + + var ofd = that.openFiles[fd]; + + if(!ofd) { + deferred.reject(new EBadFileDescriptor('invalid file descriptor')); + } else if(!_(ofd.flags).contains(O_READ)) { + deferred.reject(new EBadFileDescriptor('descriptor does not permit reading')); + } else { + read_data(files, ofd, buffer, offset, length, position, check_result); + } + + deferred.promise.then( + function(result) { + callback(undefined, result); + }, + function(error) { + callback(error); + } + ); + }, + function() { + callback(new EFileSystemError('unknown error')); } - }; - - var ofd = this.openFiles[fd]; - - if(!ofd) { - deferred.reject(new EBadFileDescriptor('invalid file descriptor')); - } else if(!_(flags).contains(O_READ)) { - deferred.reject(new EBadFileDescriptor('descriptor does not permit reading')); - } else { - read_data(files, ofd, buffer, offset, length, position, check_result); - } - - // TODO: check buffer length - - return deferred.promise; + ); }; FileSystem.prototype.write = function write(fd, buffer, offset, length, position, callback) { - var deferred = when.defer(); - var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW); - var files = transaction.objectStore(FILE_STORE_NAME); + var that = this; + this.promise.then( + function() { + var deferred = when.defer(); + var transaction = that.db.transaction([FILE_STORE_NAME], IDB_RW); + var files = transaction.objectStore(FILE_STORE_NAME); - offset = (undefined === offset) ? 0 : offset; - length = (undefined === length) ? buffer.length - offset : length; + offset = (undefined === offset) ? 0 : offset; + length = (undefined === length) ? buffer.length - offset : length; - function check_result(error, nbytes) { - if(error) { - deferred.reject(error); - } else { - deferred.resolve(nbytes); + function check_result(error, nbytes) { + if(error) { + deferred.reject(error); + } else { + deferred.resolve(nbytes); + } + }; + + var ofd = that.openFiles[fd]; + + if(!ofd) { + deferred.reject(new EBadFileDescriptor('invalid file descriptor')); + } else if(!_(ofd.flags).contains(O_WRITE)) { + deferred.reject(new EBadFileDescriptor('descriptor does not permit writing')); + } else if(buffer.length - offset < length) { + deferred.reject(new EIO('intput buffer is too small')); + } else { + write_data(files, ofd, buffer, offset, length, position, check_result); + } + + deferred.promise.then( + function(result) { + callback(undefined, result); + }, + function(error) { + callback(error); + } + ); + }, + function() { + callback(new EFileSystemError('unknown error')); } - }; - - var ofd = this.openFiles[fd]; - - if(!ofd) { - deferred.reject(new EBadFileDescriptor('invalid file descriptor')); - } else if(!_(flags).contains(O_WRITE)) { - deferred.reject(new EBadFileDescriptor('descriptor does not permit writing')); - } else if(buffer.length - offset < length) { - deferred.reject(new EIO('intput buffer is too small')); - } else { - write_data(files, ofd, buffer, offset, length, position, check_result); - } - - // TODO: check buffer length - - return deferred.promise; + ); }; FileSystem.prototype.seek = function seek(fd, offset, origin) { diff --git a/examples/refactoring-test.html b/examples/refactoring-test.html index 4f1c45d..f922956 100644 --- a/examples/refactoring-test.html +++ b/examples/refactoring-test.html @@ -21,8 +21,22 @@ var flags = 'FORMAT'; //var flags; var fs = new IDBFS.FileSystem('local', flags); -fs.open('/', 'r', function(error, result) { - console.log('1', error, result); +var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); +console.log('buffer', buffer); +var data = new Uint8Array(buffer.length); +console.log('data', data); +debugger; +fs.open('/myfile', 'w+', function(error, fd) { + if(error) throw error; + console.log('descriptor:', fd); + fs.write(fd, buffer, 0, buffer.length, 0, function(error, nbytes) { + console.log('write:', nbytes) + if(error) throw error; + fs.read(fd, data, 0, data.length, 0, function(error, nbytes) { + console.log('read:', nbytes); + console.log('data', data); + }); + }); }); /* diff --git a/src/file-system.js b/src/file-system.js index dfadce6..953b02d 100644 --- a/src/file-system.js +++ b/src/file-system.js @@ -449,7 +449,7 @@ define(function(require) { if(error) { callback(error); } else { - fileData = {}; + fileData = new Uint8Array(0); write_object(objectStore, fileData, fileNode.data, update_directory_data); } }; @@ -507,7 +507,7 @@ define(function(require) { fileNode.mtime = Date.now(); fileNode.version += 1; - write_object(objectStore, fileNode.data, update_file_node); + write_object(objectStore, newData, fileNode.data, update_file_node); } }; @@ -515,7 +515,7 @@ define(function(require) { if(error) { callback(error); } else { - write_object(objectStore, fileNode.id, return_nbytes); + write_object(objectStore, fileNode, fileNode.id, return_nbytes); } }; @@ -523,7 +523,7 @@ define(function(require) { if(error) { callback(error); } else { - callback(undefined, nbytes); + callback(undefined, length); } }; }; @@ -551,6 +551,7 @@ define(function(require) { var _position = (undefined !== position) ? position : ofd.position; length = (_position + length > buffer.length) ? length - _position : length; var dataView = fileData.subarray(_position, _position + length); + buffer.set(dataView, offset); if(undefined === position) { ofd.position += length; } @@ -832,67 +833,93 @@ define(function(require) { }; FileSystem.prototype.read = function read(fd, buffer, offset, length, position, callback) { - var deferred = when.defer(); - var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW); - var files = transaction.objectStore(FILE_STORE_NAME); + var that = this; + this.promise.then( + function() { + var deferred = when.defer(); + var transaction = that.db.transaction([FILE_STORE_NAME], IDB_RW); + var files = transaction.objectStore(FILE_STORE_NAME); - offset = (undefined === offset) ? 0 : offset; - length = (undefined === length) ? buffer.length - offset : length; + offset = (undefined === offset) ? 0 : offset; + length = (undefined === length) ? buffer.length - offset : length; - function check_result(error, nbytes) { - if(error) { - // if(transaction.error) transaction.abort(); - deferred.reject(error); - } else { - deferred.resolve(nbytes); + function check_result(error, nbytes) { + if(error) { + // if(transaction.error) transaction.abort(); + deferred.reject(error); + } else { + deferred.resolve(nbytes); + } + }; + + var ofd = that.openFiles[fd]; + + if(!ofd) { + deferred.reject(new EBadFileDescriptor('invalid file descriptor')); + } else if(!_(ofd.flags).contains(O_READ)) { + deferred.reject(new EBadFileDescriptor('descriptor does not permit reading')); + } else { + read_data(files, ofd, buffer, offset, length, position, check_result); + } + + deferred.promise.then( + function(result) { + callback(undefined, result); + }, + function(error) { + callback(error); + } + ); + }, + function() { + callback(new EFileSystemError('unknown error')); } - }; - - var ofd = this.openFiles[fd]; - - if(!ofd) { - deferred.reject(new EBadFileDescriptor('invalid file descriptor')); - } else if(!_(flags).contains(O_READ)) { - deferred.reject(new EBadFileDescriptor('descriptor does not permit reading')); - } else { - read_data(files, ofd, buffer, offset, length, position, check_result); - } - - // TODO: check buffer length - - return deferred.promise; + ); }; FileSystem.prototype.write = function write(fd, buffer, offset, length, position, callback) { - var deferred = when.defer(); - var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW); - var files = transaction.objectStore(FILE_STORE_NAME); + var that = this; + this.promise.then( + function() { + var deferred = when.defer(); + var transaction = that.db.transaction([FILE_STORE_NAME], IDB_RW); + var files = transaction.objectStore(FILE_STORE_NAME); - offset = (undefined === offset) ? 0 : offset; - length = (undefined === length) ? buffer.length - offset : length; + offset = (undefined === offset) ? 0 : offset; + length = (undefined === length) ? buffer.length - offset : length; - function check_result(error, nbytes) { - if(error) { - deferred.reject(error); - } else { - deferred.resolve(nbytes); + function check_result(error, nbytes) { + if(error) { + deferred.reject(error); + } else { + deferred.resolve(nbytes); + } + }; + + var ofd = that.openFiles[fd]; + + if(!ofd) { + deferred.reject(new EBadFileDescriptor('invalid file descriptor')); + } else if(!_(ofd.flags).contains(O_WRITE)) { + deferred.reject(new EBadFileDescriptor('descriptor does not permit writing')); + } else if(buffer.length - offset < length) { + deferred.reject(new EIO('intput buffer is too small')); + } else { + write_data(files, ofd, buffer, offset, length, position, check_result); + } + + deferred.promise.then( + function(result) { + callback(undefined, result); + }, + function(error) { + callback(error); + } + ); + }, + function() { + callback(new EFileSystemError('unknown error')); } - }; - - var ofd = this.openFiles[fd]; - - if(!ofd) { - deferred.reject(new EBadFileDescriptor('invalid file descriptor')); - } else if(!_(flags).contains(O_WRITE)) { - deferred.reject(new EBadFileDescriptor('descriptor does not permit writing')); - } else if(buffer.length - offset < length) { - deferred.reject(new EIO('intput buffer is too small')); - } else { - write_data(files, ofd, buffer, offset, length, position, check_result); - } - - // TODO: check buffer length - - return deferred.promise; + ); }; FileSystem.prototype.seek = function seek(fd, offset, origin) { diff --git a/tests/spec/idbfs.spec.js b/tests/spec/idbfs.spec.js index 820dabb..a935349 100644 --- a/tests/spec/idbfs.spec.js +++ b/tests/spec/idbfs.spec.js @@ -24,6 +24,24 @@ function mk_db_name() { return name; }; +function array_buffer_equal(left, right) { + if(!(left instanceof ArrayBuffer && right instanceof ArrayBuffer)) { + return false; + } + + if(left.byteLength !== right.byteLength) { + return false; + } + + for(var i = 0; i < left.byteLength; ++ i) { + if(left[i] !== right[i]) { + return false; + } + } + + return true; +}; + describe("IDBFS", function() { it("is defined", function() { expect(typeof IDBFS).not.toEqual(undefined); @@ -431,8 +449,158 @@ describe('fs.open', function() { expect(_result).not.toBeDefined(); }); }); -/* + it('should return a unique file descriptor', function() { + var complete1 = false; + var complete2 = false; + var _error, _result1, _result2; + var that = this; + + that.fs.open('/file1', 'w+', function(error, fd) { + if(error) throw error; + _error = error; + _result1 = fd; + + complete1 = true; + }); + that.fs.open('/file2', 'w+', function(error, fd) { + if(error) throw error; + _error = error; + _result2 = fd; + + complete2 = true; + }); + + waitsFor(function() { + return complete1 && complete2; + }, 'test to complete', DEFAULT_TIMEOUT); + + runs(function() { + expect(_error).not.toBeDefined(); + expect(_result1).toBeDefined(); + expect(_result2).toBeDefined(); + expect(_result1).not.toEqual(_result2); + }); + }); + + it('should create a new file when flagged for write', function() { + var complete = false; + var _error, _result; + var that = this; + + that.fs.open('/myfile', 'w', function(error, result) { + if(error) throw error; + that.fs.stat('/myfile', function(error, result) { + _error = error; + _result = result; + + complete = true; + }) + }); + + waitsFor(function() { + return complete; + }, 'test to complete', DEFAULT_TIMEOUT); + + runs(function() { + expect(_error).not.toBeDefined(); + expect(_result).toBeDefined(); + }); + }); +}); + +describe('fs.write', function() { + beforeEach(function() { + this.db_name = mk_db_name(); + this.fs = new IDBFS.FileSystem(this.db_name, 'FORMAT'); + }); + + afterEach(function() { + indexedDB.deleteDatabase(this.db_name); + delete this.fs; + }); + + it('should be a function', function() { + expect(typeof this.fs.write).toEqual('function'); + }); + + it('should write data to a file', function() { + var complete = false; + var _error, _result; + var that = this; + + var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + + that.fs.open('/myfile', 'w', function(error, result) { + if(error) throw error; + + var fd = result; + that.fs.write(fd, buffer, 0, buffer.length, 0, function(error, result) { + _error = error; + _result = result; + + complete = true; + }) + }); + + waitsFor(function() { + return complete; + }, 'test to complete', DEFAULT_TIMEOUT); + + runs(function() { + expect(_error).not.toBeDefined(); + expect(_result).toEqual(buffer.length); + }); + }); +}); + +describe('fs.read', function() { + beforeEach(function() { + this.db_name = mk_db_name(); + this.fs = new IDBFS.FileSystem(this.db_name, 'FORMAT'); + }); + + afterEach(function() { + indexedDB.deleteDatabase(this.db_name); + delete this.fs; + }); + + it('should be a function', function() { + expect(typeof this.fs.read).toEqual('function'); + }); + + it('should read data from a file', function() { + var complete = false; + var _error, _result; + var that = this; + + var wbuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + var rbuffer = new Uint8Array(wbuffer.length); + + that.fs.open('/myfile', 'w+', function(error, result) { + if(error) throw error; + + var fd = result; + that.fs.write(fd, wbuffer, 0, wbuffer.length, 0, function(error, result) { + if(error) throw error; + + that.fs.read(fd, rbuffer, 0, rbuffer.length, 0, function(error, result) { + _error = error; + _result = result; + + complete = true; + }); + }) + }); + + waitsFor(function() { + return complete; + }, 'test to complete', DEFAULT_TIMEOUT); + + runs(function() { + expect(_error).not.toBeDefined(); + expect(_result).toEqual(rbuffer.length); + expect(array_buffer_equal(wbuffer.buffer, rbuffer.buffer)).toEqual(true); + }); }); -*/ }); \ No newline at end of file