samsam icon indicating copy to clipboard operation
samsam copied to clipboard

Infinite recursion on circular object when using sinon.match({})

Open ajaska opened this issue 3 years ago • 0 comments

When using sinon.match with an object literal (for partial matching), samsam enters an infinite loop.

  • library version : sinon@latest - 13.0.1
  • Environment : node
  • Example URL :
  • Other libraries you are using:

What did you expect to happen? Sinon correctly supports circular objects without sinon.match, so I expected this to work. (See workarounds below).

What actually happens RangeError: Maximum call stack size exceeded

How to reproduce

const sinon = require("sinon");

const circular_obj = { a: null };
circular_obj.a = circular_obj;

const fake = sinon.fake();
fake({ b: circular_obj, c: "c" });

sinon.assert.calledWith(fake, sinon.match({ b: circular_obj }));

Output

/Users/arlanjaska/sandbox/sinon_testing/node_modules/type-detect/type-detect.js:45
function typeDetect(obj) {
                   ^

RangeError: Maximum call stack size exceeded
    at typeDetect (/Users/arlanjaska/sandbox/sinon_testing/node_modules/type-detect/type-detect.js:45:20)
    at typeOf (/Users/arlanjaska/sandbox/sinon_testing/node_modules/@sinonjs/commons/lib/type-of.js:12:12)
    at /Users/arlanjaska/sandbox/sinon_testing/node_modules/@sinonjs/samsam/lib/create-matcher/match-object.js:46:20
    at Array.every (<anonymous>)
    at matchObject (/Users/arlanjaska/sandbox/sinon_testing/node_modules/@sinonjs/samsam/lib/create-matcher/match-object.js:38:12)
    at /Users/arlanjaska/sandbox/sinon_testing/node_modules/@sinonjs/samsam/lib/create-matcher/match-object.js:47:18
    at Array.every (<anonymous>)
    at matchObject (/Users/arlanjaska/sandbox/sinon_testing/node_modules/@sinonjs/samsam/lib/create-matcher/match-object.js:38:12)
    at /Users/arlanjaska/sandbox/sinon_testing/node_modules/@sinonjs/samsam/lib/create-matcher/match-object.js:47:18
    at Array.every (<anonymous>)

Additional context This could probably be solved for this case by tossing in an identical() check somewhere in here. Not sure how it's handled in general though.

Workarounds

  • Use sinon.match.same
sinon.assert.calledWith(fake, sinon.match({ b: sinon.match.same(circular_obj) }));
  • If you are okay with checking every property, don't use sinon.match
sinon.assert.calledWith(fake, { b: circular_obj, c: "c" });

ajaska avatar Apr 06 '22 03:04 ajaska