Skip to content

Commit b70b80b

Browse files
crisbetothePunderWoman
authored andcommitted
fix(migrations): do not generate aliased variables with the same name (#56154)
Adds some logic to avoid generating expressions like `let $index = $index` in the control flow migration. Fixes #56152. PR Close #56154
1 parent 88732f0 commit b70b80b

File tree

2 files changed

+74
-8
lines changed

2 files changed

+74
-8
lines changed

packages/core/schematics/ng-generate/control-flow-migration/fors.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,23 +137,31 @@ function migrateStandardNgFor(etm: ElementToMigrate, tmpl: string, offset: numbe
137137
if (part.match(aliasWithEqualRegexp)) {
138138
// 'let myIndex = index' -> ['let myIndex', 'index']
139139
const aliasParts = part.split('=');
140-
// -> 'let myIndex = $index'
141-
aliases.push(` ${aliasParts[0].trim()} = $${aliasParts[1].trim()}`);
140+
const aliasedName = aliasParts[0].replace('let', '').trim();
141+
const originalName = aliasParts[1].trim();
142+
if (aliasedName !== '$' + originalName) {
143+
// -> 'let myIndex = $index'
144+
aliases.push(` let ${aliasedName} = $${originalName}`);
145+
}
142146
// if the aliased variable is the index, then we store it
143-
if (aliasParts[1].trim() === 'index') {
147+
if (originalName === 'index') {
144148
// 'let myIndex' -> 'myIndex'
145-
aliasedIndex = aliasParts[0].replace('let', '').trim();
149+
aliasedIndex = aliasedName;
146150
}
147151
}
148152
// declared with `index as myIndex`
149153
if (part.match(aliasWithAsRegexp)) {
150154
// 'index as myIndex' -> ['index', 'myIndex']
151155
const aliasParts = part.split(/\s+as\s+/);
152-
// -> 'let myIndex = $index'
153-
aliases.push(` let ${aliasParts[1].trim()} = $${aliasParts[0].trim()}`);
156+
const originalName = aliasParts[0].trim();
157+
const aliasedName = aliasParts[1].trim();
158+
if (aliasedName !== '$' + originalName) {
159+
// -> 'let myIndex = $index'
160+
aliases.push(` let ${aliasedName} = $${originalName}`);
161+
}
154162
// if the aliased variable is the index, then we store it
155-
if (aliasParts[0].trim() === 'index') {
156-
aliasedIndex = aliasParts[1].trim();
163+
if (originalName === 'index') {
164+
aliasedIndex = aliasedName;
157165
}
158166
}
159167
}

packages/core/schematics/test/control_flow_migration_spec.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,6 +2189,64 @@ describe('control flow migration', () => {
21892189
);
21902190
});
21912191

2192+
it('should not generate aliased variables declared via the `as` syntax with the same name as the original', async () => {
2193+
writeFile(
2194+
'/comp.ts',
2195+
`
2196+
import {Component} from '@angular/core';
2197+
import {NgFor} from '@angular/common';
2198+
interface Item {
2199+
id: number;
2200+
text: string;
2201+
}
2202+
2203+
@Component({
2204+
imports: [NgFor],
2205+
template: \`<div *ngFor="let item of items; index as $index;">{{$index}}</div>\`
2206+
})
2207+
class Comp {
2208+
items: Item[] = [{id: 1, text: 'blah'}, {id: 2, text: 'stuff'}];
2209+
}
2210+
`,
2211+
);
2212+
2213+
await runMigration();
2214+
const content = tree.readContent('/comp.ts');
2215+
2216+
expect(content).toContain(
2217+
'template: `@for (item of items; track item) {<div>{{$index}}</div>}`',
2218+
);
2219+
});
2220+
2221+
it('should not generate aliased variables declared via the `let` syntax with the same name as the original', async () => {
2222+
writeFile(
2223+
'/comp.ts',
2224+
`
2225+
import {Component} from '@angular/core';
2226+
import {NgFor} from '@angular/common';
2227+
interface Item {
2228+
id: number;
2229+
text: string;
2230+
}
2231+
2232+
@Component({
2233+
imports: [NgFor],
2234+
template: \`<div *ngFor="let item of items; let $index = index">{{$index}}</div>\`
2235+
})
2236+
class Comp {
2237+
items: Item[] = [{id: 1, text: 'blah'}, {id: 2, text: 'stuff'}];
2238+
}
2239+
`,
2240+
);
2241+
2242+
await runMigration();
2243+
const content = tree.readContent('/comp.ts');
2244+
2245+
expect(content).toContain(
2246+
'template: `@for (item of items; track item) {<div>{{$index}}</div>}`',
2247+
);
2248+
});
2249+
21922250
it('should migrate with a trackBy function and an aliased index', async () => {
21932251
writeFile(
21942252
'/comp.ts',

0 commit comments

Comments
 (0)