Skip to content

Commit be17a60

Browse files
Fix namespace handling
1 parent 72bf7c8 commit be17a60

3 files changed

Lines changed: 109 additions & 30 deletions

File tree

compiler/core/lam_compile.ml

Lines changed: 95 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,12 @@ type initialization = J.block
233233

234234
let compile output_prefix =
235235
let root_module_name (id : Ident.t) =
236-
match String.index_opt id.name '$' with
237-
| Some index -> String.sub id.name 0 index
238-
| None -> id.name
236+
match Ext_namespace.try_split_module_name id.name with
237+
| Some (_namespace, module_name) -> module_name
238+
| None -> (
239+
match String.index_opt id.name '$' with
240+
| Some index -> String.sub id.name 0 index
241+
| None -> id.name)
239242
in
240243
let rec extract_nested_external_component_segments segments
241244
((lam : Lam.t), (make_dynamic_import : bool option ref)) :
@@ -271,6 +274,16 @@ let compile output_prefix =
271274
extract_nested_external_component_segments [] (arg, dynamic_import)
272275
with
273276
| Some (id, dynamic_import, segments) -> (
277+
let denamespace_segment segment =
278+
let root_name = root_module_name id in
279+
let namespaced_prefix = root_name ^ "$" in
280+
if Ext_string.starts_with segment namespaced_prefix then
281+
match String.split_on_char '$' segment with
282+
| root :: _namespace :: rest when rest <> [] ->
283+
String.concat "$" (root :: rest)
284+
| _ -> segment
285+
else segment
286+
in
274287
let segments =
275288
match segments with
276289
| head :: rest
@@ -280,6 +293,11 @@ let compile output_prefix =
280293
rest
281294
| _ -> segments
282295
in
296+
let segments =
297+
match segments with
298+
| head :: rest -> denamespace_segment head :: rest
299+
| [] -> []
300+
in
283301
match segments with
284302
| [] -> None
285303
| _ ->
@@ -290,6 +308,72 @@ let compile output_prefix =
290308
| None -> None)
291309
| _ -> None
292310
in
311+
let normalize_hidden_component_name (id : Ident.t) (hidden_name : string) =
312+
let root_name = root_module_name id in
313+
let id_parts = String.split_on_char '$' id.name in
314+
let namespace_parts =
315+
match id_parts with
316+
| _root :: rest -> rest
317+
| [] -> []
318+
in
319+
let hidden_parts = String.split_on_char '$' hidden_name in
320+
let hidden_parts_without_root =
321+
match hidden_parts with
322+
| first :: rest when String.equal first root_name -> rest
323+
| _ -> hidden_parts
324+
in
325+
let rec drop_prefix prefix parts =
326+
match (prefix, parts) with
327+
| [], _ -> parts
328+
| x :: xs, y :: ys when String.equal x y -> drop_prefix xs ys
329+
| _ -> parts
330+
in
331+
let tail = drop_prefix namespace_parts hidden_parts_without_root in
332+
match tail with
333+
| [] -> hidden_name
334+
| _ -> String.concat "$" (root_name :: tail)
335+
in
336+
let hidden_component_name_candidates (id : Ident.t) (hidden_name : string) =
337+
let candidates = ref [] in
338+
let push candidate =
339+
if not (List.mem candidate !candidates) then
340+
candidates := candidate :: !candidates
341+
in
342+
(match String.split_on_char '$' hidden_name with
343+
| root :: _namespace :: rest when rest <> [] ->
344+
push (String.concat "$" (root :: rest))
345+
| _ -> ());
346+
push (normalize_hidden_component_name id hidden_name);
347+
push hidden_name;
348+
List.rev !candidates
349+
in
350+
let rewrite_nested_jsx_component_expr (jsx_tag : Lam.t)
351+
(compiled_expr : J.expression) : J.expression =
352+
let rec extract_module_id (expr : J.expression) =
353+
match expr.expression_desc with
354+
| Var (Qualified (module_id, _)) -> Some module_id
355+
| Static_index (inner, _, _) -> extract_module_id inner
356+
| _ -> None
357+
in
358+
match extract_nested_external_component_field jsx_tag with
359+
| Some (id, dynamic_import, hidden_name) -> (
360+
let hidden_name_candidates =
361+
hidden_component_name_candidates id hidden_name
362+
in
363+
let resolved_hidden_name =
364+
match hidden_name_candidates with
365+
| candidate :: _ -> Some candidate
366+
| [] -> None
367+
in
368+
match (resolved_hidden_name, extract_module_id compiled_expr) with
369+
| Some hidden_name, Some module_id ->
370+
{
371+
compiled_expr with
372+
expression_desc = Var (Qualified (module_id, Some hidden_name));
373+
}
374+
| _ -> compiled_expr)
375+
| None -> compiled_expr
376+
in
293377
let rec compile_external_field (* Like [List.empty]*)
294378
?(dynamic_import = false) (lamba_cxt : Lam_compile_context.t)
295379
(id : Ident.t) name : Js_output.t =
@@ -361,15 +445,11 @@ let compile output_prefix =
361445
let args =
362446
if appinfo.ap_transformed_jsx then
363447
match (appinfo.ap_args, args) with
364-
| jsx_tag :: _, _ :: rest_args -> (
365-
match extract_nested_external_component_field jsx_tag with
366-
| Some (id, dynamic_import, hidden_name) ->
367-
E.ml_var_dot ~dynamic_import id hidden_name :: rest_args
368-
| None -> args)
448+
| jsx_tag :: _, jsx_expr :: rest_args ->
449+
rewrite_nested_jsx_component_expr jsx_tag jsx_expr :: rest_args
369450
| _ -> args
370451
else args
371452
in
372-
373453
let fn = E.ml_var_dot ~dynamic_import module_id ident_info.name in
374454
let expression =
375455
match appinfo.ap_info.ap_status with
@@ -1596,11 +1676,8 @@ let compile output_prefix =
15961676
let args =
15971677
if appinfo.ap_transformed_jsx then
15981678
match (appinfo.ap_args, args) with
1599-
| jsx_tag :: _, _ :: rest_args -> (
1600-
match extract_nested_external_component_field jsx_tag with
1601-
| Some (id, dynamic_import, hidden_name) ->
1602-
E.ml_var_dot ~dynamic_import id hidden_name :: rest_args
1603-
| None -> args)
1679+
| jsx_tag :: _, jsx_expr :: rest_args ->
1680+
rewrite_nested_jsx_component_expr jsx_tag jsx_expr :: rest_args
16041681
| _ -> args
16051682
else args
16061683
in
@@ -1676,21 +1753,10 @@ let compile output_prefix =
16761753
} ->
16771754
let new_cxt = {lambda_cxt with continuation = NeedValue Not_tail} in
16781755
let tag_block, tag_expr =
1679-
match extract_nested_external_component_field jsx_tag with
1680-
| Some (id, dynamic_import, hidden_name) -> (
1681-
match
1682-
Lam_compile_env.query_external_id_info ~dynamic_import id
1683-
(hidden_name ^ "$jsx")
1684-
with
1685-
| exception Not_found -> (
1686-
match compile_lambda new_cxt jsx_tag with
1687-
| {block; value = Some b} -> (block, b)
1688-
| {value = None} -> assert false)
1689-
| _ -> ([], E.ml_var_dot ~dynamic_import id hidden_name))
1690-
| None -> (
1691-
match compile_lambda new_cxt jsx_tag with
1692-
| {block; value = Some b} -> (block, b)
1693-
| {value = None} -> assert false)
1756+
match compile_lambda new_cxt jsx_tag with
1757+
| {block; value = Some b} ->
1758+
(block, rewrite_nested_jsx_component_expr jsx_tag b)
1759+
| {value = None} -> assert false
16941760
in
16951761
let rest_blocks, rest_exprs =
16961762
Ext_list.split_map rest_args (fun x ->

compiler/syntax/src/jsx_v4.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,17 @@ let filename_from_loc (pstr_loc : Location.t) =
122122
let file_name = String.capitalize_ascii file_name in
123123
file_name
124124

125+
let unnamespace_module_name file_name =
126+
match String.index_opt file_name '$' with
127+
| Some index -> String.sub file_name 0 index
128+
| None -> (
129+
match Ext_namespace.try_split_module_name file_name with
130+
| Some (module_name, _namespace) -> module_name
131+
| None -> file_name)
132+
125133
(* Build a string representation of a module name with segments separated by $ *)
126134
let make_module_name file_name nested_modules fn_name =
135+
let file_name = unnamespace_module_name file_name in
127136
let full_module_name =
128137
match (file_name, nested_modules, fn_name) with
129138
(* TODO: is this even reachable? It seems like the fileName always exists *)

tests/build_tests/rsc_nested_jsx_members/input.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ assert.match(
2525
);
2626
assert.match(
2727
output,
28-
/JsxRuntime\.jsx\(Sidebar\$RscNestedJsxMembers\.Sidebar(?:\$RscNestedJsxMembers)?\$Provider,/,
28+
/JsxRuntime\.jsx\(Sidebar\$RscNestedJsxMembers\.Sidebar\$Provider,/,
29+
);
30+
assert.doesNotMatch(
31+
output,
32+
/JsxRuntime\.jsx\(Sidebar\$RscNestedJsxMembers\.Sidebar\$RscNestedJsxMembers\$Provider,/,
2933
);
3034
assert.doesNotMatch(output, /\.Provider\.make,/);
3135
assert.match(

0 commit comments

Comments
 (0)