From 43cda06aaad7f6394dd2235e0479204e95894d22 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Mon, 3 Feb 2020 16:26:46 -0500 Subject: [PATCH 1/2] Add failing test for #2215 --- test/util/core/function-to-string-test.js | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/util/core/function-to-string-test.js b/test/util/core/function-to-string-test.js index 0953daccd..8a4399707 100644 --- a/test/util/core/function-to-string-test.js +++ b/test/util/core/function-to-string-test.js @@ -35,4 +35,32 @@ describe("util/core/functionToString", function() { assert.equals(functionToString.call(obj.doStuff), "doStuff"); }); + + // https://github.com/sinonjs/sinon/issues/2215 + it("ignores errors thrown by property accessors on thisValue", function() { + var obj = {}; + + Object.defineProperty(obj, "foo", { + enumerable: true, + get: function() { + throw new Error(); + } + }); + + // this will cause `fn` to be after `foo` when enumerated + obj.fn = function() { + return "foo"; + }; + + // validate that the keys are in the expected order that will cause the bug + var keys = Object.keys(obj); + assert.equals(keys[0], "foo"); + assert.equals(keys[1], "fn"); + + var spy = createSpy(obj, "fn"); + + obj.fn(); + + assert.equals(spy.toString(), "fn"); + }); }); From be704daacb864a5e79429dbb263f5c048abed105 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Mon, 3 Feb 2020 16:27:12 -0500 Subject: [PATCH 2/2] Ignore errors on thisValue property accesses --- lib/sinon/util/core/function-to-string.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/sinon/util/core/function-to-string.js b/lib/sinon/util/core/function-to-string.js index fa0265bed..b54092df7 100644 --- a/lib/sinon/util/core/function-to-string.js +++ b/lib/sinon/util/core/function-to-string.js @@ -8,9 +8,14 @@ module.exports = function toString() { while (i--) { thisValue = this.getCall(i).thisValue; + // eslint-disable-next-line guard-for-in for (prop in thisValue) { - if (thisValue[prop] === this) { - return prop; + try { + if (thisValue[prop] === this) { + return prop; + } + } catch (e) { + // no-op - accessing props can throw an error, nothing to do here } } }