Skip to content
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
2 changes: 2 additions & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [JS/TS] Fix #4025: No reflection info for pojos (by @alfonsogarciacaro)
* [JS/TS] Fix #4049: decimal/bigint to integer conversion checks (by @ncave)
* [JS/TS] Fix `decimal` to `char` conversion checks (by @ManngelMaxime)
* [JS/TS] Propagate non-captured exception when running `Async.Start` or `Async.StartImmediate` (by @MangelMaxime)
* [JS/TS] Report an error at compilation time when trying to use `Async.RunSynchronously` (by @MangelMaxime)

## 5.0.0-alpha.10 - 2025-02-16

Expand Down
2 changes: 2 additions & 0 deletions src/Fable.Compiler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [JS/TS] Fix #4025: No reflection info for pojos (by @alfonsogarciacaro)
* [JS/TS] Fix #4049: decimal/bigint to integer conversion checks (by @ncave)
* [JS/TS] Fix `decimal` to `char` conversion checks (by @ManngelMaxime)
* [JS/TS] Propagate non-captured exception when running `Async.Start` or `Async.StartImmediate` (by @MangelMaxime)
* [JS/TS] Report an error at compilation time when trying to use `Async.RunSynchronously` (by @MangelMaxime)

## 5.0.0-alpha.10 - 2025-02-16

Expand Down
2 changes: 1 addition & 1 deletion src/Fable.Transforms/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3622,7 +3622,6 @@ let asyncBuilder (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Exp

let asyncs com (ctx: Context) r t (i: CallInfo) (_: Expr option) (args: Expr list) =
match i.CompiledName with
// TODO: Throw error for RunSynchronously
| "Start" ->
"Async.Start will behave as StartImmediate" |> addWarning com ctx.InlinePath r

Expand All @@ -3634,6 +3633,7 @@ let asyncs com (ctx: Context) r t (i: CallInfo) (_: Expr option) (args: Expr lis
| "Catch" ->
Helper.LibCall(com, "Async", "catchAsync", t, args, i.SignatureArgTypes, genArgs = i.GenericArgs, ?loc = r)
|> Some
| "RunSynchronously" -> None
// Fable.Core extensions
| meth ->
Helper.LibCall(
Expand Down
27 changes: 13 additions & 14 deletions src/fable-library-ts/Async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,14 @@ export function sleep(millisecondsDueTime: number) {
});
}

export function runSynchronously(): never {
throw new Error("Asynchronous code cannot be run synchronously in JS");
}

export function start<T>(computation: Async<T>, cancellationToken?: CancellationToken) {
return startWithContinuations(computation, cancellationToken);
return startWithContinuations(
computation,
emptyContinuation,
function (err) { throw err },
emptyContinuation,
cancellationToken
);
}

export function startImmediate<T>(computation: Async<T>, cancellationToken?: CancellationToken) {
Expand All @@ -173,19 +175,16 @@ export function startImmediate<T>(computation: Async<T>, cancellationToken?: Can

export function startWithContinuations<T>(
computation: Async<T>,
continuation?: Continuation<T> | CancellationToken,
exceptionContinuation?: Continuation<any>,
cancellationContinuation?: Continuation<any>,
continuation: Continuation<T>,
exceptionContinuation: Continuation<any>,
cancellationContinuation: Continuation<any>,
cancelToken?: CancellationToken) {
if (typeof continuation !== "function") {
cancelToken = continuation as CancellationToken;
continuation = undefined;
}

const trampoline = new Trampoline();
computation({
onSuccess: continuation ? continuation as Continuation<T> : emptyContinuation,
onError: exceptionContinuation ? exceptionContinuation : emptyContinuation,
onCancel: cancellationContinuation ? cancellationContinuation : emptyContinuation,
onError: exceptionContinuation,
onCancel: cancellationContinuation,
cancelToken: cancelToken ? cancelToken : defaultCancellationToken,
trampoline,
});
Expand Down
3 changes: 3 additions & 0 deletions src/fable-library-ts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* [JS/TS] Fix #4049: decimal/bigint to integer conversion checks (by @ncave)
* [JS/TS] Fix `decimal` to `char` conversion checks (by @ManngelMaxime)
* [JS/TS] Propagate non-captured exception when running `Async.Start` or `Async.StartImmediate` (by @MangelMaxime)
* [JS/TS] Remove `Async.RunSynchronously` (by @MangelMaxime)
* [JS/TS] Change signature of `startWithContinuations` to always require all its arguments (by @MangelMaxime)

## 2.0.0-beta.1 - 2025-02-16

Expand Down
13 changes: 11 additions & 2 deletions src/fcs-fable/src/Compiler/Service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3860,6 +3860,9 @@ type FSharpCheckProjectResults
|> Array.toSeq
#endif //!FABLE_COMPILER
| Choice2Of2 task ->
#if FABLE_COMPILER
seq {}
#else
Async.RunSynchronously(
async {
let! tcSymbolUses = task
Expand All @@ -3872,6 +3875,7 @@ type FSharpCheckProjectResults
},
?cancellationToken = cancellationToken
)
#endif //!FABLE_COMPILER

results
|> Seq.filter (fun symbolUse -> symbolUse.ItemOccurrence <> ItemOccurrence.RelatedText)
Expand All @@ -3890,7 +3894,7 @@ type FSharpCheckProjectResults

let cenv = SymbolEnv(tcGlobals, thisCcu, Some ccuSig, tcImports)

let tcSymbolUses =
let tcSymbolUses : TcSymbolUses seq =
match builderOrSymbolUses with
| Choice1Of2 builder ->
#if FABLE_COMPILER
Expand All @@ -3908,7 +3912,12 @@ type FSharpCheckProjectResults
| _ -> TcSymbolUses.Empty)
|> Array.toSeq
#endif //!FABLE_COMPILER
| Choice2Of2 tcSymbolUses -> Async.RunSynchronously(tcSymbolUses, ?cancellationToken = cancellationToken)
| Choice2Of2 tcSymbolUses ->
#if FABLE_COMPILER
seq {}
#else
Async.RunSynchronously(tcSymbolUses, ?cancellationToken = cancellationToken)
#endif //!FABLE_COMPILER

[|
for r in tcSymbolUses do
Expand Down
23 changes: 22 additions & 1 deletion tests/Js/Main/AsyncTests.fs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Fable.Tests.Async

open System
open Util
open Util.Testing

#if FABLE_COMPILER
Expand Down Expand Up @@ -72,6 +73,26 @@ let tests =
!result
f true + f false |> equal 22

testCase "Non captured exception in async is propagated when using Async.StartImmediate" <| fun () ->
throwsAnyError (fun _ ->
async {
failwith "boom!"
} |> Async.StartImmediate
)

#if FABLE_COMPILER
// Behaviour of Async.Start, is the same as Async.StartImmediate in JS
// We disable this test for .NET, because it seems like we can't capture the exception
// This should be fine, because Fable generate a warning about the Async.Start
// behaviour being the same as Async.StartImmediate
testCase "Non captured exception in async is propagated when using Async.Start" <| fun () ->
throwsAnyError (fun _ ->
async {
failwith "boom!"
} |> Async.Start
)
#endif

testCase "Simple async is executed correctly" <| fun () ->
let result = ref false
let x = async { return 99 }
Expand Down Expand Up @@ -596,4 +617,4 @@ let tests =
let! res = parentWorkflow()
equal 7 res
}
]
]
Loading