diff options
Diffstat (limited to 'node_modules/istanbul-lib-instrument/dist/visitor.js')
| -rw-r--r-- | node_modules/istanbul-lib-instrument/dist/visitor.js | 597 |
1 files changed, 0 insertions, 597 deletions
diff --git a/node_modules/istanbul-lib-instrument/dist/visitor.js b/node_modules/istanbul-lib-instrument/dist/visitor.js deleted file mode 100644 index bd8f9e3ff..000000000 --- a/node_modules/istanbul-lib-instrument/dist/visitor.js +++ /dev/null @@ -1,597 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _sourceCoverage = require('./source-coverage'); - -var _constants = require('./constants'); - -var _crypto = require('crypto'); - -var _babelTemplate = require('babel-template'); - -var _babelTemplate2 = _interopRequireDefault(_babelTemplate); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -// istanbul ignore comment pattern -var COMMENT_RE = /^\s*istanbul\s+ignore\s+(if|else|next)(?=\W|$)/; -// istanbul ignore file pattern -var COMMENT_FILE_RE = /^\s*istanbul\s+ignore\s+(file)(?=\W|$)/; -// source map URL pattern -var SOURCE_MAP_RE = /[#@]\s*sourceMappingURL=(.*)\s*$/m; - -// generate a variable name from hashing the supplied file path -function genVar(filename) { - var hash = (0, _crypto.createHash)(_constants.SHA); - hash.update(filename); - return 'cov_' + parseInt(hash.digest('hex').substr(0, 12), 16).toString(36); -} - -// VisitState holds the state of the visitor, provides helper functions -// and is the `this` for the individual coverage visitors. - -var VisitState = function () { - function VisitState(types, sourceFilePath, inputSourceMap) { - _classCallCheck(this, VisitState); - - this.varName = genVar(sourceFilePath); - this.attrs = {}; - this.nextIgnore = null; - this.cov = new _sourceCoverage.SourceCoverage(sourceFilePath); - - if (typeof inputSourceMap !== "undefined") { - this.cov.inputSourceMap(inputSourceMap); - } - this.types = types; - this.sourceMappingURL = null; - } - - // should we ignore the node? Yes, if specifically ignoring - // or if the node is generated. - - - _createClass(VisitState, [{ - key: 'shouldIgnore', - value: function shouldIgnore(path) { - return this.nextIgnore || !path.node.loc; - } - - // extract the ignore comment hint (next|if|else) or null - - }, { - key: 'hintFor', - value: function hintFor(node) { - var hint = null; - if (node.leadingComments) { - node.leadingComments.forEach(function (c) { - var v = (c.value || /* istanbul ignore next: paranoid check */"").trim(); - var groups = v.match(COMMENT_RE); - if (groups) { - hint = groups[1]; - } - }); - } - return hint; - } - - // extract a source map URL from comments and keep track of it - - }, { - key: 'maybeAssignSourceMapURL', - value: function maybeAssignSourceMapURL(node) { - var that = this; - var extractURL = function extractURL(comments) { - if (!comments) { - return; - } - comments.forEach(function (c) { - var v = (c.value || /* istanbul ignore next: paranoid check */"").trim(); - var groups = v.match(SOURCE_MAP_RE); - if (groups) { - that.sourceMappingURL = groups[1]; - } - }); - }; - extractURL(node.leadingComments); - extractURL(node.trailingComments); - } - - // for these expressions the statement counter needs to be hoisted, so - // function name inference can be preserved - - }, { - key: 'counterNeedsHoisting', - value: function counterNeedsHoisting(path) { - return path.isFunctionExpression() || path.isArrowFunctionExpression() || path.isClassExpression(); - } - - // all the generic stuff that needs to be done on enter for every node - - }, { - key: 'onEnter', - value: function onEnter(path) { - var n = path.node; - - this.maybeAssignSourceMapURL(n); - - // if already ignoring, nothing more to do - if (this.nextIgnore !== null) { - return; - } - // check hint to see if ignore should be turned on - var hint = this.hintFor(n); - if (hint === 'next') { - this.nextIgnore = n; - return; - } - // else check custom node attribute set by a prior visitor - if (this.getAttr(path.node, 'skip-all') !== null) { - this.nextIgnore = n; - } - } - - // all the generic stuff on exit of a node, - // including reseting ignores and custom node attrs - - }, { - key: 'onExit', - value: function onExit(path) { - // restore ignore status, if needed - if (path.node === this.nextIgnore) { - this.nextIgnore = null; - } - // nuke all attributes for the node - delete path.node.__cov__; - } - - // set a node attribute for the supplied node - - }, { - key: 'setAttr', - value: function setAttr(node, name, value) { - node.__cov__ = node.__cov__ || {}; - node.__cov__[name] = value; - } - - // retrieve a node attribute for the supplied node or null - - }, { - key: 'getAttr', - value: function getAttr(node, name) { - var c = node.__cov__; - if (!c) { - return null; - } - return c[name]; - } - - // - - }, { - key: 'increase', - value: function increase(type, id, index) { - var T = this.types; - var wrap = index !== null - // If `index` present, turn `x` into `x[index]`. - ? function (x) { - return T.memberExpression(x, T.numericLiteral(index), true); - } : function (x) { - return x; - }; - return T.updateExpression('++', wrap(T.memberExpression(T.memberExpression(T.identifier(this.varName), T.identifier(type)), T.numericLiteral(id), true))); - } - }, { - key: 'insertCounter', - value: function insertCounter(path, increment) { - var T = this.types; - if (path.isBlockStatement()) { - path.node.body.unshift(T.expressionStatement(increment)); - } else if (path.isStatement()) { - path.insertBefore(T.expressionStatement(increment)); - } else if (this.counterNeedsHoisting(path) && T.isVariableDeclarator(path.parentPath)) { - // make an attempt to hoist the statement counter, so that - // function names are maintained. - var parent = path.parentPath.parentPath; - if (parent && T.isExportNamedDeclaration(parent.parentPath)) { - parent.parentPath.insertBefore(T.expressionStatement(increment)); - } else if (parent && (T.isProgram(parent.parentPath) || T.isBlockStatement(parent.parentPath))) { - parent.insertBefore(T.expressionStatement(increment)); - } else { - path.replaceWith(T.sequenceExpression([increment, path.node])); - } - } else /* istanbul ignore else: not expected */if (path.isExpression()) { - path.replaceWith(T.sequenceExpression([increment, path.node])); - } else { - console.error('Unable to insert counter for node type:', path.node.type); - } - } - }, { - key: 'insertStatementCounter', - value: function insertStatementCounter(path) { - /* istanbul ignore if: paranoid check */ - if (!(path.node && path.node.loc)) { - return; - } - var index = this.cov.newStatement(path.node.loc); - var increment = this.increase('s', index, null); - this.insertCounter(path, increment); - } - }, { - key: 'insertFunctionCounter', - value: function insertFunctionCounter(path) { - var T = this.types; - /* istanbul ignore if: paranoid check */ - if (!(path.node && path.node.loc)) { - return; - } - var n = path.node; - - var dloc = null; - // get location for declaration - switch (n.type) { - case "FunctionDeclaration": - /* istanbul ignore else: paranoid check */ - if (n.id) { - dloc = n.id.loc; - } - break; - case "FunctionExpression": - if (n.id) { - dloc = n.id.loc; - } - break; - } - if (!dloc) { - dloc = { - start: n.loc.start, - end: { line: n.loc.start.line, column: n.loc.start.column + 1 } - }; - } - - var name = path.node.id ? path.node.id.name : path.node.name; - var index = this.cov.newFunction(name, dloc, path.node.body.loc); - var increment = this.increase('f', index, null); - var body = path.get('body'); - /* istanbul ignore else: not expected */ - if (body.isBlockStatement()) { - body.node.body.unshift(T.expressionStatement(increment)); - } else { - console.error('Unable to process function body node type:', path.node.type); - } - } - }, { - key: 'getBranchIncrement', - value: function getBranchIncrement(branchName, loc) { - var index = this.cov.addBranchPath(branchName, loc); - return this.increase('b', branchName, index); - } - }, { - key: 'insertBranchCounter', - value: function insertBranchCounter(path, branchName, loc) { - var increment = this.getBranchIncrement(branchName, loc || path.node.loc); - this.insertCounter(path, increment); - } - }, { - key: 'findLeaves', - value: function findLeaves(node, accumulator, parent, property) { - if (!node) { - return; - } - if (node.type === "LogicalExpression") { - var hint = this.hintFor(node); - if (hint !== 'next') { - this.findLeaves(node.left, accumulator, node, 'left'); - this.findLeaves(node.right, accumulator, node, 'right'); - } - } else { - accumulator.push({ - node: node, - parent: parent, - property: property - }); - } - } - }]); - - return VisitState; -}(); - -// generic function that takes a set of visitor methods and -// returns a visitor object with `enter` and `exit` properties, -// such that: -// -// * standard entry processing is done -// * the supplied visitors are called only when ignore is not in effect -// This relieves them from worrying about ignore states and generated nodes. -// * standard exit processing is done -// - - -function entries() { - var enter = Array.prototype.slice.call(arguments); - // the enter function - var wrappedEntry = function wrappedEntry(path, node) { - this.onEnter(path); - if (this.shouldIgnore(path)) { - return; - } - var that = this; - enter.forEach(function (e) { - e.call(that, path, node); - }); - }; - var exit = function exit(path, node) { - this.onExit(path, node); - }; - return { - enter: wrappedEntry, - exit: exit - }; -} - -function coverStatement(path) { - this.insertStatementCounter(path); -} - -/* istanbul ignore next: no node.js support */ -function coverAssignmentPattern(path) { - var n = path.node; - var b = this.cov.newBranch('default-arg', n.loc); - this.insertBranchCounter(path.get('right'), b); -} - -function coverFunction(path) { - this.insertFunctionCounter(path); -} - -function coverVariableDeclarator(path) { - this.insertStatementCounter(path.get('init')); -} - -function skipInit(path) { - if (path.node.init) { - this.setAttr(path.node.init, 'skip-all', true); - } -} - -function makeBlock(path) { - var T = this.types; - if (!path.node) { - path.replaceWith(T.blockStatement([])); - } - if (!path.isBlockStatement()) { - path.replaceWith(T.blockStatement([path.node])); - path.node.loc = path.node.body[0].loc; - } -} - -function blockProp(prop) { - return function (path) { - makeBlock.call(this, path.get(prop)); - }; -} - -function makeParenthesizedExpression(path) { - var T = this.types; - if (path.node) { - path.replaceWith(T.parenthesizedExpression(path.node)); - } -} - -function parenthesizedExpressionProp(prop) { - return function (path) { - makeParenthesizedExpression.call(this, path.get(prop)); - }; -} - -function convertArrowExpression(path) { - var n = path.node; - var T = this.types; - if (!T.isBlockStatement(n.body)) { - var bloc = n.body.loc; - if (n.expression === true) { - n.expression = false; - } - n.body = T.blockStatement([T.returnStatement(n.body)]); - // restore body location - n.body.loc = bloc; - // set up the location for the return statement so it gets - // instrumented - n.body.body[0].loc = bloc; - } -} - -function coverIfBranches(path) { - var n = path.node, - hint = this.hintFor(n), - ignoreIf = hint === 'if', - ignoreElse = hint === 'else', - branch = this.cov.newBranch('if', n.loc); - - if (ignoreIf) { - this.setAttr(n.consequent, 'skip-all', true); - } else { - this.insertBranchCounter(path.get('consequent'), branch, n.loc); - } - if (ignoreElse) { - this.setAttr(n.alternate, 'skip-all', true); - } else { - this.insertBranchCounter(path.get('alternate'), branch, n.loc); - } -} - -function createSwitchBranch(path) { - var b = this.cov.newBranch('switch', path.node.loc); - this.setAttr(path.node, 'branchName', b); -} - -function coverSwitchCase(path) { - var T = this.types; - var b = this.getAttr(path.parentPath.node, 'branchName'); - /* istanbul ignore if: paranoid check */ - if (b === null) { - throw new Error('Unable to get switch branch name'); - } - var increment = this.getBranchIncrement(b, path.node.loc); - path.node.consequent.unshift(T.expressionStatement(increment)); -} - -function coverTernary(path) { - var n = path.node, - branch = this.cov.newBranch('cond-expr', path.node.loc), - cHint = this.hintFor(n.consequent), - aHint = this.hintFor(n.alternate); - - if (cHint !== 'next') { - this.insertBranchCounter(path.get('consequent'), branch); - } - if (aHint !== 'next') { - this.insertBranchCounter(path.get('alternate'), branch); - } -} - -function coverLogicalExpression(path) { - var T = this.types; - if (path.parentPath.node.type === "LogicalExpression") { - return; // already processed - } - var leaves = []; - this.findLeaves(path.node, leaves); - var b = this.cov.newBranch("binary-expr", path.node.loc); - for (var i = 0; i < leaves.length; i += 1) { - var leaf = leaves[i]; - var hint = this.hintFor(leaf.node); - if (hint === 'next') { - continue; - } - var increment = this.getBranchIncrement(b, leaf.node.loc); - if (!increment) { - continue; - } - leaf.parent[leaf.property] = T.sequenceExpression([increment, leaf.node]); - } -} - -var codeVisitor = { - ArrowFunctionExpression: entries(convertArrowExpression, coverFunction), - AssignmentPattern: entries(coverAssignmentPattern), - BlockStatement: entries(), // ignore processing only - ClassMethod: entries(coverFunction), - ClassDeclaration: entries(parenthesizedExpressionProp('superClass')), - ExpressionStatement: entries(coverStatement), - BreakStatement: entries(coverStatement), - ContinueStatement: entries(coverStatement), - DebuggerStatement: entries(coverStatement), - ReturnStatement: entries(coverStatement), - ThrowStatement: entries(coverStatement), - TryStatement: entries(coverStatement), - VariableDeclaration: entries(), // ignore processing only - VariableDeclarator: entries(coverVariableDeclarator), - IfStatement: entries(blockProp('consequent'), blockProp('alternate'), coverStatement, coverIfBranches), - ForStatement: entries(blockProp('body'), skipInit, coverStatement), - ForInStatement: entries(blockProp('body'), skipInit, coverStatement), - ForOfStatement: entries(blockProp('body'), skipInit, coverStatement), - WhileStatement: entries(blockProp('body'), coverStatement), - DoWhileStatement: entries(blockProp('body'), coverStatement), - SwitchStatement: entries(createSwitchBranch, coverStatement), - SwitchCase: entries(coverSwitchCase), - WithStatement: entries(blockProp('body'), coverStatement), - FunctionDeclaration: entries(coverFunction), - FunctionExpression: entries(coverFunction), - LabeledStatement: entries(coverStatement), - ConditionalExpression: entries(coverTernary), - LogicalExpression: entries(coverLogicalExpression) -}; -// the template to insert at the top of the program. -var coverageTemplate = (0, _babelTemplate2.default)('\n var COVERAGE_VAR = (function () {\n var path = PATH,\n hash = HASH,\n Function = (function(){}).constructor,\n global = (new Function(\'return this\'))(),\n gcv = GLOBAL_COVERAGE_VAR,\n coverageData = INITIAL,\n coverage = global[gcv] || (global[gcv] = {});\n if (coverage[path] && coverage[path].hash === hash) {\n return coverage[path];\n }\n coverageData.hash = hash;\n return coverage[path] = coverageData;\n })();\n'); -// the rewire plugin (and potentially other babel middleware) -// may cause files to be instrumented twice, see: -// https://github.com/istanbuljs/babel-plugin-istanbul/issues/94 -// we should only instrument code for coverage the first time -// it's run through istanbul-lib-instrument. -function alreadyInstrumented(path, visitState) { - return path.scope.hasBinding(visitState.varName); -} -function shouldIgnoreFile(programNode) { - return programNode.parent && programNode.parent.comments.some(function (c) { - return COMMENT_FILE_RE.test(c.value); - }); -} -/** - * programVisitor is a `babel` adaptor for instrumentation. - * It returns an object with two methods `enter` and `exit`. - * These should be assigned to or called from `Program` entry and exit functions - * in a babel visitor. - * These functions do not make assumptions about the state set by Babel and thus - * can be used in a context other than a Babel plugin. - * - * The exit function returns an object that currently has the following keys: - * - * `fileCoverage` - the file coverage object created for the source file. - * `sourceMappingURL` - any source mapping URL found when processing the file. - * - * @param {Object} types - an instance of babel-types - * @param {string} sourceFilePath - the path to source file - * @param {Object} opts - additional options - * @param {string} [opts.coverageVariable=__coverage__] the global coverage variable name. - * @param {object} [opts.inputSourceMap=undefined] the input source map, that maps the uninstrumented code back to the - * original code. - */ -function programVisitor(types) { - var sourceFilePath = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'unknown.js'; - var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { coverageVariable: '__coverage__', inputSourceMap: undefined }; - - var T = types; - var visitState = new VisitState(types, sourceFilePath, opts.inputSourceMap); - return { - enter: function enter(path) { - if (shouldIgnoreFile(path.find(function (p) { - return p.isProgram(); - }))) { - return; - } - if (alreadyInstrumented(path, visitState)) { - return; - } - path.traverse(codeVisitor, visitState); - }, - exit: function exit(path) { - if (alreadyInstrumented(path, visitState)) { - return; - } - visitState.cov.freeze(); - var coverageData = visitState.cov.toJSON(); - if (shouldIgnoreFile(path.find(function (p) { - return p.isProgram(); - }))) { - return { fileCoverage: coverageData, sourceMappingURL: visitState.sourceMappingURL }; - } - coverageData[_constants.MAGIC_KEY] = _constants.MAGIC_VALUE; - var hash = (0, _crypto.createHash)(_constants.SHA).update(JSON.stringify(coverageData)).digest('hex'); - var coverageNode = T.valueToNode(coverageData); - delete coverageData[_constants.MAGIC_KEY]; - var cv = coverageTemplate({ - GLOBAL_COVERAGE_VAR: T.stringLiteral(opts.coverageVariable), - COVERAGE_VAR: T.identifier(visitState.varName), - PATH: T.stringLiteral(sourceFilePath), - INITIAL: coverageNode, - HASH: T.stringLiteral(hash) - }); - cv._blockHoist = 5; - path.node.body.unshift(cv); - return { - fileCoverage: coverageData, - sourceMappingURL: visitState.sourceMappingURL - }; - } - }; -} - -exports.default = programVisitor;
\ No newline at end of file |
