Skip to content

Commit dfdfb78

Browse files
committed
GenType: fix issue with @as("0") and other numbers.
There is some special code in the type emitter to take care of poly variants of the form e.g. `#0`, which is represented internally as the string "0". This conflicts with normal variants annotated with `@as("0")` and such. This PR resolves the case of numeric poly variants early on, and removes the special casing in the code emitter. Fixes #6486
1 parent 182c6e8 commit dfdfb78

8 files changed

+80
-28
lines changed

jscomp/gentype/GenTypeCommon.ml

+16-17
Original file line numberDiff line numberDiff line change
@@ -38,30 +38,29 @@ let isJSSafePropertyName name =
3838
| 'A' .. 'z' | '0' .. '9' -> true
3939
| _ -> false)
4040

41+
let isNumber s =
42+
let len = String.length s in
43+
len > 0
44+
&& (match len > 1 with
45+
| true -> (s.[0] [@doesNotRaise]) > '0'
46+
| false -> true)
47+
&&
48+
let res = ref true in
49+
for i = 0 to len - 1 do
50+
match s.[i] [@doesNotRaise] with
51+
| '0' .. '9' -> ()
52+
| _ -> res := false
53+
done;
54+
res.contents
55+
4156
let labelJSToString case =
42-
let isNumber s =
43-
let len = String.length s in
44-
len > 0
45-
&& (match len > 1 with
46-
| true -> (s.[0] [@doesNotRaise]) > '0'
47-
| false -> true)
48-
&&
49-
let res = ref true in
50-
for i = 0 to len - 1 do
51-
match s.[i] [@doesNotRaise] with
52-
| '0' .. '9' -> ()
53-
| _ -> res := false
54-
done;
55-
res.contents
56-
in
5757
match case.labelJS with
5858
| NullLabel -> "null"
5959
| UndefinedLabel -> "undefined"
6060
| BoolLabel b -> b |> string_of_bool
6161
| FloatLabel s -> s
6262
| IntLabel i -> i
63-
| StringLabel s ->
64-
if s = case.label && isNumber s then s else s |> EmitText.quotes
63+
| StringLabel s -> s |> EmitText.quotes
6564

6665
type closedFlag = Open | Closed
6766

jscomp/gentype/TranslateCoreType.ml

+11-2
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ and translateCoreType_ ~config ~typeVarsGen
178178
if asString then
179179
match attributes |> Annotation.getAsString with
180180
| Some labelRenamed -> StringLabel labelRenamed
181-
| None -> StringLabel label
181+
| None ->
182+
if isNumber label then IntLabel label
183+
else StringLabel label
182184
else if asInt then (
183185
match attributes |> Annotation.getAsInt with
184186
| Some n ->
@@ -187,6 +189,7 @@ and translateCoreType_ ~config ~typeVarsGen
187189
| None ->
188190
lastBsInt := !lastBsInt + 1;
189191
IntLabel (string_of_int !lastBsInt))
192+
else if isNumber label then IntLabel label
190193
else StringLabel label
191194
in
192195
{label; labelJS})
@@ -202,7 +205,13 @@ and translateCoreType_ ~config ~typeVarsGen
202205
payloadsTranslations
203206
|> List.map (fun (label, _attributes, translation) ->
204207
{
205-
case = {label; labelJS = StringLabel label};
208+
case =
209+
{
210+
label;
211+
labelJS =
212+
(if isNumber label then IntLabel label
213+
else StringLabel label);
214+
};
206215
t = translation.type_;
207216
})
208217
in

jscomp/gentype/TranslateTypeDeclarations.ml

+15-6
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let createExportTypeFromTypeDeclaration ~annotation ~loc ~nameAs ~opaque ~type_
2121
annotation;
2222
}
2323

24-
let createCase (label, attributes) =
24+
let createCase (label, attributes) ~poly =
2525
{
2626
label;
2727
labelJS =
@@ -34,7 +34,8 @@ let createCase (label, attributes) =
3434
| Some (_, FloatPayload s) -> FloatLabel s
3535
| Some (_, IntPayload i) -> IntLabel i
3636
| Some (_, StringPayload asLabel) -> StringLabel asLabel
37-
| _ -> StringLabel label);
37+
| _ ->
38+
if poly && isNumber label then IntLabel label else StringLabel label);
3839
}
3940

4041
(**
@@ -190,7 +191,9 @@ let traslateDeclarationKind ~config ~loc ~outputFileRelative ~resolver
190191
match (coreType, translation.type_) with
191192
| {ctyp_desc = Ttyp_variant (rowFields, _, _)}, Variant variant ->
192193
let rowFieldsVariants = rowFields |> TranslateCoreType.processVariant in
193-
let noPayloads = rowFieldsVariants.noPayloads |> List.map createCase in
194+
let noPayloads =
195+
rowFieldsVariants.noPayloads |> List.map (createCase ~poly:true)
196+
in
194197
let payloads =
195198
if
196199
variant.payloads |> List.length
@@ -199,7 +202,7 @@ let traslateDeclarationKind ~config ~loc ~outputFileRelative ~resolver
199202
(List.combine variant.payloads rowFieldsVariants.payloads
200203
[@doesNotRaise])
201204
|> List.map (fun (payload, (label, attributes, _)) ->
202-
let case = (label, attributes) |> createCase in
205+
let case = (label, attributes) |> createCase ~poly:true in
203206
{payload with case})
204207
else variant.payloads
205208
in
@@ -277,7 +280,10 @@ let traslateDeclarationKind ~config ~loc ~outputFileRelative ~resolver
277280
variantsNoPayload
278281
|> List.map
279282
(fun (name, attributes, _argTypes, _importTypes, recordValue) ->
280-
{((name, attributes) |> createCase) with label = recordValue})
283+
{
284+
((name, attributes) |> createCase ~poly:false) with
285+
label = recordValue;
286+
})
281287
in
282288
let payloads =
283289
variantsWithPayload
@@ -290,7 +296,10 @@ let traslateDeclarationKind ~config ~loc ~outputFileRelative ~resolver
290296
in
291297
{
292298
case =
293-
{((name, attributes) |> createCase) with label = recordValue};
299+
{
300+
((name, attributes) |> createCase ~poly:false) with
301+
label = recordValue;
302+
};
294303
t = type_;
295304
})
296305
in

jscomp/gentype/TranslateTypeExprFromTypes.ml

+7-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,13 @@ and translateTypeExprFromTypes_ ~config ~typeVarsGen ~typeEnv
382382
| {noPayloads; payloads = []; unknowns = []} ->
383383
let noPayloads =
384384
noPayloads
385-
|> List.map (fun label -> {label; labelJS = StringLabel label})
385+
|> List.map (fun label ->
386+
{
387+
label;
388+
labelJS =
389+
(if isNumber label then IntLabel label
390+
else StringLabel label);
391+
})
386392
in
387393
let type_ =
388394
createVariant ~inherits:[] ~noPayloads ~payloads:[] ~polymorphic:true

jscomp/gentype_tests/typescript-react-example/package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/gentype_tests/typescript-react-example/src/Unboxed.bs.js

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/gentype_tests/typescript-react-example/src/Unboxed.gen.tsx

+8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ export type r2 = string;
1616

1717
export type t = number[] | number | ((_1:number) => number);
1818

19+
export type tabIndex = "0" | "1";
20+
1921
export const testV1: (x:v1) => v1 = UnboxedBS.testV1;
2022

2123
export const r2Test: (x:r2) => r2 = UnboxedBS.r2Test;
24+
25+
export const a: tabIndex = UnboxedBS.a;
26+
27+
export const b: tabIndex = UnboxedBS.b;
28+
29+
export const zero: 0 = UnboxedBS.zero;

jscomp/gentype_tests/typescript-react-example/src/Unboxed.res

+13-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,16 @@ type r2 = B({g: string})
1515
@genType let r2Test = (x: r2) => x
1616

1717
@genType @unboxed
18-
type t = Array(array<int>) | Record({x:int}) | Function((. int) => int)
18+
type t = Array(array<int>) | Record({x: int}) | Function((. int) => int)
19+
20+
@genType
21+
type tabIndex = | @as("0") Activity | @as("1") UserKeyword
22+
23+
@genType
24+
let a = Activity
25+
26+
@genType
27+
let b = UserKeyword
28+
29+
@genType
30+
let zero = #0

0 commit comments

Comments
 (0)