Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(compiler): throw error for duplicate template references #40538

Closed
wants to merge 2 commits into from

Conversation

crisbeto
Copy link
Member

Adds an error if a reference is used more than once on the same element (e.g. <div #a #a>). We used to have this error in ViewEngine, but it wasn't ported over to Ivy.

Fixes #40536.

@google-cla google-cla bot added the cla: yes label Jan 23, 2021
@pullapprove pullapprove bot requested a review from alxhub January 23, 2021 09:18
@crisbeto crisbeto added action: review The PR is still awaiting reviews from at least one requested reviewer area: compiler Issues related to `ngc`, Angular's template compiler target: patch This PR is targeted for the next patch release type: bug/fix labels Jan 23, 2021
@ngbot ngbot bot modified the milestone: Backlog Jan 23, 2021
@Airblader
Copy link
Contributor

@crisbeto What about the other case mentioned in the ticket where the reference is not on the same element, but on two?

If I understand correctly this also fixes that one, but no test for it has been added.

@crisbeto
Copy link
Member Author

It looks like I missed the other case and this code only checked within the same element. I've updated the code to check across elements as well.

@@ -75,6 +75,7 @@ class HtmlAstToIvyAst implements html.Visitor {
styles: string[] = [];
styleUrls: string[] = [];
ngContentSelectors: string[] = [];
private allReferenceNames = new Set<string>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reference names are scoped to their containing template; whereas it looks like this tracks a global set. The VE template parser appears to be buggy here as well, in that it only checks for duplicated variable declarations in the root, not in nested templates. E.g. this correctly succeeds in VE:

<div *ngIf="true" #divRef></div>
<div #divRef></div>

but this should be rejected, but is incorrectly accepted:

<div *ngIf="true" #divRef #divRef></div>

Also note that the similar operation of reporting duplicate template variables (which is different to reference declarations, to be clear) is currently checked during type-checking:

// The template's variable declarations need to be added as `TcbVariableOp`s.
const varMap = new Map<string, TmplAstVariable>();
for (const v of templateOrNodes.variables) {
// Validate that variables on the `TmplAstTemplate` are only declared once.
if (!varMap.has(v.name)) {
varMap.set(v.name, v);
} else {
const firstDecl = varMap.get(v.name)!;
tcb.oobRecorder.duplicateTemplateVar(tcb.id, v, firstDecl);
}

That's just for reference, though; I think it's fine to report this error from within the template transform.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding was that we create one HtmlToIvyAst per parsed file so the registry shouldn't be global, or am I mistaken? For reference, here's where we create it: https://github.com/angular/angular/blob/master/packages/compiler/src/render3/r3_template_transform.ts#L58

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My usage of global was a bit poor; I meant to say "for a single component template". The single set is a problem for e.g:

<div *ngIf="true" #divRef></div>
<div #divRef></div>

as the first divRef occurs within an ng-template which creates a new scope, so the two declarations are actually not conflicting.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean now. I suppose that we can make it work, but the question is whether it's worth the trouble. In my opinion, even though the names won't conflict at runtime, it's cleaner if they're all unique anyway.

@crisbeto
Copy link
Member Author

Now that I'm looking at it again, it seems like Ivy explicitly supports multiple local references within the same template. See https://github.com/angular/angular/blob/master/packages/core/test/acceptance/query_spec.ts#L64. I'll roll back the changes so they only verify that the references are unique within a particular element.

Adds an error if a reference is used more than once on the same element (e.g. `<div #a #a>`).
We used to have this error in ViewEngine, but it wasn't ported over to Ivy.

Fixes angular#40536.
@crisbeto crisbeto added action: merge The PR is ready for merge by the caretaker action: presubmit The PR is in need of a google3 presubmit and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Feb 8, 2021
@AndrewKushnir
Copy link
Contributor

Presubmit.

@AndrewKushnir AndrewKushnir removed the action: presubmit The PR is in need of a google3 presubmit label Feb 9, 2021
alxhub pushed a commit that referenced this pull request Feb 10, 2021
Adds an error if a reference is used more than once on the same element (e.g. `<div #a #a>`).
We used to have this error in ViewEngine, but it wasn't ported over to Ivy.

Fixes #40536.

PR Close #40538
@alxhub alxhub closed this in 9478cda Feb 10, 2021
alxhub pushed a commit that referenced this pull request Feb 10, 2021
Adds an error if a reference is used more than once on the same element (e.g. `<div #a #a>`).
We used to have this error in ViewEngine, but it wasn't ported over to Ivy.

Fixes #40536.

PR Close #40538
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Mar 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: compiler Issues related to `ngc`, Angular's template compiler cla: yes target: patch This PR is targeted for the next patch release type: bug/fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Duplicate template reference variables are not treated as error with Ivy
5 participants