Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #3847 #3852

Merged
merged 1 commit into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Fixed

* [JS/TS] Fixed unwrapping optional arguments (#3847) (by @ncave)

## 4.19.2 - 2024-06-13

### Fixed
Expand Down
8 changes: 4 additions & 4 deletions src/Fable.Transforms/Fable2Babel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1891,10 +1891,10 @@ module Util =

let args =
match paramsInfo with
| Some i when List.sameLength args i.Parameters ->
List.zip args i.Parameters
|> List.map (fun (a, i) ->
if i.IsOptional then
| Some info when args.Length <= info.Parameters.Length ->
List.zipSafe args info.Parameters
|> List.map (fun (a, p) ->
if p.IsOptional then
unwrapOptionalArg com a |> snd
else
a
Expand Down
2 changes: 1 addition & 1 deletion src/Fable.Transforms/Rust/AST/Rust.AST.Adapters.fs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ module fmt =
type Macros =
static member assert_eq(actual, expected) = assert (actual = expected)
static member assert_ne(actual, expected) = assert (actual <> expected)
static member unreachable() = failwith "should not happen"
static member unreachable() = failwith "unreachable!"
static member panic() = failwith "panic!"
static member panic(str: string) = failwith str

Expand Down
19 changes: 17 additions & 2 deletions src/Fable.Transforms/Rust/Fable2Rust.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,21 @@ module Util =
// let rest = List.rev rest |> List.map (fun e -> com.TransformExpr(ctx, e))
// rest @ [Expression.spreadElement(com.TransformExpr(ctx, last))]
| args ->
let optionalArgs =
if args.Length < parameters.Length then
parameters
|> List.skip args.Length
|> List.filter (fun p -> p.IsOptional)
|> List.map (fun p ->
match p.Type with
| Fable.Option(t, isStruct) -> Fable.Value(Fable.NewOption(None, t, isStruct), None)
| _ -> failwith "unreachable"
)
else
[]

let args = List.append args optionalArgs

let argsWithTypes =
if argTypes.Length = args.Length then
args |> List.zip argTypes |> List.map (fun (t, a) -> Some t, a)
Expand Down Expand Up @@ -2877,7 +2892,7 @@ module Util =
|> prepareRefForPatternMatch com ctx fableExpr.Type (tryGetIdentName fableExpr)

mkLetExpr pat expr
| _ -> failwith "Should not happen"
| _ -> failwith "unreachable"

let transformTest (com: IRustCompiler) ctx range kind (fableExpr: Fable.Expr) : Rust.Expr =
match kind with
Expand Down Expand Up @@ -2923,7 +2938,7 @@ module Util =
let thenExpr = mkBoolLitExpr true
let elseExpr = mkBoolLitExpr false
mkIfThenElseExpr guardExpr thenExpr elseExpr
| _ -> failwith "Should not happen"
| _ -> failwith "unreachable"

let transformSwitch (com: IRustCompiler) ctx (evalExpr: Fable.Expr) cases defaultCase targets : Rust.Expr =
let namesForIndex evalType evalName caseIndex = //todo refactor with below
Expand Down
8 changes: 3 additions & 5 deletions src/Fable.Transforms/Transforms.Util.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1265,11 +1265,9 @@ module AST =
| None -> args, []
| Some index when index > args.Length || index > info.Parameters.Length -> args, []
| Some index ->
let args, namedValues = List.splitAt index args

let namedKeys = List.skip index info.Parameters |> List.truncate namedValues.Length

args, List.zipSafe namedKeys namedValues
let args, namedArgs = List.splitAt index args
let namedParams = List.skip index info.Parameters |> List.truncate namedArgs.Length
args, List.zipSafe namedParams namedArgs

/// Used to compare arg idents of a lambda wrapping a function call
let argEquals (argIdents: Ident list) argExprs =
Expand Down
2 changes: 2 additions & 0 deletions tests/Dart/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import './src/SudokuTests.dart' as sudoku;
import './src/TailCallTests.dart' as tailcall;
import './src/TimeSpanTests.dart' as timespan;
import './src/TupleTests.dart' as tuple;
import './src/TypeTests.dart' as type_;
import './src/UnionTests.dart' as union;

void main() {
Expand Down Expand Up @@ -51,5 +52,6 @@ void main() {
tailcall.tests();
timespan.tests();
tuple.tests();
type_.tests();
union.tests();
}
1 change: 1 addition & 0 deletions tests/Dart/src/Fable.Tests.Dart.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<Compile Include="TailCallTests.fs" />
<Compile Include="TimeSpanTests.fs" />
<Compile Include="TupleTests.fs" />
<Compile Include="TypeTests.fs" />
<Compile Include="UnionTests.fs" />
<Content Include="..\main.dart" />
</ItemGroup>
Expand Down
22 changes: 22 additions & 0 deletions tests/Dart/src/RecordTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,28 @@ let tests() =
// x = {| y with Baz = 23 |} |> equal true // Doesn't compile
x = {| y with Bar = 14 |} |> equal false

testCase "Anonymous records can have optional fields" <| fun () ->
let add (o: {| bar: int option; zas: string option; foo: int option option |}) =
let bar = o.bar |> Option.map string |> Option.defaultValue "-"
let zas = defaultArg o.zas ""
let foo = match o.foo with Some(Some i) -> string i | Some None -> "xx" | None -> "x"
bar + zas + foo

{| bar = Some 3; zas = Some "ooooo"; foo = Some None |} |> add |> equal "3oooooxx"
{| bar = Some 22; zas = Some ""; foo = Some(Some 999) |} |> add |> equal "22999"
{| bar = None; zas = None; foo = None |} |> add |> equal "-x"
{| foo = Some None; bar = None; zas = None |} |> add |> equal "-xx"

testCase "Anonymous records can have optional function fields" <| fun () ->
let add (o: {| bar: (int -> int -> int) option; foo: int -> int -> int |}) =
let fn = o.bar
let f1 = fn |> Option.map (fun f -> f 6 9) |> Option.defaultValue -3
let f2 = match fn with Some f -> f 1 8 | None -> -5
o.foo 3 4 + f1 + f2

{| bar = Some (+); foo = (*) |} |> add |> equal 36
{| bar = None; foo = (+) |} |> add |> equal -1

testCase "SRTP works with anonymous records" <| fun () ->
let ar = [| {|Id=Id"foo"; Name="Sarah"|}; {|Id=Id"bar"; Name="James"|} |]
replaceById {|Id=Id"ja"; Name="Voll"|} ar |> Seq.head |> fun x -> equal "Sarah" x.Name
Expand Down
Loading
Loading