Author: ptw
Date: 2007-12-04 14:00:52 -0800 (Tue, 04 Dec 2007)
New Revision: 7445

Modified:
   openlaszlo/trunk/WEB-INF/lps/lfc/compiler/LzRuntime.lzs
   openlaszlo/trunk/WEB-INF/lps/lfc/debugger/LzMessage.lzs
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
   
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
Log:
Change 20071202-ptw-w by [EMAIL PROTECTED] on 2007-12-02 20:37:06 EST
    in /Users/ptw/OpenLaszlo/ringding-2
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: Debugger improvements to help me with diamond DHTML

Bugs Fixed:
LPP-5182 'We could give better backtraces for unhandled errors in DHTML'
LPP-5181 'new calls do not have correct line number in backtrace'

Technical Reviewer: [EMAIL PROTECTED] (Message-Id: <[EMAIL PROTECTED]>)
QA Reviewer: [EMAIL PROTECTED] (pending)

Details:
    LzMessage: Look for saved backtrace

    LzRuntime: Pass uncaught error backtrace to LzMessage

    JavascriptGenerator, CodeGenerator:  Break out call-site
    annotation, use in function calls and new calls

    JavascriptGenerator:  Put a catch block around all functions to
    record a backtrace if an exception is thrown and not caught.

Tests:
    smokecheck, test case from bugs



Modified: openlaszlo/trunk/WEB-INF/lps/lfc/compiler/LzRuntime.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/compiler/LzRuntime.lzs     2007-12-04 
20:05:52 UTC (rev 7444)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/compiler/LzRuntime.lzs     2007-12-04 
22:00:52 UTC (rev 7445)
@@ -105,6 +105,10 @@
     * @access private
     */
   Debug.backtraceStack.maxDepth = 100;
+  /** Backtrace for uncaught errors
+   * @access private
+   */
+  Debug.uncaughtBacktraceStack = null;
 
   /**
     * Doc'd on real definition
@@ -327,9 +331,18 @@
      * error handler
      */
     if (typeof window.addEventListener == 'function') {
-      // The DOM 1 interface is more useful than the DOM 2 interface.
+      // The DOM 1 interface is more useful than the DOM 2 interface
       window.onerror = function (errorString, fileName, lineNo) {
-#pragma "warnUndefinedReferences=false"
+        #pragma "warnUndefinedReferences=false"
+        if (Debug.uncaughtBacktraceStack) {
+          // If backtracing has caught our stack info, use that rather
+          // than browser info
+          errorString = new String(errorString);
+          errorString.$lzsc$b = Debug.uncaughtBacktraceStack;
+          Debug.uncaughtBacktraceStack = null;
+          fileName = null;
+          lineNo = null;
+        }
         $reportSourceWarning(fileName, lineNo, errorString, true);
         // pass through to browser debugger
         return false;

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/debugger/LzMessage.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/debugger/LzMessage.lzs     2007-12-04 
20:05:52 UTC (rev 7444)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/debugger/LzMessage.lzs     2007-12-04 
22:00:52 UTC (rev 7445)
@@ -264,25 +264,33 @@
 function LzSourceMessage (file, line, message) {
   switch (arguments.length) {
     case 0:
-    file = null;
+      file = null;
     case 1:
-    line = null;
+      line = null;
     case 2:
-    message = '';
+      message = '';
   }
   // Append a backtrace if there is one -- skip back to the
   // $reportSourceWarning or warnInternal frames.
   if ('backtraceStack' in Debug) {
-    var bts = Debug.backtraceStack;
-    var btsl = bts.length;
-    var skip = 3;
-    for (var i = btsl - 1; i > skip; i--) {
-      var callee = bts[i].callee;
-      if (callee === $reportSourceWarning ||
-          callee === Debug.warnInternal) {
-        // Skip the caller and the constructor frames too
-        skip = btsl - i + 3;
-        break;
+    var skip;
+    if ((message instanceof String) && ('$lzsc$b' in message)) {
+      // An uncaught error reported by the window.onerror handler will
+      // have a captured stack
+      Debug.backtraceStack = message.$lzsc$b;
+      skip = 2;
+    } else {
+      var bts = Debug.backtraceStack;
+      var btsl = bts.length;
+      skip = 3;
+      for (var i = btsl - 1; i > skip; i--) {
+        var callee = bts[i].callee;
+        if (callee === $reportSourceWarning ||
+            callee === Debug.warnInternal) {
+          // Skip the caller and the constructor frames too
+          skip = btsl - i + 3;
+          break;
+        }
       }
     }
     if (Debug.backtraceStack.length > skip) {

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java    
    2007-12-04 20:05:52 UTC (rev 7444)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java    
    2007-12-04 22:00:52 UTC (rev 7445)
@@ -1260,6 +1260,23 @@
     return translateReference(node).get().node;
   }
 
+  void noteCallSite (SimpleNode node) {
+      // Note current call-site in a function context and backtracing
+    if ((options.getBoolean(Compiler.DEBUG_BACKTRACE) && (node.beginLine != 
0)) &&
+        (context.findFunctionContext() != null)) {
+      Map registers = (Map)context.get(TranslationContext.REGISTERS);
+      // We know arguments register will exist if we are doing
+      // bactraces because it will be referenced in the function
+      // prefix.
+      if (registers != null && registers.containsKey("arguments")) {
+        
collector.push(Values.Register(((Instructions.Register)registers.get("arguments")).regno));
+        collector.push("lineno");
+        collector.push(node.beginLine);
+        collector.emit(Instructions.SetMember);
+      }
+    }
+  }
+
   public SimpleNode visitCallExpression(SimpleNode node, boolean isReferenced, 
SimpleNode[] children) {
     SimpleNode fnexpr = children[0];
     SimpleNode[] args = children[1].getChildren();
@@ -1430,21 +1447,7 @@
       }
     }
 
-    // Note current call-site in a function context and backtracing
-    if ((options.getBoolean(Compiler.DEBUG_BACKTRACE) && (node.beginLine != 
0)) &&
-        (context.findFunctionContext() != null)) {
-      Map registers = (Map)context.get(TranslationContext.REGISTERS);
-      // We know arguments register will exist if we are doing
-      // bactraces because it will be referenced in the function
-      // prefix.
-      if (registers != null && registers.containsKey("arguments")) {
-        
collector.push(Values.Register(((Instructions.Register)registers.get("arguments")).regno));
-        collector.push("lineno");
-        collector.push(node.beginLine);
-        collector.emit(Instructions.SetMember);
-      }
-    }
-
+    noteCallSite(node);
     // Okay, it is not going to be transformed.  Just do it!
     visitFunctionCallParameters(node, isReferenced, args);
     boolean isref = translateReferenceForCall(fnexpr, true, node);
@@ -1472,6 +1475,7 @@
   public SimpleNode visitNewExpression(SimpleNode node, boolean isReferenced, 
SimpleNode[] children) {
     SimpleNode ref = children[0];
     SimpleNode[] args = children[1].getChildren();
+    noteCallSite(node);
     visitFunctionCallParameters(node, isReferenced, args);
     boolean isref = translateReferenceForCall(ref, true, node);
     if (isref) {

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
  2007-12-04 20:05:52 UTC (rev 7444)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
  2007-12-04 22:00:52 UTC (rev 7445)
@@ -809,6 +809,18 @@
     return node;
   }
 
+  SimpleNode noteCallSite(SimpleNode node) {
+    // Note current call-site in a function context and backtracing
+    if ((options.getBoolean(Compiler.DEBUG_BACKTRACE) && (node.beginLine != 
0)) &&
+        (context.findFunctionContext() != null)) {
+      SimpleNode newNode = new ASTExpressionList(0);
+      newNode.set(0, (new Compiler.Parser()).parse("$lzsc$a.lineno = " + 
node.beginLine).get(0).get(0));
+      newNode.set(1, new Compiler.PassThroughNode(node));
+      return visitExpression(newNode);
+    }
+    return node;
+  }
+
   // Could do inline expansions here, like setAttribute
   public SimpleNode visitCallExpression(SimpleNode node, boolean isReferenced, 
SimpleNode[] children) {
     SimpleNode fnexpr = children[0];
@@ -901,15 +913,7 @@
 //     if (options.getBoolean(Compiler.WARN_UNDEFINED_REFERENCES)) {
 //       return makeCheckedNode(node);
 //     }
-    // Note current call-site in a function context and backtracing
-    if ((options.getBoolean(Compiler.DEBUG_BACKTRACE) && (node.beginLine != 
0)) &&
-        (context.findFunctionContext() != null)) {
-      SimpleNode newNode = new ASTExpressionList(0);
-      newNode.set(0, (new Compiler.Parser()).parse("$lzsc$a.lineno = " + 
node.beginLine).get(0).get(0));
-      newNode.set(1, new Compiler.PassThroughNode(node));
-      return visitExpression(newNode);
-    }
-    return node;
+    return noteCallSite(node);
   }
 
   public SimpleNode visitSuperCallExpression(SimpleNode node, boolean 
isReferenced, SimpleNode[] children) {
@@ -922,7 +926,7 @@
       SimpleNode child = children[i];
       children[i] = visitExpression(child, isReferenced);
     }
-    return node;
+    return noteCallSite(node);
   }
 
   public SimpleNode visitPrefixExpression(SimpleNode node, boolean 
isReferenced, SimpleNode[] children) {
@@ -1170,17 +1174,23 @@
       }
     }
     List prefix = new ArrayList();
+    List error = new ArrayList();
     List suffix = new ArrayList();
     if (options.getBoolean(Compiler.DEBUG_BACKTRACE)) {
       prefix.add(parseFragment(
-                   "var $lzsc$s = Debug['backtraceStack'];" +
+                   "var $lzsc$d = Debug, $lzsc$s = $lzsc$d.backtraceStack;" +
                    "if ($lzsc$s) {" +
                    "  var $lzsc$a = Array.prototype.slice.call(arguments, 0);" 
+
                    "  $lzsc$a.callee = arguments.callee;" +
                    "  $lzsc$a['this'] = this;" +
                    "  $lzsc$s.push($lzsc$a);" +
-                   "  if ($lzsc$s.length > $lzsc$s.maxDepth) 
{Debug.stackOverflow()};" +
+                   "  if ($lzsc$s.length > $lzsc$s.maxDepth) 
{$lzsc$d.stackOverflow()};" +
                    "}"));
+      error.add(parseFragment(
+                  "if ($lzsc$s && (! $lzsc$d.uncaughtBacktraceStack)) {" +
+                  "  $lzsc$d.uncaughtBacktraceStack = $lzsc$s.slice(0);" +
+                  "}" +
+                  "throw($lzsc$e);"));
       suffix.add(parseFragment(
                     "if ($lzsc$s) {" +
                     "  $lzsc$s.pop();" +
@@ -1378,16 +1388,27 @@
     // FIXME: (LPP-2075) [2006-05-19 ptw] Wrap body in try and make
     // suffix be a finally clause, so suffix will not be skipped by
     // inner returns.
-    if (! suffix.isEmpty()) {
+    if (! suffix.isEmpty() || ! error.isEmpty()) {
+      int i = 0;
       SimpleNode newStmts = new ASTStatementList(0);
       newStmts.setChildren((SimpleNode[])newBody.toArray(new SimpleNode[0]));
       SimpleNode tryNode = new ASTTryStatement(0);
-      tryNode.set(0, newStmts);
-      SimpleNode finallyNode = new ASTFinallyClause(0);
-      SimpleNode suffixStmts = new ASTStatementList(0);
-      suffixStmts.setChildren((SimpleNode[])suffix.toArray(new SimpleNode[0]));
-      finallyNode.set(0, suffixStmts);
-      tryNode.set(1, finallyNode);
+      tryNode.set(i++, newStmts);
+      if (! error.isEmpty()) {
+        SimpleNode catchNode = new ASTCatchClause(0);
+        SimpleNode catchStmts = new ASTStatementList(0);
+        catchStmts.setChildren((SimpleNode[])error.toArray(new SimpleNode[0]));
+        catchNode.set(0, new ASTIdentifier("$lzsc$e"));
+        catchNode.set(1, catchStmts);
+        tryNode.set(i++, catchNode);
+      }
+      if (! suffix.isEmpty()) {
+        SimpleNode finallyNode = new ASTFinallyClause(0);
+        SimpleNode suffixStmts = new ASTStatementList(0);
+        suffixStmts.setChildren((SimpleNode[])suffix.toArray(new 
SimpleNode[0]));
+        finallyNode.set(0, suffixStmts);
+        tryNode.set(i, finallyNode);
+      }
       newBody = new ArrayList();
       newBody.add(tryNode);
     }


_______________________________________________
Laszlo-checkins mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-checkins

Reply via email to