Repository navigation
fix(compiler): recover from a rule lightningcss cannot parse - #493
Open
YevheniiKotyrlo wants to merge 6 commits into
Open
YevheniiKotyrlo wants to merge 6 commits into
YevheniiKotyrlo wants to merge 6 commits into
Conversation
The compiler records every declaration it could not translate, but nothing read compile().warnings() during a build, so a dropped float or z-index: auto was silent. The Metro transformer now prints one block per CSS file: capped in summary mode, listed in full in verbose mode, and printed again only when the file's warnings change. The warnings option sets the level, and none silences it. lightningcss also warns about input it cannot parse, such as an unknown at-rule or pseudo-element, whose rule then disappears. Those warnings reach a new syntax channel, kept apart from what React Native cannot express; this package's own @nativeMapping is not reported.
YevheniiKotyrlo
marked this pull request as ready for review
October 16, 2026 13:18
YevheniiKotyrlo
marked this pull request as draft
October 16, 2026 13:47
YevheniiKotyrlo
marked this pull request as ready for review
October 16, 2026 14:40
A value warning was kept as whatever the compiler held, so the report carried a fallback for objects and null that no producer records. The one number, a percentage line-height, is now recorded as text where it is produced, CompilerWarnings.values is string[], and the value entries sort with the same code-unit order as every other channel. A misspelled @nativeMapping is pinned as reported, since the filter that keeps the package's own at-rule quiet matches its name exactly.
The syntax-warning change left a blank line between compile() and the doc comment that describes it.
YevheniiKotyrlo
marked this pull request as draft
October 17, 2026 09:18
lightningcss ran without errorRecovery, so one rule or declaration it could not parse threw and the whole stylesheet compiled to nothing: lightningcss 1.30.1 throws on a media query's <general-enclosed> condition, on scroll-state(), and on var() with no argument, all of which a browser drops on its own while keeping every sibling. Both passes now recover, and the warning lightningcss gives for each dropped rule reaches compile().warnings() as `syntax`.
YevheniiKotyrlo
force-pushed
the
fix/syntax-error-recovery
branch
from
October 17, 2026 09:25
faae963 to
fb345e3
Compare
YevheniiKotyrlo
marked this pull request as ready for review
October 17, 2026 12:05
Contributor
Author
Snippet —
|
| result | |
|---|---|
main (eda2b286) |
throws Unexpected token Ident("bar"), so the sheet compiles to nothing |
this PR, merged into main |
["before", "after"] |
Run through the repo's jest on Windows with Node 26.
This was referenced Oct 21, 2026
… warning With error recovery, lightningcss keeps a media query whose feature holds a value outside its syntax, such as (prefers-color-scheme: 0), and warns instead of dropping the rule, so the second pass parses it again. This case is the one that fails without the second pass's errorRecovery.
…tion lightningcss parses scroll-state() from 1.31.0 on, without a warning, so on a newer lightningcss the container case would no longer exercise error recovery. Both 1.30.1 and 1.33.0 refuse a <general-enclosed> container condition with a warning, as they do the media case's.
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
The compiler runs lightningcss without
errorRecovery, so one rule or declaration lightningcss cannot parse throws, and the whole stylesheet compiles to nothing. lightningcss 1.30.1 throws on@media (foo bar)- a<general-enclosed>condition, which a browser evaluates as unknown - on@container scroll-state(stuck: top), onvar()with no argument, and on a value outside a media feature's syntax, such as@media (prefers-color-scheme: 0). A browser keeps every rule beside each of them (css-syntax-3 §5, mediaqueries-5 §3.2).Solution
Both passes run with
errorRecovery: true, so lightningcss drops what it cannot parse and the rest compiles. A media query whose feature value it refuses it keeps, with a warning, so the second pass reads that query again and recovers too; what the query compiles to is the media compiler's, and #426 answers such a feature as unknown. Each warning the first pass gives reachescompile().warnings()assyntax, through the channel #430 adds.Tests
src/__tests__/compiler/error-recovery.test.tscompiles each case beside other rules: those rules survive, a media or container query with a<general-enclosed>condition is dropped and reported, the query on(prefers-color-scheme: 0)is reported, and a declaration that fails to parse goes alone. The container case avoidsscroll-state(), which lightningcss parses from 1.31.0. All four fail on #430 without this change, and the(prefers-color-scheme: 0)case also fails without the second pass'serrorRecovery.Verification
On Ubuntu with the workflow's steps - build, lint, typecheck,
yarn test,node --test node/__tests__/*.mjs, both library builds, the web export, the unstaged-changes checks and commitlint - everything passes, and the iOS dev build passes with Xcode 27.1, where the workflow pins 26.6.Not run: the Android example build.
The snippet, run on
mainand here: #493 (comment)Merge order
It carries #430's commits, whose warning channel is where a dropped rule is reported, so #430 lands first.
#379 changes lines of
metro/metro-transformer.tsthat #430's commits change; whichever lands second rebases.