Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8076226

nashorn: java.lang.String behavior of replace and split not as java methods

XMLWordPrintable

    • x86
    • linux_redhat_6.0

      FULL PRODUCT VERSION :
      java version "1.8.0_40"
      Java(TM) SE Runtime Environment (build 1.8.0_40-b26)
      Java HotSpot(TM) Client VM (build 25.40-b25, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Red Hat Enterprise Linux Server release 6.4 (Santiago)

      A DESCRIPTION OF THE PROBLEM :
      Behavior of the String object in Nashorn script engine is different for replace and split.
      Though the object is java.lang.String the replace and split works like the javascript native String object.

      REGRESSION. Last worked in version 8u40

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      - Create a script engine
      - Execute a javascript with java.lang.String replace or split
      - Expected behavior of replace method is to replace all the character sequence with replacement string

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      PQR-PQR-PQR
      ACTUAL -
      PQR-ABC-ABC

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import javax.script.Compilable;
      import javax.script.CompiledScript;
      import javax.script.ScriptContext;
      import javax.script.ScriptEngine;
      import javax.script.ScriptEngineManager;
      import javax.script.SimpleScriptContext;

      public class TestJavascript {

          public static void main(String[] args) throws Exception {
              
              ScriptEngineManager scriptManager = new ScriptEngineManager();
              ScriptEngine scriptEngine = scriptManager.getEngineByName("JavaScript");
              Compilable jsCompile = (Compilable) scriptEngine;
              
              CompiledScript cs = jsCompile.compile("java.lang.System.out.println(new java.lang.String(\"ABC-ABC-ABC\").replace(\"ABC\", \"PQR\"));");

              ScriptContext sc = new SimpleScriptContext();
              cs.eval(sc);
          }
              
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Change the Javascript prototype for replace and split with same implementation as in Java.
      ------------------------------------------------------------------------
      String.prototype.replace = function(target, replacement) {
          var cstring = new java.lang.String(this);
          return Pattern.compile(target, Pattern.LITERAL).matcher(cstring).replaceAll(Matcher.quoteReplacement(replacement));
      }

      String.prototype.split = function(regex, limit) {
          var cstring = new java.lang.String(this);
          var StringArrayType = Java.type("java.lang.String[]")
          var ch = 0;
          if (((regex.length() == 1 &&
                      ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
                  (regex.length() == 2 &&
                      regex.charAt(0) == '\\' &&
                      (((ch = regex.charAt(1)) - '0') | ('9' - ch)) < 0 &&
                      ((ch - 'a') | ('z' - ch)) < 0 &&
                      ((ch - 'A') | ('Z' - ch)) < 0)) &&
              (ch < '\uD800' ||
                  ch > '\uDBFF')) {
              var off = 0;
              var next = 0;
              var limited = limit > 0;
              var list = new java.util.ArrayList();
              while ((next = cstring.indexOf(ch, off)) != -1) {
                  if (!limited || list.size() < limit - 1) {
                      list.add(cstring.substring(off, next));
                      off = next + 1;
                  } else { // last one
                      //assert (list.size() == limit - 1);
                      list.add(cstring.substring(off, cstring.length()));
                      off = cstring.length();
                      break;
                  }
              }
              // If no match was found, return this
              if (off == 0) {
                  var ret = new StringArrayType(1);
                  ret[0] = cstring;
                  return ret;
              }
              // Add remaining segment
              if (!limited || list.size() < limit) {
                  list.add(cstring.substring(off, cstring.length()));
              }
              // Construct result
              var resultSize = list.size();
              if (limit == 0) {
                  while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
                      resultSize--;
                  }
              }
              var result = new StringArrayType(resultSize);
              return list.subList(0, resultSize).toArray(result);
          }
          return Pattern.compile(regex).split(cstring, limit);
      }

      SUPPORT :
      YES

            hannesw Hannes Wallnoefer
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: