Skip to content
Draft
32 changes: 24 additions & 8 deletions compiler/bsb/bsb_package_specs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,23 @@ let from_json suffix (x : Ext_json_types.t) : Spec_set.t =
| Arr {content; _} -> from_array suffix content
| _ -> Spec_set.singleton (from_json_single suffix x)

let bs_package_output = "-bs-package-output"

[@@@warning "+9"]

let package_flag ({format; in_source; suffix} : Bsb_spec_set.spec) dir =
Ext_string.inter2 bs_package_output
(Ext_string.concat5 (string_of_format format) Ext_string.single_colon
(if in_source then dir else Bsb_config.top_prefix_of_format format // dir)
Ext_string.single_colon suffix)
let package_flag ({format; in_source; suffix} : Bsb_spec_set.spec) _dir =
(* Generates three separate compiler flags that were split from the original
single "-bs-package-output module:path:suffix" flag.

For in-source builds, pass "." as the base directory. The compiler will
extract the source subdirectory from output_prefix to construct the correct path.
For out-of-source builds, pass the lib output directory (e.g., "lib/es6").
*)
let module_system_flag = "-bs-module-system " ^ string_of_format format in
let suffix_flag = "-bs-suffix " ^ suffix in
let output_path =
if in_source then "." else Bsb_config.top_prefix_of_format format
in
let output_flag = "-bs-package-output " ^ output_path in
module_system_flag ^ " " ^ suffix_flag ^ " " ^ output_flag

(* FIXME: we should adapt it *)
let package_flag_of_package_specs (package_specs : t) ~(dirname : string) :
Expand Down Expand Up @@ -179,7 +187,15 @@ let get_list_of_output_js (package_specs : t)
Ext_namespace.change_ext_ns_suffix output_file_sans_extension
spec.suffix
in
(if spec.in_source then Bsb_config.rev_lib_bs_prefix basename
(if spec.in_source then
(* When dir=".", name_sans_extension can be "./Module" (from Filename.concat "." "Module").
Strip the "./" prefix to avoid generating "../.././Module.res.js" *)
let basename_clean =
if Ext_string.starts_with basename "./" then
String.sub basename 2 (String.length basename - 2)
else basename
in
Bsb_config.rev_lib_bs_prefix basename_clean
else Bsb_config.lib_bs_prefix_of_format spec.format // basename)
:: acc)
package_specs.modules []
Expand Down
17 changes: 15 additions & 2 deletions compiler/bsc/rescript_compiler_main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,23 @@ let command_line_flags : (string * Bsc_args.spec * string) array =
string_call ignore,
"*internal* Set jsx mode, this is no longer used and is a no-op." );
("-bs-jsx-preserve", set Js_config.jsx_preserve, "*internal* Preserve jsx");
( "-bs-module-system",
string_call (fun s ->
Js_config.default_module_system :=
match Js_packages_info.module_system_of_string s with
| Some ms -> ms
| None ->
Bsc_args.bad_arg
("Invalid module system: " ^ s
^ ". Use: commonjs, esmodule, or es6-global")),
"*internal* Set module system: commonjs, esmodule, es6-global" );
( "-bs-suffix",
string_call (fun s -> Js_config.default_suffix := s),
"*internal* Set import file suffix: .js, .mjs, .cjs" );
( "-bs-package-output",
string_call Js_packages_state.update_npm_package_path,
"*internal* Set npm-output-path: [opt_module]:path, for example: \
'lib/cjs', 'amdjs:lib/amdjs', 'es6:lib/es6' " );
"*internal* Set output path (when combined with -bs-module-system and \
-bs-suffix)" );
( "-bs-ast",
unit_call (fun _ ->
Js_config.binary_ast := true;
Expand Down
2 changes: 2 additions & 0 deletions compiler/common/js_config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ let jsx_version = ref None
let jsx_module = ref React
let jsx_preserve = ref false
let js_stdout = ref true
let default_module_system = ref Ext_module_system.Commonjs
let default_suffix = ref Literals.suffix_js
let all_module_aliases = ref false
let no_stdlib = ref false
let no_export = ref false
Expand Down
4 changes: 4 additions & 0 deletions compiler/common/js_config.mli
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ val jsx_preserve : bool ref

val js_stdout : bool ref

val default_module_system : Ext_module_system.t ref

val default_suffix : string ref

val all_module_aliases : bool ref

val no_stdlib : bool ref
Expand Down
333 changes: 317 additions & 16 deletions compiler/core/js_name_of_module_id.ml

Large diffs are not rendered by default.

12 changes: 10 additions & 2 deletions compiler/core/js_packages_info.ml
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,21 @@ let add_npm_package_path (packages_info : t) (s : string) : t =
in
let m =
match Ext_string.split ~keep_empty:true s ':' with
| [path] -> {module_system = Esmodule; path; suffix = Literals.suffix_js}
(* NEW: Just path - use configured module system and suffix *)
| [path] ->
{
module_system = !Js_config.default_module_system;
path;
suffix = !Js_config.default_suffix;
}
(* OLD: module_system:path - use configured suffix *)
| [module_system; path] ->
{
module_system = handle_module_system module_system;
path;
suffix = Literals.suffix_js;
suffix = !Js_config.default_suffix;
}
(* OLD: Full format - all explicit *)
| [module_system; path; suffix] ->
{module_system = handle_module_system module_system; path; suffix}
| _ -> Bsc_args.bad_arg ("invalid npm package path: " ^ s)
Expand Down
3 changes: 3 additions & 0 deletions compiler/core/js_packages_info.mli
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ val is_empty : t -> bool

val dump_packages_info : Format.formatter -> t -> unit

val module_system_of_string : string -> module_system option
(** Parse module system from string (commonjs, esmodule, es6, es6-global) *)

val add_npm_package_path : t -> string -> t
(** used by command line option
e.g [-bs-package-output commonjs:xx/path]
Expand Down
41 changes: 35 additions & 6 deletions compiler/core/lam_compile_main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ let lambda_as_module
: unit =
let package_info = Js_packages_state.get_packages_info () in
if Js_packages_info.is_empty package_info && !Js_config.js_stdout then begin
Js_dump_program.dump_deps_program ~output_prefix Commonjs (lambda_output) stdout
(* Use configured module system instead of hardcoded Commonjs *)
Js_dump_program.dump_deps_program ~output_prefix !Js_config.default_module_system (lambda_output) stdout
end else
Js_packages_info.iter package_info (fun {module_system; path; suffix} ->
let output_chan chan =
Expand All @@ -303,12 +304,40 @@ let lambda_as_module
let basename =
Ext_namespace.change_ext_ns_suffix (Filename.basename output_prefix) suffix
in
(* Construct target path:
- For bsb (path="."): extract source subdir from output_prefix
- For rewatch: path already contains full directory from file_path.parent()
- basename is the final filename *)
let target_file =
(Lazy.force Ext_path.package_dir //
path //
basename
(* #913 only generate little-case js file *)
) in
(* Check if path is a base output directory (bsb mode) vs full path (rewatch mode)
Use starts_with to handle both Unix (lib/es6) and Windows (lib\es6) paths *)
let is_base_path =
path = "." ||
Ext_string.starts_with path "lib" &&
(Ext_string.contain_substring path "bs" ||
Ext_string.contain_substring path "js" ||
Ext_string.contain_substring path "es6")
in
if is_base_path then
(* Legacy bsb mode: path is base dir, extract source subdir from output_prefix *)
let source_subdir = Filename.dirname output_prefix in
(* When source_subdir is ".", don't include it in the path to avoid "././" *)
if source_subdir = "." then
(Lazy.force Ext_path.package_dir //
path //
basename)
else
(Lazy.force Ext_path.package_dir //
path //
source_subdir //
basename)
else
(* Rewatch mode: path already contains full directory *)
(Lazy.force Ext_path.package_dir //
path //
basename
(* #913 only generate little-case js file *)
) in
(if not !Clflags.dont_write_files then
Ext_pervasives.with_file_as_chan
target_file output_chan );
Expand Down
3 changes: 2 additions & 1 deletion compiler/core/lam_compile_primitive.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ let get_module_system () =
let package_info = Js_packages_state.get_packages_info () in
let module_system =
if Js_packages_info.is_empty package_info && !Js_config.js_stdout then
[Ext_module_system.Commonjs]
(* Use configured module system instead of hardcoded Commonjs *)
[!Js_config.default_module_system]
else
Js_packages_info.map package_info (fun {module_system} -> module_system)
in
Expand Down
Loading
Loading