From 9ff2c1d37b7c8b890fa88568f953b7560731a21f Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:56:00 -0500 Subject: [PATCH] refactor(@angular/build): remove unnecessary source-map-support polyfill for Vitest browser coverage Removes the injection of the source-map-support library in the Vitest builder. This workaround was previously required for correct stack traces in browser mode when coverage was enabled but is no longer necessary. This change simplifies the plugin logic and ensures source maps are consistently handled. --- .../unit-test/runners/vitest/plugins.ts | 41 +------------------ tests/e2e/tests/vitest/browser-sourcemaps.ts | 17 ++++++++ 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts index 22c5993eabe2..666bfcc260af 100644 --- a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts +++ b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts @@ -114,15 +114,6 @@ export async function createVitestConfigPlugin( delete config.plugins; } - // Add browser source map support if coverage is enabled - if ( - (browser || testConfig?.browser?.enabled) && - (options.coverage.enabled || testConfig?.coverage?.enabled) - ) { - projectPlugins.unshift(createSourcemapSupportPlugin()); - setupFiles.unshift('virtual:source-map-support'); - } - const projectResolver = createRequire(projectSourceRoot + '/').resolve; const projectDefaults: UserWorkspaceConfig = { @@ -276,7 +267,7 @@ export function createVitestPlugins(pluginOptions: PluginOptions): VitestPlugins const map = sourceMapText ? JSON.parse(sourceMapText) : undefined; if (map) { - adjustSourcemapSources(map, !vitestConfig?.coverage?.enabled, workspaceRoot, id); + adjustSourcemapSources(map, true, workspaceRoot, id); } return { @@ -343,36 +334,6 @@ function adjustSourcemapSources( } } -function createSourcemapSupportPlugin(): VitestPlugins[0] { - return { - name: 'angular:source-map-support', - enforce: 'pre', - resolveId(source) { - if (source.includes('virtual:source-map-support')) { - return '\0source-map-support'; - } - }, - async load(id) { - if (id !== '\0source-map-support') { - return; - } - - const packageResolve = createRequire(__filename).resolve; - const supportPath = packageResolve('source-map-support/browser-source-map-support.js'); - - const content = await readFile(supportPath, 'utf-8'); - - // The `source-map-support` library currently relies on `this` being defined in the global scope. - // However, when running in an ESM environment, `this` is undefined. - // To workaround this, we patch the library to use `globalThis` instead of `this`. - return ( - content.replaceAll(/this\.(define|sourceMapSupport|base64js)/g, 'globalThis.$1') + - '\n;globalThis.sourceMapSupport.install();' - ); - }, - }; -} - async function generateCoverageOption( optionsCoverage: NormalizedUnitTestBuilderOptions['coverage'], configCoverage: VitestCoverageOption | undefined, diff --git a/tests/e2e/tests/vitest/browser-sourcemaps.ts b/tests/e2e/tests/vitest/browser-sourcemaps.ts index 90c04457c7c8..f272d3dbd49d 100644 --- a/tests/e2e/tests/vitest/browser-sourcemaps.ts +++ b/tests/e2e/tests/vitest/browser-sourcemaps.ts @@ -7,6 +7,7 @@ import { stripVTControlCharacters } from 'node:util'; export default async function (): Promise { await applyVitestBuilder(); + await installPackage('@vitest/coverage-v8'); await installPackage('playwright@1'); await installPackage('@vitest/browser-playwright@4'); await ng('generate', 'component', 'my-comp'); @@ -37,4 +38,20 @@ export default async function (): Promise { 'Expected stack trace to point to the source file.', ); } + + // Again but with coverage + try { + await noSilentNg('test', '--no-watch', '--coverage', '--browsers', 'chromiumHeadless'); + throw new Error('Expected "ng test" to fail.'); + } catch (error: any) { + const stdout = stripVTControlCharacters(error.stdout || error.message); + // We expect the failure from failing.spec.ts + assert.match(stdout, /1 failed/, 'Expected 1 test to fail.'); + // Check that the stack trace points to the correct file + assert.match( + stdout, + /\bsrc[\/\\]app[\/\\]failing\.spec\.ts:4:\d+/, + 'Expected stack trace to point to the source file.', + ); + } }