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

[Shadow CSS] Host context fix #21256

Closed
wants to merge 2 commits into from
Closed

Conversation

alx1417
Copy link

@alx1417 alx1417 commented Jan 2, 2018

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

[x] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] angular.io application / infrastructure changes
[ ] Other... Please describe:

What is the current behavior?

When you use more than one :host-context selector in the same css rule, the compiled css generate a invalid css code "-shadowcsscontext".

Example:

// Preprocessed code
:host-context(.one):host-context(.two) {}
/* Generated code*/
.one-shadowcsscontext(.two)[nghost],
.one   -shadowcsscontext(.two)[nghost] {}

Issue Number: #19199

What is the new behavior?

You can use two or more :host-context selector in the same css rule and generate all css combinations.

Example:

// Preprocessed code
:host-context(.one) :host-context(.two) {}
/* Generated code*/
.one[nghost] .two[ngcontent],
.one .two [a-host], 
.two[nghost] .one[ngcontent], 
.two .one [nghost], 
.one.two[nghost],
.one.two [nghost] {}

Does this PR introduce a breaking change?

[ ] Yes
[x] No

Other information

Fix an error when use two or more :host-context selector.
Now all host-context generate all posible combinations in the css result.

Close issue angular#19199
@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed, please reply here (e.g. I signed it!) and we'll verify. Thanks.


  • If you've already signed a CLA, it's possible we don't have your GitHub username or you're using a different email address on your commit. Check your existing CLA data and verify that your email is set on your git commits.
  • If your company signed a CLA, they designated a Point of Contact who decides which employees are authorized to participate. You may need to contact the Point of Contact for your company and ask to be added to the group of authorized contributors. If you don't know who your Point of Contact is, direct the project maintainer to go/cla#troubleshoot. The email used to register you as an authorized contributor must be the email used for the Git commit.
  • In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again. If the bot doesn't comment, it means it doesn't think anything has changed.

@alx1417
Copy link
Author

alx1417 commented Jan 2, 2018

I signed it!

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again. If the bot doesn't comment, it means it doesn't think anything has changed.

@alx1417
Copy link
Author

alx1417 commented Jan 2, 2018

I signed it!

1 similar comment
@alx1417
Copy link
Author

alx1417 commented Jan 2, 2018

I signed it!

@googlebot
Copy link

CLAs look good, thanks!

@googlebot googlebot added cla: yes and removed cla: no labels Jan 2, 2018
Fix an error when use two or more :host-context selector.
Now all host-context generate all posible combinations in the css result.

Close issue angular#19199
@mhevery mhevery requested a review from vicb January 4, 2018 00:49
@mhevery mhevery added the area: core Issues related to the framework runtime label Jan 4, 2018
@vicb
Copy link
Contributor

vicb commented Jan 11, 2018

What does :host-context(.one):host-context(.two) mean ?
is it equivalent to :host-context(.one .two) ?

@alx1417
Copy link
Author

alx1417 commented Jan 12, 2018

Hi vicb,

The code that you propouse is similar but not equivalent.

When use :host-context(.one .two) only have one combination of class (.one>.two).

When use :host-context(.one):host-context(.two) you have the two possible orders(.one>.two or .two >.one).

Also, in some cases is not possible use :host-context(.one .two) :

  • You not know the order of the clases. .one .two {} OR .two .one {}
  • The structure of the scss does not allow it, for example using the host context in multiples @Mixins
// mixins.scss
@mixin device-type-mobile {
  :host-context(.mobile) & {  @content;  }
}
@mixin device-os-ios {
  :host-context(.ios) & { @content;  }
}
// usage.scss
.wrapper {
  background: green;
  @include device-type-mobile {
    background: red;
    @include device-os-ios {
      background: blue;
    }
  }
}
// generated.css (Forced break lines and commented)

 // No mixin applied.
.wrapper[_ngcontent-c5] {
  background: green;
}

// One mixin applied
.mobile[_nghost-c5]   .wrapper[_ngcontent-c5], 
.mobile   [_nghost-c5]   .wrapper[_ngcontent-c5] {
  background: red;
}

// Two mixin applied
// Order .ios > .mobile
.ios[_nghost-c5]   .mobile[_ngcontent-c5]   .wrapper[_ngcontent-c5],
.ios   .mobile   [_nghost-c5]   .wrapper[_ngcontent-c5],
// Order .mobile > .ios
.mobile[_nghost-c5]   .ios[_ngcontent-c5]   .wrapper[_ngcontent-c5], 
.mobile   .ios   [_nghost-c5]   .wrapper[_ngcontent-c5],
// Same level .mobile = .ios
.ios.mobile[_nghost-c5]   .wrapper[_ngcontent-c5],
.ios.mobile   [_nghost-c5]   .wrapper[_ngcontent-c5] {
  background: blue;
}

Thank you for review the code.

@vicb
Copy link
Contributor

vicb commented Jan 16, 2018

When use :host-context(.one):host-context(.two) you have the two possible orders(.one>.two or .two >.one).

Do you have a link to a spec that would explain this behavior ?

@vicb vicb changed the title Host context fix [Shadow CSS] Host context fix Jan 16, 2018
@alx1417
Copy link
Author

alx1417 commented Jan 18, 2018

Do you have a link to a spec that would explain this behavior ?

In this link the explain of the :host-context say:

The :host-context() selector looks for a CSS class in any ancestor of the component host element, up to the document root.

Not specify the behaviour when use two host-context, but if we apply the previous description to two host context, we have two selectors that "looks for a CSS class in any ancestor".

:host-context(.one) {} // .one [host] {}
:host-context(.two) {} // .two [host] {}
:host-context(.one .two) {} // .one .two [host] {}
:host-context(.two .one ) {} // .two .one [host] {}

:host-context(.one):host-context(.two) {} // .one .two [host], .two .one [host] {}
// .one should be ancestor and .two also
// NOTE: Now, before the fix, this return an invalid css (.one -shadowcsscontext(.two)  [host])

:host-context(.one) {
  color: red;
  :host-context(.two) {
    color: blue;
  }
}
/* Is not necessary that stay at the same level, for example
.one [host] {color: red},
.one .two [host], .two .one[host] {color: blue}
*/

I generate the two orders because the two host-context should by ancestors.

@vicb vicb self-assigned this Jan 29, 2018
@vicb vicb removed their request for review August 15, 2018 21:10
@vicb vicb removed their assignment Aug 15, 2018
@jasonaden jasonaden added this to the needsTriage milestone Jan 29, 2019
@mhevery mhevery added this to Needs review in mhevery-review-queue via automation Dec 4, 2020
@mhevery mhevery moved this from Needs review to Discuss in mhevery-review-queue Dec 4, 2020
@mhevery mhevery moved this from Discuss to CleanUp in mhevery-review-queue Dec 4, 2020
@petebacondarwin petebacondarwin added action: review The PR is still awaiting reviews from at least one requested reviewer target: patch This PR is targeted for the next patch release labels Jan 19, 2021
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Jan 19, 2021
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Jan 19, 2021
Copy link
Member

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

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

First of all, thank you @alx1417 for this PR. I am sorry it has taken so long to review it.

I don't believe the test nor the implementation are correct here.

Can you consider my suggested test? If you agree the test is correct, then the implementation needs to change since it fails this test.

Further, if you are going to update the implementation, then I think the changes should be in the _colonHostContextPartReplacer() method, rather than the _convertColonRule() which is shared with handling :host() selectors. And we should also look at the array manipulation being used as I think this could be a bit more performant.

Comment on lines +200 to +203
expect(s(':host-context(.one) :host-context(.two) {}', 'contenta', 'a-host'))
.toEqual(
'.one[a-host] .two[contenta], .one .two [a-host], .two[a-host] .one[contenta], .two .one [a-host], .one.two[a-host], .one.two [a-host] {}');
});
Copy link
Member

Choose a reason for hiding this comment

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

Just rebasing and tidying up this PR. I think this test is not actually correct.

First, I don't think that there should be a space between the :host-context() selectors in the string passed to s(). Having :host-context(...) :host-context(...) doesn't make sense to me. I am not even sure how we should interpret this.

Second, I think that contenta should not appear in the final selection at all.

This is what I would expect:

Suggested change
expect(s(':host-context(.one) :host-context(.two) {}', 'contenta', 'a-host'))
.toEqual(
'.one[a-host] .two[contenta], .one .two [a-host], .two[a-host] .one[contenta], .two .one [a-host], .one.two[a-host], .one.two [a-host] {}');
});
expect(s(':host-context(.one):host-context(.two) {}', 'contenta', 'a-host')
.replace(/ \{\}$/, '')
.split(/\,\s+/)
.sort())
.toEqual([
'.one .two[a-host]', // `one` is an ancestor and `two` is on the host
'.one .two [a-host]', // `one` and `two` are both ancestors (in that order)
'.one.two [a-host]', // `one` and `two` are both on the same ancestor
'.one.two[a-host]', // `one` and `two` both on the host
'.two .one [a-host]', // `two` and `one` are both ancestors (in that order)
'.two .one[a-host]', // `two` is an ancestor and `one` is on the host
]);

@petebacondarwin
Copy link
Member

Closing in favour of #40494.

mhevery-review-queue automation moved this from CleanUp to Done Jan 20, 2021
@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 Feb 20, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: review The PR is still awaiting reviews from at least one requested reviewer area: core Issues related to the framework runtime cla: yes target: patch This PR is targeted for the next patch release
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

6 participants