From 66e42ce37046014fd2b9d8f37ebfc14435e3cc7d Mon Sep 17 00:00:00 2001
From: Brian White <mscdex@mscdex.net>
Date: Thu, 8 Sep 2016 18:31:39 -0400
Subject: [PATCH] buffer: fix ArrayBuffer checks

This commit fixes detection of ArrayBuffers from different V8 contexts.
This is especially a problem for environments like nw.js where the
node and browser V8 contexts are not shared.
---
 lib/buffer.js                           | 9 +++------
 test/parallel/test-buffer-alloc.js      | 6 ++++++
 test/parallel/test-buffer-bytelength.js | 5 +++++
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/lib/buffer.js b/lib/buffer.js
index b7e250da2d578c..cefec86e9abb67 100644
--- a/lib/buffer.js
+++ b/lib/buffer.js
@@ -103,7 +103,7 @@ Buffer.from = function(value, encodingOrOffset, length) {
   if (typeof value === 'number')
     throw new TypeError('"value" argument must not be a number');
 
-  if (value instanceof ArrayBuffer)
+  if (isArrayBuffer(value))
     return fromArrayBuffer(value, encodingOrOffset, length);
 
   if (typeof value === 'string')
@@ -234,9 +234,6 @@ function fromArrayLike(obj) {
 }
 
 function fromArrayBuffer(obj, byteOffset, length) {
-  if (!isArrayBuffer(obj))
-    throw new TypeError('argument is not an ArrayBuffer');
-
   byteOffset >>>= 0;
 
   const maxLength = obj.byteLength - byteOffset;
@@ -267,7 +264,7 @@ function fromObject(obj) {
   }
 
   if (obj) {
-    if (obj.buffer instanceof ArrayBuffer || 'length' in obj) {
+    if (isArrayBuffer(obj.buffer) || 'length' in obj) {
       if (typeof obj.length !== 'number' || obj.length !== obj.length) {
         return new FastBuffer();
       }
@@ -354,7 +351,7 @@ function base64ByteLength(str, bytes) {
 
 function byteLength(string, encoding) {
   if (typeof string !== 'string') {
-    if (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)
+    if (ArrayBuffer.isView(string) || isArrayBuffer(string))
       return string.byteLength;
 
     string = '' + string;
diff --git a/test/parallel/test-buffer-alloc.js b/test/parallel/test-buffer-alloc.js
index c80ee10382a968..231b1b61fa2c72 100644
--- a/test/parallel/test-buffer-alloc.js
+++ b/test/parallel/test-buffer-alloc.js
@@ -1,6 +1,7 @@
 'use strict';
 const common = require('../common');
 const assert = require('assert');
+const vm = require('vm');
 
 const Buffer = require('buffer').Buffer;
 const SlowBuffer = require('buffer').SlowBuffer;
@@ -1049,6 +1050,11 @@ assert.throws(() => {
 // Regression test
 assert.doesNotThrow(() => Buffer.from(new ArrayBuffer()));
 
+// Test that ArrayBuffer from a different context is detected correctly
+const arrayBuf = vm.runInNewContext('new ArrayBuffer()');
+assert.doesNotThrow(() => Buffer.from(arrayBuf));
+assert.doesNotThrow(() => Buffer.from({ buffer: arrayBuf }));
+
 assert.throws(() => Buffer.alloc({ valueOf: () => 1 }),
               /"size" argument must be a number/);
 assert.throws(() => Buffer.alloc({ valueOf: () => -1 }),
diff --git a/test/parallel/test-buffer-bytelength.js b/test/parallel/test-buffer-bytelength.js
index 521cff7d3bd16a..14d7c95dd231aa 100644
--- a/test/parallel/test-buffer-bytelength.js
+++ b/test/parallel/test-buffer-bytelength.js
@@ -4,6 +4,7 @@ require('../common');
 const assert = require('assert');
 const Buffer = require('buffer').Buffer;
 const SlowBuffer = require('buffer').SlowBuffer;
+const vm = require('vm');
 
 // coerce values to string
 assert.strictEqual(Buffer.byteLength(32, 'latin1'), 2);
@@ -87,3 +88,7 @@ assert.strictEqual(Buffer.byteLength('Il était tué', 'binary'), 12);
 ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach(function(encoding) {
   assert.strictEqual(24, Buffer.byteLength('Il était tué', encoding));
 });
+
+// Test that ArrayBuffer from a different context is detected correctly
+const arrayBuf = vm.runInNewContext('new ArrayBuffer()');
+assert.strictEqual(Buffer.byteLength(arrayBuf), 0);