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

Handle ExportNamedDeclarations #507

Merged
merged 4 commits into from
Jun 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions lib/instrumenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,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 @@ -790,6 +791,7 @@
coverStatement: function (node, walker) {
var sName,
incrStatementCount,
parent,
grandParent;

this.maybeSkipNode(node, 'next');
Expand All @@ -805,10 +807,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 @@ -817,10 +828,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 @@ -1048,4 +1080,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();
}
};
}