`compile()` fails with "failed to deserialize; expected an object-like struct named Specifier, found ()" on lightningcss >= 1.31 (any unresolved `var()`); the 1.30.2 guard doesn't cover it
Maintainer antworten meist innerhalb von 3 Tagen
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 45/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- react-native, typescript
- Bereich
- build-system, compilers
Rechercherichtung
Start in src/compiler/compiler.ts, where the second-pass Rule and StyleSheetExit visitors return the nodes they receive, and the first-pass StyleSheetExit returns the output of inlineVariables. Then check the version guard in lightningcss-loader.ts. Reproduce with compile(".a{color:var(--x)}", {}) on lightningcss 1.31+ and compare against 1.30.1. Done means the output matches 1.30.1 for defined, undefined and nested-fallback variables, or the loader rejects the affected versions with a clear message.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Summary
Any stylesheet that still contains a var() after variable inlining makes compile() throw when the installed lightningcss is 1.31.x, 1.32.0 or 1.33.0. This is the same lightningcss regression that the loader already blocks for 1.30.2, but the guard only matches that exact version (and its message says "or try upgrading", which doesn't help). The peer range is lightningcss >=1.27.0, so npm/bun install 1.33.0 by default and nothing catches it.
In practice, Tailwind 4 emits .border{border-style:var(--tw-border-style)}, so any NativeWind 5 app that uses border crashes the iOS/Android bundle on a fresh install.
Versions
- react-native-css
3.1.0-rc.0(also3.0.7) - lightningcss
1.31.1,1.32.0,1.33.0(also1.30.2and1.31.0) - Node 24.18, macOS arm64, npm 11
Minimal reproduction
mkdir repro && cd repro && npm init -y
npm i --legacy-peer-deps [email protected] [email protected]
// repro.cjs
const { compile } = require("react-native-css/compiler");
compile(".a{color:var(--x)}", {});
$ node repro.cjs
Error: failed to deserialize; expected an object-like struct named Specifier, found ()
compile(".a{color:var(--x)}", { inlineVariables: false }) fails the same way.
Expected: the same output as with lightningcss 1.30.1.
Actual: throws.
Results
| react-native-css | lightningcss | .a{color:var(--x)} |
.border{border-style:var(--x)} + .border-dashed{border-style:dashed} |
.a{border-style:dashed} |
|---|---|---|---|---|
| 3.1.0-rc.0 | 1.30.1 | OK | OK | OK |
| 3.1.0-rc.0 | 1.31.1 | FAIL | FAIL | OK |
| 3.1.0-rc.0 | 1.32.0 | FAIL | FAIL | OK |
| 3.1.0-rc.0 | 1.33.0 | FAIL | FAIL | OK |
| 3.0.7 | 1.30.1 | — | OK | — |
| 3.0.7 | 1.33.0 | — | FAIL | — |
When --x is defined once (so it gets inlined away), it passes on every version.
Cause
This comes from upstream lightningcss: parcel-bundler/lightningcss#1065 and #1081, both still open on 1.33.0. Since 1.30.2 (commit 9879b91, "Use serde-content instead of private serde types"), an explicit null in an Option<T> field of a node that a JS visitor returns no longer deserializes as None. The var() token is serialized to JS as {"name":{"ident":"--x","from":null},"fallback":null}, so handing it back unchanged throws. If the field is omitted, it works.
You can reproduce it with lightningcss alone:
require("lightningcss").transform({
filename: "a.css",
code: Buffer.from(".a{color:var(--x)}"),
visitor: { Declaration: (d) => d }, // identity -> throws on >= 1.30.2
});
In src/compiler/compiler.ts, three visitors return the node they received:
- second pass:
Rule(rule) { ...; return rule; }andStyleSheetExit(sheet) { ...; return sheet; }. Neither changes the AST, and this pass's output is discarded anyway (onlybuilderis used). This is whyinlineVariables: falsestill fails. - first pass:
StyleSheetExit(sheet) { return inlineVariables(sheet, vars); }. It legitimately modifies the AST, but any remainingvar()still hasfrom: null/fallback: null.
Suggested fix
I tested this locally by patching dist/ against lightningcss 1.31.1 and 1.33.0. The output is byte-identical to lightningcss 1.30.1 on a stylesheet with defined, undefined, nested-fallback and media-conditional variables:
-
In the second pass, return nothing from
RuleandStyleSheetExit(the visitor only reads). -
In the first pass, strip
nulls before returning the inlined sheet, e.g.const stripNulls = <T>(v: T): T => JSON.parse(JSON.stringify(v, (_k, x) => (x === null ? undefined : x))); firstPassVisitor.StyleSheetExit = (sheet) => stripNulls(inlineVariables(sheet, vars));A targeted recursive delete would be cheaper than a JSON round-trip. The same workaround is described in lightningcss#1081 and #1065.
If you'd rather not touch the compiler, a smaller step is to make the guard in lightningcss-loader.ts reject >=1.30.2 until upstream ships a fix (or narrow the peer to >=1.27.0 <1.30.2), and remove "or try upgrading" from the message.
Workaround for users
{ "overrides": { "lightningcss": "1.30.1" } }
(resolutions for yarn, pnpm.overrides for pnpm.)
Related
- #293: the same error on Expo's
@expo/log-boxCSS modules. It's likely the same root cause (any leftovervar()), not a log-box-specific problem. - nativewind/nativewind#1605, #1657: closed when the 1.30.2 guard landed, before 1.31 existed.
- #331: the Dependabot bump to lightningcss 1.32.0 was closed unmerged.
- Vorherrschende Sprache
- TypeScript
- Sterne
- 166
- Forks
- 45
- Ø Merge
- 13 T. 14 Std.
- Gemergte PRs (30 T.)
- 1
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus nativewind/react-native-css
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
nativewind/react-native-css#545 ·
Maintainer antworten meist innerhalb von 3 Tagen
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
nativewind/react-native-css#544 ·
Maintainer antworten meist innerhalb von 3 Tagen
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
nativewind/react-native-css#543 ·
Maintainer antworten meist innerhalb von 3 Tagen
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 84/100
nativewind/react-native-css#540 ·
Maintainer antworten meist innerhalb von 3 Tagen
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
nativewind/react-native-css#538 ·
Maintainer antworten meist innerhalb von 3 Tagen
Alle Issues in nativewind/react-native-css
Ähnliche Issues
-
Shell: serve the home app's Cookie Policy on a hard reloadEvtl. vergeben @2001anshkaushik hat das heute übernommen. Offenfeature module:ai
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
rocketride-org/rocketride-server#2899 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 2 Tagen
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
wazuh/wazuh-dashboard-plugins#9551 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
gofish-graphics/gofish-graphics#1252 ·
Maintainer antworten meist innerhalb von 1 Tag
-
optimization P3 size:XS
Schwierigkeit 1/5 1-3 Stunden Anfängerfreundlichkeit 88/100
josephfung/curia#2366 ·
Maintainer antworten meist innerhalb von 1 Tag
-
type:bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
nightgauge/nightgauge#2688 ·
Maintainer antworten meist innerhalb von 1 Tag