Skip to content

Commit

Permalink
fixup! fix(compiler): this.a should always refer to class property a
Browse files Browse the repository at this point in the history
  • Loading branch information
JoostK committed Oct 7, 2024
1 parent 0c8817e commit f7ba14f
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1249,13 +1249,13 @@ import * as i0 from "@angular/core";
export class MyComponent {
}
MyComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: MyComponent, isStandalone: true, selector: "my-component", ngImport: i0, template: '<ng-template let-a [ngIf]="true">{{this.a}}</ng-template>', isInline: true });
MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: MyComponent, isStandalone: true, selector: "my-component", ngImport: i0, template: '<ng-template let-a [ngIf]="true">{{a}}</ng-template>', isInline: true });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyComponent, decorators: [{
type: Component,
args: [{
selector: 'my-component',
standalone: true,
template: '<ng-template let-a [ngIf]="true">{{this.a}}</ng-template>',
template: '<ng-template let-a [ngIf]="true">{{a}}</ng-template>',
}]
}] });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ MyComponent_ng_template_0_Template(rf, ctx) {
if (rf & 1) {
i0.ɵɵtext(0);
} if (rf & 2) {
const $a_r1$ = i0.ɵɵnextContext();
const $a_r1$ = ctx.$implicit;
i0.ɵɵtextInterpolate($a_r1$);
}
}
Expand All @@ -15,4 +15,4 @@ function MyComponent_Template(rf, ctx) {
} if (rf & 2) {
i0.ɵɵproperty("ngIf", true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Component} from '@angular/core';
@Component({
selector: 'my-component',
standalone: true,
template: '<ng-template let-a [ngIf]="true">{{this.a}}</ng-template>',
template: '<ng-template let-a [ngIf]="true">{{a}}</ng-template>',
})
export class MyComponent {
p1!: any;
Expand Down
10 changes: 1 addition & 9 deletions packages/compiler/src/render3/view/t2_binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -922,21 +922,13 @@ class TemplateBinder extends RecursiveAstVisitor implements Visitor {
private maybeMap(ast: PropertyRead | SafePropertyRead | PropertyWrite, name: string): void {
// If the receiver of the expression isn't the `ImplicitReceiver`, this isn't the root of an
// `AST` expression that maps to a `Variable` or `Reference`.
if (!(ast.receiver instanceof ImplicitReceiver)) {
if (!(ast.receiver instanceof ImplicitReceiver) || ast.receiver instanceof ThisReceiver) {
return;
}

// Check whether the name exists in the current scope. If so, map it. Otherwise, the name is
// probably a property on the top-level component context.
const target = this.scope.lookup(name);

// It's not allowed to read template entities via `this`, however it previously worked by
// accident (see #55115). Since `@let` declarations are new, we can fix it from the beginning,
// whereas pre-existing template entities will be fixed in #55115.
if (target instanceof LetDeclaration && ast.receiver instanceof ThisReceiver) {
return;
}

if (target !== null) {
this.bindings.set(ast, target);
}
Expand Down
29 changes: 29 additions & 0 deletions packages/compiler/test/render3/view/binding_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,35 @@ describe('t2 binding', () => {
expect((target as a.LetDeclaration)?.name).toBe('value');
});

it('should not resolve a `this` access to a template reference', () => {
const template = parseTemplate(
`
<input #value>
{{this.value}}
`,
'',
);
const binder = new R3TargetBinder(new SelectorMatcher<DirectiveMeta[]>());
const res = binder.bind({template: template.nodes});
const interpolationWrapper = (template.nodes[1] as a.BoundText).value as e.ASTWithSource;
const propertyRead = (interpolationWrapper.ast as e.Interpolation).expressions[0];
const target = res.getExpressionTarget(propertyRead);

expect(target).toBe(null);
});

it('should not resolve a `this` access to a template variable', () => {
const template = parseTemplate(`<ng-template let-value>{{this.value}}</ng-template>`, '');
const binder = new R3TargetBinder(new SelectorMatcher<DirectiveMeta[]>());
const res = binder.bind({template: template.nodes});
const templateNode = template.nodes[0] as a.Template;
const interpolationWrapper = (templateNode.children[0] as a.BoundText).value as e.ASTWithSource;
const propertyRead = (interpolationWrapper.ast as e.Interpolation).expressions[0];
const target = res.getExpressionTarget(propertyRead);

expect(target).toBe(null);
});

it('should not resolve a `this` access to a `@let` declaration', () => {
const template = parseTemplate(
`
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/acceptance/embedded_views_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('embedded views', () => {
});

it('should resolve template input variables through the implicit receiver', () => {
@Component({template: `<ng-template let-a [ngIf]="true">{{this.a}}</ng-template>`})
@Component({template: `<ng-template let-a [ngIf]="true">{{a}}</ng-template>`})
class TestCmp {}

TestBed.configureTestingModule({declarations: [TestCmp]});
Expand Down

0 comments on commit f7ba14f

Please sign in to comment.