Skip to content

Commit 0322222

Browse files
authored
Merge pull request #660 from bloomberg/error_checking_external
Error checking external
2 parents 771c82f + 5e5c65c commit 0322222

File tree

9 files changed

+566
-443
lines changed

9 files changed

+566
-443
lines changed

jscomp/bin/bs_ppx.ml

Lines changed: 238 additions & 213 deletions
Large diffs are not rendered by default.

jscomp/bin/compiler.ml

Lines changed: 257 additions & 215 deletions
Large diffs are not rendered by default.

jscomp/lam_compile_external_call.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ let translate_ffi (ffi : Ast_external_attributes.ffi ) prim_name
251251

252252
let translate cxt
253253
({prim_name ; prim_native_name}
254-
: Ast_external_attributes.prim) args =
254+
: Primitive.description) args =
255255
if Ast_external_attributes.is_bs_external_prefix prim_native_name then
256256
begin
257257
match Ast_external_attributes.unsafe_from_string prim_native_name with

jscomp/syntax/ast_external_attributes.ml

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,49 @@ type ffi =
7070
| Js_get_index
7171
| Js_set_index
7272

73-
type prim = Primitive.description
73+
74+
75+
let valid_js_char =
76+
let a = Array.init 256 (fun i ->
77+
let c = Char.chr i in
78+
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c = '_' || c = '$'
79+
) in
80+
(fun c -> Array.unsafe_get a (Char.code c))
81+
82+
let valid_first_js_char =
83+
let a = Array.init 256 (fun i ->
84+
let c = Char.chr i in
85+
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c = '_' || c = '$'
86+
) in
87+
(fun c -> Array.unsafe_get a (Char.code c))
88+
89+
(** Approximation could be improved *)
90+
let valid_ident (s : string) =
91+
let len = String.length s in
92+
len > 0 && valid_js_char s.[0] && valid_first_js_char s.[0] &&
93+
(let module E = struct exception E end in
94+
try
95+
for i = 1 to len - 1 do
96+
if not (valid_js_char (String.unsafe_get s i)) then
97+
raise E.E
98+
done ;
99+
true
100+
with E.E -> false )
101+
102+
let valid_global_name ?loc txt =
103+
if not (valid_ident txt) then
104+
let v = Ext_string.split_by ~keep_empty:true (fun x -> x = '.') txt in
105+
List.iter
106+
(fun s ->
107+
if not (valid_ident s) then
108+
Location.raise_errorf ?loc "Not a valid name %s" txt
109+
) v
110+
111+
let valid_method_name ?loc txt =
112+
if not (valid_ident txt) then
113+
Location.raise_errorf ?loc "Not a valid name %s" txt
114+
115+
74116

75117
let check_external_module_name ?loc x =
76118
match x with
@@ -85,13 +127,12 @@ let check_external_module_name_opt ?loc x =
85127

86128
let check_ffi ?loc ffi =
87129
match ffi with
88-
| Js_global {txt = ""}
89-
| Js_send {name = ""}
90-
| Js_set ""
91-
| Js_get ""
92-
-> Location.raise_errorf ?loc "empty name encountered"
93-
| Js_global _ | Js_send _ | Js_set _ | Js_get _
94-
| Obj_create _
130+
| Js_global {txt} -> valid_global_name ?loc txt
131+
| Js_send {name }
132+
| Js_set name
133+
| Js_get name
134+
-> valid_method_name ?loc name
135+
| Obj_create _ -> ()
95136
| Js_get_index | Js_set_index
96137
-> ()
97138

@@ -101,10 +142,8 @@ let check_ffi ?loc ffi =
101142
| Js_new {external_module_name ; txt = name}
102143
| Js_call {external_module_name ; txt = {name ; _}}
103144
->
104-
check_external_module_name_opt ?loc external_module_name ;
105-
if name = "" then
106-
Location.raise_errorf ?loc "empty name in externals"
107-
145+
check_external_module_name_opt ?loc external_module_name ;
146+
valid_global_name ?loc name
108147

109148

110149
(**

jscomp/syntax/ast_external_attributes.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ type t =
7474
| Bs of arg_kind list * arg_type * ffi
7575
| Normal
7676

77-
type prim = Primitive.description
77+
7878

7979

8080

jscomp/test/.depend

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ gpr_459_test.cmj : mt.cmi
269269
gpr_459_test.cmx : mt.cmx
270270
gpr_627_test.cmj : mt.cmi
271271
gpr_627_test.cmx : mt.cmx
272+
gpr_658.cmj : ../runtime/js.cmj
273+
gpr_658.cmx : ../runtime/js.cmx
272274
guide_for_ext.cmj :
273275
guide_for_ext.cmx :
274276
hamming_test.cmj : ../stdlib/printf.cmi mt.cmi ../stdlib/lazy.cmi \
@@ -1041,6 +1043,8 @@ gpr_459_test.cmo : mt.cmi
10411043
gpr_459_test.cmj : mt.cmj
10421044
gpr_627_test.cmo : mt.cmi
10431045
gpr_627_test.cmj : mt.cmj
1046+
gpr_658.cmo : ../runtime/js.cmo
1047+
gpr_658.cmj : ../runtime/js.cmj
10441048
guide_for_ext.cmo :
10451049
guide_for_ext.cmj :
10461050
hamming_test.cmo : ../stdlib/printf.cmi mt.cmi ../stdlib/lazy.cmi \

jscomp/test/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ OTHERS := literals a test_ari test_export2 test_internalOO test_obj_simple_ffi t
6060
bs_rest_test infer_type_test fs_test module_as_function\
6161
test_case_set test_mutliple string_bound_get_test inline_string_test\
6262
ppx_this_obj_test unsafe_obj_external gpr_627_test jsoo_485_test jsoo_400_test \
63-
test_require more_uncurry earger_curry_test poly_type bench mutable_obj_test
63+
test_require more_uncurry earger_curry_test poly_type bench mutable_obj_test gpr_658
6464

6565

6666

jscomp/test/gpr_658.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
4+
5+
/* No side effect */

jscomp/test/gpr_658.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
3+
4+
(* external obj : < hi : int > Js.t = "{hi:1}" [@@bs.val] *)
5+
6+
external mk : hi:int -> unit -> < hi : int > Js.t = "" [@@bs.obj]
7+
8+
(* external set_name : < > -> string -> unit = "1name" [@@bs.set] *)

0 commit comments

Comments
 (0)