Skip to content

Commit 70700fe

Browse files
authored
Fix dynamic Import issue with function-defined externals (#7060)
* fix dynamic import for Lfunction * changelog
1 parent ac30044 commit 70700fe

5 files changed

+64
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
- Use FORCE_COLOR environmental variable to force colorized output https://github.com/rescript-lang/rescript-compiler/pull/7033
2222
- Allow spreads of variants in patterns (`| ...someVariant as v => `) when the variant spread is a subtype of the variant matched on. https://github.com/rescript-lang/rescript-compiler/pull/6721
23+
- Fix the issue where dynamic imports are not working for function-defined externals. https://github.com/rescript-lang/rescript-compiler/pull/7060
2324

2425
#### :bug: Bug fix
2526

jscomp/core/lam_compile.ml

+54
Original file line numberDiff line numberDiff line change
@@ -1625,6 +1625,60 @@ and compile_prim (prim_info : Lam.prim_info)
16251625
Js_output.output_of_block_and_expression lambda_cxt.continuation
16261626
(Ext_list.concat_append args_block block)
16271627
exp
1628+
| { primitive = Pimport; args = [] | _ :: _ :: _; loc } ->
1629+
Location.raise_errorf ~loc
1630+
"Missing argument: Dynamic import requires a module or \
1631+
module value that is a file as argument."
1632+
| { primitive = Pimport as primitive; args = [ mod_ ]; loc} ->
1633+
(match mod_ with
1634+
| Lglobal_module _ | Lvar _
1635+
| Lprim { primitive = Pfield _ | Pjs_call _ ; _ } ->
1636+
let args_block, args_expr =
1637+
let new_cxt =
1638+
{ lambda_cxt with continuation = NeedValue Not_tail }
1639+
in
1640+
match compile_lambda new_cxt mod_ with
1641+
| { block; value = Some b; _ } -> ([ block ], b)
1642+
| { value = None; _ } -> assert false
1643+
in
1644+
let args_code : J.block = List.concat args_block in
1645+
let exp =
1646+
Lam_compile_primitive.translate output_prefix loc lambda_cxt primitive [args_expr]
1647+
in
1648+
Js_output.output_of_block_and_expression lambda_cxt.continuation args_code
1649+
exp
1650+
| Lfunction {
1651+
body =
1652+
( (Lprim _ as body)
1653+
| Lsequence ((Lprim _ as body), Lconst Const_js_undefined _) );
1654+
_;
1655+
} ->
1656+
let body = match body with
1657+
| Lprim ({ primitive = Pjs_call prim_info; args; loc }) ->
1658+
Lam.prim
1659+
~primitive:(Lam_primitive.Pjs_call { prim_info with dynamic_import = true })
1660+
~args
1661+
loc
1662+
| _ -> body
1663+
in
1664+
let args_block, args_expr =
1665+
let new_cxt =
1666+
{ lambda_cxt with continuation = NeedValue Not_tail }
1667+
in
1668+
match compile_lambda new_cxt body with
1669+
| { block; value = Some b; _ } -> ([ block ], b)
1670+
| { value = None; _ } -> assert false
1671+
in
1672+
let args_code : J.block = List.concat args_block in
1673+
let exp =
1674+
Lam_compile_primitive.translate output_prefix loc lambda_cxt primitive [args_expr]
1675+
in
1676+
Js_output.output_of_block_and_expression lambda_cxt.continuation args_code
1677+
exp
1678+
| _ ->
1679+
Location.raise_errorf ~loc
1680+
"Invalid argument: unsupported argument to dynamic import. If \
1681+
you believe this should be supported, please open an issue.")
16281682
| { primitive; args; loc } ->
16291683
let args_block, args_expr =
16301684
if args = [] then ([], [])

jscomp/core/lam_compile_primitive.ml

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ let ensure_value_unit (st : Lam_compile_context.continuation) e : E.t =
3838

3939
let module_of_expression = function
4040
| J.Var (J.Qualified (module_id, value)) -> [ (module_id, value) ]
41+
| J.Call ({expression_desc = (J.Var (J.Qualified (module_id, value)))}, _, _) -> [ (module_id, value) ]
4142
| _ -> []
4243

4344
let get_module_system () =

jscomp/test/import_external.js

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/test/import_external.res

+5
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,8 @@
22
external makeA: string = "default"
33

44
let f8 = Js.import(makeA)
5+
6+
@module("b")
7+
external makeB: string => unit = "default"
8+
9+
let f9 = Js.import(makeB)

0 commit comments

Comments
 (0)