From 1a5c464c4595bd8c7d3d19c0fe00b479b9ff81fc Mon Sep 17 00:00:00 2001 From: mnespor Date: Fri, 27 Apr 2018 00:09:07 -0500 Subject: [PATCH] Copy own __proto__ on older versions of node - In the __proto__ test, construct the source object with Object.defineProperty() instead of JSON.parse() - Use Object.getOwnPropertyDescriptor() when cloning an own __proto__ to work around a bug in accessing __proto__ in some environments --- index.js | 12 +++++++++--- test/index.js | 16 +++++++--------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index ff35dd8..ed7455b 100644 --- a/index.js +++ b/index.js @@ -45,10 +45,16 @@ var setProperty = function setProperty(target, options) { } }; -// Return a new object instead of __proto__ if '__proto__' is not an own property +// Return undefined instead of __proto__ if '__proto__' is not an own property var getProperty = function getProperty(obj, name) { - if (name === '__proto__' && !hasOwn.call(obj, name)) { - return undefined; + if (name === '__proto__') { + if (!hasOwn.call(obj, name)) { + return undefined; + } else if (Object.getOwnPropertyDescriptor) { + // In early versions of node, obj['__proto__'] is buggy when obj has + // __proto__ as an own property. Object.getOwnPropertyDescriptor() works. + return Object.getOwnPropertyDescriptor(obj, name).value; + } } return obj[name]; diff --git a/test/index.js b/test/index.js index be7f5b5..a57e435 100644 --- a/test/index.js +++ b/test/index.js @@ -628,15 +628,13 @@ test('non-object target', function (t) { }); test('__proto__ is merged as an own property', function (t) { - var malicious = JSON.parse('{ "fred": 1, "__proto__": { "george": 1 } }'); - // this test isn't valid for earlier versions of V8, which strip __proto__ during JSON.parse() - if (Object.prototype.hasOwnProperty.call(malicious, '__proto__')) { - var target = {}; - extend(true, target, malicious); - t.notOk(target.george); - t.ok(Object.prototype.hasOwnProperty.call(target, '__proto__')); - t.deepEqual(target.__proto__, { george: 1 }); // eslint-disable-line no-proto - } + var malicious = { fred: 1 }; + Object.defineProperty(malicious, '__proto__', { value: { george: 1 }, enumerable: true }); + var target = {}; + extend(true, target, malicious); + t.notOk(target.george); + t.ok(Object.prototype.hasOwnProperty.call(target, '__proto__')); + t.deepEqual(Object.getOwnPropertyDescriptor(target, '__proto__').value, { george: 1 }); t.end(); });