Skip to content

Commit 48e4665

Browse files
committed
[JS/TS] add tests for nullness supports
[JS/TS] Add support for `Unchecked.nonNull`
1 parent e96be5a commit 48e4665

File tree

5 files changed

+111
-0
lines changed

5 files changed

+111
-0
lines changed

.fantomasignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
src/fcs-fable
22
tests/**
33
tests_external/**
4+
5+
!tests/Js/Main/Nullness.fs

src/Fable.Transforms/Replacements.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2979,6 +2979,7 @@ let unchecked (com: ICompiler) (ctx: Context) r t (i: CallInfo) (_: Expr option)
29792979
| "Hash", [ arg ] -> structuralHash com r arg |> Some
29802980
| "Equals", [ arg1; arg2 ] -> equals com ctx r true arg1 arg2 |> Some
29812981
| "Compare", [ arg1; arg2 ] -> compare com ctx r arg1 arg2 |> Some
2982+
| "NonNull", [ arg ] -> arg |> Some
29822983
| _ -> None
29832984

29842985
let enums (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr option) (args: Expr list) =

tests/Js/Main/Fable.Tests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
<Compile Include="TimeOnlyTests.fs" />
8282
<Compile Include="TimeSpanTests.fs" />
8383
<Compile Include="ListCollectorTests.fs" />
84+
<Compile Include="Nullness.fs" />
8485
<Compile Include="Main.fs" />
8586
</ItemGroup>
8687

tests/Js/Main/Nullness.fs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
module Fable.Tests.Nullness
2+
3+
open Util.Testing
4+
open Fable.Core.JsInterop
5+
6+
type ABNull =
7+
| A
8+
| B of (string | null)
9+
10+
let tests =
11+
testList
12+
"Nullness"
13+
[
14+
testCase
15+
"nullArgCheck"
16+
(fun () ->
17+
let ex =
18+
try
19+
nullArgCheck "arg" null
20+
with e ->
21+
e
22+
23+
equal "Value cannot be null. (Parameter 'arg')" ex.Message
24+
)
25+
26+
testCase "Null active pattern works"
27+
<| fun () ->
28+
let getLength abnull =
29+
match abnull with
30+
| A -> 0
31+
| B Null -> 0
32+
| B(NonNull s) -> s.Length // `s` is derived to be `string`
33+
34+
equal (getLength A) 0
35+
equal (getLength (B null)) 0
36+
37+
testCase "NonNull active pattern works"
38+
<| fun () ->
39+
let getLength abnull =
40+
match abnull with
41+
| A -> 0
42+
| B Null -> 0
43+
| B(NonNull s) -> s.Length // `s` is derived to be `string`
44+
45+
equal (getLength (B "hello")) 5
46+
47+
testCase "works with generics"
48+
<| fun _ ->
49+
// Generic code, note 'T must be constrained to be a reference type
50+
let findOrNull (index: int) (list: 'T list) : 'T | null when 'T: not struct =
51+
match List.tryItem index list with
52+
| Some item -> item
53+
| None -> null
54+
55+
equal (findOrNull 1 [ "a"; "b"; "c" ]) "b"
56+
equal (findOrNull 3 [ "a"; "b"; "c" ]) null
57+
58+
#if FABLE_COMPILER
59+
testCase "works for interop with undefined"
60+
<| fun () ->
61+
let maybeUndefined (value: string) : (string | null) = importMember "./js/nullness.js"
62+
63+
match maybeUndefined "ok" with
64+
| NonNull _ -> equal true true
65+
| Null -> equal true false
66+
67+
match maybeUndefined "foo" with
68+
| NonNull _ -> equal true false
69+
| Null -> equal true true
70+
71+
testCase "works for interop with null"
72+
<| fun () ->
73+
let maybeNull (value: string) : (string | null) = importMember "./js/nullness.js"
74+
75+
match maybeNull "ok" with
76+
| NonNull _ -> equal true true
77+
| Null -> equal true false
78+
79+
match maybeNull "foo" with
80+
| NonNull _ -> equal true false
81+
| Null -> equal true true
82+
#endif
83+
84+
testCase "Unchecked.nonNull works"
85+
<| fun () ->
86+
let toUpper (text: string | null) =
87+
(Unchecked.nonNull text).ToUpperInvariant()
88+
89+
equal (toUpper "hello") "HELLO"
90+
]

tests/Js/Main/js/nullness.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export function maybeUndefined(value) {
2+
if (value === "ok") {
3+
return value;
4+
}
5+
else {
6+
return undefined;
7+
}
8+
}
9+
10+
export function maybeNull(value) {
11+
if (value === "ok") {
12+
return value;
13+
}
14+
else {
15+
return null;
16+
}
17+
}

0 commit comments

Comments
 (0)