rescript-lang / rescript-lang/rescript

JSX preserve mode generates invalid JSX for external component bindings

Offen
#8,047 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Vorherrschende Sprache
OCaml
Sterne
7.5k
Forks
485
Ø Merge
1 T. 2 Std.
Gemergte PRs (30 T.)
55

Beschreibung

Thank you for filing! Check list:

  • Is it a bug? Usage questions should often be asked in the forum instead.
  • Concise, focused, friendly issue title & description.
  • A minimal, reproducible example.
  • OS and browser versions, if relevant.
  • Is it already fixed in master? Instructions

Summary

When using the generic JSX transform with "preserve": true, external component bindings generate invalid JSX syntax like <prim => Module.Component(prim)> instead of valid JSX.

ReScript Version

12.0.0

Minimal Reproduction

https://github.com/han-tyumi/rescript-jsx-preserve-bug

git clone https://github.com/han-tyumi/rescript-jsx-preserve-bug.git
cd rescript-jsx-preserve-bug
npm install
npx rescript build
cat Test.jsx
Files

rescript.json:

{
  "name": "preserve-bug",
  "sources": ["."],
  "package-specs": {
    "module": "esmodule",
    "in-source": true
  },
  "suffix": ".jsx",
  "jsx": {
    "module": "Preact",
    "preserve": true
  }
}

Preact.res (minimal bindings):

type element
type component<'props> = 'props => element

@module("preact/jsx-runtime")
external jsx: (component<'props>, 'props) => element = "jsx"

@module("preact/jsx-runtime")
external jsxs: (component<'props>, 'props) => element = "jsxs"

type fragmentProps = {children?: element}

@module("preact/jsx-runtime")
external jsxFragment: component<fragmentProps> = "Fragment"

type domProps = {children?: element}

module Elements = {
  external someElement: element => option<element> = "%identity"

  @module("preact/jsx-runtime")
  external jsx: (string, domProps) => element = "jsx"

  @module("preact/jsx-runtime")
  external jsxs: (string, domProps) => element = "jsxs"
}

Test.res:

// Component module pattern with external make
module Head = {
  type props = {children?: Preact.element}
  @module("some-lib")
  external make: props => Preact.element = "Head"
}

// Using the component
let test = <Head> <div /> </Head>

Expected Output

Valid JSX that can be processed by standard JSX transformers:

let test = <SomeLib.Head>
  <div />
</SomeLib.Head>;

Actual Output

Invalid JSX with arrow function syntax:

let test = <prim => SomeLib.Head(prim)>
  {Primitive_option.some(<div />)}
</prim => SomeLib.Head(prim)>;

Notes

  • Lowercase DOM elements work correctly in preserve mode (e.g., <div> stays as <div>)
  • Internal component modules (with ReScript-defined make functions) work correctly (e.g., <MyComponent.make>)
  • External component bindings produce the invalid arrow function syntax shown above

This prevents using preserve mode with frameworks like Preact/Fresh where you need to bind to external components.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit der verknüpften minimalen Reproduktion unter Verwendung von rescript.json, Preact.res und Test.res, und führe anschließend npx rescript build aus, um das generierte Test.jsx zu beobachten. Verfolge die generische JSX-preserve-Verarbeitung des Compilers für externe Komponentenbindungen und füge einen Regressionstest hinzu, der die ungültige Ausgabe der Pfeilfunktion abdeckt; fertig ist die Änderung, wenn gültiges JSX erzeugt wird, das der erwarteten Form SomeLib.Head entspricht.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
javascript, ocaml
Bereich
compilers, web-dev
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.