@@ -78,67 +78,51 @@ let semantic_string_of_payload (x : t) =
7878let quote_js_string semantic =
7979 " \" " ^ String_literal. encode_js_string semantic ^ " \" "
8080
81- let rec fixed_source_of_expression (expression : Parsetree.expression ) =
82- let map_all f values =
83- let rec loop acc = function
84- | [] -> Some (List. rev acc)
85- | value :: rest -> (
86- match f value with
87- | Some mapped -> loop (mapped :: acc) rest
88- | None -> None )
89- in
90- loop [] values
81+ (* Spell a ReScript integer literal as a JavaScript one. Underscore separators
82+ need ES2021, and a decimal literal with a leading zero is a legacy octal
83+ literal, which strict-mode JavaScript rejects. *)
84+ let js_integer_source source =
85+ let source = String. concat " " (String. split_on_char '_' source) in
86+ let sign, digits =
87+ if source <> " " && source.[0 ] = '-' then
88+ (" -" , String. sub source 1 (String. length source - 1 ))
89+ else (" " , source)
90+ in
91+ let length = String. length digits in
92+ let has_radix_prefix =
93+ length > 1
94+ && digits.[0 ] = '0'
95+ &&
96+ match digits.[1 ] with
97+ | 'x' | 'X' | 'o' | 'O' | 'b' | 'B' -> true
98+ | _ -> false
9199 in
100+ if has_radix_prefix then sign ^ digits
101+ else
102+ let rec first_significant i =
103+ if i < length - 1 && digits.[i] = '0' then first_significant (i + 1 )
104+ else i
105+ in
106+ let start = first_significant 0 in
107+ sign ^ String. sub digits start (length - start)
108+
109+ let fixed_source_of_expression (expression : Parsetree.expression ) =
92110 match (unwrap_braces expression).pexp_desc with
93111 | Pexp_constant (Pconst_string payload ) ->
94112 Some (quote_js_string (String_literal. string_semantic payload))
95113 | Pexp_template {source_segments = [{txt = source}]; values = [] } -> (
96114 match String_literal. decode_js_template_escapes source with
97115 | Some semantic -> Some (quote_js_string semantic)
98116 | None -> None )
99- | Pexp_constant (Pconst_integer (source , None)) -> Some source
100- | Pexp_constant (Pconst_integer (source , Some 'n' )) -> Some (source ^ " n" )
101- | Pexp_constant (Pconst_float (source , None)) -> Some source
117+ | Pexp_constant (Pconst_integer (source , None)) ->
118+ Some (js_integer_source source)
102119 | Pexp_tagged_template
103120 {
104121 tag = {pexp_desc = Pexp_ident {txt = Lident " json" }};
105122 raw_sources = [{txt = source}];
106123 values = [] ;
107124 } ->
108125 Some source
109- | Pexp_construct ({txt = Lident "true" } , {txt = [] } ) -> Some " true"
110- | Pexp_construct ({txt = Lident "false" } , {txt = [] } ) -> Some " false"
111- | Pexp_ident {txt = Lident "null" } -> Some " null"
112- | Pexp_ident {txt = Lident "undefined" } -> Some " undefined"
113- | Pexp_array values -> (
114- match map_all fixed_source_of_expression values with
115- | Some values -> Some (" [" ^ String. concat " ," values ^ " ]" )
116- | None -> None )
117- | Pexp_object_literal fields ->
118- let field_source
119- (({txt = name } , value ) : string Location. loc * Parsetree. expression ) =
120- match fixed_source_of_expression value with
121- | Some value -> Some (quote_js_string name ^ " :" ^ value)
122- | None -> None
123- in
124- begin match map_all field_source fields with
125- | Some fields -> Some (" {" ^ String. concat " ," fields ^ " }" )
126- | None -> None
127- end
128- | Pexp_record (fields , None) ->
129- let field_source
130- ({lid; x = value ; opt} : Parsetree.expression Parsetree.record_element )
131- =
132- if opt then None
133- else
134- match (lid.txt, fixed_source_of_expression value) with
135- | Lident name , Some value -> Some (quote_js_string name ^ " :" ^ value)
136- | Ldot _ , _ | _ , None -> None
137- in
138- begin match map_all field_source fields with
139- | Some fields -> Some (" {" ^ String. concat " ," fields ^ " }" )
140- | None -> None
141- end
142126 | _ -> None
143127
144128let fixed_source_of_payload (payload : t ) =
0 commit comments