Skip to content

Commit db30a51

Browse files
committed
specialize Js.Dict.fromArray to compile to a direct JS object creation when possible
1 parent d89b3c8 commit db30a51

File tree

4 files changed

+56
-2
lines changed

4 files changed

+56
-2
lines changed

jscomp/ml/translcore.ml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,13 @@ let extract_directive_for_fn exp =
720720
exp.exp_attributes |> List.find_map (
721721
fun ({txt}, payload) -> if txt = "directive" then Ast_payload.is_single_string payload else None)
722722

723+
let args_elgible_for_dict_inlining (args : expression list) =
724+
args
725+
|> List.find_opt (fun (arg : expression) ->
726+
match arg.exp_desc with
727+
| Texp_tuple [{exp_desc = Texp_constant (Const_string _)}; _] -> false
728+
| _ -> true)
729+
|> Option.is_none
723730

724731
let rec transl_exp e =
725732
List.iter (Translattribute.check_attribute e) e.exp_attributes;
@@ -802,6 +809,28 @@ and transl_exp0 (e : Typedtree.expression) : Lambda.lambda =
802809
| _ ->
803810
wrap (Lprim (prim, argl, e.exp_loc))
804811
))
812+
| Texp_apply
813+
( {exp_desc = Texp_ident (p, _, _)},
814+
[(_lbl, Some {exp_desc = Texp_array args})] )
815+
when Path.name p = "Js.Dict.fromArray"
816+
&& args_elgible_for_dict_inlining args ->
817+
let fields = Array.make (List.length args) "" in
818+
let args =
819+
args
820+
|> List.mapi (fun index (arg : expression) ->
821+
match arg.exp_desc with
822+
| Texp_tuple
823+
[{exp_desc = Texp_constant (Const_string (fieldName, _))}; exp]
824+
->
825+
Array.set fields index fieldName;
826+
exp |> transl_exp |> extract_constant
827+
| _ -> assert false)
828+
in
829+
Lconst
830+
(Const_block
831+
( Blk_record
832+
{fields; mutable_flag = Mutable; record_repr = Record_regular},
833+
args ))
805834
| Texp_apply (funct, oargs) ->
806835
let inlined, funct =
807836
Translattribute.get_and_remove_inlined_attribute funct

jscomp/test/DictTests.js

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/test/DictTests.res

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
let dictCreationCanBeInlined = Js.Dict.fromArray([
2+
("name", "hello"),
3+
("age", "what"),
4+
("more", "stuff"),
5+
])
6+
7+
external imaginaryExternalArgs: array<(string, string)> = "imaginary"
8+
9+
let dictCreationCanNotBeInlined = Js.Dict.fromArray(imaginaryExternalArgs)

jscomp/test/build.ninja

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)