From f981192f84dec33423a8d1eadde8fda348d04ea7 Mon Sep 17 00:00:00 2001 From: sjoseph7 <17250762+sjoseph7@users.noreply.github.com> Date: Wed, 28 Oct 2020 01:53:18 -0700 Subject: [PATCH] Fix #2203: skip writing 'name' property if not writable (#2304) * Add test for #2203 * Skip writing 'name' property if not writable --- lib/sinon/util/core/extend.js | 18 +++++++++++++++--- test/extend-test.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/lib/sinon/util/core/extend.js b/lib/sinon/util/core/extend.js index 93e2d0c30..f82dc8604 100644 --- a/lib/sinon/util/core/extend.js +++ b/lib/sinon/util/core/extend.js @@ -73,8 +73,8 @@ function extendCommon(target, sources, doCopy) { return target; } -/** Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will - * override properties in previous sources. +/** Public: Extend target in place with all (own) properties, except 'name' when [[writable]] is false, + * from sources in-order. Thus, last source will override properties in previous sources. * * @arg {Object} target - The Object to extend * @arg {Object[]} sources - Objects to copy properties from. @@ -85,7 +85,19 @@ module.exports = function extend(target /*, sources */) { var sources = slice(arguments, 1); return extendCommon(target, sources, function copyValue(dest, source, prop) { - dest[prop] = source[prop]; + var destOwnPropertyDescriptor = Object.getOwnPropertyDescriptor(dest, prop); + var sourceOwnPropertyDescriptor = Object.getOwnPropertyDescriptor(source, prop); + + if (prop === "name" && !destOwnPropertyDescriptor.writable) { + return; + } + + Object.defineProperty(dest, prop, { + configurable: sourceOwnPropertyDescriptor.configurable, + enumerable: sourceOwnPropertyDescriptor.enumerable, + writable: sourceOwnPropertyDescriptor.writable, + value: sourceOwnPropertyDescriptor.value + }); }); }; diff --git a/test/extend-test.js b/test/extend-test.js index 7f5aa8bb9..23949dd07 100644 --- a/test/extend-test.js +++ b/test/extend-test.js @@ -77,4 +77,32 @@ describe("extend", function() { assert.equals(result, expected); }); + + context("when 'name' property is not writable", function() { + it("does not attempt to write to the property", function() { + var object1 = { prop1: null }; + + Object.defineProperty(object1, "name", { + configurable: false, + enumerable: true, + value: "not-writable", + writable: false + }); + + var object2 = { + prop2: "hey", + name: "write-attempt" + }; + + var result = extend(object1, object2); + + var expected = { + prop1: null, + prop2: "hey", + name: "not-writable" + }; + + assert.equals(result, expected); + }); + }); });