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