forked from rescript-lang/rescript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjs_program_loader.ml
210 lines (179 loc) · 8 KB
/
js_program_loader.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
(* Copyright (C) 2015-2016 Bloomberg Finance L.P.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition to the permissions granted to you by the LGPL, you may combine
* or link a "work that uses the Library" with a publicly distributed version
* of this file to produce a combined library or application, then distribute
* that combined work under the terms of your choosing, with no requirement
* to comply with the obligations normally placed on you by section 4 of the
* LGPL version 3 (or the corresponding section of a later version of the LGPL
* should you choose to use a later version).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
module E = Js_exp_make
module S = Js_stmt_make
(** Design guides:
1. We don't want to force user to have
[-bs-package-name] and [-bs-package-output] set
[bsc.exe -c hello.ml] should just work
by producing a [hello.js] file in the same directory
Some designs due to legacy reasons that we don't have all runtime
written in OCaml, so it might only have js files (no cmjs) for Runtime kind
{[
begin match Config_util.find file with
(* maybe from third party library*)
(* Check: be consistent when generating js files
A.ml -> a.js
a.ml -> a.js
check generated [js] file if it's capital or not
Actually, we can not tell its original name just from [id],
so we just always general litte_case.js
*)
| file ->
rebase (`File file)
(* for some primitive files, no cmj support *)
| exception Not_found ->
Ext_pervasives.failwithf ~loc:__LOC__
"@[%s not found in search path - while compiling %s @] "
file !Location.input_name
end
]}
*)
let (//) = Filename.concat
let string_of_module_id ~output_prefix
(module_system : Lam_module_ident.system)
(x : Lam_module_ident.t) : string =
#if BS_COMPILER_IN_BROWSER then
match x.kind with
| Runtime | Ml ->
"stdlib" // String.uncapitalize x.id.name
| External name -> name
#else
let result =
match x.kind with
| Runtime
| Ml ->
let id = x.id in
let modulename = String.uncapitalize id.name in
let js_file = Printf.sprintf "%s.js" modulename in
let rebase different_package package_dir dep =
let current_unit_dir =
`Dir (Js_config.get_output_dir ~pkg_dir:package_dir module_system output_prefix) in
Ext_filename.node_relative_path different_package current_unit_dir dep
in
let cmj_path, dependency_pkg_info =
Lam_compile_env.get_package_path_from_cmj module_system x
in
let current_pkg_info =
Js_config.get_current_package_name_and_path module_system
in
begin match module_system, dependency_pkg_info, current_pkg_info with
| _, NotFound , _ ->
Ext_pervasives.failwithf ~loc:__LOC__
" @[dependent module is not found while %s not in search path - compiling %s @] "
js_file !Location.input_name
| Goog, (Empty | Package_script _), _
->
Ext_pervasives.failwithf ~loc:__LOC__
" @[%s was not compiled with goog support in search path - while compiling %s @] "
js_file !Location.input_name
| (AmdJS | NodeJS | Es6 | Es6_global | AmdJS_global),
( Empty | Package_script _) ,
Found _ ->
Ext_pervasives.failwithf ~loc:__LOC__
"@[dependency %s was compiled in script mode - while compiling %s in package mode @]"
js_file !Location.input_name
| Goog , Found (package_name, x), _ ->
package_name ^ "." ^ String.uncapitalize id.name
| (AmdJS | NodeJS| Es6 | Es6_global|AmdJS_global),
(Empty | Package_script _ | Found _ ), NotFound -> assert false
| (AmdJS | NodeJS | Es6 | Es6_global|AmdJS_global),
Found(package_name, x),
Found(current_package, path) ->
if current_package = package_name then
let package_dir = Lazy.force Ext_filename.package_dir in
rebase false package_dir (`File (package_dir // x // modulename))
else
begin match module_system with
| AmdJS | NodeJS | Es6 ->
package_name // x // modulename
| Goog -> assert false (* see above *)
| Es6_global
| AmdJS_global ->
(** lib/ocaml/xx.cmj --
HACKING: FIXME
maybe we can caching relative package path calculation or employ package map *)
(* assert false *)
begin
Ext_filename.rel_normalized_absolute_path
(Js_config.get_output_dir ~pkg_dir:(Lazy.force Ext_filename.package_dir)
module_system output_prefix)
((Filename.dirname
(Filename.dirname (Filename.dirname cmj_path))) // x // modulename)
end
end
| (AmdJS | NodeJS | Es6 | AmdJS_global | Es6_global), Found(package_name, x),
Package_script(current_package)
->
if current_package = package_name then
let package_dir = Lazy.force Ext_filename.package_dir in
rebase false package_dir (`File (
package_dir // x // modulename))
else
package_name // x // modulename
| (AmdJS | NodeJS | Es6 | AmdJS_global | Es6_global),
Found(package_name, x), Empty
-> package_name // x // modulename
| (AmdJS | NodeJS | Es6 | AmdJS_global | Es6_global),
(Empty | Package_script _) ,
(Empty | Package_script _)
->
begin match Config_util.find_opt js_file with
| Some file ->
let package_dir = Lazy.force Ext_filename.package_dir in
rebase true package_dir (`File file)
| None ->
Bs_exception.error (Js_not_found js_file)
end
end
| External name -> name
(** This may not be enough,
1. For cross packages, we may need settle
down a single js package
2. We may need es6 path for dead code elimination
But frankly, very few JS packages have no dependency,
so having plugin may sound not that bad
*)
in
if Ext_sys.is_windows_or_cygwin then Ext_string.replace_backward_slash result
else result
#end
(* support es6 modules instead
TODO: enrich ast to support import export
http://www.ecma-international.org/ecma-262/6.0/#sec-imports
For every module, we need [Ident.t] for accessing and [filename] for import,
they are not necessarily the same.
Es6 modules is not the same with commonjs, we use commonjs currently
(play better with node)
FIXME: the module order matters?
*)
let make_program name export_idents block : J.program =
{
name;
exports = export_idents ;
export_set = Ident_set.of_list export_idents;
block = block;
}
let decorate_deps modules side_effect program : J.deps_program =
{ program ; modules ; side_effect }