From fcd662cba85fa128873e6055f63cf947afe3e5f3 Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Tue, 16 May 2023 09:46:26 +0200 Subject: [PATCH] fix (#2514): only force new or inherited descriptors to be configurable --- lib/sinon/util/core/wrap-method.js | 8 +++++++- test/issues/issues-test.js | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/sinon/util/core/wrap-method.js b/lib/sinon/util/core/wrap-method.js index 8acc7eeb3..8ee3a3936 100644 --- a/lib/sinon/util/core/wrap-method.js +++ b/lib/sinon/util/core/wrap-method.js @@ -137,7 +137,13 @@ module.exports = function wrapMethod(object, property, method) { for (i = 0; i < types.length; i++) { mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]); } - methodDesc.configurable = true; + + // you are not allowed to flip the configurable prop on an + // existing descriptor to anything but false (#2514) + if(!owned) { + methodDesc.configurable = true; + } + Object.defineProperty(object, property, methodDesc); // catch failing assignment diff --git a/test/issues/issues-test.js b/test/issues/issues-test.js index e616e03a8..6a1b88b05 100644 --- a/test/issues/issues-test.js +++ b/test/issues/issues-test.js @@ -873,4 +873,30 @@ describe("issues", function () { }); }); }); + + describe("#2514 (regression from fixing #2491) - writable object descriptors that are unconfigurable should be assignable", function () { + function createInstanceWithWritableUconfigurablePropertyDescriptor() { + const instance = {}; + Object.defineProperty(instance, "aMethod", { + writable: true, + configurable: false, + value: function () { + return 42; + }, + }); + + return instance; + } + + it("should be able to assign and restore unconfigurable descriptors that are writable", function () { + const o = + createInstanceWithWritableUconfigurablePropertyDescriptor(); + + refute.exception(() => + this.sandbox.stub(o, "aMethod").returns("stubbed") + ); + assert.equals("stubbed", o.aMethod()); + this.sandbox.restore(); + }); + }); });