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

Heavily improve wrapped pseudo selector handling #2498

Merged
merged 1 commit into from
Nov 12, 2017

Conversation

mgreter
Copy link
Contributor

@mgreter mgreter commented Nov 12, 2017

Quite a hacky PR, but the logic once more escapes my imagination.
Lets see what CI thinks ... fixes #2464 and fixes #2383

Correctly compiles the following:

:host(:not(.baz1)) {
  left: 0;
}

:not(:not(.baz2)) {
  left: 0;
}

a {
  :not(:not(.baz3)) {
    left: 0;
  }
}

q {

    .thing {
      color: black;
    }
  
    .a,
    .b,
    .c,
    .d,
    .e {
      &:not(.thing) { @extend .thing; }
    }

  }
  
:host(.abc1) { x: y; }
.a {@extend .abc1}

:not(.abc2) { x: y; }
.a {@extend .abc2}

:not(.thing) {
  color: red;
}
:not(.bar) {
  @extend .thing;
  background: blue;
}

:not(.foo1):not(:not(.ext1)) {
  color: red; }

a {
  :not(.foo2):not(:not(.ext2)) {
  color: red; }
}

to

:host(:not(.baz1)) {
  left: 0; }

:not(:not(.baz2)) {
  left: 0; }

a  {
  left: 0; }

q .thing, q .a:not(.thing),
q .b:not(.thing),
q .c:not(.thing),
q .d:not(.thing),
q .e:not(.thing), q :not(.bar) {
  color: black; }

:host(.abc1, .a) {
  x: y; }

:not(.abc2):not(.a) {
  x: y; }

:not(.thing) {
  color: red; }

:not(.bar) {
  background: blue; }

:not(.foo1):not(:not(.ext1)) {
  color: red; }

a :not(.foo2) {
  color: red; }

@mgreter
Copy link
Contributor Author

mgreter commented Nov 12, 2017

Found another interesting issue with ruby sass 3.4.23:

:not(.thing) {
  color: red;
}

:not(.bar) {
  @extend .thing;
}

foobar {
  :host(:not(.other)) {
    left: 0;
  }
}

results in

NoMethodError: undefined method `do_extend' for :not(.other):Sass::Selector::Pseudo
Did you mean?  extend
  Use --trace for backtrace.

@mgreter mgreter force-pushed the feature/wrapped-selectors branch from 55b38c4 to 7fd39b6 Compare November 12, 2017 01:44
@xzyfer
Copy link
Contributor

xzyfer commented Nov 12, 2017 via email

@mgreter
Copy link
Contributor Author

mgreter commented Nov 12, 2017

Dart sass is now the reference implementation. It's somewhat diverged from ruby sass. We should compare against that instead from now on.

Is there an official announcement that it is already the new reference implementation? //CC @nex3

@xzyfer
Copy link
Contributor

xzyfer commented Nov 12, 2017 via email

@mgreter
Copy link
Contributor Author

mgreter commented Nov 12, 2017

Fair enough ... the mentioned example doesn't give any result on any ruby sass version at least on sassmeister ... no time to test locally with all ruby versions ...

@mgreter
Copy link
Contributor Author

mgreter commented Nov 12, 2017

@xzyfer btw 3.4.6 is still missing release notes :-/

@xzyfer
Copy link
Contributor

xzyfer commented Nov 12, 2017 via email

@xzyfer
Copy link
Contributor

xzyfer commented Nov 12, 2017 via email

@mgreter
Copy link
Contributor Author

mgreter commented Nov 12, 2017

FYI I already verified with dart-sass and libsass output now matches, I only wanted to mention the strange behavior of ruby sass, nothing more ... looking forward to the pending release notes ...

@xzyfer
Copy link
Contributor

xzyfer commented Nov 12, 2017 via email

@mgreter mgreter force-pushed the feature/wrapped-selectors branch 2 times, most recently from 3bca071 to abd8c49 Compare November 12, 2017 04:50
@mgreter
Copy link
Contributor Author

mgreter commented Nov 12, 2017

@nex3 here is one for a starter (ruby sass 3.4):

:not(.foo2):not(:not(.ext2)) {
  color: red;
}

foo {
  :not(.foo2):not(:not(.ext2)) {
    color: red;
  }
}
# sass test.scss
:not(.foo2):not(:not(.ext2)) {
  color: red; }
foo :not(.foo2) {
  color: red; }

# sassc test.scss
:not(.foo2):not(:not(.ext2)) {
  color: red; }
foo :not(.foo2) {
  color: red; }

# dart-sass.bat test.scss
:not(.foo2):not(:not(.ext2)) {
  color: red;
}
foo :not(.foo2):not(:not(.ext2)) {
  color: red;
}

Another one:

:not(:not(.baz1)) {
  left: 0;
}
:not(.foo) {
  @extend .baz1;
}
# sass test.scss
:not(:not(.baz1)) {
  left: 0; }

# sassc test.scss
:not(:not(.baz1)) {
  left: 0; }

# dart-sass.bat test.scss
Unexpected exception:
Invalid argument(s): components may not be empty.

@mgreter mgreter force-pushed the feature/wrapped-selectors branch 2 times, most recently from 4455475 to 526e97e Compare November 12, 2017 05:27
@mgreter
Copy link
Contributor Author

mgreter commented Nov 12, 2017

This PR is as good as it gets. IMO extending pseudo selectors is pretty brittle as it is. This PR implements current 3.4 behavior as closely as I can get it to work without regressing anything that we had in earlier versions. It should support the most common use cases, but I think extending wrapped selectors should be discouraged, since it is hard to predict what behavior you want/get. It is nearly impossible to debug the code-path in libsass due to the multiple conversion between Node and Selector instances ...

@mgreter mgreter self-assigned this Nov 12, 2017
@xzyfer
Copy link
Contributor

xzyfer commented Nov 12, 2017

👍

Maybe not directly related but I thought it was worth mentioning changes to extend recently in sass sass/sass#2319.

@mgreter mgreter force-pushed the feature/wrapped-selectors branch from 4978a63 to dd871bf Compare November 12, 2017 06:09
@mgreter mgreter force-pushed the feature/wrapped-selectors branch from 88a2c87 to 8aefe1e Compare November 12, 2017 15:54
@mgreter mgreter merged commit 2eff1da into sass:master Nov 12, 2017
@nex3
Copy link
Contributor

nex3 commented Nov 16, 2017

Is there an official announcement that it is already the new reference implementation?

No, since the notion of a "reference implementation" isn't super relevant to most users. I will say that Dart Sass is generally more in line with our goals for the eventual behavior of Sass, though, since it makes some backwards-incompatible changes relative to Ruby Sass (see the README for details).

:not(.foo2):not(:not(.ext2)) {
  color: red;
}

foo {
  :not(.foo2):not(:not(.ext2)) {
    color: red;
  }
}
# sass test.scss
:not(.foo2):not(:not(.ext2)) {
  color: red; }
foo :not(.foo2) {
  color: red; }

# sassc test.scss
:not(.foo2):not(:not(.ext2)) {
  color: red; }
foo :not(.foo2) {
  color: red; }

# dart-sass.bat test.scss
:not(.foo2):not(:not(.ext2)) {
  color: red;
}
foo :not(.foo2):not(:not(.ext2)) {
  color: red;
}

Dart Sass is correct here. We shouldn't be simplifying user-authored styles, especially outside of the presence of @extend.

Another one:

:not(:not(.baz1)) {
  left: 0;
}
:not(.foo) {
  @extend .baz1;
}
# sass test.scss
:not(:not(.baz1)) {
  left: 0; }

# sassc test.scss
:not(:not(.baz1)) {
  left: 0; }

# dart-sass.bat test.scss
Unexpected exception:
Invalid argument(s): components may not be empty.

I've filed sass/dart-sass#191 to track this.

It's worth noting in general that our approach here should probably change soon, since :not() now allows full selector lists and Safari already implements that.

mgreter added a commit to mgreter/sass-spec that referenced this pull request Feb 5, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Host selector regression in 3.4.5 (since 3.4.0): :host(:not(.foo)) Support ::slotted pseudo selector
3 participants