Skip to content

Commit

Permalink
Merge pull request #507 from Victorystick/es-modules-support
Browse files Browse the repository at this point in the history
Handle ExportNamedDeclarations
  • Loading branch information
gotwarlost authored Jun 15, 2016
2 parents c521035 + d828255 commit f4195bb
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 4 deletions.
35 changes: 33 additions & 2 deletions lib/instrumenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@
this.walker = new Walker({
ArrowFunctionExpression: [ this.arrowBlockConverter ],
ExpressionStatement: this.coverStatement,
ExportNamedDeclaration: this.coverExport,
BreakStatement: this.coverStatement,
ContinueStatement: this.coverStatement,
DebuggerStatement: this.coverStatement,
Expand Down Expand Up @@ -800,6 +801,7 @@
coverStatement: function (node, walker) {
var sName,
incrStatementCount,
parent,
grandParent;

this.maybeSkipNode(node, 'next');
Expand All @@ -815,10 +817,19 @@
}
}
}

if (node.type === SYNTAX.FunctionDeclaration.name) {
sName = this.statementName(node.loc, 1);
// Called for the side-effect of setting the function's statement count to 1.
this.statementName(node.loc, 1);
} else {
// We let `coverExport` handle ExportNamedDeclarations.
parent = walker.parent();
if (parent && parent.node.type === SYNTAX.ExportNamedDeclaration.name) {
return;
}

sName = this.statementName(node.loc);

incrStatementCount = astgen.statement(
astgen.postIncrement(
astgen.subscript(
Expand All @@ -827,10 +838,31 @@
)
)
);

this.splice(incrStatementCount, node, walker);
}
},

coverExport: function (node, walker) {
var sName, incrStatementCount;

if ( !node.declaration || !node.declaration.declarations ) { return; }

this.maybeSkipNode(node, 'next');

sName = this.statementName(node.declaration.loc);
incrStatementCount = astgen.statement(
astgen.postIncrement(
astgen.subscript(
astgen.dot(astgen.variable(this.currentState.trackerVar), astgen.variable('s')),
astgen.stringLiteral(sName)
)
)
);

this.splice(incrStatementCount, node, walker);
},

splice: function (statements, node, walker) {
var targetNode = walker.isLabeled() ? walker.parent().node : node;
targetNode.prepend = targetNode.prepend || [];
Expand Down Expand Up @@ -1058,4 +1090,3 @@
}

}(typeof module !== 'undefined' && typeof module.exports !== 'undefined' && typeof exports !== 'undefined'));

11 changes: 9 additions & 2 deletions test/es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ function tryThis(str, feature) {
return false;
}

// esprima parses sources with sourceType 'script' per default.
// The only way to enable `import`/`export` is to parse as sourceType 'module'.
try {
esprima.parse(str);
try {
esprima.parse(str);
} catch (ex) {
esprima.parse(str, { sourceType: 'module' });
}
} catch (ex) {
console.error('ES6 feature [' + feature + '] is not yet supported by esprima mainline');
return false;
Expand Down Expand Up @@ -42,6 +48,7 @@ module.exports = {
},

isExportAvailable: function () {
return tryThis('export default function foo() {}', 'export');
// We can test instrumentation of exports even if the environment doesn't support them.
return true;
}
};
7 changes: 7 additions & 0 deletions test/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ function setup(file, codeArray, opts) {
}
return;
}

// `export`/`import` cannot be wrapped inside a function.
// For our purposes, simply remove the `export` from export declarations.
if ( opts.esModules ) {
generated = generated.replace(/export (var|function|let|const)/g, '$1');
}

var wrappedCode = '(function (args) { var output;\n' + generated + '\nreturn output;\n})',
fn;
global[coverageVariable] = undefined;
Expand Down
18 changes: 18 additions & 0 deletions test/instrumentation/test-es6-export.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@ if (require('../es6').isExportAvailable()) {
statements: {'1': 1, '2': 1, '3': 1}
});
test.done();
},

'should cover export declarations': function (test) {
code = [
'export var a = 2, b = 3;',
'output = a + b'
];
verifier = helper.verifier(__filename, code, {
esModules: true,
noAutoWrap: true
});
verifier.verify(test, [], 5, {
lines: {'1':1, '2': 1},
branches: {},
functions: {},
statements: {'1': 1, '2': 1}
});
test.done();
}
};
}

0 comments on commit f4195bb

Please sign in to comment.