Cleanup JSNI methods.
Introduce a new JsUtils which contains relevant JSNI methods
and make JRE use it mostly.
Change-Id: Ib5ba3d5deac0222b8f24da8d422f98bbb45a78cc
Review-Link: https://gwt-review.googlesource.com/#/c/13362/
diff --git a/dev/core/super/javaemul/internal/ArrayHelper.java b/dev/core/super/javaemul/internal/ArrayHelper.java
index aed00fc..9f466f3 100644
--- a/dev/core/super/javaemul/internal/ArrayHelper.java
+++ b/dev/core/super/javaemul/internal/ArrayHelper.java
@@ -44,6 +44,10 @@
return new Array(length);
}-*/;
+ public static native int getLength(Object array) /*-{
+ return array.length;
+ }-*/;
+
public static native void setLength(Object array, int length)/*-{
array.length = length;
}-*/;
diff --git a/dev/core/super/javaemul/internal/HashCodes.java b/dev/core/super/javaemul/internal/HashCodes.java
index eebce72..86c4c76 100644
--- a/dev/core/super/javaemul/internal/HashCodes.java
+++ b/dev/core/super/javaemul/internal/HashCodes.java
@@ -21,6 +21,7 @@
public class HashCodes {
private static int sNextHashId = 0;
+ private static final String HASH_CODE_PROPERTY = "$H";
public static int hashCodeForString(String s) {
return StringHashCache.getHashCode(s);
@@ -31,18 +32,13 @@
return 0;
}
return o instanceof String
- ? hashCodeForString(unsafeCast(o)) : getObjectIdentityHashCode(o);
+ ? hashCodeForString(JsUtils.unsafeCastToString(o)) : getObjectIdentityHashCode(o);
}
public static native int getObjectIdentityHashCode(Object o) /*-{
return o.$H || (o.$H = @HashCodes::getNextHashId()());
}-*/;
- // TODO(goktug): replace unsafeCast with a real cast when the compiler can optimize it.
- private static native String unsafeCast(Object string) /*-{
- return string;
- }-*/;
-
/**
* Called from JSNI. Do not change this implementation without updating:
* <ul>
diff --git a/dev/core/super/javaemul/internal/JsUtils.java b/dev/core/super/javaemul/internal/JsUtils.java
new file mode 100644
index 0000000..6d4e74e
--- /dev/null
+++ b/dev/core/super/javaemul/internal/JsUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2015 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 javaemul.internal;
+
+/**
+ * Provides an interface for simple JavaScript idioms that can not be expressed in Java.
+ */
+public class JsUtils {
+
+ public static native double getInfinity() /*-{
+ return Infinity;
+ }-*/;
+
+ public static native int parseInt(String s, int radix) /*-{
+ return parseInt(s, radix);
+ }-*/;
+
+ public static native boolean isUndefined(Object value) /*-{
+ return value === undefined;
+ }-*/;
+
+ // TODO(goktug): replace this with a real cast when the compiler can optimize it.
+ public static native String unsafeCastToString(Object string) /*-{
+ return string;
+ }-*/;
+
+ public static native int getIntProperty(Object map, String key) /*-{
+ return map[key];
+ }-*/;
+
+ public static native void setIntProperty(Object map, String key, int value) /*-{
+ map[key] = value;
+ }-*/;
+}
+
diff --git a/dev/core/super/javaemul/internal/StringHashCache.java b/dev/core/super/javaemul/internal/StringHashCache.java
index be5b03c..d472de9 100644
--- a/dev/core/super/javaemul/internal/StringHashCache.java
+++ b/dev/core/super/javaemul/internal/StringHashCache.java
@@ -24,7 +24,7 @@
/**
* The "old" cache; it will be dumped when front is full.
*/
- private static Object back = createMap();
+ private static Object back = createNativeObject();
/**
* Tracks the number of entries in front.
*/
@@ -32,7 +32,7 @@
/**
* The "new" cache; it will become back when it becomes full.
*/
- private static Object front = createMap();
+ private static Object front = createNativeObject();
/**
* Pulled this number out of thin air.
*/
@@ -44,17 +44,17 @@
String key = ":" + str;
// Check the front store.
- Object result = get(front, key);
- if (!isUndefined(result)) {
- return cast(result);
+ Object result = getProperty(front, key);
+ if (!JsUtils.isUndefined(result)) {
+ return unsafeCastToInt(result);
}
// Check the back store.
- result = get(back, key);
- int hashCode = isUndefined(result) ? compute(str) : cast(result);
+ result = getProperty(back, key);
+ int hashCode = JsUtils.isUndefined(result) ? compute(str) : unsafeCastToInt(result);
// Increment can trigger the swap/flush; call after checking back but
// before writing to front.
increment();
- set(front, key, hashCode);
+ JsUtils.setIntProperty(front, key, hashCode);
return hashCode;
}
@@ -89,31 +89,21 @@
private static void increment() {
if (count == MAX_CACHE) {
back = front;
- front = createMap();
+ front = createNativeObject();
count = 0;
}
++count;
}
- private static native Object get(Object map, String key) /*-{
+ private static native Object getProperty(Object map, String key) /*-{
return map[key];
}-*/;
- private static native void set(Object map, String key, int value) /*-{
- map[key] = value;
- }-*/;
-
- // Note: we are explicitly checking for undefined since '0 == null' equals true in JavaScript
- private static native boolean isUndefined(Object o) /*-{
- return o === undefined;
- }-*/;
-
- private static native int cast(Object o) /*-{
- return o;
- }-*/;
-
- private static native Object createMap() /*-{
+ private static native Object createNativeObject() /*-{
return {};
}-*/;
-}
+ private static native int unsafeCastToInt(Object o) /*-{
+ return o;
+ }-*/;
+}
diff --git a/user/super/com/google/gwt/emul/java/lang/Double.java b/user/super/com/google/gwt/emul/java/lang/Double.java
index e1514d3..f75e195 100644
--- a/user/super/com/google/gwt/emul/java/lang/Double.java
+++ b/user/super/com/google/gwt/emul/java/lang/Double.java
@@ -15,6 +15,8 @@
*/
package java.lang;
+import javaemul.internal.JsUtils;
+
/**
* Wraps a primitive <code>double</code> as an object.
*/
@@ -193,9 +195,9 @@
return (int) d;
}
- public static native boolean isInfinite(double x) /*-{
- return !isFinite(x) && !isNaN(x);
- }-*/;
+ public static boolean isInfinite(double x) {
+ return x == JsUtils.getInfinity() || x == -JsUtils.getInfinity();
+ }
public static native boolean isNaN(double x) /*-{
return isNaN(x);
diff --git a/user/super/com/google/gwt/emul/java/lang/Float.java b/user/super/com/google/gwt/emul/java/lang/Float.java
index c1242ce..5d3647b 100644
--- a/user/super/com/google/gwt/emul/java/lang/Float.java
+++ b/user/super/com/google/gwt/emul/java/lang/Float.java
@@ -31,7 +31,6 @@
public static final Class<Float> TYPE = float.class;
private static final long POWER_31_INT = 2147483648L;
- private static final long POWER_32_INT = 4294967296L;
public static int compare(float x, float y) {
return Double.compare(x, y);
@@ -131,13 +130,13 @@
return (float) Double.longBitsToDouble(bits64);
}
- public static native boolean isInfinite(float x) /*-{
- return !isFinite(x) && !isNaN(x);
- }-*/;
+ public static boolean isInfinite(float x) {
+ return Double.isInfinite(x);
+ }
- public static native boolean isNaN(float x) /*-{
- return isNaN(x);
- }-*/;
+ public static boolean isNaN(float x) {
+ return Double.isNaN(x);
+ }
public static float parseFloat(String s) throws NumberFormatException {
double doubleValue = __parseAndValidateDouble(s);
diff --git a/user/super/com/google/gwt/emul/java/lang/Integer.java b/user/super/com/google/gwt/emul/java/lang/Integer.java
index bf834cf..948bf75 100644
--- a/user/super/com/google/gwt/emul/java/lang/Integer.java
+++ b/user/super/com/google/gwt/emul/java/lang/Integer.java
@@ -265,6 +265,7 @@
return (byte) value;
}
+ @Override
public int compareTo(Integer b) {
return compare(value, b.value);
}
diff --git a/user/super/com/google/gwt/emul/java/lang/Long.java b/user/super/com/google/gwt/emul/java/lang/Long.java
index e83bd2d..77a3fd3 100644
--- a/user/super/com/google/gwt/emul/java/lang/Long.java
+++ b/user/super/com/google/gwt/emul/java/lang/Long.java
@@ -249,6 +249,7 @@
return (byte) value;
}
+ @Override
public int compareTo(Long b) {
return compare(value, b.value);
}
diff --git a/user/super/com/google/gwt/emul/java/lang/Math.java b/user/super/com/google/gwt/emul/java/lang/Math.java
index f351858..620e617 100644
--- a/user/super/com/google/gwt/emul/java/lang/Math.java
+++ b/user/super/com/google/gwt/emul/java/lang/Math.java
@@ -15,6 +15,8 @@
*/
package java.lang;
+import javaemul.internal.JsUtils;
+
/**
* Math utility methods and constants.
*/
@@ -100,9 +102,9 @@
return Math.cos(x);
}-*/;
- public static native double cosh(double x) /*-{
+ public static double cosh(double x) {
return (Math.exp(x) + Math.exp(-x)) / 2.0;
- }-*/;
+ }
public static native double exp(double x) /*-{
return Math.exp(x);
@@ -197,8 +199,13 @@
return (long) round0(x);
}
- public static native int round(float x) /*-{
- return Math.round(x);
+ public static int round(float x) {
+ double roundedValue = round0(x);
+ return unsafeCastToInt(roundedValue);
+ }
+
+ private static native int unsafeCastToInt(double d) /*-{
+ return d;
}-*/;
public static double scalb(double d, int scaleFactor) {
@@ -249,9 +256,9 @@
return Math.sin(x);
}-*/;
- public static native double sinh(double x) /*-{
- return (Math.exp(x) - Math.exp(-x)) / 2.0;
- }-*/;
+ public static double sinh(double x) {
+ return (Math.exp(x) - Math.exp(-x)) / 2.0d;
+ }
public static native double sqrt(double x) /*-{
return Math.sqrt(x);
@@ -261,13 +268,16 @@
return Math.tan(x);
}-*/;
- public static native double tanh(double x) /*-{
- if (x == Infinity) {
- return 1.0;
+ public static double tanh(double x) {
+ if (x == JsUtils.getInfinity()) {
+ return 1.0d;
+ } else if (x == -JsUtils.getInfinity()) {
+ return -1.0d;
}
- var e2x = Math.exp(2.0 * x);
+
+ double e2x = Math.exp(2.0 * x);
return (e2x - 1) / (e2x + 1);
- }-*/;
+ }
public static double toDegrees(double x) {
return x * PI_UNDER_180;
diff --git a/user/super/com/google/gwt/emul/java/lang/Number.java b/user/super/com/google/gwt/emul/java/lang/Number.java
index 4277725..b406810 100644
--- a/user/super/com/google/gwt/emul/java/lang/Number.java
+++ b/user/super/com/google/gwt/emul/java/lang/Number.java
@@ -17,6 +17,8 @@
import java.io.Serializable;
+import javaemul.internal.JsUtils;
+
/**
* Abstract base class for numeric wrapper classes.
*/
@@ -178,9 +180,13 @@
if (!__isValidDouble(s)) {
throw NumberFormatException.forInputString(s);
}
- return __parseDouble(s);
+ return parseFloat(s);
}
+ private static native double parseFloat(String str) /*-{
+ return parseFloat(str);
+ }-*/;
+
/**
* @skip
*
@@ -205,11 +211,11 @@
}
}
- int toReturn = __parseInt(s, radix);
+ int toReturn = JsUtils.parseInt(s, radix);
// isTooLow is separated into its own variable to avoid a bug in BlackBerry OS 7. See
// https://code.google.com/p/google-web-toolkit/issues/detail?id=7291.
boolean isTooLow = toReturn < lowerBound;
- if (__isNaN(toReturn)) {
+ if (Double.isNaN(toReturn)) {
throw NumberFormatException.forInputString(s);
} else if (isTooLow || toReturn > upperBound) {
throw NumberFormatException.forInputString(s);
@@ -277,14 +283,14 @@
if (head > 0) {
// accumulate negative numbers, as -Long.MAX_VALUE == Long.MIN_VALUE + 1
// (in other words, -Long.MIN_VALUE overflows, see issue 7308)
- toReturn = - __parseInt(s.substring(0, head), radix);
+ toReturn = - JsUtils.parseInt(s.substring(0, head), radix);
s = s.substring(head);
length -= head;
firstTime = false;
}
while (length >= maxDigits) {
- head = __parseInt(s.substring(0, maxDigits), radix);
+ head = JsUtils.parseInt(s.substring(0, maxDigits), radix);
s = s.substring(maxDigits);
length -= maxDigits;
if (!firstTime) {
@@ -316,22 +322,15 @@
/**
* @skip
- */
- private static native boolean __isNaN(double x) /*-{
- return isNaN(x);
- }-*/;
-
- /**
- * @skip
*
* @param str
* @return {@code true} if the string matches the float format, {@code false} otherwise
*/
private static boolean __isValidDouble(String str) {
- if (floatRegex == null) {
- floatRegex = createFloatRegex();
- }
- return regexTest(floatRegex, str);
+ if (floatRegex == null) {
+ floatRegex = createFloatRegex();
+ }
+ return regexTest(floatRegex, str);
}
private static native Object createFloatRegex() /*-{
@@ -342,24 +341,6 @@
return regex.test(value);
}-*/;
- /**
- * @skip
- *
- * @return The floating-point representation of <code>str</code>.
- */
- private static native double __parseDouble(String str) /*-{
- return parseFloat(str);
- }-*/;
-
- /**
- * @skip
- *
- * Invokes the global JS function <code>parseInt()</code>.
- */
- private static native int __parseInt(String s, int radix) /*-{
- return parseInt(s, radix);
- }-*/;
-
// CHECKSTYLE_ON
public byte byteValue() {
diff --git a/user/super/com/google/gwt/emul/java/lang/System.java b/user/super/com/google/gwt/emul/java/lang/System.java
index 0c46af0..9682b6c 100644
--- a/user/super/com/google/gwt/emul/java/lang/System.java
+++ b/user/super/com/google/gwt/emul/java/lang/System.java
@@ -56,8 +56,8 @@
Class<?> destComp = destType.getComponentType();
checkArrayType(arrayTypeMatch(srcComp, destComp), "Array types don't match");
- int srclen = getArrayLength(src);
- int destlen = getArrayLength(dest);
+ int srclen = ArrayHelper.getLength(src);
+ int destlen = ArrayHelper.getLength(dest);
if (srcOfs < 0 || destOfs < 0 || len < 0 || srcOfs + len > srclen || destOfs + len > destlen) {
throw new IndexOutOfBoundsException();
}
@@ -134,11 +134,4 @@
return !destComp.isPrimitive();
}
}
-
- /**
- * Returns the length of an array via Javascript.
- */
- private static native int getArrayLength(Object array) /*-{
- return array.length;
- }-*/;
}
diff --git a/user/super/com/google/gwt/emul/java/math/BigDecimal.java b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
index 6b2e125..a18d2f4 100644
--- a/user/super/com/google/gwt/emul/java/math/BigDecimal.java
+++ b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
@@ -38,6 +38,8 @@
import java.io.Serializable;
+import javaemul.internal.JsUtils;
+
/**
* This class represents immutable arbitrary precision decimal numbers. Each
* {@code BigDecimal} instance is represented with a unscaled arbitrary
@@ -406,10 +408,6 @@
return regexTest(unscaledRegex, str);
}
- public static native double parseInt(String value, int base) /*-{
- return parseInt(value, base);
- }-*/;
-
private static native Object createBigDecimalUnscaledRegex() /*-{
return /^[+-]?\d*$/i;
}-*/;
@@ -419,7 +417,7 @@
}-*/;
private static double parseUnscaled(String str) {
- return isValidBigUnscaledDecimal(str) ? parseInt(str, 10) : Double.NaN;
+ return isValidBigUnscaledDecimal(str) ? JsUtils.parseInt(str, 10) : Double.NaN;
}
/**
diff --git a/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java b/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java
index e66b3b0..1d27463 100644
--- a/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java
+++ b/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java
@@ -23,6 +23,7 @@
import static javaemul.internal.InternalPreconditions.checkElement;
import static javaemul.internal.InternalPreconditions.checkState;
+import javaemul.internal.JsUtils;
import javaemul.internal.annotations.SpecializeMethod;
/**
@@ -161,7 +162,8 @@
@SpecializeMethod(params = {String.class}, target = "hasStringValue")
@Override
public boolean containsKey(Object key) {
- return key instanceof String ? hasStringValue(unsafeCast(key)) : hasHashValue(key);
+ return key instanceof String
+ ? hasStringValue(JsUtils.unsafeCastToString(key)) : hasHashValue(key);
}
@Override
@@ -186,19 +188,22 @@
@SpecializeMethod(params = {String.class}, target = "getStringValue")
@Override
public V get(Object key) {
- return key instanceof String ? getStringValue(unsafeCast(key)) : getHashValue(key);
+ return key instanceof String
+ ? getStringValue(JsUtils.unsafeCastToString(key)) : getHashValue(key);
}
@SpecializeMethod(params = {String.class, Object.class}, target = "putStringValue")
@Override
public V put(K key, V value) {
- return key instanceof String ? putStringValue(unsafeCast(key), value) : putHashValue(key, value);
+ return key instanceof String
+ ? putStringValue(JsUtils.unsafeCastToString(key), value) : putHashValue(key, value);
}
@SpecializeMethod(params = {String.class}, target = "removeStringValue")
@Override
public V remove(Object key) {
- return key instanceof String ? removeStringValue(unsafeCast(key)) : removeHashValue(key);
+ return key instanceof String
+ ? removeStringValue(JsUtils.unsafeCastToString(key)) : removeHashValue(key);
}
@Override
@@ -288,9 +293,4 @@
private V removeStringValue(String key) {
return key == null ? removeHashValue(null) : stringMap.remove(key);
}
-
- // TODO(goktug): replace unsafeCast with a real cast when the compiler can optimize it.
- private static native String unsafeCast(Object string) /*-{
- return string;
- }-*/;
}
diff --git a/user/super/com/google/gwt/emul/java/util/ConcurrentModificationDetector.java b/user/super/com/google/gwt/emul/java/util/ConcurrentModificationDetector.java
index 2aa0a47..11d9ba7 100644
--- a/user/super/com/google/gwt/emul/java/util/ConcurrentModificationDetector.java
+++ b/user/super/com/google/gwt/emul/java/util/ConcurrentModificationDetector.java
@@ -15,33 +15,31 @@
*/
package java.util;
+import javaemul.internal.JsUtils;
+
/**
* A helper to detect concurrent modifications to collections. This is implemented as a helper
* utility so that we could remove the checks easily by a flag.
*/
class ConcurrentModificationDetector {
+ private static final String MOD_COUNT_PROPERTY = "_gwt_modCount";
+
public static void structureChanged(Object map) {
// Ensure that modCount is initialized if it is not already.
- int modCount = getModCount(map) | 0;
- setModCount(map, modCount + 1);
+ int modCount = JsUtils.getIntProperty(map, MOD_COUNT_PROPERTY) | 0;
+ JsUtils.setIntProperty(map, MOD_COUNT_PROPERTY, modCount + 1);
}
public static void recordLastKnownStructure(Object host, Iterator<?> iterator) {
- setModCount(iterator, getModCount(host));
+ int modCount = JsUtils.getIntProperty(host, MOD_COUNT_PROPERTY);
+ JsUtils.setIntProperty(iterator, MOD_COUNT_PROPERTY, modCount);
}
-
+
public static void checkStructuralChange(Object host, Iterator<?> iterator) {
- if (getModCount(iterator) != getModCount(host)) {
+ if (JsUtils.getIntProperty(iterator, MOD_COUNT_PROPERTY)
+ != JsUtils.getIntProperty(host, MOD_COUNT_PROPERTY)) {
throw new ConcurrentModificationException();
}
}
-
- private static native void setModCount(Object o, int modCount) /*-{
- o._gwt_modCount = modCount;
- }-*/;
-
- private static native int getModCount(Object o) /*-{
- return o._gwt_modCount;
- }-*/;
}
diff --git a/user/super/com/google/gwt/emul/java/util/InternalStringMap.java b/user/super/com/google/gwt/emul/java/util/InternalStringMap.java
index 10929b2..443d225 100644
--- a/user/super/com/google/gwt/emul/java/util/InternalStringMap.java
+++ b/user/super/com/google/gwt/emul/java/util/InternalStringMap.java
@@ -25,6 +25,8 @@
import java.util.InternalJsMapFactory.InternalJsMap;
import java.util.Map.Entry;
+import javaemul.internal.JsUtils;
+
/**
* A simple wrapper around JavaScript Map for key type is string.
*/
@@ -47,7 +49,7 @@
}
public boolean contains(String key) {
- return !isUndefined(backingMap.get(key));
+ return !JsUtils.isUndefined(backingMap.get(key));
}
public V get(String key) {
@@ -58,7 +60,7 @@
V oldValue = backingMap.get(key);
backingMap.set(key, toNullIfUndefined(value));
- if (isUndefined(oldValue)) {
+ if (JsUtils.isUndefined(oldValue)) {
size++;
structureChanged(host);
} else {
@@ -69,7 +71,7 @@
public V remove(String key) {
V value = backingMap.get(key);
- if (!isUndefined(value)) {
+ if (!JsUtils.isUndefined(value)) {
backingMap.delete(key);
size--;
structureChanged(host);
@@ -136,10 +138,6 @@
}
private static <T> T toNullIfUndefined(T value) {
- return isUndefined(value) ? null : value;
+ return JsUtils.isUndefined(value) ? null : value;
}
-
- private static native boolean isUndefined(Object value) /*-{
- return value === undefined;
- }-*/;
}