Skip to content

[Fix] io.js 3.0 - Node.js 5.3 typed array support #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 54 additions & 29 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,42 +28,67 @@ var useArrayBuffer = typeof ArrayBuffer !== 'undefined'
&& ArrayBuffer.isView
&& (Buffer.prototype instanceof Uint8Array || Buffer.TYPED_ARRAY_SUPPORT);

CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
var bufferData;
function toBuffer(data, encoding) {
/*
* No need to do anything for exact instance
* This is only valid when safe-buffer.Buffer === buffer.Buffer, i.e. when Buffer.from/Buffer.alloc existed
*/
if (data instanceof Buffer) {
// No need to do anything
bufferData = data;
} else if (typeof data === 'string') {
// Convert strings to Buffer
bufferData = Buffer.from(data, inputEnc);
} else if (useArrayBuffer && ArrayBuffer.isView(data)) {
/*
* Wrap any TypedArray instances and DataViews
* Makes sense only on engines with full TypedArray support -- let Buffer detect that
*/
bufferData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
} else if (useUint8Array && data instanceof Uint8Array) {
return data;
}

// Convert strings to Buffer
if (typeof data === 'string') {
return Buffer.from(data, encoding);
}

/*
* Wrap any TypedArray instances and DataViews
* Makes sense only on engines with full TypedArray support -- let Buffer detect that
*/
if (useArrayBuffer && ArrayBuffer.isView(data)) {
// Bug in Node.js <6.3.1, which treats this as out-of-bounds
if (data.byteLength === 0) {
return Buffer.alloc(0);
}

var res = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
/*
* Uint8Array in engines where Buffer.from might not work with ArrayBuffer, just copy over
* Doesn't make sense with other TypedArray instances
* Recheck result size, as offset/length doesn't work on Node.js <5.10
* We just go to Uint8Array case if this fails
*/
bufferData = Buffer.from(data);
} else if (
if (res.byteLength === data.byteLength) {
return res;
}
}

/*
* Uint8Array in engines where Buffer.from might not work with ArrayBuffer, just copy over
* Doesn't make sense with other TypedArray instances
*/
if (useUint8Array && data instanceof Uint8Array) {
return Buffer.from(data);
}

/*
* Old Buffer polyfill on an engine that doesn't have TypedArray support
* Also, this is from a different Buffer polyfill implementation then we have, as instanceof check failed
* Convert to our current Buffer implementation
*/
if (
Buffer.isBuffer(data)
&& data.constructor
&& data.constructor.isBuffer
&& data.constructor.isBuffer(data)
&& data.constructor
&& typeof data.constructor.isBuffer === 'function'
&& data.constructor.isBuffer(data)
) {
/*
* Old Buffer polyfill on an engine that doesn't have TypedArray support
* Also, this is from a different Buffer polyfill implementation then we have, as instanceof check failed
* Convert to our current Buffer implementation
*/
bufferData = Buffer.from(data);
} else {
throw new Error('The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView.');
return Buffer.from(data);
}

throw new TypeError('The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView.');
}

CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
var bufferData = toBuffer(data, inputEnc); // asserts correct input type
var outData = this._update(bufferData);
if (this.hashMode) {
return this;
Expand Down
66 changes: 66 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,72 @@ test('encodings', function (t) {
});
});

test('handle SafeBuffer instances', function (t) {
function Cipher() {
CipherBase.call(this, 'finalName');
this._cache = [];
}
inherits(Cipher, CipherBase);
Cipher.prototype._update = function (input) {
t.ok(Buffer.isBuffer(input));
this._cache.push(input);
};
Cipher.prototype._final = function () {
return Buffer.concat(this._cache);
};

var cipher = new Cipher();
var final = cipher.update(Buffer.from('a0c1', 'hex')).finalName('hex');
t.equals(final, 'a0c1');

t.end();
});

test('handle Uint8Array view', function (t) {
function Cipher() {
CipherBase.call(this, 'finalName');
this._cache = [];
}
inherits(Cipher, CipherBase);
Cipher.prototype._update = function (input) {
t.ok(Buffer.isBuffer(input));
this._cache.push(input);
};
Cipher.prototype._final = function () {
return Buffer.concat(this._cache);
};

var buf = new Uint8Array([0, 1, 2, 3, 4, 5]);
var uarr = new Uint8Array(buf.buffer, 2, 3);

var cipher = new Cipher();
var final = cipher.update(uarr).finalName('hex');
t.equals(final, '020304');

t.end();
});

test('handle empty Uint8Array instances', function (t) {
function Cipher() {
CipherBase.call(this, 'finalName');
this._cache = [];
}
inherits(Cipher, CipherBase);
Cipher.prototype._update = function (input) {
t.ok(Buffer.isBuffer(input));
this._cache.push(input);
};
Cipher.prototype._final = function () {
return Buffer.concat(this._cache);
};

var cipher = new Cipher();
var final = cipher.update(new Uint8Array(0)).finalName('hex');
t.equals(final, '');

t.end();
});

test('handle UInt16Array', function (t) {
function Cipher() {
CipherBase.call(this, 'finalName');
Expand Down
Loading