Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): fully remove third-party sourcema…
Browse files Browse the repository at this point in the history
…ps when disabled in esbuild builder

When using the esbuild-based browser application builder, third-party sourcemaps will now be fully removed
when the `sourcemap` option's `vendor` sub-option is disabled. The `vendor` sub-option is disabled by default
and is only enabled if explicitly enabled within the project's configuration. Sourcemaps are considered
third-party if their referencing code is contained within a `node_modules` directory.
Previously, sourcemap URL comments may have been unintentionally left intact when processing third-party code
via the Babel-based JavaScript transformer. These sourcemap URL comments are now removed correctly when
code is both transformed and return directly when no transformation is required.

(cherry picked from commit 0c94254)
  • Loading branch information
clydin authored and dgp1130 committed Apr 14, 2023
1 parent 890497f commit f72155b
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async function transformWithBabel({
const result = await transformAsync(data, {
filename,
inputSourceMap: (useInputSourcemap ? undefined : false) as undefined,
sourceMaps: options.sourcemap ? 'inline' : false,
sourceMaps: useInputSourcemap ? 'inline' : false,
compact: false,
configFile: false,
babelrc: false,
Expand All @@ -94,5 +94,11 @@ async function transformWithBabel({
],
});

return result?.code ?? data;
const outputCode = result?.code ?? data;

// Strip sourcemaps if they should not be used.
// Babel will keep the original comments even if sourcemaps are disabled.
return useInputSourcemap
? outputCode
: outputCode.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, '');
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,14 @@ export class JavaScriptTransformer {
forceAsyncTransformation = data.includes('async') && /async(?:\s+function)?\s*\*/.test(data);

if (!forceAsyncTransformation) {
return Buffer.from(data, 'utf-8');
const keepSourcemap =
this.#commonOptions.sourcemap &&
(!!this.#commonOptions.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));

return Buffer.from(
keepSourcemap ? data : data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''),
'utf-8',
);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/**
* @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.io/license
*/

import { buildEsbuildBrowser } from '../../index';
import { BASE_OPTIONS, BROWSER_BUILDER_INFO, describeBuilder } from '../setup';

describeBuilder(buildEsbuildBrowser, BROWSER_BUILDER_INFO, (harness) => {
describe('Option: "sourceMap"', () => {
it('should not generate script sourcemap files by default', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
sourceMap: undefined,
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/main.js.map').toNotExist();
});

it('should not generate script sourcemap files when false', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
sourceMap: false,
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/main.js.map').toNotExist();
});

it('should not generate script sourcemap files when scripts suboption is false', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
sourceMap: { scripts: false },
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/main.js.map').toNotExist();
});

it('should generate script sourcemap files when true', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
sourceMap: true,
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/main.js.map').toExist();
});

it('should generate script sourcemap files when scripts suboption is true', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
sourceMap: { scripts: true },
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/main.js.map').toExist();
});

it('should not include third-party sourcemaps when true', async () => {
await harness.writeFile('src/polyfills.js', `console.log('main');`);

harness.useTarget('build', {
...BASE_OPTIONS,
sourceMap: true,
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/main.js.map').content.not.toContain('/core/index.ts');
harness.expectFile('dist/main.js.map').content.not.toContain('/common/index.ts');
});

it('should not include third-party sourcemaps when vendor suboption is false', async () => {
await harness.writeFile('src/polyfills.js', `console.log('main');`);

harness.useTarget('build', {
...BASE_OPTIONS,
sourceMap: { scripts: true, vendor: false },
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/main.js.map').content.not.toContain('/core/index.ts');
harness.expectFile('dist/main.js.map').content.not.toContain('/common/index.ts');
});

it('should include third-party sourcemaps when vendor suboption is true', async () => {
await harness.writeFile('src/polyfills.js', `console.log('main');`);

harness.useTarget('build', {
...BASE_OPTIONS,
sourceMap: { scripts: true, vendor: true },
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/main.js.map').content.toContain('/core/index.ts');
harness.expectFile('dist/main.js.map').content.toContain('/common/index.ts');
});
});
});

0 comments on commit f72155b

Please sign in to comment.