Skip to content

Commit e0c869a

Browse files
authored
Remove unsafe "j" interpolation (rescript-lang#6068)
* Deprecate unsafe ``` j`$(a)$(b)` ``` interpolation * Remove unsafe "j" string interpolation. * Update CHANGELOG.md * Convert printexec and arg to .res * Remove deprecated module `Printexc` * Update artifacts.txt * arg: use string interpolation * Convert caml_format_test to .res * Convert chn_test to .res * Convert gpr_3142 test to .res * Convert inline_const test to .res * Convert inline_const_test * Convert mario_game test to .res * Convert. sexp test to .res * artifacts * ninja: add pervasives for .res(i) files too * cleanup ninja
1 parent 9fb5a89 commit e0c869a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4059
-4295
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ subset of the arguments, and return a curried type with the remaining ones https
3636
Also, `(. int) => string => bool` is not equivalen to `(. int, string) => bool` anymore.
3737
These are only breaking changes for unformatted code.
3838
- Exponentiation operator `**` is now right-associative. `2. ** 3. ** 2.` now compile to `Math.pow(2, Math.pow(3, 2))` and not anymore `Math.pow(Math.pow(2, 3), 2)`. Parentheses can be used to change precedence.
39+
- Remove unsafe ``` j`$(a)$(b)` ``` interpolation deprecated in compiler version 10 https://github.com/rescript-lang/rescript-compiler/pull/6068
40+
- Remove deprecated module `Printexc`
3941

4042
#### :bug: Bug Fix
4143

@@ -79,6 +81,7 @@ These are only breaking changes for unformatted code.
7981

8082
- Better error message for extension point https://github.com/rescript-lang/rescript-compiler/pull/6057
8183
- Improve format check help https://github.com/rescript-lang/rescript-compiler/pull/6056
84+
- Deprecate unsafe ``` j`$(a)$(b)` ``` interpolation: use string templates ``` `${a}${b}` ``` instead https://github.com/rescript-lang/rescript-compiler/pull/6067
8285

8386
# 10.1.3
8487

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
We've found a bug for you!
3+
/.../fixtures/jinterp.res:3:10-21
4+
5+
1 │
6+
2 │ let a = 11
7+
3 │ let b = j`number $(a)`
8+
9+
The unsafe j`$(a)$(b)` interpolation was removed, use string template `${a}${b}` instead.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
let a = 11
3+
let b = j`number $(a)`

jscomp/frontend/ast_utf8_string_interp.ml

+7-120
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,6 @@ type cxt = {
6262

6363
type exn += Error of pos * pos * error
6464

65-
let pp_error fmt err =
66-
Format.pp_print_string fmt
67-
@@
68-
match err with
69-
| Invalid_code_point -> "Invalid code point"
70-
| Unterminated_backslash -> "\\ ended unexpectedly"
71-
| Invalid_escape_code c -> "Invalid escape code: " ^ String.make 1 c
72-
| Invalid_hex_escape -> "Invalid \\x escape"
73-
| Invalid_unicode_escape -> "Invalid \\u escape"
74-
| Unterminated_variable -> "$ unterminated"
75-
| Unmatched_paren -> "Unmatched paren"
76-
| Invalid_syntax_of_var s ->
77-
"`" ^ s ^ "' is not a valid syntax of interpolated identifer"
78-
7965
let valid_lead_identifier_char x =
8066
match x with 'a' .. 'z' | '_' -> true | _ -> false
8167

@@ -97,31 +83,6 @@ let valid_identifier s =
9783
| ' ' | '\n' | '\t' -> true
9884
| _ -> false *)
9985

100-
(**
101-
FIXME: multiple line offset
102-
if there is no line offset. Note {|{j||} border will never trigger a new line
103-
*)
104-
let update_position border ({ lnum; offset; byte_bol } : pos)
105-
(pos : Lexing.position) =
106-
if lnum = 0 then { pos with pos_cnum = pos.pos_cnum + border + offset }
107-
(* When no newline, the column number is [border + offset] *)
108-
else
109-
{
110-
pos with
111-
pos_lnum = pos.pos_lnum + lnum;
112-
pos_bol = pos.pos_cnum + border + byte_bol;
113-
pos_cnum =
114-
pos.pos_cnum + border + byte_bol + offset
115-
(* when newline, the column number is [offset] *);
116-
}
117-
118-
let update border (start : pos) (finish : pos) (loc : Location.t) : Location.t =
119-
let start_pos = loc.loc_start in
120-
{
121-
loc with
122-
loc_start = update_position border start start_pos;
123-
loc_end = update_position border finish start_pos;
124-
}
12586

12687
(** Note [Var] kind can not be mpty *)
12788
let empty_segment { content } = Ext_string.is_empty content
@@ -308,21 +269,6 @@ let transform_test s =
308269
check_and_transform 0 s 0 cxt;
309270
List.rev cxt.segments
310271

311-
(** TODO: test empty var $() $ failure,
312-
Allow identifers x.A.y *)
313-
314-
open Ast_helper
315-
316-
(** Longident.parse "Pervasives.^" *)
317-
let concat_ident : Longident.t = Ldot (Lident "Pervasives", "^")
318-
(* FIXME: remove deps on `Pervasives` *)
319-
320-
(* JS string concatMany *)
321-
(* Ldot (Ldot (Lident "Js", "String2"), "concat") *)
322-
323-
(* Longident.parse "Js.String.make" *)
324-
let to_string_ident : Longident.t = Ldot (Ldot (Lident "Js", "String2"), "make")
325-
326272
module Delim = struct
327273
let parse_processed = function
328274
| None -> Some External_arg_spec.DNone
@@ -332,102 +278,43 @@ module Delim = struct
332278

333279
type interpolation =
334280
| Js (* string interpolation *)
335-
| J (* old unsafe interpolation *)
336281
| Unrecognized (* no interpolation: delimiter not recognized *)
337-
let parse_unprocessed = function
282+
let parse_unprocessed loc = function
338283
| "js" -> Js
339-
| "j" -> J
284+
| "j" ->
285+
Location.raise_errorf ~loc
286+
"The unsafe j`$(a)$(b)` interpolation was removed, use string template `${a}${b}` instead."
340287
| _ -> Unrecognized
341288

342289
let escaped_j_delimiter = "*j" (* not user level syntax allowed *)
343-
let unescaped_j_delimiter = "j"
344290
let unescaped_js_delimiter = "js"
345291
let escaped = Some escaped_j_delimiter
346292
end
347293

348-
let border = String.length "{j|"
349-
350-
let aux loc (segment : segment) ~to_string_ident : Parsetree.expression =
351-
match segment with
352-
| { start; finish; kind; content } -> (
353-
match kind with
354-
| String ->
355-
let loc = update border start finish loc in
356-
Ast_compatible.const_exp_string content ?delimiter:Delim.escaped ~loc
357-
| Var (soffset, foffset) ->
358-
let loc =
359-
{
360-
loc with
361-
loc_start = update_position (soffset + border) start loc.loc_start;
362-
loc_end = update_position (foffset + border) finish loc.loc_start;
363-
}
364-
in
365-
Ast_compatible.apply_simple ~loc
366-
(Exp.ident ~loc { loc; txt = to_string_ident })
367-
[ Exp.ident ~loc { loc; txt = Lident content } ])
368-
369-
let concat_exp a_loc x ~(lhs : Parsetree.expression) : Parsetree.expression =
370-
let loc = Bs_loc.merge a_loc lhs.pexp_loc in
371-
Ast_compatible.apply_simple ~loc
372-
(Exp.ident { txt = concat_ident; loc })
373-
[ lhs; aux loc x ~to_string_ident:(Longident.Lident "__unsafe_cast") ]
374-
375-
(* Invariant: the [lhs] is always of type string *)
376-
let rec handle_segments loc (rev_segments : segment list) =
377-
match rev_segments with
378-
| [] -> Ast_compatible.const_exp_string ~loc "" ?delimiter:Delim.escaped
379-
| [ segment ] -> aux loc segment ~to_string_ident (* string literal *)
380-
| { content = "" } :: rest -> handle_segments loc rest
381-
| a :: rest -> concat_exp loc a ~lhs:(handle_segments loc rest)
382-
383-
let transform_interp loc s =
384-
let s_len = String.length s in
385-
let buf = Buffer.create (s_len * 2) in
386-
try
387-
let cxt : cxt =
388-
{
389-
segment_start = { lnum = 0; offset = 0; byte_bol = 0 };
390-
buf;
391-
s_len;
392-
segments = [];
393-
pos_lnum = 0;
394-
byte_bol = 0;
395-
pos_bol = 0;
396-
}
397-
in
398-
399-
check_and_transform 0 s 0 cxt;
400-
handle_segments loc cxt.segments
401-
with Error (start, pos, error) ->
402-
Location.raise_errorf ~loc:(update border start pos loc) "%a" pp_error error
403-
404294
let transform_exp (e : Parsetree.expression) s delim : Parsetree.expression =
405-
match Delim.parse_unprocessed delim with
295+
match Delim.parse_unprocessed e.pexp_loc delim with
406296
| Js ->
407297
let js_str = Ast_utf8_string.transform e.pexp_loc s in
408298
{
409299
e with
410300
pexp_desc = Pexp_constant (Pconst_string (js_str, Delim.escaped));
411301
}
412-
| J -> transform_interp e.pexp_loc s
413302
| Unrecognized -> e
414303

415304

416305
let transform_pat (p : Parsetree.pattern) s delim : Parsetree.pattern =
417-
match Delim.parse_unprocessed delim with
306+
match Delim.parse_unprocessed p.ppat_loc delim with
418307
| Js ->
419308
let js_str = Ast_utf8_string.transform p.ppat_loc s in
420309
{
421310
p with
422311
ppat_desc = Ppat_constant (Pconst_string (js_str, Delim.escaped));
423312
}
424-
| J (* No j interpolation on patterns *)
425313
| Unrecognized -> p
426314

427315
let is_unicode_string opt = Ext_string.equal opt Delim.escaped_j_delimiter
428316

429317
let is_unescaped s =
430-
Ext_string.equal s Delim.unescaped_j_delimiter
431-
|| Ext_string.equal s Delim.unescaped_js_delimiter
318+
Ext_string.equal s Delim.unescaped_js_delimiter
432319

433320
let parse_processed_delim = Delim.parse_processed

jscomp/ounit_tests/ounit_unicode_tests.ml

-76
Original file line numberDiff line numberDiff line change
@@ -243,80 +243,4 @@ let suites =
243243
0,2,0,3,String,")"
244244
]
245245
end;
246-
__LOC__ >:: begin fun _ ->
247-
match Ast_utf8_string_interp.transform_test {j| $( ()) |j}
248-
with
249-
|exception Ast_utf8_string_interp.Error
250-
({lnum = 0; offset = 1; byte_bol = 0},
251-
{lnum = 0; offset = 6; byte_bol = 0}, Invalid_syntax_of_var " (")
252-
-> OUnit.assert_bool __LOC__ true
253-
| _ -> OUnit.assert_bool __LOC__ false
254-
end
255-
;
256-
__LOC__ >:: begin fun _ ->
257-
match Ast_utf8_string_interp.transform_test {|$()|}
258-
with
259-
| exception Ast_utf8_string_interp.Error ({lnum = 0; offset = 0; byte_bol = 0},
260-
{lnum = 0; offset = 3; byte_bol = 0}, Invalid_syntax_of_var "")
261-
-> OUnit.assert_bool __LOC__ true
262-
| _ -> OUnit.assert_bool __LOC__ false
263-
end
264-
;
265-
__LOC__ >:: begin fun _ ->
266-
match Ast_utf8_string_interp.transform_test {|$ ()|}
267-
with
268-
| exception Ast_utf8_string_interp.Error
269-
({lnum = 0; offset = 0; byte_bol = 0},
270-
{lnum = 0; offset = 1; byte_bol = 0}, Invalid_syntax_of_var "")
271-
-> OUnit.assert_bool __LOC__ true
272-
| _ -> OUnit.assert_bool __LOC__ false
273-
end ;
274-
__LOC__ >:: begin fun _ ->
275-
match Ast_utf8_string_interp.transform_test {|$()|} with
276-
| exception Ast_utf8_string_interp.Error
277-
({lnum = 0; offset = 0; byte_bol = 0},
278-
{lnum = 0; offset = 3; byte_bol = 0}, Invalid_syntax_of_var "")
279-
-> OUnit.assert_bool __LOC__ true
280-
| _ -> OUnit.assert_bool __LOC__ false
281-
end
282-
;
283-
__LOC__ >:: begin fun _ ->
284-
match Ast_utf8_string_interp.transform_test {|$(hello world)|} with
285-
| exception Ast_utf8_string_interp.Error
286-
({lnum = 0; offset = 0; byte_bol = 0},
287-
{lnum = 0; offset = 14; byte_bol = 0}, Invalid_syntax_of_var "hello world")
288-
-> OUnit.assert_bool __LOC__ true
289-
| _ -> OUnit.assert_bool __LOC__ false
290-
end
291-
292-
293-
;
294-
__LOC__ >:: begin fun _ ->
295-
match Ast_utf8_string_interp.transform_test {|$( hi*) |} with
296-
| exception Ast_utf8_string_interp.Error
297-
({lnum = 0; offset = 0; byte_bol = 0},
298-
{lnum = 0; offset = 7; byte_bol = 0}, Invalid_syntax_of_var " hi*")
299-
->
300-
OUnit.assert_bool __LOC__ true
301-
| _ -> OUnit.assert_bool __LOC__ false
302-
end;
303-
__LOC__ >:: begin fun _ ->
304-
match Ast_utf8_string_interp.transform_test {|xx $|} with
305-
| exception Ast_utf8_string_interp.Error
306-
({lnum = 0; offset = 3; byte_bol = 0},
307-
{lnum = 0; offset = 3; byte_bol = 0}, Unterminated_variable)
308-
->
309-
OUnit.assert_bool __LOC__ true
310-
| _ -> OUnit.assert_bool __LOC__ false
311-
end ;
312-
313-
__LOC__ >:: begin fun _ ->
314-
match Ast_utf8_string_interp.transform_test {|$(world |}; with
315-
| exception Ast_utf8_string_interp.Error
316-
({lnum = 0; offset = 0; byte_bol = 0},
317-
{lnum = 0; offset = 9; byte_bol = 0}, Unmatched_paren)
318-
->
319-
OUnit.assert_bool __LOC__ true
320-
| _ -> OUnit.assert_bool __LOC__ false
321-
end
322246
]

0 commit comments

Comments
 (0)