Skip to content

Commit ec2dbe7

Browse files
JoostKAndrewKushnir
authored andcommittedSep 11, 2020
fix(compiler): detect pipes in ICUs in template binder (#38810)
Recent work on compiler internals in #38539 led to an unexpected failure, where a pipe used exclusively inside of an ICU would no longer be emitted into the compilation output. This caused runtime errors due to missing pipes. The issue occurred because the change in #38539 would determine the set of used pipes up-front, independent from the template compilation using the `R3TargetBinder`. However, `R3TargetBinder` did not consider expressions within ICUs, so any pipe usages within those expressions would not be detected. This fix unblocks #38539 and also concerns upcoming linker work, given that prelink compilations would not go through full template compilation but only `R3TargetBinder`. PR Close #38810
1 parent 8096c63 commit ec2dbe7

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed
 

‎packages/compiler/src/render3/view/t2_binder.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,10 @@ class TemplateBinder extends RecursiveAstVisitor implements Visitor {
434434
visitText(text: Text) {}
435435
visitContent(content: Content) {}
436436
visitTextAttribute(attribute: TextAttribute) {}
437-
visitIcu(icu: Icu): void {}
437+
visitIcu(icu: Icu): void {
438+
Object.keys(icu.vars).forEach(key => icu.vars[key].visit(this));
439+
Object.keys(icu.placeholders).forEach(key => icu.placeholders[key].visit(this));
440+
}
438441

439442
// The remaining visitors are concerned with processing AST expressions within template bindings
440443

‎packages/compiler/test/render3/view/binding_spec.ts

+34
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,38 @@ describe('t2 binding', () => {
194194
expect(consumer).toEqual(el);
195195
});
196196
});
197+
198+
describe('used pipes', () => {
199+
it('should record pipes used in interpolations', () => {
200+
const template = parseTemplate('{{value|date}}', '', {});
201+
const binder = new R3TargetBinder(makeSelectorMatcher());
202+
const res = binder.bind({template: template.nodes});
203+
expect(res.getUsedPipes()).toEqual(['date']);
204+
});
205+
206+
it('should record pipes used in bound attributes', () => {
207+
const template = parseTemplate('<person [age]="age|number"></person>', '', {});
208+
const binder = new R3TargetBinder(makeSelectorMatcher());
209+
const res = binder.bind({template: template.nodes});
210+
expect(res.getUsedPipes()).toEqual(['number']);
211+
});
212+
213+
it('should record pipes used in bound template attributes', () => {
214+
const template = parseTemplate('<ng-template [ngIf]="obs|async"></ng-template>', '', {});
215+
const binder = new R3TargetBinder(makeSelectorMatcher());
216+
const res = binder.bind({template: template.nodes});
217+
expect(res.getUsedPipes()).toEqual(['async']);
218+
});
219+
220+
it('should record pipes used in ICUs', () => {
221+
const template = parseTemplate(
222+
`<span i18n>{count|number, plural,
223+
=1 { {{value|date}} }
224+
}</span>`,
225+
'', {});
226+
const binder = new R3TargetBinder(makeSelectorMatcher());
227+
const res = binder.bind({template: template.nodes});
228+
expect(res.getUsedPipes()).toEqual(['number', 'date']);
229+
});
230+
});
197231
});

0 commit comments

Comments
 (0)