Skip to content

Commit

Permalink
fix #994 try/catch in C# async
Browse files Browse the repository at this point in the history
  • Loading branch information
Jand42 committed Jul 30, 2018
1 parent bba9f8a commit 062fea3
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 19 deletions.
30 changes: 14 additions & 16 deletions src/compiler/WebSharper.Compiler.CSharp/Continuation.fs
Expand Up @@ -72,12 +72,9 @@ type AwaitTransformer() =
override this.TransformAwait(a) =
let awaited = Id.New "$await"
let doneLabel = Id.New "$done"
let isStarted = ItemGet(Var awaited, Value (String "status"), NoSideEffect)
let start = Call(Some (Var awaited), NonGeneric Definitions.Task, TaskMethod.Start, [])
let exc = ItemGet(Var awaited, Value (String "exc"), NoSideEffect)
Sequential [
NewVar(awaited, this.TransformExpression a)
Conditional (Unary(UnaryOperator.``!``, isStarted), start, Undefined)
IgnoredStatementExpr <| Continuation(doneLabel, Var awaited)
IgnoredStatementExpr <| Labeled(doneLabel, Empty)
IgnoredStatementExpr <| If (exc, Throw exc, Empty)
Expand Down Expand Up @@ -278,6 +275,7 @@ type ContinuationTransformer(labels) =
let stateVar = Id.New "$state"
let topLabel = Id.New "$top"
let localFunctions = ResizeArray()
let mutable tryScope = 0

// let mutable currentFinallyIndex = None
// let mutable hasFinally = false
Expand All @@ -302,6 +300,8 @@ type ContinuationTransformer(labels) =

member this.LocalFunctions = localFunctions :> _ seq

member this.TryScope = tryScope

override this.TransformGoto(a) =
gotoIndex labelLookup.[a]

Expand Down Expand Up @@ -341,11 +341,17 @@ type ContinuationTransformer(labels) =
addStatements i
| Labeled(_, TryWith(body, e, catch)) ->
multScope <| fun () ->
tryScope <- tryScope + 1
addStatements body
currentScope.Add (Catch (e, this.TransformStatement catch))
tryScope <- tryScope - 1
currentScope.Add (Catch (e, CombineStatements [ this.TransformStatement catch; gotoIndex (nextIndex + 1) ] ))
newState()
currentScope.Add (SingleState lastState)
| Labeled(_, TryFinally(body, final)) ->
multScope <| fun () ->
tryScope <- tryScope + 1
addStatements body
tryScope <- tryScope - 1
currentScope.Add (Finally (this.TransformStatement final))
| Labeled (_, ls) ->
newState()
Expand Down Expand Up @@ -477,12 +483,11 @@ type AsyncTransformer(labels, returns) =

let task = Id.New "$task"
let run = Id.New "$run"
let mutable tryScope = 0

override this.Yield(v) =
Block [
ExprStatement <| Call(Some v, NonGeneric Definitions.Task, TaskMethod.OnCompleted, [ Var run ])
Return (Value (Bool true))
Return Undefined
]

override this.TransformReturn(a) =
Expand All @@ -491,24 +496,17 @@ type AsyncTransformer(labels, returns) =
yield ExprStatement <| ItemSet(Var task, Value (String "result"), a)
yield ExprStatement <| ItemSet(Var task, Value (String "status"), Value (Int (int System.Threading.Tasks.TaskStatus.RanToCompletion)))
yield ExprStatement <| Call(Some (Var task), NonGeneric Definitions.Task, TaskMethod.RunContinuations, [])
yield Return (Value (Bool false))
yield Return Undefined
]

override this.TransformTryWith(body, e, catch) =
tryScope <- tryScope + 1
let trBody = this.TransformStatement body
tryScope <- tryScope - 1
let trCatch = this.TransformStatement catch
TryWith(trBody, e, trCatch)

override this.TransformThrow(a) =
if tryScope = 0 then
if this.TryScope = 0 then
Block [
if IgnoreExprSourcePos a <> Undefined then
yield ExprStatement <| ItemSet(Var task, Value (String "exc"), a)
yield ExprStatement <| ItemSet(Var task, Value (String "status"), Value (Int (int System.Threading.Tasks.TaskStatus.Faulted)))
yield ExprStatement <| Call(Some (Var task), NonGeneric Definitions.Task, TaskMethod.RunContinuations, [])
yield Return (Value (Bool false))
yield Return Undefined
]
else
Throw(a)
Expand Down
19 changes: 18 additions & 1 deletion src/compiler/WebSharper.Compiler/JavaScriptWriter.fs
Expand Up @@ -296,7 +296,24 @@ and private transformStatement (env: Environment) (statement: Statement) : J.Sta
| _ ->
res.Add(trS a)
s |> List.iter add
List.ofSeq res
let mutable skip = false
res |> Seq.filter (fun s ->
if skip then
match J.RemoveOuterStatementSourcePos s with
| J.Function _ | J.Vars _ ->
true
| J.Labelled _ ->
skip <- false
true
| _ ->
false
else
match J.RemoveOuterStatementSourcePos s with
| J.Return _ | J.Throw _ | J.Break _ | J.Continue _ ->
skip <- true
| _ -> ()
true
) |> List.ofSeq
let flattenS s =
match IgnoreStatementSourcePos s with
| Block s -> flatten s
Expand Down
5 changes: 3 additions & 2 deletions tests/WebSharper.CSharp.Tests/Remoting.cs
Expand Up @@ -343,15 +343,16 @@ public async Task AsyncTryCatch()
if (!ShouldRun) { Expect(0); return; }
var r = await AddOneAsyncSafe(1783);
Equal(r, 1784);
r = 0;
try
{
await TestServerFailure();
IsTrue(false, "Expected server error");
}
catch (Exception)
{
IsTrue(true, "Expected server error");
r = 1;
}
Equal(r, 1);
}
}
}

0 comments on commit 062fea3

Please sign in to comment.