Skip to content

Commit f67c121

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

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

jscomp/ml/translcore.ml

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

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

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

0 commit comments

Comments
 (0)