gotwarlost / istanbul

Yet another JS code coverage tool that computes statement, line, function and branch coverage with module loader hooks to transparently add coverage when running tests. Supports all JS coverage use cases including unit tests, server side functional tests and browser tests. Built for scale.
Other
8.7k stars 786 forks source link

istanbul instrumentation function.toString() #310

Open paulhoconnor opened 9 years ago

paulhoconnor commented 9 years ago

any downstream interpretation of function.toString(), as instrumented by istanbul, sees instrumentation code, interprets as garbage, and throws a ReferenceError. An example of this is eval'ing functions into different threads.

/* istanbul ignore next */ should cause the next 'thing' not to be instrumented

gotwarlost commented 9 years ago

ignore is just reporting fakery now. Doesn't mean "do not instrument". Need to look into this

ioncreature commented 9 years ago

Have the same problem.

I send function to MongoDB like:

function filter(){
 ...
}

User.find({
    $where: filter.toString()
}, function( error, users ){
    // MongoError: ReferenceError: __cov_G1RH9TezwmrgBKIjkjZ4FQ is not defined
});

Do you know any way to avoid this?

fritx commented 8 years ago

+1 met the same issue. the fn is passed into another process and becomes

'function (){__cov_gjt0lukdoxUzQSDPHovUcQ.f[\'66\']++;__cov_gjt0lukdoxUzQSDPHovUcQ.s[\'219\']++;return document.title;}'

but there is no __con_* in that different context

Unhandled rejection ReferenceError: __cov_gjt0lukdoxUzQSDPHovUcQ is not defined
fritx commented 8 years ago

My solution:

fnstr = fnstr.replace(/__cov_(.+?)\+\+;?/g, '')
tagyoureit commented 7 years ago

Brilliant!! I was having the same problem, and this is a beautiful solution.

I made one addition...

fnstr = fnstr.replace(/__cov_(.+?)\+\+[,;]?/g, '')

I changed the ? to [,?].

This is because my .toString() result included an if statement with multiple items if (address > -1 && program >= 1 && program <= 4) {

Istanbul generated:

((__cov_x3uoF3uO18CbkEPjMSjaKw.b['9'][0]++,address>-1)&&(__cov_x3uoF3uO18CbkEPjMSjaKw.b['9'][1]++,program>=1)&&(__cov_x3uoF3uO18CbkEPjMSjaKw.b['9'][2]++,program<=4)){__cov_x3uoF3uO18CbkEPjMSjaKw.b['8'][0]++;__cov_x3uoF3uO18CbkEPjMSjaKw.s['24']++;if((__cov_x3uoF3uO18CbkEPjMSjaKw.b['11'][0]++,speed<=450)||(__cov_x3uoF3uO18CbkEPjMSjaKw.b['11'][1]++,speed>=3450)||(__cov_x3uoF3uO18CbkEPjMSjaKw.b['11'][2]++,isNaN(speed))||(__cov_x3uoF3uO18CbkEPjMSjaKw.b['11'][3]++,speed==null))

Notice the __cov_x3uoF3uO18CbkEPjMSjaKw.b['9'][0]++, ending , instead of ;.

Original regex resulted in if ((, address > -1) && (, program >= 1) && (, program <= 4)) {

With the modification the result is clean, running code.

Thanks @fritx !

andrew-aladev commented 4 years ago

Another workaround is to have 2 same functions: first with ignore and second one without it.

export function fn () { ... }

// istanbul ignore next
function fnCopy () { ... }

... fnCopy.toString() ...

fn exported and covered, fnCopy used inside another context without istanbul.

But this workaround is ugly and I don't like it.