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

Array-like AbstractJSObject-based instance not treated as array by native array functions

    Details

    • Subcomponent:
    • Resolved In Build:
      b148
    • CPU:
      x86
    • OS:
      generic

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_92"
      Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 10.0.10586]

      A DESCRIPTION OF THE PROBLEM :
      When calling the native array function "concat", an argument that is an AbstractJSObject array is not treated as an array. Array.concat should use the items of an array argument, but instead it treats the entire AbstractJSObject array as a single item.

      However, the documentation for JSObject states that "Nashorn will treat objects of such classes just like nashorn script objects." (https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/JSObject.html)

      (This kind of behavior applies in other situations as well, Array.concat is just an example.)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached Java program.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      first,red,green,blue
      ACTUAL -
      first,ArrayLike{items=[red, green, blue]}

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package org.lab;

      import jdk.nashorn.api.scripting.AbstractJSObject;
      import jdk.nashorn.api.scripting.JSObject;
      import jdk.nashorn.api.scripting.NashornScriptEngineFactory;

      import javax.script.*;
      import java.util.*;

      public class Main {

          public static void main(String[] args) throws ScriptException {

              ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
              Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);

              JSObject array = new ArrayLike(new String[] { "red", "green", "blue" });
              bindings.put("theArray", array);

              String script = "print(['first'].concat(theArray));";

              engine.eval(script, bindings);
          }

          static class ArrayLike extends AbstractJSObject {

              private final String[] items;

              ArrayLike(String[] items) {
                  this.items = items;
              }

              @Override
              public Object getMember(String name) {
                  if ("length".equals(name)) return items.length;
                  if ("toString".equals(name)) return ValueAsFunction.forValue(toString());
                  return null;
              }

              @Override
              public Object getSlot(int index) {
                  return hasSlot(index) ? items[index] : null;
              }

              @Override
              public boolean hasSlot(int slot) {
                  return slot >= 0 && slot < items.length;
              }

              @Override
              public boolean isArray() {
                  return true;
              }

              @Override
              public String toString() {
                  return "ArrayLike{items=" + Arrays.toString(items) + "}";
              }
          }

          static class ValueAsFunction extends AbstractJSObject {
              private final Object value;

              ValueAsFunction(Object value) {
                  this.value = value;
              }

              @Override
              public Object call(Object thiz, Object... args) {
                  return value;
              }

              @Override
              public boolean isFunction() {
                  return true;
              }

              static ValueAsFunction forValue(Object value) {
                  return new ValueAsFunction(value);
              }
          }
      }

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

        Attachments

          Activity

            People

            • Assignee:
              hannesw Hannes Wallnoefer
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: