From 090fc336416b9f7f9ee54dd8991bf1760d81df50 Mon Sep 17 00:00:00 2001 From: yglukhov Date: Sat, 13 Jun 2015 18:49:29 +0300 Subject: [PATCH 1/3] Fixed and slightly changed exception handling. --- compiler/jsgen.nim | 29 +++++++++++++++++++---------- lib/system/jssys.nim | 29 ++++------------------------- 2 files changed, 23 insertions(+), 35 deletions(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index f6ec256d2..fd0e600b7 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -509,8 +509,8 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = # excHandler = sp; # try { # stmts; - # TMP = e - # } catch (e) { + # } catch (EXC) { + # var prevJSError = lastJSError; lastJSError = EXC; # if (e.typ && e.typ == NTI433 || e.typ == NTI2321) { # stmts; # } else if (e.typ && e.typ == NTI32342) { @@ -518,9 +518,9 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = # } else { # stmts; # } + # lastJSError = prevJSError; # } finally { # stmts; - # excHandler = excHandler.prev; # } genLineDir(p, n) if not isEmptyType(n.typ): @@ -529,7 +529,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = inc(p.unique) var safePoint = "Tmp$1" % [rope(p.unique)] addf(p.body, - "var $1 = {prev: excHandler, exc: null};$nexcHandler = $1;$n" | + "" | "local $1 = pcall(", [safePoint]) if optStackTrace in p.options: add(p.body, "framePtr = F;" & tnl) @@ -539,14 +539,17 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = gen(p, n.sons[0], a) moveInto(p, a, r) var i = 1 - if p.target == targetJS and length > 1 and n.sons[i].kind == nkExceptBranch: - addf(p.body, "} catch (EXC) {$n lastJSError = EXC;$n", []) + var generalCatchBranchExists = false + var catchBranchesExist = length > 1 and n.sons[i].kind == nkExceptBranch + if p.target == targetJS and catchBranchesExist: + addf(p.body, "} catch (EXC) {$n var prevJSError = lastJSError; lastJSError = EXC;$n", []) elif p.target == targetLua: addf(p.body, "end)$n", []) while i < length and n.sons[i].kind == nkExceptBranch: let blen = sonsLen(n.sons[i]) if blen == 1: # general except section: + generalCatchBranchExists = true if i > 1: addf(p.body, "else {$n" | "else$n", []) gen(p, n.sons[i].sons[0], a) moveInto(p, a, r) @@ -558,17 +561,22 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = if n.sons[i].sons[j].kind != nkType: internalError(n.info, "genTryStmt") if orExpr != nil: add(orExpr, "||" | " or ") - addf(orExpr, "isObj($1.exc.m_type, $2)", - [safePoint, genTypeInfo(p, n.sons[i].sons[j].typ)]) + addf(orExpr, "isObj(lastJSError.m_type, $1)", + [genTypeInfo(p, n.sons[i].sons[j].typ)]) if i > 1: add(p.body, "else ") - addf(p.body, "if ($1.exc && ($2)) {$n" | "if $1.exc and ($2) then$n", + addf(p.body, "if (lastJSError && ($2)) {$n" | "if $1.exc and ($2) then$n", [safePoint, orExpr]) gen(p, n.sons[i].sons[blen - 1], a) moveInto(p, a, r) addf(p.body, "}$n" | "end$n", []) inc(i) if p.target == targetJS: - add(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl) + if catchBranchesExist: + if not generalCatchBranchExists: + useMagic(p, "reraiseException") + add(p.body, "else { reraiseException(); }") + add(p.body, "lastJSError = prevJSError;" & tnl) + add(p.body, "} finally {" & tnl) if i < length and n.sons[i].kind == nkFinally: genStmt(p, n.sons[i].sons[0]) if p.target == targetJS: @@ -1067,6 +1075,7 @@ proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) = r.kind = resExpr proc genEcho(p: PProc, n: PNode, r: var TCompRes) = + useMagic(p, "toJSStr") # Used in rawEcho useMagic(p, "rawEcho") add(r.res, "rawEcho(") let n = n[1].skipConv diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index f082023ee..a6711a778 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -37,9 +37,6 @@ type var framePtr {.importc, nodecl, volatile.}: PCallFrame - excHandler {.importc, nodecl, volatile.}: PSafePoint = nil - # list of exception handlers - # a global variable for the root of all try blocks lastJSError {.importc, nodecl, volatile.}: PJSError = nil {.push stacktrace: off, profiler:off.} @@ -52,9 +49,7 @@ proc nimCharToStr(x: char): string {.compilerproc.} = result[0] = x proc getCurrentExceptionMsg*(): string = - if excHandler != nil and excHandler.exc != nil: - return $excHandler.exc.msg - elif lastJSError != nil: + if lastJSError != nil: return $lastJSError.message else: return "" @@ -102,29 +97,13 @@ proc rawWriteStackTrace(): string = proc raiseException(e: ref Exception, ename: cstring) {. compilerproc, asmNoStackFrame.} = e.name = ename - if excHandler != nil: - excHandler.exc = e - else: - when NimStackTrace: - var buf = rawWriteStackTrace() - else: - var buf = "" - if e.msg != nil and e.msg[0] != '\0': - add(buf, "Error: unhandled exception: ") - add(buf, e.msg) - else: - add(buf, "Error: unhandled exception") - add(buf, " [") - add(buf, ename) - add(buf, "]\n") - alert(buf) - asm """throw `e`;""" + asm "throw `e`;" proc reraiseException() {.compilerproc, asmNoStackFrame.} = - if excHandler == nil: + if lastJSError == nil: raise newException(ReraiseError, "no exception to reraise") else: - asm """throw excHandler.exc;""" + asm "throw lastJSError;" proc raiseOverflow {.exportc: "raiseOverflow", noreturn.} = raise newException(OverflowError, "over- or underflow") From fa1f3aecce3398f4d7afe69294ba9b3f928a66a2 Mon Sep 17 00:00:00 2001 From: yglukhov Date: Mon, 15 Jun 2015 23:08:38 +0300 Subject: [PATCH 2/3] Unhandled exceptions handling brought back. --- compiler/jsgen.nim | 19 +++++++++++-------- lib/system/jssys.nim | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index fd0e600b7..d84b0f2f9 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -505,12 +505,12 @@ proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) = proc genTry(p: PProc, n: PNode, r: var TCompRes) = # code to generate: # - # var sp = {prev: excHandler, exc: null}; - # excHandler = sp; + # ++excHandler; # try { # stmts; # } catch (EXC) { # var prevJSError = lastJSError; lastJSError = EXC; + # --excHandler; # if (e.typ && e.typ == NTI433 || e.typ == NTI2321) { # stmts; # } else if (e.typ && e.typ == NTI32342) { @@ -527,6 +527,11 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = r.kind = resVal r.res = getTemp(p) inc(p.unique) + var i = 1 + var length = sonsLen(n) + var catchBranchesExist = length > 1 and n.sons[i].kind == nkExceptBranch + if catchBranchesExist: + add(p.body, "++excHandler;" & tnl) var safePoint = "Tmp$1" % [rope(p.unique)] addf(p.body, "" | @@ -534,15 +539,13 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = [safePoint]) if optStackTrace in p.options: add(p.body, "framePtr = F;" & tnl) addf(p.body, "try {$n" | "function()$n", []) - var length = sonsLen(n) var a: TCompRes gen(p, n.sons[0], a) moveInto(p, a, r) - var i = 1 var generalCatchBranchExists = false - var catchBranchesExist = length > 1 and n.sons[i].kind == nkExceptBranch if p.target == targetJS and catchBranchesExist: - addf(p.body, "} catch (EXC) {$n var prevJSError = lastJSError; lastJSError = EXC;$n", []) + addf(p.body, "} catch (EXC) {$n var prevJSError = lastJSError;$n" & + " lastJSError = EXC;$n --excHandler;$n", []) elif p.target == targetLua: addf(p.body, "end)$n", []) while i < length and n.sons[i].kind == nkExceptBranch: @@ -574,7 +577,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = if catchBranchesExist: if not generalCatchBranchExists: useMagic(p, "reraiseException") - add(p.body, "else { reraiseException(); }") + add(p.body, "else {" & tnl & "reraiseException();" & tnl & "}" & tnl) add(p.body, "lastJSError = prevJSError;" & tnl) add(p.body, "} finally {" & tnl) if i < length and n.sons[i].kind == nkFinally: @@ -1685,7 +1688,7 @@ proc genHeader(): Rope = result = ("/* Generated by the Nim Compiler v$1 */$n" & "/* (c) 2015 Andreas Rumpf */$n$n" & "var framePtr = null;$n" & - "var excHandler = null;$n" & + "var excHandler = 0;$n" & "var lastJSError = null;$n") % [rope(VersionAsString)] diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index a6711a778..4d5ba1f73 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -37,6 +37,7 @@ type var framePtr {.importc, nodecl, volatile.}: PCallFrame + excHandler {.importc, nodecl, volatile.}: int = 0 lastJSError {.importc, nodecl, volatile.}: PJSError = nil {.push stacktrace: off, profiler:off.} @@ -94,15 +95,38 @@ proc rawWriteStackTrace(): string = else: result = "No stack traceback available\n" +proc unhandledException(e: ref Exception) {. + compilerproc, asmNoStackFrame.} = + when NimStackTrace: + var buf = rawWriteStackTrace() + else: + var buf = "" + if e.msg != nil and e.msg[0] != '\0': + add(buf, "Error: unhandled exception: ") + add(buf, e.msg) + else: + add(buf, "Error: unhandled exception") + add(buf, " [") + add(buf, e.name) + add(buf, "]\n") + alert(buf) + proc raiseException(e: ref Exception, ename: cstring) {. compilerproc, asmNoStackFrame.} = e.name = ename + if excHandler == 0: + unhandledException(e) asm "throw `e`;" proc reraiseException() {.compilerproc, asmNoStackFrame.} = if lastJSError == nil: raise newException(ReraiseError, "no exception to reraise") else: + if excHandler == 0: + var isNimException : bool + asm "`isNimException` = lastJSError.m_type;" + if isNimException: + unhandledException(cast[ref Exception](lastJSError)) asm "throw lastJSError;" proc raiseOverflow {.exportc: "raiseOverflow", noreturn.} = From ffa4f8dc997331f2005f19ab2fb9f34b433f9e16 Mon Sep 17 00:00:00 2001 From: yglukhov Date: Mon, 15 Jun 2015 23:30:09 +0300 Subject: [PATCH 3/3] Added noUnhandledHandler --- lib/system/jssys.nim | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 4d5ba1f73..5a9333a0e 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -114,19 +114,21 @@ proc unhandledException(e: ref Exception) {. proc raiseException(e: ref Exception, ename: cstring) {. compilerproc, asmNoStackFrame.} = e.name = ename - if excHandler == 0: - unhandledException(e) + when not defined(noUnhandledHandler): + if excHandler == 0: + unhandledException(e) asm "throw `e`;" proc reraiseException() {.compilerproc, asmNoStackFrame.} = if lastJSError == nil: raise newException(ReraiseError, "no exception to reraise") else: - if excHandler == 0: - var isNimException : bool - asm "`isNimException` = lastJSError.m_type;" - if isNimException: - unhandledException(cast[ref Exception](lastJSError)) + when not defined(noUnhandledHandler): + if excHandler == 0: + var isNimException : bool + asm "`isNimException` = lastJSError.m_type;" + if isNimException: + unhandledException(cast[ref Exception](lastJSError)) asm "throw lastJSError;" proc raiseOverflow {.exportc: "raiseOverflow", noreturn.} =