diff --git a/src/__tests__/native/vars.test.tsx b/src/__tests__/native/vars.test.tsx
index d87eb7c4..66586fbd 100644
--- a/src/__tests__/native/vars.test.tsx
+++ b/src/__tests__/native/vars.test.tsx
@@ -2,7 +2,7 @@
import { render, screen } from "@testing-library/react-native";
import { View } from "react-native-css/components/View";
import { registerCSS, testID } from "react-native-css/jest";
-import { vars } from "react-native-css/runtime";
+import { VariableContextProvider, vars } from "react-native-css/runtime";
test("vars", () => {
registerCSS(
@@ -36,3 +36,49 @@ test("vars", () => {
color: "blue",
});
});
+
+test("an element's own vars() outranks an inherited value", () => {
+ // `--my-var` is defined twice so `inline-variables.ts` cannot fold it into
+ // the consuming declaration; a single definition performs no runtime var()
+ // read and would pass without exercising precedence at all.
+ registerCSS(
+ `.decoy { --my-var: seed; }
+ .other-decoy { --my-var: seed2; }
+ .my-class { color: var(--my-var); }`,
+ );
+
+ render(
+
+
+ ,
+ );
+
+ // css-cascade-4 ยง7.2: inheritance is a defaulting step, reached only when the
+ // cascade yields no declared value for the element. The element declares
+ // `--my-var`, so the ancestor's `red` never applies to it.
+ expect(screen.getByTestId(testID).props.style).toStrictEqual({
+ color: "blue",
+ });
+});
+
+test("an inherited value still applies when the element declares nothing", () => {
+ registerCSS(
+ `.decoy { --my-var: seed; }
+ .other-decoy { --my-var: seed2; }
+ .my-class { color: var(--my-var); }`,
+ );
+
+ render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId(testID).props.style).toStrictEqual({
+ color: "red",
+ });
+});
diff --git a/src/native/styles/variables.ts b/src/native/styles/variables.ts
index af3d6ee2..d6361b97 100644
--- a/src/native/styles/variables.ts
+++ b/src/native/styles/variables.ts
@@ -46,11 +46,6 @@ export function varResolver(
return;
}
- if (name in variables) {
- renderGuards?.push(["v", name, variables[name]]);
- return resolve(variables[name]);
- }
-
variableHistory.add(name);
let value = resolve(inlineVariables?.[name] as StyleDescriptor);
@@ -61,13 +56,12 @@ export function varResolver(
return value;
}
- value = resolve(variables[name]);
- if (value !== undefined) {
- renderGuards?.push(["v", name, value]);
- options.inlineVariables ??= { [VAR_SYMBOL]: "inline" };
- options.inlineVariables[name] = value;
-
- return value;
+ if (name in variables) {
+ // The RAW inherited descriptor, not the resolved value: `testGuards`
+ // compares this against the next render's context, and a resolved value
+ // would never match.
+ renderGuards?.push(["v", name, variables[name]]);
+ return resolve(variables[name]);
}
value = resolve(get(universalVariables(name)));