From 7a41e8f79290fbc67d99ab85fadc4d3b437f2bf8 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 31 Oct 2023 11:06:21 +0100 Subject: [PATCH] fix(@ngtools/webpack): remove setClassDebugInfo calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Angular v17 adds another dev-mode-only function that needs to be removed called `ɵsetClassDebugInfo`. These changes update the Webpack plugin to account for it. --- goldens/public-api/ngtools/webpack/index.md | 2 + packages/ngtools/webpack/src/ivy/plugin.ts | 1 + .../ngtools/webpack/src/ivy/transformation.ts | 16 ++++-- .../remove-ivy-jit-support-calls.ts | 11 ++++ .../remove-ivy-jit-support-calls_spec.ts | 53 ++++++++++++++----- 5 files changed, 66 insertions(+), 17 deletions(-) diff --git a/goldens/public-api/ngtools/webpack/index.md b/goldens/public-api/ngtools/webpack/index.md index d50f6a068d..13ddc85cab 100644 --- a/goldens/public-api/ngtools/webpack/index.md +++ b/goldens/public-api/ngtools/webpack/index.md @@ -35,6 +35,8 @@ export interface AngularWebpackPluginOptions { // (undocumented) emitNgModuleScope: boolean; // (undocumented) + emitSetClassDebugInfo?: boolean; + // (undocumented) fileReplacements: Record; // (undocumented) inlineStyleFileExtension?: string; diff --git a/packages/ngtools/webpack/src/ivy/plugin.ts b/packages/ngtools/webpack/src/ivy/plugin.ts index 8fc2efb618..7ea56ba58c 100644 --- a/packages/ngtools/webpack/src/ivy/plugin.ts +++ b/packages/ngtools/webpack/src/ivy/plugin.ts @@ -49,6 +49,7 @@ export interface AngularWebpackPluginOptions { directTemplateLoading: boolean; emitClassMetadata: boolean; emitNgModuleScope: boolean; + emitSetClassDebugInfo?: boolean; jitMode: boolean; inlineStyleFileExtension?: string; } diff --git a/packages/ngtools/webpack/src/ivy/transformation.ts b/packages/ngtools/webpack/src/ivy/transformation.ts index 7308a097a1..b30adfe136 100644 --- a/packages/ngtools/webpack/src/ivy/transformation.ts +++ b/packages/ngtools/webpack/src/ivy/transformation.ts @@ -14,7 +14,11 @@ import { replaceResources } from '../transformers/replace_resources'; export function createAotTransformers( builder: ts.BuilderProgram, - options: { emitClassMetadata?: boolean; emitNgModuleScope?: boolean }, + options: { + emitClassMetadata?: boolean; + emitNgModuleScope?: boolean; + emitSetClassDebugInfo?: boolean; + }, imageDomains: Set, ): ts.CustomTransformers { const getTypeChecker = () => builder.getProgram().getTypeChecker(); @@ -25,10 +29,16 @@ export function createAotTransformers( const removeClassMetadata = !options.emitClassMetadata; const removeNgModuleScope = !options.emitNgModuleScope; - if (removeClassMetadata || removeNgModuleScope) { + const removeSetClassDebugInfo = !options.emitSetClassDebugInfo; + if (removeClassMetadata || removeNgModuleScope || removeSetClassDebugInfo) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion transformers.before!.push( - removeIvyJitSupportCalls(removeClassMetadata, removeNgModuleScope, getTypeChecker), + removeIvyJitSupportCalls( + removeClassMetadata, + removeNgModuleScope, + removeSetClassDebugInfo, + getTypeChecker, + ), ); } diff --git a/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls.ts b/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls.ts index 0d7e715519..55b239dff0 100644 --- a/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls.ts +++ b/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls.ts @@ -12,6 +12,7 @@ import { elideImports } from './elide_imports'; export function removeIvyJitSupportCalls( classMetadata: boolean, ngModuleScope: boolean, + debugInfo: boolean, getTypeChecker: () => ts.TypeChecker, ): ts.TransformerFactory { return (context: ts.TransformationContext) => { @@ -43,6 +44,16 @@ export function removeIvyJitSupportCalls( return undefined; } } + + if ( + debugInfo && + ts.isBinaryExpression(innerExpression) && + isIvyPrivateCallExpression(innerExpression.right, 'ɵsetClassDebugInfo') + ) { + removedNodes.push(innerExpression); + + return undefined; + } } return ts.visitEachChild(node, visitNode, context); diff --git a/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls_spec.ts b/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls_spec.ts index 436a6e673c..0f14d99a8e 100644 --- a/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls_spec.ts +++ b/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls_spec.ts @@ -177,6 +177,16 @@ const inputAsyncArrowFn = tags.stripIndent` }); })(); `; +const inputDebugInfo = tags.stripIndent` + import { Component } from '@angular/core'; + import * as i0 from "@angular/core"; + export class TestCmp { + } + TestCmp.ɵfac = function TestCmp_Factory(t) { return new (t || TestCmp)(); }; + TestCmp.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestCmp, selectors: [["test-cmp"]], decls: 0, vars: 0, template: function TestCmp_Template(rf, ctx) { }, encapsulation: 2 }); + (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestCmp, { className: "TestCmp" }); })(); +`; + describe('@ngtools/webpack transformers', () => { describe('remove-ivy-dev-calls', () => { it('should allow removing only set class metadata with pure annotation', () => { @@ -194,7 +204,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(input, (getTypeChecker) => - removeIvyJitSupportCalls(true, false, getTypeChecker), + removeIvyJitSupportCalls(true, false, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -215,7 +225,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(true, false, getTypeChecker), + removeIvyJitSupportCalls(true, false, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -248,7 +258,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(input, (getTypeChecker) => - removeIvyJitSupportCalls(false, true, getTypeChecker), + removeIvyJitSupportCalls(false, true, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -281,7 +291,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(false, true, getTypeChecker), + removeIvyJitSupportCalls(false, true, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -299,7 +309,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(input, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, getTypeChecker), + removeIvyJitSupportCalls(true, true, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -317,7 +327,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, getTypeChecker), + removeIvyJitSupportCalls(true, true, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -325,7 +335,7 @@ describe('@ngtools/webpack transformers', () => { it('should allow removing neither set class metadata nor ng module scope with pure annotation', () => { const result = transform(input, (getTypeChecker) => - removeIvyJitSupportCalls(false, false, getTypeChecker), + removeIvyJitSupportCalls(false, false, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${input}`); @@ -333,7 +343,7 @@ describe('@ngtools/webpack transformers', () => { it('should allow removing neither set class metadata nor ng module scope', () => { const result = transform(inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(false, false, getTypeChecker), + removeIvyJitSupportCalls(false, false, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${inputNoPure}`); @@ -364,7 +374,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(imports + input, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, getTypeChecker), + removeIvyJitSupportCalls(true, true, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -395,7 +405,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(imports + inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, getTypeChecker), + removeIvyJitSupportCalls(true, true, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -413,7 +423,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(inputArrowFnWithBody, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, getTypeChecker), + removeIvyJitSupportCalls(true, true, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -431,7 +441,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(inputArrowFnWithImplicitReturn, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, getTypeChecker), + removeIvyJitSupportCalls(true, true, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -446,7 +456,7 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(inputAsync, (getTypeChecker) => - removeIvyJitSupportCalls(true, false, getTypeChecker), + removeIvyJitSupportCalls(true, false, false, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); @@ -461,7 +471,22 @@ describe('@ngtools/webpack transformers', () => { `; const result = transform(inputAsyncArrowFn, (getTypeChecker) => - removeIvyJitSupportCalls(true, false, getTypeChecker), + removeIvyJitSupportCalls(true, false, false, getTypeChecker), + ); + + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); + + it('should remove setClassDebugInfo calls', () => { + const output = tags.stripIndent` + import * as i0 from "@angular/core"; + export class TestCmp { } + TestCmp.ɵfac = function TestCmp_Factory(t) { return new (t || TestCmp)(); }; + TestCmp.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestCmp, selectors: [["test-cmp"]], decls: 0, vars: 0, template: function TestCmp_Template(rf, ctx) { }, encapsulation: 2 }); + `; + + const result = transform(inputDebugInfo, (getTypeChecker) => + removeIvyJitSupportCalls(true, false, true, getTypeChecker), ); expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);