Makes NPE extend from JsException
This is so that TypeErrors could be treated by compiler
as NPE. The patch doesn't change the GWT behaviour as
that would be a breaking change but enable J2CL to change
the behavior.
Change-Id: I86e83ebec477b17a30abbcf5bde1f6689d143b87
Review-Link: https://gwt-review.googlesource.com/#/c/14902/
diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java
index e6aa553..2b27fb9 100644
--- a/dev/core/test/com/google/gwt/dev/CompilerTest.java
+++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java
@@ -1519,6 +1519,7 @@
staleTypeNames.remove("java.lang.Double");
staleTypeNames.remove("java.lang.Number");
staleTypeNames.remove("java.lang.String");
+ staleTypeNames.remove("java.lang.Throwable");
// Show that only this little change is stale, not the whole world.
assertEquals(2, staleTypeNames.size());
}
@@ -2552,6 +2553,7 @@
staleTypeNames.remove("java.lang.Double");
staleTypeNames.remove("java.lang.Number");
staleTypeNames.remove("java.lang.String");
+ staleTypeNames.remove("java.lang.Throwable");
assertEquals(expectedProcessedStaleTypeNames, staleTypeNames);
}
return Files.toString(outputJsFile, Charsets.UTF_8);
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 fc5dbeb..a8b2958 100644
--- a/user/src/com/google/gwt/core/client/impl/StackTraceCreator.java
+++ b/user/src/com/google/gwt/core/client/impl/StackTraceCreator.java
@@ -351,7 +351,7 @@
private static native boolean supportsErrorStack() /*-{
// Error.stackTraceLimit is cheaper to check and available in both IE and Chrome
if (Error.stackTraceLimit > 0) {
- Error.stackTraceLimit = 64;
+ $wnd.Error.stackTraceLimit = Error.stackTraceLimit = 64;
return true;
}
diff --git a/user/src/com/google/gwt/user/client/rpc/core/java/lang/NullPointerException_CustomFieldSerializer.java b/user/src/com/google/gwt/user/client/rpc/core/java/lang/NullPointerException_CustomFieldSerializer.java
new file mode 100644
index 0000000..6b79190
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/rpc/core/java/lang/NullPointerException_CustomFieldSerializer.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.rpc.core.java.lang;
+
+import com.google.gwt.user.client.rpc.CustomFieldSerializer;
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
+/**
+ * Custom field serializer for {@link java.lang.NullPointerException}.
+ * This is necessary since NullPointerException emul extends JsException which is inconsistent
+ * with server-side.
+ */
+public final class NullPointerException_CustomFieldSerializer
+ extends CustomFieldSerializer<NullPointerException> {
+
+ public static NullPointerException instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return new NullPointerException(streamReader.readString());
+ }
+
+ public static void deserialize(
+ SerializationStreamReader streamReader, NullPointerException instance)
+ throws SerializationException {
+ instance.initCause((Throwable) streamReader.readObject());
+ }
+
+ public static void serialize(
+ SerializationStreamWriter streamWriter, NullPointerException instance)
+ throws SerializationException {
+ streamWriter.writeString(instance.getMessage());
+ streamWriter.writeObject(instance.getCause());
+ }
+
+ @Override
+ public boolean hasCustomInstantiateInstance() {
+ return true;
+ }
+
+ @Override
+ public NullPointerException instantiateInstance(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return instantiate(streamReader);
+ }
+
+ @Override
+ public void deserializeInstance(
+ SerializationStreamReader streamReader, NullPointerException instance)
+ throws SerializationException {
+ deserialize(streamReader, instance);
+ }
+
+ @Override
+ public void serializeInstance(
+ SerializationStreamWriter streamWriter, NullPointerException instance)
+ throws SerializationException {
+ serialize(streamWriter, instance);
+ }
+}
diff --git a/user/super/com/google/gwt/emul/java/lang/JsException.java b/user/super/com/google/gwt/emul/java/lang/JsException.java
index 47b7354..7a37e9c 100644
--- a/user/super/com/google/gwt/emul/java/lang/JsException.java
+++ b/user/super/com/google/gwt/emul/java/lang/JsException.java
@@ -21,8 +21,16 @@
* primitives like {@code null}, numbers, etc.
*/
public class JsException extends RuntimeException {
+
protected JsException(Object backingJsObject) {
super(backingJsObject);
}
-}
+ JsException(String msg) {
+ super(msg);
+ }
+
+ JsException() {
+ super();
+ }
+}
diff --git a/user/super/com/google/gwt/emul/java/lang/NullPointerException.java b/user/super/com/google/gwt/emul/java/lang/NullPointerException.java
index 4a08e96..2425878 100644
--- a/user/super/com/google/gwt/emul/java/lang/NullPointerException.java
+++ b/user/super/com/google/gwt/emul/java/lang/NullPointerException.java
@@ -15,12 +15,15 @@
*/
package java.lang;
+import jsinterop.annotations.JsPackage;
+import jsinterop.annotations.JsType;
+
/**
* See <a
* href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/NullPointerException.html">the
* official Java API doc</a> for details.
*/
-public class NullPointerException extends RuntimeException {
+public class NullPointerException extends JsException {
public NullPointerException() {
}
@@ -29,7 +32,17 @@
super(message);
}
- native Object createError(String msg) /*-{
- return new TypeError(msg);
- }-*/;
+ NullPointerException(Object typeError) {
+ super(typeError);
+ }
+
+ @Override
+ Object createError(String msg) {
+ return new NativeTypeError(msg);
+ }
+
+ @JsType(isNative = true, name = "TypeError", namespace = JsPackage.GLOBAL)
+ private static class NativeTypeError {
+ NativeTypeError(String msg) { }
+ }
}
diff --git a/user/super/com/google/gwt/emul/java/lang/Throwable.java b/user/super/com/google/gwt/emul/java/lang/Throwable.java
index 94623cb..bf53e83 100644
--- a/user/super/com/google/gwt/emul/java/lang/Throwable.java
+++ b/user/super/com/google/gwt/emul/java/lang/Throwable.java
@@ -24,7 +24,11 @@
import javaemul.internal.JsUtils;
import javaemul.internal.annotations.DoNotInline;
+
+import jsinterop.annotations.JsMethod;
+import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsProperty;
+import jsinterop.annotations.JsType;
/**
* See <a
@@ -41,11 +45,7 @@
* The client uses the generated field serializers which can use JSNI. That
* leaves the server free to special case Throwable so that only the
* detailMessage field is serialized.
- *
- * Throwable is given special treatment by server's SerializabilityUtil class
- * to ensure that only the detailMessage field is serialized. Changing the
- * field modifiers below may necessitate a change to the server's
- * SerializabilityUtil.fieldQualifiesForSerialization(Field) method.
+ * See SerializabilityUtil.
*/
private String detailMessage;
private transient Throwable cause;
@@ -118,9 +118,9 @@
// TODO(goktug): set 'name' property to class name and 'message' to detailMessage instead when
// they are respected by dev tools logging.
- native Object createError(String msg) /*-{
- return new Error(msg);
- }-*/;
+ Object createError(String msg) {
+ return new NativeError(msg);
+ }
private static native Object fixIE(Object e) /*-{
// In IE -unlike every other browser-, the stack property is not defined until you throw it.
@@ -279,4 +279,26 @@
String className = getClass().getName();
return message == null ? className : className + ": " + message;
}
+
+ @JsMethod
+ public static Throwable of(Object e) {
+ // If the JS error is already mapped to a Java Exception, use it.
+ if (e != null) {
+ Throwable throwable = JsUtils.getProperty(e, "__java$exception");
+ if (throwable != null) {
+ return throwable;
+ }
+ }
+
+ // If the JS error is being seen for the first time, map it best corresponding Java exception.
+ return e instanceof NativeTypeError ? new NullPointerException(e) : new JsException(e);
+ }
+
+ @JsType(isNative = true, name = "Error", namespace = JsPackage.GLOBAL)
+ private static class NativeError {
+ NativeError(String msg) { }
+ }
+
+ @JsType(isNative = true, name = "TypeError", namespace = JsPackage.GLOBAL)
+ private static class NativeTypeError { }
}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
index 4a7b817..b0ff418 100644
--- a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
+++ b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
@@ -37,6 +37,10 @@
return string;
}-*/;
+ public static native <T> T getProperty(Object map, String key) /*-{
+ return map[key];
+ }-*/;
+
public static native void setPropertySafe(Object map, String key, Object value) /*-{
try {
// This may throw exception in strict mode.