fix(compiler-cli): handle deferred blocks with shared dependencies co… · angular/angular@5cd26a9 · GitHub
Skip to content

Commit 5cd26a9

Browse files
crisbetoatscott
authored andcommitted
fix(compiler-cli): handle deferred blocks with shared dependencies correctly (#59926)
When the compiler analyzes the defer blocks in a component, it generates two sets of dependencies: ones specific for each block and others from all the deferred blocks within the component. The logic that combines all the defer block dependencies wasn't de-duplicating them which resulted in us producing `setClassMetadataAsync` calls where the callback can have multiple parameters with the same name. This was a problem both in full and partial compilation, but the latter was more visible, because Babel throws an error in such cases. These changes add some logic to de-duplicate the dependencies so that we produce valid code. Fixes #59922. PR Close #59926
1 parent b0266bd commit 5cd26a9

7 files changed

Lines changed: 200 additions & 3 deletions

File tree

‎packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts‎

Lines changed: 13 additions & 3 deletions

‎packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_deferred/GOLDEN_PARTIAL.js‎

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,3 +1122,99 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE
11221122
****************************************************************************************************/
11231123
export {};
11241124

1125+
/****************************************************************************************************
1126+
* PARTIAL FILE: deferred_with_duplicate_external_dep_lazy.js
1127+
****************************************************************************************************/
1128+
import { Directive } from '@angular/core';
1129+
import * as i0 from "@angular/core";
1130+
export class DuplicateLazyDep {
1131+
}
1132+
DuplicateLazyDep.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: DuplicateLazyDep, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1133+
DuplicateLazyDep.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: DuplicateLazyDep, isStandalone: true, selector: "duplicate-lazy-dep", ngImport: i0 });
1134+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: DuplicateLazyDep, decorators: [{
1135+
type: Directive,
1136+
args: [{ selector: 'duplicate-lazy-dep' }]
1137+
}] });
1138+
1139+
/****************************************************************************************************
1140+
* PARTIAL FILE: deferred_with_duplicate_external_dep_lazy.d.ts
1141+
****************************************************************************************************/
1142+
import * as i0 from "@angular/core";
1143+
export declare class DuplicateLazyDep {
1144+
static ɵfac: i0.ɵɵFactoryDeclaration<DuplicateLazyDep, never>;
1145+
static ɵdir: i0.ɵɵDirectiveDeclaration<DuplicateLazyDep, "duplicate-lazy-dep", never, {}, {}, never, never, true, never>;
1146+
}
1147+
1148+
/****************************************************************************************************
1149+
* PARTIAL FILE: deferred_with_duplicate_external_dep_other.js
1150+
****************************************************************************************************/
1151+
import { Directive } from '@angular/core';
1152+
import * as i0 from "@angular/core";
1153+
export class OtherLazyDep {
1154+
}
1155+
OtherLazyDep.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: OtherLazyDep, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1156+
OtherLazyDep.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: OtherLazyDep, isStandalone: true, selector: "other-lazy-dep", ngImport: i0 });
1157+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: OtherLazyDep, decorators: [{
1158+
type: Directive,
1159+
args: [{ selector: 'other-lazy-dep' }]
1160+
}] });
1161+
1162+
/****************************************************************************************************
1163+
* PARTIAL FILE: deferred_with_duplicate_external_dep_other.d.ts
1164+
****************************************************************************************************/
1165+
import * as i0 from "@angular/core";
1166+
export declare class OtherLazyDep {
1167+
static ɵfac: i0.ɵɵFactoryDeclaration<OtherLazyDep, never>;
1168+
static ɵdir: i0.ɵɵDirectiveDeclaration<OtherLazyDep, "other-lazy-dep", never, {}, {}, never, never, true, never>;
1169+
}
1170+
1171+
/****************************************************************************************************
1172+
* PARTIAL FILE: deferred_with_duplicate_external_dep.js
1173+
****************************************************************************************************/
1174+
import { Component } from '@angular/core';
1175+
import * as i0 from "@angular/core";
1176+
export class MyApp {
1177+
}
1178+
MyApp.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, deps: [], target: i0.ɵɵFactoryTarget.Component });
1179+
MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "0.0.0-PLACEHOLDER", type: MyApp, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
1180+
@defer {
1181+
<duplicate-lazy-dep/>
1182+
}
1183+
1184+
@defer {
1185+
<duplicate-lazy-dep/>
1186+
}
1187+
1188+
@defer {
1189+
<other-lazy-dep/>
1190+
}
1191+
`, isInline: true, deferBlockDependencies: [() => [import("./deferred_with_duplicate_external_dep_lazy").then(m => m.DuplicateLazyDep)], () => [import("./deferred_with_duplicate_external_dep_lazy").then(m => m.DuplicateLazyDep)], () => [import("./deferred_with_duplicate_external_dep_other").then(m => m.OtherLazyDep)]] });
1192+
i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, resolveDeferredDeps: () => [import("./deferred_with_duplicate_external_dep_lazy").then(m => m.DuplicateLazyDep), import("./deferred_with_duplicate_external_dep_other").then(m => m.OtherLazyDep)], resolveMetadata: (DuplicateLazyDep, OtherLazyDep) => ({ decorators: [{
1193+
type: Component,
1194+
args: [{
1195+
template: `
1196+
@defer {
1197+
<duplicate-lazy-dep/>
1198+
}
1199+
1200+
@defer {
1201+
<duplicate-lazy-dep/>
1202+
}
1203+
1204+
@defer {
1205+
<other-lazy-dep/>
1206+
}
1207+
`,
1208+
imports: [DuplicateLazyDep, OtherLazyDep],
1209+
}]
1210+
}], ctorParameters: null, propDecorators: null }) });
1211+
1212+
/****************************************************************************************************
1213+
* PARTIAL FILE: deferred_with_duplicate_external_dep.d.ts
1214+
****************************************************************************************************/
1215+
import * as i0 from "@angular/core";
1216+
export declare class MyApp {
1217+
static ɵfac: i0.ɵɵFactoryDeclaration<MyApp, never>;
1218+
static ɵcmp: i0.ɵɵComponentDeclaration<MyApp, "ng-component", never, {}, {}, never, never, true, never>;
1219+
}
1220+

‎packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_deferred/TEST_CASES.json‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,25 @@
290290
"failureMessage": "Incorrect template"
291291
}
292292
]
293+
},
294+
{
295+
"description": "should handle a component with deferred blocks that share the same dependency",
296+
"inputFiles": [
297+
"deferred_with_duplicate_external_dep.ts",
298+
"deferred_with_duplicate_external_dep_lazy.ts",
299+
"deferred_with_duplicate_external_dep_other.ts"
300+
],
301+
"expectations": [
302+
{
303+
"files": [
304+
{
305+
"expected": "deferred_with_duplicate_external_dep_template.js",
306+
"generated": "deferred_with_duplicate_external_dep.js"
307+
}
308+
],
309+
"failureMessage": "Incorrect template"
310+
}
311+
]
293312
}
294313
]
295314
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {Component} from '@angular/core';
2+
import {DuplicateLazyDep} from './deferred_with_duplicate_external_dep_lazy';
3+
import {OtherLazyDep} from './deferred_with_duplicate_external_dep_other';
4+
5+
@Component({
6+
template: `
7+
@defer {
8+
<duplicate-lazy-dep/>
9+
}
10+
11+
@defer {
12+
<duplicate-lazy-dep/>
13+
}
14+
15+
@defer {
16+
<other-lazy-dep/>
17+
}
18+
`,
19+
imports: [DuplicateLazyDep, OtherLazyDep],
20+
})
21+
export class MyApp {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import {Directive} from '@angular/core';
2+
3+
@Directive({selector: 'duplicate-lazy-dep'})
4+
export class DuplicateLazyDep {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import {Directive} from '@angular/core';
2+
3+
@Directive({selector: 'other-lazy-dep'})
4+
export class OtherLazyDep {}

0 commit comments

Comments
 (0)