google / j2cl

Java to Closure JavaScript transpiler
Apache License 2.0
1.23k stars 144 forks source link

"abc".split("") get error result ["","a","b","c"] #143

Open xiaoxidashen opened 2 years ago

xiaoxidashen commented 2 years ago

Describe the bug

"abc".split("") get error array ["","a","b","c"]

To Reproduce

use j2clmavenplugin

//in java MathUtil.java
package cn.util;

import jsinterop.annotations.JsType;

@JsType
public class MathUtil {

    public static native void ppp(String s);

    public static void test() {
        String s = "abc";
        ppp(s);
        String[] split = s.split("");
        ppp("String.valueOf(split)"+"["+String.valueOf(split)+"]");
        ppp("split.length "+split.length+"");
        for (String s1 : split) {
            ppp("["+s1+"]");
        }
    }
}
//MathUtil.native.js
setTimeout(function() {

    MathUtil.ppp = function (s) {
        console.log(s);
    }

    MathUtil.test();

}, 0);

get result in browser console

abc
String.valueOf(split)[,a,b,c]
split.length 4
[]
[a]
[b]
[c]

"abc".split("") The expected result is ["a","b","c"]

gkdn commented 2 years ago

As commented in the Javadoc [1], unfortunately java.lang.String.split emulation has a lot of incompatibilities with JDK. String.split is using regular expressions, and it is impractical to ship a complete Java compatible regex emulation to web. Instead we cheat in this method, try to mimic Java split behavior using JS regex. Although it works mostly the same, this results in different behavior for many edge cases.

Depend on your use case, one alternative API that would work consistently with JVM is the Guava's Splitter which doesn't use regex.

(Being said that split("") is surprisingly uncommon so maybe it is worthwhile special case that scenario 😞 )

[1]

Regular expressions vary from the standard implementation. The regex parameter is interpreted by JavaScript as a JavaScript regular expression. For consistency, use only the subset of regular expression syntax common to both Java and JavaScript.

gkdn commented 2 years ago

(Note: in offline discussion rluble@ pointed out that the JDK behavior is actually changed from Java 7 to Java 8 where J2CL is following the earlier behavior)