diff --git a/src/buffer-utils.js b/src/buffer-utils.js new file mode 100644 index 0000000..b97e764 --- /dev/null +++ b/src/buffer-utils.js @@ -0,0 +1,34 @@ +/** + * Provide guarantees about Buffer vs. Uint8Array for internal code + * that has a preference. + * + * From the node.js Buffer docs: http://nodejs.org/api/buffer.html#buffer_buffer + * + * "A Buffer object can also be used with typed arrays. The buffer + * object is cloned to an ArrayBuffer that is used as the backing + * store for the typed array. The memory of the buffer and the + * ArrayBuffer is not shared." + * + * In a browser, where we use https://github.com/feross/buffer, a Buffer + * is really a Uint8Array augmented with other methods and properties. As + * such, we do feature detection instead of type identifiation. + */ + +function ensureBuffer(maybeBuffer) { + if(!(typeof maybeBuffer.copy === 'function')) { + maybeBuffer = new Buffer(maybeBuffer); + } + return maybeBuffer; +} + +function ensureUint8Array(maybeU8) { + if(!('buffer' in maybeU8 && 'byteOffset' in maybeU8 && 'byteLength' in maybeU8)) { + maybeU8 = new Uint8Array(maybeU8); + } + return maybeU8; +} + +module.exports = { + ensureBuffer: ensureBuffer, + ensureUint8Array: ensureUint8Array +}; diff --git a/src/encoding.js b/src/encoding.js new file mode 100644 index 0000000..582e801 --- /dev/null +++ b/src/encoding.js @@ -0,0 +1,19 @@ +var TextEncoder = require('../lib/encoding.js').TextEncoder; +var TextDecoder = require('../lib/encoding.js').TextDecoder; +var BufferUtils = require('./buffer-utils.js'); + +// Adapt encodings to work with Buffer or Uint8Array, they expect the latter +function decode(buf) { + buf = BufferUtils.ensureUint8Array(buf); + return (new TextDecoder('utf8')).decode(buf); +} + +function encode(string) { + var u8 = (new TextEncoder('utf8')).encode(string); + return BufferUtils.ensureBuffer(u8); +} + +module.exports = { + encode: encode, + decode: decode +}; diff --git a/src/filesystem/implementation.js b/src/filesystem/implementation.js index 86ee92d..1da2e0d 100644 --- a/src/filesystem/implementation.js +++ b/src/filesystem/implementation.js @@ -1,8 +1,5 @@ var _ = require('../../lib/nodash.js'); -var TextDecoder = require('../../lib/encoding.js').TextDecoder; -var TextEncoder = require('../../lib/encoding.js').TextEncoder; - var Path = require('../path.js'); var normalize = Path.normalize; var dirname = Path.dirname; @@ -33,6 +30,8 @@ var XATTR_REPLACE = Constants.XATTR_REPLACE; var FS_NOMTIME = Constants.FS_NOMTIME; var FS_NOCTIME = Constants.FS_NOCTIME; +var Encoding = require('../encoding.js'); +var BufferUtils = require('../buffer-utils.js'); var Errors = require('../errors.js'); var DirectoryEntry = require('../directory-entry.js'); var OpenFileDescription = require('../open-file-description.js'); @@ -641,7 +640,7 @@ function open_file(context, path, flags, callback) { if(error) { callback(error); } else { - fileData = new Uint8Array(0); + fileData = new Buffer(0); context.put(fileNode.data, fileData, update_directory_data); } } @@ -676,6 +675,8 @@ function open_file(context, path, flags, callback) { function replace_data(context, ofd, buffer, offset, length, callback) { var fileNode; + buffer = BufferUtils.ensureBuffer(buffer); + function return_nbytes(error) { if(error) { callback(error); @@ -706,9 +707,9 @@ function replace_data(context, ofd, buffer, offset, length, callback) { callback(error); } else { fileNode = result; - var newData = new Uint8Array(length); - var bufferWindow = buffer.subarray(offset, offset + length); - newData.set(bufferWindow); + var newData = new Buffer(length); + var bufferWindow = buffer.slice(offset, offset + length); + bufferWindow.copy(newData); ofd.position = length; fileNode.size = length; @@ -725,6 +726,8 @@ function write_data(context, ofd, buffer, offset, length, position, callback) { var fileNode; var fileData; + buffer = BufferUtils.ensureBuffer(buffer); + function return_nbytes(error) { if(error) { callback(error); @@ -757,12 +760,12 @@ function write_data(context, ofd, buffer, offset, length, position, callback) { fileData = result; var _position = (!(undefined === position || null === position)) ? position : ofd.position; var newSize = Math.max(fileData.length, _position + length); - var newData = new Uint8Array(newSize); + var newData = new Buffer(newSize); if(fileData) { - newData.set(fileData); - } - var bufferWindow = buffer.subarray(offset, offset + length); - newData.set(bufferWindow, _position); + newData.copy(fileData); + } + var bufferWindow = buffer.slice(offset, offset + length); + bufferWindow.copy(newData, _position); if(undefined === position) { ofd.position += length; } @@ -790,6 +793,8 @@ function read_data(context, ofd, buffer, offset, length, position, callback) { var fileNode; var fileData; + buffer = BufferUtils.ensureBuffer(buffer); + function handle_file_data(error, result) { if(error) { callback(error); @@ -797,8 +802,8 @@ function read_data(context, ofd, buffer, offset, length, position, callback) { fileData = result; var _position = (!(undefined === position || null === position)) ? position : ofd.position; length = (_position + length > buffer.length) ? length - _position : length; - var dataView = fileData.subarray(_position, _position + length); - buffer.set(dataView, offset); + var dataView = fileData.slice(_position, _position + length); + dataView.copy(buffer, offset); if(undefined === position) { ofd.position += length; } @@ -1182,9 +1187,9 @@ function truncate_file(context, path, length, callback) { if (error) { callback(error); } else { - var data = new Uint8Array(length); + var data = new Buffer(length); if(fileData) { - data.set(fileData.subarray(0, length)); + fileData.copy(data); } context.put(fileNode.data, data, update_file_node); } @@ -1234,9 +1239,11 @@ function ftruncate_file(context, ofd, length, callback) { if (error) { callback(error); } else { - var data = new Uint8Array(length); + var data; if(fileData) { - data.set(fileData.subarray(0, length)); + data = fileData.slice(0, length); + } else { + data = new Buffer(length); } context.put(fileNode.data, data, update_file_node); } @@ -1651,7 +1658,7 @@ function readFile(fs, context, path, options, callback) { var stats = new Stats(fstatResult, fs.name); var size = stats.size; - var buffer = new Uint8Array(size); + var buffer = new Buffer(size); read_data(context, ofd, buffer, 0, size, 0, function(err3, nbytes) { if(err3) { @@ -1661,7 +1668,7 @@ function readFile(fs, context, path, options, callback) { var data; if(options.encoding === 'utf8') { - data = new TextDecoder('utf-8').decode(buffer); + data = Encoding.decode(buffer); } else { data = buffer; } @@ -1704,7 +1711,7 @@ function writeFile(fs, context, path, data, options, callback) { data = '' + data; } if(typeof data === "string" && options.encoding === 'utf8') { - data = new TextEncoder('utf-8').encode(data); + data = Encoding.encode(data); } open_file(context, path, flags, function(err, fileNode) { @@ -1740,7 +1747,7 @@ function appendFile(fs, context, path, data, options, callback) { data = '' + data; } if(typeof data === "string" && options.encoding === 'utf8') { - data = new TextEncoder('utf-8').encode(data); + data = Encoding.encode(data); } open_file(context, path, flags, function(err, fileNode) { diff --git a/tests/spec/fs.appendFile.spec.js b/tests/spec/fs.appendFile.spec.js index c76ae14..0224250 100644 --- a/tests/spec/fs.appendFile.spec.js +++ b/tests/spec/fs.appendFile.spec.js @@ -72,11 +72,11 @@ describe('fs.appendFile', function() { // String and utf8 binary encoded versions of the same thing: var contents = "This is a file."; - var binary = new Uint8Array([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]); + var binary = new Buffer([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]); var more = " Appended."; - var binary2 = new Uint8Array([32, 65, 112, 112, 101, 110, 100, 101, 100, 46]); - var binary3 = new Uint8Array([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46, - 32, 65, 112, 112, 101, 110, 100, 101, 100, 46]); + var binary2 = new Buffer([32, 65, 112, 112, 101, 110, 100, 101, 100, 46]); + var binary3 = new Buffer([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46, + 32, 65, 112, 112, 101, 110, 100, 101, 100, 46]); fs.writeFile('/mybinaryfile', binary, function(error) { if(error) throw error; diff --git a/tests/spec/fs.truncate.spec.js b/tests/spec/fs.truncate.spec.js index 9d3d5ca..0c8eaba 100644 --- a/tests/spec/fs.truncate.spec.js +++ b/tests/spec/fs.truncate.spec.js @@ -38,8 +38,8 @@ describe('fs.truncate', function() { it('should truncate a file', function(done) { var fs = util.fs(); - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); - var truncated = new Uint8Array([1]); + var buffer = new Buffer([1, 2, 3, 4, 5, 6, 7, 8]); + var truncated = new Buffer([1]); fs.open('/myfile', 'w', function(error, result) { if(error) throw error; @@ -68,8 +68,8 @@ describe('fs.truncate', function() { it('should pad a file with zeros when the length is greater than the file size', function(done) { var fs = util.fs(); - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); - var truncated = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 0]); + var buffer = new Buffer([1, 2, 3, 4, 5, 6, 7, 8]); + var truncated = new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 0]); fs.open('/myfile', 'w', function(error, result) { if(error) throw error; @@ -98,7 +98,7 @@ describe('fs.truncate', function() { it('should update the file size', function(done) { var fs = util.fs(); - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + var buffer = new Buffer([1, 2, 3, 4, 5, 6, 7, 8]); fs.open('/myfile', 'w', function(error, result) { if(error) throw error; @@ -127,7 +127,7 @@ describe('fs.truncate', function() { it('should truncate a valid descriptor', function(done) { var fs = util.fs(); - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + var buffer = new Buffer([1, 2, 3, 4, 5, 6, 7, 8]); fs.open('/myfile', 'w', function(error, result) { if(error) throw error; @@ -152,7 +152,7 @@ describe('fs.truncate', function() { it('should follow symbolic links', function(done) { var fs = util.fs(); - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + var buffer = new Buffer([1, 2, 3, 4, 5, 6, 7, 8]); fs.open('/myfile', 'w', function(error, result) { if(error) throw error; diff --git a/tests/spec/fs.writeFile-readFile.spec.js b/tests/spec/fs.writeFile-readFile.spec.js index 3c9cd6a..048b72b 100644 --- a/tests/spec/fs.writeFile-readFile.spec.js +++ b/tests/spec/fs.writeFile-readFile.spec.js @@ -70,7 +70,7 @@ describe('fs.writeFile, fs.readFile', function() { var fs = util.fs(); // String and utf8 binary encoded versions of the same thing: var contents = "This is a file."; - var binary = new Uint8Array([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]); + var binary = new Buffer([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]); fs.writeFile('/myfile', binary, function(error) { if(error) throw error;