Fix isJavaScriptObject to not treat boolean/number as JSO
JsJsonBoolean/JsJsonNumber updated to avoid issue (since those are
JSOs that relied on unboxing behavior)
Change-Id: I53b5150fdc6060133af4b9c95876e8c16492e1b5
diff --git a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java
index 122fa90..4805bdd 100644
--- a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java
+++ b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java
@@ -161,7 +161,7 @@
@HasNoSideEffects
static boolean isJavaScriptObject(Object src) {
- return !isJavaString(src) && !Util.hasTypeMarker(src);
+ return isJsObjectOrFunction(src) && !Util.hasTypeMarker(src);
}
/**
@@ -278,6 +278,11 @@
return o;
}
+ @HasNoSideEffects
+ static native boolean isJsObjectOrFunction(Object src) /*-{
+ return typeof(src) === "object" || typeof(src) === "function";
+ }-*/;
+
// NOTE: if any of these three are edited, update JProgram.DispatchType's constructor
/**
* Returns whether the Object is a Java String.
diff --git a/elemental/src/elemental/js/json/JsJsonBoolean.java b/elemental/src/elemental/js/json/JsJsonBoolean.java
index c3d0c1b..66192d1 100644
--- a/elemental/src/elemental/js/json/JsJsonBoolean.java
+++ b/elemental/src/elemental/js/json/JsJsonBoolean.java
@@ -18,7 +18,7 @@
import elemental.json.JsonBoolean;
/**
- * Client-side 'zero overhead' JSO implementation using extension method
+ * Client-side 'low overhead' JSO implementation using extension method
* technique.
*/
final public class JsJsonBoolean extends JsJsonValue
@@ -32,8 +32,7 @@
* MAGIC: primitive boolean cast to object interface.
*/
private static native JsJsonBoolean createProd(boolean bool) /*-{
- // box for DevMode, not ProdMode
- return @com.google.gwt.core.client.GWT::isScript()() ? bool : Object(bool);
+ return Object(bool);
}-*/;
protected JsJsonBoolean() {
@@ -44,6 +43,6 @@
}
private native boolean valueProd() /*-{
- return @elemental.js.json.JsJsonValue::debox(Lelemental/json/JsonValue;)(this);
+ return this && this.valueOf();
}-*/;
}
diff --git a/elemental/src/elemental/js/json/JsJsonNumber.java b/elemental/src/elemental/js/json/JsJsonNumber.java
index 1d0e513..b9a444c 100644
--- a/elemental/src/elemental/js/json/JsJsonNumber.java
+++ b/elemental/src/elemental/js/json/JsJsonNumber.java
@@ -18,7 +18,7 @@
import elemental.json.JsonNumber;
/**
- * Client-side 'zero overhead' JSO implementation using extension method
+ * Client-side 'low overhead' JSO implementation using extension method
* technique.
*/
final public class JsJsonNumber extends JsJsonValue
@@ -32,8 +32,7 @@
* MAGIC: primitive number cast to object interface.
*/
private static native JsJsonNumber createProd(double number) /*-{
- // box for DevMode, not ProdMode
- return @com.google.gwt.core.client.GWT::isScript()() ? number : Object(number);
+ return Object(number);
}-*/;
protected JsJsonNumber() {
@@ -44,6 +43,6 @@
}
private native double valueProd() /*-{
- return @elemental.js.json.JsJsonValue::debox(Lelemental/json/JsonValue;)(this);
+ return this && this.valueOf();
}-*/;
}
diff --git a/user/test/com/google/gwt/dev/jjs/test/SingleJsoImplTest.java b/user/test/com/google/gwt/dev/jjs/test/SingleJsoImplTest.java
index 9f9d6a0..b669889 100644
--- a/user/test/com/google/gwt/dev/jjs/test/SingleJsoImplTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/SingleJsoImplTest.java
@@ -585,6 +585,23 @@
return {};
}-*/;
+ interface JsFunction {
+ int call();
+ }
+
+ final static class JsFunctionImpl extends JavaScriptObject implements JsFunction {
+ protected JsFunctionImpl() {
+ }
+
+ static native JsFunction makeFunc() /*-{
+ return function() { return 42; };
+ }-*/;
+
+ public native int call() /*-{
+ return this();
+ }-*/;
+ }
+
@Override
public String getModuleName() {
return "com.google.gwt.dev.jjs.CompilerSuite";
@@ -983,4 +1000,16 @@
assertNotNull(o);
assertTrue(o.isOk());
}
+
+ public void testJsFunctionCastsAsJso() {
+ JsFunction func = JsFunctionImpl.makeFunc();
+ assertTrue(func instanceof JavaScriptObject);
+ JavaScriptObject jso = (JavaScriptObject) func;
+ JsFunction func2 = (JsFunction) jso;
+ if (func2 instanceof JavaScriptObject) {
+ assertEquals(42, func2.call());
+ } else {
+ fail("Function should return true for instanceof JSO");
+ }
+ }
}
diff --git a/user/test/com/google/gwt/emultest/java/lang/BooleanTest.java b/user/test/com/google/gwt/emultest/java/lang/BooleanTest.java
index 7975d66..b2c264c 100644
--- a/user/test/com/google/gwt/emultest/java/lang/BooleanTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/BooleanTest.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.emultest.java.lang;
+import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.junit.client.GWTTestCase;
/**
@@ -93,6 +94,16 @@
}
}
+ public void testDoesNotCastToJso() {
+ try {
+ Boolean b = true;
+ Object o = b;
+ JavaScriptObject jso = (JavaScriptObject) o;
+ fail("Boolean should fail to cast to a JSO");
+ } catch (ClassCastException e) {
+ }
+ }
+
public void testEqualityNormalizer() {
Boolean b = false;
if (b != null) {
diff --git a/user/test/com/google/gwt/emultest/java/lang/DoubleTest.java b/user/test/com/google/gwt/emultest/java/lang/DoubleTest.java
index e18693d..7fb15e5 100644
--- a/user/test/com/google/gwt/emultest/java/lang/DoubleTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/DoubleTest.java
@@ -16,6 +16,7 @@
package com.google.gwt.emultest.java.lang;
+import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.junit.client.GWTTestCase;
/**
@@ -105,6 +106,16 @@
}
}
+ public void testDoesNotCastToJso() {
+ try {
+ Double d = 1.2;
+ Object o = d;
+ JavaScriptObject jso = (JavaScriptObject) o;
+ fail("Double should fail to cast to a JSO");
+ } catch (ClassCastException e) {
+ }
+ }
+
public void testEqualityNormalizer() {
Double d = 0.0;
if (d != null) {