| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| Expand Up | @@ -10,6 +10,10 @@ import { Architect } from '@angular-devkit/architect'; | |
| import * as path from 'path'; | ||
| import { browserBuild, createArchitect, host } from '../../../testing/test-utils'; | ||
|
|
||
| // Following the naming conventions from | ||
| // https://sourcemaps.info/spec.html#h.ghqpj1ytqjbm | ||
| const IGNORE_LIST = 'x_google_ignoreList'; | ||
|
|
||
| describe('Browser Builder external source map', () => { | ||
| const target = { project: 'app', target: 'build' }; | ||
| let architect: Architect; | ||
| Expand Down Expand Up | @@ -50,3 +54,70 @@ describe('Browser Builder external source map', () => { | |
| expect(hasTsSourcePaths).toBe(false, `vendor.js.map not should have '.ts' extentions`); | ||
| }); | ||
| }); | ||
|
|
||
| describe('Identifying third-party code in source maps', () => { | ||
|
Comment thread
Copy link
Copy Markdown
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityIt's prefer if new tests were created using the new test harness. https://github.com/angular/angular-cli/tree/56320245a126481816a8ccfb0cc248a00be49561/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior But I guess we can migrate this as a whole eventually.
Sorry, something went wrong.
All reactions
|
||
| interface SourceMap { | ||
| sources: string[]; | ||
| [IGNORE_LIST]: number[]; | ||
| } | ||
|
|
||
| const target = { project: 'app', target: 'build' }; | ||
| let architect: Architect; | ||
|
|
||
| beforeEach(async () => { | ||
| await host.initialize().toPromise(); | ||
| architect = (await createArchitect(host.root())).architect; | ||
| }); | ||
| afterEach(async () => host.restore().toPromise()); | ||
|
|
||
| it('specifies which sources are third party when vendor processing is disabled', async () => { | ||
| const overrides = { | ||
| sourceMap: { | ||
| scripts: true, | ||
| vendor: false, | ||
| }, | ||
| }; | ||
|
|
||
| const { files } = await browserBuild(architect, host, target, overrides); | ||
| const mainMap: SourceMap = JSON.parse(await files['main.js.map']); | ||
| const polyfillsMap: SourceMap = JSON.parse(await files['polyfills.js.map']); | ||
| const runtimeMap: SourceMap = JSON.parse(await files['runtime.js.map']); | ||
| const vendorMap: SourceMap = JSON.parse(await files['vendor.js.map']); | ||
|
|
||
| expect(mainMap[IGNORE_LIST]).not.toBeUndefined(); | ||
| expect(polyfillsMap[IGNORE_LIST]).not.toBeUndefined(); | ||
| expect(runtimeMap[IGNORE_LIST]).not.toBeUndefined(); | ||
| expect(vendorMap[IGNORE_LIST]).not.toBeUndefined(); | ||
|
|
||
| expect(mainMap[IGNORE_LIST].length).toEqual(0); | ||
| expect(polyfillsMap[IGNORE_LIST].length).not.toEqual(0); | ||
| expect(runtimeMap[IGNORE_LIST].length).not.toEqual(0); | ||
| expect(vendorMap[IGNORE_LIST].length).not.toEqual(0); | ||
|
|
||
| const thirdPartyInMain = mainMap.sources.some((s) => s.includes('node_modules')); | ||
| const thirdPartyInPolyfills = polyfillsMap.sources.some((s) => s.includes('node_modules')); | ||
| const thirdPartyInRuntime = runtimeMap.sources.some((s) => s.includes('webpack')); | ||
| const thirdPartyInVendor = vendorMap.sources.some((s) => s.includes('node_modules')); | ||
| expect(thirdPartyInMain).toBe(false, `main.js.map should not include any node modules`); | ||
| expect(thirdPartyInPolyfills).toBe(true, `polyfills.js.map should include some node modules`); | ||
| expect(thirdPartyInRuntime).toBe(true, `runtime.js.map should include some webpack code`); | ||
| expect(thirdPartyInVendor).toBe(true, `vendor.js.map should include some node modules`); | ||
|
|
||
| // All sources in the main map are first-party. | ||
| expect(mainMap.sources.filter((_, i) => !mainMap[IGNORE_LIST].includes(i))).toEqual([ | ||
| './src/app/app.component.ts', | ||
| './src/app/app.module.ts', | ||
| './src/environments/environment.ts', | ||
| './src/main.ts', | ||
| ]); | ||
|
|
||
| // Only some sources in the polyfills map are first-party. | ||
| expect(polyfillsMap.sources.filter((_, i) => !polyfillsMap[IGNORE_LIST].includes(i))).toEqual([ | ||
| './src/polyfills.ts', | ||
| ]); | ||
|
|
||
| // None of the sources in the runtime and vendor maps are first-party. | ||
| expect(runtimeMap.sources.filter((_, i) => !runtimeMap[IGNORE_LIST].includes(i))).toEqual([]); | ||
| expect(vendorMap.sources.filter((_, i) => !vendorMap[IGNORE_LIST].includes(i))).toEqual([]); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| /** | ||
| * @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 { Compilation, Compiler } from 'webpack'; | ||
|
|
||
| // Following the naming conventions from | ||
| // https://sourcemaps.info/spec.html#h.ghqpj1ytqjbm | ||
| const IGNORE_LIST = 'x_google_ignoreList'; | ||
|
|
||
| const PLUGIN_NAME = 'devtools-ignore-plugin'; | ||
|
|
||
| interface SourceMap { | ||
| sources: string[]; | ||
| [IGNORE_LIST]: number[]; | ||
| } | ||
|
|
||
| /** | ||
| * This plugin adds a field to source maps that identifies which sources are | ||
| * vendored or runtime-injected (aka third-party) sources. These are consumed by | ||
| * Chrome DevTools to automatically ignore-list sources. | ||
| */ | ||
| export class DevToolsIgnorePlugin { | ||
| apply(compiler: Compiler) { | ||
| const { RawSource } = compiler.webpack.sources; | ||
|
|
||
| compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => { | ||
| compilation.hooks.processAssets.tap( | ||
| { | ||
| name: PLUGIN_NAME, | ||
| stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING, | ||
| additionalAssets: true, | ||
|
Comment thread
victorporof marked this conversation as resolved.
|
||
| }, | ||
| (assets) => { | ||
| for (const [name, asset] of Object.entries(assets)) { | ||
| // Instead of using `asset.map()` to fetch the source maps from | ||
| // SourceMapSource assets, process them directly as a RawSource. | ||
| // This is because `.map()` is slow and can take several seconds. | ||
| if (!name.endsWith('.map')) { | ||
| // Ignore non source map files. | ||
| continue; | ||
| } | ||
|
|
||
| const mapContent = asset.source().toString(); | ||
| if (!mapContent) { | ||
| continue; | ||
| } | ||
|
|
||
| const map = JSON.parse(mapContent) as SourceMap; | ||
| const ignoreList = []; | ||
|
|
||
| for (const [index, path] of map.sources.entries()) { | ||
| if (path.includes('/node_modules/') || path.startsWith('webpack/')) { | ||
| ignoreList.push(index); | ||
| } | ||
| } | ||
|
|
||
| map[IGNORE_LIST] = ignoreList; | ||
| compilation.updateAsset(name, new RawSource(JSON.stringify(map))); | ||
| } | ||
| }, | ||
| ); | ||
| }); | ||
| } | ||
| } | ||
| Back | FazBrowse Home | New Git URL |
Uh oh!
There was an error while loading. Please reload this page.