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

Bugfix/separate selectors #1253

Merged
merged 4 commits into from Oct 14, 2019
Merged

Conversation

fanich37
Copy link
Contributor

@fanich37 fanich37 commented Oct 8, 2019

Not sure about implementation at all but that's how I see it from my understanding of how the PostCSS and Autoprefixer works ☺️

@ai
Copy link
Member

ai commented Oct 8, 2019

Wow, great. This fix is great (and looks like correct) but should have a double check (and I am too drunk right now). I will try to check it this week.

lib/selector.js Outdated
class Selector extends Prefixer {
constructor (name, prefixes, all) {
super(name, prefixes, all)
this.regexpCache = {}
SELECTORS_CACHE[name] = {
Copy link
Member

Choose a reason for hiding this comment

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

How we will lean this cache? Will we have a problem if PostCSS will process many very different files (or even different versions of the same files) during the same Node.js session (so the cache will be alive?)

If you want a per-document cache, you can use node.root().autoprefixerSelectors cache. It will be attached only for the same CSS root.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, that's a really good question. I need to say I didn't even thought about such cases. I'll try to check them asap. Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't tested it yet. I just thought that SELECTORS_CACHE is filled with data during the file/files preprocessing. So probably it should work fine with multiple files. But I'm not 100% sure. By the way the naming SELECTORS_CACHE is kinda misleading. It's not a cache, it's just a collection.

Copy link
Member

Choose a reason for hiding this comment

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

Can we replace it to this.selectors since we use only instance methods and data there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, it wouldn't work in such implementation. The idea with this global const is to keep all possible selectors with all relevant prefixes. And with this.selectors we only get relevant selectors for this.name. But rule might contain several selectors.

I like your propose about using node.root().autoprefixerSelectors. I haven't checked it yet and actually I don't know how it works but may be It could help to get rid of SELECTORS_CACHE.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can try to do so. My concern is that replace method uses the instance method this.prefixed(prefix) inside. But hacks ::placeholder and :fullscreen are overriding it. The ::placeholder also overrides this.possible() method.

Copy link
Member

Choose a reason for hiding this comment

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

My concern is that replace method uses the instance method this.prefixed(prefix) inside.

If it really rely on instance, you can't detouch it from this instance.

Don't forget that PostCSS can be called on many different CSS files.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If it really rely on instance, you can't detouch it from this instance.

That's make sense.
I'll try to implement your idea.

Don't forget that PostCSS can be called on many different CSS files.

Can it process different files with different browser settings?

Copy link
Member

Choose a reason for hiding this comment

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

Can it process different files with different browser settings?

Yeap. The same instance can be used for different target browsers or different whitespace settings.

It will be safer just to think that every PostCSS call must be independent from each other.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know what was I thinking when I decided to use global const SELECTORS_CACHE. Each instance of class Selector gets property all on its init. And all is just the Prefixes instance that already contains all the data we need to process grouping rules 😄

@fanich37
Copy link
Contributor Author

fanich37 commented Oct 8, 2019

Wow, great. This fix is great (and looks like correct) but should have a double check (and I am too drunk right now). I will try to check it this week.

Thank for your fast reply! It would be awesome if you found some time to test it more precisely. But it's definitely not the fix to rush with 👍

lib/selector.js Outdated
@@ -1,3 +1,5 @@
let list = require('postcss').list
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
let list = require('postcss').list
let { list } = require('postcss')

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Replaced with your suggestion 👍

lib/selector.js Outdated
prefixeds[name] = {}

possible.forEach(prefix => {
if (selToProc.length > 1) {
Copy link
Member

Choose a reason for hiding this comment

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

I think we can remove this if. Array with a single element will have the same result after processing with map and join. It will be a little slower, but it is not a problem here since the main idea is to reduce code complexity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed it.

for (let prefix of this.possible()) {
prefixeds[prefix] = this.replace(rule.selector, prefix)

if (rule.selector.includes(',')) {
Copy link
Member

Choose a reason for hiding this comment

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

I completely lost the idea behind this method (but I wrote it 😭).

Can you describe (you can do it in Russian) what do we do here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll try to do it in english 🤞

This method collects all possible prefixes for the selector, creates prefixed version of the rule.selector, caches the result and adds it to the rule. So the rule looks like this at the end (copied from master branch):

Rule {
    type: 'rule',
    selector: '.a, .a .b::placeholder, a:read-only',
    // lots of properties
    _autoprefixerPrefixeds: {
        '-webkit-': '.a, .a .b::-webkit-input-placeholder, a:read-only',
        '-moz-': '.a, .a .b::-moz-placeholder, a:read-only',
        '-ms-': '.a, .a .b::-ms-input-placeholder, a:read-only',
        '-o-': '.a, .a .b::-o-placeholder, a:read-only',
        '-moz- old': '.a, .a .b:-moz-placeholder, a:read-only',
        '-ms- old': '.a, .a .b:-ms-input-placeholder, a:read-only' }
    }
}

As you can see :read-only is left without prefixes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I refactored code, and I think now it's much more easier to reason about. Plus, I decided that each selector has to process only that part of rule that contains the selector and not the whole rule as I did before.

@ai
Copy link
Member

ai commented Oct 13, 2019

Great! Now it became much simpler.

@ai ai merged commit f626441 into postcss:master Oct 14, 2019
@ai
Copy link
Member

ai commented Oct 14, 2019

Thanks. Released in 9.6.5. Great work in cleaning PR.

@fanich37
Copy link
Contributor Author

fanich37 commented Oct 14, 2019

Thanks. Released in 9.6.5. Great work in cleaning PR.

Thanks for your review and questions that helped me to find the proper solution 👍

@fanich37 fanich37 deleted the bugfix/separate_selectors branch October 17, 2019 20:52
@gaelreyrol
Copy link

gaelreyrol commented Nov 11, 2019

I have now an error with pseudo element placeholder since this patch. See cssnano/cssnano#828

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants