feat(ivy): add ɵɵtextInterpolateX instructions (#30011)
- `ɵɵtextBinding(..., ɵɵinterpolationX())` instructions will now just be `ɵɵtextInterpolate(...)` instructions PR Close #30011
This commit is contained in:
		
							parent
							
								
									48093823cb
								
							
						
					
					
						commit
						dd0815095f
					
				| @ -168,7 +168,7 @@ describe('Renderer', () => { | |||||||
|         ɵngcc0.ɵɵtext(0); |         ɵngcc0.ɵɵtext(0); | ||||||
|     } if (rf & 2) { |     } if (rf & 2) { | ||||||
|         ɵngcc0.ɵɵselect(0); |         ɵngcc0.ɵɵselect(0); | ||||||
|         ɵngcc0.ɵɵtextBinding(0, ɵngcc0.ɵɵinterpolation1("", ctx.person.name, "")); |         ɵngcc0.ɵɵtextInterpolate(ctx.person.name); | ||||||
|     } }, encapsulation: 2 }); |     } }, encapsulation: 2 }); | ||||||
| /*@__PURE__*/ ɵngcc0.ɵsetClassMetadata(A, [{ | /*@__PURE__*/ ɵngcc0.ɵsetClassMetadata(A, [{ | ||||||
|         type: Component, |         type: Component, | ||||||
|  | |||||||
| @ -810,7 +810,7 @@ describe('compiler compliance', () => { | |||||||
|             const $myComp$ = $r3$.ɵɵnextContext(); |             const $myComp$ = $r3$.ɵɵnextContext(); | ||||||
|             const $foo$ = $r3$.ɵɵreference(1); |             const $foo$ = $r3$.ɵɵreference(1); | ||||||
|             $r3$.ɵɵselect(1); |             $r3$.ɵɵselect(1); | ||||||
|             $r3$.ɵɵtextBinding(1, $r3$.ɵɵinterpolation2("", $myComp$.salutation, " ", $foo$, "")); |             $r3$.ɵɵtextInterpolate2("", $myComp$.salutation, " ", $foo$, ""); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         … |         … | ||||||
| @ -2074,9 +2074,9 @@ describe('compiler compliance', () => { | |||||||
|                 } |                 } | ||||||
|                 if (rf & 2) { |                 if (rf & 2) { | ||||||
|                   $r3$.ɵɵselect(0); |                   $r3$.ɵɵselect(0); | ||||||
|                   $r3$.ɵɵtextBinding(0, $r3$.ɵɵinterpolation1("", $r3$.ɵɵpipeBind2(1, 3, $r3$.ɵɵpipeBind2(2, 6, ctx.name, ctx.size), ctx.size), "")); |                   $r3$.ɵɵtextInterpolate($r3$.ɵɵpipeBind2(1, 3, $r3$.ɵɵpipeBind2(2, 6, ctx.name, ctx.size), ctx.size)); | ||||||
|                   $r3$.ɵɵselect(4); |                   $r3$.ɵɵselect(4); | ||||||
|                   $r3$.ɵɵtextBinding(4, $r3$.ɵɵinterpolation2("", $r3$.ɵɵpipeBindV(5, 9, $r3$.ɵɵpureFunction1(18, $c0$, ctx.name)), " ", ctx.name ? 1 : $r3$.ɵɵpipeBind1(6, 16, 2), "")); |                   $r3$.ɵɵtextInterpolate2("", $r3$.ɵɵpipeBindV(5, 9, $r3$.ɵɵpureFunction1(18, $c0$, ctx.name)), " ", ctx.name ? 1 : $r3$.ɵɵpipeBind1(6, 16, 2), ""); | ||||||
|                 } |                 } | ||||||
|               }, |               }, | ||||||
|               pipes: [MyPurePipe, MyPipe], |               pipes: [MyPurePipe, MyPipe], | ||||||
| @ -2139,14 +2139,14 @@ describe('compiler compliance', () => { | |||||||
|                 } |                 } | ||||||
|                 if (rf & 2) { |                 if (rf & 2) { | ||||||
|                   $r3$.ɵɵselect(0); |                   $r3$.ɵɵselect(0); | ||||||
|                   $r3$.ɵɵtextBinding(0, $r3$.ɵɵinterpolation5( |                   $r3$.ɵɵtextInterpolate5( | ||||||
|                     "0:", i0.ɵɵpipeBind1(1, 5, ctx.name), |                     "0:", i0.ɵɵpipeBind1(1, 5, ctx.name), | ||||||
|                     "1:", i0.ɵɵpipeBind2(2, 7, ctx.name, 1), |                     "1:", i0.ɵɵpipeBind2(2, 7, ctx.name, 1), | ||||||
|                     "2:", i0.ɵɵpipeBind3(3, 10, ctx.name, 1, 2), |                     "2:", i0.ɵɵpipeBind3(3, 10, ctx.name, 1, 2), | ||||||
|                     "3:", i0.ɵɵpipeBind4(4, 14, ctx.name, 1, 2, 3), |                     "3:", i0.ɵɵpipeBind4(4, 14, ctx.name, 1, 2, 3), | ||||||
|                     "4:", i0.ɵɵpipeBindV(5, 19, $r3$.ɵɵpureFunction1(25, $c0$, ctx.name)), |                     "4:", i0.ɵɵpipeBindV(5, 19, $r3$.ɵɵpureFunction1(25, $c0$, ctx.name)), | ||||||
|                     "" |                     "" | ||||||
|                   )); |                   ); | ||||||
|                 } |                 } | ||||||
|               }, |               }, | ||||||
|               pipes: [MyPipe], |               pipes: [MyPipe], | ||||||
| @ -2192,7 +2192,7 @@ describe('compiler compliance', () => { | |||||||
|             if (rf & 2) { |             if (rf & 2) { | ||||||
|               const $user$ = $r3$.ɵɵreference(1); |               const $user$ = $r3$.ɵɵreference(1); | ||||||
|               $r3$.ɵɵselect(2); |               $r3$.ɵɵselect(2); | ||||||
|               $r3$.ɵɵtextBinding(2, $r3$.ɵɵinterpolation1("Hello ", $user$.value, "!")); |               $r3$.ɵɵtextInterpolate1("Hello ", $user$.value, "!"); | ||||||
|             } |             } | ||||||
|           }, |           }, | ||||||
|           encapsulation: 2 |           encapsulation: 2 | ||||||
| @ -2255,7 +2255,7 @@ describe('compiler compliance', () => { | |||||||
|             const $foo$ = $r3$.ɵɵreference(1); |             const $foo$ = $r3$.ɵɵreference(1); | ||||||
|             const $baz$ = $r3$.ɵɵreference(5); |             const $baz$ = $r3$.ɵɵreference(5); | ||||||
|             $r3$.ɵɵselect(1); |             $r3$.ɵɵselect(1); | ||||||
|             $r3$.ɵɵtextBinding(1, $r3$.ɵɵinterpolation3("", $foo$, "-", $bar$, "-", $baz$, "")); |             $r3$.ɵɵtextInterpolate3("", $foo$, "-", $bar$, "-", $baz$, ""); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         function MyComponent_div_3_Template(rf, ctx) { |         function MyComponent_div_3_Template(rf, ctx) { | ||||||
| @ -2271,7 +2271,7 @@ describe('compiler compliance', () => { | |||||||
|             $r3$.ɵɵnextContext(); |             $r3$.ɵɵnextContext(); | ||||||
|             const $foo$ = $r3$.ɵɵreference(1); |             const $foo$ = $r3$.ɵɵreference(1); | ||||||
|             $r3$.ɵɵselect(1); |             $r3$.ɵɵselect(1); | ||||||
|             $r3$.ɵɵtextBinding(1, $r3$.ɵɵinterpolation2(" ", $foo$, "-", $bar$, " ")); |             $r3$.ɵɵtextInterpolate2(" ", $foo$, "-", $bar$, " "); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         … |         … | ||||||
| @ -2291,7 +2291,7 @@ describe('compiler compliance', () => { | |||||||
|             if (rf & 2) { |             if (rf & 2) { | ||||||
|               const $foo$ = $r3$.ɵɵreference(1); |               const $foo$ = $r3$.ɵɵreference(1); | ||||||
|               $r3$.ɵɵselect(2); |               $r3$.ɵɵselect(2); | ||||||
|               $r3$.ɵɵtextBinding(2, $r3$.ɵɵinterpolation1(" ", $foo$, " ")); |               $r3$.ɵɵtextInterpolate1(" ", $foo$, " "); | ||||||
|             } |             } | ||||||
|           }, |           }, | ||||||
|           directives:[IfDirective], |           directives:[IfDirective], | ||||||
| @ -2300,9 +2300,7 @@ describe('compiler compliance', () => { | |||||||
| 
 | 
 | ||||||
|       const result = compile(files, angularFiles); |       const result = compile(files, angularFiles); | ||||||
|       const source = result.source; |       const source = result.source; | ||||||
| 
 |  | ||||||
|       expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef'); |       expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef'); | ||||||
| 
 |  | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should support local refs mixed with context assignments', () => { |     it('should support local refs mixed with context assignments', () => { | ||||||
| @ -2344,7 +2342,7 @@ describe('compiler compliance', () => { | |||||||
|           const $item$ = $i0$.ɵɵnextContext().$implicit; |           const $item$ = $i0$.ɵɵnextContext().$implicit; | ||||||
|           const $foo$ = $i0$.ɵɵreference(2); |           const $foo$ = $i0$.ɵɵreference(2); | ||||||
|           $r3$.ɵɵselect(1); |           $r3$.ɵɵselect(1); | ||||||
|           $i0$.ɵɵtextBinding(1, $i0$.ɵɵinterpolation2(" ", $foo$, " - ", $item$, " ")); |           $i0$.ɵɵtextInterpolate2(" ", $foo$, " - ", $item$, " "); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
| @ -2648,7 +2646,7 @@ describe('compiler compliance', () => { | |||||||
|             if (rf & 2) { |             if (rf & 2) { | ||||||
|               const $item$ = ctx.$implicit; |               const $item$ = ctx.$implicit; | ||||||
|               $r3$.ɵɵselect(1); |               $r3$.ɵɵselect(1); | ||||||
|               $r3$.ɵɵtextBinding(1, $r3$.ɵɵinterpolation1("", $item$.name, "")); |               $r3$.ɵɵtextInterpolate($item$.name); | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|           … |           … | ||||||
| @ -2731,7 +2729,7 @@ describe('compiler compliance', () => { | |||||||
|               const $info$ = ctx.$implicit; |               const $info$ = ctx.$implicit; | ||||||
|               const $item$ = $r3$.ɵɵnextContext().$implicit; |               const $item$ = $r3$.ɵɵnextContext().$implicit; | ||||||
|               $r3$.ɵɵselect(1); |               $r3$.ɵɵselect(1); | ||||||
|               $r3$.ɵɵtextBinding(1, $r3$.ɵɵinterpolation2(" ", $item$.name, ": ", $info$.description, " ")); |               $r3$.ɵɵtextInterpolate2(" ", $item$.name, ": ", $info$.description, " "); | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
| @ -2749,7 +2747,7 @@ describe('compiler compliance', () => { | |||||||
|             if (rf & 2) { |             if (rf & 2) { | ||||||
|               const $item$ = ctx.$implicit; |               const $item$ = ctx.$implicit; | ||||||
|               $r3$.ɵɵselect(2); |               $r3$.ɵɵselect(2); | ||||||
|               $r3$.ɵɵtextBinding(2, $r3$.ɵɵinterpolation1("", IDENT.name, "")); |               $r3$.ɵɵtextInterpolate(IDENT.name); | ||||||
|               $r3$.ɵɵselect(4); |               $r3$.ɵɵselect(4); | ||||||
|               $r3$.ɵɵproperty("forOf", IDENT.infos); |               $r3$.ɵɵproperty("forOf", IDENT.infos); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -45,7 +45,7 @@ describe('compiler compliance: bindings', () => { | |||||||
|         } |         } | ||||||
|         if (rf & 2) { |         if (rf & 2) { | ||||||
|           $r3$.ɵɵselect(1); |           $r3$.ɵɵselect(1); | ||||||
|           $i0$.ɵɵtextBinding(1, $i0$.ɵɵinterpolation1("Hello ", $ctx$.name, "")); |           $i0$.ɵɵtextInterpolate1("Hello ", $ctx$.name, ""); | ||||||
|         } |         } | ||||||
|       }`;
 |       }`;
 | ||||||
|       const result = compile(files, angularFiles); |       const result = compile(files, angularFiles); | ||||||
| @ -567,7 +567,7 @@ describe('compiler compliance: bindings', () => { | |||||||
|           if (rf & 2) { |           if (rf & 2) { | ||||||
|             const $_r0$ = $i0$.ɵɵreference(1); |             const $_r0$ = $i0$.ɵɵreference(1); | ||||||
|             $r3$.ɵɵselect(4); |             $r3$.ɵɵselect(4); | ||||||
|             $i0$.ɵɵtextBinding(4, $i0$.ɵɵinterpolation1(" ", $_r0$.id, " ")); |             $i0$.ɵɵtextInterpolate1(" ", $_r0$.id, " "); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       `;
 |       `;
 | ||||||
|  | |||||||
| @ -93,7 +93,7 @@ describe('r3_view_compiler', () => { | |||||||
| 
 | 
 | ||||||
|   describe('interpolations', () => { |   describe('interpolations', () => { | ||||||
|     // Regression #21927
 |     // Regression #21927
 | ||||||
|     it('should generate a correct call to bV with more than 8 interpolations', () => { |     it('should generate a correct call to textInterpolateV with more than 8 interpolations', () => { | ||||||
|       const files: MockDirectory = { |       const files: MockDirectory = { | ||||||
|         app: { |         app: { | ||||||
|           'example.ts': ` |           'example.ts': ` | ||||||
| @ -112,10 +112,19 @@ describe('r3_view_compiler', () => { | |||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       const bV_call = |       const bV_call = ` | ||||||
|           `$r3$.ɵɵinterpolationV([" ",ctx.list[0]," ",ctx.list[1]," ",ctx.list[2]," ",ctx.list[3],
 |       … | ||||||
|         " ",ctx.list[4]," ",ctx.list[5]," ",ctx.list[6]," ",ctx.list[7]," ",ctx.list[8], |       function MyApp_Template(rf, ctx) { | ||||||
|         " "])`;
 |         if (rf & 1) { | ||||||
|  |           $i0$.ɵɵtext(0); | ||||||
|  |         } | ||||||
|  |         if (rf & 2) { | ||||||
|  |           $i0$.ɵɵselect(0); | ||||||
|  |           $i0$.ɵɵtextInterpolateV([" ", ctx.list[0], " ", ctx.list[1], " ", ctx.list[2], " ", ctx.list[3], " ", ctx.list[4], " ", ctx.list[5], " ", ctx.list[6], " ", ctx.list[7], " ", ctx.list[8], " "]); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       … | ||||||
|  |       `;
 | ||||||
|       const result = compile(files, angularFiles); |       const result = compile(files, angularFiles); | ||||||
|       expectEmit(result.source, bV_call, 'Incorrect bV call'); |       expectEmit(result.source, bV_call, 'Incorrect bV call'); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -999,7 +999,7 @@ describe('compiler compliance: styling', () => { | |||||||
|               $r3$.ɵɵclassProp(0, $r3$.ɵɵpipeBind2(4, 10, $ctx$.fooExp, 2000)); |               $r3$.ɵɵclassProp(0, $r3$.ɵɵpipeBind2(4, 10, $ctx$.fooExp, 2000)); | ||||||
|               $r3$.ɵɵstylingApply(); |               $r3$.ɵɵstylingApply(); | ||||||
|               $r3$.ɵɵselect(5); |               $r3$.ɵɵselect(5); | ||||||
|               $r3$.ɵɵtextBinding(5, $r3$.ɵɵinterpolation1(" ", $ctx$.item, "")); |               $r3$.ɵɵtextInterpolate1(" ", $ctx$.item, ""); | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|           `;
 |           `;
 | ||||||
|  | |||||||
| @ -78,7 +78,7 @@ describe('compiler compliance: template', () => { | |||||||
|           $i0$.ɵɵselect(0); |           $i0$.ɵɵselect(0); | ||||||
|           $i0$.ɵɵproperty("title", $myComp1$.format($outer1$, $middle1$, $inner1$, $myComp1$.component)); |           $i0$.ɵɵproperty("title", $myComp1$.format($outer1$, $middle1$, $inner1$, $myComp1$.component)); | ||||||
|           $r3$.ɵɵselect(1); |           $r3$.ɵɵselect(1); | ||||||
|           $i0$.ɵɵtextBinding(1, $i0$.ɵɵinterpolation1(" ", $myComp1$.format($outer1$, $middle1$, $inner1$, $myComp1$.component), " ")); |           $i0$.ɵɵtextInterpolate1(" ", $myComp1$.format($outer1$, $middle1$, $inner1$, $myComp1$.component), " "); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
| @ -215,7 +215,7 @@ describe('compiler compliance: template', () => { | |||||||
|           const $item$ = ctx.$implicit; |           const $item$ = ctx.$implicit; | ||||||
|           const $i$ = ctx.index; |           const $i$ = ctx.index; | ||||||
|           $r3$.ɵɵselect(1); |           $r3$.ɵɵselect(1); | ||||||
|           $i0$.ɵɵtextBinding(1, $i0$.ɵɵinterpolation2(" ", $i$, " - ", $item$, " ")); |           $i0$.ɵɵtextInterpolate2(" ", $i$, " - ", $item$, " "); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       // ...
 |       // ...
 | ||||||
| @ -272,7 +272,7 @@ describe('compiler compliance: template', () => { | |||||||
|           const $i$ = $div$.index; |           const $i$ = $div$.index; | ||||||
|           const $item$ = $div$.$implicit; |           const $item$ = $div$.$implicit; | ||||||
|           $r3$.ɵɵselect(1); |           $r3$.ɵɵselect(1); | ||||||
|           $i0$.ɵɵtextBinding(1, $i0$.ɵɵinterpolation2(" ", $i$, " - ", $item$, " ")); |           $i0$.ɵɵtextInterpolate2(" ", $i$, " - ", $item$, " "); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
| @ -343,7 +343,7 @@ describe('compiler compliance: template', () => { | |||||||
|           const $middle$ = $i0$.ɵɵnextContext().$implicit; |           const $middle$ = $i0$.ɵɵnextContext().$implicit; | ||||||
|           const $myComp$ = $i0$.ɵɵnextContext(2); |           const $myComp$ = $i0$.ɵɵnextContext(2); | ||||||
|           $r3$.ɵɵselect(1); |           $r3$.ɵɵselect(1); | ||||||
|           $i0$.ɵɵtextBinding(1, $i0$.ɵɵinterpolation2(" ", $middle$.value, " - ", $myComp$.name, " ")); |           $i0$.ɵɵtextInterpolate2(" ", $middle$.value, " - ", $myComp$.name, " "); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1961,7 +1961,7 @@ describe('ngtsc behavioral tests', () => { | |||||||
| 
 | 
 | ||||||
|     env.driveMain(); |     env.driveMain(); | ||||||
|     const jsContents = env.getContents('test.js'); |     const jsContents = env.getContents('test.js'); | ||||||
|     expect(jsContents).toContain('interpolation1("", ctx.text, "")'); |     expect(jsContents).toContain('ɵɵtextInterpolate(ctx.text)'); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   it('should handle `encapsulation` field', () => { |   it('should handle `encapsulation` field', () => { | ||||||
|  | |||||||
| @ -44,7 +44,7 @@ describe('template source-mapping', () => { | |||||||
|             {source: '<h3>', generated: 'i0.ɵɵelementStart(0, "h3")', sourceUrl: '../test.ts'}); |             {source: '<h3>', generated: 'i0.ɵɵelementStart(0, "h3")', sourceUrl: '../test.ts'}); | ||||||
|         expect(mappings).toContain({ |         expect(mappings).toContain({ | ||||||
|           source: 'Hello {{ name }}', |           source: 'Hello {{ name }}', | ||||||
|           generated: 'i0.ɵɵtextBinding(1, i0.ɵɵinterpolation1("Hello ", ctx.name, ""))', |           generated: 'i0.ɵɵtextInterpolate1("Hello ", ctx.name, "")', | ||||||
|           sourceUrl: '../test.ts' |           sourceUrl: '../test.ts' | ||||||
|         }); |         }); | ||||||
|         expect(mappings).toContain( |         expect(mappings).toContain( | ||||||
| @ -57,8 +57,7 @@ describe('template source-mapping', () => { | |||||||
|             {source: '<h2>', generated: 'i0.ɵɵelementStart(0, "h2")', sourceUrl: '../test.ts'}); |             {source: '<h2>', generated: 'i0.ɵɵelementStart(0, "h2")', sourceUrl: '../test.ts'}); | ||||||
|         expect(mappings).toContain({ |         expect(mappings).toContain({ | ||||||
|           source: '{{ greeting + " " + name }}', |           source: '{{ greeting + " " + name }}', | ||||||
|           generated: |           generated: 'i0.ɵɵtextInterpolate(ctx.greeting + " " + ctx.name)', | ||||||
|               'i0.ɵɵtextBinding(1, i0.ɵɵinterpolation1("", ctx.greeting + " " + ctx.name, ""))', |  | ||||||
|           sourceUrl: '../test.ts' |           sourceUrl: '../test.ts' | ||||||
|         }); |         }); | ||||||
|         expect(mappings).toContain( |         expect(mappings).toContain( | ||||||
| @ -85,8 +84,7 @@ describe('template source-mapping', () => { | |||||||
|             {source: '<div>', generated: 'i0.ɵɵelementStart(0, "div")', sourceUrl: '../test.ts'}); |             {source: '<div>', generated: 'i0.ɵɵelementStart(0, "div")', sourceUrl: '../test.ts'}); | ||||||
|         expect(mappings).toContain({ |         expect(mappings).toContain({ | ||||||
|           source: '{{200.3 | percent : 2 }}', |           source: '{{200.3 | percent : 2 }}', | ||||||
|           generated: |           generated: 'i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(2, 1, 200.3, 2))', | ||||||
|               'i0.ɵɵtextBinding(1, i0.ɵɵinterpolation1("", i0.ɵɵpipeBind2(2, 1, 200.3, 2), ""))', |  | ||||||
|           sourceUrl: '../test.ts' |           sourceUrl: '../test.ts' | ||||||
|         }); |         }); | ||||||
|         expect(mappings).toContain( |         expect(mappings).toContain( | ||||||
| @ -270,7 +268,7 @@ describe('template source-mapping', () => { | |||||||
| 
 | 
 | ||||||
|         // expect(mappings).toContain({
 |         // expect(mappings).toContain({
 | ||||||
|         //   source: '{{ name }}',
 |         //   source: '{{ name }}',
 | ||||||
|         //   generated: 'i0.ɵɵtextBinding(1, i0.ɵɵinterpolation1("", ctx_r0.name, ""))',
 |         //   generated: 'i0.ɵɵtextInterpolate(ctx_r0.name)',
 | ||||||
|         //   sourceUrl: '../test.ts'
 |         //   sourceUrl: '../test.ts'
 | ||||||
|         // });
 |         // });
 | ||||||
|       }); |       }); | ||||||
| @ -294,7 +292,7 @@ describe('template source-mapping', () => { | |||||||
| 
 | 
 | ||||||
|         // expect(mappings).toContain({
 |         // expect(mappings).toContain({
 | ||||||
|         //   source: '{{ name }}',
 |         //   source: '{{ name }}',
 | ||||||
|         //   generated: 'i0.ɵɵtextBinding(1, i0.ɵɵinterpolation1("", ctx_r0.name, ""))',
 |         //   generated: 'i0.ɵɵtextInterpolate(ctx_r0.name)',
 | ||||||
|         //   sourceUrl: '../test.ts'
 |         //   sourceUrl: '../test.ts'
 | ||||||
|         // });
 |         // });
 | ||||||
|       }); |       }); | ||||||
| @ -370,7 +368,7 @@ describe('template source-mapping', () => { | |||||||
| 
 | 
 | ||||||
|       // Update mode
 |       // Update mode
 | ||||||
|       expect(mappings).toContain({ |       expect(mappings).toContain({ | ||||||
|         generated: 'i0.ɵɵtextBinding(3, i0.ɵɵinterpolation1("", 1 + 2, ""))', |         generated: 'i0.ɵɵtextInterpolate(1 + 2)', | ||||||
|         source: '{{ 1 + 2 }}', |         source: '{{ 1 + 2 }}', | ||||||
|         sourceUrl: '../test.ts' |         sourceUrl: '../test.ts' | ||||||
|       }); |       }); | ||||||
| @ -396,9 +394,10 @@ describe('template source-mapping', () => { | |||||||
|       expect(mappings).toContain( |       expect(mappings).toContain( | ||||||
|           {generated: 'i0.ɵɵelementEnd()', source: '</div>', sourceUrl: '../test.ts'}); |           {generated: 'i0.ɵɵelementEnd()', source: '</div>', sourceUrl: '../test.ts'}); | ||||||
| 
 | 
 | ||||||
|  |       // TODO(benlesh): We need to circle back and prevent the extra parens from being generated.
 | ||||||
|       // Update mode
 |       // Update mode
 | ||||||
|       expect(mappings).toContain({ |       expect(mappings).toContain({ | ||||||
|         generated: 'i0.ɵɵtextBinding(3, i0.ɵɵinterpolation1("", 1 + 2, ""))', |         generated: 'i0.ɵɵtextInterpolate(1 + 2)', | ||||||
|         source: '{{ 1 + 2 }}', |         source: '{{ 1 + 2 }}', | ||||||
|         sourceUrl: '../test.ts' |         sourceUrl: '../test.ts' | ||||||
|       }); |       }); | ||||||
| @ -452,7 +451,7 @@ describe('template source-mapping', () => { | |||||||
| 
 | 
 | ||||||
|         // Update mode
 |         // Update mode
 | ||||||
|         expect(mappings).toContain({ |         expect(mappings).toContain({ | ||||||
|           generated: 'i0.ɵɵtextBinding(3, i0.ɵɵinterpolation1("", 1 + 2, ""))', |           generated: 'i0.ɵɵtextInterpolate(1 + 2)', | ||||||
|           source: '{{ 1 + 2 }}', |           source: '{{ 1 + 2 }}', | ||||||
|           sourceUrl: '../dir/test.html' |           sourceUrl: '../dir/test.html' | ||||||
|         }); |         }); | ||||||
| @ -496,7 +495,7 @@ describe('template source-mapping', () => { | |||||||
| 
 | 
 | ||||||
|         // Update mode
 |         // Update mode
 | ||||||
|         expect(mappings).toContain({ |         expect(mappings).toContain({ | ||||||
|           generated: 'i0.ɵɵtextBinding(3, i0.ɵɵinterpolation1("", 1 + 2, ""))', |           generated: 'i0.ɵɵtextInterpolate(1 + 2)', | ||||||
|           source: '{{ 1 + 2 }}', |           source: '{{ 1 + 2 }}', | ||||||
|           sourceUrl: '../extraRootDir/test.html' |           sourceUrl: '../extraRootDir/test.html' | ||||||
|         }); |         }); | ||||||
|  | |||||||
| @ -56,7 +56,7 @@ export class JitEvaluator { | |||||||
|   evaluateCode( |   evaluateCode( | ||||||
|       sourceUrl: string, ctx: EmitterVisitorContext, vars: {[key: string]: any}, |       sourceUrl: string, ctx: EmitterVisitorContext, vars: {[key: string]: any}, | ||||||
|       createSourceMap: boolean): any { |       createSourceMap: boolean): any { | ||||||
|     let fnBody = `${ctx.toSource()}\n//# sourceURL=${sourceUrl}`; |     let fnBody = `"use strict";${ctx.toSource()}\n//# sourceURL=${sourceUrl}`; | ||||||
|     const fnArgNames: string[] = []; |     const fnArgNames: string[] = []; | ||||||
|     const fnArgValues: any[] = []; |     const fnArgValues: any[] = []; | ||||||
|     for (const argName in vars) { |     for (const argName in vars) { | ||||||
|  | |||||||
| @ -102,6 +102,17 @@ export class Identifiers { | |||||||
| 
 | 
 | ||||||
|   static getCurrentView: o.ExternalReference = {name: 'ɵɵgetCurrentView', moduleName: CORE}; |   static getCurrentView: o.ExternalReference = {name: 'ɵɵgetCurrentView', moduleName: CORE}; | ||||||
| 
 | 
 | ||||||
|  |   static textInterpolate: o.ExternalReference = {name: 'ɵɵtextInterpolate', moduleName: CORE}; | ||||||
|  |   static textInterpolate1: o.ExternalReference = {name: 'ɵɵtextInterpolate1', moduleName: CORE}; | ||||||
|  |   static textInterpolate2: o.ExternalReference = {name: 'ɵɵtextInterpolate2', moduleName: CORE}; | ||||||
|  |   static textInterpolate3: o.ExternalReference = {name: 'ɵɵtextInterpolate3', moduleName: CORE}; | ||||||
|  |   static textInterpolate4: o.ExternalReference = {name: 'ɵɵtextInterpolate4', moduleName: CORE}; | ||||||
|  |   static textInterpolate5: o.ExternalReference = {name: 'ɵɵtextInterpolate5', moduleName: CORE}; | ||||||
|  |   static textInterpolate6: o.ExternalReference = {name: 'ɵɵtextInterpolate6', moduleName: CORE}; | ||||||
|  |   static textInterpolate7: o.ExternalReference = {name: 'ɵɵtextInterpolate7', moduleName: CORE}; | ||||||
|  |   static textInterpolate8: o.ExternalReference = {name: 'ɵɵtextInterpolate8', moduleName: CORE}; | ||||||
|  |   static textInterpolateV: o.ExternalReference = {name: 'ɵɵtextInterpolateV', moduleName: CORE}; | ||||||
|  | 
 | ||||||
|   static restoreView: o.ExternalReference = {name: 'ɵɵrestoreView', moduleName: CORE}; |   static restoreView: o.ExternalReference = {name: 'ɵɵrestoreView', moduleName: CORE}; | ||||||
| 
 | 
 | ||||||
|   static interpolation1: o.ExternalReference = {name: 'ɵɵinterpolation1', moduleName: CORE}; |   static interpolation1: o.ExternalReference = {name: 'ɵɵinterpolation1', moduleName: CORE}; | ||||||
|  | |||||||
| @ -941,9 +941,17 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | |||||||
| 
 | 
 | ||||||
|     const value = text.value.visit(this._valueConverter); |     const value = text.value.visit(this._valueConverter); | ||||||
|     this.allocateBindingSlots(value); |     this.allocateBindingSlots(value); | ||||||
|     this.updateInstruction( | 
 | ||||||
|         nodeIndex, text.sourceSpan, R3.textBinding, |     if (value instanceof Interpolation) { | ||||||
|         () => [o.literal(nodeIndex), this.convertPropertyBinding(o.variable(CONTEXT_NAME), value)]); |       this.updateInstruction( | ||||||
|  |           nodeIndex, text.sourceSpan, getTextInterpolationExpression(value), | ||||||
|  |           () => this.getUpdateInstructionArguments(o.variable(CONTEXT_NAME), value)); | ||||||
|  |     } else { | ||||||
|  |       this.updateInstruction( | ||||||
|  |           nodeIndex, text.sourceSpan, R3.textBinding, | ||||||
|  |           () => | ||||||
|  |               [o.literal(nodeIndex), this.convertPropertyBinding(o.variable(CONTEXT_NAME), value)]); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   visitText(text: t.Text) { |   visitText(text: t.Text) { | ||||||
| @ -1736,6 +1744,35 @@ function getAttributeInterpolationExpression(interpolation: Interpolation) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Gets the instruction to generate for interpolated text. | ||||||
|  |  * @param interpolation An Interpolation AST | ||||||
|  |  */ | ||||||
|  | function getTextInterpolationExpression(interpolation: Interpolation): o.ExternalReference { | ||||||
|  |   switch (getInterpolationArgsLength(interpolation)) { | ||||||
|  |     case 1: | ||||||
|  |       return R3.textInterpolate; | ||||||
|  |     case 3: | ||||||
|  |       return R3.textInterpolate1; | ||||||
|  |     case 5: | ||||||
|  |       return R3.textInterpolate2; | ||||||
|  |     case 7: | ||||||
|  |       return R3.textInterpolate3; | ||||||
|  |     case 9: | ||||||
|  |       return R3.textInterpolate4; | ||||||
|  |     case 11: | ||||||
|  |       return R3.textInterpolate5; | ||||||
|  |     case 13: | ||||||
|  |       return R3.textInterpolate6; | ||||||
|  |     case 15: | ||||||
|  |       return R3.textInterpolate7; | ||||||
|  |     case 17: | ||||||
|  |       return R3.textInterpolate8; | ||||||
|  |     default: | ||||||
|  |       return R3.textInterpolateV; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Gets the number of arguments expected to be passed to a generated instruction in the case of |  * Gets the number of arguments expected to be passed to a generated instruction in the case of | ||||||
|  * interpolation instructions. |  * interpolation instructions. | ||||||
|  | |||||||
| @ -57,6 +57,16 @@ export { | |||||||
|   ɵɵelement, |   ɵɵelement, | ||||||
|   ɵɵlistener, |   ɵɵlistener, | ||||||
|   ɵɵtext, |   ɵɵtext, | ||||||
|  |   ɵɵtextInterpolate, | ||||||
|  |   ɵɵtextInterpolate1, | ||||||
|  |   ɵɵtextInterpolate2, | ||||||
|  |   ɵɵtextInterpolate3, | ||||||
|  |   ɵɵtextInterpolate4, | ||||||
|  |   ɵɵtextInterpolate5, | ||||||
|  |   ɵɵtextInterpolate6, | ||||||
|  |   ɵɵtextInterpolate7, | ||||||
|  |   ɵɵtextInterpolate8, | ||||||
|  |   ɵɵtextInterpolateV, | ||||||
|   ɵɵembeddedViewStart, |   ɵɵembeddedViewStart, | ||||||
|   ɵɵprojection, |   ɵɵprojection, | ||||||
|   ɵɵbind, |   ɵɵbind, | ||||||
|  | |||||||
| @ -107,7 +107,18 @@ export { | |||||||
|   ɵɵtemplate, |   ɵɵtemplate, | ||||||
| 
 | 
 | ||||||
|   ɵɵtext, |   ɵɵtext, | ||||||
|   ɵɵtextBinding} from './instructions/all'; |   ɵɵtextBinding, | ||||||
|  |   ɵɵtextInterpolate, | ||||||
|  |   ɵɵtextInterpolate1, | ||||||
|  |   ɵɵtextInterpolate2, | ||||||
|  |   ɵɵtextInterpolate3, | ||||||
|  |   ɵɵtextInterpolate4, | ||||||
|  |   ɵɵtextInterpolate5, | ||||||
|  |   ɵɵtextInterpolate6, | ||||||
|  |   ɵɵtextInterpolate7, | ||||||
|  |   ɵɵtextInterpolate8, | ||||||
|  |   ɵɵtextInterpolateV, | ||||||
|  | } from './instructions/all'; | ||||||
| export {RenderFlags} from './interfaces/definition'; | export {RenderFlags} from './interfaces/definition'; | ||||||
| export {CssSelectorList} from './interfaces/projection'; | export {CssSelectorList} from './interfaces/projection'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -36,6 +36,7 @@ export * from './element'; | |||||||
| export * from './element_container'; | export * from './element_container'; | ||||||
| export * from './embedded_view'; | export * from './embedded_view'; | ||||||
| export * from './get_current_view'; | export * from './get_current_view'; | ||||||
|  | export * from './interpolation'; | ||||||
| export * from './listener'; | export * from './listener'; | ||||||
| export * from './namespace'; | export * from './namespace'; | ||||||
| export * from './next_context'; | export * from './next_context'; | ||||||
| @ -45,3 +46,4 @@ export * from './property_interpolation'; | |||||||
| export * from './select'; | export * from './select'; | ||||||
| export * from './styling'; | export * from './styling'; | ||||||
| export * from './text'; | export * from './text'; | ||||||
|  | export * from './text_interpolation'; | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ | |||||||
| import {SanitizerFn} from '../interfaces/sanitization'; | import {SanitizerFn} from '../interfaces/sanitization'; | ||||||
| import {getSelectedIndex} from '../state'; | import {getSelectedIndex} from '../state'; | ||||||
| import {ɵɵelementAttribute} from './element'; | import {ɵɵelementAttribute} from './element'; | ||||||
| import {ɵɵinterpolation1, ɵɵinterpolation2, ɵɵinterpolation3, ɵɵinterpolation4, ɵɵinterpolation5, ɵɵinterpolation6, ɵɵinterpolation7, ɵɵinterpolation8, ɵɵinterpolationV} from './property_interpolation'; | import {ɵɵinterpolation1, ɵɵinterpolation2, ɵɵinterpolation3, ɵɵinterpolation4, ɵɵinterpolation5, ɵɵinterpolation6, ɵɵinterpolation7, ɵɵinterpolation8, ɵɵinterpolationV} from './interpolation'; | ||||||
| import {TsickleIssue1009} from './shared'; | import {TsickleIssue1009} from './shared'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										289
									
								
								packages/core/src/render3/instructions/interpolation.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								packages/core/src/render3/instructions/interpolation.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,289 @@ | |||||||
|  | /** | ||||||
|  |  * @license | ||||||
|  |  * Copyright Google Inc. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | import {assertEqual, assertLessThan} from '../../util/assert'; | ||||||
|  | import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from '../bindings'; | ||||||
|  | import {BINDING_INDEX, TVIEW} from '../interfaces/view'; | ||||||
|  | import {getLView} from '../state'; | ||||||
|  | import {NO_CHANGE} from '../tokens'; | ||||||
|  | import {renderStringify} from '../util/misc_utils'; | ||||||
|  | 
 | ||||||
|  | import {storeBindingMetadata} from './shared'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Create interpolation bindings with a variable number of expressions. | ||||||
|  |  * | ||||||
|  |  * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead. | ||||||
|  |  * Those are faster because there is no need to create an array of expressions and iterate over it. | ||||||
|  |  * | ||||||
|  |  * `values`: | ||||||
|  |  * - has static text at even indexes, | ||||||
|  |  * - has evaluated expressions at odd indexes. | ||||||
|  |  * | ||||||
|  |  * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise. | ||||||
|  |  * | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵinterpolationV(values: any[]): string|NO_CHANGE { | ||||||
|  |   ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values'); | ||||||
|  |   ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values'); | ||||||
|  |   let isBindingUpdated = false; | ||||||
|  |   const lView = getLView(); | ||||||
|  |   const tData = lView[TVIEW].data; | ||||||
|  |   let bindingIndex = lView[BINDING_INDEX]; | ||||||
|  | 
 | ||||||
|  |   if (tData[bindingIndex] == null) { | ||||||
|  |     // 2 is the index of the first static interstitial value (ie. not prefix)
 | ||||||
|  |     for (let i = 2; i < values.length; i += 2) { | ||||||
|  |       tData[bindingIndex++] = values[i]; | ||||||
|  |     } | ||||||
|  |     bindingIndex = lView[BINDING_INDEX]; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   for (let i = 1; i < values.length; i += 2) { | ||||||
|  |     // Check if bindings (odd indexes) have changed
 | ||||||
|  |     isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated; | ||||||
|  |   } | ||||||
|  |   lView[BINDING_INDEX] = bindingIndex; | ||||||
|  |   storeBindingMetadata(lView, values[0], values[values.length - 1]); | ||||||
|  | 
 | ||||||
|  |   if (!isBindingUpdated) { | ||||||
|  |     return NO_CHANGE; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Build the updated content
 | ||||||
|  |   let content = values[0]; | ||||||
|  |   for (let i = 1; i < values.length; i += 2) { | ||||||
|  |     content += renderStringify(values[i]) + values[i + 1]; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return content; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Creates an interpolation binding with 1 expression. | ||||||
|  |  * | ||||||
|  |  * @param prefix static value used for concatenation only. | ||||||
|  |  * @param v0 value checked for change. | ||||||
|  |  * @param suffix static value used for concatenation only. | ||||||
|  |  * | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵinterpolation1(prefix: string, v0: any, suffix: string): string|NO_CHANGE { | ||||||
|  |   const lView = getLView(); | ||||||
|  |   const different = bindingUpdated(lView, lView[BINDING_INDEX]++, v0); | ||||||
|  |   storeBindingMetadata(lView, prefix, suffix); | ||||||
|  |   return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Creates an interpolation binding with 2 expressions. | ||||||
|  |  * | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵinterpolation2( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, suffix: string): string|NO_CHANGE { | ||||||
|  |   const lView = getLView(); | ||||||
|  |   const bindingIndex = lView[BINDING_INDEX]; | ||||||
|  |   const different = bindingUpdated2(lView, bindingIndex, v0, v1); | ||||||
|  |   lView[BINDING_INDEX] += 2; | ||||||
|  | 
 | ||||||
|  |   // Only set static strings the first time (data will be null subsequent runs).
 | ||||||
|  |   const data = storeBindingMetadata(lView, prefix, suffix); | ||||||
|  |   if (data) { | ||||||
|  |     lView[TVIEW].data[bindingIndex] = i0; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Creates an interpolation binding with 3 expressions. | ||||||
|  |  * | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵinterpolation3( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, suffix: string): string| | ||||||
|  |     NO_CHANGE { | ||||||
|  |   const lView = getLView(); | ||||||
|  |   const bindingIndex = lView[BINDING_INDEX]; | ||||||
|  |   const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2); | ||||||
|  |   lView[BINDING_INDEX] += 3; | ||||||
|  | 
 | ||||||
|  |   // Only set static strings the first time (data will be null subsequent runs).
 | ||||||
|  |   const data = storeBindingMetadata(lView, prefix, suffix); | ||||||
|  |   if (data) { | ||||||
|  |     const tData = lView[TVIEW].data; | ||||||
|  |     tData[bindingIndex] = i0; | ||||||
|  |     tData[bindingIndex + 1] = i1; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return different ? | ||||||
|  |       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix : | ||||||
|  |       NO_CHANGE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Create an interpolation binding with 4 expressions. | ||||||
|  |  * | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵinterpolation4( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     suffix: string): string|NO_CHANGE { | ||||||
|  |   const lView = getLView(); | ||||||
|  |   const bindingIndex = lView[BINDING_INDEX]; | ||||||
|  |   const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); | ||||||
|  |   lView[BINDING_INDEX] += 4; | ||||||
|  | 
 | ||||||
|  |   // Only set static strings the first time (data will be null subsequent runs).
 | ||||||
|  |   const data = storeBindingMetadata(lView, prefix, suffix); | ||||||
|  |   if (data) { | ||||||
|  |     const tData = lView[TVIEW].data; | ||||||
|  |     tData[bindingIndex] = i0; | ||||||
|  |     tData[bindingIndex + 1] = i1; | ||||||
|  |     tData[bindingIndex + 2] = i2; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return different ? | ||||||
|  |       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + | ||||||
|  |           renderStringify(v3) + suffix : | ||||||
|  |       NO_CHANGE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Creates an interpolation binding with 5 expressions. | ||||||
|  |  * | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵinterpolation5( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     i3: string, v4: any, suffix: string): string|NO_CHANGE { | ||||||
|  |   const lView = getLView(); | ||||||
|  |   const bindingIndex = lView[BINDING_INDEX]; | ||||||
|  |   let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); | ||||||
|  |   different = bindingUpdated(lView, bindingIndex + 4, v4) || different; | ||||||
|  |   lView[BINDING_INDEX] += 5; | ||||||
|  | 
 | ||||||
|  |   // Only set static strings the first time (data will be null subsequent runs).
 | ||||||
|  |   const data = storeBindingMetadata(lView, prefix, suffix); | ||||||
|  |   if (data) { | ||||||
|  |     const tData = lView[TVIEW].data; | ||||||
|  |     tData[bindingIndex] = i0; | ||||||
|  |     tData[bindingIndex + 1] = i1; | ||||||
|  |     tData[bindingIndex + 2] = i2; | ||||||
|  |     tData[bindingIndex + 3] = i3; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return different ? | ||||||
|  |       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + | ||||||
|  |           renderStringify(v3) + i3 + renderStringify(v4) + suffix : | ||||||
|  |       NO_CHANGE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Creates an interpolation binding with 6 expressions. | ||||||
|  |  * | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵinterpolation6( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     i3: string, v4: any, i4: string, v5: any, suffix: string): string|NO_CHANGE { | ||||||
|  |   const lView = getLView(); | ||||||
|  |   const bindingIndex = lView[BINDING_INDEX]; | ||||||
|  |   let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); | ||||||
|  |   different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different; | ||||||
|  |   lView[BINDING_INDEX] += 6; | ||||||
|  | 
 | ||||||
|  |   // Only set static strings the first time (data will be null subsequent runs).
 | ||||||
|  |   const data = storeBindingMetadata(lView, prefix, suffix); | ||||||
|  |   if (data) { | ||||||
|  |     const tData = lView[TVIEW].data; | ||||||
|  |     tData[bindingIndex] = i0; | ||||||
|  |     tData[bindingIndex + 1] = i1; | ||||||
|  |     tData[bindingIndex + 2] = i2; | ||||||
|  |     tData[bindingIndex + 3] = i3; | ||||||
|  |     tData[bindingIndex + 4] = i4; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return different ? | ||||||
|  |       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + | ||||||
|  |           renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + suffix : | ||||||
|  |       NO_CHANGE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Creates an interpolation binding with 7 expressions. | ||||||
|  |  * | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵinterpolation7( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string): string| | ||||||
|  |     NO_CHANGE { | ||||||
|  |   const lView = getLView(); | ||||||
|  |   const bindingIndex = lView[BINDING_INDEX]; | ||||||
|  |   let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); | ||||||
|  |   different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different; | ||||||
|  |   lView[BINDING_INDEX] += 7; | ||||||
|  | 
 | ||||||
|  |   // Only set static strings the first time (data will be null subsequent runs).
 | ||||||
|  |   const data = storeBindingMetadata(lView, prefix, suffix); | ||||||
|  |   if (data) { | ||||||
|  |     const tData = lView[TVIEW].data; | ||||||
|  |     tData[bindingIndex] = i0; | ||||||
|  |     tData[bindingIndex + 1] = i1; | ||||||
|  |     tData[bindingIndex + 2] = i2; | ||||||
|  |     tData[bindingIndex + 3] = i3; | ||||||
|  |     tData[bindingIndex + 4] = i4; | ||||||
|  |     tData[bindingIndex + 5] = i5; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return different ? | ||||||
|  |       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + | ||||||
|  |           renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + i5 + | ||||||
|  |           renderStringify(v6) + suffix : | ||||||
|  |       NO_CHANGE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Creates an interpolation binding with 8 expressions. | ||||||
|  |  * | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵinterpolation8( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any, | ||||||
|  |     suffix: string): string|NO_CHANGE { | ||||||
|  |   const lView = getLView(); | ||||||
|  |   const bindingIndex = lView[BINDING_INDEX]; | ||||||
|  |   let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); | ||||||
|  |   different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different; | ||||||
|  |   lView[BINDING_INDEX] += 8; | ||||||
|  | 
 | ||||||
|  |   // Only set static strings the first time (data will be null subsequent runs).
 | ||||||
|  |   const data = storeBindingMetadata(lView, prefix, suffix); | ||||||
|  |   if (data) { | ||||||
|  |     const tData = lView[TVIEW].data; | ||||||
|  |     tData[bindingIndex] = i0; | ||||||
|  |     tData[bindingIndex + 1] = i1; | ||||||
|  |     tData[bindingIndex + 2] = i2; | ||||||
|  |     tData[bindingIndex + 3] = i3; | ||||||
|  |     tData[bindingIndex + 4] = i4; | ||||||
|  |     tData[bindingIndex + 5] = i5; | ||||||
|  |     tData[bindingIndex + 6] = i6; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return different ? | ||||||
|  |       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + | ||||||
|  |           renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + i5 + | ||||||
|  |           renderStringify(v6) + i6 + renderStringify(v7) + suffix : | ||||||
|  |       NO_CHANGE; | ||||||
|  | } | ||||||
| @ -5,293 +5,14 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {assertEqual, assertLessThan} from '../../util/assert'; |  | ||||||
| import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from '../bindings'; |  | ||||||
| import {SanitizerFn} from '../interfaces/sanitization'; | import {SanitizerFn} from '../interfaces/sanitization'; | ||||||
| import {BINDING_INDEX, TVIEW} from '../interfaces/view'; | import {getSelectedIndex} from '../state'; | ||||||
| import {getLView, getSelectedIndex} from '../state'; |  | ||||||
| import {NO_CHANGE} from '../tokens'; | import {NO_CHANGE} from '../tokens'; | ||||||
| import {renderStringify} from '../util/misc_utils'; |  | ||||||
| 
 | 
 | ||||||
| import {TsickleIssue1009, elementPropertyInternal, storeBindingMetadata} from './shared'; | import {ɵɵinterpolation1, ɵɵinterpolation2, ɵɵinterpolation3, ɵɵinterpolation4, ɵɵinterpolation5, ɵɵinterpolation6, ɵɵinterpolation7, ɵɵinterpolation8, ɵɵinterpolationV} from './interpolation'; | ||||||
|  | import {TsickleIssue1009, elementPropertyInternal} from './shared'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Create interpolation bindings with a variable number of expressions. |  | ||||||
|  * |  | ||||||
|  * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead. |  | ||||||
|  * Those are faster because there is no need to create an array of expressions and iterate over it. |  | ||||||
|  * |  | ||||||
|  * `values`: |  | ||||||
|  * - has static text at even indexes, |  | ||||||
|  * - has evaluated expressions at odd indexes. |  | ||||||
|  * |  | ||||||
|  * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵinterpolationV(values: any[]): string|NO_CHANGE { |  | ||||||
|   ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values'); |  | ||||||
|   ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values'); |  | ||||||
|   let different = false; |  | ||||||
|   const lView = getLView(); |  | ||||||
|   const tData = lView[TVIEW].data; |  | ||||||
|   let bindingIndex = lView[BINDING_INDEX]; |  | ||||||
| 
 |  | ||||||
|   if (tData[bindingIndex] == null) { |  | ||||||
|     // 2 is the index of the first static interstitial value (ie. not prefix)
 |  | ||||||
|     for (let i = 2; i < values.length; i += 2) { |  | ||||||
|       tData[bindingIndex++] = values[i]; |  | ||||||
|     } |  | ||||||
|     bindingIndex = lView[BINDING_INDEX]; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   for (let i = 1; i < values.length; i += 2) { |  | ||||||
|     // Check if bindings (odd indexes) have changed
 |  | ||||||
|     bindingUpdated(lView, bindingIndex++, values[i]) && (different = true); |  | ||||||
|   } |  | ||||||
|   lView[BINDING_INDEX] = bindingIndex; |  | ||||||
|   storeBindingMetadata(lView, values[0], values[values.length - 1]); |  | ||||||
| 
 |  | ||||||
|   if (!different) { |  | ||||||
|     return NO_CHANGE; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   // Build the updated content
 |  | ||||||
|   let content = values[0]; |  | ||||||
|   for (let i = 1; i < values.length; i += 2) { |  | ||||||
|     content += renderStringify(values[i]) + values[i + 1]; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return content; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Creates an interpolation binding with 1 expression. |  | ||||||
|  * |  | ||||||
|  * @param prefix static value used for concatenation only. |  | ||||||
|  * @param v0 value checked for change. |  | ||||||
|  * @param suffix static value used for concatenation only. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵinterpolation1(prefix: string, v0: any, suffix: string): string|NO_CHANGE { |  | ||||||
|   const lView = getLView(); |  | ||||||
|   const different = bindingUpdated(lView, lView[BINDING_INDEX]++, v0); |  | ||||||
|   storeBindingMetadata(lView, prefix, suffix); |  | ||||||
|   return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Creates an interpolation binding with 2 expressions. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵinterpolation2( |  | ||||||
|     prefix: string, v0: any, i0: string, v1: any, suffix: string): string|NO_CHANGE { |  | ||||||
|   const lView = getLView(); |  | ||||||
|   const bindingIndex = lView[BINDING_INDEX]; |  | ||||||
|   const different = bindingUpdated2(lView, bindingIndex, v0, v1); |  | ||||||
|   lView[BINDING_INDEX] += 2; |  | ||||||
| 
 |  | ||||||
|   // Only set static strings the first time (data will be null subsequent runs).
 |  | ||||||
|   const data = storeBindingMetadata(lView, prefix, suffix); |  | ||||||
|   if (data) { |  | ||||||
|     lView[TVIEW].data[bindingIndex] = i0; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Creates an interpolation binding with 3 expressions. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵinterpolation3( |  | ||||||
|     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, suffix: string): string| |  | ||||||
|     NO_CHANGE { |  | ||||||
|   const lView = getLView(); |  | ||||||
|   const bindingIndex = lView[BINDING_INDEX]; |  | ||||||
|   const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2); |  | ||||||
|   lView[BINDING_INDEX] += 3; |  | ||||||
| 
 |  | ||||||
|   // Only set static strings the first time (data will be null subsequent runs).
 |  | ||||||
|   const data = storeBindingMetadata(lView, prefix, suffix); |  | ||||||
|   if (data) { |  | ||||||
|     const tData = lView[TVIEW].data; |  | ||||||
|     tData[bindingIndex] = i0; |  | ||||||
|     tData[bindingIndex + 1] = i1; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return different ? |  | ||||||
|       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix : |  | ||||||
|       NO_CHANGE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Create an interpolation binding with 4 expressions. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵinterpolation4( |  | ||||||
|     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, |  | ||||||
|     suffix: string): string|NO_CHANGE { |  | ||||||
|   const lView = getLView(); |  | ||||||
|   const bindingIndex = lView[BINDING_INDEX]; |  | ||||||
|   const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); |  | ||||||
|   lView[BINDING_INDEX] += 4; |  | ||||||
| 
 |  | ||||||
|   // Only set static strings the first time (data will be null subsequent runs).
 |  | ||||||
|   const data = storeBindingMetadata(lView, prefix, suffix); |  | ||||||
|   if (data) { |  | ||||||
|     const tData = lView[TVIEW].data; |  | ||||||
|     tData[bindingIndex] = i0; |  | ||||||
|     tData[bindingIndex + 1] = i1; |  | ||||||
|     tData[bindingIndex + 2] = i2; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return different ? |  | ||||||
|       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + |  | ||||||
|           renderStringify(v3) + suffix : |  | ||||||
|       NO_CHANGE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Creates an interpolation binding with 5 expressions. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵinterpolation5( |  | ||||||
|     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, |  | ||||||
|     i3: string, v4: any, suffix: string): string|NO_CHANGE { |  | ||||||
|   const lView = getLView(); |  | ||||||
|   const bindingIndex = lView[BINDING_INDEX]; |  | ||||||
|   let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); |  | ||||||
|   different = bindingUpdated(lView, bindingIndex + 4, v4) || different; |  | ||||||
|   lView[BINDING_INDEX] += 5; |  | ||||||
| 
 |  | ||||||
|   // Only set static strings the first time (data will be null subsequent runs).
 |  | ||||||
|   const data = storeBindingMetadata(lView, prefix, suffix); |  | ||||||
|   if (data) { |  | ||||||
|     const tData = lView[TVIEW].data; |  | ||||||
|     tData[bindingIndex] = i0; |  | ||||||
|     tData[bindingIndex + 1] = i1; |  | ||||||
|     tData[bindingIndex + 2] = i2; |  | ||||||
|     tData[bindingIndex + 3] = i3; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return different ? |  | ||||||
|       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + |  | ||||||
|           renderStringify(v3) + i3 + renderStringify(v4) + suffix : |  | ||||||
|       NO_CHANGE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Creates an interpolation binding with 6 expressions. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵinterpolation6( |  | ||||||
|     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, |  | ||||||
|     i3: string, v4: any, i4: string, v5: any, suffix: string): string|NO_CHANGE { |  | ||||||
|   const lView = getLView(); |  | ||||||
|   const bindingIndex = lView[BINDING_INDEX]; |  | ||||||
|   let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); |  | ||||||
|   different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different; |  | ||||||
|   lView[BINDING_INDEX] += 6; |  | ||||||
| 
 |  | ||||||
|   // Only set static strings the first time (data will be null subsequent runs).
 |  | ||||||
|   const data = storeBindingMetadata(lView, prefix, suffix); |  | ||||||
|   if (data) { |  | ||||||
|     const tData = lView[TVIEW].data; |  | ||||||
|     tData[bindingIndex] = i0; |  | ||||||
|     tData[bindingIndex + 1] = i1; |  | ||||||
|     tData[bindingIndex + 2] = i2; |  | ||||||
|     tData[bindingIndex + 3] = i3; |  | ||||||
|     tData[bindingIndex + 4] = i4; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return different ? |  | ||||||
|       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + |  | ||||||
|           renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + suffix : |  | ||||||
|       NO_CHANGE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Creates an interpolation binding with 7 expressions. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵinterpolation7( |  | ||||||
|     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, |  | ||||||
|     i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string): string| |  | ||||||
|     NO_CHANGE { |  | ||||||
|   const lView = getLView(); |  | ||||||
|   const bindingIndex = lView[BINDING_INDEX]; |  | ||||||
|   let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); |  | ||||||
|   different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different; |  | ||||||
|   lView[BINDING_INDEX] += 7; |  | ||||||
| 
 |  | ||||||
|   // Only set static strings the first time (data will be null subsequent runs).
 |  | ||||||
|   const data = storeBindingMetadata(lView, prefix, suffix); |  | ||||||
|   if (data) { |  | ||||||
|     const tData = lView[TVIEW].data; |  | ||||||
|     tData[bindingIndex] = i0; |  | ||||||
|     tData[bindingIndex + 1] = i1; |  | ||||||
|     tData[bindingIndex + 2] = i2; |  | ||||||
|     tData[bindingIndex + 3] = i3; |  | ||||||
|     tData[bindingIndex + 4] = i4; |  | ||||||
|     tData[bindingIndex + 5] = i5; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return different ? |  | ||||||
|       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + |  | ||||||
|           renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + i5 + |  | ||||||
|           renderStringify(v6) + suffix : |  | ||||||
|       NO_CHANGE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Creates an interpolation binding with 8 expressions. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵinterpolation8( |  | ||||||
|     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, |  | ||||||
|     i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any, |  | ||||||
|     suffix: string): string|NO_CHANGE { |  | ||||||
|   const lView = getLView(); |  | ||||||
|   const bindingIndex = lView[BINDING_INDEX]; |  | ||||||
|   let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); |  | ||||||
|   different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different; |  | ||||||
|   lView[BINDING_INDEX] += 8; |  | ||||||
| 
 |  | ||||||
|   // Only set static strings the first time (data will be null subsequent runs).
 |  | ||||||
|   const data = storeBindingMetadata(lView, prefix, suffix); |  | ||||||
|   if (data) { |  | ||||||
|     const tData = lView[TVIEW].data; |  | ||||||
|     tData[bindingIndex] = i0; |  | ||||||
|     tData[bindingIndex + 1] = i1; |  | ||||||
|     tData[bindingIndex + 2] = i2; |  | ||||||
|     tData[bindingIndex + 3] = i3; |  | ||||||
|     tData[bindingIndex + 4] = i4; |  | ||||||
|     tData[bindingIndex + 5] = i5; |  | ||||||
|     tData[bindingIndex + 6] = i6; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return different ? |  | ||||||
|       prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + |  | ||||||
|           renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + i5 + |  | ||||||
|           renderStringify(v6) + i6 + renderStringify(v7) + suffix : |  | ||||||
|       NO_CHANGE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /////////////////////////////////////////////////////////////////////
 |  | ||||||
| /// NEW INSTRUCTIONS
 |  | ||||||
| /////////////////////////////////////////////////////////////////////
 |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * |  * | ||||||
|  * Update an interpolated property on an element with a lone bound value |  * Update an interpolated property on an element with a lone bound value | ||||||
|  | |||||||
							
								
								
									
										298
									
								
								packages/core/src/render3/instructions/text_interpolation.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								packages/core/src/render3/instructions/text_interpolation.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,298 @@ | |||||||
|  | /** | ||||||
|  |  * @license | ||||||
|  |  * Copyright Google Inc. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  |  */ | ||||||
|  | import {getSelectedIndex} from '../state'; | ||||||
|  | 
 | ||||||
|  | import {ɵɵinterpolation1, ɵɵinterpolation2, ɵɵinterpolation3, ɵɵinterpolation4, ɵɵinterpolation5, ɵɵinterpolation6, ɵɵinterpolation7, ɵɵinterpolation8, ɵɵinterpolationV} from './interpolation'; | ||||||
|  | import {TsickleIssue1009} from './shared'; | ||||||
|  | import {ɵɵtextBinding} from './text'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * Update text content with a lone bound value | ||||||
|  |  * | ||||||
|  |  * Used when a text node has 1 interpolated value in it, an no additional text | ||||||
|  |  * surrounds that interpolated value: | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>{{v0}}</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolate(v0); | ||||||
|  |  * ``` | ||||||
|  |  * @returns itself, so that it may be chained. | ||||||
|  |  * @see textInterpolateV | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolate(v0: any): TsickleIssue1009 { | ||||||
|  |   ɵɵtextInterpolate1('', v0, ''); | ||||||
|  |   return ɵɵtextInterpolate; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * Update text content with single bound value surrounded by other text. | ||||||
|  |  * | ||||||
|  |  * Used when a text node has 1 interpolated value in it: | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>prefix{{v0}}suffix</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolate1('prefix', v0, 'suffix'); | ||||||
|  |  * ``` | ||||||
|  |  * @returns itself, so that it may be chained. | ||||||
|  |  * @see textInterpolateV | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolate1(prefix: string, v0: any, suffix: string): TsickleIssue1009 { | ||||||
|  |   const index = getSelectedIndex(); | ||||||
|  |   ɵɵtextBinding(index, ɵɵinterpolation1(prefix, v0, suffix)); | ||||||
|  |   return ɵɵtextInterpolate1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * Update text content with 2 bound values surrounded by other text. | ||||||
|  |  * | ||||||
|  |  * Used when a text node has 2 interpolated values in it: | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>prefix{{v0}}-{{v1}}suffix</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolate2('prefix', v0, '-', v1, 'suffix'); | ||||||
|  |  * ``` | ||||||
|  |  * @returns itself, so that it may be chained. | ||||||
|  |  * @see textInterpolateV | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolate2( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, suffix: string): TsickleIssue1009 { | ||||||
|  |   const index = getSelectedIndex(); | ||||||
|  |   ɵɵtextBinding(index, ɵɵinterpolation2(prefix, v0, i0, v1, suffix)); | ||||||
|  |   return ɵɵtextInterpolate2; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * Update text content with 3 bound values surrounded by other text. | ||||||
|  |  * | ||||||
|  |  * Used when a text node has 3 interpolated values in it: | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>prefix{{v0}}-{{v1}}-{{v2}}suffix</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolate3( | ||||||
|  |  * 'prefix', v0, '-', v1, '-', v2, 'suffix'); | ||||||
|  |  * ``` | ||||||
|  |  * @returns itself, so that it may be chained. | ||||||
|  |  * @see textInterpolateV | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolate3( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, | ||||||
|  |     suffix: string): TsickleIssue1009 { | ||||||
|  |   const index = getSelectedIndex(); | ||||||
|  |   ɵɵtextBinding(index, ɵɵinterpolation3(prefix, v0, i0, v1, i1, v2, suffix)); | ||||||
|  |   return ɵɵtextInterpolate3; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * Update text content with 4 bound values surrounded by other text. | ||||||
|  |  * | ||||||
|  |  * Used when a text node has 4 interpolated values in it: | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolate4( | ||||||
|  |  * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix'); | ||||||
|  |  * ``` | ||||||
|  |  * @returns itself, so that it may be chained. | ||||||
|  |  * @see ɵɵtextInterpolateV | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolate4( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     suffix: string): TsickleIssue1009 { | ||||||
|  |   const index = getSelectedIndex(); | ||||||
|  |   ɵɵtextBinding(index, ɵɵinterpolation4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix)); | ||||||
|  |   return ɵɵtextInterpolate4; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * Update text content with 5 bound values surrounded by other text. | ||||||
|  |  * | ||||||
|  |  * Used when a text node has 5 interpolated values in it: | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolate5( | ||||||
|  |  * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix'); | ||||||
|  |  * ``` | ||||||
|  |  * @returns itself, so that it may be chained. | ||||||
|  |  * @see textInterpolateV | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolate5( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     i3: string, v4: any, suffix: string): TsickleIssue1009 { | ||||||
|  |   const index = getSelectedIndex(); | ||||||
|  |   ɵɵtextBinding(index, ɵɵinterpolation5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix)); | ||||||
|  |   return ɵɵtextInterpolate5; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * Update text content with 6 bound values surrounded by other text. | ||||||
|  |  * | ||||||
|  |  * Used when a text node has 6 interpolated values in it: | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolate6( | ||||||
|  |  *    'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix'); | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * @param i4 Static value used for concatenation only. | ||||||
|  |  * @param v5 Value checked for change. @returns itself, so that it may be chained. | ||||||
|  |  * @see textInterpolateV | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolate6( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     i3: string, v4: any, i4: string, v5: any, suffix: string): TsickleIssue1009 { | ||||||
|  |   const index = getSelectedIndex(); | ||||||
|  |   ɵɵtextBinding( | ||||||
|  |       index, ɵɵinterpolation6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix)); | ||||||
|  |   return ɵɵtextInterpolate6; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * Update text content with 7 bound values surrounded by other text. | ||||||
|  |  * | ||||||
|  |  * Used when a text node has 7 interpolated values in it: | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolate7( | ||||||
|  |  *    'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix'); | ||||||
|  |  * ``` | ||||||
|  |  * @returns itself, so that it may be chained. | ||||||
|  |  * @see textInterpolateV | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolate7( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, | ||||||
|  |     suffix: string): TsickleIssue1009 { | ||||||
|  |   const index = getSelectedIndex(); | ||||||
|  |   ɵɵtextBinding( | ||||||
|  |       index, ɵɵinterpolation7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix)); | ||||||
|  |   return ɵɵtextInterpolate7; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * Update text content with 8 bound values surrounded by other text. | ||||||
|  |  * | ||||||
|  |  * Used when a text node has 8 interpolated values in it: | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolate8( | ||||||
|  |  *  'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix'); | ||||||
|  |  * ``` | ||||||
|  |  * @returns itself, so that it may be chained. | ||||||
|  |  * @see textInterpolateV | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolate8( | ||||||
|  |     prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, | ||||||
|  |     i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any, | ||||||
|  |     suffix: string): TsickleIssue1009 { | ||||||
|  |   const index = getSelectedIndex(); | ||||||
|  |   ɵɵtextBinding( | ||||||
|  |       index, | ||||||
|  |       ɵɵinterpolation8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix)); | ||||||
|  |   return ɵɵtextInterpolate8; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Update text content with 9 or more bound values other surrounded by text. | ||||||
|  |  * | ||||||
|  |  * Used when the number of interpolated values exceeds 8. | ||||||
|  |  * | ||||||
|  |  * ```html
 | ||||||
|  |  * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix</div> | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Its compiled representation is: | ||||||
|  |  * | ||||||
|  |  * ```ts
 | ||||||
|  |  * ɵɵtextInterpolateV( | ||||||
|  |  *  ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9, | ||||||
|  |  *  'suffix']); | ||||||
|  |  * ``` | ||||||
|  |  *. | ||||||
|  |  * @param values The a collection of values and the strings in between those values, beginning with | ||||||
|  |  * a string prefix and ending with a string suffix. | ||||||
|  |  * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`) | ||||||
|  |  * | ||||||
|  |  * @returns itself, so that it may be chained. | ||||||
|  |  * @codeGenApi | ||||||
|  |  */ | ||||||
|  | export function ɵɵtextInterpolateV(values: any[]): TsickleIssue1009 { | ||||||
|  |   const index = getSelectedIndex(); | ||||||
|  | 
 | ||||||
|  |   ɵɵtextBinding(index, ɵɵinterpolationV(values)); | ||||||
|  |   return ɵɵtextInterpolateV; | ||||||
|  | } | ||||||
| @ -127,6 +127,16 @@ export const angularCoreEnv: {[name: string]: Function} = | |||||||
|        'ɵɵtemplate': r3.ɵɵtemplate, |        'ɵɵtemplate': r3.ɵɵtemplate, | ||||||
|        'ɵɵtext': r3.ɵɵtext, |        'ɵɵtext': r3.ɵɵtext, | ||||||
|        'ɵɵtextBinding': r3.ɵɵtextBinding, |        'ɵɵtextBinding': r3.ɵɵtextBinding, | ||||||
|  |        'ɵɵtextInterpolate': r3.ɵɵtextInterpolate, | ||||||
|  |        'ɵɵtextInterpolate1': r3.ɵɵtextInterpolate1, | ||||||
|  |        'ɵɵtextInterpolate2': r3.ɵɵtextInterpolate2, | ||||||
|  |        'ɵɵtextInterpolate3': r3.ɵɵtextInterpolate3, | ||||||
|  |        'ɵɵtextInterpolate4': r3.ɵɵtextInterpolate4, | ||||||
|  |        'ɵɵtextInterpolate5': r3.ɵɵtextInterpolate5, | ||||||
|  |        'ɵɵtextInterpolate6': r3.ɵɵtextInterpolate6, | ||||||
|  |        'ɵɵtextInterpolate7': r3.ɵɵtextInterpolate7, | ||||||
|  |        'ɵɵtextInterpolate8': r3.ɵɵtextInterpolate8, | ||||||
|  |        'ɵɵtextInterpolateV': r3.ɵɵtextInterpolateV, | ||||||
|        'ɵɵembeddedViewStart': r3.ɵɵembeddedViewStart, |        'ɵɵembeddedViewStart': r3.ɵɵembeddedViewStart, | ||||||
|        'ɵɵembeddedViewEnd': r3.ɵɵembeddedViewEnd, |        'ɵɵembeddedViewEnd': r3.ɵɵembeddedViewEnd, | ||||||
|        'ɵɵi18n': r3.ɵɵi18n, |        'ɵɵi18n': r3.ɵɵi18n, | ||||||
|  | |||||||
							
								
								
									
										115
									
								
								packages/core/test/acceptance/text_spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								packages/core/test/acceptance/text_spec.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,115 @@ | |||||||
|  | /** | ||||||
|  |  * @license | ||||||
|  |  * Copyright Google Inc. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  |  */ | ||||||
|  | import {Component} from '@angular/core'; | ||||||
|  | import {TestBed} from '@angular/core/testing'; | ||||||
|  | import {of } from 'rxjs'; | ||||||
|  | 
 | ||||||
|  | describe('text instructions', () => { | ||||||
|  |   it('should handle all flavors of interpolated text', () => { | ||||||
|  |     @Component({ | ||||||
|  |       template: ` | ||||||
|  |         <div>a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i{{nine}}j</div> | ||||||
|  |         <div>a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i</div> | ||||||
|  |         <div>a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h</div> | ||||||
|  |         <div>a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g</div> | ||||||
|  |         <div>a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f</div> | ||||||
|  |         <div>a{{one}}b{{two}}c{{three}}d{{four}}e</div> | ||||||
|  |         <div>a{{one}}b{{two}}c{{three}}d</div> | ||||||
|  |         <div>a{{one}}b{{two}}c</div> | ||||||
|  |         <div>a{{one}}b</div> | ||||||
|  |         <div>{{one}}</div> | ||||||
|  |       ` | ||||||
|  |     }) | ||||||
|  |     class App { | ||||||
|  |       one = 1; | ||||||
|  |       two = 2; | ||||||
|  |       three = 3; | ||||||
|  |       four = 4; | ||||||
|  |       five = 5; | ||||||
|  |       six = 6; | ||||||
|  |       seven = 7; | ||||||
|  |       eight = 8; | ||||||
|  |       nine = 9; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     TestBed.configureTestingModule({declarations: [App]}); | ||||||
|  |     const fixture = TestBed.createComponent(App); | ||||||
|  |     fixture.detectChanges(); | ||||||
|  | 
 | ||||||
|  |     const allTextContent = Array.from(fixture.nativeElement.querySelectorAll('div')) | ||||||
|  |                                .map((div: HTMLDivElement) => div.textContent); | ||||||
|  | 
 | ||||||
|  |     expect(allTextContent).toEqual([ | ||||||
|  |       'a1b2c3d4e5f6g7h8i9j', | ||||||
|  |       'a1b2c3d4e5f6g7h8i', | ||||||
|  |       'a1b2c3d4e5f6g7h', | ||||||
|  |       'a1b2c3d4e5f6g', | ||||||
|  |       'a1b2c3d4e5f', | ||||||
|  |       'a1b2c3d4e', | ||||||
|  |       'a1b2c3d', | ||||||
|  |       'a1b2c', | ||||||
|  |       'a1b', | ||||||
|  |       '1', | ||||||
|  |     ]); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should handle piped values in interpolated text', () => { | ||||||
|  |     @Component({ | ||||||
|  |       template: ` | ||||||
|  |         <p>{{who | async}} sells {{(item | async)?.what}} down by the {{(item | async)?.where}}.</p> | ||||||
|  |       ` | ||||||
|  |     }) | ||||||
|  |     class App { | ||||||
|  |       who = of ('Sally'); | ||||||
|  |       item = of ({ | ||||||
|  |         what: 'seashells', | ||||||
|  |         where: 'seashore', | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     TestBed.configureTestingModule({declarations: [App]}); | ||||||
|  |     const fixture = TestBed.createComponent(App); | ||||||
|  |     fixture.detectChanges(); | ||||||
|  | 
 | ||||||
|  |     const p = fixture.nativeElement.querySelector('p') as HTMLDivElement; | ||||||
|  |     expect(p.textContent).toBe('Sally sells seashells down by the seashore.'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should not sanitize urls in interpolated text', () => { | ||||||
|  |     @Component({ | ||||||
|  |       template: '<p>{{thisisfine}}</p>', | ||||||
|  |     }) | ||||||
|  |     class App { | ||||||
|  |       thisisfine = 'javascript:alert("image_of_dog_with_coffee_in_burning_building.gif")'; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     TestBed.configureTestingModule({declarations: [App]}); | ||||||
|  |     const fixture = TestBed.createComponent(App); | ||||||
|  |     fixture.detectChanges(); | ||||||
|  |     const p = fixture.nativeElement.querySelector('p'); | ||||||
|  | 
 | ||||||
|  |     expect(p.textContent) | ||||||
|  |         .toBe('javascript:alert("image_of_dog_with_coffee_in_burning_building.gif")'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should not allow writing HTML in interpolated text', () => { | ||||||
|  |     @Component({ | ||||||
|  |       template: '<div>{{test}}</div>', | ||||||
|  |     }) | ||||||
|  |     class App { | ||||||
|  |       test = '<h1>LOL, big text</h1>'; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     TestBed.configureTestingModule({declarations: [App]}); | ||||||
|  |     const fixture = TestBed.createComponent(App); | ||||||
|  |     fixture.detectChanges(); | ||||||
|  |     const div = fixture.nativeElement.querySelector('div'); | ||||||
|  | 
 | ||||||
|  |     expect(div.innerHTML).toBe('<h1>LOL, big text</h1>'); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -1603,5 +1603,11 @@ | |||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     "name": "ɵɵtextBinding" |     "name": "ɵɵtextBinding" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "name": "ɵɵtextInterpolate" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "name": "ɵɵtextInterpolate1" | ||||||
|   } |   } | ||||||
| ] | ] | ||||||
							
								
								
									
										20
									
								
								tools/public_api_guard/core/core.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								tools/public_api_guard/core/core.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -1057,6 +1057,26 @@ export declare function ɵɵtext(index: number, value?: any): void; | |||||||
| 
 | 
 | ||||||
| export declare function ɵɵtextBinding<T>(index: number, value: T | NO_CHANGE): void; | export declare function ɵɵtextBinding<T>(index: number, value: T | NO_CHANGE): void; | ||||||
| 
 | 
 | ||||||
|  | export declare function ɵɵtextInterpolate(v0: any): TsickleIssue1009; | ||||||
|  | 
 | ||||||
|  | export declare function ɵɵtextInterpolate1(prefix: string, v0: any, suffix: string): TsickleIssue1009; | ||||||
|  | 
 | ||||||
|  | export declare function ɵɵtextInterpolate2(prefix: string, v0: any, i0: string, v1: any, suffix: string): TsickleIssue1009; | ||||||
|  | 
 | ||||||
|  | export declare function ɵɵtextInterpolate3(prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, suffix: string): TsickleIssue1009; | ||||||
|  | 
 | ||||||
|  | export declare function ɵɵtextInterpolate4(prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, suffix: string): TsickleIssue1009; | ||||||
|  | 
 | ||||||
|  | export declare function ɵɵtextInterpolate5(prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, suffix: string): TsickleIssue1009; | ||||||
|  | 
 | ||||||
|  | export declare function ɵɵtextInterpolate6(prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string): TsickleIssue1009; | ||||||
|  | 
 | ||||||
|  | export declare function ɵɵtextInterpolate7(prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string): TsickleIssue1009; | ||||||
|  | 
 | ||||||
|  | export declare function ɵɵtextInterpolate8(prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any, suffix: string): TsickleIssue1009; | ||||||
|  | 
 | ||||||
|  | export declare function ɵɵtextInterpolateV(values: any[]): TsickleIssue1009; | ||||||
|  | 
 | ||||||
| export declare function ɵɵviewQuery<T>(predicate: Type<any> | string[], descend: boolean, read: any): QueryList<T>; | export declare function ɵɵviewQuery<T>(predicate: Type<any> | string[], descend: boolean, read: any): QueryList<T>; | ||||||
| 
 | 
 | ||||||
| export declare const PACKAGE_ROOT_URL: InjectionToken<string>; | export declare const PACKAGE_ROOT_URL: InjectionToken<string>; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user