From 651a5b51eb838e8e23a5b94ba34e8e06630a004a Mon Sep 17 00:00:00 2001 From: Trevor Norris Date: Sat, 26 Sep 2015 15:26:52 -0600 Subject: [PATCH] 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 --- src/node_buffer.cc | 21 ++++++++---------- test/parallel/test-buffer-inheritance.js | 38 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 test/parallel/test-buffer-inheritance.js diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 5e0de52..9dbf3f0 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -163,24 +163,20 @@ void CallbackInfo::WeakCallback(Isolate* isolate, Local object) { // Buffer methods bool HasInstance(Local val) { - return val->IsObject() && HasInstance(val.As()); + return val->IsUint8Array(); } bool HasInstance(Local obj) { - if (!obj->IsUint8Array()) - return false; - Local array = obj.As(); - Environment* env = Environment::GetCurrent(array->GetIsolate()); - return array->GetPrototype()->StrictEquals(env->buffer_prototype_object()); + return obj->IsUint8Array(); } char* Data(Local 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()); + CHECK(val->IsUint8Array()); + Local ui = val.As(); + ArrayBuffer::Contents ab_c = ui->Buffer()->GetContents(); + return static_cast(ab_c.Data()) + ui->ByteOffset(); } @@ -193,8 +189,9 @@ char* Data(Local obj) { size_t Length(Local val) { - CHECK(val->IsObject()); - return Length(val.As()); + CHECK(val->IsUint8Array()); + Local ui = val.As(); + return ui->ByteLength(); } diff --git a/test/parallel/test-buffer-inheritance.js b/test/parallel/test-buffer-inheritance.js new file mode 100644 index 0000000..eb2f4a5 --- /dev/null +++ b/test/parallel/test-buffer-inheritance.js @@ -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(); +}); -- 2.7.4