Skip to content

Commit

Permalink
buffer: Only check if instance is Uint8Array
Browse files Browse the repository at this point in the history
Native Buffer method calls do not require anything from the prototype.
So it is unnecessary to check if the Object's prototype is equal to
Buffer.prototype.

This fixes an issue that prevents Buffer from being inherited the ES5
way. Now the following will work:

    function A(n) {
      const b = new Buffer(n);
      Object.setPrototypeOf(b, A.prototype);
      return b;
    }

    Object.setPrototypeOf(A.prototype, Buffer.prototype);
    Object.setPrototypeOf(A, Buffer);

    console.log(new A(4));

Fix: nodejs#2882
  • Loading branch information
trevnorris committed Oct 6, 2015
1 parent 7547947 commit b7eb4f1
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 12 deletions.
21 changes: 9 additions & 12 deletions src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,24 +163,20 @@ void CallbackInfo::WeakCallback(Isolate* isolate, Local<Object> object) {
// Buffer methods

bool HasInstance(Local<Value> val) {
return val->IsObject() && HasInstance(val.As<Object>());
return val->IsUint8Array();
}


bool HasInstance(Local<Object> obj) {
if (!obj->IsUint8Array())
return false;
Local<Uint8Array> array = obj.As<Uint8Array>();
Environment* env = Environment::GetCurrent(array->GetIsolate());
return array->GetPrototype()->StrictEquals(env->buffer_prototype_object());
return obj->IsUint8Array();
}


char* Data(Local<Value> val) {
CHECK(val->IsObject());
// Use a fully qualified name here to work around a bug in gcc 4.2.
// It mistakes an unadorned call to Data() for the v8::String::Data type.
return node::Buffer::Data(val.As<Object>());
CHECK(val->IsUint8Array());
Local<Uint8Array> ui = val.As<Uint8Array>();
ArrayBuffer::Contents ab_c = ui->Buffer()->GetContents();
return static_cast<char*>(ab_c.Data()) + ui->ByteOffset();
}


Expand All @@ -193,8 +189,9 @@ char* Data(Local<Object> obj) {


size_t Length(Local<Value> val) {
CHECK(val->IsObject());
return Length(val.As<Object>());
CHECK(val->IsUint8Array());
Local<Uint8Array> ui = val.As<Uint8Array>();
return ui->ByteLength();
}


Expand Down
38 changes: 38 additions & 0 deletions test/parallel/test-buffer-inheritance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict';

const common = require('../common');
const assert = require('assert');


function T(n) {
const ui8 = new Uint8Array(n);
Object.setPrototypeOf(ui8, T.prototype);
return ui8;
}
Object.setPrototypeOf(T.prototype, Buffer.prototype);
Object.setPrototypeOf(T, Buffer);

T.prototype.sum = function sum() {
let cntr = 0;
for (let i = 0; i < this.length; i++)
cntr += this[i];
return cntr;
};


const vals = [new T(4), T(4)];

vals.forEach(function(t) {
assert.equal(t.constructor, T);
assert.equal(t.__proto__, T.prototype);
assert.equal(t.__proto__.__proto__, Buffer.prototype);

t.fill(5);
let cntr = 0;
for (let i = 0; i < t.length; i++)
cntr += t[i];
assert.equal(t.length * 5, cntr);

// Check this does not throw
t.toString();
});

0 comments on commit b7eb4f1

Please sign in to comment.