Skip to content

Commit 9f5862a

Browse files
committed
feat(@angular/build): move istanbul-lib-instrument to optional peer dependency
Move `istanbul-lib-instrument` from dependencies to optional peer dependencies. This helps reduce the transitive dependency count for new projects. BREAKING CHANGE: `istanbul-lib-instrument` is now an optional peer dependency. Projects using karma with code coverage enabled will need to ensure that istanbul-lib-instrument is installed. Note: `ng update` will automatically add this dependency during the update process.
1 parent 03e0acc commit 9f5862a

File tree

7 files changed

+48
-8
lines changed

7 files changed

+48
-8
lines changed

modules/testing/builder/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ ts_project(
2121
# resolvable in the test project.
2222
":node_modules/@angular/ssr",
2323
":node_modules/browser-sync",
24+
":node_modules/istanbul-lib-instrument",
2425
":node_modules/jsdom",
2526
":node_modules/ng-packagr",
2627
":node_modules/vitest",

modules/testing/builder/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"@angular/ssr": "workspace:*",
77
"@vitest/coverage-v8": "4.1.2",
88
"browser-sync": "3.0.4",
9+
"istanbul-lib-instrument": "6.0.3",
910
"jsdom": "29.0.1",
1011
"ng-packagr": "22.0.0-next.1",
1112
"rxjs": "7.8.2",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
"http-proxy": "^1.18.1",
108108
"http-proxy-middleware": "3.0.5",
109109
"husky": "9.1.7",
110+
"istanbul-lib-instrument": "6.0.3",
110111
"jasmine": "~6.1.0",
111112
"jasmine-core": "~6.1.0",
112113
"jasmine-reporters": "^2.5.2",

packages/angular/build/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
"browserslist": "^4.26.0",
3030
"esbuild": "0.27.3",
3131
"https-proxy-agent": "8.0.0",
32-
"istanbul-lib-instrument": "6.0.3",
3332
"jsonc-parser": "3.3.1",
3433
"listr2": "10.2.1",
3534
"magic-string": "0.30.21",
@@ -51,6 +50,7 @@
5150
"devDependencies": {
5251
"@angular-devkit/core": "workspace:*",
5352
"@angular/ssr": "workspace:*",
53+
"istanbul-lib-instrument": "6.0.3",
5454
"jsdom": "29.0.1",
5555
"less": "4.6.4",
5656
"ng-packagr": "22.0.0-next.1",
@@ -67,6 +67,7 @@
6767
"@angular/platform-server": "0.0.0-ANGULAR-FW-PEER-DEP",
6868
"@angular/service-worker": "0.0.0-ANGULAR-FW-PEER-DEP",
6969
"@angular/ssr": "^0.0.0-PLACEHOLDER",
70+
"istanbul-lib-instrument": "^6.0.0",
7071
"karma": "^6.4.0",
7172
"less": "^4.2.0",
7273
"ng-packagr": "0.0.0-NG-PACKAGR-PEER-DEP",
@@ -95,6 +96,9 @@
9596
"@angular/ssr": {
9697
"optional": true
9798
},
99+
"istanbul-lib-instrument": {
100+
"optional": true
101+
},
98102
"karma": {
99103
"optional": true
100104
},

packages/angular/build/src/tools/babel/plugins/add-code-coverage.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@
77
*/
88

99
import { NodePath, PluginObj, types } from '@babel/core';
10-
import { Visitor, programVisitor } from 'istanbul-lib-instrument';
10+
import type { Visitor } from 'istanbul-lib-instrument';
1111
import assert from 'node:assert';
1212

1313
/**
1414
* A babel plugin factory function for adding istanbul instrumentation.
1515
*
1616
* @returns A babel plugin object instance.
1717
*/
18-
export default function (): PluginObj {
18+
export default function (
19+
programVisitor: typeof import('istanbul-lib-instrument').programVisitor,
20+
): PluginObj {
1921
const visitors = new WeakMap<NodePath, Visitor>();
2022

2123
return {

packages/angular/build/src/tools/esbuild/javascript-transformer-worker.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import { type PluginItem, transformAsync } from '@babel/core';
1010
import fs from 'node:fs';
11+
import { createRequire } from 'node:module';
1112
import path from 'node:path';
1213
import Piscina from 'piscina';
1314

@@ -66,8 +67,32 @@ async function transformWithBabel(
6667
const plugins: PluginItem[] = [];
6768

6869
if (options.instrumentForCoverage) {
69-
const { default: coveragePlugin } = await import('../babel/plugins/add-code-coverage.js');
70-
plugins.push(coveragePlugin);
70+
try {
71+
let resolvedPath = 'istanbul-lib-instrument';
72+
try {
73+
const requireFn = createRequire(filename);
74+
resolvedPath = requireFn.resolve('istanbul-lib-instrument');
75+
} catch {
76+
// Fallback to pool worker import traversal
77+
}
78+
79+
const istanbul = await import(resolvedPath);
80+
const programVisitor = istanbul.programVisitor ?? istanbul.default?.programVisitor;
81+
82+
if (!programVisitor) {
83+
throw new Error('programVisitor is not available in istanbul-lib-instrument.');
84+
}
85+
86+
const { default: coveragePluginFactory } =
87+
await import('../babel/plugins/add-code-coverage.js');
88+
plugins.push(coveragePluginFactory(programVisitor));
89+
} catch (error) {
90+
const details = error instanceof Error ? error.message : String(error);
91+
throw new Error(
92+
`The 'istanbul-lib-instrument' package is required for code coverage but was not found or failed to load. Details: ${details}`,
93+
{ cause: error },
94+
);
95+
}
7196
}
7297

7398
if (shouldLink) {

pnpm-lock.yaml

Lines changed: 9 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)