Skip to content
This repository was archived by the owner on Dec 8, 2024. It is now read-only.

Commit f4195bb

Browse files
authored
Merge pull request #507 from Victorystick/es-modules-support
Handle ExportNamedDeclarations
2 parents c521035 + d828255 commit f4195bb

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

lib/instrumenter.js

+33-2
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@
402402
this.walker = new Walker({
403403
ArrowFunctionExpression: [ this.arrowBlockConverter ],
404404
ExpressionStatement: this.coverStatement,
405+
ExportNamedDeclaration: this.coverExport,
405406
BreakStatement: this.coverStatement,
406407
ContinueStatement: this.coverStatement,
407408
DebuggerStatement: this.coverStatement,
@@ -800,6 +801,7 @@
800801
coverStatement: function (node, walker) {
801802
var sName,
802803
incrStatementCount,
804+
parent,
803805
grandParent;
804806

805807
this.maybeSkipNode(node, 'next');
@@ -815,10 +817,19 @@
815817
}
816818
}
817819
}
820+
818821
if (node.type === SYNTAX.FunctionDeclaration.name) {
819-
sName = this.statementName(node.loc, 1);
822+
// Called for the side-effect of setting the function's statement count to 1.
823+
this.statementName(node.loc, 1);
820824
} else {
825+
// We let `coverExport` handle ExportNamedDeclarations.
826+
parent = walker.parent();
827+
if (parent && parent.node.type === SYNTAX.ExportNamedDeclaration.name) {
828+
return;
829+
}
830+
821831
sName = this.statementName(node.loc);
832+
822833
incrStatementCount = astgen.statement(
823834
astgen.postIncrement(
824835
astgen.subscript(
@@ -827,10 +838,31 @@
827838
)
828839
)
829840
);
841+
830842
this.splice(incrStatementCount, node, walker);
831843
}
832844
},
833845

846+
coverExport: function (node, walker) {
847+
var sName, incrStatementCount;
848+
849+
if ( !node.declaration || !node.declaration.declarations ) { return; }
850+
851+
this.maybeSkipNode(node, 'next');
852+
853+
sName = this.statementName(node.declaration.loc);
854+
incrStatementCount = astgen.statement(
855+
astgen.postIncrement(
856+
astgen.subscript(
857+
astgen.dot(astgen.variable(this.currentState.trackerVar), astgen.variable('s')),
858+
astgen.stringLiteral(sName)
859+
)
860+
)
861+
);
862+
863+
this.splice(incrStatementCount, node, walker);
864+
},
865+
834866
splice: function (statements, node, walker) {
835867
var targetNode = walker.isLabeled() ? walker.parent().node : node;
836868
targetNode.prepend = targetNode.prepend || [];
@@ -1058,4 +1090,3 @@
10581090
}
10591091

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

test/es6.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ function tryThis(str, feature) {
99
return false;
1010
}
1111

12+
// esprima parses sources with sourceType 'script' per default.
13+
// The only way to enable `import`/`export` is to parse as sourceType 'module'.
1214
try {
13-
esprima.parse(str);
15+
try {
16+
esprima.parse(str);
17+
} catch (ex) {
18+
esprima.parse(str, { sourceType: 'module' });
19+
}
1420
} catch (ex) {
1521
console.error('ES6 feature [' + feature + '] is not yet supported by esprima mainline');
1622
return false;
@@ -42,6 +48,7 @@ module.exports = {
4248
},
4349

4450
isExportAvailable: function () {
45-
return tryThis('export default function foo() {}', 'export');
51+
// We can test instrumentation of exports even if the environment doesn't support them.
52+
return true;
4653
}
4754
};

test/helper.js

+7
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ function setup(file, codeArray, opts) {
104104
}
105105
return;
106106
}
107+
108+
// `export`/`import` cannot be wrapped inside a function.
109+
// For our purposes, simply remove the `export` from export declarations.
110+
if ( opts.esModules ) {
111+
generated = generated.replace(/export (var|function|let|const)/g, '$1');
112+
}
113+
107114
var wrappedCode = '(function (args) { var output;\n' + generated + '\nreturn output;\n})',
108115
fn;
109116
global[coverageVariable] = undefined;

test/instrumentation/test-es6-export.js

+18
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ if (require('../es6').isExportAvailable()) {
2121
statements: {'1': 1, '2': 1, '3': 1}
2222
});
2323
test.done();
24+
},
25+
26+
'should cover export declarations': function (test) {
27+
code = [
28+
'export var a = 2, b = 3;',
29+
'output = a + b'
30+
];
31+
verifier = helper.verifier(__filename, code, {
32+
esModules: true,
33+
noAutoWrap: true
34+
});
35+
verifier.verify(test, [], 5, {
36+
lines: {'1':1, '2': 1},
37+
branches: {},
38+
functions: {},
39+
statements: {'1': 1, '2': 1}
40+
});
41+
test.done();
2442
}
2543
};
2644
}

0 commit comments

Comments
 (0)