2

I'm using a JavaScript spy library, simple-spy.

I've found out that when spying on a given function, the resulting spy always has an arity of 0.

This creates a problem with my use of this currying function.

So I've submitted a pull-request that adds arity transparency to the spy library.

The code looks like this:

function spy(fn) {
    const inner = (...args) => {
        stub.callCount++;
        stub.args.push(args);
        return fn(...args);
    };

    // ends up a string like
    // 'a,b,c,d'
    // depending on the `fn.length`
    const stubArgs = Array(fn.length)
        .fill(null)
        .map((m, i) => String.fromCodePoint(97 + i))
        .join();

    const stubBody = 'return inner(...arguments);';

    // this seems to be the only way
    // to create a function with
    // programmatically specified arity
    const stub = eval(
        // the wrapping parens is to
        // prevent it from evaluating as
        // a function declaration
        `(function (${stubArgs}) { ${stubBody} })`
    );

    stub.reset = () => {
        stub.callCount = 0;
        stub.args = [];
    };

    stub.reset();

    return stub;
}

exports.spy = spy;

This seems to work.

Is it possible to do this without the use of eval?

Is it possible to reduce the use of eval to even less that this?

I'm aware that there are other issues with this spy implementation. It is simplistic and it works for my use case so far.

Shahar 'Dawn' Or
  • 2,713
  • 1
  • 26
  • 38
  • 3
    You can use `Function` and set the arguments. Not much much better but better. You can also set `.length` with defineProperty on functions – Benjamin Gruenbaum Oct 28 '16 at 22:01

1 Answers1

2

Like Benjamin wrote, I used a simple:

function spy(fn) {
    const stub = (...args) => {
        stub.callCount++;
        stub.args.push(args);
        return fn(...args);
    };

    stub.reset = () => {
        stub.callCount = 0;
        stub.args = [];
    };

    stub.reset();

    Object.defineProperty(stub, 'length', {value: fn.length});

    return stub;
}

exports.spy = spy;

Much, much better looking.

Community
  • 1
  • 1
Shahar 'Dawn' Or
  • 2,713
  • 1
  • 26
  • 38