Skip to content

Commit

Permalink
[Fix] io.js 3.0 - Node.js 5.3 typed array support
Browse files Browse the repository at this point in the history
  • Loading branch information
ChALkeR authored and ljharb committed Nov 20, 2024
1 parent f03cebf commit b7ddd2a
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 29 deletions.
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

0 comments on commit b7ddd2a

Please sign in to comment.