Move String.split to Java code.

Change-Id: Icd60ddc3a3f4493b25e0b4e33b1047c4fb4ca19f
diff --git a/dev/core/super/javaemul/internal/ArrayStamper.java b/dev/core/super/javaemul/internal/ArrayStamper.java
index 5c3d828..a6a9ed2 100644
--- a/dev/core/super/javaemul/internal/ArrayStamper.java
+++ b/dev/core/super/javaemul/internal/ArrayStamper.java
@@ -18,7 +18,7 @@
 /**
  * A utility to provide array stamping. Provided as a separate class to simplify super-source.
  */
-public class ArrayStamper {
+class ArrayStamper {
   public static native <T> T[] stampJavaTypeInfo(Object array, T[] referenceType) /*-{
     return @com.google.gwt.lang.Array::stampJavaTypeInfo(*)(array, referenceType);
   }-*/;
diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java
index 825faa6..85d9059 100644
--- a/user/super/com/google/gwt/emul/java/lang/String.java
+++ b/user/super/com/google/gwt/emul/java/lang/String.java
@@ -26,7 +26,6 @@
 import java.util.Locale;
 
 import javaemul.internal.ArrayHelper;
-import javaemul.internal.ArrayStamper;
 import javaemul.internal.EmulatedCharset;
 import javaemul.internal.HashCodes;
 import javaemul.internal.annotations.DoNotInline;
@@ -531,7 +530,7 @@
     // in order to escape regexp special characters (e.g. '.').
     String hex = Integer.toHexString(from);
     String regex = "\\u" + "0000".substring(hex.length()) + hex;
-    Object jsRegEx = createRegEx(regex, "g");
+    Object jsRegEx = createRegExp(regex, "g");
     String replace = fromCharCode(to);
     return replace(jsRegEx, replace);
   }
@@ -566,7 +565,7 @@
    */
   public String replaceAll(String regex, String replace) {
     replace = translateReplaceString(replace);
-    Object jsRegEx = createRegEx(regex, "g");
+    Object jsRegEx = createRegExp(regex, "g");
     return replace(jsRegEx, replace);
   }
 
@@ -580,18 +579,34 @@
    */
   public String replaceFirst(String regex, String replace) {
     replace = translateReplaceString(replace);
-    Object jsRegEx = createRegEx(regex, "");
+    Object jsRegEx = createRegExp(regex, "");
     return replace(jsRegEx, replace);
   }
 
-  private native Object createRegEx(String regex, String mode) /*-{
+  private static native Object createRegExp(String regex, String mode) /*-{
     return RegExp(regex, mode);
   }-*/;
 
+  private static native Object execRegExp(Object regex, String value) /*-{
+    return regex.exec(value);
+  }-*/;
+
+  private static native int resetRegExpLastIndex(Object compiledRegEx) /*-{
+    compiledRegEx.lastIndex = 0;
+  }-*/;
+
   private native String replace(Object regex, String replace) /*-{
     return this.replace(regex, replace);
   }-*/;
 
+  private static native int getMatchIndex(Object matchObject) /*-{
+    return matchObject.index;
+  }-*/;
+
+  private static native int getMatchLength(Object matchObject, int index) /*-{
+    return matchObject[index].length;
+  }-*/;
+
   /**
    * Regular expressions vary from the standard implementation. The
    * <code>regex</code> parameter is interpreted by JavaScript as a JavaScript
@@ -611,37 +626,32 @@
    * TODO(jat): properly handle Java regex syntax
    */
   public String[] split(String regex, int maxMatch) {
-    String[] jsArrayString = split0(regex, maxMatch);
-    ArrayStamper.stampJavaTypeInfo(jsArrayString, new String[0]);
-    return jsArrayString;
-  }
-
-  private native String[] split0(String regex, int maxMatch) /*-{
     // The compiled regular expression created from the string
-    var compiled = new RegExp(regex, "g");
+    Object compiled = createRegExp(regex, "g");
     // the Javascipt array to hold the matches prior to conversion
-    var out = [];
+    String[] out = new String[0];
     // how many matches performed so far
-    var count = 0;
+    int count = 0;
     // The current string that is being matched; trimmed as each piece matches
-    var trail = this;
+    String trail = this;
     // used to detect repeated zero length matches
     // Must be null to start with because the first match of "" makes no
     // progress by intention
-    var lastTrail = null;
+    String lastTrail = null;
     // We do the split manually to avoid Javascript incompatibility
     while (true) {
       // None of the information in the match returned are useful as we have no
       // subgroup handling
-      var matchObj = compiled.exec(trail);
+      Object matchObj = execRegExp(compiled, trail);
       if (matchObj == null || trail == "" || (count == (maxMatch - 1) && maxMatch > 0)) {
         out[count] = trail;
         break;
       } else {
-        out[count] = trail.substring(0, matchObj.index);
-        trail = trail.substring(matchObj.index + matchObj[0].length, trail.length);
+        out[count] = trail.substring(0, getMatchIndex(matchObj));
+        trail = trail.substring(
+            getMatchIndex(matchObj) + getMatchLength(matchObj, 0), trail.length());
         // Force the compiled pattern to reset internal state
-        compiled.lastIndex = 0;
+        resetRegExpLastIndex(compiled);
         // Only one zero length match per character to ensure termination
         if (lastTrail == trail) {
           out[count] = trail.substring(0, 1);
@@ -654,17 +664,17 @@
     // all blank delimiters at the end are supposed to disappear if maxMatch == 0;
     // however, if the input string is empty, the output should consist of a
     // single empty string
-    if (maxMatch == 0 && this.length > 0) {
-      var lastNonEmpty = out.length;
+    if (maxMatch == 0 && this.length() > 0) {
+      int lastNonEmpty = out.length;
       while (lastNonEmpty > 0 && out[lastNonEmpty - 1] == "") {
         --lastNonEmpty;
       }
       if (lastNonEmpty < out.length) {
-        out.splice(lastNonEmpty, out.length - lastNonEmpty);
+        ArrayHelper.setLength(out, lastNonEmpty);
       }
     }
     return out;
-  }-*/;
+  }
 
   public boolean startsWith(String prefix) {
     return startsWith(prefix, 0);