From fb2981dc4e0ac21f5389bb3b36d5853f8580e5a6 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:39:36 -0400 Subject: [PATCH] fix(@angular-devkit/build-angular): use istanbul-lib-instrument directly for karma code coverage The `istanbul-lib-instrument` package provides the required functionality needed to instrument code for test coverage within the context of the Angular CLI. Since the build pipeline already contains a customized babel preset, this package can be integrated directly into the pipeline. This reduces the number of dependencies required for `@angular-devkit/build-angular` including the deprecated `inflight` package. --- package.json | 2 +- .../angular_devkit/build_angular/BUILD.bazel | 2 +- .../angular_devkit/build_angular/package.json | 2 +- .../tools/babel/plugins/add-code-coverage.ts | 43 ++++++++ .../src/tools/babel/plugins/types.d.ts | 20 ++++ .../src/tools/babel/presets/application.ts | 8 +- yarn.lock | 97 ++++++------------- 7 files changed, 96 insertions(+), 78 deletions(-) create mode 100644 packages/angular_devkit/build_angular/src/tools/babel/plugins/add-code-coverage.ts create mode 100644 packages/angular_devkit/build_angular/src/tools/babel/plugins/types.d.ts diff --git a/package.json b/package.json index 98fec7bfaf9a..fdf70e248ff9 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,6 @@ "ansi-colors": "4.1.3", "autoprefixer": "10.4.19", "babel-loader": "9.1.3", - "babel-plugin-istanbul": "6.1.1", "browser-sync": "3.0.2", "browserslist": "^4.21.5", "buffer": "6.0.3", @@ -144,6 +143,7 @@ "https-proxy-agent": "7.0.4", "husky": "9.0.11", "ini": "4.1.3", + "istanbul-lib-instrument": "6.0.2", "jasmine": "^5.0.0", "jasmine-core": "~5.1.0", "jasmine-spec-reporter": "~7.0.0", diff --git a/packages/angular_devkit/build_angular/BUILD.bazel b/packages/angular_devkit/build_angular/BUILD.bazel index b21a2ef4a55a..ee677ac1ff9b 100644 --- a/packages/angular_devkit/build_angular/BUILD.bazel +++ b/packages/angular_devkit/build_angular/BUILD.bazel @@ -161,7 +161,6 @@ ts_library( "@npm//ansi-colors", "@npm//autoprefixer", "@npm//babel-loader", - "@npm//babel-plugin-istanbul", "@npm//browserslist", "@npm//copy-webpack-plugin", "@npm//critters", @@ -171,6 +170,7 @@ ts_library( "@npm//fast-glob", "@npm//http-proxy-middleware", "@npm//https-proxy-agent", + "@npm//istanbul-lib-instrument", "@npm//jsonc-parser", "@npm//karma", "@npm//karma-source-map-support", diff --git a/packages/angular_devkit/build_angular/package.json b/packages/angular_devkit/build_angular/package.json index 3d7e03eda822..86e5e58b873c 100644 --- a/packages/angular_devkit/build_angular/package.json +++ b/packages/angular_devkit/build_angular/package.json @@ -26,7 +26,6 @@ "ansi-colors": "4.1.3", "autoprefixer": "10.4.19", "babel-loader": "9.1.3", - "babel-plugin-istanbul": "6.1.1", "browserslist": "^4.21.5", "copy-webpack-plugin": "12.0.2", "critters": "0.0.22", @@ -35,6 +34,7 @@ "fast-glob": "3.3.2", "http-proxy-middleware": "3.0.0", "https-proxy-agent": "7.0.4", + "istanbul-lib-instrument": "6.0.2", "jsonc-parser": "3.2.1", "karma-source-map-support": "1.4.0", "less": "4.2.0", diff --git a/packages/angular_devkit/build_angular/src/tools/babel/plugins/add-code-coverage.ts b/packages/angular_devkit/build_angular/src/tools/babel/plugins/add-code-coverage.ts new file mode 100644 index 000000000000..efa95870f698 --- /dev/null +++ b/packages/angular_devkit/build_angular/src/tools/babel/plugins/add-code-coverage.ts @@ -0,0 +1,43 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { NodePath, PluginObj, types } from '@babel/core'; +import { Visitor, programVisitor } from 'istanbul-lib-instrument'; +import assert from 'node:assert'; + +/** + * A babel plugin factory function for adding istanbul instrumentation. + * + * @returns A babel plugin object instance. + */ +export default function (): PluginObj { + const visitors = new WeakMap(); + + return { + visitor: { + Program: { + enter(path, state) { + const visitor = programVisitor(types, state.filename, { + // Babel returns a Converter object from the `convert-source-map` package + inputSourceMap: (state.file.inputMap as undefined | { toObject(): object })?.toObject(), + }); + visitors.set(path, visitor); + + visitor.enter(path); + }, + exit(path) { + const visitor = visitors.get(path); + assert(visitor, 'Instrumentation visitor should always be present for program path.'); + + visitor.exit(path); + visitors.delete(path); + }, + }, + }, + }; +} diff --git a/packages/angular_devkit/build_angular/src/tools/babel/plugins/types.d.ts b/packages/angular_devkit/build_angular/src/tools/babel/plugins/types.d.ts new file mode 100644 index 000000000000..4ff052dcb136 --- /dev/null +++ b/packages/angular_devkit/build_angular/src/tools/babel/plugins/types.d.ts @@ -0,0 +1,20 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +declare module 'istanbul-lib-instrument' { + export interface Visitor { + enter(path: import('@babel/core').NodePath): void; + exit(path: import('@babel/core').NodePath): void; + } + + export function programVisitor( + types: typeof import('@babel/core').types, + filePath?: string, + options?: { inputSourceMap?: object | null }, + ): Visitor; +} diff --git a/packages/angular_devkit/build_angular/src/tools/babel/presets/application.ts b/packages/angular_devkit/build_angular/src/tools/babel/presets/application.ts index f7b780ac2e30..fb02e3337930 100644 --- a/packages/angular_devkit/build_angular/src/tools/babel/presets/application.ts +++ b/packages/angular_devkit/build_angular/src/tools/babel/presets/application.ts @@ -265,13 +265,7 @@ export default function (api: unknown, options: ApplicationPresetOptions) { } if (options.instrumentCode) { - plugins.push([ - require('babel-plugin-istanbul').default, - { - inputSourceMap: options.instrumentCode.inputSourceMap ?? false, - cwd: options.instrumentCode.includedBasePath, - }, - ]); + plugins.push(require('../plugins/add-code-coverage').default); } if (needRuntimeTransform) { diff --git a/yarn.lock b/yarn.lock index cc5605759c19..994b3fbfa0c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -84,7 +84,6 @@ __metadata: ansi-colors: "npm:4.1.3" autoprefixer: "npm:10.4.19" babel-loader: "npm:9.1.3" - babel-plugin-istanbul: "npm:6.1.1" browserslist: "npm:^4.21.5" copy-webpack-plugin: "npm:12.0.2" critters: "npm:0.0.22" @@ -94,6 +93,7 @@ __metadata: fast-glob: "npm:3.3.2" http-proxy-middleware: "npm:3.0.0" https-proxy-agent: "npm:7.0.4" + istanbul-lib-instrument: "npm:6.0.2" jsonc-parser: "npm:3.2.1" karma-source-map-support: "npm:1.4.0" less: "npm:4.2.0" @@ -689,7 +689,6 @@ __metadata: ansi-colors: "npm:4.1.3" autoprefixer: "npm:10.4.19" babel-loader: "npm:9.1.3" - babel-plugin-istanbul: "npm:6.1.1" browser-sync: "npm:3.0.2" browserslist: "npm:^4.21.5" buffer: "npm:6.0.3" @@ -711,6 +710,7 @@ __metadata: https-proxy-agent: "npm:7.0.4" husky: "npm:9.0.11" ini: "npm:4.1.3" + istanbul-lib-instrument: "npm:6.0.2" jasmine: "npm:^5.0.0" jasmine-core: "npm:~5.1.0" jasmine-spec-reporter: "npm:~7.0.0" @@ -1019,7 +1019,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:7.24.7, @babel/core@npm:^7.12.3, @babel/core@npm:^7.16.0": +"@babel/core@npm:7.24.7, @babel/core@npm:^7.12.3, @babel/core@npm:^7.16.0, @babel/core@npm:^7.23.9": version: 7.24.7 resolution: "@babel/core@npm:7.24.7" dependencies: @@ -1322,7 +1322,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.24.7": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.7": version: 7.24.7 resolution: "@babel/parser@npm:7.24.7" bin: @@ -3297,20 +3297,7 @@ __metadata: languageName: node linkType: hard -"@istanbuljs/load-nyc-config@npm:^1.0.0": - version: 1.1.0 - resolution: "@istanbuljs/load-nyc-config@npm:1.1.0" - dependencies: - camelcase: "npm:^5.3.1" - find-up: "npm:^4.1.0" - get-package-type: "npm:^0.1.0" - js-yaml: "npm:^3.13.1" - resolve-from: "npm:^5.0.0" - checksum: 10c0/dd2a8b094887da5a1a2339543a4933d06db2e63cbbc2e288eb6431bd832065df0c099d091b6a67436e71b7d6bf85f01ce7c15f9253b4cbebcc3b9a496165ba42 - languageName: node - linkType: hard - -"@istanbuljs/schema@npm:^0.1.2": +"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": version: 0.1.3 resolution: "@istanbuljs/schema@npm:0.1.3" checksum: 10c0/61c5286771676c9ca3eb2bd8a7310a9c063fb6e0e9712225c8471c582d157392c88f5353581c8c9adbe0dff98892317d2fdfc56c3499aa42e0194405206a963a @@ -7237,7 +7224,14 @@ __metadata: languageName: node linkType: hard -"argparse@npm:^1.0.7, argparse@npm:~1.0.9": +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e + languageName: node + linkType: hard + +"argparse@npm:~1.0.9": version: 1.0.10 resolution: "argparse@npm:1.0.10" dependencies: @@ -7246,13 +7240,6 @@ __metadata: languageName: node linkType: hard -"argparse@npm:^2.0.1": - version: 2.0.1 - resolution: "argparse@npm:2.0.1" - checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e - languageName: node - linkType: hard - "array-back@npm:^3.0.1, array-back@npm:^3.1.0": version: 3.1.0 resolution: "array-back@npm:3.1.0" @@ -7537,19 +7524,6 @@ __metadata: languageName: node linkType: hard -"babel-plugin-istanbul@npm:6.1.1": - version: 6.1.1 - resolution: "babel-plugin-istanbul@npm:6.1.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.0.0" - "@istanbuljs/load-nyc-config": "npm:^1.0.0" - "@istanbuljs/schema": "npm:^0.1.2" - istanbul-lib-instrument: "npm:^5.0.4" - test-exclude: "npm:^6.0.0" - checksum: 10c0/1075657feb705e00fd9463b329921856d3775d9867c5054b449317d39153f8fbcebd3e02ebf00432824e647faff3683a9ca0a941325ef1afe9b3c4dd51b24beb - languageName: node - linkType: hard - "babel-plugin-polyfill-corejs2@npm:^0.4.10": version: 0.4.11 resolution: "babel-plugin-polyfill-corejs2@npm:0.4.11" @@ -8054,7 +8028,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": +"camelcase@npm:^5.0.0": version: 5.3.1 resolution: "camelcase@npm:5.3.1" checksum: 10c0/92ff9b443bfe8abb15f2b1513ca182d16126359ad4f955ebc83dc4ddcc4ef3fdd2c078bc223f2673dc223488e75c99b16cc4d056624374b799e6a1555cf61b23 @@ -10084,7 +10058,7 @@ __metadata: languageName: node linkType: hard -"esprima@npm:^4.0.0, esprima@npm:^4.0.1": +"esprima@npm:^4.0.1": version: 4.0.1 resolution: "esprima@npm:4.0.1" bin: @@ -10795,13 +10769,6 @@ __metadata: languageName: node linkType: hard -"get-package-type@npm:^0.1.0": - version: 0.1.0 - resolution: "get-package-type@npm:0.1.0" - checksum: 10c0/e34cdf447fdf1902a1f6d5af737eaadf606d2ee3518287abde8910e04159368c268568174b2e71102b87b26c2020486f126bfca9c4fb1ceb986ff99b52ecd1be - languageName: node - linkType: hard - "get-stream@npm:^5.1.0": version: 5.2.0 resolution: "get-stream@npm:5.2.0" @@ -12149,7 +12116,20 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-instrument@npm:^5.0.4, istanbul-lib-instrument@npm:^5.1.0": +"istanbul-lib-instrument@npm:6.0.2": + version: 6.0.2 + resolution: "istanbul-lib-instrument@npm:6.0.2" + dependencies: + "@babel/core": "npm:^7.23.9" + "@babel/parser": "npm:^7.23.9" + "@istanbuljs/schema": "npm:^0.1.3" + istanbul-lib-coverage: "npm:^3.2.0" + semver: "npm:^7.5.4" + checksum: 10c0/405c6ac037bf8c7ee7495980b0cd5544b2c53078c10534d0c9ceeb92a9ea7dcf8510f58ccfce31336458a8fa6ccef27b570bbb602abaa8c1650f5496a807477c + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^5.1.0": version: 5.2.1 resolution: "istanbul-lib-instrument@npm:5.2.1" dependencies: @@ -12331,18 +12311,6 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^3.13.1": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" - dependencies: - argparse: "npm:^1.0.7" - esprima: "npm:^4.0.0" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/6746baaaeac312c4db8e75fa22331d9a04cccb7792d126ed8ce6a0bbcfef0cedaddd0c5098fade53db067c09fe00aa1c957674b4765610a8b06a5a189e46433b - languageName: node - linkType: hard - "jsbn@npm:1.1.0": version: 1.1.0 resolution: "jsbn@npm:1.1.0" @@ -15933,13 +15901,6 @@ __metadata: languageName: node linkType: hard -"resolve-from@npm:^5.0.0": - version: 5.0.0 - resolution: "resolve-from@npm:5.0.0" - checksum: 10c0/b21cb7f1fb746de8107b9febab60095187781137fd803e6a59a76d421444b1531b641bba5857f5dc011974d8a5c635d61cec49e6bd3b7fc20e01f0fafc4efbf2 - languageName: node - linkType: hard - "resolve-path@npm:^1.4.0": version: 1.4.0 resolution: "resolve-path@npm:1.4.0"