Repository navigation
fix(compiler): drop a namespace-qualified attribute selector - #449
Open
YevheniiKotyrlo wants to merge 4 commits into
Open
YevheniiKotyrlo wants to merge 4 commits into
YevheniiKotyrlo wants to merge 4 commits into
Conversation
This was referenced Sep 10, 2026
Contributor
Author
react-native-web writes a dataSet entry as a data-* attribute for every value but null and undefined, so [data-x] matches data-x="false" in a browser. The runtime treated false as absent there, as it rightly does for a boolean prop, and compared an array value as no value, where the DOM holds its comma-joined text. HTML compares a dir value ASCII case-insensitively, so [dir="RTL"] matches dir="rtl" unless the selector carries the s flag. The compiler emitted the operand as written, and the direction condition never matched it. It now folds the operand unless s is given. Both folds share one ASCII lowercasing helper, which the runtime's i flag also uses.
The compound path and the :is() / :where() path each built the same query from an attribute selector, one with its own copy of the operator map. Both now call one builder.
React Native carries the class list as className, so an attribute query reading props.class answered false for every element, and [class~="x"], [class*="x"] and [class] never matched. The attribute builder maps class to className.
[ns|att] represents only an attribute in the namespace ns (Selectors 4 §6.4), and a React Native prop is in no namespace, so the selector can match nothing. The compiler ignored the namespace and read the prop, so [ns|data-x="a"] matched where every browser matches nothing. An undeclared prefix is an invalid selector, with the same outcome. The attribute builder now answers no query for a namespace-qualified attribute, and both of its callers drop the selector; [|att] and [*|att] are unchanged.
YevheniiKotyrlo
force-pushed
the
fix/attribute-selector-namespaces
branch
from
October 11, 2026 12:35
5cc5324 to
590d395
Compare
This branch has not been deployed
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On
main, the compiler ignores an attribute selector's namespace.[ns|att]represents only an attribute in the namespacens(Selectors 4 §6.4), and no React Native prop is in a namespace, so the selector can match nothing. Instead the compiler reads the prop, and[ns|data-x="a"]matchesdataSet={{ x: "a" }}where every browser matches nothing.An undeclared prefix (
[undeclared|data-x="a"]) makes the selector invalid, with the same outcome in a browser. lightningcss passes it through.Solution
The attribute builder answers no query for a namespace-qualified attribute. Each of its two callers then drops the selector: the compound path and the
:is()/:where()path.[att],[|att]and[*|att]are unchanged, since with no namespaced props they denote the same set.Tests
Every case renders as Chromium 153, Firefox 155 and WebKit 26.6 do.
src/__tests__/compiler/selectors.test.tsxcovers:[att],[|att],[*|att]and an undeclared prefix emit;:is()path.src/__tests__/native/attributes.test.tsxrenders[|att],[*|att]and an undeclared prefix over a matchingdataSetvalue.Verification
On Windows with Node 26:
yarn lintcleanyarn typecheckcleanyarn test --coverage: every failure also fails onmainon this machine (the four babel cases)yarn buildcleanyarn example expo export --platform webexportedMerge order
This builds on #448's single attribute builder, which builds on #447, so #447 and #448 land first and this carries their commits until they do.
Base
Re-written on #448 (
291ce56d), which sits on #447 andmain(a5002c5).