Skip to content

Commit

Permalink
Compiler: support for es6 import/export
Browse files Browse the repository at this point in the history
  • Loading branch information
hhugo committed Nov 26, 2023
1 parent 8d87bba commit 4c22226
Show file tree
Hide file tree
Showing 15 changed files with 813 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Compiler: change control-flow compilation strategy (#1496)
* Compiler: Dead code elimination of unused references (#2076)
* Compiler: reduce memory consumption (#1516)
* Compiler: support for es6 import and export construct
* Lib: add download attribute to anchor element
* Misc: switch CI to OCaml 5.1
* Misc: preliminary support for OCaml 5.2
Expand Down
3 changes: 2 additions & 1 deletion compiler/bin-jsoo_minify/jsoo_minify.ml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ let f { Cmd_arg.common; output_file; use_stdin; files } =
let true_ () = true in
let open Config in
let passes : ((unit -> bool) * (unit -> Js_traverse.mapper)) list =
[ (Flag.shortvar, fun () -> (new Js_traverse.rename_variable :> Js_traverse.mapper))
[ ( Flag.shortvar
, fun () -> (new Js_traverse.rename_variable ~esm:false :> Js_traverse.mapper) )
; (true_, fun () -> new Js_traverse.simpl)
; (true_, fun () -> new Js_traverse.clean)
]
Expand Down
2 changes: 1 addition & 1 deletion compiler/lib/driver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ if (typeof module === 'object' && module.exports) {
if Config.Flag.shortvar ()
then (
let t5 = Timer.make () in
let js = (new Js_traverse.rename_variable)#program js in
let js = (new Js_traverse.rename_variable ~esm:false)#program js in
if times () then Format.eprintf " shortten vars: %a@." Timer.print t5;
js)
else js
Expand Down
40 changes: 40 additions & 0 deletions compiler/lib/javascript.ml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ and statement =
| Throw_statement of expression
| Try_statement of block * (formal_parameter option * block) option * block option
| Debugger_statement
| Import of import * Parse_info.t
| Export of export * Parse_info.t

and ('left, 'right) either =
| Left of 'left
Expand Down Expand Up @@ -422,6 +424,44 @@ and function_body = statement_list

and program = statement_list

and export =
| ExportVar of variable_declaration_kind * variable_declaration list
| ExportFun of ident * function_declaration
| ExportClass of ident * class_declaration
| ExportNames of (ident * Utf8_string.t) list
(* default *)
| ExportDefaultFun of ident * function_declaration
| ExportDefaultClass of ident * class_declaration
| ExportDefaultExpression of expression
(* from *)
| ExportFrom of
{ kind : export_from_kind
; from : Utf8_string.t
}
| CoverExportFrom of early_error

and export_from_kind =
| Export_all of Utf8_string.t option
| Export_names of (Utf8_string.t * Utf8_string.t) list

and import =
{ from : Utf8_string.t
; kind : import_kind
}

and import_default = ident

and import_kind =
| Namespace of import_default option * ident
(* import * as name from "fname" *)
(* import defaultname, * as name from "fname" *)
| Named of import_default option * (Utf8_string.t * ident) list
(* import { 'a' as a, ...} from "fname" *)
(* import defaultname, { 'a' as a, ...} from "fname" *)
| Default of import_default
(* import defaultname from "fname" *)
| SideEffect (* import "fname" *)

and program_with_annots = (statement_list * (Js_token.Annot.t * Parse_info.t) list) list

let compare_ident t1 t2 =
Expand Down
40 changes: 40 additions & 0 deletions compiler/lib/javascript.mli
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ and statement =
| Throw_statement of expression
| Try_statement of block * (formal_parameter option * block) option * block option
| Debugger_statement
| Import of import * Parse_info.t
| Export of export * Parse_info.t

and ('left, 'right) either =
| Left of 'left
Expand Down Expand Up @@ -342,6 +344,44 @@ and function_body = statement_list

and program = statement_list

and export =
| ExportVar of variable_declaration_kind * variable_declaration list
| ExportFun of ident * function_declaration
| ExportClass of ident * class_declaration
| ExportNames of (ident * Utf8_string.t) list
(* default *)
| ExportDefaultFun of ident * function_declaration
| ExportDefaultClass of ident * class_declaration
| ExportDefaultExpression of expression
(* from *)
| ExportFrom of
{ kind : export_from_kind
; from : Utf8_string.t
}
| CoverExportFrom of early_error

and export_from_kind =
| Export_all of Utf8_string.t option
| Export_names of (Utf8_string.t * Utf8_string.t) list

and import =
{ from : Utf8_string.t
; kind : import_kind
}

and import_default = ident

and import_kind =
| Namespace of import_default option * ident
(* import * as name from "fname" *)
(* import defaultname, * as name from "fname" *)
| Named of import_default option * (Utf8_string.t * ident) list
(* import { 'a' as a, ...} from "fname" *)
(* import defaultname, { 'a' as a, ...} from "fname" *)
| Default of import_default
(* import defaultname from "fname" *)
| SideEffect (* import "fname" *)

and program_with_annots = (statement_list * (Js_token.Annot.t * Parse_info.t) list) list

val compare_ident : ident -> ident -> int
Expand Down
153 changes: 146 additions & 7 deletions compiler/lib/js_output.ml
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,9 @@ struct
| Try_statement _
| Function_declaration _
| Class_declaration _
| Debugger_statement -> false
| Debugger_statement
| Import _
| Export _ -> false

let starts_with ~obj ~funct ~let_identifier ~async_identifier l e =
let rec traverse l e =
Expand Down Expand Up @@ -368,6 +370,13 @@ struct
Buffer.add_char b quote;
PP.string f (Buffer.contents b)

let pp_string_lit f (Stdlib.Utf8_string.Utf8 s) =
let quote = best_string_quote s in
pp_string f ~quote s

let pp_ident_or_string_lit f (Stdlib.Utf8_string.Utf8 s_lit as s) =
if is_ident s_lit then PP.string f s_lit else pp_string_lit f s

let rec comma_list f f_elt l =
match l with
| [] -> ()
Expand Down Expand Up @@ -523,9 +532,7 @@ struct
then (
PP.string f ")";
PP.end_group f)
| EStr (Utf8 s) ->
let quote = best_string_quote s in
pp_string f ~quote s
| EStr x -> pp_string_lit f x
| ETemplate l -> template f l
| EBool b -> PP.string f (if b then "true" else "false")
| ENum num ->
Expand Down Expand Up @@ -833,9 +840,7 @@ struct
and property_name f n =
match n with
| PNI (Utf8 s) -> PP.string f s
| PNS (Utf8 s) ->
let quote = best_string_quote s in
pp_string f ~quote s
| PNS s -> pp_string_lit f s
| PNN v -> expression Expression f (ENum v)
| PComputed e ->
PP.string f "[";
Expand Down Expand Up @@ -1409,6 +1414,140 @@ struct
PP.string f "finally";
block f b);
PP.end_group f
| Import ({ kind; from }, _loc) ->
PP.start_group f 0;
PP.string f "import";
(match kind with
| SideEffect -> ()
| Default i ->
PP.space f;
ident f i
| Namespace (def, i) ->
Option.iter def ~f:(fun def ->
PP.space f;
ident f def;
PP.string f ",");
PP.space f;
PP.string f "* as ";
ident f i
| Named (def, l) ->
Option.iter def ~f:(fun def ->
PP.space f;
ident f def;
PP.string f ",");
PP.space f;
PP.string f "{";
PP.space f;
comma_list
f
(fun f (s, i) ->
if match i with
| S { name; _ } when Stdlib.Utf8_string.equal name s -> true
| _ -> false
then ident f i
else (
pp_ident_or_string_lit f s;
PP.string f " as ";
ident f i))
l;
PP.space f;
PP.string f "}");
(match kind with
| SideEffect -> ()
| _ ->
PP.space f;
PP.string f "from");
PP.space f;
pp_string_lit f from;
PP.string f ";";
PP.end_group f
| Export (e, _loc) ->
PP.start_group f 0;
PP.string f "export";
(match e with
| ExportNames l ->
PP.space f;
PP.string f "{";
PP.space f;
comma_list
f
(fun f (i, s) ->
if match i with
| S { name; _ } when Stdlib.Utf8_string.equal name s -> true
| _ -> false
then ident f i
else (
ident f i;
PP.string f " as ";
pp_ident_or_string_lit f s))
l;
PP.space f;
PP.string f "};"
| ExportFrom { kind; from } ->
PP.space f;
(match kind with
| Export_all None -> PP.string f "*"
| Export_all (Some s) ->
PP.string f "* as ";
pp_ident_or_string_lit f s
| Export_names l ->
PP.string f "{";
PP.space f;
comma_list
f
(fun f (a, b) ->
if Stdlib.Utf8_string.equal a b
then pp_ident_or_string_lit f a
else (
pp_ident_or_string_lit f a;
PP.string f " as ";
pp_ident_or_string_lit f b))
l;
PP.space f;
PP.string f "}");
PP.space f;
PP.string f "from";
PP.space f;
pp_string_lit f from;
PP.string f ";"
| ExportDefaultExpression ((EFun _ | EClass _) as e) ->
PP.space f;
PP.string f "default";
PP.space f;
expression Expression f e
| ExportDefaultExpression e ->
PP.space f;
PP.string f "default";
PP.space f;
parenthesized_expression
~last_semi
~obj:true
~funct:true
~let_identifier:true
Expression
f
e
| ExportDefaultFun (id, decl) ->
PP.space f;
PP.string f "default";
PP.space f;
statement f (Function_declaration (id, decl), loc)
| ExportDefaultClass (id, decl) ->
PP.space f;
PP.string f "default";
PP.space f;
statement f (Class_declaration (id, decl), loc)
| ExportFun (id, decl) ->
PP.space f;
statement f (Function_declaration (id, decl), loc)
| ExportClass (id, decl) ->
PP.space f;
statement f (Class_declaration (id, decl), loc)
| ExportVar (k, l) ->
PP.space f;
variable_declaration_list k (not can_omit_semi) f l
| CoverExportFrom e -> early_error e);
PP.end_group f
and statement_list f ?skip_last_semi b =
match b with
Expand Down
Loading

0 comments on commit 4c22226

Please sign in to comment.