diff options
Diffstat (limited to 'node_modules/istanbul-lib-instrument')
| -rw-r--r-- | node_modules/istanbul-lib-instrument/CHANGELOG.md | 617 | ||||
| -rw-r--r-- | node_modules/istanbul-lib-instrument/LICENSE | 24 | ||||
| -rw-r--r-- | node_modules/istanbul-lib-instrument/README.md | 22 | ||||
| -rw-r--r-- | node_modules/istanbul-lib-instrument/package.json | 50 | ||||
| -rw-r--r-- | node_modules/istanbul-lib-instrument/src/constants.js | 14 | ||||
| -rw-r--r-- | node_modules/istanbul-lib-instrument/src/index.js | 21 | ||||
| -rw-r--r-- | node_modules/istanbul-lib-instrument/src/instrumenter.js | 160 | ||||
| -rw-r--r-- | node_modules/istanbul-lib-instrument/src/read-coverage.js | 77 | ||||
| -rw-r--r-- | node_modules/istanbul-lib-instrument/src/source-coverage.js | 135 | ||||
| -rw-r--r-- | node_modules/istanbul-lib-instrument/src/visitor.js | 746 | 
10 files changed, 1866 insertions, 0 deletions
diff --git a/node_modules/istanbul-lib-instrument/CHANGELOG.md b/node_modules/istanbul-lib-instrument/CHANGELOG.md new file mode 100644 index 0000000..3bbf41c --- /dev/null +++ b/node_modules/istanbul-lib-instrument/CHANGELOG.md @@ -0,0 +1,617 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [5.1.0](https://www.github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument-v5.0.4...istanbul-lib-instrument-v5.1.0) (2021-10-27) + + +### Features + +* option to evaluate logical truthiness, for applications such as fuzzing ([#629](https://www.github.com/istanbuljs/istanbuljs/issues/629)) ([a743b84](https://www.github.com/istanbuljs/istanbuljs/commit/a743b8442e977f0c77ffa282eed7ac84ca200d1f)) + +### [5.0.4](https://www.github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument-v5.0.3...istanbul-lib-instrument-v5.0.4) (2021-10-16) + + +### Bug Fixes + +* **magic-value:** make incrementing magic value a manual step ([#641](https://www.github.com/istanbuljs/istanbuljs/issues/641)) ([823010b](https://www.github.com/istanbuljs/istanbuljs/commit/823010b821cf81bd91377d75fc83f0875925db66)) + +### [5.0.3](https://www.github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument-v5.0.2...istanbul-lib-instrument-v5.0.3) (2021-10-06) + + +### Bug Fixes + +* coverage.branchMap else location. ([#633](https://www.github.com/istanbuljs/istanbuljs/issues/633)) ([eb4b4ec](https://www.github.com/istanbuljs/istanbuljs/commit/eb4b4ec8f4b858655a66b0033fcc662f44ef4cc9)) + +### [5.0.2](https://www.github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument-v5.0.1...istanbul-lib-instrument-v5.0.2) (2021-09-13) + + +### Bug Fixes + +* **build:** verfiy automated publication ([b232690](https://www.github.com/istanbuljs/istanbuljs/commit/b232690193f4b524332046c96dd1cdc6e881c6c7)) + +### [5.0.1](https://www.github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument-v5.0.0...istanbul-lib-instrument-v5.0.1) (2021-09-13) + + +### Bug Fixes + +* **build:** verfiy automated publication ([74c96bd](https://www.github.com/istanbuljs/istanbuljs/commit/74c96bdc4224a06e2e1166ebd9adf8faf28438b1)) + +## [5.0.0](https://www.github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument-v4.0.3...istanbul-lib-instrument-v5.0.0) (2021-09-13) + + +### ⚠ BREAKING CHANGES + +* istanbul-lib-instrument no longer uses babel + +### Code Refactoring + +* istanbul-lib-instrument no longer uses babel ([8d3badb](https://www.github.com/istanbuljs/istanbuljs/commit/8d3badb8f6c9a4bed9af8e19c3ac6459ebd7267b)) + +## [4.0.3](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@4.0.2...istanbul-lib-instrument@4.0.3) (2020-05-09) + + +### Bug Fixes + +* Prevent readInitialCoverage from reading babel config ([#562](https://github.com/istanbuljs/istanbuljs/issues/562)) ([49b4745](https://github.com/istanbuljs/istanbuljs/commit/49b474525c15e703642916011bd86f663aca0c3d)) + + + + + +## [4.0.2](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@4.0.1...istanbul-lib-instrument@4.0.2) (2020-05-06) + + +### Bug Fixes + +* Add ts-ignore to reassignment of generated function ([#557](https://github.com/istanbuljs/istanbuljs/issues/557)) ([817efb0](https://github.com/istanbuljs/istanbuljs/commit/817efb04fc161efae426b2231a0221606b09f559)) +* Use @babel/core for all babel imports. ([#555](https://github.com/istanbuljs/istanbuljs/issues/555)) ([a99a13e](https://github.com/istanbuljs/istanbuljs/commit/a99a13ee6931fc124a2a723c3f511cdbcb0aa81d)) + + + + + +## [4.0.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@4.0.0...istanbul-lib-instrument@4.0.1) (2020-02-03) + + +### Bug Fixes + +* Always call coverage initialization function ([#524](https://github.com/istanbuljs/istanbuljs/issues/524)) ([c6536c1](https://github.com/istanbuljs/istanbuljs/commit/c6536c14bf0663ca7e0493dd40ea132b05352594)) + + + + + +# [4.0.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@4.0.0-alpha.3...istanbul-lib-instrument@4.0.0) (2019-12-20) + +**Note:** Version bump only for package istanbul-lib-instrument + + + + + +# [4.0.0-alpha.3](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@4.0.0-alpha.2...istanbul-lib-instrument@4.0.0-alpha.3) (2019-12-07) + +**Note:** Version bump only for package istanbul-lib-instrument + + + + + +# [4.0.0-alpha.2](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@4.0.0-alpha.1...istanbul-lib-instrument@4.0.0-alpha.2) (2019-11-01) + + +### Bug Fixes + +* Produce properly merged source-maps when inputSourceMap is provided ([#487](https://github.com/istanbuljs/istanbuljs/issues/487)) ([8f8c88e](https://github.com/istanbuljs/istanbuljs/commit/8f8c88e3a2add4c08729e41e356aa7981dc69d4d)) + + + + + +# [4.0.0-alpha.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@4.0.0-alpha.0...istanbul-lib-instrument@4.0.0-alpha.1) (2019-10-06) + + +### Bug Fixes + +* Eliminate babel hoisting of the coverage variable ([#481](https://github.com/istanbuljs/istanbuljs/issues/481)) ([8dfbcba](https://github.com/istanbuljs/istanbuljs/commit/8dfbcba)), closes [#92](https://github.com/istanbuljs/istanbuljs/issues/92) +* Honor ignore hints in chained if statements ([#469](https://github.com/istanbuljs/istanbuljs/issues/469)) ([a629770](https://github.com/istanbuljs/istanbuljs/commit/a629770)), closes [#468](https://github.com/istanbuljs/istanbuljs/issues/468) +* Populate lastFileCoverage for already instrumented files ([#470](https://github.com/istanbuljs/istanbuljs/issues/470)) ([ea6d779](https://github.com/istanbuljs/istanbuljs/commit/ea6d779)), closes [istanbuljs/nyc#594](https://github.com/istanbuljs/nyc/issues/594) + + +### Features + +* Use @istanbuljs/schema to pull defaults ([#485](https://github.com/istanbuljs/istanbuljs/issues/485)) ([87e27f3](https://github.com/istanbuljs/istanbuljs/commit/87e27f3)), closes [#460](https://github.com/istanbuljs/istanbuljs/issues/460) + + +### BREAKING CHANGES + +* The defaults for `autoWrap`, `preserveComments`, +`esModules` and `produceSourceMap` are now true.  This applies only to +the stand-alone instrumenter, the visitor does not use these options. +* The `flow` and `jsx` parser plugins are no longer +enabled by default.  This applies only to the stand-alone instrumenter, +the visitor does not use this option. +* The `plugins` option of the stand-alone instrumenter +has been renamed to `parserPlugins` to match nyc. + + + + + +# [4.0.0-alpha.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@3.3.0...istanbul-lib-instrument@4.0.0-alpha.0) (2019-06-19) + + +### Features + +* Update dependencies, require Node.js 8 ([#401](https://github.com/istanbuljs/istanbuljs/issues/401)) ([bf3a539](https://github.com/istanbuljs/istanbuljs/commit/bf3a539)) + + +### BREAKING CHANGES + +* Node.js 8 is now required + + + + + +# [3.3.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@3.2.0...istanbul-lib-instrument@3.3.0) (2019-04-24) + + +### Features + +* Enable classProperties and classPrivateProperties parsers and coverage. ([#379](https://github.com/istanbuljs/istanbuljs/issues/379)) ([c09dc38](https://github.com/istanbuljs/istanbuljs/commit/c09dc38)) + + + + + +# [3.2.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@3.1.2...istanbul-lib-instrument@3.2.0) (2019-04-09) + + +### Features + +* Add bigInt and importMeta to default parser plugins. ([#356](https://github.com/istanbuljs/istanbuljs/issues/356)) ([fb4d6ed](https://github.com/istanbuljs/istanbuljs/commit/fb4d6ed)), closes [#338](https://github.com/istanbuljs/istanbuljs/issues/338) + + + + + +## [3.1.2](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@3.1.1...istanbul-lib-instrument@3.1.2) (2019-04-03) + + +### Bug Fixes + +* Be more friendly to ts-node. ([#352](https://github.com/istanbuljs/istanbuljs/issues/352)) ([40d15f5](https://github.com/istanbuljs/istanbuljs/commit/40d15f5)), closes [#336](https://github.com/istanbuljs/istanbuljs/issues/336) + + + + + +## [3.1.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@3.1.0...istanbul-lib-instrument@3.1.1) (2019-03-12) + + +### Bug Fixes + +* Honor istanbul ignore next hints placed before export statement. ([#298](https://github.com/istanbuljs/istanbuljs/issues/298)) ([f24795d](https://github.com/istanbuljs/istanbuljs/commit/f24795d)), closes [#297](https://github.com/istanbuljs/istanbuljs/issues/297) + + + + + +# [3.1.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@3.0.1...istanbul-lib-instrument@3.1.0) (2019-01-26) + + +### Features + +* dont skip for loop initialization instrumentation ([#188](https://github.com/istanbuljs/istanbuljs/issues/188)) ([2e0258e](https://github.com/istanbuljs/istanbuljs/commit/2e0258e)) +* New options coverageGlobalScope and coverageGlobalScopeFunc. ([#200](https://github.com/istanbuljs/istanbuljs/issues/200)) ([25509c7](https://github.com/istanbuljs/istanbuljs/commit/25509c7)), closes [#199](https://github.com/istanbuljs/istanbuljs/issues/199) + + + + + +<a name="3.0.1"></a> +## [3.0.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@3.0.0...istanbul-lib-instrument@3.0.1) (2018-12-25) + + + + +**Note:** Version bump only for package istanbul-lib-instrument + +<a name="3.0.0"></a> +# [3.0.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@2.3.2...istanbul-lib-instrument@3.0.0) (2018-09-06) + + +### Chores + +* Update test for babel 7. ([#218](https://github.com/istanbuljs/istanbuljs/issues/218)) ([9cf4d43](https://github.com/istanbuljs/istanbuljs/commit/9cf4d43)), closes [#205](https://github.com/istanbuljs/istanbuljs/issues/205) + + +### Features + +* Add option plugins ([#205](https://github.com/istanbuljs/istanbuljs/issues/205)) ([312f81f](https://github.com/istanbuljs/istanbuljs/commit/312f81f)) +* Update babel to 7.0.0. ([#215](https://github.com/istanbuljs/istanbuljs/issues/215)) ([8a96613](https://github.com/istanbuljs/istanbuljs/commit/8a96613)) + + +### BREAKING CHANGES + +* was added which requires an option for the `decorators` +plugin.  Add it to get tests working again, commit updated api.md. + + + + +<a name="2.3.2"></a> +## [2.3.2](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@2.3.1...istanbul-lib-instrument@2.3.2) (2018-07-24) + + + + +**Note:** Version bump only for package istanbul-lib-instrument + +<a name="2.3.1"></a> +## [2.3.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@2.3.0...istanbul-lib-instrument@2.3.1) (2018-07-07) + + +### Bug Fixes + +* Don't ignore src/visitor.js for self test. ([#194](https://github.com/istanbuljs/istanbuljs/issues/194)) ([71b815d](https://github.com/istanbuljs/istanbuljs/commit/71b815d)) + + + + +<a name="2.3.0"></a> +# [2.3.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@2.2.1...istanbul-lib-instrument@2.3.0) (2018-06-27) + + +### Features + +* update pinned babel version to latest release. ([#189](https://github.com/istanbuljs/istanbuljs/issues/189)) ([ac8ec07](https://github.com/istanbuljs/istanbuljs/commit/ac8ec07)) + + + + +<a name="2.2.1"></a> +## [2.2.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@2.2.0...istanbul-lib-instrument@2.2.1) (2018-06-26) + + +### Bug Fixes + +* Instrument ObjectMethod's. ([#182](https://github.com/istanbuljs/istanbuljs/issues/182)) ([126f09d](https://github.com/istanbuljs/istanbuljs/commit/126f09d)) +* update default args test guard to work on supported versions. ([#185](https://github.com/istanbuljs/istanbuljs/issues/185)) ([955511a](https://github.com/istanbuljs/istanbuljs/commit/955511a)) + + + + +<a name="2.2.0"></a> +# [2.2.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@2.0.2...istanbul-lib-instrument@2.2.0) (2018-06-06) + + +### Features + +* add support for optional catch binding ([#175](https://github.com/istanbuljs/istanbuljs/issues/175)) ([088dd9f](https://github.com/istanbuljs/istanbuljs/commit/088dd9f)) + + + + +<a name="2.1.0"></a> +# [2.1.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@2.0.2...istanbul-lib-instrument@2.1.0) (2018-05-31) + + +### Features + +* add support for optional catch binding ([#175](https://github.com/istanbuljs/istanbuljs/issues/175)) ([088dd9f](https://github.com/istanbuljs/istanbuljs/commit/088dd9f)) + + + + +<a name="2.0.2"></a> +## [2.0.2](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@2.0.1...istanbul-lib-instrument@2.0.2) (2018-05-31) + + + + +**Note:** Version bump only for package istanbul-lib-instrument + +<a name="2.0.1"></a> +## [2.0.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@2.0.0...istanbul-lib-instrument@2.0.1) (2018-05-31) + + +### Bug Fixes + +* should import [@babel](https://github.com/babel)/template ([85a0d1a](https://github.com/istanbuljs/istanbuljs/commit/85a0d1a)) + + + + +<a name="2.0.0"></a> +# [2.0.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.10.1...istanbul-lib-instrument@2.0.0) (2018-05-31) + + +### Bug Fixes + +* parenthesize superClass on non-idetifier case ([#158](https://github.com/istanbuljs/istanbuljs/issues/158)) ([6202c88](https://github.com/istanbuljs/istanbuljs/commit/6202c88)) + + +### Chores + +* upgrade babel in instrumenter ([#174](https://github.com/istanbuljs/istanbuljs/issues/174)) ([ce23e91](https://github.com/istanbuljs/istanbuljs/commit/ce23e91)) + + +### BREAKING CHANGES + +* babel@7 drops Node@4 support + + + + +<a name="1.10.1"></a> +## [1.10.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.10.0...istanbul-lib-instrument@1.10.1) (2018-03-09) + + +### Bug Fixes + +* default value for ignorelassMethods ([#151](https://github.com/istanbuljs/istanbuljs/issues/151)) ([5dd88e8](https://github.com/istanbuljs/istanbuljs/commit/5dd88e8)) + + + + +<a name="1.10.0"></a> +# [1.10.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.9.2...istanbul-lib-instrument@1.10.0) (2018-03-04) + + +### Features + +* allows an array of ignored method names to be provided ([#127](https://github.com/istanbuljs/istanbuljs/issues/127)) ([67918e2](https://github.com/istanbuljs/istanbuljs/commit/67918e2)) + + + + +<a name="1.9.2"></a> +## [1.9.2](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.9.1...istanbul-lib-instrument@1.9.2) (2018-02-13) + + +### Bug Fixes + +* compatibility with babel 7 ([#135](https://github.com/istanbuljs/istanbuljs/issues/135)) ([6cac849](https://github.com/istanbuljs/istanbuljs/commit/6cac849)) +* handle instrumentation when a function is called Function ([#131](https://github.com/istanbuljs/istanbuljs/issues/131)) ([b12a07e](https://github.com/istanbuljs/istanbuljs/commit/b12a07e)) +* proper passing of the preserveComments option to babel ([#122](https://github.com/istanbuljs/istanbuljs/issues/122)) ([470bb0e](https://github.com/istanbuljs/istanbuljs/commit/470bb0e)) +* update instrument, account for lack of arrow expression ([#119](https://github.com/istanbuljs/istanbuljs/issues/119)) ([#125](https://github.com/istanbuljs/istanbuljs/issues/125)) ([0968206](https://github.com/istanbuljs/istanbuljs/commit/0968206)) + + + + +<a name="1.9.1"></a> +## [1.9.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.9.0...istanbul-lib-instrument@1.9.1) (2017-10-22) + + +### Bug Fixes + +* address issue with class instrumentation ([#111](https://github.com/istanbuljs/istanbuljs/issues/111)) ([cbd1c14](https://github.com/istanbuljs/istanbuljs/commit/cbd1c14)) + + + + +<a name="1.9.0"></a> +# [1.9.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.8.0...istanbul-lib-instrument@1.9.0) (2017-10-21) + + +### Bug Fixes + +* support conditional expression for superClass ([#106](https://github.com/istanbuljs/istanbuljs/issues/106)) ([aae256f](https://github.com/istanbuljs/istanbuljs/commit/aae256f)) + + +### Features + +* add support for ignoring entire files ([#108](https://github.com/istanbuljs/istanbuljs/issues/108)) ([f12da65](https://github.com/istanbuljs/istanbuljs/commit/f12da65)) + + + + +<a name="1.8.0"></a> +# [1.8.0](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.7.5...istanbul-lib-instrument@1.8.0) (2017-09-05) + + +### Features + +* add support for object-spread syntax ([#82](https://github.com/istanbuljs/istanbuljs/issues/82)) ([28d5566](https://github.com/istanbuljs/istanbuljs/commit/28d5566)) + + + + +<a name="1.7.5"></a> +## [1.7.5](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.7.4...istanbul-lib-instrument@1.7.5) (2017-08-23) + + +### Bug Fixes + +* name of function is now preserved or named exports ([#79](https://github.com/istanbuljs/istanbuljs/issues/79)) ([2ce8974](https://github.com/istanbuljs/istanbuljs/commit/2ce8974)) + + + + +<a name="1.7.4"></a> +## [1.7.4](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.7.3...istanbul-lib-instrument@1.7.4) (2017-07-16) + + +### Bug Fixes + +* update increment operator to appropriate expression type ([#74](https://github.com/istanbuljs/istanbuljs/issues/74)) ([dc69e66](https://github.com/istanbuljs/istanbuljs/commit/dc69e66)) + + + + +<a name="1.7.3"></a> +## [1.7.3](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.7.2...istanbul-lib-instrument@1.7.3) (2017-06-25) + + + + +<a name="1.7.2"></a> +## [1.7.2](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-instrument@1.7.1...istanbul-lib-instrument@1.7.2) (2017-05-27) + + +### Bug Fixes + +* hoist statement counter for class variables, so that name is preserved ([#60](https://github.com/istanbuljs/istanbuljs/issues/60)) ([120d221](https://github.com/istanbuljs/istanbuljs/commit/120d221)) + + + + +<a name="1.7.1"></a> +## [1.7.1](https://github.com/istanbuljs/istanbul-lib-instrument/compare/istanbul-lib-instrument@1.7.0...istanbul-lib-instrument@1.7.1) (2017-04-29) + + +### Bug Fixes + +* don't instrument a file if it has already been instrumented ([#38](https://github.com/istanbuljs/istanbuljs/issues/38)) ([9c38e4e](https://github.com/istanbuljs/istanbul-lib-instrument/commit/9c38e4e)) + + + + +<a name="1.7.0"></a> +# [1.7.0](https://github.com/istanbuljs/istanbul-lib-instrument/compare/istanbul-lib-instrument@1.6.2...istanbul-lib-instrument@1.7.0) (2017-03-27) + + +### Features + +* use extended babylon support; adding features such as jsx ([#22](https://github.com/istanbuljs/istanbuljs/issues/22)) ([11c2438](https://github.com/istanbuljs/istanbul-lib-instrument/commit/11c2438)) + +<a name="1.6.2"></a> +## [1.6.2](https://github.com/istanbuljs/istanbul-lib-instrument/compare/istanbul-lib-instrument@1.6.1...istanbul-lib-instrument@1.6.2) (2017-03-22) + + +### Bug Fixes + +* loc is sometimes not defined, so loc.start fails see [#99](https://github.com/istanbuljs/istanbuljs/issues/99) ([#18](https://github.com/istanbuljs/istanbuljs/issues/18)) ([df85ba6](https://github.com/istanbuljs/istanbul-lib-instrument/commit/df85ba6)) + +<a name="1.6.1"></a> +## [1.6.1](https://github.com/istanbuljs/istanbul-lib-instrument/compare/istanbul-lib-instrument@1.6.0...istanbul-lib-instrument@1.6.1) (2017-03-21) + +<a name="1.6.0"></a> +# [1.6.0](https://github.com/istanbuljs/istanbul-lib-instrument/compare/istanbul-lib-instrument@1.4.2...istanbul-lib-instrument@1.6.0) (2017-03-21) + + +### Features + +* adds line number property back to coverage.json ([b03b927](https://github.com/istanbuljs/istanbul-lib-instrument/commit/b03b927)) + +<a name="1.4.2"></a> +## [1.4.2](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.4.1...v1.4.2) (2017-01-04) + + +### Bug Fixes + +* only hoist counter for a smaller subset of function declarations ([9f8931e](https://github.com/istanbuljs/istanbul-lib-instrument/commit/9f8931e)) + + + +<a name="1.4.1"></a> +## [1.4.1](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.4.0...v1.4.1) (2017-01-04) + + +### Bug Fixes + +* address regression discussed in https://github.com/istanbuljs/babel-plugin-istanbul/issues/78 ([#40](https://github.com/istanbuljs/istanbul-lib-instrument/issues/40)) ([7f458a3](https://github.com/istanbuljs/istanbul-lib-instrument/commit/7f458a3)) + + + +<a name="1.4.0"></a> +# [1.4.0](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.3.1...v1.4.0) (2017-01-02) + + +### Features + +* preserve inferred function names ([#38](https://github.com/istanbuljs/istanbul-lib-instrument/issues/38)) ([312666e](https://github.com/istanbuljs/istanbul-lib-instrument/commit/312666e)) + + + +<a name="1.3.1"></a> +## [1.3.1](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.3.0...v1.3.1) (2016-12-27) + + +### Bug Fixes + +* function declaration assignment now retains function name ([#33](https://github.com/istanbuljs/istanbul-lib-instrument/issues/33)) ([2d781da](https://github.com/istanbuljs/istanbul-lib-instrument/commit/2d781da)) + + + +<a name="1.3.0"></a> +# [1.3.0](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.2.0...v1.3.0) (2016-11-10) + + +### Features + +* allow an input source-map to be passed to instrumentSync()  ([#23](https://github.com/istanbuljs/istanbul-lib-instrument/issues/23)) ([b08e4f5](https://github.com/istanbuljs/istanbul-lib-instrument/commit/b08e4f5)) + + + +<a name="1.2.0"></a> +# [1.2.0](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.1.4...v1.2.0) (2016-10-25) + + +### Features + +* implement function to extract empty coverage data from an instrumented file ([#28](https://github.com/istanbuljs/istanbul-lib-instrument/issues/28)) ([06d0ef6](https://github.com/istanbuljs/istanbul-lib-instrument/commit/06d0ef6)) + + + +<a name="1.1.4"></a> +## [1.1.4](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.1.3...v1.1.4) (2016-10-17) + + +### Bug Fixes + +* hoist coverage variable to very top of file ([#26](https://github.com/istanbuljs/istanbul-lib-instrument/issues/26)) ([0225e8c](https://github.com/istanbuljs/istanbul-lib-instrument/commit/0225e8c)) + + + +<a name="1.1.3"></a> +## [1.1.3](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.1.2...v1.1.3) (2016-09-13) + + +### Performance Improvements + +* simplify coverage variable naming https://github.com/istanbuljs/istanbul-lib-instrument/pull/24 ([7252aae](https://github.com/istanbuljs/istanbul-lib-instrument/commit/7252aae)) + + + +<a name="1.1.2"></a> +## [1.1.2](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.1.1...v1.1.2) (2016-09-08) + + +### Performance Improvements + +* use zero-based numeric indices for much faster instrumented code ([#22](https://github.com/istanbuljs/istanbul-lib-instrument/issues/22)) ([5b401f5](https://github.com/istanbuljs/istanbul-lib-instrument/commit/5b401f5)) + + + +<a name="1.1.1"></a> +## [1.1.1](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.1.0...v1.1.1) (2016-08-30) + + +### Bug Fixes + +* upgrade istanbul-lib-coverage ([eb9b1f6](https://github.com/istanbuljs/istanbul-lib-instrument/commit/eb9b1f6)) + + + +<a name="1.1.0"></a> +# [1.1.0](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.1.0-alpha.4...v1.1.0) (2016-08-11) + + +### Bug Fixes + +* guard against invalid loc ([#16](https://github.com/istanbuljs/istanbul-lib-instrument/issues/16)) ([23ebfc3](https://github.com/istanbuljs/istanbul-lib-instrument/commit/23ebfc3)) + + + +<a name="1.1.0-alpha.4"></a> +# [1.1.0-alpha.4](https://github.com/istanbuljs/istanbul-lib-instrument/compare/v1.0.0-alpha.5...v1.1.0-alpha.4) (2016-07-20) + + +### Bug Fixes + +* require more performant babel-generator ([#15](https://github.com/istanbuljs/istanbul-lib-instrument/issues/15)) ([21b2563](https://github.com/istanbuljs/istanbul-lib-instrument/commit/21b2563)) diff --git a/node_modules/istanbul-lib-instrument/LICENSE b/node_modules/istanbul-lib-instrument/LICENSE new file mode 100644 index 0000000..d55d291 --- /dev/null +++ b/node_modules/istanbul-lib-instrument/LICENSE @@ -0,0 +1,24 @@ +Copyright 2012-2015 Yahoo! Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +    * Redistributions of source code must retain the above copyright +      notice, this list of conditions and the following disclaimer. +    * Redistributions in binary form must reproduce the above copyright +      notice, this list of conditions and the following disclaimer in the +      documentation and/or other materials provided with the distribution. +    * Neither the name of the Yahoo! Inc. nor the +      names of its contributors may be used to endorse or promote products +      derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/istanbul-lib-instrument/README.md b/node_modules/istanbul-lib-instrument/README.md new file mode 100644 index 0000000..902831c --- /dev/null +++ b/node_modules/istanbul-lib-instrument/README.md @@ -0,0 +1,22 @@ +## istanbul-lib-instrument + +[](https://travis-ci.org/istanbuljs/istanbul-lib-instrument) + +Istanbul instrumenter library. + +Version 1.1.x now implements instrumentation using `Babel`. The implementation is inspired +by prior art by @dtinth as demonstrated in the `__coverage__` babel plugin. + +It provides 2 "modes" of instrumentation. + +-   The old API that is mostly unchanged (except for incompatibilities noted) and +    performs the instrumentation using babel as a library. + +-   A `programVisitor` function for the Babel AST that can be used by a Babel plugin +    to emit instrumentation for ES6 code directly without any source map +    processing. This is the preferred path for babel users. The Babel plugin is +    called `babel-plugin-istanbul`. + +Incompatibilities and changes to instrumentation behavior can be found in +[v0-changes.md](v0-changes.md). + diff --git a/node_modules/istanbul-lib-instrument/package.json b/node_modules/istanbul-lib-instrument/package.json new file mode 100644 index 0000000..cf344c1 --- /dev/null +++ b/node_modules/istanbul-lib-instrument/package.json @@ -0,0 +1,50 @@ +{ +  "name": "istanbul-lib-instrument", +  "version": "5.1.0", +  "description": "Core istanbul API for JS code coverage", +  "author": "Krishnan Anantheswaran <kananthmail-github@yahoo.com>", +  "main": "src/index.js", +  "files": [ +    "src" +  ], +  "scripts": { +    "test": "nyc mocha" +  }, +  "dependencies": { +    "@babel/core": "^7.12.3", +    "@babel/parser": "^7.14.7", +    "@istanbuljs/schema": "^0.1.2", +    "istanbul-lib-coverage": "^3.2.0", +    "semver": "^6.3.0" +  }, +  "devDependencies": { +    "@babel/cli": "^7.7.5", +    "chai": "^4.2.0", +    "clone": "^2.1.2", +    "debug": "^4.1.1", +    "documentation": "^12.1.4", +    "js-yaml": "^3.13.1", +    "mocha": "^6.2.3", +    "nopt": "^4.0.1", +    "nyc": "^15.1.0" +  }, +  "license": "BSD-3-Clause", +  "bugs": { +    "url": "https://github.com/istanbuljs/istanbuljs/issues" +  }, +  "homepage": "https://istanbul.js.org/", +  "repository": { +    "type": "git", +    "url": "git+ssh://git@github.com/istanbuljs/istanbuljs.git", +    "directory": "packages/istanbul-lib-instrument" +  }, +  "keywords": [ +    "coverage", +    "istanbul", +    "js", +    "instrumentation" +  ], +  "engines": { +    "node": ">=8" +  } +} diff --git a/node_modules/istanbul-lib-instrument/src/constants.js b/node_modules/istanbul-lib-instrument/src/constants.js new file mode 100644 index 0000000..2cd402b --- /dev/null +++ b/node_modules/istanbul-lib-instrument/src/constants.js @@ -0,0 +1,14 @@ +const { createHash } = require('crypto'); +const { name } = require('../package.json'); +// TODO: increment this version if there are schema changes +// that are not backwards compatible: +const VERSION = '4'; + +const SHA = 'sha1'; +module.exports = { +    SHA, +    MAGIC_KEY: '_coverageSchema', +    MAGIC_VALUE: createHash(SHA) +        .update(name + '@' + VERSION) +        .digest('hex') +}; diff --git a/node_modules/istanbul-lib-instrument/src/index.js b/node_modules/istanbul-lib-instrument/src/index.js new file mode 100644 index 0000000..33d2a4c --- /dev/null +++ b/node_modules/istanbul-lib-instrument/src/index.js @@ -0,0 +1,21 @@ +const { defaults } = require('@istanbuljs/schema'); +const Instrumenter = require('./instrumenter'); +const programVisitor = require('./visitor'); +const readInitialCoverage = require('./read-coverage'); + +/** + * createInstrumenter creates a new instrumenter with the + * supplied options. + * @param {Object} opts - instrumenter options. See the documentation + * for the Instrumenter class. + */ +function createInstrumenter(opts) { +    return new Instrumenter(opts); +} + +module.exports = { +    createInstrumenter, +    programVisitor, +    readInitialCoverage, +    defaultOpts: defaults.instrumenter +}; diff --git a/node_modules/istanbul-lib-instrument/src/instrumenter.js b/node_modules/istanbul-lib-instrument/src/instrumenter.js new file mode 100644 index 0000000..95743c7 --- /dev/null +++ b/node_modules/istanbul-lib-instrument/src/instrumenter.js @@ -0,0 +1,160 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +const { transformSync } = require('@babel/core'); +const { defaults } = require('@istanbuljs/schema'); +const programVisitor = require('./visitor'); +const readInitialCoverage = require('./read-coverage'); + +/** + * Instrumenter is the public API for the instrument library. + * It is typically used for ES5 code. For ES6 code that you + * are already running under `babel` use the coverage plugin + * instead. + * @param {Object} opts optional. + * @param {string} [opts.coverageVariable=__coverage__] name of global coverage variable. + * @param {boolean} [opts.reportLogic=false] report boolean value of logical expressions. + * @param {boolean} [opts.preserveComments=false] preserve comments in output. + * @param {boolean} [opts.compact=true] generate compact code. + * @param {boolean} [opts.esModules=false] set to true to instrument ES6 modules. + * @param {boolean} [opts.autoWrap=false] set to true to allow `return` statements outside of functions. + * @param {boolean} [opts.produceSourceMap=false] set to true to produce a source map for the instrumented code. + * @param {Array} [opts.ignoreClassMethods=[]] set to array of class method names to ignore for coverage. + * @param {Function} [opts.sourceMapUrlCallback=null] a callback function that is called when a source map URL + *     is found in the original code. This function is called with the source file name and the source map URL. + * @param {boolean} [opts.debug=false] - turn debugging on. + * @param {array} [opts.parserPlugins] - set babel parser plugins, see @istanbuljs/schema for defaults. + */ +class Instrumenter { +    constructor(opts = {}) { +        this.opts = { +            ...defaults.instrumenter, +            ...opts +        }; +        this.fileCoverage = null; +        this.sourceMap = null; +    } +    /** +     * instrument the supplied code and track coverage against the supplied +     * filename. It throws if invalid code is passed to it. ES5 and ES6 syntax +     * is supported. To instrument ES6 modules, make sure that you set the +     * `esModules` property to `true` when creating the instrumenter. +     * +     * @param {string} code - the code to instrument +     * @param {string} filename - the filename against which to track coverage. +     * @param {object} [inputSourceMap] - the source map that maps the not instrumented code back to it's original form. +     * Is assigned to the coverage object and therefore, is available in the json output and can be used to remap the +     * coverage to the untranspiled source. +     * @returns {string} the instrumented code. +     */ +    instrumentSync(code, filename, inputSourceMap) { +        if (typeof code !== 'string') { +            throw new Error('Code must be a string'); +        } +        filename = filename || String(new Date().getTime()) + '.js'; +        const { opts } = this; +        let output = {}; +        const babelOpts = { +            configFile: false, +            babelrc: false, +            ast: true, +            filename: filename || String(new Date().getTime()) + '.js', +            inputSourceMap, +            sourceMaps: opts.produceSourceMap, +            compact: opts.compact, +            comments: opts.preserveComments, +            parserOpts: { +                allowReturnOutsideFunction: opts.autoWrap, +                sourceType: opts.esModules ? 'module' : 'script', +                plugins: opts.parserPlugins +            }, +            plugins: [ +                [ +                    ({ types }) => { +                        const ee = programVisitor(types, filename, { +                            coverageVariable: opts.coverageVariable, +                            reportLogic: opts.reportLogic, +                            coverageGlobalScope: opts.coverageGlobalScope, +                            coverageGlobalScopeFunc: +                                opts.coverageGlobalScopeFunc, +                            ignoreClassMethods: opts.ignoreClassMethods, +                            inputSourceMap +                        }); + +                        return { +                            visitor: { +                                Program: { +                                    enter: ee.enter, +                                    exit(path) { +                                        output = ee.exit(path); +                                    } +                                } +                            } +                        }; +                    } +                ] +            ] +        }; + +        const codeMap = transformSync(code, babelOpts); + +        if (!output || !output.fileCoverage) { +            const initialCoverage = +                readInitialCoverage(codeMap.ast) || +                /* istanbul ignore next: paranoid check */ {}; +            this.fileCoverage = initialCoverage.coverageData; +            this.sourceMap = inputSourceMap; +            return code; +        } + +        this.fileCoverage = output.fileCoverage; +        this.sourceMap = codeMap.map; +        const cb = this.opts.sourceMapUrlCallback; +        if (cb && output.sourceMappingURL) { +            cb(filename, output.sourceMappingURL); +        } + +        return codeMap.code; +    } +    /** +     * callback-style instrument method that calls back with an error +     * as opposed to throwing one. Note that in the current implementation, +     * the callback will be called in the same process tick and is not asynchronous. +     * +     * @param {string} code - the code to instrument +     * @param {string} filename - the filename against which to track coverage. +     * @param {Function} callback - the callback +     * @param {Object} inputSourceMap - the source map that maps the not instrumented code back to it's original form. +     * Is assigned to the coverage object and therefore, is available in the json output and can be used to remap the +     * coverage to the untranspiled source. +     */ +    instrument(code, filename, callback, inputSourceMap) { +        if (!callback && typeof filename === 'function') { +            callback = filename; +            filename = null; +        } +        try { +            const out = this.instrumentSync(code, filename, inputSourceMap); +            callback(null, out); +        } catch (ex) { +            callback(ex); +        } +    } +    /** +     * returns the file coverage object for the last file instrumented. +     * @returns {Object} the file coverage object. +     */ +    lastFileCoverage() { +        return this.fileCoverage; +    } +    /** +     * returns the source map produced for the last file instrumented. +     * @returns {null|Object} the source map object. +     */ +    lastSourceMap() { +        return this.sourceMap; +    } +} + +module.exports = Instrumenter; diff --git a/node_modules/istanbul-lib-instrument/src/read-coverage.js b/node_modules/istanbul-lib-instrument/src/read-coverage.js new file mode 100644 index 0000000..5b76dbb --- /dev/null +++ b/node_modules/istanbul-lib-instrument/src/read-coverage.js @@ -0,0 +1,77 @@ +const { parseSync, traverse } = require('@babel/core'); +const { defaults } = require('@istanbuljs/schema'); +const { MAGIC_KEY, MAGIC_VALUE } = require('./constants'); + +function getAst(code) { +    if (typeof code === 'object' && typeof code.type === 'string') { +        // Assume code is already a babel ast. +        return code; +    } + +    if (typeof code !== 'string') { +        throw new Error('Code must be a string'); +    } + +    // Parse as leniently as possible +    return parseSync(code, { +        babelrc: false, +        configFile: false, +        parserOpts: { +            allowAwaitOutsideFunction: true, +            allowImportExportEverywhere: true, +            allowReturnOutsideFunction: true, +            allowSuperOutsideMethod: true, +            sourceType: 'script', +            plugins: defaults.instrumenter.parserPlugins +        } +    }); +} + +module.exports = function readInitialCoverage(code) { +    const ast = getAst(code); + +    let covScope; +    traverse(ast, { +        ObjectProperty(path) { +            const { node } = path; +            if ( +                !node.computed && +                path.get('key').isIdentifier() && +                node.key.name === MAGIC_KEY +            ) { +                const magicValue = path.get('value').evaluate(); +                if (!magicValue.confident || magicValue.value !== MAGIC_VALUE) { +                    return; +                } +                covScope = +                    path.scope.getFunctionParent() || +                    path.scope.getProgramParent(); +                path.stop(); +            } +        } +    }); + +    if (!covScope) { +        return null; +    } + +    const result = {}; + +    for (const key of ['path', 'hash', 'gcv', 'coverageData']) { +        const binding = covScope.getOwnBinding(key); +        if (!binding) { +            return null; +        } +        const valuePath = binding.path.get('init'); +        const value = valuePath.evaluate(); +        if (!value.confident) { +            return null; +        } +        result[key] = value.value; +    } + +    delete result.coverageData[MAGIC_KEY]; +    delete result.coverageData.hash; + +    return result; +}; diff --git a/node_modules/istanbul-lib-instrument/src/source-coverage.js b/node_modules/istanbul-lib-instrument/src/source-coverage.js new file mode 100644 index 0000000..ec3f234 --- /dev/null +++ b/node_modules/istanbul-lib-instrument/src/source-coverage.js @@ -0,0 +1,135 @@ +const { classes } = require('istanbul-lib-coverage'); + +function cloneLocation(loc) { +    return { +        start: { +            line: loc && loc.start.line, +            column: loc && loc.start.column +        }, +        end: { +            line: loc && loc.end.line, +            column: loc && loc.end.column +        } +    }; +} +/** + * SourceCoverage provides mutation methods to manipulate the structure of + * a file coverage object. Used by the instrumenter to create a full coverage + * object for a file incrementally. + * + * @private + * @param pathOrObj {String|Object} - see the argument for {@link FileCoverage} + * @extends FileCoverage + * @constructor + */ +class SourceCoverage extends classes.FileCoverage { +    constructor(pathOrObj) { +        super(pathOrObj); +        this.meta = { +            last: { +                s: 0, +                f: 0, +                b: 0 +            } +        }; +    } + +    newStatement(loc) { +        const s = this.meta.last.s; +        this.data.statementMap[s] = cloneLocation(loc); +        this.data.s[s] = 0; +        this.meta.last.s += 1; +        return s; +    } + +    newFunction(name, decl, loc) { +        const f = this.meta.last.f; +        name = name || '(anonymous_' + f + ')'; +        this.data.fnMap[f] = { +            name, +            decl: cloneLocation(decl), +            loc: cloneLocation(loc), +            // DEPRECATED: some legacy reports require this info. +            line: loc && loc.start.line +        }; +        this.data.f[f] = 0; +        this.meta.last.f += 1; +        return f; +    } + +    newBranch(type, loc, isReportLogic = false) { +        const b = this.meta.last.b; +        this.data.b[b] = []; +        this.data.branchMap[b] = { +            loc: cloneLocation(loc), +            type, +            locations: [], +            // DEPRECATED: some legacy reports require this info. +            line: loc && loc.start.line +        }; +        this.meta.last.b += 1; +        this.maybeNewBranchTrue(type, b, isReportLogic); +        return b; +    } + +    maybeNewBranchTrue(type, name, isReportLogic) { +        if (!isReportLogic) { +            return; +        } +        if (type !== 'binary-expr') { +            return; +        } +        this.data.bT = this.data.bT || {}; +        this.data.bT[name] = []; +    } + +    addBranchPath(name, location) { +        const bMeta = this.data.branchMap[name]; +        const counts = this.data.b[name]; + +        /* istanbul ignore if: paranoid check */ +        if (!bMeta) { +            throw new Error('Invalid branch ' + name); +        } +        bMeta.locations.push(cloneLocation(location)); +        counts.push(0); +        this.maybeAddBranchTrue(name); +        return counts.length - 1; +    } + +    maybeAddBranchTrue(name) { +        if (!this.data.bT) { +            return; +        } +        const countsTrue = this.data.bT[name]; +        if (!countsTrue) { +            return; +        } +        countsTrue.push(0); +    } + +    /** +     * Assigns an input source map to the coverage that can be used +     * to remap the coverage output to the original source +     * @param sourceMap {object} the source map +     */ +    inputSourceMap(sourceMap) { +        this.data.inputSourceMap = sourceMap; +    } + +    freeze() { +        // prune empty branches +        const map = this.data.branchMap; +        const branches = this.data.b; +        const branchesT = this.data.bT || {}; +        Object.keys(map).forEach(b => { +            if (map[b].locations.length === 0) { +                delete map[b]; +                delete branches[b]; +                delete branchesT[b]; +            } +        }); +    } +} + +module.exports = { SourceCoverage }; diff --git a/node_modules/istanbul-lib-instrument/src/visitor.js b/node_modules/istanbul-lib-instrument/src/visitor.js new file mode 100644 index 0000000..64f9245 --- /dev/null +++ b/node_modules/istanbul-lib-instrument/src/visitor.js @@ -0,0 +1,746 @@ +const { createHash } = require('crypto'); +const { template } = require('@babel/core'); +const { defaults } = require('@istanbuljs/schema'); +const { SourceCoverage } = require('./source-coverage'); +const { SHA, MAGIC_KEY, MAGIC_VALUE } = require('./constants'); + +// pattern for istanbul to ignore a section +const COMMENT_RE = /^\s*istanbul\s+ignore\s+(if|else|next)(?=\W|$)/; +// pattern for istanbul to ignore the whole file +const COMMENT_FILE_RE = /^\s*istanbul\s+ignore\s+(file)(?=\W|$)/; +// source map URL pattern +const SOURCE_MAP_RE = /[#@]\s*sourceMappingURL=(.*)\s*$/m; + +// generate a variable name from hashing the supplied file path +function genVar(filename) { +    const hash = createHash(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. +class VisitState { +    constructor( +        types, +        sourceFilePath, +        inputSourceMap, +        ignoreClassMethods = [], +        reportLogic = false +    ) { +        this.varName = genVar(sourceFilePath); +        this.attrs = {}; +        this.nextIgnore = null; +        this.cov = new SourceCoverage(sourceFilePath); + +        if (typeof inputSourceMap !== 'undefined') { +            this.cov.inputSourceMap(inputSourceMap); +        } +        this.ignoreClassMethods = ignoreClassMethods; +        this.types = types; +        this.sourceMappingURL = null; +        this.reportLogic = reportLogic; +    } + +    // should we ignore the node? Yes, if specifically ignoring +    // or if the node is generated. +    shouldIgnore(path) { +        return this.nextIgnore || !path.node.loc; +    } + +    // extract the ignore comment hint (next|if|else) or null +    hintFor(node) { +        let hint = null; +        if (node.leadingComments) { +            node.leadingComments.forEach(c => { +                const v = ( +                    c.value || /* istanbul ignore next: paranoid check */ '' +                ).trim(); +                const groups = v.match(COMMENT_RE); +                if (groups) { +                    hint = groups[1]; +                } +            }); +        } +        return hint; +    } + +    // extract a source map URL from comments and keep track of it +    maybeAssignSourceMapURL(node) { +        const extractURL = comments => { +            if (!comments) { +                return; +            } +            comments.forEach(c => { +                const v = ( +                    c.value || /* istanbul ignore next: paranoid check */ '' +                ).trim(); +                const groups = v.match(SOURCE_MAP_RE); +                if (groups) { +                    this.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 +    counterNeedsHoisting(path) { +        return ( +            path.isFunctionExpression() || +            path.isArrowFunctionExpression() || +            path.isClassExpression() +        ); +    } + +    // all the generic stuff that needs to be done on enter for every node +    onEnter(path) { +        const 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 +        const 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; +        } + +        // else check for ignored class methods +        if ( +            path.isFunctionExpression() && +            this.ignoreClassMethods.some( +                name => path.node.id && name === path.node.id.name +            ) +        ) { +            this.nextIgnore = n; +            return; +        } +        if ( +            path.isClassMethod() && +            this.ignoreClassMethods.some(name => name === path.node.key.name) +        ) { +            this.nextIgnore = n; +            return; +        } +    } + +    // all the generic stuff on exit of a node, +    // including reseting ignores and custom node attrs +    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 +    setAttr(node, name, value) { +        node.__cov__ = node.__cov__ || {}; +        node.__cov__[name] = value; +    } + +    // retrieve a node attribute for the supplied node or null +    getAttr(node, name) { +        const c = node.__cov__; +        if (!c) { +            return null; +        } +        return c[name]; +    } + +    // +    increase(type, id, index) { +        const T = this.types; +        const wrap = +            index !== null +                ? // If `index` present, turn `x` into `x[index]`. +                  x => T.memberExpression(x, T.numericLiteral(index), true) +                : x => x; +        return T.updateExpression( +            '++', +            wrap( +                T.memberExpression( +                    T.memberExpression( +                        T.callExpression(T.identifier(this.varName), []), +                        T.identifier(type) +                    ), +                    T.numericLiteral(id), +                    true +                ) +            ) +        ); +    } + +    // Reads the logic expression conditions and conditionally increments truthy counter. +    increaseTrue(type, id, index, node) { +        const T = this.types; +        const tempName = `${this.varName}_temp`; + +        return T.sequenceExpression([ +            T.assignmentExpression( +                '=', +                T.memberExpression( +                    T.callExpression(T.identifier(this.varName), []), +                    T.identifier(tempName) +                ), +                node // Only evaluates once. +            ), +            T.parenthesizedExpression( +                T.conditionalExpression( +                    T.memberExpression( +                        T.callExpression(T.identifier(this.varName), []), +                        T.identifier(tempName) +                    ), +                    this.increase(type, id, index), +                    T.nullLiteral() +                ) +            ), +            T.memberExpression( +                T.callExpression(T.identifier(this.varName), []), +                T.identifier(tempName) +            ) +        ]); +    } + +    insertCounter(path, increment) { +        const 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. +            const 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])); +            } +        } /* istanbul ignore else: not expected */ else if ( +            path.isExpression() +        ) { +            path.replaceWith(T.sequenceExpression([increment, path.node])); +        } else { +            console.error( +                'Unable to insert counter for node type:', +                path.node.type +            ); +        } +    } + +    insertStatementCounter(path) { +        /* istanbul ignore if: paranoid check */ +        if (!(path.node && path.node.loc)) { +            return; +        } +        const index = this.cov.newStatement(path.node.loc); +        const increment = this.increase('s', index, null); +        this.insertCounter(path, increment); +    } + +    insertFunctionCounter(path) { +        const T = this.types; +        /* istanbul ignore if: paranoid check */ +        if (!(path.node && path.node.loc)) { +            return; +        } +        const n = path.node; + +        let dloc = null; +        // get location for declaration +        switch (n.type) { +            case 'FunctionDeclaration': +            case 'FunctionExpression': +                /* istanbul ignore else: paranoid check */ +                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 } +            }; +        } + +        const name = path.node.id ? path.node.id.name : path.node.name; +        const index = this.cov.newFunction(name, dloc, path.node.body.loc); +        const increment = this.increase('f', index, null); +        const 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 +            ); +        } +    } + +    getBranchIncrement(branchName, loc) { +        const index = this.cov.addBranchPath(branchName, loc); +        return this.increase('b', branchName, index); +    } + +    getBranchLogicIncrement(path, branchName, loc) { +        const index = this.cov.addBranchPath(branchName, loc); +        return [ +            this.increase('b', branchName, index), +            this.increaseTrue('bT', branchName, index, path.node) +        ]; +    } + +    insertBranchCounter(path, branchName, loc) { +        const increment = this.getBranchIncrement( +            branchName, +            loc || path.node.loc +        ); +        this.insertCounter(path, increment); +    } + +    findLeaves(node, accumulator, parent, property) { +        if (!node) { +            return; +        } +        if (node.type === 'LogicalExpression') { +            const 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, +                parent, +                property +            }); +        } +    } +} + +// 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(...enter) { +    // the enter function +    const wrappedEntry = function(path, node) { +        this.onEnter(path); +        if (this.shouldIgnore(path)) { +            return; +        } +        enter.forEach(e => { +            e.call(this, path, node); +        }); +    }; +    const exit = function(path, node) { +        this.onExit(path, node); +    }; +    return { +        enter: wrappedEntry, +        exit +    }; +} + +function coverStatement(path) { +    this.insertStatementCounter(path); +} + +/* istanbul ignore next: no node.js support */ +function coverAssignmentPattern(path) { +    const n = path.node; +    const 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 coverClassPropDeclarator(path) { +    this.insertStatementCounter(path.get('value')); +} + +function makeBlock(path) { +    const 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; +        path.node.body[0].leadingComments = path.node.leadingComments; +        path.node.leadingComments = undefined; +    } +} + +function blockProp(prop) { +    return function(path) { +        makeBlock.call(this, path.get(prop)); +    }; +} + +function makeParenthesizedExpressionForNonIdentifier(path) { +    const T = this.types; +    if (path.node && !path.isIdentifier()) { +        path.replaceWith(T.parenthesizedExpression(path.node)); +    } +} + +function parenthesizedExpressionProp(prop) { +    return function(path) { +        makeParenthesizedExpressionForNonIdentifier.call(this, path.get(prop)); +    }; +} + +function convertArrowExpression(path) { +    const n = path.node; +    const T = this.types; +    if (!T.isBlockStatement(n.body)) { +        const 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) { +    const n = path.node; +    const hint = this.hintFor(n); +    const ignoreIf = hint === 'if'; +    const ignoreElse = hint === 'else'; +    const 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); +    } +} + +function createSwitchBranch(path) { +    const b = this.cov.newBranch('switch', path.node.loc); +    this.setAttr(path.node, 'branchName', b); +} + +function coverSwitchCase(path) { +    const T = this.types; +    const b = this.getAttr(path.parentPath.node, 'branchName'); +    /* istanbul ignore if: paranoid check */ +    if (b === null) { +        throw new Error('Unable to get switch branch name'); +    } +    const increment = this.getBranchIncrement(b, path.node.loc); +    path.node.consequent.unshift(T.expressionStatement(increment)); +} + +function coverTernary(path) { +    const n = path.node; +    const branch = this.cov.newBranch('cond-expr', path.node.loc); +    const cHint = this.hintFor(n.consequent); +    const 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) { +    const T = this.types; +    if (path.parentPath.node.type === 'LogicalExpression') { +        return; // already processed +    } +    const leaves = []; +    this.findLeaves(path.node, leaves); +    const b = this.cov.newBranch( +        'binary-expr', +        path.node.loc, +        this.reportLogic +    ); +    for (let i = 0; i < leaves.length; i += 1) { +        const leaf = leaves[i]; +        const hint = this.hintFor(leaf.node); +        if (hint === 'next') { +            continue; +        } + +        if (this.reportLogic) { +            const increment = this.getBranchLogicIncrement( +                leaf, +                b, +                leaf.node.loc +            ); +            if (!increment[0]) { +                continue; +            } +            leaf.parent[leaf.property] = T.sequenceExpression([ +                increment[0], +                increment[1] +            ]); +            continue; +        } + +        const increment = this.getBranchIncrement(b, leaf.node.loc); +        if (!increment) { +            continue; +        } +        leaf.parent[leaf.property] = T.sequenceExpression([ +            increment, +            leaf.node +        ]); +    } +} + +const codeVisitor = { +    ArrowFunctionExpression: entries(convertArrowExpression, coverFunction), +    AssignmentPattern: entries(coverAssignmentPattern), +    BlockStatement: entries(), // ignore processing only +    ExportDefaultDeclaration: entries(), // ignore processing only +    ExportNamedDeclaration: entries(), // ignore processing only +    ClassMethod: entries(coverFunction), +    ClassDeclaration: entries(parenthesizedExpressionProp('superClass')), +    ClassProperty: entries(coverClassPropDeclarator), +    ClassPrivateProperty: entries(coverClassPropDeclarator), +    ObjectMethod: entries(coverFunction), +    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'), coverStatement), +    ForInStatement: entries(blockProp('body'), coverStatement), +    ForOfStatement: entries(blockProp('body'), 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) +}; +const globalTemplateAlteredFunction = template(` +        var Function = (function(){}).constructor; +        var global = (new Function(GLOBAL_COVERAGE_SCOPE))(); +`); +const globalTemplateFunction = template(` +        var global = (new Function(GLOBAL_COVERAGE_SCOPE))(); +`); +const globalTemplateVariable = template(` +        var global = GLOBAL_COVERAGE_SCOPE; +`); +// the template to insert at the top of the program. +const coverageTemplate = template( +    ` +    function COVERAGE_FUNCTION () { +        var path = PATH; +        var hash = HASH; +        GLOBAL_COVERAGE_TEMPLATE +        var gcv = GLOBAL_COVERAGE_VAR; +        var coverageData = INITIAL; +        var coverage = global[gcv] || (global[gcv] = {}); +        if (!coverage[path] || coverage[path].hash !== hash) { +            coverage[path] = coverageData; +        } + +        var actualCoverage = coverage[path]; +        { +            // @ts-ignore +            COVERAGE_FUNCTION = function () { +                return actualCoverage; +            } +        } + +        return actualCoverage; +    } +`, +    { preserveComments: true } +); +// 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(c => 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 {boolean} [opts.reportLogic=false] report boolean value of logical expressions. + * @param {string} [opts.coverageGlobalScope=this] the global coverage variable scope. + * @param {boolean} [opts.coverageGlobalScopeFunc=true] use an evaluated function to find coverageGlobalScope. + * @param {Array} [opts.ignoreClassMethods=[]] names of methods to ignore by default on classes. + * @param {object} [opts.inputSourceMap=undefined] the input source map, that maps the uninstrumented code back to the + * original code. + */ +function programVisitor(types, sourceFilePath = 'unknown.js', opts = {}) { +    const T = types; +    opts = { +        ...defaults.instrumentVisitor, +        ...opts +    }; +    const visitState = new VisitState( +        types, +        sourceFilePath, +        opts.inputSourceMap, +        opts.ignoreClassMethods, +        opts.reportLogic +    ); +    return { +        enter(path) { +            if (shouldIgnoreFile(path.find(p => p.isProgram()))) { +                return; +            } +            if (alreadyInstrumented(path, visitState)) { +                return; +            } +            path.traverse(codeVisitor, visitState); +        }, +        exit(path) { +            if (alreadyInstrumented(path, visitState)) { +                return; +            } +            visitState.cov.freeze(); +            const coverageData = visitState.cov.toJSON(); +            if (shouldIgnoreFile(path.find(p => p.isProgram()))) { +                return { +                    fileCoverage: coverageData, +                    sourceMappingURL: visitState.sourceMappingURL +                }; +            } +            coverageData[MAGIC_KEY] = MAGIC_VALUE; +            const hash = createHash(SHA) +                .update(JSON.stringify(coverageData)) +                .digest('hex'); +            coverageData.hash = hash; +            const coverageNode = T.valueToNode(coverageData); +            delete coverageData[MAGIC_KEY]; +            delete coverageData.hash; +            let gvTemplate; +            if (opts.coverageGlobalScopeFunc) { +                if (path.scope.getBinding('Function')) { +                    gvTemplate = globalTemplateAlteredFunction({ +                        GLOBAL_COVERAGE_SCOPE: T.stringLiteral( +                            'return ' + opts.coverageGlobalScope +                        ) +                    }); +                } else { +                    gvTemplate = globalTemplateFunction({ +                        GLOBAL_COVERAGE_SCOPE: T.stringLiteral( +                            'return ' + opts.coverageGlobalScope +                        ) +                    }); +                } +            } else { +                gvTemplate = globalTemplateVariable({ +                    GLOBAL_COVERAGE_SCOPE: opts.coverageGlobalScope +                }); +            } +            const cv = coverageTemplate({ +                GLOBAL_COVERAGE_VAR: T.stringLiteral(opts.coverageVariable), +                GLOBAL_COVERAGE_TEMPLATE: gvTemplate, +                COVERAGE_FUNCTION: T.identifier(visitState.varName), +                PATH: T.stringLiteral(sourceFilePath), +                INITIAL: coverageNode, +                HASH: T.stringLiteral(hash) +            }); +            // explicitly call this.varName to ensure coverage is always initialized +            path.node.body.unshift( +                T.expressionStatement( +                    T.callExpression(T.identifier(visitState.varName), []) +                ) +            ); +            path.node.body.unshift(cv); +            return { +                fileCoverage: coverageData, +                sourceMappingURL: visitState.sourceMappingURL +            }; +        } +    }; +} + +module.exports = programVisitor;  | 
