Browse Source

buffer: allow ArrayBuffer as Buffer argument

Buffer now uses the ArrayBuffer as the backing store if passed to the
constructor.

Fixes: https://github.com/nodejs/io.js/issues/106
PR-URL: https://github.com/nodejs/io.js/pull/2002
Reviewed-By: Domenic Denicola <d@domenic.me>
v4.0.0-rc
Trevor Norris 10 years ago
committed by Rod Vagg
parent
commit
4643b8b667
  1. 5
      lib/internal/buffer_new.js
  2. 15
      src/node_buffer.cc
  3. 46
      test/parallel/test-buffer-arraybuffer.js

5
lib/internal/buffer_new.js

@ -104,7 +104,10 @@ function fromObject(obj) {
return b; return b;
} }
// TODO(trevnorris): This will fail for an actual ArrayBuffer. if (obj instanceof ArrayBuffer) {
return binding.createFromArrayBuffer(obj);
}
if (obj.buffer instanceof ArrayBuffer || obj.length) { if (obj.buffer instanceof ArrayBuffer || obj.length) {
var length; var length;
if (typeof obj.length !== 'number' || obj.length !== obj.length) if (typeof obj.length !== 'number' || obj.length !== obj.length)

15
src/node_buffer.cc

@ -528,6 +528,20 @@ void CreateFromString(const FunctionCallbackInfo<Value>& args) {
} }
void CreateFromArrayBuffer(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
if (!args[0]->IsArrayBuffer())
return env->ThrowTypeError("argument is not an ArrayBuffer");
Local<ArrayBuffer> ab = args[0].As<ArrayBuffer>();
Local<Uint8Array> ui = Uint8Array::New(ab, 0, ab->ByteLength());
Maybe<bool> mb =
ui->SetPrototype(env->context(), env->buffer_prototype_object());
if (!mb.FromMaybe(false))
return env->ThrowError("Unable to set Object prototype");
args.GetReturnValue().Set(ui);
}
void Slice(const FunctionCallbackInfo<Value>& args) { void Slice(const FunctionCallbackInfo<Value>& args) {
CHECK(args[0]->IsUint8Array()); CHECK(args[0]->IsUint8Array());
CHECK(args[1]->IsNumber()); CHECK(args[1]->IsNumber());
@ -1171,6 +1185,7 @@ void Initialize(Handle<Object> target,
env->SetMethod(target, "setupBufferJS", SetupBufferJS); env->SetMethod(target, "setupBufferJS", SetupBufferJS);
env->SetMethod(target, "create", Create); env->SetMethod(target, "create", Create);
env->SetMethod(target, "createFromString", CreateFromString); env->SetMethod(target, "createFromString", CreateFromString);
env->SetMethod(target, "createFromArrayBuffer", CreateFromArrayBuffer);
env->SetMethod(target, "slice", Slice); env->SetMethod(target, "slice", Slice);
env->SetMethod(target, "byteLengthUtf8", ByteLengthUtf8); env->SetMethod(target, "byteLengthUtf8", ByteLengthUtf8);

46
test/parallel/test-buffer-arraybuffer.js

@ -0,0 +1,46 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const Buffer = require('buffer').Buffer;
const LENGTH = 16;
const ab = new ArrayBuffer(LENGTH);
const dv = new DataView(ab);
const ui = new Uint8Array(ab);
const buf = new Buffer(ab);
assert.ok(buf instanceof Buffer);
// For backwards compatibility of old .parent property test that if buf is not
// a slice then .parent should be undefined.
assert.equal(buf.parent, undefined);
assert.equal(buf.buffer, ab);
assert.equal(buf.length, ab.byteLength);
buf.fill(0xC);
for (let i = 0; i < LENGTH; i++) {
assert.equal(ui[i], 0xC);
ui[i] = 0xF;
assert.equal(buf[i], 0xF);
}
buf.writeUInt32LE(0xF00, 0);
buf.writeUInt32BE(0xB47, 4);
buf.writeDoubleLE(3.1415, 8);
assert.equal(dv.getUint32(0, true), 0xF00);
assert.equal(dv.getUint32(4), 0xB47);
assert.equal(dv.getFloat64(8, true), 3.1415);
// Now test protecting users from doing stupid things
assert.throws(function() {
function AB() { }
AB.__proto__ = ArrayBuffer;
AB.prototype.__proto__ = ArrayBuffer.prototype;
new Buffer(new AB());
}, TypeError);
Loading…
Cancel
Save