Commit c4091ee
authored
Ensure compiled range media queries are correctly parenthesised (#1114)
Fixes #1105
In the test case added, the range query `(width < 256px)` gets compiled
into `not (min-width: 256px)`. If we combine this with another query,
for example `(width < 256px) or (hover: none)`, the compiled query
should parenthesise the compiled range query. That is, the output should
be `(not (min-width: 256px)) or (hover: none)`. Instead, we see an
output of `not (min-width: 256px) or (hover: none)`, which incorrectly
negates the entire media query, not just the `min-width`.
`QueryFeature::needs_parens` determines if parentheses are need with the
following logic:
```rust
match self {
QueryFeature::Interval { .. } => parent_operator != Some(Operator::And),
QueryFeature::Range { operator, .. } => {
matches!(
operator,
MediaFeatureComparison::GreaterThan | MediaFeatureComparison::LessThan
)
}
_ => false,
}
}
```
This is correct ***if*** both interval and range queries are being
compiled, since parentheses are required when the range is replaced with
a negation.
However, above this return was the block:
```rust
if !should_compile!(targets, MediaIntervalSyntax) {
return false;
}
```
This causes the check to be skipped when `Feature::MediaIntervalSyntax`
isn't enabled.
This leaves an edge case: if `Feature::MediaRangeSyntax` is enabled,
without `Feature::MediaIntervalSyntax`, the correct parentheses check
isn't carried out.
One would think that this is an unreasonable edge case, since targeting
a browser without range syntax support would also be a browser without
interval syntax support. However, in `turbopack-css`, the
`MediaRangeSyntax` feature is always included, without adding
`MediaIntervalSyntax` (see
vercel/next.js@a95f861#diff-389b0ea768c0dbbca95b4aff5d1237ecddb33677521e3e2eb1f717c43c0d4658).
In Next 16, the default targets were updated (see
vercel/next.js#84401), which caused
`MediaIntervalSyntax` to no longer be included by default, hence opening
up this edge case.
I beleive that, unfortunately, the reason for Next adding
`MediaIntervalSyntax` still holds, and applies to intervals too. I'll
make a PR there to add `MediaIntervalSyntax` which will avoid this edge
case, but it'd be nice to fix it here, too :)
This moves the `MediaIntervalSyntax` check into the `Interval` case in
the switch, and adds a separate `MediaRangeSyntax` check in the `Range`
case.1 parent 28d7794 commit c4091ee
2 files changed
+40
-9
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
82 | 89 | | |
83 | 90 | | |
84 | 91 | | |
| |||
9064 | 9071 | | |
9065 | 9072 | | |
9066 | 9073 | | |
| 9074 | + | |
| 9075 | + | |
| 9076 | + | |
| 9077 | + | |
| 9078 | + | |
| 9079 | + | |
| 9080 | + | |
| 9081 | + | |
| 9082 | + | |
| 9083 | + | |
| 9084 | + | |
| 9085 | + | |
| 9086 | + | |
| 9087 | + | |
| 9088 | + | |
| 9089 | + | |
| 9090 | + | |
| 9091 | + | |
| 9092 | + | |
| 9093 | + | |
| 9094 | + | |
| 9095 | + | |
| 9096 | + | |
| 9097 | + | |
| 9098 | + | |
9067 | 9099 | | |
9068 | 9100 | | |
9069 | 9101 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1131 | 1131 | | |
1132 | 1132 | | |
1133 | 1133 | | |
1134 | | - | |
1135 | | - | |
1136 | | - | |
1137 | | - | |
1138 | 1134 | | |
1139 | | - | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
1140 | 1138 | | |
1141 | | - | |
1142 | | - | |
1143 | | - | |
1144 | | - | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
1145 | 1144 | | |
1146 | 1145 | | |
1147 | 1146 | | |
| |||
0 commit comments