-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Now spies preserve original function arity #1055
Conversation
I haven't tested it carefully yet but it looks good to me.
Yes, but as you point out, there isn't much choice for dynamically making spies of a given arity. It would appear for example that Sinon uses hard-coded proxy functions limited to 12 arguments at most and they warn against using EDIT: I am going to sleep now but I wonder if something along these lines might help. |
More explanation here (look at comments): http://www.bennadel.com/blog/1909-javascript-function-constructor-does-not-create-a-closure.htm | ||
*/ | ||
/* jshint evil: true */ | ||
wrapper = eval('(function (' + args + ') { return spy.apply(this, Array.prototype.slice.call(arguments)); })'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we did:
var spy = /* full spy def., which can close over wrapper */,
wrapper = (function(spy){ return Function(args, 'return spy.apply(this, arguments);') }(spy))
Then you get a "closure" (really just formal param from the IIFE) of the spy, and you also get a working this
value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying with something like that before I used an eval
. It looks that when function is created with new Function
constructor, then it losts all of context in which it was created. So then I tried passing a spy
as first argument, but then I went into troubles with preserving this
which resulted the line above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dang. After playing around with it for a while, I now better understand exactly what you mean — Function
does not create closures (different from what I call context, which I usually treat as a synonym to the this
value). You can sort of force the spy
inside the function body if you bind(spy)
and use this.apply
but then you can't change the binding of the returned spy. Basically it's just not possible to do without eval
, as you already figured out. Or you can hard-code in the proxies like Sinon does but then you should add documentation to the effect of "Jasmine spies preserve arity up to length XX but not longer" or similar.
How frustrating.
Following our discussion, and doing a quick check I can see that |
Resolves #991
Sadly I needed to use
eval
for make spies working as expected.