Skip to content

Commit 2a41068

Browse files
johnhaley81claude
andcommitted
Fix critical PPX bug: DOM element externals not injected at structure level
**Root Cause**: External declarations for DOM elements with data attributes were generated at expression level but only injected at structure level, causing "Unbound value makeProps_div_*" compilation errors. **Technical Analysis**: - DOM elements processed in `transformLowercaseCall3` (expression level) - External declarations stored in `externalDeclarations` ref - But externals only injected in `method! structure` which resets the ref - Result: DOM element externals never reach final AST output **Solution**: Modified structure processing to preserve externals across nested contexts by: 1. Storing parent externals before processing 2. Collecting all externals (React components + DOM elements) 3. Restoring and accumulating externals properly 4. Injecting all externals at structure boundaries **Maintains**: - Existing functionality for React components - Deduplication logic (externalExists check) - Zero-runtime performance (compile-time only) - Kebab-case transformation (data_test_id → data-test-id) **Fixes**: All DOM elements with data attributes now compile successfully including nested modules, functions, and complex nested structures. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 4ca0aa3 commit 2a41068

2 files changed

Lines changed: 13 additions & 4 deletions

File tree

demo/main.re

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ module WithoutForward = {
221221
};
222222
};
223223

224+
224225
module DataAttrsDemo = {
225226
[@react.component]
226227
let make = () => {
@@ -233,7 +234,7 @@ module DataAttrsDemo = {
233234
</div>
234235

235236
<div
236-
className="demo-multi"
237+
className="demo-multi" data_testid="demo-multi" data_value="test"
237238
>
238239
{React.string("Data attributes: data_testid becomes data-testid")}
239240
</div>
@@ -267,6 +268,7 @@ module DataAttrsDemo = {
267268
};
268269
};
269270

271+
270272
module App = {
271273
[@react.component]
272274
let make = (~initialValue) => {

ppx/reason_react_ppx.ml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,14 +1464,21 @@ let jsxMapper =
14641464
[@@raises Invalid_argument]
14651465

14661466
method! structure ctxt stru =
1467+
(* Store existing externals from any parent context *)
1468+
let parentExternals = !externalDeclarations in
14671469
externalDeclarations := [];
14681470

1471+
(* Process the structure, collecting React component externals *)
14691472
let processedStru = super#structure ctxt (reactComponentTransform ~ctxt self stru) in
14701473

1471-
let externals = List.rev !externalDeclarations in
1472-
externalDeclarations := [];
1474+
(* Collect externals from both React components and DOM elements *)
1475+
let allExternals = List.rev !externalDeclarations in
1476+
1477+
(* Restore parent externals and add our collected externals *)
1478+
externalDeclarations := allExternals @ parentExternals;
14731479

1474-
externals @ processedStru
1480+
(* Inject externals at the beginning of this structure *)
1481+
allExternals @ processedStru
14751482
[@@raises Invalid_argument]
14761483

14771484
method! expression ctxt expr =

0 commit comments

Comments
 (0)