Migrate all javaemul.internal to user
Change-Id: I4121c7979552043bce654f6ea418f1519e3d51c4
diff --git a/user/BUILD b/user/BUILD
index 64ca2fa..2fb8d6f 100644
--- a/user/BUILD
+++ b/user/BUILD
@@ -60,10 +60,13 @@
java_library(
name = "gwt-user-bare",
srcs = glob(
- ["src/**/*.java"],
+ [
+ "src/**/*.java",
+ "super/com/google/gwt/emul/javaemul/internal/**/*.java",
+ ],
exclude = [
"src/com/google/gwt/junit/**/*.java", # see gwt-testing
- "**/super/**",
+ "**/EmulatedCharset.java",
"**/RunStyleSelenium.java",
],
),
@@ -343,8 +346,6 @@
"src/com/google/gwt/user/client/impl/WindowImpl.java",
"src/com/google/gwt/dom/client/*.java",
"src/com/google/gwt/core/client/impl/Impl.java",
- "src/com/google/gwt/core/client/impl/Disposable.java",
- "src/com/google/gwt/core/client/impl/UnloadSupport.java",
"src/com/google/gwt/core/client/impl/StackTraceCreator.java",
"src/com/google/gwt/core/client/impl/SchedulerImpl.java",
"src/com/google/gwt/core/client/impl/AsyncFragmentLoader.java",
@@ -359,12 +360,13 @@
"src/com/google/gwt/i18n/client/impl/*.java",
"src/com/google/gwt/i18n/client/*.java",
"src/com/google/gwt/i18n/rebind/keygen/*.java",
+ "super/com/google/gwt/emul/javaemul/internal/ArrayHelper.java",
+ "super/com/google/gwt/emul/javaemul/internal/ArrayStamper.java",
# And it's also sensible to want for serialization:
"src/com/google/gwt/user/client/ui/SuggestOracle.java",
],
exclude = [
"**/junit/**",
- "**/super/**",
"**/package-info.java",
"src/com/google/web/bindery/requestfactory/server/RequestFactoryJarExtractor.java",
],
@@ -641,24 +643,30 @@
)
filegroup(
- name = "emul",
- srcs = glob(
- [
- "super/com/google/gwt/emul/java/**/*.java",
- ],
- ),
+ name = "java_emul",
+ srcs = glob(["super/com/google/gwt/emul/java/**/*.java"]),
visibility = ["//third_party/java_src/j2cl:__subpackages__"],
)
filegroup(
- name = "emul_test",
+ name = "java_emul_internal",
+ srcs = glob(["super/com/google/gwt/emul/javaemul/**/*.java"]),
+ visibility = ["//third_party/java_src/j2cl:__subpackages__"],
+)
+
+filegroup(
+ name = "java_emul_test",
srcs = glob(
[
"test/com/google/gwt/emultest/**/*.java",
"test/com/google/gwt/testing/TestUtils.java",
"test/org/apache/commons/**/*.java",
],
- exclude = ["**/package-info.java"],
+ exclude = [
+ "test/**/java8/**",
+ "test/**/*Java8Suite.java",
+ "**/package-info.java",
+ ],
),
visibility = ["//third_party/java_src/j2cl:__subpackages__"],
)
diff --git a/user/build.xml b/user/build.xml
index bf50826..7769964 100755
--- a/user/build.xml
+++ b/user/build.xml
@@ -104,7 +104,8 @@
<target name="compile" description="Compile all class files"
unless="compile.complete">
<mkdir dir="${javac.out}"/>
- <gwt.javac excludes="**/super/**">
+ <gwt.javac excludes="**/EmulatedCharset.java">
+ <src path="super/com/google/gwt/emul/javaemul/internal"/>
<classpath>
<pathelement location="${gwt.tools.lib}/gss/2015-10-07/closure-stylesheets-library-20151007-rebased.jar"/>
<pathelement location="${gwt.tools.lib}/gss/2015-11-04/closure-stylesheets-library-20151104-rebased.jar"/>
diff --git a/user/src/com/google/gwt/core/client/JavaScriptObject.java b/user/src/com/google/gwt/core/client/JavaScriptObject.java
index 3462bc7..abaa697 100644
--- a/user/src/com/google/gwt/core/client/JavaScriptObject.java
+++ b/user/src/com/google/gwt/core/client/JavaScriptObject.java
@@ -15,8 +15,6 @@
*/
package com.google.gwt.core.client;
-import javaemul.internal.HashCodes;
-
/**
* An opaque handle to a native JavaScript object. A
* <code>JavaScriptObject</code> cannot be created directly.
@@ -148,7 +146,7 @@
*/
@Override
public final int hashCode() {
- return HashCodes.getObjectIdentityHashCode(this);
+ return super.hashCode();
}
/**
diff --git a/user/super/com/google/gwt/emul/Emulation.gwt.xml b/user/super/com/google/gwt/emul/Emulation.gwt.xml
index 9555138..9b75e95 100644
--- a/user/super/com/google/gwt/emul/Emulation.gwt.xml
+++ b/user/super/com/google/gwt/emul/Emulation.gwt.xml
@@ -15,7 +15,6 @@
<!-- A JavaScript-based emulation of the Java Runtime library. -->
<!-- Do not inherit this module directly; inherit com.google.gwt.core.Core. -->
<module>
- <inherits name="javaemul.internal.Internal"/>
<inherits name="com.google.gwt.emul.Preconditions" />
<extend-configuration-property name="compiler.enum.obfuscate.names.blacklist"
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/ArrayHelper.java b/user/super/com/google/gwt/emul/javaemul/internal/ArrayHelper.java
new file mode 100644
index 0000000..1fc2a0e
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/ArrayHelper.java
@@ -0,0 +1,98 @@
+/*
+ * 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 utilities to perform operations on Arrays.
+ */
+public class ArrayHelper {
+
+ public static final int ARRAY_PROCESS_BATCH_SIZE = 10000;
+
+ public static <T> T[] clone(T[] array, int fromIndex, int toIndex) {
+ Object result = unsafeClone(array, fromIndex, toIndex);
+ return ArrayStamper.stampJavaTypeInfo(result, array);
+ }
+
+ /**
+ * Unlike clone, this method returns a copy of the array that is not type marked. This is only
+ * safe for temp arrays as returned array will not do any type checks.
+ */
+ public static native Object[] unsafeClone(Object array, int fromIndex, int toIndex) /*-{
+ return array.slice(fromIndex, toIndex);
+ }-*/;
+
+ public static <T> T[] createFrom(T[] array, int length) {
+ Object result = createNativeArray(length);
+ return ArrayStamper.stampJavaTypeInfo(result, array);
+ }
+
+ private static native Object createNativeArray(int length)/*-{
+ 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;
+ }-*/;
+
+ public static native void removeFrom(Object array, int index, int deleteCount) /*-{
+ array.splice(index, deleteCount);
+ }-*/;
+
+ public static native void insertTo(Object array, int index, Object value) /*-{
+ array.splice(index, 0, value);
+ }-*/;
+
+ public static void insertTo(Object array, int index, Object[] values) {
+ copy(values, 0, array, index, values.length, false);
+ }
+
+ public static void copy(Object array, int srcOfs, Object dest, int destOfs, int len) {
+ copy(array, srcOfs, dest, destOfs, len, true);
+ }
+
+ private static void copy(
+ Object src, int srcOfs, Object dest, int destOfs, int len, boolean overwrite) {
+ /*
+ * Array.prototype.splice is not used directly to overcome the limits imposed to the number of
+ * function parameters by browsers.
+ */
+
+ if (src == dest) {
+ // copying to the same array, make a copy first
+ src = unsafeClone(src, srcOfs, srcOfs + len);
+ srcOfs = 0;
+ }
+ for (int batchStart = srcOfs, end = srcOfs + len; batchStart < end;) {
+ // increment in block
+ int batchEnd = Math.min(batchStart + ARRAY_PROCESS_BATCH_SIZE, end);
+ len = batchEnd - batchStart;
+ applySplice(dest, destOfs, overwrite ? len : 0, unsafeClone(src, batchStart, batchEnd));
+ batchStart = batchEnd;
+ destOfs += len;
+ }
+ }
+
+ private static native void applySplice(Object array, int index, int deleteCount,
+ Object arrayToAdd) /*-{
+ Array.prototype.splice.apply(array, [index, deleteCount].concat(arrayToAdd));
+ }-*/;
+}
+
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/ArrayStamper.java b/user/super/com/google/gwt/emul/javaemul/internal/ArrayStamper.java
new file mode 100644
index 0000000..7da1402
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/ArrayStamper.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+/**
+ * A utility to provide array stamping. Provided as a separate class to simplify super-source.
+ */
+class ArrayStamper {
+ public static native <T> T[] stampJavaTypeInfo(Object array, T[] referenceType) /*-{
+ return @com.google.gwt.lang.Array::stampJavaTypeInfo(
+ Ljava/lang/Object;[Ljava/lang/Object;)(array, referenceType);
+ }-*/;
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/Coercions.java b/user/super/com/google/gwt/emul/javaemul/internal/Coercions.java
new file mode 100644
index 0000000..267b98f
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/Coercions.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014 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;
+
+/**
+ * Private implementation class for GWT. This API should not be
+ * considered public or stable.
+ */
+public final class Coercions {
+
+ /**
+ * Coerce js int to 32 bits.
+ * Trick related to JS and lack of integer rollover.
+ * {@see com.google.gwt.lang.Cast#narrow_int}
+ */
+ public static int ensureInt(int value) {
+ return value | 0;
+ }
+
+ private Coercions() { }
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/ConsoleLogger.java b/user/super/com/google/gwt/emul/javaemul/internal/ConsoleLogger.java
new file mode 100644
index 0000000..ebad921
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/ConsoleLogger.java
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+/**
+ * A helper to print log messages to console.
+ * <p> Note that, this is not a public API and can change/disappear in any release.
+ */
+public class ConsoleLogger {
+ public static ConsoleLogger createIfSupported() {
+ return isSupported() ? new ConsoleLogger() : null;
+ }
+
+ private static native boolean isSupported() /*-{
+ return !!window.console;
+ }-*/;
+
+ public native void log(String level, String message) /*-{
+ console[level](message);
+ }-*/;
+
+ public void log(String level, Throwable t) {
+ log(level, t, "Exception: ", true);
+ }
+
+ private void log(String level, Throwable t, String label, boolean expanded) {
+ groupStart(label + t.toString(), expanded);
+ log(level, getBackingError(t));
+ Throwable cause = t.getCause();
+ if (cause != null) {
+ log(level, cause, "Caused by: ", false);
+ }
+ for (Throwable suppressed : t.getSuppressed()) {
+ log(level, suppressed, "Suppressed: ", false);
+ }
+ groupEnd();
+ }
+
+ private native void groupStart(String msg, boolean expanded) /*-{
+ // Not all browsers support grouping:
+ var groupStart = (!expanded && console.groupCollapsed) || console.group || console.log;
+ groupStart.call(console, msg);
+ }-*/;
+
+ private native void groupEnd() /*-{
+ var groupEnd = console.groupEnd || function(){};
+ groupEnd.call(console);
+ }-*/;
+
+ private native String getBackingError(Throwable t) /*-{
+ // Converts CollectorLegacy (IE8/IE9/Safari5) function stack to something readable.
+ function stringify(fnStack) {
+ if (!fnStack || fnStack.length == 0) {
+ return "";
+ }
+ return "\t" + fnStack.join("\n\t");
+ }
+ var backingError = t.backingJsObject;
+ return backingError && (backingError.stack || stringify(t["fnStack"]));
+ }-*/;
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/DateUtil.java b/user/super/com/google/gwt/emul/javaemul/internal/DateUtil.java
new file mode 100644
index 0000000..321bf95
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/DateUtil.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * Simple Helper class to return Date.now.
+ */
+public class DateUtil {
+ /**
+ * Returns the numeric value corresponding to the current time -
+ * the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
+ */
+ public static native double now() /*-{
+ // IE8 does not have Date.now
+ // when removing IE8 support we change this to Date.now()
+ if (Date.now) {
+ // Date.now vs Date.getTime() performance comparison:
+ // http://jsperf.com/date-now-vs-new-date/8
+ return Date.now();
+ }
+ return (new Date()).getTime();
+ }-*/;
+}
\ No newline at end of file
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/EmulatedCharset.java b/user/super/com/google/gwt/emul/javaemul/internal/EmulatedCharset.java
new file mode 100644
index 0000000..ddde0fa
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/EmulatedCharset.java
@@ -0,0 +1,201 @@
+/*
+ * 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;
+
+import java.nio.charset.Charset;
+
+/**
+ * Provides Charset implementations.
+ */
+public abstract class EmulatedCharset extends Charset {
+
+ public static final EmulatedCharset UTF_8 = new UtfCharset("UTF-8");
+
+ public static final EmulatedCharset ISO_LATIN_1 = new LatinCharset("ISO-LATIN-1");
+
+ public static final EmulatedCharset ISO_8859_1 = new LatinCharset("ISO-8859-1");
+
+ private static class LatinCharset extends EmulatedCharset {
+ public LatinCharset(String name) {
+ super(name);
+ }
+
+ @Override
+ public byte[] getBytes(String str) {
+ int n = str.length();
+ byte[] bytes = new byte[n];
+ for (int i = 0; i < n; ++i) {
+ bytes[i] = (byte) (str.charAt(i) & 255);
+ }
+ return bytes;
+ }
+
+ @Override
+ public char[] decodeString(byte[] bytes, int ofs, int len) {
+ char[] chars = new char[len];
+ for (int i = 0; i < len; ++i) {
+ chars[i] = (char) (bytes[ofs + i] & 255);
+ }
+ return chars;
+ }
+ }
+
+ private static class UtfCharset extends EmulatedCharset {
+ public UtfCharset(String name) {
+ super(name);
+ }
+
+ @Override
+ public char[] decodeString(byte[] bytes, int ofs, int len) {
+ // TODO(jat): consider using decodeURIComponent(escape(bytes)) instead
+ int charCount = 0;
+ for (int i = 0; i < len; ) {
+ ++charCount;
+ byte ch = bytes[ofs + i];
+ if ((ch & 0xC0) == 0x80) {
+ throw new IllegalArgumentException("Invalid UTF8 sequence");
+ } else if ((ch & 0x80) == 0) {
+ ++i;
+ } else if ((ch & 0xE0) == 0xC0) {
+ i += 2;
+ } else if ((ch & 0xF0) == 0xE0) {
+ i += 3;
+ } else if ((ch & 0xF8) == 0xF0) {
+ i += 4;
+ } else {
+ // no 5+ byte sequences since max codepoint is less than 2^21
+ throw new IllegalArgumentException("Invalid UTF8 sequence");
+ }
+ if (i > len) {
+ throw new IndexOutOfBoundsException("Invalid UTF8 sequence");
+ }
+ }
+ char[] chars = new char[charCount];
+ int outIdx = 0;
+ int count = 0;
+ for (int i = 0; i < len; ) {
+ int ch = bytes[ofs + i++];
+ if ((ch & 0x80) == 0) {
+ count = 1;
+ ch &= 127;
+ } else if ((ch & 0xE0) == 0xC0) {
+ count = 2;
+ ch &= 31;
+ } else if ((ch & 0xF0) == 0xE0) {
+ count = 3;
+ ch &= 15;
+ } else if ((ch & 0xF8) == 0xF0) {
+ count = 4;
+ ch &= 7;
+ } else if ((ch & 0xFC) == 0xF8) {
+ count = 5;
+ ch &= 3;
+ }
+ while (--count > 0) {
+ byte b = bytes[ofs + i++];
+ if ((b & 0xC0) != 0x80) {
+ throw new IllegalArgumentException("Invalid UTF8 sequence at "
+ + (ofs + i - 1) + ", byte=" + Integer.toHexString(b));
+ }
+ ch = (ch << 6) | (b & 63);
+ }
+ outIdx += Character.toChars(ch, chars, outIdx);
+ }
+ return chars;
+ }
+
+ @Override
+ public byte[] getBytes(String str) {
+ // TODO(jat): consider using unescape(encodeURIComponent(bytes)) instead
+ int n = str.length();
+ int byteCount = 0;
+ for (int i = 0; i < n;) {
+ int ch = str.codePointAt(i);
+ i += Character.charCount(ch);
+ if (ch < (1 << 7)) {
+ byteCount++;
+ } else if (ch < (1 << 11)) {
+ byteCount += 2;
+ } else if (ch < (1 << 16)) {
+ byteCount += 3;
+ } else if (ch < (1 << 21)) {
+ byteCount += 4;
+ } else if (ch < (1 << 26)) {
+ byteCount += 5;
+ }
+ }
+ byte[] bytes = new byte[byteCount];
+ int out = 0;
+ for (int i = 0; i < n;) {
+ int ch = str.codePointAt(i);
+ i += Character.charCount(ch);
+ out += encodeUtf8(bytes, out, ch);
+ }
+ return bytes;
+ }
+
+ /**
+ * Encode a single character in UTF8.
+ *
+ * @param bytes byte array to store character in
+ * @param ofs offset into byte array to store first byte
+ * @param codePoint character to encode
+ * @return number of bytes consumed by encoding the character
+ * @throws IllegalArgumentException if codepoint >= 2^26
+ */
+ private int encodeUtf8(byte[] bytes, int ofs, int codePoint) {
+ if (codePoint < (1 << 7)) {
+ bytes[ofs] = (byte) (codePoint & 127);
+ return 1;
+ } else if (codePoint < (1 << 11)) {
+ // 110xxxxx 10xxxxxx
+ bytes[ofs++] = (byte) (((codePoint >> 6) & 31) | 0xC0);
+ bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
+ return 2;
+ } else if (codePoint < (1 << 16)) {
+ // 1110xxxx 10xxxxxx 10xxxxxx
+ bytes[ofs++] = (byte) (((codePoint >> 12) & 15) | 0xE0);
+ bytes[ofs++] = (byte) (((codePoint >> 6) & 63) | 0x80);
+ bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
+ return 3;
+ } else if (codePoint < (1 << 21)) {
+ // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ bytes[ofs++] = (byte) (((codePoint >> 18) & 7) | 0xF0);
+ bytes[ofs++] = (byte) (((codePoint >> 12) & 63) | 0x80);
+ bytes[ofs++] = (byte) (((codePoint >> 6) & 63) | 0x80);
+ bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
+ return 4;
+ } else if (codePoint < (1 << 26)) {
+ // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ bytes[ofs++] = (byte) (((codePoint >> 24) & 3) | 0xF8);
+ bytes[ofs++] = (byte) (((codePoint >> 18) & 63) | 0x80);
+ bytes[ofs++] = (byte) (((codePoint >> 12) & 63) | 0x80);
+ bytes[ofs++] = (byte) (((codePoint >> 6) & 63) | 0x80);
+ bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
+ return 5;
+ }
+ throw new IllegalArgumentException("Character out of range: " + codePoint);
+ }
+ }
+
+ public EmulatedCharset(String name) {
+ super(name, null);
+ }
+
+ public abstract byte[] getBytes(String string);
+
+ public abstract char[] decodeString(byte[] bytes, int ofs, int len);
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java b/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java
new file mode 100644
index 0000000..86c4c76
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+/**
+ * Contains logics for calculating hash codes in JavaScript.
+ */
+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);
+ }
+
+ public static int getIdentityHashCode(Object o) {
+ if (o == null) {
+ return 0;
+ }
+ return o instanceof String
+ ? hashCodeForString(JsUtils.unsafeCastToString(o)) : getObjectIdentityHashCode(o);
+ }
+
+ public static native int getObjectIdentityHashCode(Object o) /*-{
+ return o.$H || (o.$H = @HashCodes::getNextHashId()());
+ }-*/;
+
+ /**
+ * Called from JSNI. Do not change this implementation without updating:
+ * <ul>
+ * <li>{@link com.google.gwt.user.client.rpc.impl.SerializerBase}</li>
+ * </ul>
+ */
+ private static int getNextHashId() {
+ return ++sNextHashId;
+ }
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/Internal.gwt.xml b/user/super/com/google/gwt/emul/javaemul/internal/Internal.gwt.xml
new file mode 100644
index 0000000..5365991
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/Internal.gwt.xml
@@ -0,0 +1,22 @@
+<!-- -->
+<!-- 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 -->
+<!-- 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. License for the specific language governing permissions and -->
+<!-- limitations under the License. -->
+
+<!-- Internal JRE emultation helpers. -->
+<!-- Do not inherit this module directly; inherit com.google.gwt.core.Core. -->
+<!-- -->
+<!-- Types from this module should never be used in any user code -->
+<!-- -->
+<module>
+ <source path=""/>
+</module>
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java b/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java
new file mode 100644
index 0000000..15e064b
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java
@@ -0,0 +1,490 @@
+/*
+ * Copyright 2014 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;
+
+import java.util.NoSuchElementException;
+
+/**
+ * A utility class that provides utility functions to do precondition checks inside GWT-SDK.
+ */
+// Some parts adapted from Guava
+public final class InternalPreconditions {
+ private static final boolean CHECKED_MODE =
+ System.getProperty("jre.checkedMode", "ENABLED").equals("ENABLED");
+ private static final boolean TYPE_CHECK =
+ System.getProperty("jre.checks.type", "ENABLED").equals("ENABLED");
+ private static final boolean API_CHECK =
+ System.getProperty("jre.checks.api", "ENABLED").equals("ENABLED");
+ private static final boolean BOUND_CHECK =
+ System.getProperty("jre.checks.bounds", "ENABLED").equals("ENABLED");
+
+ public static void checkType(boolean expression) {
+ if (TYPE_CHECK) {
+ checkCriticalType(expression);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalType(expression);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ public static void checkCriticalType(boolean expression) {
+ if (!expression) {
+ throw new ClassCastException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression that verifies array type.
+ */
+ public static void checkArrayType(boolean expression) {
+ if (TYPE_CHECK) {
+ checkCriticalArrayType(expression);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalArrayType(expression);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ public static void checkCriticalArrayType(boolean expression) {
+ if (!expression) {
+ throw new ArrayStoreException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression that verifies array type.
+ */
+ public static void checkArrayType(boolean expression, Object errorMessage) {
+ if (TYPE_CHECK) {
+ checkCriticalArrayType(expression, errorMessage);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalArrayType(expression, errorMessage);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ public static void checkCriticalArrayType(boolean expression, Object errorMessage) {
+ if (!expression) {
+ throw new ArrayStoreException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving existence of an element.
+ */
+ public static void checkElement(boolean expression) {
+ if (API_CHECK) {
+ checkCriticalElement(expression);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalElement(expression);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving existence of an element.
+ * <p>
+ * For cases where failing fast is pretty important and not failing early could cause bugs that
+ * are much harder to debug.
+ */
+ public static void checkCriticalElement(boolean expression) {
+ if (!expression) {
+ throw new NoSuchElementException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving existence of an element.
+ */
+ public static void checkElement(boolean expression, Object errorMessage) {
+ if (API_CHECK) {
+ checkCriticalElement(expression, errorMessage);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalElement(expression, errorMessage);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving existence of an element.
+ * <p>
+ * For cases where failing fast is pretty important and not failing early could cause bugs that
+ * are much harder to debug.
+ */
+ public static void checkCriticalElement(boolean expression, Object errorMessage) {
+ if (!expression) {
+ throw new NoSuchElementException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the calling method.
+ */
+ public static void checkArgument(boolean expression) {
+ if (API_CHECK) {
+ checkCriticalArgument(expression);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalArgument(expression);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the calling method.
+ * <p>
+ * For cases where failing fast is pretty important and not failing early could cause bugs that
+ * are much harder to debug.
+ */
+ public static void checkCriticalArgument(boolean expression) {
+ if (!expression) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the calling method.
+ */
+ public static void checkArgument(boolean expression, Object errorMessage) {
+ if (API_CHECK) {
+ checkCriticalArgument(expression, errorMessage);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalArgument(expression, errorMessage);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the calling method.
+ * <p>
+ * For cases where failing fast is pretty important and not failing early could cause bugs that
+ * are much harder to debug.
+ */
+ public static void checkCriticalArgument(boolean expression, Object errorMessage) {
+ if (!expression) {
+ throw new IllegalArgumentException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the calling method.
+ */
+ public static void checkArgument(boolean expression, String errorMessageTemplate,
+ Object... errorMessageArgs) {
+ if (API_CHECK) {
+ checkCriticalArgument(expression, errorMessageTemplate, errorMessageArgs);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalArgument(expression, errorMessageTemplate, errorMessageArgs);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the calling method.
+ * <p>
+ * For cases where failing fast is pretty important and not failing early could cause bugs that
+ * are much harder to debug.
+ */
+ public static void checkCriticalArgument(boolean expression, String errorMessageTemplate,
+ Object... errorMessageArgs) {
+ if (!expression) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance, but not
+ * involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(boolean expression) {
+ if (API_CHECK) {
+ checkCritcalState(expression);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCritcalState(expression);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance, but not
+ * involving any parameters to the calling method.
+ * <p>
+ * For cases where failing fast is pretty important and not failing early could cause bugs that
+ * are much harder to debug.
+ */
+ public static void checkCritcalState(boolean expression) {
+ if (!expression) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance, but not
+ * involving any parameters to the calling method.
+ */
+ public static void checkState(boolean expression, Object errorMessage) {
+ if (API_CHECK) {
+ checkCriticalState(expression, errorMessage);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalState(expression, errorMessage);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance, but not
+ * involving any parameters to the calling method.
+ */
+ public static void checkCriticalState(boolean expression, Object errorMessage) {
+ if (!expression) {
+ throw new IllegalStateException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling method is not null.
+ */
+ public static <T> T checkNotNull(T reference) {
+ if (API_CHECK) {
+ checkCriticalNotNull(reference);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalNotNull(reference);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ return reference;
+ }
+
+ public static <T> T checkCriticalNotNull(T reference) {
+ if (reference == null) {
+ throw new NullPointerException();
+ }
+ return reference;
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling method is not null.
+ */
+ public static void checkNotNull(Object reference, Object errorMessage) {
+ if (API_CHECK) {
+ checkCriticalNotNull(reference, errorMessage);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalNotNull(reference, errorMessage);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ public static void checkCriticalNotNull(Object reference, Object errorMessage) {
+ if (reference == null) {
+ throw new NullPointerException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures that {@code size} specifies a valid array size (i.e. non-negative).
+ */
+ public static void checkArraySize(int size) {
+ if (API_CHECK) {
+ checkCriticalArraySize(size);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalArraySize(size);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ public static void checkCriticalArraySize(int size) {
+ if (size < 0) {
+ throw new NegativeArraySizeException("Negative array size: " + size);
+ }
+ }
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>element</i> in an array, list or string of size
+ * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive.
+ */
+ public static void checkElementIndex(int index, int size) {
+ if (BOUND_CHECK) {
+ checkCriticalElementIndex(index, size);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalElementIndex(index, size);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ public static void checkCriticalElementIndex(int index, int size) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+ }
+ }
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>position</i> in an array, list or string of
+ * size {@code size}. A position index may range from zero to {@code size}, inclusive.
+ */
+ public static void checkPositionIndex(int index, int size) {
+ if (BOUND_CHECK) {
+ checkCriticalPositionIndex(index, size);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalPositionIndex(index, size);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ public static void checkCriticalPositionIndex(int index, int size) {
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+ }
+ }
+
+ /**
+ * Ensures that {@code start} and {@code end} specify a valid <i>positions</i> in an array, list
+ * or string of size {@code size}, and are in order. A position index may range from zero to
+ * {@code size}, inclusive.
+ */
+ public static void checkPositionIndexes(int start, int end, int size) {
+ if (BOUND_CHECK) {
+ checkCriticalPositionIndexes(start, end, size);
+ } else if (CHECKED_MODE) {
+ try {
+ checkCriticalPositionIndexes(start, end, size);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /**
+ * Ensures that {@code start} and {@code end} specify a valid <i>positions</i> in an array, list
+ * or string of size {@code size}, and are in order. A position index may range from zero to
+ * {@code size}, inclusive.
+ */
+ public static void checkCriticalPositionIndexes(int start, int end, int size) {
+ if (start < 0) {
+ throw new IndexOutOfBoundsException("fromIndex: " + start + " < 0");
+ }
+ if (end > size) {
+ throw new IndexOutOfBoundsException("toIndex: " + end + " > size " + size);
+ }
+ if (start > end) {
+ throw new IllegalArgumentException("fromIndex: " + start + " > toIndex: " + end);
+ }
+ }
+
+ /**
+ * Checks that bounds are correct.
+ *
+ * @throw StringIndexOutOfBoundsException if the range is not legal
+ */
+ public static void checkStringBounds(int start, int end, int size) {
+ if (start < 0) {
+ throw new StringIndexOutOfBoundsException("fromIndex: " + start + " < 0");
+ }
+ if (end > size) {
+ throw new StringIndexOutOfBoundsException("toIndex: " + end + " > size " + size);
+ }
+ if (end < start) {
+ throw new StringIndexOutOfBoundsException("fromIndex: " + start + " > toIndex: " + end);
+ }
+ }
+
+ /**
+ * Substitutes each {@code %s} in {@code template} with an argument. These are matched by
+ * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than
+ * placeholders, the unmatched arguments will be appended to the end of the formatted message in
+ * square braces.
+ */
+ private static String format(String template, Object... args) {
+ template = String.valueOf(template); // null -> "null"
+
+ // start substituting the arguments into the '%s' placeholders
+ StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
+ int templateStart = 0;
+ int i = 0;
+ while (i < args.length) {
+ int placeholderStart = template.indexOf("%s", templateStart);
+ if (placeholderStart == -1) {
+ break;
+ }
+ builder.append(template.substring(templateStart, placeholderStart));
+ builder.append(args[i++]);
+ templateStart = placeholderStart + 2;
+ }
+ builder.append(template.substring(templateStart));
+
+ // if we run out of placeholders, append the extra args in square braces
+ if (i < args.length) {
+ builder.append(" [");
+ builder.append(args[i++]);
+ while (i < args.length) {
+ builder.append(", ");
+ builder.append(args[i++]);
+ }
+ builder.append(']');
+ }
+
+ return builder.toString();
+ }
+
+ // Hides the constructor for this static utility class.
+ private InternalPreconditions() { }
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
new file mode 100644
index 0000000..a1ecbde
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
@@ -0,0 +1,59 @@
+/*
+ * 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 void setPropertySafe(Object map, String key, Object value) /*-{
+ try {
+ // This may throw exception in strict mode.
+ map[key] = value;
+ } catch(ignored) { }
+ }-*/;
+
+ 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;
+ }-*/;
+
+ public static native String typeOf(Object o) /*-{
+ return typeof o;
+ }-*/;
+}
+
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/LongCompareHolder.java b/user/super/com/google/gwt/emul/javaemul/internal/LongCompareHolder.java
new file mode 100644
index 0000000..5a75c7c
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/LongCompareHolder.java
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * A helper class for long comparison.
+ */
+public class LongCompareHolder {
+ // TODO(dankurka): replace this with @JsFunction once its available in GWT.
+ public static native Object getLongComparator() /*-{
+ return @com.google.gwt.lang.LongLib::compare(*);
+ }-*/;
+}
+
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/StringHashCache.java b/user/super/com/google/gwt/emul/javaemul/internal/StringHashCache.java
new file mode 100644
index 0000000..d472de9
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/StringHashCache.java
@@ -0,0 +1,109 @@
+/*
+ * 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;
+
+import static javaemul.internal.Coercions.ensureInt;
+
+/**
+ * Hashcode caching for strings.
+ */
+class StringHashCache {
+ /**
+ * The "old" cache; it will be dumped when front is full.
+ */
+ private static Object back = createNativeObject();
+ /**
+ * Tracks the number of entries in front.
+ */
+ private static int count = 0;
+ /**
+ * The "new" cache; it will become back when it becomes full.
+ */
+ private static Object front = createNativeObject();
+ /**
+ * Pulled this number out of thin air.
+ */
+ private static final int MAX_CACHE = 256;
+
+ public static int getHashCode(String str) {
+ // Accesses must to be prefixed with ':' to prevent conflict with built-in
+ // JavaScript properties.
+ String key = ":" + str;
+
+ // Check the front store.
+ Object result = getProperty(front, key);
+ if (!JsUtils.isUndefined(result)) {
+ return unsafeCastToInt(result);
+ }
+ // Check the back store.
+ 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();
+ JsUtils.setIntProperty(front, key, hashCode);
+
+ return hashCode;
+ }
+
+ private static int compute(String str) {
+ int hashCode = 0;
+ int n = str.length();
+ int nBatch = n - 4;
+ int i = 0;
+
+ // Process batches of 4 characters at a time and add them to the hash coercing to 32 bits
+ while (i < nBatch) {
+ hashCode = str.charAt(i + 3)
+ + 31 * (str.charAt(i + 2)
+ + 31 * (str.charAt(i + 1)
+ + 31 * (str.charAt(i)
+ + 31 * hashCode)));
+
+ hashCode = ensureInt(hashCode); // make sure we don't overflow
+ i += 4;
+ }
+
+ // Now process the leftovers
+ while (i < n) {
+ hashCode = hashCode * 31 + str.charAt(i++);
+ }
+ hashCode = ensureInt(hashCode); // make sure we don't overflow
+
+ return hashCode;
+ }
+
+ private static void increment() {
+ if (count == MAX_CACHE) {
+ back = front;
+ front = createNativeObject();
+ count = 0;
+ }
+ ++count;
+ }
+
+ private static native Object getProperty(Object map, String key) /*-{
+ return map[key];
+ }-*/;
+
+ private static native Object createNativeObject() /*-{
+ return {};
+ }-*/;
+
+ private static native int unsafeCastToInt(Object o) /*-{
+ return o;
+ }-*/;
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/CompilerHint.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/CompilerHint.java
new file mode 100644
index 0000000..b887a6e
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/CompilerHint.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2009 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.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark another annotation as a compiler hint.
+ */
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface CompilerHint {
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/DoNotInline.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/DoNotInline.java
new file mode 100644
index 0000000..4e7321d
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/DoNotInline.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 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.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark a given method as not inlineable.
+ * <p>
+ * Internal SDK use only, might change or disappear at any time.
+ */
+@CompilerHint
+@Target(ElementType.METHOD)
+public @interface DoNotInline {
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/ForceInline.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/ForceInline.java
new file mode 100644
index 0000000..c0561c2
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/ForceInline.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 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.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark a given method as not inlineable.
+ * <p>
+ * Internal SDK use only, might change or disappear at any time.
+ */
+@CompilerHint
+@Target(ElementType.METHOD)
+public @interface ForceInline {
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/GwtIncompatible.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/GwtIncompatible.java
new file mode 100644
index 0000000..df8326f
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/GwtIncompatible.java
@@ -0,0 +1,32 @@
+/*
+ * 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.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A simple of a GwtIncompatible annotation for internal emulation use.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
+@Documented
+public @interface GwtIncompatible {
+ String value() default "";
+}
\ No newline at end of file
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/HasNoSideEffects.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/HasNoSideEffects.java
new file mode 100644
index 0000000..f21fcff
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/HasNoSideEffects.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 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.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark a given method as side-effect free.
+ * <p>
+ * Internal SDK use only, might change or disappear at any time.
+ */
+@CompilerHint
+@Target(ElementType.METHOD)
+public @interface HasNoSideEffects {
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java
new file mode 100644
index 0000000..ddab6cd
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009 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.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark a given method as being specialized. If the specified
+ * parameters and return context match of a JMethodCall, then the call
+ * is retargeted at the specialized version.
+ */
+@Target(ElementType.METHOD)
+@CompilerHint
+public @interface SpecializeMethod {
+
+ /**
+ * Represents a type that matches any type, even void.
+ */
+ interface ANY { }
+
+ /**
+ * List of parameter types, matched via assignability.
+ */
+ Class<?>[] params();
+
+ /**
+ * List of return types to match, or null if you don't care.
+ */
+ Class<?> returns() default ANY.class;
+
+ /**
+ * The name of the method to target. It must have a signature matching to the {@link #params()}.
+ */
+ String target();
+}