From 1914f7a52b2e2369d2c3476f0fe65a976db1f8f1 Mon Sep 17 00:00:00 2001 From: "David Humphrey (:humph) david.humphrey@senecacollege.ca" Date: Wed, 4 Jun 2014 15:52:08 -0400 Subject: [PATCH 1/4] WIP - moving to Buffer internally from Uint8Array, not passing all tests yet. --- src/buffer-utils.js | 34 ++++++++++++++++ src/encoding.js | 19 +++++++++ src/filesystem/implementation.js | 51 ++++++++++++++---------- tests/spec/fs.appendFile.spec.js | 8 ++-- tests/spec/fs.truncate.spec.js | 14 +++---- tests/spec/fs.writeFile-readFile.spec.js | 2 +- 6 files changed, 94 insertions(+), 34 deletions(-) create mode 100644 src/buffer-utils.js create mode 100644 src/encoding.js 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; From fa65a349055240fe351fd908d9d10d8dce0395c9 Mon Sep 17 00:00:00 2001 From: "David Humphrey (:humph) david.humphrey@senecacollege.ca" Date: Fri, 6 Jun 2014 11:14:52 -0400 Subject: [PATCH 2/4] Get Buffer use fixed, expose Buffer via Filer.Buffer, most tests passing. --- lib/encoding-indexes-shim.js | 11 - lib/encoding.js | 593 ------------------------------- src/buffer-utils.js | 34 -- src/encoding.js | 10 +- src/filesystem/implementation.js | 24 +- src/index.js | 1 + src/shell/shell.js | 8 +- tests/spec/fs.close.spec.js | 2 +- tests/spec/fs.lseek.spec.js | 21 +- tests/spec/fs.read.spec.js | 10 +- tests/spec/fs.write.spec.js | 4 +- tests/spec/times.spec.js | 7 +- 12 files changed, 40 insertions(+), 685 deletions(-) delete mode 100644 lib/encoding-indexes-shim.js delete mode 100644 lib/encoding.js delete mode 100644 src/buffer-utils.js diff --git a/lib/encoding-indexes-shim.js b/lib/encoding-indexes-shim.js deleted file mode 100644 index 5b9ea8e..0000000 --- a/lib/encoding-indexes-shim.js +++ /dev/null @@ -1,11 +0,0 @@ -// Hack to allow using encoding.js with only utf8. -// Right now there's a bug where it expects global['encoding-indexes']: -// -// function index(name) { -// if (!('encoding-indexes' in global)) -// throw new Error("Indexes missing. Did you forget to include encoding-indexes.js?"); -// return global['encoding-indexes'][name]; -// } -(function(global) { - global['encoding-indexes'] = global['encoding-indexes'] || []; -}(this)); diff --git a/lib/encoding.js b/lib/encoding.js deleted file mode 100644 index 04b71d9..0000000 --- a/lib/encoding.js +++ /dev/null @@ -1,593 +0,0 @@ -/*! - * Shim implementation of the TextEncoder, TextDecoder spec: - * http://encoding.spec.whatwg.org/#interface-textencoder - * - * http://code.google.com/p/stringencoding/source/browse/encoding.js - * 09b44d71759d on Sep 19, 2013 - * Used under Apache License 2.0 - http://code.google.com/p/stringencoding/ - * - * Filer: modified to remove non-utf8 aspects, converted to CommonJS - */ -(function(global) { - 'use strict'; - - // - // Utilities - // - - /** - * @param {number} a The number to test. - * @param {number} min The minimum value in the range, inclusive. - * @param {number} max The maximum value in the range, inclusive. - * @return {boolean} True if a >= min and a <= max. - */ - function inRange(a, min, max) { - return min <= a && a <= max; - } - - /** - * @param {number} n The numerator. - * @param {number} d The denominator. - * @return {number} The result of the integer division of n by d. - */ - function div(n, d) { - return Math.floor(n / d); - } - - - // - // Implementation of Encoding specification - // http://dvcs.w3.org/hg/encoding/raw-file/tip/Overview.html - // - - // - // 3. Terminology - // - - // - // 4. Encodings - // - - /** @const */ var EOF_byte = -1; - /** @const */ var EOF_code_point = -1; - - /** - * @constructor - * @param {Uint8Array} bytes Array of bytes that provide the stream. - */ - function ByteInputStream(bytes) { - /** @type {number} */ - var pos = 0; - - /** @return {number} Get the next byte from the stream. */ - this.get = function() { - return (pos >= bytes.length) ? EOF_byte : Number(bytes[pos]); - }; - - /** @param {number} n Number (positive or negative) by which to - * offset the byte pointer. */ - this.offset = function(n) { - pos += n; - if (pos < 0) { - throw new Error('Seeking past start of the buffer'); - } - if (pos > bytes.length) { - throw new Error('Seeking past EOF'); - } - }; - - /** - * @param {Array.} test Array of bytes to compare against. - * @return {boolean} True if the start of the stream matches the test - * bytes. - */ - this.match = function(test) { - if (test.length > pos + bytes.length) { - return false; - } - var i; - for (i = 0; i < test.length; i += 1) { - if (Number(bytes[pos + i]) !== test[i]) { - return false; - } - } - return true; - }; - } - - /** - * @constructor - * @param {Array.} bytes The array to write bytes into. - */ - function ByteOutputStream(bytes) { - /** @type {number} */ - var pos = 0; - - /** - * @param {...number} var_args The byte or bytes to emit into the stream. - * @return {number} The last byte emitted. - */ - this.emit = function(var_args) { - /** @type {number} */ - var last = EOF_byte; - var i; - for (i = 0; i < arguments.length; ++i) { - last = Number(arguments[i]); - bytes[pos++] = last; - } - return last; - }; - } - - /** - * @constructor - * @param {string} string The source of code units for the stream. - */ - function CodePointInputStream(string) { - /** - * @param {string} string Input string of UTF-16 code units. - * @return {Array.} Code points. - */ - function stringToCodePoints(string) { - /** @type {Array.} */ - var cps = []; - // Based on http://www.w3.org/TR/WebIDL/#idl-DOMString - var i = 0, n = string.length; - while (i < string.length) { - var c = string.charCodeAt(i); - if (!inRange(c, 0xD800, 0xDFFF)) { - cps.push(c); - } else if (inRange(c, 0xDC00, 0xDFFF)) { - cps.push(0xFFFD); - } else { // (inRange(cu, 0xD800, 0xDBFF)) - if (i === n - 1) { - cps.push(0xFFFD); - } else { - var d = string.charCodeAt(i + 1); - if (inRange(d, 0xDC00, 0xDFFF)) { - var a = c & 0x3FF; - var b = d & 0x3FF; - i += 1; - cps.push(0x10000 + (a << 10) + b); - } else { - cps.push(0xFFFD); - } - } - } - i += 1; - } - return cps; - } - - /** @type {number} */ - var pos = 0; - /** @type {Array.} */ - var cps = stringToCodePoints(string); - - /** @param {number} n The number of bytes (positive or negative) - * to advance the code point pointer by.*/ - this.offset = function(n) { - pos += n; - if (pos < 0) { - throw new Error('Seeking past start of the buffer'); - } - if (pos > cps.length) { - throw new Error('Seeking past EOF'); - } - }; - - - /** @return {number} Get the next code point from the stream. */ - this.get = function() { - if (pos >= cps.length) { - return EOF_code_point; - } - return cps[pos]; - }; - } - - /** - * @constructor - */ - function CodePointOutputStream() { - /** @type {string} */ - var string = ''; - - /** @return {string} The accumulated string. */ - this.string = function() { - return string; - }; - - /** @param {number} c The code point to encode into the stream. */ - this.emit = function(c) { - if (c <= 0xFFFF) { - string += String.fromCharCode(c); - } else { - c -= 0x10000; - string += String.fromCharCode(0xD800 + ((c >> 10) & 0x3ff)); - string += String.fromCharCode(0xDC00 + (c & 0x3ff)); - } - }; - } - - /** - * @constructor - * @param {string} message Description of the error. - */ - function EncodingError(message) { - this.name = 'EncodingError'; - this.message = message; - this.code = 0; - } - EncodingError.prototype = Error.prototype; - - /** - * @param {boolean} fatal If true, decoding errors raise an exception. - * @param {number=} opt_code_point Override the standard fallback code point. - * @return {number} The code point to insert on a decoding error. - */ - function decoderError(fatal, opt_code_point) { - if (fatal) { - throw new EncodingError('Decoder error'); - } - return opt_code_point || 0xFFFD; - } - - /** - * @param {number} code_point The code point that could not be encoded. - */ - function encoderError(code_point) { - throw new EncodingError('The code point ' + code_point + - ' could not be encoded.'); - } - - /** - * @param {string} label The encoding label. - * @return {?{name:string,labels:Array.}} - */ - function getEncoding(label) { - label = String(label).trim().toLowerCase(); - if (Object.prototype.hasOwnProperty.call(label_to_encoding, label)) { - return label_to_encoding[label]; - } - return null; - } - - /** @type {Array.<{encodings: Array.<{name:string,labels:Array.}>, - * heading: string}>} */ - var encodings = [ - { - "encodings": [ - { - "labels": [ - "unicode-1-1-utf-8", - "utf-8", - "utf8" - ], - "name": "utf-8" - } - ], - "heading": "The Encoding" - } - // XXXfiler - removed non-utf8 aspects - ]; - - var name_to_encoding = {}; - var label_to_encoding = {}; - encodings.forEach(function(category) { - category.encodings.forEach(function(encoding) { - name_to_encoding[encoding.name] = encoding; - encoding.labels.forEach(function(label) { - label_to_encoding[label] = encoding; - }); - }); - }); - - // - // 7. The encoding - // - - // 7.1 utf-8 - - /** - * @constructor - * @param {{fatal: boolean}} options - */ - function UTF8Decoder(options) { - var fatal = options.fatal; - var /** @type {number} */ utf8_code_point = 0, - /** @type {number} */ utf8_bytes_needed = 0, - /** @type {number} */ utf8_bytes_seen = 0, - /** @type {number} */ utf8_lower_boundary = 0; - - /** - * @param {ByteInputStream} byte_pointer The byte stream to decode. - * @return {?number} The next code point decoded, or null if not enough - * data exists in the input stream to decode a complete code point. - */ - this.decode = function(byte_pointer) { - var bite = byte_pointer.get(); - if (bite === EOF_byte) { - if (utf8_bytes_needed !== 0) { - return decoderError(fatal); - } - return EOF_code_point; - } - byte_pointer.offset(1); - - if (utf8_bytes_needed === 0) { - if (inRange(bite, 0x00, 0x7F)) { - return bite; - } - if (inRange(bite, 0xC2, 0xDF)) { - utf8_bytes_needed = 1; - utf8_lower_boundary = 0x80; - utf8_code_point = bite - 0xC0; - } else if (inRange(bite, 0xE0, 0xEF)) { - utf8_bytes_needed = 2; - utf8_lower_boundary = 0x800; - utf8_code_point = bite - 0xE0; - } else if (inRange(bite, 0xF0, 0xF4)) { - utf8_bytes_needed = 3; - utf8_lower_boundary = 0x10000; - utf8_code_point = bite - 0xF0; - } else { - return decoderError(fatal); - } - utf8_code_point = utf8_code_point * Math.pow(64, utf8_bytes_needed); - return null; - } - if (!inRange(bite, 0x80, 0xBF)) { - utf8_code_point = 0; - utf8_bytes_needed = 0; - utf8_bytes_seen = 0; - utf8_lower_boundary = 0; - byte_pointer.offset(-1); - return decoderError(fatal); - } - utf8_bytes_seen += 1; - utf8_code_point = utf8_code_point + (bite - 0x80) * - Math.pow(64, utf8_bytes_needed - utf8_bytes_seen); - if (utf8_bytes_seen !== utf8_bytes_needed) { - return null; - } - var code_point = utf8_code_point; - var lower_boundary = utf8_lower_boundary; - utf8_code_point = 0; - utf8_bytes_needed = 0; - utf8_bytes_seen = 0; - utf8_lower_boundary = 0; - if (inRange(code_point, lower_boundary, 0x10FFFF) && - !inRange(code_point, 0xD800, 0xDFFF)) { - return code_point; - } - return decoderError(fatal); - }; - } - - /** - * @constructor - * @param {{fatal: boolean}} options - */ - function UTF8Encoder(options) { - var fatal = options.fatal; - /** - * @param {ByteOutputStream} output_byte_stream Output byte stream. - * @param {CodePointInputStream} code_point_pointer Input stream. - * @return {number} The last byte emitted. - */ - this.encode = function(output_byte_stream, code_point_pointer) { - var code_point = code_point_pointer.get(); - if (code_point === EOF_code_point) { - return EOF_byte; - } - code_point_pointer.offset(1); - if (inRange(code_point, 0xD800, 0xDFFF)) { - return encoderError(code_point); - } - if (inRange(code_point, 0x0000, 0x007f)) { - return output_byte_stream.emit(code_point); - } - var count, offset; - if (inRange(code_point, 0x0080, 0x07FF)) { - count = 1; - offset = 0xC0; - } else if (inRange(code_point, 0x0800, 0xFFFF)) { - count = 2; - offset = 0xE0; - } else if (inRange(code_point, 0x10000, 0x10FFFF)) { - count = 3; - offset = 0xF0; - } - var result = output_byte_stream.emit( - div(code_point, Math.pow(64, count)) + offset); - while (count > 0) { - var temp = div(code_point, Math.pow(64, count - 1)); - result = output_byte_stream.emit(0x80 + (temp % 64)); - count -= 1; - } - return result; - }; - } - - name_to_encoding['utf-8'].getEncoder = function(options) { - return new UTF8Encoder(options); - }; - name_to_encoding['utf-8'].getDecoder = function(options) { - return new UTF8Decoder(options); - }; - - // - // Implementation of Text Encoding Web API - // - - /** @const */ var DEFAULT_ENCODING = 'utf-8'; - - /** - * @constructor - * @param {string=} opt_encoding The label of the encoding; - * defaults to 'utf-8'. - * @param {{fatal: boolean}=} options - */ - function TextEncoder(opt_encoding, options) { - if (!(this instanceof TextEncoder)) { - throw new TypeError('Constructor cannot be called as a function'); - } - opt_encoding = opt_encoding ? String(opt_encoding) : DEFAULT_ENCODING; - options = Object(options); - /** @private */ - this._encoding = getEncoding(opt_encoding); - if (this._encoding === null || (this._encoding.name !== 'utf-8' && - this._encoding.name !== 'utf-16le' && - this._encoding.name !== 'utf-16be')) - throw new TypeError('Unknown encoding: ' + opt_encoding); - /** @private @type {boolean} */ - this._streaming = false; - /** @private */ - this._encoder = null; - /** @private @type {{fatal: boolean}=} */ - this._options = { fatal: Boolean(options.fatal) }; - - if (Object.defineProperty) { - Object.defineProperty( - this, 'encoding', - { get: function() { return this._encoding.name; } }); - } else { - this.encoding = this._encoding.name; - } - - return this; - } - - TextEncoder.prototype = { - /** - * @param {string=} opt_string The string to encode. - * @param {{stream: boolean}=} options - */ - encode: function encode(opt_string, options) { - opt_string = opt_string ? String(opt_string) : ''; - options = Object(options); - // TODO: any options? - if (!this._streaming) { - this._encoder = this._encoding.getEncoder(this._options); - } - this._streaming = Boolean(options.stream); - - var bytes = []; - var output_stream = new ByteOutputStream(bytes); - var input_stream = new CodePointInputStream(opt_string); - while (input_stream.get() !== EOF_code_point) { - this._encoder.encode(output_stream, input_stream); - } - if (!this._streaming) { - var last_byte; - do { - last_byte = this._encoder.encode(output_stream, input_stream); - } while (last_byte !== EOF_byte); - this._encoder = null; - } - return new Uint8Array(bytes); - } - }; - - - /** - * @constructor - * @param {string=} opt_encoding The label of the encoding; - * defaults to 'utf-8'. - * @param {{fatal: boolean}=} options - */ - function TextDecoder(opt_encoding, options) { - if (!(this instanceof TextDecoder)) { - throw new TypeError('Constructor cannot be called as a function'); - } - opt_encoding = opt_encoding ? String(opt_encoding) : DEFAULT_ENCODING; - options = Object(options); - /** @private */ - this._encoding = getEncoding(opt_encoding); - if (this._encoding === null) - throw new TypeError('Unknown encoding: ' + opt_encoding); - - /** @private @type {boolean} */ - this._streaming = false; - /** @private */ - this._decoder = null; - /** @private @type {{fatal: boolean}=} */ - this._options = { fatal: Boolean(options.fatal) }; - - if (Object.defineProperty) { - Object.defineProperty( - this, 'encoding', - { get: function() { return this._encoding.name; } }); - } else { - this.encoding = this._encoding.name; - } - - return this; - } - - // TODO: Issue if input byte stream is offset by decoder - // TODO: BOM detection will not work if stream header spans multiple calls - // (last N bytes of previous stream may need to be retained?) - TextDecoder.prototype = { - /** - * @param {ArrayBufferView=} opt_view The buffer of bytes to decode. - * @param {{stream: boolean}=} options - */ - decode: function decode(opt_view, options) { - if (opt_view && !('buffer' in opt_view && 'byteOffset' in opt_view && - 'byteLength' in opt_view)) { - throw new TypeError('Expected ArrayBufferView'); - } else if (!opt_view) { - opt_view = new Uint8Array(0); - } - options = Object(options); - - if (!this._streaming) { - this._decoder = this._encoding.getDecoder(this._options); - this._BOMseen = false; - } - this._streaming = Boolean(options.stream); - - var bytes = new Uint8Array(opt_view.buffer, - opt_view.byteOffset, - opt_view.byteLength); - var input_stream = new ByteInputStream(bytes); - - var output_stream = new CodePointOutputStream(), code_point; - while (input_stream.get() !== EOF_byte) { - code_point = this._decoder.decode(input_stream); - if (code_point !== null && code_point !== EOF_code_point) { - output_stream.emit(code_point); - } - } - if (!this._streaming) { - do { - code_point = this._decoder.decode(input_stream); - if (code_point !== null && code_point !== EOF_code_point) { - output_stream.emit(code_point); - } - } while (code_point !== EOF_code_point && - input_stream.get() != EOF_byte); - this._decoder = null; - } - - var result = output_stream.string(); - if (!this._BOMseen && result.length) { - this._BOMseen = true; - if (['utf-8', 'utf-16le', 'utf-16be'].indexOf(this.encoding) !== -1 && - result.charCodeAt(0) === 0xFEFF) { - result = result.substring(1); - } - } - - return result; - } - }; - - // Prefer native impl if available - module.exports = { - TextEncoder: global['TextEncoder'] || TextEncoder, - TextDecoder: global['TextDecoder'] || TextDecoder - }; -}(this)); diff --git a/src/buffer-utils.js b/src/buffer-utils.js deleted file mode 100644 index b97e764..0000000 --- a/src/buffer-utils.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 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 index 582e801..b3f1031 100644 --- a/src/encoding.js +++ b/src/encoding.js @@ -1,16 +1,10 @@ -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); + return buf.toString('utf8'); } function encode(string) { - var u8 = (new TextEncoder('utf8')).encode(string); - return BufferUtils.ensureBuffer(u8); + return new Buffer(string, 'utf8'); } module.exports = { diff --git a/src/filesystem/implementation.js b/src/filesystem/implementation.js index 1da2e0d..5393e07 100644 --- a/src/filesystem/implementation.js +++ b/src/filesystem/implementation.js @@ -31,7 +31,6 @@ 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,6 +640,7 @@ function open_file(context, path, flags, callback) { callback(error); } else { fileData = new Buffer(0); + fileData.fill(0); context.put(fileNode.data, fileData, update_directory_data); } } @@ -675,8 +675,6 @@ 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); @@ -708,8 +706,8 @@ function replace_data(context, ofd, buffer, offset, length, callback) { } else { fileNode = result; var newData = new Buffer(length); - var bufferWindow = buffer.slice(offset, offset + length); - bufferWindow.copy(newData); + newData.fill(0); + buffer.copy(newData, 0, offset, offset + length); ofd.position = length; fileNode.size = length; @@ -726,8 +724,6 @@ 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); @@ -761,11 +757,11 @@ function write_data(context, ofd, buffer, offset, length, position, callback) { var _position = (!(undefined === position || null === position)) ? position : ofd.position; var newSize = Math.max(fileData.length, _position + length); var newData = new Buffer(newSize); + newData.fill(0); if(fileData) { - newData.copy(fileData); + fileData.copy(newData); } - var bufferWindow = buffer.slice(offset, offset + length); - bufferWindow.copy(newData, _position); + buffer.copy(newData, _position, offset, offset + length); if(undefined === position) { ofd.position += length; } @@ -793,8 +789,6 @@ 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); @@ -802,8 +796,7 @@ 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.slice(_position, _position + length); - dataView.copy(buffer, offset); + fileData.copy(buffer, offset, _position, _position + length); if(undefined === position) { ofd.position += length; } @@ -1188,6 +1181,7 @@ function truncate_file(context, path, length, callback) { callback(error); } else { var data = new Buffer(length); + data.fill(0); if(fileData) { fileData.copy(data); } @@ -1244,6 +1238,7 @@ function ftruncate_file(context, ofd, length, callback) { data = fileData.slice(0, length); } else { data = new Buffer(length); + data.fill(0); } context.put(fileNode.data, data, update_file_node); } @@ -1659,6 +1654,7 @@ function readFile(fs, context, path, options, callback) { var stats = new Stats(fstatResult, fs.name); var size = stats.size; var buffer = new Buffer(size); + buffer.fill(0); read_data(context, ofd, buffer, 0, size, 0, function(err3, nbytes) { if(err3) { diff --git a/src/index.js b/src/index.js index 584008a..35e55b4 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ module.exports = { FileSystem: require('./filesystem/interface.js'), + Buffer: Buffer, Path: require('./path.js'), Errors: require('./errors.js') }; diff --git a/src/shell/shell.js b/src/shell/shell.js index 4c66782..d49f4fc 100644 --- a/src/shell/shell.js +++ b/src/shell/shell.js @@ -4,7 +4,7 @@ var Environment = require('./environment.js'); var async = require('../../lib/async.js'); var Network = require('./network.js'); var Zlib = require('../../lib/zip-utils.js'); -var TextEncoder = require('../../lib/encoding.js').TextEncoder; +var Encoding = require('../encoding.js'); function Shell(fs, options) { options = options || {}; @@ -537,10 +537,6 @@ Shell.prototype.zip = function(zipfile, paths, options, callback) { } zipfile = Path.resolve(this.cwd, zipfile); - function encode(s) { - return new TextEncoder('utf8').encode(s); - } - function addFile(path, callback) { fs.readFile(path, function(err, data) { if(err) return callback(err); @@ -556,7 +552,7 @@ Shell.prototype.zip = function(zipfile, paths, options, callback) { fs.readdir(path, function(err, list) { // Add the directory itself (with no data) and a trailing / zip.addFile([], { - filename: encode(path + '/'), + filename: Encoding.encode(path + '/'), compressionMethod: Zlib.Zip.CompressionMethod.STORE }); diff --git a/tests/spec/fs.close.spec.js b/tests/spec/fs.close.spec.js index 5fd9a39..8f09771 100644 --- a/tests/spec/fs.close.spec.js +++ b/tests/spec/fs.close.spec.js @@ -12,7 +12,7 @@ describe('fs.close', function() { }); it('should release the file descriptor', function(done) { - var buffer = new Uint8Array(0); + var buffer = new Filer.Buffer(0); var fs = util.fs(); fs.open('/myfile', 'w+', function(error, result) { diff --git a/tests/spec/fs.lseek.spec.js b/tests/spec/fs.lseek.spec.js index 3d124ea..266e22a 100644 --- a/tests/spec/fs.lseek.spec.js +++ b/tests/spec/fs.lseek.spec.js @@ -48,8 +48,9 @@ describe('fs.lseek', function() { it('should set the current position if whence is SET', function(done) { var fs = util.fs(); var offset = 3; - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); - var result_buffer = new Uint8Array(buffer.length + offset); + var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]); + var result_buffer = new Filer.Buffer(buffer.length + offset); + result_buffer.fill(0); fs.open('/myfile', 'w+', function(error, fd) { if(error) throw error; @@ -71,7 +72,7 @@ describe('fs.lseek', function() { if(error) throw error; expect(result.size).to.equal(offset + buffer.length); - var expected = new Uint8Array([1, 2, 3, 1, 2, 3, 4, 5, 6, 7, 8]); + var expected = new Filer.Buffer([1, 2, 3, 1, 2, 3, 4, 5, 6, 7, 8]); expect(result_buffer).to.deep.equal(expected); done(); }); @@ -85,8 +86,9 @@ describe('fs.lseek', function() { it('should update the current position if whence is CUR', function(done) { var fs = util.fs(); var offset = -2; - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); - var result_buffer = new Uint8Array(2 * buffer.length + offset); + var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]); + var result_buffer = new Filer.Buffer(2 * buffer.length + offset); + result_buffer.fill(0); fs.open('/myfile', 'w+', function(error, fd) { if(error) throw error; @@ -108,7 +110,7 @@ describe('fs.lseek', function() { if(error) throw error; expect(result.size).to.equal(offset + 2 * buffer.length); - var expected = new Uint8Array([1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8]); + var expected = new Filer.Buffer([1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8]); expect(result_buffer).to.deep.equal(expected); done(); }); @@ -122,7 +124,7 @@ describe('fs.lseek', function() { it('should update the current position if whence is END', function(done) { var fs = util.fs(); var offset = 5; - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]); var result_buffer; fs.open('/myfile', 'w+', function(error, result) { @@ -147,10 +149,11 @@ describe('fs.lseek', function() { if(error) throw error; expect(result.size).to.equal(offset + 2 * buffer.length); - result_buffer = new Uint8Array(result.size); + result_buffer = new Filer.Buffer(result.size); + result_buffer.fill(0); fs.read(fd2, result_buffer, 0, result_buffer.length, 0, function(error, result) { if(error) throw error; - var expected = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8]); + var expected = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8]); expect(result_buffer).to.deep.equal(expected); done(); }); diff --git a/tests/spec/fs.read.spec.js b/tests/spec/fs.read.spec.js index e18bdab..7d2bf2b 100644 --- a/tests/spec/fs.read.spec.js +++ b/tests/spec/fs.read.spec.js @@ -13,8 +13,9 @@ describe('fs.read', function() { it('should read data from a file', function(done) { var fs = util.fs(); - var wbuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); - var rbuffer = new Uint8Array(wbuffer.length); + var wbuffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]); + var rbuffer = new Filer.Buffer(wbuffer.length); + rbuffer.fill(0); fs.open('/myfile', 'w+', function(error, fd) { if(error) throw error; @@ -33,8 +34,9 @@ describe('fs.read', function() { it('should update the current file position', function(done) { var fs = util.fs(); - var wbuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); - var rbuffer = new Uint8Array(wbuffer.length); + var wbuffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]); + var rbuffer = new Filer.Buffer(wbuffer.length); + rbuffer.fill(0); var _result = 0; fs.open('/myfile', 'w+', function(error, fd) { diff --git a/tests/spec/fs.write.spec.js b/tests/spec/fs.write.spec.js index 7e1896f..afc67af 100644 --- a/tests/spec/fs.write.spec.js +++ b/tests/spec/fs.write.spec.js @@ -13,7 +13,7 @@ describe('fs.write', function() { it('should write data to a file', function(done) { var fs = util.fs(); - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]); fs.open('/myfile', 'w', function(error, fd) { if(error) throw error; @@ -34,7 +34,7 @@ describe('fs.write', function() { it('should update the current file position', function(done) { var fs = util.fs(); - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]); var _result = 0; fs.open('/myfile', 'w', function(error, fd) { diff --git a/tests/spec/times.spec.js b/tests/spec/times.spec.js index 68ea719..f64cf7f 100644 --- a/tests/spec/times.spec.js +++ b/tests/spec/times.spec.js @@ -355,7 +355,7 @@ describe('node times (atime, mtime, ctime)', function() { it('should update atime, ctime, mtime when calling fs.write()', function(done) { var fs = util.fs(); - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]); createTree(function() { fs.open('/myfile', 'w', function(err, fd) { @@ -383,7 +383,7 @@ describe('node times (atime, mtime, ctime)', function() { it('should make no change when calling fs.read()', function(done) { var fs = util.fs(); - var buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); + var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]); createTree(function() { fs.open('/myfile', 'w', function(err, fd) { @@ -399,7 +399,8 @@ describe('node times (atime, mtime, ctime)', function() { if(error) throw error; stat('/myfile', function(stats1) { - var buffer2 = new Uint8Array(buffer.length); + var buffer2 = new Filer.Buffer(buffer.length); + buffer2.fill(0); fs.read(fd, buffer2, 0, buffer2.length, 0, function(err, nbytes) { fs.close(fd, function(error) { From c8dcd2d14a0b3bb051ef749a9008353aec6e1f07 Mon Sep 17 00:00:00 2001 From: "David Humphrey (:humph) david.humphrey@senecacollege.ca" Date: Fri, 6 Jun 2014 11:41:26 -0400 Subject: [PATCH 3/4] Switch to build-time check vs run-time for request module in browserify --- package.json | 6 ++++- src/shell/network.js | 57 ++++++++------------------------------------ src/shell/shell.js | 2 +- 3 files changed, 16 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index e1c2e8c..0766c34 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,13 @@ "type": "git", "url": "https://github.com/js-platform/filer.git" }, + "browser": { + "request": "browser-request" + }, "dependencies": { "bower": "~1.0.0", - "request": "^2.36.0" + "request": "^2.36.0", + "browser-request": "^0.3.1" }, "devDependencies": { "chai": "~1.9.1", diff --git a/src/shell/network.js b/src/shell/network.js index 3c68fb8..c018423 100644 --- a/src/shell/network.js +++ b/src/shell/network.js @@ -1,59 +1,22 @@ -function browserDownload(uri, callback) { - var query = new XMLHttpRequest(); - query.onload = function() { - var err = query.status != 200 ? { message: query.statusText, code: query.status } : null, - data = err ? null : new Uint8Array(query.response); +var request = require('request'); - callback(err, data); - }; - query.open("GET", uri); - if("withCredentials" in query) { - query.withCredentials = true; - } - - query.responseType = "arraybuffer"; - query.send(); -} - -function nodeDownload(uri, callback) { - require('request')({ +module.exports.download = function(uri, callback) { + request({ url: uri, method: "GET", encoding: null }, function(err, msg, body) { - var data = null, - arrayBuffer, - statusCode, - arrayLength = body && body.length, - error; + var statusCode; + var error; msg = msg || null; statusCode = msg && msg.statusCode; - - error = statusCode != 200 ? { message: err || 'Not found!', code: statusCode } : null; + error = statusCode !== 200 ? { message: err || 'Not found!', code: statusCode } : null; if (error) { - return callback(error, null); + callback(error, null); + return; } - - arrayBuffer = arrayLength && new ArrayBuffer(arrayLength); - - // Convert buffer to Uint8Array - if (arrayBuffer && (statusCode == 200)) { - data = new Uint8Array(arrayBuffer); - for (var i = 0; i < body.length; ++i) { - data[i] = body[i]; - } - } - - callback(null, data); + callback(null, body); }); -} - -module.exports.download = (function() { - if (typeof XMLHttpRequest === 'undefined') { - return nodeDownload; - } else { - return browserDownload; - } -}()); +}; diff --git a/src/shell/shell.js b/src/shell/shell.js index d49f4fc..15bf5f8 100644 --- a/src/shell/shell.js +++ b/src/shell/shell.js @@ -543,7 +543,7 @@ Shell.prototype.zip = function(zipfile, paths, options, callback) { // Make path relative within the zip var relpath = path.replace(/^\//, ''); - zip.addFile(data, { filename: encode(relpath) }); + zip.addFile(data, { filename: Encoding.encode(relpath) }); callback(); }); } From 939d015e6d905eb3c355eadff4829ed95b36b87d Mon Sep 17 00:00:00 2001 From: "David Humphrey (:humph) david.humphrey@senecacollege.ca" Date: Fri, 6 Jun 2014 21:29:09 -0400 Subject: [PATCH 4/4] All tests passing, replaced zlib.js with jszip, upstream fixes to browser-request + jszip for Buffers --- lib/zip-utils.js | 73 ------------------------------------------- package.json | 3 +- src/shell/network.js | 2 +- src/shell/shell.js | 48 ++++++++++++++-------------- tests/test-dir.zip | Bin 1004 -> 1004 bytes 5 files changed, 28 insertions(+), 98 deletions(-) delete mode 100644 lib/zip-utils.js diff --git a/lib/zip-utils.js b/lib/zip-utils.js deleted file mode 100644 index 5a55c3a..0000000 --- a/lib/zip-utils.js +++ /dev/null @@ -1,73 +0,0 @@ -var ZlibNamespace = {}; - -/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var n=void 0,y=!0,aa=this;function G(e,b){var a=e.split("."),d=aa;!(a[0]in d)&&d.execScript&&d.execScript("var "+a[0]);for(var c;a.length&&(c=a.shift());)!a.length&&b!==n?d[c]=b:d=d[c]?d[c]:d[c]={}};var H="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function ba(e,b){this.index="number"===typeof b?b:0;this.f=0;this.buffer=e instanceof(H?Uint8Array:Array)?e:new (H?Uint8Array:Array)(32768);if(2*this.buffer.length<=this.index)throw Error("invalid index");this.buffer.length<=this.index&&ca(this)}function ca(e){var b=e.buffer,a,d=b.length,c=new (H?Uint8Array:Array)(d<<1);if(H)c.set(b);else for(a=0;a>>8&255]<<16|L[e>>>16&255]<<8|L[e>>>24&255])>>32-b:L[e]>>8-b);if(8>b+f)l=l<>b-p-1&1,8===++f&&(f=0,d[c++]=L[l],l=0,c===d.length&&(d=ca(this)));d[c]=l;this.buffer=d;this.f=f;this.index=c};ba.prototype.finish=function(){var e=this.buffer,b=this.index,a;0ha;++ha){for(var U=ha,ja=U,ka=7,U=U>>>1;U;U>>>=1)ja<<=1,ja|=U&1,--ka;da[ha]=(ja<>>0}var L=da;function la(e){var b=n,a,d="number"===typeof b?b:b=0,c=e.length;a=-1;for(d=c&7;d--;++b)a=a>>>8^V[(a^e[b])&255];for(d=c>>3;d--;b+=8)a=a>>>8^V[(a^e[b])&255],a=a>>>8^V[(a^e[b+1])&255],a=a>>>8^V[(a^e[b+2])&255],a=a>>>8^V[(a^e[b+3])&255],a=a>>>8^V[(a^e[b+4])&255],a=a>>>8^V[(a^e[b+5])&255],a=a>>>8^V[(a^e[b+6])&255],a=a>>>8^V[(a^e[b+7])&255];return(a^4294967295)>>>0} -var ma=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759, -2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977, -2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755, -2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956, -3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270, -936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],V=H?new Uint32Array(ma):ma;function na(e){this.buffer=new (H?Uint16Array:Array)(2*e);this.length=0}na.prototype.getParent=function(e){return 2*((e-2)/4|0)};na.prototype.push=function(e,b){var a,d,c=this.buffer,f;a=this.length;c[this.length++]=b;for(c[this.length++]=e;0c[d])f=c[a],c[a]=c[d],c[d]=f,f=c[a+1],c[a+1]=c[d+1],c[d+1]=f,a=d;else break;return this.length}; -na.prototype.pop=function(){var e,b,a=this.buffer,d,c,f;b=a[0];e=a[1];this.length-=2;a[0]=a[this.length];a[1]=a[this.length+1];for(f=0;;){c=2*f+2;if(c>=this.length)break;c+2a[c]&&(c+=2);if(a[c]>a[f])d=a[f],a[f]=a[c],a[c]=d,d=a[f+1],a[f+1]=a[c+1],a[c+1]=d;else break;f=c}return{index:e,value:b,length:this.length}};function pa(e,b){this.k=qa;this.l=0;this.input=H&&e instanceof Array?new Uint8Array(e):e;this.e=0;b&&(b.lazy&&(this.l=b.lazy),"number"===typeof b.compressionType&&(this.k=b.compressionType),b.outputBuffer&&(this.c=H&&b.outputBuffer instanceof Array?new Uint8Array(b.outputBuffer):b.outputBuffer),"number"===typeof b.outputIndex&&(this.e=b.outputIndex));this.c||(this.c=new (H?Uint8Array:Array)(32768))}var qa=2,sa=[],Y; -for(Y=0;288>Y;Y++)switch(y){case 143>=Y:sa.push([Y+48,8]);break;case 255>=Y:sa.push([Y-144+400,9]);break;case 279>=Y:sa.push([Y-256+0,7]);break;case 287>=Y:sa.push([Y-280+192,8]);break;default:throw"invalid literal: "+Y;} -pa.prototype.g=function(){var e,b,a,d,c=this.input;switch(this.k){case 0:a=0;for(d=c.length;a>>8&255;m[h++]=q&255;m[h++]=q>>>8&255;if(H)m.set(f,h),h+=f.length,m=m.subarray(0,h);else{w=0;for(u=f.length;wx)for(;0x?x:138,E>x-3&&E=E?(M[K++]=17,M[K++]=E-3,S[17]++):(M[K++]=18,M[K++]=E-11,S[18]++),x-=E;else if(M[K++]=P[v],S[P[v]]++,x--,3>x)for(;0x?x:6,E>x-3&&ED;D++)oa[D]=X[g[D]];for(C=19;4=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272, -a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:throw"invalid length: "+a;}}var b=[],a,d;for(a=3;258>=a;a++)d=e(a),b[a]=d[2]<<24| -d[1]<<16|d[0];return b}(),Ja=H?new Uint32Array(xa):xa; -function ta(e,b){function a(a,c){var b=a.n,d=[],e=0,f;f=Ja[a.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(y){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b- -65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>= -b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:throw"invalid distance";}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var k,l;k=0;for(l=d.length;k=f;)t[f++]=0;for(f=0;29>=f;)r[f++]=0}t[256]=1;d=0;for(c=b.length;d=c){u&&a(u,-1);f=0;for(l=c-d;fl&&b+lf&&(c=d,f=l);if(258===l)break}return new wa(f,b-c)} -function ua(e,b){var a=e.length,d=new na(572),c=new (H?Uint8Array:Array)(a),f,l,p,k,q;if(!H)for(k=0;k2*c[h-1]+f[h]&&(c[h]=2*c[h-1]+f[h]),p[h]=Array(c[h]),k[h]=Array(c[h]);for(m=0;me[m]?(p[h][s]=t,k[h][s]=b,r+=2):(p[h][s]=e[m],k[h][s]=m,++m);q[h]=0;1===f[h]&&d(h)}return l} -function va(e){var b=new (H?Uint16Array:Array)(e.length),a=[],d=[],c=0,f,l,p,k;f=0;for(l=e.length;f>>=1}return b};function $(e){e=e||{};this.files=[];this.d=e.comment}var Ma=[80,75,1,2],Na=[80,75,3,4],Oa=[80,75,5,6];$.prototype.m=function(e,b){b=b||{};var a,d=e.length,c=0;H&&e instanceof Array&&(e=new Uint8Array(e));"number"!==typeof b.compressionMethod&&(b.compressionMethod=8);if(b.compress)switch(b.compressionMethod){case 0:break;case 8:c=la(e);e=(new pa(e,b.deflateOption)).g();a=y;break;default:throw Error("unknown compression method:"+b.compressionMethod);}this.files.push({buffer:e,a:b,j:a,r:!1,size:d,h:c})}; -$.prototype.q=function(e){this.i=e}; -$.prototype.g=function(){var e=this.files,b,a,d,c,f,l=0,p=0,k,q,w,u,m,h,s,t,r,Q,z,A,F,I,N,B,C,g,J;B=0;for(C=e.length;Bg;++g)F[g]=Qa(N,11===B?b.h&255:256*Math.random()|0);for(J=F.length;g>8&255;w=b.a.compressionMethod;a[d++]=a[c++]=w&255;a[d++]=a[c++]=w>>8&255;u=b.a.date||new Date;a[d++]=a[c++]=(u.getMinutes()&7)<<5|u.getSeconds()/2|0;a[d++]=a[c++]=u.getHours()<<3|u.getMinutes()>>3;a[d++]=a[c++]=(u.getMonth()+1&7)<<5|u.getDate();a[d++]=a[c++]=(u.getFullYear()- -1980&127)<<1|u.getMonth()+1>>3;m=b.h;a[d++]=a[c++]=m&255;a[d++]=a[c++]=m>>8&255;a[d++]=a[c++]=m>>16&255;a[d++]=a[c++]=m>>24&255;h=b.buffer.length;a[d++]=a[c++]=h&255;a[d++]=a[c++]=h>>8&255;a[d++]=a[c++]=h>>16&255;a[d++]=a[c++]=h>>24&255;s=b.size;a[d++]=a[c++]=s&255;a[d++]=a[c++]=s>>8&255;a[d++]=a[c++]=s>>16&255;a[d++]=a[c++]=s>>24&255;a[d++]=a[c++]=t&255;a[d++]=a[c++]=t>>8&255;a[d++]=a[c++]=0;a[d++]=a[c++]=0;a[c++]=r&255;a[c++]=r>>8&255;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]= -0;a[c++]=0;a[c++]=k&255;a[c++]=k>>8&255;a[c++]=k>>16&255;a[c++]=k>>24&255;if(Q=b.a.filename)if(H)a.set(Q,d),a.set(Q,c),d+=t,c+=t;else for(g=0;g>8&255;a[f++]=C&255;a[f++]=C>>8&255;a[f++]=p&255;a[f++]=p>>8&255;a[f++]=p>>16&255;a[f++]=p>>24&255;a[f++]=l&255;a[f++]=l>>8&255;a[f++]=l>>16&255;a[f++]=l>>24&255;r=this.d?this.d.length:0;a[f++]=r&255;a[f++]=r>>8&255;if(this.d)if(H)a.set(this.d,f);else{g=0;for(J=r;g>8&255;Pa(e,b);return a^b} -function Pa(e,b){e[0]=(V[(e[0]^b)&255]^e[0]>>>8)>>>0;e[1]=(6681*(20173*(e[1]+(e[0]&255))>>>0)>>>0)+1>>>0;e[2]=(V[(e[2]^e[1]>>>24)&255]^e[2]>>>8)>>>0};function Ra(e,b){var a,d,c,f;if(Object.keys)a=Object.keys(b);else for(d in a=[],c=0,b)a[c++]=d;c=0;for(f=a.length;cx;++x)for(var y=x,ba=7,y=y>>>1;y;y>>>=1)--ba;var z=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759, -2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977, -2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755, -2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956, -3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270, -936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],B=w?new Uint32Array(z):z;function C(a){var b=a.length,c=0,d=Number.POSITIVE_INFINITY,f,h,k,e,g,l,p,s,r,A;for(s=0;sc&&(c=a[s]),a[s]>=1;A=k<<16|s;for(r=l;rE;E++)switch(!0){case 143>=E:D.push([E+48,8]);break;case 255>=E:D.push([E-144+400,9]);break;case 279>=E:D.push([E-256+0,7]);break;case 287>=E:D.push([E-280+192,8]);break;default:m("invalid literal: "+E)} -var ca=function(){function a(a){switch(!0){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272, -a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:m("invalid length: "+a)}}var b=[],c,d;for(c=3;258>=c;c++)d=a(c),b[c]=d[2]<<24|d[1]<< -16|d[0];return b}();w&&new Uint32Array(ca);function F(a,b){this.l=[];this.m=32768;this.d=this.f=this.c=this.t=0;this.input=w?new Uint8Array(a):a;this.u=!1;this.n=G;this.L=!1;if(b||!(b={}))b.index&&(this.c=b.index),b.bufferSize&&(this.m=b.bufferSize),b.bufferType&&(this.n=b.bufferType),b.resize&&(this.L=b.resize);switch(this.n){case H:this.a=32768;this.b=new (w?Uint8Array:Array)(32768+this.m+258);break;case G:this.a=0;this.b=new (w?Uint8Array:Array)(this.m);this.e=this.X;this.B=this.S;this.q=this.W;break;default:m(Error("invalid inflate mode"))}} -var H=0,G=1; -F.prototype.r=function(){for(;!this.u;){var a=I(this,3);a&1&&(this.u=!0);a>>>=1;switch(a){case 0:var b=this.input,c=this.c,d=this.b,f=this.a,h=b.length,k=q,e=q,g=d.length,l=q;this.d=this.f=0;c+1>=h&&m(Error("invalid uncompressed block header: LEN"));k=b[c++]|b[c++]<<8;c+1>=h&&m(Error("invalid uncompressed block header: NLEN"));e=b[c++]|b[c++]<<8;k===~e&&m(Error("invalid uncompressed block header: length verify"));c+k>b.length&&m(Error("input buffer is broken"));switch(this.n){case H:for(;f+k>d.length;){l= -g-f;k-=l;if(w)d.set(b.subarray(c,c+l),f),f+=l,c+=l;else for(;l--;)d[f++]=b[c++];this.a=f;d=this.e();f=this.a}break;case G:for(;f+k>d.length;)d=this.e({H:2});break;default:m(Error("invalid inflate mode"))}if(w)d.set(b.subarray(c,c+k),f),f+=k,c+=k;else for(;k--;)d[f++]=b[c++];this.c=c;this.a=f;this.b=d;break;case 1:this.q(da,ea);break;case 2:fa(this);break;default:m(Error("unknown BTYPE: "+a))}}return this.B()}; -var J=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],K=w?new Uint16Array(J):J,L=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],M=w?new Uint16Array(L):L,ga=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],O=w?new Uint8Array(ga):ga,ha=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],ia=w?new Uint16Array(ha):ha,ja=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11, -12,12,13,13],P=w?new Uint8Array(ja):ja,Q=new (w?Uint8Array:Array)(288),R,la;R=0;for(la=Q.length;R=R?8:255>=R?9:279>=R?7:8;var da=C(Q),S=new (w?Uint8Array:Array)(30),T,ma;T=0;for(ma=S.length;T=k&&m(Error("input buffer is broken")),c|=f[h++]<>>b;a.d=d-b;a.c=h;return e} -function U(a,b){for(var c=a.f,d=a.d,f=a.input,h=a.c,k=f.length,e=b[0],g=b[1],l,p;d=k);)c|=f[h++]<>>16;a.f=c>>p;a.d=d-p;a.c=h;return l&65535} -function fa(a){function b(a,b,c){var d,e=this.K,f,g;for(g=0;gh)d>=f&&(this.a=d,c=this.e(),d=this.a),c[d++]=h;else{k=h-257;g=M[k];0=f&&(this.a=d,c=this.e(),d=this.a);for(;g--;)c[d]=c[d++-e]}for(;8<=this.d;)this.d-=8,this.c--;this.a=d}; -u.W=function(a,b){var c=this.b,d=this.a;this.C=a;for(var f=c.length,h,k,e,g;256!==(h=U(this,a));)if(256>h)d>=f&&(c=this.e(),f=c.length),c[d++]=h;else{k=h-257;g=M[k];0f&&(c=this.e(),f=c.length);for(;g--;)c[d]=c[d++-e]}for(;8<=this.d;)this.d-=8,this.c--;this.a=d}; -u.e=function(){var a=new (w?Uint8Array:Array)(this.a-32768),b=this.a-32768,c,d,f=this.b;if(w)a.set(f.subarray(32768,a.length));else{c=0;for(d=a.length;cc;++c)f[c]=f[b+c];this.a=32768;return f}; -u.X=function(a){var b,c=this.input.length/this.c+1|0,d,f,h,k=this.input,e=this.b;a&&("number"===typeof a.H&&(c=a.H),"number"===typeof a.Q&&(c+=a.Q));2>c?(d=(k.length-this.c)/this.C[2],h=258*(d/2)|0,f=hb&&(this.b.length=b),a=this.b);return this.buffer=a};function V(a){a=a||{};this.files=[];this.v=a.comment}V.prototype.M=function(a){this.j=a};V.prototype.s=function(a){var b=a[2]&65535|2;return b*(b^1)>>8&255};V.prototype.k=function(a,b){a[0]=(B[(a[0]^b)&255]^a[0]>>>8)>>>0;a[1]=(6681*(20173*(a[1]+(a[0]&255))>>>0)>>>0)+1>>>0;a[2]=(B[(a[2]^a[1]>>>24)&255]^a[2]>>>8)>>>0};V.prototype.U=function(a){var b=[305419896,591751049,878082192],c,d;w&&(b=new Uint32Array(b));c=0;for(d=a.length;c>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<< -8;this.g=a[b++]|a[b++]<<8;this.F=a[b++]|a[b++]<<8;this.fa=a[b++]|a[b++]<<8;this.ha=a[b++]|a[b++]<<8;this.ga=a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24;this.aa=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.filename=String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.v=w?a.subarray(b,b+this.F):a.slice(b,b+this.F);this.length=b-this.offset};function pa(a,b){this.input=a;this.offset=b}var qa={O:1,da:8,ea:2048}; -pa.prototype.parse=function(){var a=this.input,b=this.offset;(a[b++]!==Y[0]||a[b++]!==Y[1]||a[b++]!==Y[2]||a[b++]!==Y[3])&&m(Error("invalid local file header signature"));this.$=a[b++]|a[b++]<<8;this.I=a[b++]|a[b++]<<8;this.A=a[b++]|a[b++]<<8;this.time=a[b++]|a[b++]<<8;this.V=a[b++]|a[b++]<<8;this.p=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<<8;this.g=a[b++]|a[b++]<<8;this.filename= -String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.length=b-this.offset}; -function $(a){var b=[],c={},d,f,h,k;if(!a.i){if(a.o===q){var e=a.input,g;if(!a.D)a:{var l=a.input,p;for(p=l.length-12;0>>0;a.o=(e[g++]| -e[g++]<<8|e[g++]<<16|e[g++]<<24)>>>0;a.w=e[g++]|e[g++]<<8;a.v=w?e.subarray(g,g+a.w):e.slice(g,g+a.w)}d=a.o;h=0;for(k=a.ba;h>>8^B[(n^l[t])&255];for(N=ka>>3;N--;t+=8)n=n>>>8^B[(n^l[t])&255],n=n>>>8^B[(n^l[t+1])&255],n=n>>>8^B[(n^l[t+2])&255],n=n>>>8^B[(n^l[t+3])&255],n=n>>>8^B[(n^l[t+4])&255],n=n>>>8^B[(n^l[t+5])&255],n=n>>>8^B[(n^l[t+6])&255],n=n>>>8^B[(n^l[t+7])&255];p=(n^4294967295)>>>0;k.p!==p&&m(Error("wrong crc: file=0x"+ -k.p.toString(16)+", data=0x"+p.toString(16)))}return l};u.M=function(a){this.j=a};function ra(a,b,c){c^=a.s(b);a.k(b,c);return c}u.k=V.prototype.k;u.T=V.prototype.U;u.s=V.prototype.s;v("Zlib.Unzip",W);v("Zlib.Unzip.prototype.decompress",W.prototype.r);v("Zlib.Unzip.prototype.getFilenames",W.prototype.Z);v("Zlib.Unzip.prototype.setPassword",W.prototype.M);}).call(ZlibNamespace); - -module.exports = ZlibNamespace.Zlib; diff --git a/package.json b/package.json index 0766c34..b8cf9a5 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "dependencies": { "bower": "~1.0.0", "request": "^2.36.0", - "browser-request": "^0.3.1" + "browser-request": "git://github.com/humphd/browser-request.git#959ea95bf200d64939ed76897d3b06bb684f3a0d", + "jszip": "git://github.com/humphd/jszip.git#ad3f356bb165aba1cafeabe1bb3e49293803f975" }, "devDependencies": { "chai": "~1.9.1", diff --git a/src/shell/network.js b/src/shell/network.js index c018423..1cc7ea0 100644 --- a/src/shell/network.js +++ b/src/shell/network.js @@ -3,7 +3,7 @@ var request = require('request'); module.exports.download = function(uri, callback) { request({ url: uri, - method: "GET", + method: 'GET', encoding: null }, function(err, msg, body) { var statusCode; diff --git a/src/shell/shell.js b/src/shell/shell.js index 15bf5f8..648b2fa 100644 --- a/src/shell/shell.js +++ b/src/shell/shell.js @@ -3,8 +3,8 @@ var Errors = require('../errors.js'); var Environment = require('./environment.js'); var async = require('../../lib/async.js'); var Network = require('./network.js'); -var Zlib = require('../../lib/zip-utils.js'); var Encoding = require('../encoding.js'); +var JSZip = require('jszip'); function Shell(fs, options) { options = options || {}; @@ -489,24 +489,24 @@ Shell.prototype.unzip = function(zipfile, options, callback) { fs.readFile(path, function(err, data) { if(err) return callback(err); - var unzip = new Zlib.Unzip(data); + var zip = new JSZip(data); + var filenames = []; + zip.filter(function(relPath, file) { + var isDir = file.options.dir; + var data = isDir ? null : file.asNodeBuffer(); - // Separate filenames within the zip archive with what will go in fs. - // Also mark any directories (i.e., paths with a trailing '/') - var filenames = unzip.getFilenames().map(function(filename) { - return { - zipFilename: filename, - fsFilename: Path.join(destination, filename), - isDirectory: /\/$/.test(filename) - }; + filenames.push({ + absPath: Path.join(destination, file.name), + isDirectory: isDir, + data: data + }); }); function decompress(path, callback) { - var data = unzip.decompress(path.zipFilename); if(path.isDirectory) { - sh.mkdirp(path.fsFilename, callback); + sh.mkdirp(path.absPath, callback); } else { - fs.writeFile(path.fsFilename, data, callback); + fs.writeFile(path.absPath, path.data, callback); } } @@ -537,24 +537,24 @@ Shell.prototype.zip = function(zipfile, paths, options, callback) { } zipfile = Path.resolve(this.cwd, zipfile); + function toRelPath(path) { + // Make path relative within the zip + return path.replace(/^\//, ''); + } + function addFile(path, callback) { fs.readFile(path, function(err, data) { if(err) return callback(err); - // Make path relative within the zip - var relpath = path.replace(/^\//, ''); - zip.addFile(data, { filename: Encoding.encode(relpath) }); + zip.file(toRelPath(path), data, {binary: true}); callback(); }); } function addDir(path, callback) { fs.readdir(path, function(err, list) { - // Add the directory itself (with no data) and a trailing / - zip.addFile([], { - filename: Encoding.encode(path + '/'), - compressionMethod: Zlib.Zip.CompressionMethod.STORE - }); + // Add the directory itself + zip.folder(toRelPath(path)); if(!options.recursive) { callback(); @@ -580,7 +580,7 @@ Shell.prototype.zip = function(zipfile, paths, options, callback) { }); } - var zip = new Zlib.Zip(); + var zip = new JSZip(); // Make sure the zipfile doesn't already exist. fs.stat(zipfile, function(err, stats) { @@ -591,7 +591,9 @@ Shell.prototype.zip = function(zipfile, paths, options, callback) { async.eachSeries(paths, add, function(err) { if(err) return callback(err); - var compressed = zip.compress(); + var compressed; + compressed = zip.generate({type: 'nodebuffer'}); + fs.writeFile(zipfile, compressed, callback); }); }); diff --git a/tests/test-dir.zip b/tests/test-dir.zip index 0e41eca0f4915048f573c1a749b0c05279224776..307f25377cc288ed46d0e9b1d35cb0b4bf106574 100644 GIT binary patch delta 123 zcmaFE{)T;mfk2_xq~OvDZU#n{uZ#=~EDRGJY%#@pBN-VcKVUSREWzjnWldr92D7Sw pWHeI*klezQ3M8eNqk&`@bBq)N5CnL$vVmw;AUqB