Replaces the way Throwable is linked to JavaScript.

The new implementation is obfuscatable so multiple J2CL
applications or GWT/J2CL mix in same page won't collide
on the property which otherwise would lead to hard to debug
issues.

Change-Id: I6d4b9f201192cad4881790f1f3086511e0e26e5c
diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java
index 1b05279..2883ded 100644
--- a/dev/core/test/com/google/gwt/dev/CompilerTest.java
+++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java
@@ -2759,6 +2759,7 @@
         "java.lang.String$NativeFunction",
         "java.lang.String$NativeString",
         "java.lang.Throwable",
+        "java.lang.Throwable$HasJavaThrowable",
         "java.lang.Throwable$NativeError",
         "java.lang.Throwable$NativeTypeError",
         "javaemul.internal.NativeRegExp",
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 25fbef3..ae36177 100644
--- a/user/super/com/google/gwt/emul/java/lang/Throwable.java
+++ b/user/super/com/google/gwt/emul/java/lang/Throwable.java
@@ -22,11 +22,11 @@
 import java.io.PrintStream;
 import java.io.Serializable;
 
-import javaemul.internal.JsUtils;
 import javaemul.internal.annotations.DoNotInline;
 
 import jsinterop.annotations.JsMethod;
 import jsinterop.annotations.JsNonNull;
+import jsinterop.annotations.JsPackage;
 import jsinterop.annotations.JsProperty;
 import jsinterop.annotations.JsType;
 
@@ -150,7 +150,10 @@
 
   private void linkBack(Object error) {
     if (error != null) {
-      JsUtils.setPropertySafe(error, "__java$exception", this);
+      try {
+        // This may throw exception in strict mode.
+        ((HasJavaThrowable) error).setJavaThrowable(this);
+      } catch (Throwable ignored) { }
     }
   }
 
@@ -294,7 +297,7 @@
   public static @JsNonNull 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");
+      Throwable throwable = ((HasJavaThrowable) e).getJavaThrowable();
       if (throwable != null) {
         return throwable;
       }
@@ -311,4 +314,13 @@
 
   @JsType(isNative = true, name = "TypeError", namespace = "<window>")
   private static class NativeTypeError { }
+
+  @JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
+  private interface HasJavaThrowable {
+    @JsProperty(name = "__java$exception")
+    void setJavaThrowable(Throwable t);
+
+    @JsProperty(name = "__java$exception")
+    Throwable getJavaThrowable();
+  }
 }
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 03fb8a1..fa2dca9 100644
--- a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
+++ b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
@@ -59,12 +59,5 @@
   public static native void setProperty(Object map, String key, Object value) /*-{
     map[key] = value;
   }-*/;
-
-  public static native void setPropertySafe(Object map, String key, Object value) /*-{
-    try {
-      // This may throw exception in strict mode.
-      map[key] = value;
-    } catch(ignored) { }
-  }-*/;
 }