fix(ivy): properly parenthesize ternary expressions when emitted (#34221)
Previously, ternary expressions were emitted as: condExpr ? trueCase : falseCase However, this causes problems when ternary operations are nested. In particular, a template expression of the form: a?.b ? c : d would have compiled to: a == null ? null : a.b ? c : d The ternary operator is right-associative, so that expression is interpreted as: a == null ? null : (a.b ? c : d) when in reality left-associativity is desired in this particular instance: (a == null ? null : a.b) ? c : d This commit adds a check in the expression translator to detect such left-associative usages of ternaries and to enforce such associativity with parentheses when necessary. A test is also added for the template type-checking expression translator, to ensure it correctly produces right-associative expressions for ternaries in the user's template. Fixes #34087 PR Close #34221
This commit is contained in:

committed by
Andrew Kushnir

parent
f72de51a6f
commit
718d7fe5fe
@ -755,4 +755,29 @@ describe('compiler compliance: template', () => {
|
||||
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
|
||||
it('should safely nest ternary operations', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: \`
|
||||
{{a?.b ? 1 : 2 }}\`
|
||||
})
|
||||
export class MyComponent {}
|
||||
|
||||
@NgModule({declarations: [MyComponent]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const template = `i0.ɵɵtextInterpolate1(" ", (ctx.a == null ? null : ctx.a.b) ? 1 : 2, "")`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user