Makes some change to Collector for further refactoring - Finally gets rid of explicit inferFrom API in Collectors - Introduces CollectorModern as a base for CollectorMoz and CollectorChrome - CollectorChrome no longer extends CollectorMoz Change-Id: I496c2358180662e54ff50cd2a5c08b29f505e314
diff --git a/user/src/com/google/gwt/core/client/impl/StackTraceCreator.java b/user/src/com/google/gwt/core/client/impl/StackTraceCreator.java index 9384bbd..757413b 100644 --- a/user/src/com/google/gwt/core/client/impl/StackTraceCreator.java +++ b/user/src/com/google/gwt/core/client/impl/StackTraceCreator.java
@@ -57,22 +57,7 @@ public abstract JavaScriptObject collect(); - protected StackTraceElement[] getStackTrace(JsArrayString stack) { - if (stack.length() == 0) { - return null; - } - int length = stack.length(); - StackTraceElement[] stackTrace = new StackTraceElement[length]; - for (int i = 0; i < length; i++) { - stackTrace[i] = new StackTraceElement(UNKNOWN, stack.get(i), null, LINE_NUMBER_UNKNOWN); - } - return stackTrace; - } - - /** - * Attempt to infer the stack from an unknown JavaScriptObject that had been thrown. - */ - public abstract JsArrayString inferFrom(JavaScriptObject e); + public abstract StackTraceElement[] getStackTrace(JavaScriptObject stackInfo); } /** @@ -113,8 +98,9 @@ }-*/; @Override - public JsArrayString inferFrom(JavaScriptObject e) { - return getFnStack(e); + public StackTraceElement[] getStackTrace(JavaScriptObject stackInfo) { + JsArrayString stack = getFnStack(stackInfo); + return fnStacktoSte(stack); } } @@ -138,14 +124,8 @@ }-*/; @Override - public JsArrayString inferFrom(JavaScriptObject e) { - return getFnStack(e); - } - - @Override - protected StackTraceElement[] getStackTrace(JsArrayString st) { - JsArray<JsArrayString> stack = st.cast(); - + public StackTraceElement[] getStackTrace(JavaScriptObject stackInfo) { + JsArray<JsArrayString> stack = getFnStack(stackInfo).cast(); if (stack.length() == 0) { return null; } @@ -173,13 +153,10 @@ } /** - * Mozilla provides a <code>stack</code> property in thrown objects. + * Modern browsers provide a <code>stack</code> property in thrown objects. */ - static class CollectorMoz extends Collector { - /** - * This implementation doesn't suffer from the limitations of crawling - * <code>caller</code> since Mozilla provides proper activation records. - */ + abstract static class CollectorModern extends Collector { + @Override public JavaScriptObject collect() { return makeException(); @@ -195,24 +172,28 @@ return e; } }-*/; + } + + static class CollectorMoz extends CollectorModern { @Override - public JsArrayString inferFrom(JavaScriptObject e) { - JsArrayString stack = getStack(e); + public StackTraceElement[] getStackTrace(JavaScriptObject stackInfo) { + JsArrayString stack = inferFrom(stackInfo); + return fnStacktoSte(stack); + } + + private JsArrayString inferFrom(JavaScriptObject e) { + JsArrayString stack = split(e); for (int i = 0, j = stack.length(); i < j; i++) { stack.set(i, extractName(stack.get(i))); } return stack; } - private native JsArrayString getStack(JavaScriptObject e) /*-{ - return (e && e.stack) ? e.stack.split('\n') : []; - }-*/; - /** * Extract the name of a function from it's toString() representation. */ - protected String extractName(String fnToString) { + private String extractName(String fnToString) { String toReturn = ""; fnToString = fnToString.trim(); int index = fnToString.indexOf("("); @@ -250,7 +231,7 @@ * at Type.functionName [as methodName] (file.js:1:2) * </pre> */ - static class CollectorChrome extends CollectorMoz { + static class CollectorChrome extends CollectorModern { static { increaseChromeStackTraceLimit(); @@ -262,9 +243,12 @@ Error.stackTraceLimit = 128; }-*/; - @Override - public JsArrayString inferFrom(JavaScriptObject e) { - JsArrayString stack = super.inferFrom(e); + private JsArrayString inferFrom(JavaScriptObject stackInfo) { + JsArrayString stack = split(stackInfo); + for (int i = 0, j = stack.length(); i < j; i++) { + stack.set(i, extractName(stack.get(i))); + } + if (stack.length() > 0 && stack.get(0).startsWith(ANONYMOUS + "@@")) { // Chrome contains the error itself as the first line of the stack (iOS doesn't). stack = splice(stack, 1); @@ -272,8 +256,7 @@ return stack; } - @Override - protected String extractName(String fnToString) { + private String extractName(String fnToString) { String extractedName = ANONYMOUS; String location = ""; @@ -326,7 +309,9 @@ } @Override - protected StackTraceElement[] getStackTrace(JsArrayString stack) { + public StackTraceElement[] getStackTrace(JavaScriptObject stackInfo) { + JsArrayString stack = inferFrom(stackInfo); + int length = stack.length(); if (length == 0) { return null; @@ -383,13 +368,8 @@ } @Override - protected StackTraceElement[] getStackTrace(JsArrayString stack) { - return null; - } - - @Override - public JsArrayString inferFrom(JavaScriptObject e) { - return null; + public StackTraceElement[] getStackTrace(JavaScriptObject stackInfo) { + return new StackTraceElement[0]; } } @@ -411,8 +391,7 @@ private static void constructStackTrace(Throwable t, Object thrown, boolean strip) { JavaScriptObject e = (thrown instanceof JavaScriptObject) ? (JavaScriptObject) thrown : null; - JsArrayString stack = collector.inferFrom(e); - StackTraceElement[] stackTrace = collector.getStackTrace(stack); + StackTraceElement[] stackTrace = collector.getStackTrace(e); if (stackTrace != null) { if (strip) { stackTrace = dropInternalFrames(stackTrace); @@ -447,6 +426,18 @@ return "stack" in new Error; // Checked via 'in' to avoid execution of stack getter in Chrome }-*/; + private static StackTraceElement[] fnStacktoSte(JsArrayString stack) { + int length = stack.length(); + if (length == 0) { + return null; + } + StackTraceElement[] stackTrace = new StackTraceElement[length]; + for (int i = 0; i < length; i++) { + stackTrace[i] = new StackTraceElement(UNKNOWN, stack.get(i), null, LINE_NUMBER_UNKNOWN); + } + return stackTrace; + } + private static native JsArrayString getFnStack(JavaScriptObject e) /*-{ return (e && e.fnStack && e.fnStack instanceof Array) ? e.fnStack : []; }-*/; @@ -455,12 +446,17 @@ return fn.name || (fn.name = @StackTraceCreator::extractFunctionName(*)(fn.toString())); }-*/; + // Visible for testing static native String extractFunctionName(String fnName) /*-{ var fnRE = /function(?:\s+([\w$]+))?\s*\(/; var match = fnRE.exec(fnName); return (match && match[1]) || @StackTraceCreator::ANONYMOUS; }-*/; + private static native JsArrayString split(JavaScriptObject e) /*-{ + return (e && e.stack) ? e.stack.split('\n') : []; + }-*/; + private static native <T> T splice(T arr, int length) /*-{ (arr.length >= length) && arr.splice(0, length); return arr;
diff --git a/user/test/com/google/gwt/core/client/impl/StackTraceCreatorCollectorTest.java b/user/test/com/google/gwt/core/client/impl/StackTraceCreatorCollectorTest.java index 6123e16..9f9b04a 100644 --- a/user/test/com/google/gwt/core/client/impl/StackTraceCreatorCollectorTest.java +++ b/user/test/com/google/gwt/core/client/impl/StackTraceCreatorCollectorTest.java
@@ -18,7 +18,7 @@ import static com.google.gwt.core.client.impl.StackTraceCreator.extractFunctionName; import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArrayString; +import com.google.gwt.core.client.impl.StackTraceCreator.Collector; import com.google.gwt.core.client.impl.StackTraceCreator.CollectorChrome; import com.google.gwt.core.client.impl.StackTraceCreator.CollectorChromeNoSourceMap; import com.google.gwt.core.client.impl.StackTraceCreator.CollectorMoz; @@ -208,10 +208,9 @@ return new StackTraceElement("Unknown", methodName, fileName, lineNumber); } - private static void assertStackTrace(JavaScriptObject exception, CollectorMoz collector, + private static void assertStackTrace(JavaScriptObject exception, Collector collector, StackTraceElement[] expected) { - JsArrayString stack = collector.inferFrom(exception); - assertEquals(expected, collector.getStackTrace(stack)); + assertEquals(expected, collector.getStackTrace(exception)); } private static void assertEquals(StackTraceElement[] expecteds, StackTraceElement[] actuals) {