Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

JSX preserve mode spreads an `@unboxed` props record (`{..."x"}` instead of `"x"`)

Chiusa
#8,813 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Una pull request collegata è già stata integrata.

  • #8847 di @cknitt — chiusa senza merge
  • #8857 di @cknitt — integrata

Valutazione

Difficoltà
4/5
Tempo stimato
1-2 giorni
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Ferma
Stack tecnologico
javascript, ocaml
Ambito
compilers

Direzione di ricerca

Start with jsx_props_of in compiler/ml/translcore.ml and jsx_printable in compiler/core/js_dump.ml, then compare the preserve-mode output with the reproduction and expected output in the issue. Done means both @unboxed record examples preserve the string as the props value instead of spreading it. Pull request #8847 is already open for this issue.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Found by adversarial experiments on semantic analysts.

What is broken

jsx_props_of turns every props expression that is not a Record_regular record literal into Jsx_props_spread:
https://github.com/rescript-lang/rescript/blob/8d51b9ce7/compiler/ml/translcore.ml#L1049-L1096

An @unboxed record literal compiles to its single field's value, which is not an object. jsx_printable does not reject this case:
https://github.com/rescript-lang/rescript/blob/8d51b9ce7/compiler/core/js_dump.ml#L176-L190

Reproduction

@@jsxConfig({version: 4, module_: "MyJsx"})
module MyJsx = {
  type element = int
  type component<'props> = 'props => element
  external component: component<'props> => component<'props> = "%identity"
  @module("rt") external jsx: (component<'props>, 'props) => element = "jsx"
  @module("rt") external jsxs: (component<'props>, 'props) => element = "jsxs"
  external array: array<element> => element = "%identity"
}
@unboxed type props = {title: string}
module C = {@module("lib") external make: MyJsx.component<props> = "C"}
module D = {@val external make: MyJsx.component<props> = "lowerD"}
let el = <C title="x" />
let el2 = <D title="y" />

bsc -nopervasives -bs-jsx 4 -bs-jsx-preserve K12.res at master:

let el = <Lib.C
  {..."x"}
/>;
let el2 = Rt.jsx(lowerD, {..."y"});

Expected, as printed by bsc -nopervasives -bs-jsx 4 and by preserve mode at ece8b148:

let el = Rt.jsx(Lib.C, "x");
let el2 = Rt.jsx(lowerD, "y");

Introduced

#8754 (a7721303a).

Impact

The component receives {0: "x"} instead of "x": the generated code is wrong, with no error or warning. The case is rare, because the props type must be an @unboxed record.

Lingua principale
OCaml
Stelle
7.5k
Fork
484
Merge medio
20h 27m
PR unite (30g)
120

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di rescript-lang/rescript

Tutte le issue di rescript-lang/rescript

Issue simili

Altre issue su Compilers

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.