Merge

Thu, 07 Nov 2013 18:11:12 +0530

author
sundar
date
Thu, 07 Nov 2013 18:11:12 +0530
changeset 669
3b794f364c77
parent 667
bda654c6d59c
parent 668
2f07b4234451
child 670
d091499d67fc

Merge

     1.1 --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Tue Nov 05 13:09:40 2013 +0400
     1.2 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Thu Nov 07 18:11:12 2013 +0530
     1.3 @@ -595,6 +595,21 @@
     1.4      }
     1.5  
     1.6      /**
     1.7 +     * Utilitity to convert this script object to the given type.
     1.8 +     *
     1.9 +     * @param type destination type to convert to
    1.10 +     * @return converted object
    1.11 +     */
    1.12 +    public <T> T to(final Class<T> type) {
    1.13 +        return inGlobal(new Callable<T>() {
    1.14 +            @Override
    1.15 +            public T call() {
    1.16 +                return type.cast(ScriptUtils.convert(sobj, type));
    1.17 +            }
    1.18 +        });
    1.19 +    }
    1.20 +
    1.21 +    /**
    1.22       * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings.
    1.23       *
    1.24       * @param obj object to be wrapped/converted
     2.1 --- a/src/jdk/nashorn/api/scripting/ScriptUtils.java	Tue Nov 05 13:09:40 2013 +0400
     2.2 +++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java	Thu Nov 07 18:11:12 2013 +0530
     2.3 @@ -25,13 +25,17 @@
     2.4  
     2.5  package jdk.nashorn.api.scripting;
     2.6  
     2.7 +import java.lang.invoke.MethodHandle;
     2.8 +import jdk.internal.dynalink.beans.StaticClass;
     2.9 +import jdk.internal.dynalink.linker.LinkerServices;
    2.10 +import jdk.nashorn.internal.runtime.linker.Bootstrap;
    2.11  import jdk.nashorn.internal.runtime.Context;
    2.12  import jdk.nashorn.internal.runtime.ScriptFunction;
    2.13  import jdk.nashorn.internal.runtime.ScriptObject;
    2.14  import jdk.nashorn.internal.runtime.ScriptRuntime;
    2.15  
    2.16  /**
    2.17 - * Utilities that are to be called from script code
    2.18 + * Utilities that are to be called from script code.
    2.19   */
    2.20  public final class ScriptUtils {
    2.21      private ScriptUtils() {}
    2.22 @@ -128,4 +132,41 @@
    2.23  
    2.24          return ScriptObjectMirror.unwrapArray(args, Context.getGlobal());
    2.25      }
    2.26 +
    2.27 +    /**
    2.28 +     * Convert the given object to the given type.
    2.29 +     *
    2.30 +     * @param obj object to be converted
    2.31 +     * @param type destination type to convert to
    2.32 +     * @return converted object
    2.33 +     */
    2.34 +    public static Object convert(final Object obj, final Object type) {
    2.35 +        if (obj == null) {
    2.36 +            return null;
    2.37 +        }
    2.38 +
    2.39 +        final Class<?> clazz;
    2.40 +        if (type instanceof Class) {
    2.41 +            clazz = (Class<?>)type;
    2.42 +        } else if (type instanceof StaticClass) {
    2.43 +            clazz = ((StaticClass)type).getRepresentedClass();
    2.44 +        } else {
    2.45 +            throw new IllegalArgumentException("type expected");
    2.46 +        }
    2.47 +
    2.48 +        final LinkerServices linker = Bootstrap.getLinkerServices();
    2.49 +        final MethodHandle converter = linker.getTypeConverter(obj.getClass(),  clazz);
    2.50 +        if (converter == null) {
    2.51 +            // no supported conversion!
    2.52 +            throw new UnsupportedOperationException("conversion not supported");
    2.53 +        }
    2.54 +
    2.55 +        try {
    2.56 +            return converter.invoke(obj);
    2.57 +        } catch (final RuntimeException | Error e) {
    2.58 +            throw e;
    2.59 +        } catch (final Throwable t) {
    2.60 +            throw new RuntimeException(t);
    2.61 +        }
    2.62 +    }
    2.63  }
     3.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java	Tue Nov 05 13:09:40 2013 +0400
     3.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java	Thu Nov 07 18:11:12 2013 +0530
     3.3 @@ -88,6 +88,9 @@
     3.4      /** JavaScript compliant conversion function from Object to number */
     3.5      public static final Call TO_NUMBER = staticCall(myLookup, JSType.class, "toNumber", double.class, Object.class);
     3.6  
     3.7 +    /** JavaScript compliant conversion function from Object to String */
     3.8 +    public static final Call TO_STRING = staticCall(myLookup, JSType.class, "toString", String.class, Object.class);
     3.9 +
    3.10      /** JavaScript compliant conversion function from Object to int32 */
    3.11      public static final Call TO_INT32 = staticCall(myLookup, JSType.class, "toInt32", int.class, Object.class);
    3.12  
     4.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Tue Nov 05 13:09:40 2013 +0400
     4.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Thu Nov 07 18:11:12 2013 +0530
     4.3 @@ -33,14 +33,18 @@
     4.4  import java.lang.invoke.MethodType;
     4.5  import java.lang.reflect.Method;
     4.6  import java.lang.reflect.Modifier;
     4.7 +import java.util.Map;
     4.8 +import java.util.HashMap;
     4.9  import jdk.internal.dynalink.CallSiteDescriptor;
    4.10  import jdk.internal.dynalink.beans.BeansLinker;
    4.11  import jdk.internal.dynalink.linker.GuardedInvocation;
    4.12  import jdk.internal.dynalink.linker.GuardingDynamicLinker;
    4.13 +import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
    4.14  import jdk.internal.dynalink.linker.LinkRequest;
    4.15  import jdk.internal.dynalink.linker.LinkerServices;
    4.16  import jdk.internal.dynalink.support.Guards;
    4.17  import jdk.nashorn.internal.runtime.Context;
    4.18 +import jdk.nashorn.internal.runtime.JSType;
    4.19  import jdk.nashorn.internal.runtime.ScriptRuntime;
    4.20  
    4.21  /**
    4.22 @@ -50,7 +54,7 @@
    4.23   * setters for Java objects that couldn't be linked by any other linker, and throw appropriate ECMAScript errors for
    4.24   * attempts to invoke arbitrary Java objects as functions or constructors.
    4.25   */
    4.26 -final class NashornBottomLinker implements GuardingDynamicLinker {
    4.27 +final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeConverterFactory {
    4.28  
    4.29      @Override
    4.30      public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
    4.31 @@ -129,6 +133,29 @@
    4.32          throw new AssertionError("unknown call type " + desc);
    4.33      }
    4.34  
    4.35 +    @Override
    4.36 +    public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
    4.37 +        final GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType);
    4.38 +        return gi == null ? null : gi.asType(MH.type(targetType, sourceType));
    4.39 +    }
    4.40 +
    4.41 +    /**
    4.42 +     * Main part of the implementation of {@link GuardingTypeConverterFactory#convertToType(Class, Class)} that doesn't
    4.43 +     * care about adapting the method signature; that's done by the invoking method. Returns conversion from Object to String/number/boolean (JS primitive types).
    4.44 +     * @param sourceType the source type
    4.45 +     * @param targetType the target type
    4.46 +     * @return a guarded invocation that converts from the source type to the target type.
    4.47 +     * @throws Exception if something goes wrong
    4.48 +     */
    4.49 +    private static GuardedInvocation convertToTypeNoCast(final Class<?> sourceType, final Class<?> targetType) throws Exception {
    4.50 +        final MethodHandle mh = CONVERTERS.get(targetType);
    4.51 +        if (mh != null) {
    4.52 +            return new GuardedInvocation(mh, null);
    4.53 +        }
    4.54 +
    4.55 +        return null;
    4.56 +    }
    4.57 +
    4.58      private static GuardedInvocation getInvocation(final MethodHandle handle, final Object self, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
    4.59          return Bootstrap.asType(new GuardedInvocation(handle, Guards.getClassGuard(self.getClass())), linkerServices, desc);
    4.60      }
    4.61 @@ -161,6 +188,15 @@
    4.62          throw new AssertionError("unknown call type " + desc);
    4.63      }
    4.64  
    4.65 +    private static final Map<Class<?>, MethodHandle> CONVERTERS = new HashMap<>();
    4.66 +    static {
    4.67 +        CONVERTERS.put(boolean.class, JSType.TO_BOOLEAN.methodHandle());
    4.68 +        CONVERTERS.put(double.class, JSType.TO_NUMBER.methodHandle());
    4.69 +        CONVERTERS.put(int.class, JSType.TO_INTEGER.methodHandle());
    4.70 +        CONVERTERS.put(long.class, JSType.TO_LONG.methodHandle());
    4.71 +        CONVERTERS.put(String.class, JSType.TO_STRING.methodHandle());
    4.72 +    }
    4.73 +
    4.74      private static String getArgument(final LinkRequest linkRequest) {
    4.75          final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
    4.76          if (desc.getNameTokenCount() > 2) {
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/script/basic/JDK-8027828.js	Thu Nov 07 18:11:12 2013 +0530
     5.3 @@ -0,0 +1,35 @@
     5.4 +/*
     5.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + * 
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.
    5.11 + * 
    5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.15 + * version 2 for more details (a copy is included in the LICENSE file that
    5.16 + * accompanied this code).
    5.17 + * 
    5.18 + * You should have received a copy of the GNU General Public License version
    5.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.21 + * 
    5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.23 + * or visit www.oracle.com if you need additional information or have any
    5.24 + * questions.
    5.25 + */
    5.26 +
    5.27 +/**
    5.28 + * JDK-8027828: ClassCastException when converting return value of a Java method to boolean
    5.29 + *
    5.30 + * @test
    5.31 + * @run
    5.32 + */
    5.33 +
    5.34 +var x = new java.util.HashMap()
    5.35 +x.put('test', new java.io.File('test'))
    5.36 +if (x.get("test")) {
    5.37 +  print('Found!')
    5.38 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/script/basic/JDK-8027828.js.EXPECTED	Thu Nov 07 18:11:12 2013 +0530
     6.3 @@ -0,0 +1,1 @@
     6.4 +Found!
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/script/basic/convert.js	Thu Nov 07 18:11:12 2013 +0530
     7.3 @@ -0,0 +1,61 @@
     7.4 +/*
     7.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + * 
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.
    7.11 + * 
    7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.15 + * version 2 for more details (a copy is included in the LICENSE file that
    7.16 + * accompanied this code).
    7.17 + * 
    7.18 + * You should have received a copy of the GNU General Public License version
    7.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.21 + * 
    7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    7.23 + * or visit www.oracle.com if you need additional information or have any
    7.24 + * questions.
    7.25 + */
    7.26 +
    7.27 +/**
    7.28 + * Tests for convert method of ScriptUtils.
    7.29 + *
    7.30 + * @test
    7.31 + * @run
    7.32 + */
    7.33 +
    7.34 +var ScriptUtils = Java.type("jdk.nashorn.api.scripting.ScriptUtils");
    7.35 +obj = { valueOf: function() { print("hello"); return 43.3; } };
    7.36 +
    7.37 +// object to double
    7.38 +print(ScriptUtils.convert(obj, java.lang.Number.class));
    7.39 +
    7.40 +// array to List
    7.41 +var arr = [3, 44, 23, 33];
    7.42 +var list = ScriptUtils.convert(arr, java.util.List.class);
    7.43 +print(list instanceof java.util.List)
    7.44 +print(list);
    7.45 +
    7.46 +// object to Map
    7.47 +obj = { foo: 333, bar: 'hello'};
    7.48 +var map = ScriptUtils.convert(obj, java.util.Map.class);
    7.49 +print(map instanceof java.util.Map);
    7.50 +for (m in map) {
    7.51 +   print(m + " " + map[m]);
    7.52 +}
    7.53 +
    7.54 +// object to String
    7.55 +obj = { toString: function() { print("in toString"); return "foo" } };
    7.56 +print(ScriptUtils.convert(obj, java.lang.String.class));
    7.57 +
    7.58 +// array to Java array
    7.59 +var jarr = ScriptUtils.convert(arr, Java.type("int[]"));
    7.60 +print(jarr instanceof Java.type("int[]"));
    7.61 +for (i in jarr) {
    7.62 +    print(jarr[i]);
    7.63 +}
    7.64 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/script/basic/convert.js.EXPECTED	Thu Nov 07 18:11:12 2013 +0530
     8.3 @@ -0,0 +1,14 @@
     8.4 +hello
     8.5 +43.3
     8.6 +true
     8.7 +[3, 44, 23, 33]
     8.8 +true
     8.9 +foo 333
    8.10 +bar hello
    8.11 +in toString
    8.12 +foo
    8.13 +true
    8.14 +3
    8.15 +44
    8.16 +23
    8.17 +33
     9.1 --- a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java	Tue Nov 05 13:09:40 2013 +0400
     9.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java	Thu Nov 07 18:11:12 2013 +0530
     9.3 @@ -26,6 +26,7 @@
     9.4  package jdk.nashorn.api.scripting;
     9.5  
     9.6  import java.util.HashMap;
     9.7 +import java.util.List;
     9.8  import java.util.Map;
     9.9  import javax.script.ScriptEngine;
    9.10  import javax.script.ScriptEngineManager;
    9.11 @@ -227,4 +228,28 @@
    9.12          final Object newObj = ((ScriptObjectMirror)e2obj.getMember("foo")).newObject();
    9.13          assertTrue(newObj instanceof ScriptObjectMirror);
    9.14      }
    9.15 +
    9.16 +    @Test
    9.17 +    public void conversionTest() throws ScriptException {
    9.18 +        final ScriptEngineManager m = new ScriptEngineManager();
    9.19 +        final ScriptEngine e = m.getEngineByName("nashorn");
    9.20 +        final ScriptObjectMirror arr = (ScriptObjectMirror)e.eval("[33, 45, 23]");
    9.21 +        final int[] intArr = arr.to(int[].class);
    9.22 +        assertEquals(intArr[0], 33);
    9.23 +        assertEquals(intArr[1], 45);
    9.24 +        assertEquals(intArr[2], 23);
    9.25 +
    9.26 +        final List<?> list = arr.to(List.class);
    9.27 +        assertEquals(list.get(0), 33);
    9.28 +        assertEquals(list.get(1), 45);
    9.29 +        assertEquals(list.get(2), 23);
    9.30 +
    9.31 +        ScriptObjectMirror obj = (ScriptObjectMirror)e.eval(
    9.32 +            "({ valueOf: function() { return 42 } })");
    9.33 +        assertEquals(Double.valueOf(42.0), obj.to(Double.class));
    9.34 +
    9.35 +        obj = (ScriptObjectMirror)e.eval(
    9.36 +            "({ toString: function() { return 'foo' } })");
    9.37 +        assertEquals("foo", obj.to(String.class));
    9.38 +    }
    9.39  }

mercurial