-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ensure
@utility
is processed before using them (#15542)
This PR fixes an issue where using an `@utility` before it is defined, and _if_ that `@utility` contains `@apply`, that it won't result in the expected output. But results in an `@apply` rule that is not substituted. Additionally, if you have multiple levels of `@apply`, we have to make sure that everything is applied (no pun intended) in the right order. Right now, the following steps are taken: 1. Collect all the `@utility` at-rules (and register them in the system as utilities). 2. Substitute `@apply` on the AST (including `@utility`'s ASTs) with the content of the utility. 3. Delete the `@utility` at-rules such that they are removed from the CSS output itself. The reason we do it in this order is because handling `@apply` during `@utility` handling means that we could rely on another `@utility` that is defined later and therefore the order of the utilities starts to matter. This is not a bad thing, but the moment you import multiple CSS files or plugins, this could become hard to manage. Another important step is that when using `@utility foo`, the implementation creates a `structuredClone` from its AST when first using the utility. The reason we do that is because `foo` and `foo!` generate different output and we don't want to accidentally mutate the same AST. This structured clone is the start of the problem in the linked issue (#15501). If we don't do the structured clone, then substituting the `@apply` rules would work, but then `foo` and `foo!` will generate the same output, which is bad. The linked issue has this structure: ```css .foo { @apply bar; } @Utility bar { @apply flex; } ``` If we follow the steps above, this would substitute `@apply bar` first, which results in: ```css .foo { @apply flex; } ``` But the `bar` utility, was already cloned (and cached) so now we end up with an `@apply` rule that is not substituted. To properly solve this problem, we have to make sure that we collect all the `@apply` at-rules, and apply them in the correct order. To do this, we run a topological sort on them which ensures that all the dependencies are applied before substituting the current `@apply`. This means that in the above example, in order to process `@apply bar`, we have to process the `bar` utility first. If we run into a circular dependency, then we will throw an error like before. You'll notice that the error message in this PR is updated to a different spot. This one is a bit easier to grasp because it shows the error where the circular dependency _starts_ not where it _ends_ (and completes the circle). The previous message was not wrong (since it's a circle), but now it's a bit easier to reason about. Fixes: #15501
- Loading branch information
1 parent
dcf116b
commit 02cfc45
Showing
5 changed files
with
237 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters