8027236: Ensure ScriptObject and ConsString aren't visible to Java

Fri, 01 Nov 2013 15:36:33 +0100

author
attila
date
Fri, 01 Nov 2013 15:36:33 +0100
changeset 663
98bab0cdd7bf
parent 662
ae5f2130c3b9
child 664
144861e24260
child 665
dcedc753fd09

8027236: Ensure ScriptObject and ConsString aren't visible to Java
Reviewed-by: lagergren, sundar

src/jdk/nashorn/api/scripting/ScriptObjectMirror.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/Global.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ConsString.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/JSType.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/Bootstrap.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8027236.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8027236.js.EXPECTED file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Fri Nov 01 19:54:48 2013 +0530
     1.2 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Fri Nov 01 15:36:33 2013 +0100
     1.3 @@ -41,6 +41,7 @@
     1.4  import java.util.Set;
     1.5  import java.util.concurrent.Callable;
     1.6  import javax.script.Bindings;
     1.7 +import jdk.nashorn.internal.runtime.ConsString;
     1.8  import jdk.nashorn.internal.runtime.Context;
     1.9  import jdk.nashorn.internal.runtime.GlobalObject;
    1.10  import jdk.nashorn.internal.runtime.JSType;
    1.11 @@ -594,14 +595,20 @@
    1.12      }
    1.13  
    1.14      /**
    1.15 -     * Make a script object mirror on given object if needed.
    1.16 +     * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings.
    1.17       *
    1.18 -     * @param obj object to be wrapped
    1.19 -     * @param homeGlobal global to which this object belongs
    1.20 -     * @return wrapped object
    1.21 +     * @param obj object to be wrapped/converted
    1.22 +     * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
    1.23 +     * @return wrapped/converted object
    1.24       */
    1.25      public static Object wrap(final Object obj, final ScriptObject homeGlobal) {
    1.26 -        return (obj instanceof ScriptObject && homeGlobal != null) ? new ScriptObjectMirror((ScriptObject)obj, homeGlobal) : obj;
    1.27 +        if(obj instanceof ScriptObject) {
    1.28 +            return homeGlobal != null ? new ScriptObjectMirror((ScriptObject)obj, homeGlobal) : obj;
    1.29 +        }
    1.30 +        if(obj instanceof ConsString) {
    1.31 +            return obj.toString();
    1.32 +        }
    1.33 +        return obj;
    1.34      }
    1.35  
    1.36      /**
     2.1 --- a/src/jdk/nashorn/internal/objects/Global.java	Fri Nov 01 19:54:48 2013 +0530
     2.2 +++ b/src/jdk/nashorn/internal/objects/Global.java	Fri Nov 01 15:36:33 2013 +0100
     2.3 @@ -53,19 +53,19 @@
     2.4  import jdk.nashorn.internal.runtime.GlobalObject;
     2.5  import jdk.nashorn.internal.runtime.JSType;
     2.6  import jdk.nashorn.internal.runtime.NativeJavaPackage;
     2.7 +import jdk.nashorn.internal.runtime.PropertyDescriptor;
     2.8  import jdk.nashorn.internal.runtime.PropertyMap;
     2.9 +import jdk.nashorn.internal.runtime.Scope;
    2.10  import jdk.nashorn.internal.runtime.ScriptEnvironment;
    2.11 -import jdk.nashorn.internal.runtime.PropertyDescriptor;
    2.12 -import jdk.nashorn.internal.runtime.arrays.ArrayData;
    2.13 -import jdk.nashorn.internal.runtime.regexp.RegExpResult;
    2.14 -import jdk.nashorn.internal.runtime.Scope;
    2.15  import jdk.nashorn.internal.runtime.ScriptFunction;
    2.16  import jdk.nashorn.internal.runtime.ScriptObject;
    2.17  import jdk.nashorn.internal.runtime.ScriptRuntime;
    2.18  import jdk.nashorn.internal.runtime.ScriptingFunctions;
    2.19  import jdk.nashorn.internal.runtime.Source;
    2.20 +import jdk.nashorn.internal.runtime.arrays.ArrayData;
    2.21  import jdk.nashorn.internal.runtime.linker.Bootstrap;
    2.22  import jdk.nashorn.internal.runtime.linker.InvokeByName;
    2.23 +import jdk.nashorn.internal.runtime.regexp.RegExpResult;
    2.24  import jdk.nashorn.internal.scripts.JO;
    2.25  
    2.26  /**
     3.1 --- a/src/jdk/nashorn/internal/objects/NativeObject.java	Fri Nov 01 19:54:48 2013 +0530
     3.2 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java	Fri Nov 01 15:36:33 2013 +0100
     3.3 @@ -60,6 +60,7 @@
     3.4  import jdk.nashorn.internal.runtime.ScriptRuntime;
     3.5  import jdk.nashorn.internal.runtime.linker.Bootstrap;
     3.6  import jdk.nashorn.internal.runtime.linker.InvokeByName;
     3.7 +import jdk.nashorn.internal.runtime.linker.NashornBeansLinker;
     3.8  
     3.9  /**
    3.10   * ECMA 15.2 Object objects
    3.11 @@ -729,8 +730,7 @@
    3.12              final MethodType methodType, final Object source) {
    3.13          final GuardedInvocation inv;
    3.14          try {
    3.15 -            inv = linker.getGuardedInvocation(createLinkRequest(operation, methodType, source),
    3.16 -                Bootstrap.getLinkerServices());
    3.17 +            inv = NashornBeansLinker.getGuardedInvocation(linker, createLinkRequest(operation, methodType, source), Bootstrap.getLinkerServices());
    3.18              assert passesGuard(source, inv.getGuard());
    3.19          } catch(RuntimeException|Error e) {
    3.20              throw e;
     4.1 --- a/src/jdk/nashorn/internal/runtime/ConsString.java	Fri Nov 01 19:54:48 2013 +0530
     4.2 +++ b/src/jdk/nashorn/internal/runtime/ConsString.java	Fri Nov 01 15:36:33 2013 +0100
     4.3 @@ -57,10 +57,7 @@
     4.4  
     4.5      @Override
     4.6      public String toString() {
     4.7 -        if (!flat) {
     4.8 -            flatten();
     4.9 -        }
    4.10 -        return (String) left;
    4.11 +        return (String) flattened();
    4.12      }
    4.13  
    4.14      @Override
    4.15 @@ -70,18 +67,19 @@
    4.16  
    4.17      @Override
    4.18      public char charAt(final int index) {
    4.19 -        if (!flat) {
    4.20 -            flatten();
    4.21 -        }
    4.22 -        return left.charAt(index);
    4.23 +        return flattened().charAt(index);
    4.24      }
    4.25  
    4.26      @Override
    4.27      public CharSequence subSequence(final int start, final int end) {
    4.28 +        return flattened().subSequence(start, end);
    4.29 +    }
    4.30 +
    4.31 +    private CharSequence flattened() {
    4.32          if (!flat) {
    4.33              flatten();
    4.34          }
    4.35 -        return left.subSequence(start, end);
    4.36 +        return left;
    4.37      }
    4.38  
    4.39      private void flatten() {
     5.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java	Fri Nov 01 19:54:48 2013 +0530
     5.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java	Fri Nov 01 15:36:33 2013 +0100
     5.3 @@ -883,7 +883,7 @@
     5.4       */
     5.5      public static Object toJavaArray(final Object obj, final Class<?> componentType) {
     5.6          if (obj instanceof ScriptObject) {
     5.7 -            return convertArray(((ScriptObject)obj).getArray().asObjectArray(), componentType);
     5.8 +            return ((ScriptObject)obj).getArray().asArrayOfType(componentType);
     5.9          } else if (obj instanceof JSObject) {
    5.10              final ArrayLikeIterator<?> itr = ArrayLikeIterator.arrayLikeIterator(obj);
    5.11              final int len = (int) itr.getLength();
    5.12 @@ -908,6 +908,15 @@
    5.13       * @return converted Java array
    5.14       */
    5.15      public static Object convertArray(final Object[] src, final Class<?> componentType) {
    5.16 +        if(componentType == Object.class) {
    5.17 +            for(int i = 0; i < src.length; ++i) {
    5.18 +                final Object e = src[i];
    5.19 +                if(e instanceof ConsString) {
    5.20 +                    src[i] = e.toString();
    5.21 +                }
    5.22 +            }
    5.23 +        }
    5.24 +
    5.25          final int l = src.length;
    5.26          final Object dst = Array.newInstance(componentType, l);
    5.27          final MethodHandle converter = Bootstrap.getLinkerServices().getTypeConverter(Object.class, componentType);
     6.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Fri Nov 01 19:54:48 2013 +0530
     6.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Fri Nov 01 15:36:33 2013 +0100
     6.3 @@ -63,7 +63,7 @@
     6.4          final DynamicLinkerFactory factory = new DynamicLinkerFactory();
     6.5          factory.setPrioritizedLinkers(new NashornLinker(), new NashornPrimitiveLinker(), new NashornStaticClassLinker(),
     6.6                  new BoundDynamicMethodLinker(), new JavaSuperAdapterLinker(), new JSObjectLinker(), new ReflectionCheckLinker());
     6.7 -        factory.setFallbackLinkers(new BeansLinker(), new NashornBottomLinker());
     6.8 +        factory.setFallbackLinkers(new NashornBeansLinker(), new NashornBottomLinker());
     6.9          factory.setSyncOnRelink(true);
    6.10          final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1);
    6.11          if (relinkThreshold > -1) {
     7.1 --- a/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java	Fri Nov 01 19:54:48 2013 +0530
     7.2 +++ b/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java	Fri Nov 01 15:36:33 2013 +0100
     7.3 @@ -72,7 +72,7 @@
     7.4                  type.changeParameterType(0, dynamicMethodClass).changeParameterType(1, boundThis.getClass()));
     7.5  
     7.6          // Delegate to BeansLinker
     7.7 -        final GuardedInvocation inv = BeansLinker.getLinkerForClass(dynamicMethodClass).getGuardedInvocation(
     7.8 +        final GuardedInvocation inv = NashornBeansLinker.getGuardedInvocation(BeansLinker.getLinkerForClass(dynamicMethodClass),
     7.9                  linkRequest.replaceArguments(newDescriptor, args), linkerServices);
    7.10          if(inv == null) {
    7.11              return null;
     8.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java	Fri Nov 01 19:54:48 2013 +0530
     8.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java	Fri Nov 01 15:36:33 2013 +0100
     8.3 @@ -100,8 +100,9 @@
     8.4                  type.changeParameterType(0, adapterClass), 0);
     8.5  
     8.6          // Delegate to BeansLinker
     8.7 -        final GuardedInvocation guardedInv = BeansLinker.getLinkerForClass(adapterClass).getGuardedInvocation(
     8.8 -                linkRequest.replaceArguments(newDescriptor, args), linkerServices);
     8.9 +        final GuardedInvocation guardedInv = NashornBeansLinker.getGuardedInvocation(
    8.10 +                BeansLinker.getLinkerForClass(adapterClass), linkRequest.replaceArguments(newDescriptor, args),
    8.11 +                linkerServices);
    8.12  
    8.13          final MethodHandle guard = IS_ADAPTER_OF_CLASS.bindTo(adapterClass);
    8.14          if(guardedInv == null) {
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Fri Nov 01 15:36:33 2013 +0100
     9.3 @@ -0,0 +1,127 @@
     9.4 +/*
     9.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.  Oracle designates this
    9.11 + * particular file as subject to the "Classpath" exception as provided
    9.12 + * by Oracle in the LICENSE file that accompanied this code.
    9.13 + *
    9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.17 + * version 2 for more details (a copy is included in the LICENSE file that
    9.18 + * accompanied this code).
    9.19 + *
    9.20 + * You should have received a copy of the GNU General Public License version
    9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.23 + *
    9.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    9.25 + * or visit www.oracle.com if you need additional information or have any
    9.26 + * questions.
    9.27 + */
    9.28 +
    9.29 +package jdk.nashorn.internal.runtime.linker;
    9.30 +
    9.31 +import java.lang.invoke.MethodHandle;
    9.32 +import java.lang.invoke.MethodHandles;
    9.33 +import java.lang.invoke.MethodType;
    9.34 +import jdk.internal.dynalink.beans.BeansLinker;
    9.35 +import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
    9.36 +import jdk.internal.dynalink.linker.GuardedInvocation;
    9.37 +import jdk.internal.dynalink.linker.GuardingDynamicLinker;
    9.38 +import jdk.internal.dynalink.linker.LinkRequest;
    9.39 +import jdk.internal.dynalink.linker.LinkerServices;
    9.40 +import jdk.internal.dynalink.support.Lookup;
    9.41 +import jdk.nashorn.internal.runtime.ConsString;
    9.42 +
    9.43 +/**
    9.44 + * This linker delegates to a {@code BeansLinker} but passes it a special linker services object that has a modified
    9.45 + * {@code asType} method that will ensure that we never pass internal engine objects that should not be externally
    9.46 + * observable (currently only ConsString) to Java APIs, but rather that we flatten it into a String. We can't just add
    9.47 + * this functionality as custom converters via {@code GuaardingTypeConverterFactory}, since they are not consulted when
    9.48 + * the target method handle parameter signature is {@code Object}.
    9.49 + */
    9.50 +public class NashornBeansLinker implements GuardingDynamicLinker {
    9.51 +    private static final MethodHandle EXPORT_ARGUMENT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportArgument", Object.class, Object.class);
    9.52 +
    9.53 +    private final BeansLinker beansLinker = new BeansLinker();
    9.54 +
    9.55 +    @Override
    9.56 +    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
    9.57 +        return getGuardedInvocation(beansLinker, linkRequest, linkerServices);
    9.58 +    }
    9.59 +
    9.60 +    /**
    9.61 +     * Delegates to the specified linker but injects its linker services wrapper so that it will apply all special
    9.62 +     * conversions that this class does.
    9.63 +     * @param delegateLinker the linker to which the actual work is delegated to.
    9.64 +     * @param linkRequest the delegated link request
    9.65 +     * @param linkerServices the original link services that will be augmented with special conversions
    9.66 +     * @return the guarded invocation from the delegate, possibly augmented with special conversions
    9.67 +     * @throws Exception if the delegate throws an exception
    9.68 +     */
    9.69 +    public static GuardedInvocation getGuardedInvocation(final GuardingDynamicLinker delegateLinker, final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
    9.70 +        return delegateLinker.getGuardedInvocation(linkRequest, new NashornBeansLinkerServices(linkerServices));
    9.71 +    }
    9.72 +
    9.73 +    @SuppressWarnings("unused")
    9.74 +    private static Object exportArgument(final Object arg) {
    9.75 +        return arg instanceof ConsString ? arg.toString() : arg;
    9.76 +    }
    9.77 +
    9.78 +    private static class NashornBeansLinkerServices implements LinkerServices {
    9.79 +        private final LinkerServices linkerServices;
    9.80 +
    9.81 +        NashornBeansLinkerServices(final LinkerServices linkerServices) {
    9.82 +            this.linkerServices = linkerServices;
    9.83 +        }
    9.84 +
    9.85 +        @Override
    9.86 +        public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
    9.87 +            final MethodHandle typed = linkerServices.asType(handle, fromType);
    9.88 +
    9.89 +            final MethodType handleType = handle.type();
    9.90 +            final int paramCount = handleType.parameterCount();
    9.91 +            assert fromType.parameterCount() == handleType.parameterCount();
    9.92 +
    9.93 +            MethodHandle[] filters = null;
    9.94 +            for(int i = 0; i < paramCount; ++i) {
    9.95 +                if(shouldConvert(handleType.parameterType(i), fromType.parameterType(i))) {
    9.96 +                    if(filters == null) {
    9.97 +                        filters = new MethodHandle[paramCount];
    9.98 +                    }
    9.99 +                    filters[i] = EXPORT_ARGUMENT;
   9.100 +                }
   9.101 +            }
   9.102 +
   9.103 +            return filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed;
   9.104 +        }
   9.105 +
   9.106 +        private static boolean shouldConvert(final Class<?> handleType, final Class<?> fromType) {
   9.107 +            return handleType == Object.class && fromType == Object.class;
   9.108 +        }
   9.109 +
   9.110 +        @Override
   9.111 +        public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
   9.112 +            return linkerServices.getTypeConverter(sourceType, targetType);
   9.113 +        }
   9.114 +
   9.115 +        @Override
   9.116 +        public boolean canConvert(final Class<?> from, final Class<?> to) {
   9.117 +            return linkerServices.canConvert(from, to);
   9.118 +        }
   9.119 +
   9.120 +        @Override
   9.121 +        public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception {
   9.122 +            return linkerServices.getGuardedInvocation(linkRequest);
   9.123 +        }
   9.124 +
   9.125 +        @Override
   9.126 +        public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
   9.127 +            return linkerServices.compareConversion(sourceType, targetType1, targetType2);
   9.128 +        }
   9.129 +    }
   9.130 +}
    10.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java	Fri Nov 01 19:54:48 2013 +0530
    10.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java	Fri Nov 01 15:36:33 2013 +0100
    10.3 @@ -93,7 +93,7 @@
    10.4      }
    10.5  
    10.6      private static GuardedInvocation delegate(LinkerServices linkerServices, final LinkRequest request) throws Exception {
    10.7 -        return staticClassLinker.getGuardedInvocation(request, linkerServices);
    10.8 +        return NashornBeansLinker.getGuardedInvocation(staticClassLinker, request, linkerServices);
    10.9      }
   10.10  
   10.11      private static GuardedInvocation checkNullConstructor(final GuardedInvocation ctorInvocation, final Class<?> receiverClass) {
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/test/script/basic/JDK-8027236.js	Fri Nov 01 15:36:33 2013 +0100
    11.3 @@ -0,0 +1,37 @@
    11.4 +/*
    11.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + * 
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.
   11.11 + * 
   11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.15 + * version 2 for more details (a copy is included in the LICENSE file that
   11.16 + * accompanied this code).
   11.17 + * 
   11.18 + * You should have received a copy of the GNU General Public License version
   11.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.21 + * 
   11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   11.23 + * or visit www.oracle.com if you need additional information or have any
   11.24 + * questions.
   11.25 + */
   11.26 +
   11.27 +/**
   11.28 + * JDK-8027236: Ensure ScriptObject and ConsString aren't visible to Java
   11.29 + *
   11.30 + * @test
   11.31 + * @run
   11.32 + */
   11.33 +
   11.34 +// Check that ConsString is flattened
   11.35 +var m = new java.util.HashMap()
   11.36 +var x = "f"
   11.37 +x += "oo"
   11.38 +m.put(x, "bar")
   11.39 +print(m.get("foo"))
   11.40 +// Note: many more tests are run by the JavaExportImportTest TestNG class.
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/test/script/basic/JDK-8027236.js.EXPECTED	Fri Nov 01 15:36:33 2013 +0100
    12.3 @@ -0,0 +1,1 @@
    12.4 +bar
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java	Fri Nov 01 15:36:33 2013 +0100
    13.3 @@ -0,0 +1,99 @@
    13.4 +/*
    13.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.  Oracle designates this
   13.11 + * particular file as subject to the "Classpath" exception as provided
   13.12 + * by Oracle in the LICENSE file that accompanied this code.
   13.13 + *
   13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.17 + * version 2 for more details (a copy is included in the LICENSE file that
   13.18 + * accompanied this code).
   13.19 + *
   13.20 + * You should have received a copy of the GNU General Public License version
   13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.23 + *
   13.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   13.25 + * or visit www.oracle.com if you need additional information or have any
   13.26 + * questions.
   13.27 + */
   13.28 +
   13.29 +package jdk.nashorn.api.javaaccess;
   13.30 +
   13.31 +import static org.testng.AssertJUnit.assertEquals;
   13.32 +
   13.33 +import java.util.HashMap;
   13.34 +import java.util.Map;
   13.35 +import javax.script.Bindings;
   13.36 +import javax.script.ScriptContext;
   13.37 +import javax.script.ScriptEngine;
   13.38 +import javax.script.ScriptEngineManager;
   13.39 +import javax.script.ScriptException;
   13.40 +import jdk.nashorn.api.scripting.JSObject;
   13.41 +import org.testng.TestNG;
   13.42 +import org.testng.annotations.AfterClass;
   13.43 +import org.testng.annotations.BeforeClass;
   13.44 +import org.testng.annotations.Test;
   13.45 +
   13.46 +public class ConsStringTest {
   13.47 +    private static ScriptEngine e = null;
   13.48 +
   13.49 +    public static void main(final String[] args) {
   13.50 +        TestNG.main(args);
   13.51 +    }
   13.52 +
   13.53 +    @BeforeClass
   13.54 +    public static void setUpClass() throws ScriptException {
   13.55 +        e = new ScriptEngineManager().getEngineByName("nashorn");
   13.56 +    }
   13.57 +
   13.58 +    @AfterClass
   13.59 +    public static void tearDownClass() {
   13.60 +        e = null;
   13.61 +    }
   13.62 +
   13.63 +    @Test
   13.64 +    public void testConsStringFlattening() throws ScriptException {
   13.65 +        final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
   13.66 +        final Map<Object, Object> m = new HashMap<>();
   13.67 +        b.put("m", m);
   13.68 +        e.eval("var x = 'f'; x += 'oo'; var y = 'b'; y += 'ar'; m.put(x, y)");
   13.69 +        assertEquals("bar", m.get("foo"));
   13.70 +    }
   13.71 +
   13.72 +    @Test
   13.73 +    public void testConsStringFromMirror() throws ScriptException {
   13.74 +        final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
   13.75 +        final Map<Object, Object> m = new HashMap<>();
   13.76 +        e.eval("var x = 'f'; x += 'oo'; var obj = {x: x};");
   13.77 +        assertEquals("foo", ((JSObject)b.get("obj")).getMember("x"));
   13.78 +    }
   13.79 +
   13.80 +    @Test
   13.81 +    public void testArrayConsString() throws ScriptException {
   13.82 +        final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
   13.83 +        final ArrayHolder h = new ArrayHolder();
   13.84 +        b.put("h", h);
   13.85 +        e.eval("var x = 'f'; x += 'oo'; h.array = [x];");
   13.86 +        assertEquals(1, h.array.length);
   13.87 +        assertEquals("foo", h.array[0]);
   13.88 +    }
   13.89 +
   13.90 +
   13.91 +    public static class ArrayHolder {
   13.92 +        private Object[] array;
   13.93 +
   13.94 +        public void setArray(Object[] array) {
   13.95 +            this.array = array;
   13.96 +        }
   13.97 +
   13.98 +        public Object[] getArray() {
   13.99 +            return array;
  13.100 +        }
  13.101 +    }
  13.102 +}

mercurial