Skip to content

Commit f3f4c3d

Browse files
chuckjazalxhub
authored andcommitted
fix(compiler): disallow references for select and index evaluation
Also fixes an issue where enum values of 0 or '``' where not treated correctly. Fixes: #18170
1 parent 9ae3742 commit f3f4c3d

File tree

2 files changed

+152
-4
lines changed

2 files changed

+152
-4
lines changed

packages/compiler/src/aot/static_reflector.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ export class StaticReflector implements CompileReflector {
444444
} else {
445445
const staticSymbol = expression;
446446
const declarationValue = resolveReferenceValue(staticSymbol);
447-
if (declarationValue) {
447+
if (declarationValue != null) {
448448
return simplifyInContext(staticSymbol, declarationValue, depth + 1, references);
449449
} else {
450450
return staticSymbol;
@@ -522,8 +522,8 @@ export class StaticReflector implements CompileReflector {
522522
}
523523
return null;
524524
case 'index':
525-
let indexTarget = simplify(expression['expression']);
526-
let index = simplify(expression['index']);
525+
let indexTarget = simplifyInContext(context, expression['expression'], depth, 0);
526+
let index = simplifyInContext(context, expression['index'], depth, 0);
527527
if (indexTarget && isPrimitive(index)) return indexTarget[index];
528528
return null;
529529
case 'select':
@@ -535,7 +535,7 @@ export class StaticReflector implements CompileReflector {
535535
selectContext =
536536
self.getStaticSymbol(selectTarget.filePath, selectTarget.name, members);
537537
const declarationValue = resolveReferenceValue(selectContext);
538-
if (declarationValue) {
538+
if (declarationValue != null) {
539539
return simplifyInContext(
540540
selectContext, declarationValue, depth + 1, references);
541541
} else {

packages/compiler/test/aot/static_reflector_spec.ts

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,154 @@ describe('StaticReflector', () => {
914914
.toEqual([{data: {c: [3]}}]);
915915
});
916916

917+
// Regression #18170
918+
it('should evaluate enums and statics that are 0', () => {
919+
const data = Object.create(DEFAULT_TEST_DATA);
920+
const file = '/tmp/src/my_component.ts';
921+
data[file] = `
922+
import {Component} from '@angular/core';
923+
import {provideRoutes} from './macro';
924+
import {MyEnum, MyClass} from './consts';
925+
926+
@Component({
927+
template: '<div></div>',
928+
providers: [provideRoutes({
929+
path: 'foo',
930+
data: {
931+
e: MyEnum.Value
932+
}
933+
})]
934+
})
935+
export class MyComponent { }
936+
`;
937+
data['/tmp/src/macro.ts'] = `
938+
import {ANALYZE_FOR_ENTRY_COMPONENTS, ROUTES} from '@angular/core';
939+
940+
export interface Route {
941+
path?: string;
942+
data?: any;
943+
}
944+
export type Routes = Route[];
945+
export function provideRoutes(routes: Routes): any {
946+
return [
947+
{provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: routes},
948+
{provide: ROUTES, multi: true, useValue: routes},
949+
];
950+
}
951+
`;
952+
data['/tmp/src/consts.ts'] = `
953+
export enum MyEnum {
954+
Value = 0,
955+
}
956+
`;
957+
init(data);
958+
expect(reflector.annotations(reflector.getStaticSymbol(file, 'MyComponent'))[0]
959+
.providers[0][0]
960+
.useValue)
961+
.toEqual({path: 'foo', data: {e: 0}});
962+
});
963+
964+
// Regression #18170
965+
it('should agressively evaluate enums selects', () => {
966+
const data = Object.create(DEFAULT_TEST_DATA);
967+
const file = '/tmp/src/my_component.ts';
968+
data[file] = `
969+
import {Component} from '@angular/core';
970+
import {provideRoutes} from './macro';
971+
import {E} from './indirect';
972+
973+
@Component({
974+
template: '<div></div>',
975+
providers: [provideRoutes({
976+
path: 'foo',
977+
data: {
978+
e: E.Value,
979+
}
980+
})]
981+
})
982+
export class MyComponent { }
983+
`;
984+
data['/tmp/src/macro.ts'] = `
985+
import {ANALYZE_FOR_ENTRY_COMPONENTS, ROUTES} from '@angular/core';
986+
987+
export interface Route {
988+
path?: string;
989+
data?: any;
990+
}
991+
export type Routes = Route[];
992+
export function provideRoutes(routes: Routes): any {
993+
return [
994+
{provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: routes},
995+
{provide: ROUTES, multi: true, useValue: routes},
996+
];
997+
}
998+
`;
999+
data['/tmp/src/indirect.ts'] = `
1000+
import {MyEnum} from './consts';
1001+
1002+
export const E = MyEnum;
1003+
`,
1004+
data['/tmp/src/consts.ts'] = `
1005+
export enum MyEnum {
1006+
Value = 1,
1007+
}
1008+
`;
1009+
init(data);
1010+
expect(reflector.annotations(reflector.getStaticSymbol(file, 'MyComponent'))[0]
1011+
.providers[0][0]
1012+
.useValue)
1013+
.toEqual({path: 'foo', data: {e: 1}});
1014+
});
1015+
1016+
// Regression #18170
1017+
it('should agressively evaluate array indexes', () => {
1018+
const data = Object.create(DEFAULT_TEST_DATA);
1019+
const file = '/tmp/src/my_component.ts';
1020+
data[file] = `
1021+
import {Component} from '@angular/core';
1022+
import {provideRoutes} from './macro';
1023+
import {E} from './indirect';
1024+
1025+
@Component({
1026+
template: '<div></div>',
1027+
providers: [provideRoutes({
1028+
path: 'foo',
1029+
data: {
1030+
e: E[E[E[1]]],
1031+
}
1032+
})]
1033+
})
1034+
export class MyComponent { }
1035+
`;
1036+
data['/tmp/src/macro.ts'] = `
1037+
import {ANALYZE_FOR_ENTRY_COMPONENTS, ROUTES} from '@angular/core';
1038+
1039+
export interface Route {
1040+
path?: string;
1041+
data?: any;
1042+
}
1043+
export type Routes = Route[];
1044+
export function provideRoutes(routes: Routes): any {
1045+
return [
1046+
{provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: routes},
1047+
{provide: ROUTES, multi: true, useValue: routes},
1048+
];
1049+
}
1050+
`;
1051+
data['/tmp/src/indirect.ts'] = `
1052+
import {A} from './consts';
1053+
1054+
export const E = A;
1055+
`,
1056+
data['/tmp/src/consts.ts'] = `
1057+
export const A = [0, 1];
1058+
`;
1059+
init(data);
1060+
expect(reflector.annotations(reflector.getStaticSymbol(file, 'MyComponent'))[0]
1061+
.providers[0][0]
1062+
.useValue)
1063+
.toEqual({path: 'foo', data: {e: 1}});
1064+
});
9171065
});
9181066

9191067
const DEFAULT_TEST_DATA: {[key: string]: any} = {

0 commit comments

Comments
 (0)