Skip to content

Commit 653021a

Browse files
trevnorrisrvagg
authored andcommitted
buffer: allow ArrayBuffer as Buffer argument
Buffer now uses the ArrayBuffer as the backing store if passed to the constructor. Fixes: #106 PR-URL: #2002 Reviewed-By: Domenic Denicola <d@domenic.me>
1 parent 0a7bbdf commit 653021a

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

lib/internal/buffer_new.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,10 @@ function fromObject(obj) {
104104
return b;
105105
}
106106

107-
// TODO(trevnorris): This will fail for an actual ArrayBuffer.
107+
if (obj instanceof ArrayBuffer) {
108+
return binding.createFromArrayBuffer(obj);
109+
}
110+
108111
if (obj.buffer instanceof ArrayBuffer || obj.length) {
109112
var length;
110113
if (typeof obj.length !== 'number' || obj.length !== obj.length)

src/node_buffer.cc

+15
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,20 @@ void CreateFromString(const FunctionCallbackInfo<Value>& args) {
528528
}
529529

530530

531+
void CreateFromArrayBuffer(const FunctionCallbackInfo<Value>& args) {
532+
Environment* env = Environment::GetCurrent(args);
533+
if (!args[0]->IsArrayBuffer())
534+
return env->ThrowTypeError("argument is not an ArrayBuffer");
535+
Local<ArrayBuffer> ab = args[0].As<ArrayBuffer>();
536+
Local<Uint8Array> ui = Uint8Array::New(ab, 0, ab->ByteLength());
537+
Maybe<bool> mb =
538+
ui->SetPrototype(env->context(), env->buffer_prototype_object());
539+
if (!mb.FromMaybe(false))
540+
return env->ThrowError("Unable to set Object prototype");
541+
args.GetReturnValue().Set(ui);
542+
}
543+
544+
531545
void Slice(const FunctionCallbackInfo<Value>& args) {
532546
CHECK(args[0]->IsUint8Array());
533547
CHECK(args[1]->IsNumber());
@@ -1174,6 +1188,7 @@ void Initialize(Handle<Object> target,
11741188
env->SetMethod(target, "setupBufferJS", SetupBufferJS);
11751189
env->SetMethod(target, "create", Create);
11761190
env->SetMethod(target, "createFromString", CreateFromString);
1191+
env->SetMethod(target, "createFromArrayBuffer", CreateFromArrayBuffer);
11771192

11781193
env->SetMethod(target, "slice", Slice);
11791194
env->SetMethod(target, "byteLengthUtf8", ByteLengthUtf8);
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
6+
const Buffer = require('buffer').Buffer;
7+
const LENGTH = 16;
8+
9+
const ab = new ArrayBuffer(LENGTH);
10+
const dv = new DataView(ab);
11+
const ui = new Uint8Array(ab);
12+
const buf = new Buffer(ab);
13+
14+
15+
assert.ok(buf instanceof Buffer);
16+
// For backwards compatibility of old .parent property test that if buf is not
17+
// a slice then .parent should be undefined.
18+
assert.equal(buf.parent, undefined);
19+
assert.equal(buf.buffer, ab);
20+
assert.equal(buf.length, ab.byteLength);
21+
22+
23+
buf.fill(0xC);
24+
for (let i = 0; i < LENGTH; i++) {
25+
assert.equal(ui[i], 0xC);
26+
ui[i] = 0xF;
27+
assert.equal(buf[i], 0xF);
28+
}
29+
30+
buf.writeUInt32LE(0xF00, 0);
31+
buf.writeUInt32BE(0xB47, 4);
32+
buf.writeDoubleLE(3.1415, 8);
33+
34+
assert.equal(dv.getUint32(0, true), 0xF00);
35+
assert.equal(dv.getUint32(4), 0xB47);
36+
assert.equal(dv.getFloat64(8, true), 3.1415);
37+
38+
39+
// Now test protecting users from doing stupid things
40+
41+
assert.throws(function() {
42+
function AB() { }
43+
AB.__proto__ = ArrayBuffer;
44+
AB.prototype.__proto__ = ArrayBuffer.prototype;
45+
new Buffer(new AB());
46+
}, TypeError);

0 commit comments

Comments
 (0)