Indiana Jones - Exploring JS Code
Authors: Mathieu Rene & Steve Venzerul
The inspiration
A great talk by Alan Shreve
The concept (read: Hack)
Parse input
Instrument AST
Run instrumented code
Output coverage report
Reparse input into AST, use report to remove nodes that weren't executed
Output modified AST back to disk.
function someFunction(someValue) {
if (someValue % 2 === 0) console.log('foo');
else console.log('bar');
switch(someValue) {
case 0:
case 20:
console.log('nope');
break;
case 11:
try {
console.log('maybe', 1234 / 0);
throw new Error(':)');
} catch(e) {
void 0;
console.log('e', e);
}
break;
case 42:
fs.readFile('./nonexistant', (err, data) => {
if (err) {
return 10;
}
console.log('Data:', data);
});
}
}
someFunction(42);
var __coverage__ = { /* ... */ };
__coverage__ = __coverage__['fixtures/test.js'];
__coverage__.s['1']++;
var fs = require('fs');
function someFunction(someValue) {
__coverage__.f['1']++;__coverage__.s['3']++;
if (someValue % 2 === 0) {
__coverage__.b['1'][0]++;__coverage__.s['4']++;console.log('foo');
} else {
__coverage__.b['1'][1]++;__coverage__.s['5']++;console.log('bar');
}
__coverage__.s['6']++;switch (someValue) {
case 0:
__coverage__.b['2'][0]++;case 20:
__coverage__.b['2'][1]++;__coverage__.s['7']++;console.log('nope');__coverage__.s['8']++;
break;case 11:
__coverage__.b['2'][2]++;__coverage__.s['9']++;try {
__coverage__.s['10']++;console.log('maybe', 1234 / 0);__coverage__.s['11']++;
throw new Error(':)');
} catch ( e ) {
__coverage__.s['12']++;void 0;__coverage__.s['13']++;console.log('e', e);
} __coverage__.s['14']++;
break;case 42:
__coverage__.b['2'][3]++;__coverage__.s['15']++;fs.readFile('./nonexistant', (err, data) => {
__coverage__.s['16']++;
if (err) {
__coverage__.b['3'][0]++;__coverage__.s['17']++;return 10;
} else {
__coverage__.b['3'][1]++;
}
__coverage__.s['18']++;console.log('Data:', data);
});
}
}
__coverage__.s['19']++;someFunction(42);
process.on('beforeExit', () => {
require('fs').writeFileSync('coverage-fixtures_test.js.json', JSON.stringify(__coverage__), 'utf8');
});
{
"fixtures/test.js": {
"path": "fixtures/test.js",
....
"s": {
"1": 1,
"2": 1,
"3": 1,
....
},
....
"statementMap": {
"1": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 23
}
},
"2": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 37,
"column": 1
}
}
}
}
}
var fs = require('fs');
function someFunction(someValue) {
if (someValue % 2 === 0) {
console.log('foo');
} else {}
switch(someValue) {
case 0:
case 20:
break;
case 11:
break;
case 42:
fs.readFile('./nonexistant', (err, data) => {
if (err) {
return 10;
}
});
}
}
someFunction(42);
Final Output
Dreaming big
var fs = require('fs');
function someFunction(someValue) {
if (someValue % 2 === 0) {
console.log('foo');
}
fs.readFile('./nonexistant', (err, data) => {
if (err) {
return 10;
}
});
}
someFunction(42);
If you want to play with the code, head over to: https://github.com/mrene/indiana-jones
Questions?
Indiana Jones - Exploring JS Code
By signupskm
Indiana Jones - Exploring JS Code
- 1,364