summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDominik Picheta <dominikpicheta@googlemail.com>2017-12-21 12:25:29 +0000
committerGitHub <noreply@github.com>2017-12-21 12:25:29 +0000
commit8c0e73479e0ec31fdda83751400f8b515e8e43d7 (patch)
tree2f9f0bcca290b5850f3ac9003666dba00343daa2
parente0e1241a54b8ad03ac45cdd56b845370a7e050f3 (diff)
parenteba544996d5629943dbf84c0eeedaf5b958d6363 (diff)
downloadNim-8c0e73479e0ec31fdda83751400f8b515e8e43d7.tar.gz
Merge pull request #6944 from alehander42/fix-discardable
Make asyncjs Future[void] play nicely with last line discardable calls & forward declaration
-rw-r--r--lib/js/asyncjs.nim43
-rw-r--r--tests/js/tasync.nim18
2 files changed, 49 insertions, 12 deletions
diff --git a/lib/js/asyncjs.nim b/lib/js/asyncjs.nim
index bde3d787f..ec410ee39 100644
--- a/lib/js/asyncjs.nim
+++ b/lib/js/asyncjs.nim
@@ -44,10 +44,10 @@
 ##         resolve(game)
 ##     return promise
 ##
-## Forward definitions work properly, you just don't need to add the ``{.async.}`` pragma:
+## Forward definitions work properly, you just need to always add the ``{.async.}`` pragma:
 ##
 ## .. code-block:: nim
-##   proc loadGame(name: string): Future[Game]
+##   proc loadGame(name: string): Future[Game] {.async.}
 ##
 ## JavaScript compatibility
 ## ~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -83,23 +83,54 @@ proc replaceReturn(node: var NimNode) =
       replaceReturn(son)
     inc z
 
+proc isFutureVoid(node: NimNode): bool =
+  result = node.kind == nnkBracketExpr and
+           node[0].kind == nnkIdent and $node[0] == "Future" and
+           node[1].kind == nnkIdent and $node[1] == "void"
+
 proc generateJsasync(arg: NimNode): NimNode =
   assert arg.kind == nnkProcDef
   result = arg
+  var isVoid = false
+  var jsResolveNode = ident("jsResolve")
+
   if arg.params[0].kind == nnkEmpty:
     result.params[0] = nnkBracketExpr.newTree(ident("Future"), ident("void"))
+    isVoid = true
+  elif isFutureVoid(arg.params[0]):
+    isVoid = true
+
   var code = result.body
   replaceReturn(code)
   result.body = nnkStmtList.newTree()
-  var q = quote:
-    proc await[T](f: Future[T]): T {.importcpp: "(await #)".}
-    proc jsResolve[T](a: T): Future[T] {.importcpp: "#".}
-  result.body.add(q)
+
+  if len(code) > 0:
+    var awaitFunction = quote:
+      proc await[T](f: Future[T]): T {.importcpp: "(await #)".}
+    result.body.add(awaitFunction)
+
+    var resolve: NimNode
+    if isVoid:
+      resolve = quote:
+        var `jsResolveNode` {.importcpp: "undefined".}: Future[void]
+    else:
+      resolve = quote:
+        proc jsResolve[T](a: T): Future[T] {.importcpp: "#".}
+    result.body.add(resolve)
+  else:
+    result.body = newEmptyNode()
   for child in code:
     result.body.add(child)
+
+  if len(code) > 0 and isVoid:
+    var voidFix = quote:
+      return `jsResolveNode`
+    result.body.add(voidFix)
+
   result.pragma = quote:
     {.codegenDecl: "async function $2($3)".}
 
+
 macro async*(arg: untyped): untyped =
   ## Macro which converts normal procedures into
   ## javascript-compatible async procedures
diff --git a/tests/js/tasync.nim b/tests/js/tasync.nim
index a164827d2..34ef97b8b 100644
--- a/tests/js/tasync.nim
+++ b/tests/js/tasync.nim
@@ -1,8 +1,8 @@
 discard """
   disabled: true
   output: '''
-0
 x
+e
 '''
 """
 
@@ -10,16 +10,22 @@ import asyncjs
 
 # demonstrate forward definition
 # for js
-proc y(e: int): Future[string]
+proc y(e: int): Future[string] {.async.}
 
-proc x(e: int) {.async.} =
+proc e: int {.discardable.} =
+  echo "e"
+  return 2
+
+proc x(e: int): Future[void] {.async.} =
   var s = await y(e)
   echo s
+  e()
 
 proc y(e: int): Future[string] {.async.} =
-  echo 0
-  return "x"
-
+  if e > 0:
+    return await y(0)
+  else:
+    return "x"
 
 
 discard x(2)