A value read through `var()` that the property can't take still applies: `border: var(--b)` over `--b: 1px, solid` draws a border, and `border-inline-width` over `red` keeps an earlier width

Ouverte
#552 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 5 jours

Personne n'a encore pris cette issue.

Évaluation

Difficulté
3/5
Temps estimé
Une demi-journée
Accessibilité débutants
45/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
react-native, typescript
Domaine
frontend, mobile

Piste de recherche

Start with the reproducer src/__tests__/native/comma-list-in-a-variable.test.tsx and run it to see the four logged cases. The comma-list case is in shorthandHandler in src/native/styles/shorthands/_handler.ts, which calls args.flat() before matching patterns. The refused-value case is in logicalWidth in src/native/styles/shorthands/logical-border-width.ts, which returns undefined where the keys should be unset. Done when the expected outputs hold on both the folded and inlineVariables: false routes; check the interaction with #547 before changing the list handling.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

Before submitting a new issue
  • I tested using the latest version of the library, as the bug might be already fixed.
  • I tested using a supported version of react native.
  • I checked for possible duplicate issues, with possible answers.
Bug summary

In CSS a var() whose value doesn't fit the property's grammar makes the declaration invalid at computed-value time (css-variables-1 §3): the property is unset, and an earlier rule's value for it no longer applies. The shorthand readers get both halves of that wrong, on the folded route and with inlineVariables: false alike:

  1. A comma list is read as a space list. border and border-inline-width have no comma in their grammar, yet border: var(--b) over --b: 1px, solid draws a 1px solid border, and border-inline-width: var(--w) over --w: 1px, 2px applies 1 and 2, as if the value were written 1px 2px.
  2. A refused value leaves the earlier one. border-inline-width: var(--w) and border-block-width: var(--w) over --w: red are refused, but an earlier rule's 5px stays, where the property should be unset.
folded .a { --b: 1px, solid; border: var(--b); }
   => {"borderWidth":1,"borderStyle":"solid"}
kept   .a { --b: 1px, solid; border: var(--b); }
   => {"borderWidth":1,"borderStyle":"solid"}
folded .earlier { border-inline-width: 5px; } .a { --w: 1px, 2px; border-inline-width: var(--w); }
   => {"borderStartWidth":1,"borderEndWidth":2}
kept   .earlier { border-inline-width: 5px; } .a { --w: 1px, 2px; border-inline-width: var(--w); }
   => {"borderStartWidth":1,"borderEndWidth":2}
folded .earlier { border-inline-width: 5px; } .a { --w: red; border-inline-width: var(--w); }
   => {"borderStartWidth":5,"borderEndWidth":5}
kept   .earlier { border-inline-width: 5px; } .a { --w: red; border-inline-width: var(--w); }
   => {"borderStartWidth":5,"borderEndWidth":5}
folded .earlier { border-block-width: 5px; } .a { --w: red; border-block-width: var(--w); }
   => {"borderTopWidth":5,"borderBottomWidth":5}
kept   .earlier { border-block-width: 5px; } .a { --w: red; border-block-width: var(--w); }
   => {"borderTopWidth":5,"borderBottomWidth":5}
  • shorthandHandler (src/native/styles/shorthands/_handler.ts) runs args = args.flat() on the resolved value before matching it against the shorthand's patterns, so a comma-separated list's items match as one space-separated list.
  • logicalWidth (src/native/styles/shorthands/logical-border-width.ts) returns undefined for a value that isn't one or two finite non-negative numbers, and undefined sets nothing, so the earlier rule's width stays; returning the two keys as null would unset them.

I've filed them together since they're the same rule failing in two readers that share one harness. #547 keeps a list's separator when it's read through a variable, so it makes case 1 a refusal for border-inline-width, which then lands in case 2.

Library version

main at a37903f (0.0.0-nightly.a37903f)

Environment info
Windows 11 10.0.26300, Node 26.12.1, Yarn 4.9.2, react-native 0.86.3 (the repository's dev dependency).
No app or native build is involved: the output comes from the repository's jest setup.
Steps to reproduce
  1. Clone the reproducer branch, which is main at a37903f with one file added, src/__tests__/native/comma-list-in-a-variable.test.tsx, and install:
    git clone --branch repro/552-comma-list-read-as-a-space-list https://github.com/YevheniiKotyrlo/react-native-css
    cd react-native-css
    yarn install
    
  2. Run yarn jest src/__tests__/native/comma-list-in-a-variable.test.tsx and read the logged lines.

src/__tests__/native/comma-list-in-a-variable.test.tsx:

import { StyleSheet } from "react-native";

import { render, screen } from "@testing-library/react-native";
import { View } from "react-native-css/components/View";
import { registerCSS, testID } from "react-native-css/jest";

jest.mock("../../native/reanimated", () => ({
  animatedComponentFamily: (component: unknown) => component,
}));

test.each([
  ".a { --b: 1px, solid; border: var(--b); }",
  ".earlier { border-inline-width: 5px; } .a { --w: 1px, 2px; border-inline-width: var(--w); }",
  ".earlier { border-inline-width: 5px; } .a { --w: red; border-inline-width: var(--w); }",
  ".earlier { border-block-width: 5px; } .a { --w: red; border-block-width: var(--w); }",
])("%s", (css) => {
  for (const inlineVariables of [true, false]) {
    registerCSS(css, inlineVariables ? {} : { inlineVariables: false });
    render(<View testID={testID} className="earlier a" />);
    console.log(
      `${inlineVariables ? "folded" : "kept  "} ${css}\n   => ${JSON.stringify(StyleSheet.flatten(screen.getByTestId(testID).props.style))}`,
    );
    screen.unmount();
  }
});

Expected: border: var(--b) over 1px, solid draws no border; border-inline-width: var(--w) over 1px, 2px or red sets neither borderStartWidth nor borderEndWidth, so the earlier 5px no longer applies; the same for border-block-width.

Actual: the border is drawn 1px solid, 1px, 2px applies 1 and 2, and red leaves the earlier 5px.

The run's output on main at a37903f, Windows 11, Node 26.12.1
  console.log
    folded .a { --b: 1px, solid; border: var(--b); }
       => {"borderWidth":1,"borderStyle":"solid"}

      at log (src/__tests__/native/comma-list-in-a-variable.test.tsx:20:13)

  console.log
    kept   .a { --b: 1px, solid; border: var(--b); }
       => {"borderWidth":1,"borderStyle":"solid"}

      at log (src/__tests__/native/comma-list-in-a-variable.test.tsx:20:13)

  console.log
    folded .earlier { border-inline-width: 5px; } .a { --w: 1px, 2px; border-inline-width: var(--w); }
       => {"borderStartWidth":1,"borderEndWidth":2}

      at log (src/__tests__/native/comma-list-in-a-variable.test.tsx:20:13)

  console.log
    kept   .earlier { border-inline-width: 5px; } .a { --w: 1px, 2px; border-inline-width: var(--w); }
       => {"borderStartWidth":1,"borderEndWidth":2}

      at log (src/__tests__/native/comma-list-in-a-variable.test.tsx:20:13)

  console.log
    folded .earlier { border-inline-width: 5px; } .a { --w: red; border-inline-width: var(--w); }
       => {"borderStartWidth":5,"borderEndWidth":5}

      at log (src/__tests__/native/comma-list-in-a-variable.test.tsx:20:13)

  console.log
    kept   .earlier { border-inline-width: 5px; } .a { --w: red; border-inline-width: var(--w); }
       => {"borderStartWidth":5,"borderEndWidth":5}

      at log (src/__tests__/native/comma-list-in-a-variable.test.tsx:20:13)

  console.log
    folded .earlier { border-block-width: 5px; } .a { --w: red; border-block-width: var(--w); }
       => {"borderTopWidth":5,"borderBottomWidth":5}

      at log (src/__tests__/native/comma-list-in-a-variable.test.tsx:20:13)

  console.log
    kept   .earlier { border-block-width: 5px; } .a { --w: red; border-block-width: var(--w); }
       => {"borderTopWidth":5,"borderBottomWidth":5}

      at log (src/__tests__/native/comma-list-in-a-variable.test.tsx:20:13)

PASS src/__tests__/native/comma-list-in-a-variable.test.tsx
  √ .a { --b: 1px, solid; border: var(--b); } (31 ms)
  √ .earlier { border-inline-width: 5px; } .a { --w: 1px, 2px; border-inline-width: var(--w); } (5 ms)
  √ .earlier { border-inline-width: 5px; } .a { --w: red; border-inline-width: var(--w); } (3 ms)
  √ .earlier { border-block-width: 5px; } .a { --w: red; border-block-width: var(--w); } (2 ms)

Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        1.684 s, estimated 2 s
Ran all test suites matching /src\\__tests__\\native\\comma-list-in-a-variable.test.tsx/i.
Reproducible example repository

https://github.com/YevheniiKotyrlo/react-native-css/tree/repro/552-comma-list-read-as-a-space-list

Langage dominant
TypeScript
Étoiles
166
Forks
45
Merge moyen
10 j 1 h
PR mergées (30 j)
4

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de nativewind/react-native-css

Toutes les issues de nativewind/react-native-css

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.