Sinon: Problem with `getStackFrames()[0]`

Created on 12 Jun 2016  ·  3Comments  ·  Source: sinonjs/sinon

We understand you have a problem and are in a hurry, but please provide us with some info to make it much more likely for your issue to be understood, worked on and resolved quickly.

  • Sinon version : 1.17.4
  • Environment : Firefox
  • Example URL :
  • Other libraries you are using: mocha, chai

What did you expect to happen?

I expected my own error to be reported, not an internal Sinon error.

What actually happens

An internal Sinon error is shown.

How to reproduce

Describe _with code_ how to reproduce the faulty behaviour,
or link to code on JSBin or similar

See this for an example

In sinon/lib/sinon/call.js, this code is giving me the error that this.getStackFrames(...)[0] is undefined:

      if (this.stack) {
            callStr += this.getStackFrames()[0].replace(/^\s*(?:at\s+|@)?/, " at ");
      }

From the following:

    getStackFrames: function () {
        // Omit the error message and the two top stack frames in sinon itself:
        return this.stack && this.stack.split("\n").slice(3);
    },

...it appears that the slice is returning an empty array.

I'm hoping this may be enough for you to go on without a specific code sample. Thanks!

Most helpful comment

This is perhaps a slightly better version that also works in Node:

let sinon = require('sinon');

function test() {

  let stub1 = sinon.stub().returns( Promise.resolve({}) );
  let stub2 = sinon.stub();

  function run() {
    return stub1().then( stub2 );
  }

  run()
  .then( () => sinon.assert.calledTwice( stub2 ) )
  .catch( console.log );

}

setTimeout( test, 0 );

All 3 comments

This is not sufficient. I don't see any code using Sinon's API at all. You just mention the internals of Sinon, but what about the externals? Waht are you trying to achieve? You can reopen this if you add more info that makes it clear what you are trying to achieve, how, and what is not working.

I'm able to reproduce this in Chrome 55.0.2883.95 for Mac with Sinon 1.17.6 (the latest available at http://sinonjs.org/).

Here's a JSBin with a reduced test case: http://jsbin.com/mufotihiwo/edit?js,console,output

Essentially, it seems like when a stub is passed point-free to Promise#then(), Sinon _thinks_ it should have a stack trace longer than 3 lines, but it doesn't.

I haven't had a chance yet to figure out exactly what causes this.

I believe this is because the callback is invoked directly by the VM, which means there's nothing in the stack. So when Sinon chops off the first 3 lines (starting at spy.invoke()), there's nothing left. Then the String#replace() in call.toString fails because getStackFrames()[0] is undefined.

I _think_ a mitigation strategy would be to simply put a defensive check in toString() that looks something like:

callStr += ( this.getStackFrames()[0] || 'unknown function' ).replace(/^\s*(?:at\s+|@)?/, " at ");

This is perhaps a slightly better version that also works in Node:

let sinon = require('sinon');

function test() {

  let stub1 = sinon.stub().returns( Promise.resolve({}) );
  let stub2 = sinon.stub();

  function run() {
    return stub1().then( stub2 );
  }

  run()
  .then( () => sinon.assert.calledTwice( stub2 ) )
  .catch( console.log );

}

setTimeout( test, 0 );
Was this page helpful?
0 / 5 - 0 ratings

Related issues

optimatex picture optimatex  ·  4Comments

stephanwlee picture stephanwlee  ·  3Comments

ljian3377 picture ljian3377  ·  3Comments

byohay picture byohay  ·  3Comments

fearphage picture fearphage  ·  3Comments