buffer: only check if instance is Uint8Array

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: https://github.com/nodejs/node/issues/2882
PR-URL: https://github.com/nodejs/node/pull/3080
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
Trevor Norris 2015-09-26 15:26:52 -06:00
parent 8a685e7fe3
commit 05d424c029
2 changed files with 47 additions and 12 deletions

View File

@ -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();
}
@ -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();
}

View File

@ -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();
});