Skip to content

Commit da07a1e

Browse files
samwgoldmanfacebook-github-bot
authored andcommitted
Use minimal prelude libdefs when no_flowlibs=true
Summary: Now that infer and merge are a single phase, we can rely on dependencies being always concrete. This means that we can lookup builtins with abandon -- and we should, too! In follow-up diffs, I will work to ensure that NumT, StrT, ArrT, ObjProtoT, etc. behave correctly with respect to their backing builtin instance types. In general, this means doing more lookups than we did before. When the no_flowlibs setting is enabled, all of these lookups would fail. Since our tests use this option, the situation is particularly hard to ignore. Instead of always using flowlibs (slow) and writing bespoke flowlibs for every test (painstaking), this diff ensures that Flow always uses a *minimal* set of libdefs, which I am calling the prelude. The prelude includes anything that Flow looks up by name (except some React specific stuff), including "Object" and "$Iterable", but nothing else. This is not intended to be usable. There's no Object.prototype.toString, for example. Reviewed By: avikchaudhuri Differential Revision: D5263399 fbshipit-source-id: 3f51af0414ffd468622625a984fcf15664305363
1 parent d4a23e3 commit da07a1e

8 files changed

Lines changed: 104 additions & 26 deletions

File tree

Makefile

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ OCP_BUILD_FILES=\
138138
COPIED_FLOWLIB=\
139139
$(foreach lib,$(wildcard lib/*.js),_build/$(lib))
140140

141+
COPIED_PRELUDE=\
142+
$(foreach lib,$(wildcard prelude/*.js),_build/$(lib))
143+
141144
JS_STUBS=\
142145
$(wildcard js/*.js)
143146

@@ -200,7 +203,7 @@ clean-ocp: clean
200203
[ -d _obuild ] && ocp-build clean || true
201204
rm -f $(OCP_BUILD_FILES)
202205

203-
build-flow: _build/scripts/ppx_gen_flowlibs.native $(BUILT_OBJECT_FILES) $(COPIED_FLOWLIB)
206+
build-flow: _build/scripts/ppx_gen_flowlibs.native $(BUILT_OBJECT_FILES) $(COPIED_FLOWLIB) $(COPIED_PRELUDE)
204207
ocamlbuild \
205208
-use-ocamlfind -pkgs sedlex \
206209
-no-links $(INCLUDE_OPTS) $(LIB_OPTS) \
@@ -215,6 +218,7 @@ build-flow-with-ocp: $(OCP_BUILD_FILES) hack/utils/get_build_id.gen.c
215218
[ -d _obuild ] || ocp-build init
216219
# Force us to pick up libdef changes - ocp-build is fast so it's fine
217220
rm -rf _obuild/flow-flowlib
221+
rm -rf _obuild/flow-prelude
218222
ocp-build build flow
219223
mkdir -p bin
220224
cp _obuild/flow/flow.asm$(EXE) bin/flow$(EXE)
@@ -230,7 +234,7 @@ test-parser-ocp: $(OCP_BUILD_FILES) hack/utils/get_build_id.gen.c
230234
ocp-build tests flow-parser-hardcoded-test
231235
rm -f $(OCP_BUILD_FILES)
232236

233-
build-flow-debug: _build/scripts/ppx_gen_flowlibs.native $(BUILT_OBJECT_FILES) $(COPIED_FLOWLIB)
237+
build-flow-debug: _build/scripts/ppx_gen_flowlibs.native $(BUILT_OBJECT_FILES) $(COPIED_FLOWLIB) $(COPIED_PRELUDE)
234238
ocamlbuild \
235239
-use-ocamlfind -pkgs sedlex \
236240
-no-links $(INCLUDE_OPTS) $(LIB_OPTS) \
@@ -262,6 +266,11 @@ $(COPIED_FLOWLIB): _build/%.js: %.js
262266
cp $< $@
263267
rm -rf _build/src/flowlib
264268

269+
$(COPIED_PRELUDE): _build/%.js: %.js
270+
mkdir -p $(dir $@)
271+
cp $< $@
272+
rm -rf _build/src/prelude
273+
265274
_build/scripts/ppx_gen_flowlibs.native: scripts/ppx_gen_flowlibs.ml
266275
ocamlbuild \
267276
-use-ocamlfind -pkgs sedlex,compiler-libs.common,unix \

_tags

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<hack/heap/*.ml*>: warn(-27-34)
33
<hack/third-party/core/result.ml>: warn(-41)
44
<hack/utils/*.ml*>: warn(-3-27)
5-
<src/flowlib/flowlib.ml>: ppx(scripts/ppx_gen_flowlibs.native lib/)
5+
<src/flowlib/flowlib.ml>: ppx(scripts/ppx_gen_flowlibs.native lib/ prelude/)
66
<src/parser/*.ml*>: warn(-39)
77
<**/node_modules/**>: -traverse
88
<_obuild>: -traverse

ocp_build_flow.ocp.fb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ begin library "flow-flowlib"
191191
"flow-ppx-gen-flowlib:asm"
192192
]
193193
comp = [
194-
"-ppx" "%{flow-ppx-gen-flowlib_FULL_DST_DIR}%/flow-ppx-gen-flowlib.asm lib/"
194+
"-ppx" "%{flow-ppx-gen-flowlib_FULL_DST_DIR}%/flow-ppx-gen-flowlib.asm lib/ prelude/"
195195
]
196196
end
197197

prelude/prelude.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
declare class Object {}
2+
3+
declare class Function {}
4+
5+
declare class Boolean {}
6+
7+
declare class Number {}
8+
9+
declare class String {
10+
@@iterator(): Iterator<string>;
11+
}
12+
13+
declare class RegExp {}
14+
15+
declare class $ReadOnlyArray<+T> {
16+
@@iterator(): Iterator<T>;
17+
}
18+
19+
declare class Array<T> extends $ReadOnlyArray<T> {}
20+
21+
// Promise
22+
23+
declare class Promise<+R> {}
24+
declare function $await<T>(p: Promise<T> | T): T;
25+
26+
// Iterable/Iterator/Generator
27+
28+
interface $Iterator<+Yield,+Return,-Next> {
29+
@@iterator(): $Iterator<Yield,Return,Next>;
30+
}
31+
interface $Iterable<+Yield,+Return,-Next> {
32+
@@iterator(): $Iterator<Yield,Return,Next>;
33+
}
34+
interface Generator<+Yield,+Return,-Next> {
35+
@@iterator(): $Iterator<Yield,Return,Next>;
36+
}
37+
38+
type Iterator<+T> = $Iterator<T,void,void>;
39+
type Iterable<+T> = $Iterable<T,void,void>;
40+
41+
declare function $iterate<T>(p: Iterable<T>): T;
42+
43+
// Async Iterable/Iterator/Generator
44+
45+
interface $AsyncIterator<+Yield,+Return,-Next> {
46+
@@asyncIterator(): $AsyncIterator<Yield,Return,Next>;
47+
}
48+
interface $AsyncIterable<+Yield,+Return,-Next> {
49+
@@asyncIterator(): $AsyncIterator<Yield,Return,Next>;
50+
}
51+
interface AsyncGenerator<+Yield,+Return,-Next> {
52+
@@asyncIterator(): $AsyncIterator<Yield,Return,Next>;
53+
}
54+
55+
type AsyncIterator<+T> = $AsyncIterator<T,void,void>;
56+
type AsyncIterable<+T> = $AsyncIterable<T,void,void>;
57+
58+
declare function $asyncIterator<T>(p: AsyncIterable<T>): T;

scripts/ppx_gen_flowlibs.ml

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ open Ast_mapper
1414
open Ast_helper
1515

1616
(* Read in all the flowlib files *)
17-
let get_flowlibs dir =
17+
let get_libs dir =
1818
Sys.readdir dir
1919
|> Array.fold_left (fun acc file ->
2020
let contents = Script_utils.string_of_file (Filename.concat dir file) in
@@ -23,22 +23,30 @@ let get_flowlibs dir =
2323

2424
(* Turn the (name, contents) list into a PPX ast (string * string) array
2525
* expression *)
26-
let contents =
27-
let flowlib_dir = Sys.argv.(1) in
28-
get_flowlibs flowlib_dir
26+
let contents lib_dir =
27+
get_libs lib_dir
2928
|> List.map (fun (name, contents) -> Exp.tuple [
3029
Exp.constant (Const.string name); Exp.constant (Const.string contents);
3130
])
3231
|> Exp.array
3332

3433
(* Whenever we see [%flowlib_contents], replace it wil the flowlib contents *)
35-
let ppx_gen_flowlibs_mapper _argv =
36-
{ default_mapper with
37-
expr = fun mapper expr ->
38-
match expr with
39-
| { pexp_desc = Pexp_extension ({ txt = "flowlib_contents"; _ }, PStr []); _} ->
40-
contents
41-
| other -> default_mapper.expr mapper other; }
34+
let ppx_gen_flowlibs_mapper argv =
35+
let flowlib_contents, prelude_contents =
36+
match argv with
37+
| [flowlib_dir; prelude_dir] -> contents flowlib_dir, contents prelude_dir
38+
| _ ->
39+
failwith
40+
(Printf.sprintf "Expected two arguments, got %d." (List.length argv))
41+
in
42+
{ default_mapper with
43+
expr = fun mapper expr ->
44+
match expr with
45+
| { pexp_desc = Pexp_extension ({ txt = "flowlib_contents"; _ }, PStr []); _} ->
46+
flowlib_contents
47+
| { pexp_desc = Pexp_extension ({ txt = "prelude_contents"; _ }, PStr []); _} ->
48+
prelude_contents
49+
| other -> default_mapper.expr mapper other; }
4250

43-
let () =
44-
register "ppx_gen_flowlibs" ppx_gen_flowlibs_mapper
51+
let () =
52+
register "ppx_gen_flowlibs" ppx_gen_flowlibs_mapper

src/commands/commandUtils.ml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,10 +299,10 @@ let collect_flowconfig_flags main ignores_str includes_str lib_str lints_str =
299299
main { ignores; includes; libs; raw_lint_severities; }
300300

301301
let file_options =
302-
let default_lib_dir tmp_dir =
302+
let default_lib_dir ~no_flowlib tmp_dir =
303303
let root = Path.make (Tmp.temp_dir tmp_dir "flowlib") in
304304
try
305-
Flowlib.extract_flowlib root;
305+
Flowlib.extract_flowlib ~no_flowlib root;
306306
root
307307
with _ ->
308308
let msg = "Could not locate flowlib files" in
@@ -352,9 +352,9 @@ let file_options =
352352
in
353353
fun ~root ~no_flowlib ~temp_dir ~includes ~ignores ~libs flowconfig ->
354354
let default_lib_dir =
355-
if no_flowlib || FlowConfig.no_flowlib flowconfig
356-
then None
357-
else Some (default_lib_dir temp_dir) in
355+
let no_flowlib = no_flowlib || FlowConfig.no_flowlib flowconfig in
356+
Some (default_lib_dir ~no_flowlib temp_dir)
357+
in
358358
let ignores = ignores_of_arg
359359
root
360360
(FlowConfig.ignores flowconfig)

src/flowlib/flowlib.ml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
*
99
*)
1010

11-
let contents = [%flowlib_contents]
11+
let contents no_flowlib =
12+
if no_flowlib
13+
then [%prelude_contents]
14+
else [%flowlib_contents]
1215

1316
let write_flowlib dir (filename, contents) =
1417
let file = Path.(concat dir filename |> to_string) in
1518
Sys_utils.write_file ~file contents
1619

17-
let extract_flowlib dir =
18-
Array.iter (write_flowlib dir) contents
20+
let extract_flowlib ~no_flowlib dir =
21+
Array.iter (write_flowlib dir) (contents no_flowlib)

src/flowlib/flowlib.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
*
99
*)
1010

11-
val extract_flowlib : Path.t -> unit
11+
val extract_flowlib : no_flowlib:bool -> Path.t -> unit

0 commit comments

Comments
 (0)