-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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(core): more accurate matching of classes during content projection #48888
Conversation
@masaoki thanks for creating this PR. This fix would also require a test in the |
@AndrewKushnir Ok. I'm going to find a way to reproduce the exception without angular material, and try to reflect the result to the test. |
@AndrewKushnir Pushed content_spec.ts with a test added. The exception could be reproduced when the component has |
Getting the same issue. What's going on with this? |
For those looking for a fix you can rewrite the class interpolation: class="icon {{ parentMenu.iconClass }}" to [ngClass]="[ parentMenu.iconClass ? parentMenu.iconClass : '' ]" this worked for me |
@AndrewKushnir |
@masaoki thanks for the PR and sorry for the delay. While the fix avoids the JS exception, I'm not 100% sure it resolves the root cause. The
the
So the elements after a marker would be just binding names, but the logic will treat them as key-value pair and likely match (if you have Could you pleaser try to add a test case based on this example? Also it'd be interesting to see what the You can also find additional information about the Thank you. |
55090ae
to
72c8a34
Compare
@AndrewKushnir
In this case, the attrs inside isCssClassMatching() is
which makes
the attr is
The exception is gone in this case because of the additional "title" binding, but the isCssClassMatching() confusingly returns true since 'title' is after 'class' as you expected. The sort order is:
So what we actually have to do here is to find the cssClassToMatch value followed by 'class' before any number value, or the same value between AttributeMarker.Classes and another AttributeMarker.* where the 'class' found is not what we look for. I rewrote the isCssClassMatching() method to effectively work as expected. Also added both of test cases to |
Yes, that's correct 👍 Ideally, it'd be great to do it in a single pass over the attrs array, so we can probably do something like this? (note: I haven't tested it, just wanted to illustrate the idea)
|
770461f
to
cd83de5
Compare
@AndrewKushnir
I pushed changes a little modification based on your code again with a test covering the above case. |
Yes, it makes sense. When we are in the "implicit attrs" section, we should handle elements in pair ([key, value, ...]) as implemented in your change 👍 |
@AndrewKushnir Did it. Thanks for your assistance! |
@masaoki thanks for addressing the feedback! It looks like CI is failing for a couple reasons:
Please try to apply the changes and let us know if CI is still "red". Could you please also merge all commits into one and may be rephrase the commit message a bit to reflect the changes (something like Thank you. |
78f371a
to
4fc44cd
Compare
Showing a minimum app to reproduce the bug. 1. Create the app and add angular material. ``` ng new project cd project ng add @angular/material ``` 1. Overwrite the src/app/app.component.html with minimal content. ``` <button mat-button *ngIf="true"><span *ngIf="true" class="{{'a'}}"></span></button> ``` 1. Run the app. The button is not shown because of an exception. ``` main.ts:6 ERROR TypeError: item.toLowerCase is not a function at isCssClassMatching (core.mjs:8726:35) at isNodeMatchingSelector (core.mjs:8814:22) at isNodeMatchingSelectorList (core.mjs:8931:13) at matchingProjectionSlotIndex (core.mjs:14179:13) at Module.ɵɵprojectionDef (core.mjs:14222:49) at MatButton_Template (button.mjs:113:99) at executeTemplate (core.mjs:10534:9) at renderView (core.mjs:10356:13) at renderComponent (core.mjs:11529:5) at renderChildComponents (core.mjs:10216:9) ``` Because isCssClassMatching() function does not take care if the value is not string, while attrs[] may contain AttributeMarker which is actually numbers, item.toLowerCase() throws the exception. Just inserted a check if the item is string. Created a testcase for the original fix. It causes an exception without the fix. fix(core): add a check code to avoid an exception inside isCssClassMatching Showing a minimum app to reproduce the bug. 1. Create the app and add angular material. ``` ng new project cd project ng add @angular/material ``` 1. Add `import { MatButtonModule } from '@angular/material/button'`, and also MatButtonModule inside @NgModule imports in src/app/app.module.ts to use MatButtonModule. 1. Overwrite the src/app/app.component.html with minimal content. ``` <button mat-button *ngIf="true"><span *ngIf="true" class="{{'a'}}"></span></button> ``` 1. Run the app. The button is not shown because of an exception. ``` main.ts:6 ERROR TypeError: item.toLowerCase is not a function at isCssClassMatching (core.mjs:8726:35) at isNodeMatchingSelector (core.mjs:8814:22) at isNodeMatchingSelectorList (core.mjs:8931:13) at matchingProjectionSlotIndex (core.mjs:14179:13) at Module.ɵɵprojectionDef (core.mjs:14222:49) at MatButton_Template (button.mjs:113:99) at executeTemplate (core.mjs:10534:9) at renderView (core.mjs:10356:13) at renderComponent (core.mjs:11529:5) at renderChildComponents (core.mjs:10216:9) ``` Because isCssClassMatching() function does not take care if the value is not string, while attrs[] may contain AttributeMarker which is actually numbers, item.toLowerCase() throws the exception. Just inserted a check if the item is string.
4fc44cd
to
ec3e92a
Compare
@AndrewKushnir |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@masaoki the change looks good, thanks for addressing the feedback 👍
We'll run some additional internal tests in Google's codebase and if everything is ok, we'll add the PR to the merge queue.
Thank you.
Global Presubmit (internal-only link). |
Caretaker note: TGP is "green", this PR is ready for merge. |
This PR was merged into the repository by commit e655e8a. |
#48888) Showing a minimum app to reproduce the bug. 1. Create the app and add angular material. ``` ng new project cd project ng add @angular/material ``` 1. Overwrite the src/app/app.component.html with minimal content. ``` <button mat-button *ngIf="true"><span *ngIf="true" class="{{'a'}}"></span></button> ``` 1. Run the app. The button is not shown because of an exception. ``` main.ts:6 ERROR TypeError: item.toLowerCase is not a function at isCssClassMatching (core.mjs:8726:35) at isNodeMatchingSelector (core.mjs:8814:22) at isNodeMatchingSelectorList (core.mjs:8931:13) at matchingProjectionSlotIndex (core.mjs:14179:13) at Module.ɵɵprojectionDef (core.mjs:14222:49) at MatButton_Template (button.mjs:113:99) at executeTemplate (core.mjs:10534:9) at renderView (core.mjs:10356:13) at renderComponent (core.mjs:11529:5) at renderChildComponents (core.mjs:10216:9) ``` Because isCssClassMatching() function does not take care if the value is not string, while attrs[] may contain AttributeMarker which is actually numbers, item.toLowerCase() throws the exception. Just inserted a check if the item is string. Created a testcase for the original fix. It causes an exception without the fix. fix(core): add a check code to avoid an exception inside isCssClassMatching Showing a minimum app to reproduce the bug. 1. Create the app and add angular material. ``` ng new project cd project ng add @angular/material ``` 1. Add `import { MatButtonModule } from '@angular/material/button'`, and also MatButtonModule inside @NgModule imports in src/app/app.module.ts to use MatButtonModule. 1. Overwrite the src/app/app.component.html with minimal content. ``` <button mat-button *ngIf="true"><span *ngIf="true" class="{{'a'}}"></span></button> ``` 1. Run the app. The button is not shown because of an exception. ``` main.ts:6 ERROR TypeError: item.toLowerCase is not a function at isCssClassMatching (core.mjs:8726:35) at isNodeMatchingSelector (core.mjs:8814:22) at isNodeMatchingSelectorList (core.mjs:8931:13) at matchingProjectionSlotIndex (core.mjs:14179:13) at Module.ɵɵprojectionDef (core.mjs:14222:49) at MatButton_Template (button.mjs:113:99) at executeTemplate (core.mjs:10534:9) at renderView (core.mjs:10356:13) at renderComponent (core.mjs:11529:5) at renderChildComponents (core.mjs:10216:9) ``` Because isCssClassMatching() function does not take care if the value is not string, while attrs[] may contain AttributeMarker which is actually numbers, item.toLowerCase() throws the exception. Just inserted a check if the item is string. PR Close #48888
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [@angular/animations](https://github.com/angular/angular) | dependencies | patch | [`15.2.0` -> `15.2.4`](https://renovatebot.com/diffs/npm/@angular%2fanimations/15.2.0/15.2.4) | | [@angular/common](https://github.com/angular/angular) | dependencies | patch | [`15.2.0` -> `15.2.4`](https://renovatebot.com/diffs/npm/@angular%2fcommon/15.2.0/15.2.4) | | [@angular/compiler](https://github.com/angular/angular) | dependencies | patch | [`15.2.0` -> `15.2.4`](https://renovatebot.com/diffs/npm/@angular%2fcompiler/15.2.0/15.2.4) | | [@angular/compiler-cli](https://github.com/angular/angular/tree/main/packages/compiler-cli) ([source](https://github.com/angular/angular)) | devDependencies | patch | [`15.2.0` -> `15.2.4`](https://renovatebot.com/diffs/npm/@angular%2fcompiler-cli/15.2.0/15.2.4) | | [@angular/core](https://github.com/angular/angular) | dependencies | patch | [`15.2.0` -> `15.2.4`](https://renovatebot.com/diffs/npm/@angular%2fcore/15.2.0/15.2.4) | | [@angular/forms](https://github.com/angular/angular) | dependencies | patch | [`15.2.0` -> `15.2.4`](https://renovatebot.com/diffs/npm/@angular%2fforms/15.2.0/15.2.4) | | [@angular/platform-browser](https://github.com/angular/angular) | dependencies | patch | [`15.2.0` -> `15.2.4`](https://renovatebot.com/diffs/npm/@angular%2fplatform-browser/15.2.0/15.2.4) | | [@angular/platform-browser-dynamic](https://github.com/angular/angular) | dependencies | patch | [`15.2.0` -> `15.2.4`](https://renovatebot.com/diffs/npm/@angular%2fplatform-browser-dynamic/15.2.0/15.2.4) | | [zone.js](https://github.com/angular/angular) ([changelog](https://github.com/angular/angular/blob/master/packages/zone.js/CHANGELOG.md)) | dependencies | minor | [`0.12.0` -> `0.13.0`](https://renovatebot.com/diffs/npm/zone.js/0.12.0/0.13.0) | --- ### Release Notes <details> <summary>angular/angular (@​angular/animations)</summary> ### [`v15.2.4`](https://github.com/angular/angular/blob/HEAD/CHANGELOG.md#​1524-2023-03-22) [Compare Source](angular/angular@15.2.3...15.2.4) ##### core | Commit | Type | Description | | -- | -- | -- | | [bae6b5ceb1](angular/angular@bae6b5c) | fix | Allow `TestBed.configureTestingModule` to work with recursive cycle of standalone components. ([#​49473](angular/angular#49473)) | | [087f4412af](angular/angular@087f441) | fix | more accurate matching of classes during content projection ([#​48888](angular/angular#48888)) | #### Special Thanks Aditya Srinivasan, Alex Rickabaugh, Andrew Scott, Kristiyan Kostadinov, Masaoki Kobayashi, Matthieu Riegler, Paul Gschwendtner, Peter Götz, Thomas Pischke, Virginia Dooley and avmaxim <!-- CHANGELOG SPLIT MARKER --> ### [`v15.2.3`](https://github.com/angular/angular/blob/HEAD/CHANGELOG.md#​1523-2023-03-16) [Compare Source](angular/angular@15.2.2...15.2.3) #### Special Thanks Alan Agius, Esteban Gehring, Matthieu Riegler and Virginia Dooley <!-- CHANGELOG SPLIT MARKER --> ### [`v15.2.2`](https://github.com/angular/angular/blob/HEAD/CHANGELOG.md#​1522-2023-03-08) [Compare Source](angular/angular@15.2.1...15.2.2) ##### migrations | Commit | Type | Description | | -- | -- | -- | | [6207d6f1f0](angular/angular@6207d6f) | fix | add protractor support if protractor imports are detected ([#​49274](angular/angular#49274)) | #### Special Thanks Alan Agius, Andrew Kushnir, Andrew Scott, Kristiyan Kostadinov, Matthieu Riegler, Paul Gschwendtner, Sai Kartheek Bommisetty and Vinit Neogi <!-- CHANGELOG SPLIT MARKER --> ### [`v15.2.1`](https://github.com/angular/angular/blob/HEAD/CHANGELOG.md#​1521-2023-03-01) [Compare Source](angular/angular@15.2.0...15.2.1) ##### common | Commit | Type | Description | | -- | -- | -- | | [f0e926074d](angular/angular@f0e9260) | fix | make Location.normalize() return the correct path when the base path contains characters that interfere with regex syntax. ([#​49181](angular/angular#49181)) | ##### compiler-cli | Commit | Type | Description | | -- | -- | -- | | [04d8b6c61a](angular/angular@04d8b6c) | fix | do not persist component analysis if template/styles are missing ([#​49184](angular/angular#49184)) | ##### core | Commit | Type | Description | | -- | -- | -- | | [d60ea6ab5a](angular/angular@d60ea6a) | fix | update zone.js peerDependencies ranges ([#​49244](angular/angular#49244)) | ##### migrations | Commit | Type | Description | | -- | -- | -- | | [44d095a61c](angular/angular@44d095a) | fix | avoid migrating the same class multiple times in standalone migration ([#​49245](angular/angular#49245)) | | [92b0bda9e4](angular/angular@92b0bda) | fix | delete barrel exports in standalone migration ([#​49176](angular/angular#49176)) | ##### router | Commit | Type | Description | | -- | -- | -- | | [3062442728](angular/angular@3062442) | fix | add error message when using loadComponent with a NgModule ([#​49164](angular/angular#49164)) | #### Special Thanks Alan Agius, Andrew Kushnir, Aristeidis Bampakos, Craig Spence, Doug Parker, Iván Navarro, Joey Perrott, Kristiyan Kostadinov, Matthieu Riegler, Michael Ziluck, Paul Gschwendtner, Stephanie Tuerk, Vincent and Virginia Dooley <!-- CHANGELOG SPLIT MARKER --> </details> <details> <summary>angular/angular (zone.js)</summary> ### [`v0.13.0`](angular/angular@zone.js-0.12.0...zone.js-0.13.0) [Compare Source](angular/angular@zone.js-0.12.0...zone.js-0.13.0) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC4xNTQuMSIsInVwZGF0ZWRJblZlciI6IjM1LjI0LjUifQ==--> Co-authored-by: cabr2-bot <cabr2.help@gmail.com> Reviewed-on: https://codeberg.org/Calciumdibromid/CaBr2/pulls/1801 Reviewed-by: Epsilon_02 <epsilon_02@noreply.codeberg.org> Co-authored-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org> Co-committed-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
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. |
Small bug fix. Showing a minimum app to reproduce the bug.
Because isCssClassMatching() function does not take care if the value is not string, while attrs[] may contain AttributeMarker which is actually numbers, item.toLowerCase() throws the exception. Just inserted a check if the item is string.
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information