fix(ivy): flatten template fns for nested views#24943
Conversation
bbcc7e6 to
90eb88f
Compare
61a7d91 to
e68ff53
Compare
c4eee9b to
4705613
Compare
|
You can preview d4103d6 at https://pr24943-d4103d6.ngbuilds.io/. |
|
You can preview 7e5595a at https://pr24943-7e5595a.ngbuilds.io/. |
|
You can preview 26f76b1 at https://pr24943-26f76b1.ngbuilds.io/. |
|
Before this change, private properties usage is fully supported in any template, but this change is going to make private properties usage quite inconsistent. Given the class: class AppComponent {
private foo = 42
}Then using private property directly inside Component template is allowed: <!-- Works always -->
<div>{{ foo }}</div>But using private property inside any embedded template is NOT allowed: <!-- Works before -->
<!-- Throws after -->
<div *ngIf="true">{{ foo }}</div>Even supporting private property is not promised, but the implementation detail could make it confusing to users. Update: I guess I was wrong and the condition seem even worse, given |
|
|
You can preview 180082e at https://pr24943-180082e.ngbuilds.io/. |
|
@mhevery I didn't mean it's a breaking change from view engine, but having in-fact partial support is confusing (as it's indeed supported in component template by Ivy). Imagine a user have private property already and everything is fine in AOT, once he/she added an Also polluting entire module scope with additional So how about using IIFE while and do NOT emit code outside the class MyComponent {
static ngComponentDef = ɵdefineComponent({
template: (() => {
function MyComponent_li_Template_2(rf: RenderFlags, ctx: SomeContext) {
// ...
}
function MyComponent_Template(rf: RenderFlags, ctx: MyComponent) {
if (rf & 1) {
ɵE(0, "ul", null, $c1$);
ɵC(2, MyComponent_li_Template_2, null, $c2$);
ɵe();
}
// ...
}
return MyComponent_Template;
})()
})
}I guess this is also what TypeScript does in their code emitting. |
|
@mhevery Please also consider the possibility of const createFooComponent = (val: number) => (flag ? @Component({}) class FooComp { foo = val } : @Component({}) class FooComp { foo = -val })
const createBarComponent = (val: number) => (@Component({}) class { bar = val })And it's impossible to emit code to their own scopes, but only at top-level. Then the compiler would need to maintain an extra class counter per module. |
|
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
This PR fixes contexts for recursive components and components with deeply nested
ngFors. It also fixes bindings to local refs before local ref definitions.Changes:
Example:
Before:
After:
TView.componentsno longer tracks directive indices (just host element indices). We can cut the components array in half because context for components is now being stored in the component'sLViewDatainstance and can be accessed from there.reference()(r()). Previously, we were using closures to get access to local refs in parent views. Now that nested template functions are flat, they do not have access to the local refs through a closure, so we need another way to walk the view tree.referencetakes a nesting level and the local ref's index, then walks the view tree to find the correct view from which to load the local ref.Before:
After: