8021122: Not all callables are handled for toString and other function valued properties

Tue, 23 Jul 2013 18:17:25 +0530

author
sundar
date
Tue, 23 Jul 2013 18:17:25 +0530
changeset 459
0cfa27ed82fe
parent 458
4b06441b7624
child 460
e86b297d26aa

8021122: Not all callables are handled for toString and other function valued properties
Reviewed-by: attila, hannesw, jlaskey

src/jdk/nashorn/internal/ir/debug/ASTWriter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/Global.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeArray.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeDate.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeJSON.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Context.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ListAdapter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptRuntime.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/IteratorAction.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/JavaAdapterBytecodeGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8021122.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8021122.js.EXPECTED file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/ir/debug/ASTWriter.java	Thu Jul 18 16:47:45 2013 +0200
     1.2 +++ b/src/jdk/nashorn/internal/ir/debug/ASTWriter.java	Tue Jul 23 18:17:25 2013 +0530
     1.3 @@ -102,7 +102,7 @@
     1.4              preorder.add(node);
     1.5          }
     1.6  
     1.7 -        final boolean isReference = field != null && field.getAnnotation(Reference.class) != null;
     1.8 +        final boolean isReference = field != null && field.isAnnotationPresent(Reference.class);
     1.9  
    1.10          Class<?> clazz = node.getClass();
    1.11          String   type  = clazz.getName();
    1.12 @@ -183,7 +183,7 @@
    1.13                  append('\n');
    1.14  
    1.15              for (final Field child : children) {
    1.16 -                if (child.getAnnotation(Ignore.class) != null) {
    1.17 +                if (child.isAnnotationPresent(Ignore.class)) {
    1.18                      continue;
    1.19                  }
    1.20  
     2.1 --- a/src/jdk/nashorn/internal/objects/Global.java	Thu Jul 18 16:47:45 2013 +0200
     2.2 +++ b/src/jdk/nashorn/internal/objects/Global.java	Tue Jul 23 18:17:25 2013 +0530
     2.3 @@ -63,6 +63,7 @@
     2.4  import jdk.nashorn.internal.runtime.ScriptRuntime;
     2.5  import jdk.nashorn.internal.runtime.ScriptingFunctions;
     2.6  import jdk.nashorn.internal.runtime.Source;
     2.7 +import jdk.nashorn.internal.runtime.linker.Bootstrap;
     2.8  import jdk.nashorn.internal.runtime.linker.InvokeByName;
     2.9  import jdk.nashorn.internal.scripts.JO;
    2.10  
    2.11 @@ -548,7 +549,8 @@
    2.12              if (hint == String.class) {
    2.13  
    2.14                  final Object toString = TO_STRING.getGetter().invokeExact(sobj);
    2.15 -                if (toString instanceof ScriptFunction) {
    2.16 +
    2.17 +                if (Bootstrap.isCallable(toString)) {
    2.18                      final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
    2.19                      if (JSType.isPrimitive(value)) {
    2.20                          return value;
    2.21 @@ -556,7 +558,7 @@
    2.22                  }
    2.23  
    2.24                  final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
    2.25 -                if (valueOf instanceof ScriptFunction) {
    2.26 +                if (Bootstrap.isCallable(valueOf)) {
    2.27                      final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
    2.28                      if (JSType.isPrimitive(value)) {
    2.29                          return value;
    2.30 @@ -567,7 +569,7 @@
    2.31  
    2.32              if (hint == Number.class) {
    2.33                  final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
    2.34 -                if (valueOf instanceof ScriptFunction) {
    2.35 +                if (Bootstrap.isCallable(valueOf)) {
    2.36                      final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
    2.37                      if (JSType.isPrimitive(value)) {
    2.38                          return value;
    2.39 @@ -575,7 +577,7 @@
    2.40                  }
    2.41  
    2.42                  final Object toString = TO_STRING.getGetter().invokeExact(sobj);
    2.43 -                if (toString instanceof ScriptFunction) {
    2.44 +                if (Bootstrap.isCallable(toString)) {
    2.45                      final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
    2.46                      if (JSType.isPrimitive(value)) {
    2.47                          return value;
     3.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java	Thu Jul 18 16:47:45 2013 +0200
     3.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java	Tue Jul 23 18:17:25 2013 +0530
     3.3 @@ -360,7 +360,7 @@
     3.4              final ScriptObject sobj = (ScriptObject)obj;
     3.5              try {
     3.6                  final Object join = JOIN.getGetter().invokeExact(sobj);
     3.7 -                if (join instanceof ScriptFunction) {
     3.8 +                if (Bootstrap.isCallable(join)) {
     3.9                      return JOIN.getInvoker().invokeExact(join, sobj);
    3.10                  }
    3.11              } catch (final RuntimeException | Error e) {
    3.12 @@ -396,7 +396,7 @@
    3.13                          final ScriptObject sobj           = (ScriptObject)val;
    3.14                          final Object       toLocaleString = TO_LOCALE_STRING.getGetter().invokeExact(sobj);
    3.15  
    3.16 -                        if (toLocaleString instanceof ScriptFunction) {
    3.17 +                        if (Bootstrap.isCallable(toLocaleString)) {
    3.18                              sb.append((String)TO_LOCALE_STRING.getInvoker().invokeExact(toLocaleString, sobj));
    3.19                          } else {
    3.20                              throw typeError("not.a.function", "toLocaleString");
     4.1 --- a/src/jdk/nashorn/internal/objects/NativeDate.java	Thu Jul 18 16:47:45 2013 +0200
     4.2 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java	Tue Jul 23 18:17:25 2013 +0530
     4.3 @@ -47,6 +47,7 @@
     4.4  import jdk.nashorn.internal.runtime.ScriptFunction;
     4.5  import jdk.nashorn.internal.runtime.ScriptObject;
     4.6  import jdk.nashorn.internal.runtime.ScriptRuntime;
     4.7 +import jdk.nashorn.internal.runtime.linker.Bootstrap;
     4.8  import jdk.nashorn.internal.runtime.linker.InvokeByName;
     4.9  
    4.10  /**
    4.11 @@ -862,7 +863,7 @@
    4.12  
    4.13          try {
    4.14              final Object func = TO_ISO_STRING.getGetter().invokeExact(sobj);
    4.15 -            if (func instanceof ScriptFunction) {
    4.16 +            if (Bootstrap.isCallable(func)) {
    4.17                  return TO_ISO_STRING.getInvoker().invokeExact(func, sobj, key);
    4.18              }
    4.19              throw typeError("not.a.function", ScriptRuntime.safeToString(func));
     5.1 --- a/src/jdk/nashorn/internal/objects/NativeJSON.java	Thu Jul 18 16:47:45 2013 +0200
     5.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSON.java	Tue Jul 23 18:17:25 2013 +0530
     5.3 @@ -189,7 +189,7 @@
     5.4              if (value instanceof ScriptObject) {
     5.5                  final ScriptObject svalue = (ScriptObject)value;
     5.6                  final Object toJSON = TO_JSON.getGetter().invokeExact(svalue);
     5.7 -                if (toJSON instanceof ScriptFunction) {
     5.8 +                if (Bootstrap.isCallable(toJSON)) {
     5.9                      value = TO_JSON.getInvoker().invokeExact(toJSON, svalue, key);
    5.10                  }
    5.11              }
     6.1 --- a/src/jdk/nashorn/internal/objects/NativeObject.java	Thu Jul 18 16:47:45 2013 +0200
     6.2 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java	Tue Jul 23 18:17:25 2013 +0530
     6.3 @@ -407,7 +407,7 @@
     6.4              try {
     6.5                  final Object toString = TO_STRING.getGetter().invokeExact(sobj);
     6.6  
     6.7 -                if (toString instanceof ScriptFunction) {
     6.8 +                if (Bootstrap.isCallable(toString)) {
     6.9                      return TO_STRING.getInvoker().invokeExact(toString, sobj);
    6.10                  }
    6.11              } catch (final RuntimeException | Error e) {
     7.1 --- a/src/jdk/nashorn/internal/runtime/Context.java	Thu Jul 18 16:47:45 2013 +0200
     7.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java	Tue Jul 23 18:17:25 2013 +0530
     7.3 @@ -36,6 +36,7 @@
     7.4  import java.io.PrintWriter;
     7.5  import java.lang.invoke.MethodHandle;
     7.6  import java.lang.invoke.MethodHandles;
     7.7 +import java.lang.reflect.Modifier;
     7.8  import java.util.concurrent.atomic.AtomicLong;
     7.9  import java.net.MalformedURLException;
    7.10  import java.net.URL;
    7.11 @@ -555,6 +556,7 @@
    7.12       * Checks that the given package can be accessed from current call stack.
    7.13       *
    7.14       * @param fullName fully qualified package name
    7.15 +     * @throw SecurityException if not accessible
    7.16       */
    7.17      public static void checkPackageAccess(final String fullName) {
    7.18          final int index = fullName.lastIndexOf('.');
    7.19 @@ -567,6 +569,31 @@
    7.20      }
    7.21  
    7.22      /**
    7.23 +     * Checks that the given package can be accessed from current call stack.
    7.24 +     *
    7.25 +     * @param fullName fully qualified package name
    7.26 +     * @return true if package is accessible, false otherwise
    7.27 +     */
    7.28 +    public static boolean isAccessiblePackage(final String fullName) {
    7.29 +        try {
    7.30 +            checkPackageAccess(fullName);
    7.31 +            return true;
    7.32 +        } catch (final SecurityException se) {
    7.33 +            return false;
    7.34 +        }
    7.35 +    }
    7.36 +
    7.37 +    /**
    7.38 +     * Checks that the given Class can be accessed from current call stack and is public.
    7.39 +     *
    7.40 +     * @param clazz Class object to check
    7.41 +     * @return true if Class is accessible, false otherwise
    7.42 +     */
    7.43 +    public static boolean isAccessibleClass(final Class<?> clazz) {
    7.44 +        return Modifier.isPublic(clazz.getModifiers()) && Context.isAccessiblePackage(clazz.getName());
    7.45 +    }
    7.46 +
    7.47 +    /**
    7.48       * Lookup a Java class. This is used for JSR-223 stuff linking in from
    7.49       * {@code jdk.nashorn.internal.objects.NativeJava} and {@code jdk.nashorn.internal.runtime.NativeJavaPackage}
    7.50       *
     8.1 --- a/src/jdk/nashorn/internal/runtime/ListAdapter.java	Thu Jul 18 16:47:45 2013 +0200
     8.2 +++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java	Tue Jul 23 18:17:25 2013 +0530
     8.3 @@ -31,6 +31,7 @@
     8.4  import java.util.ListIterator;
     8.5  import java.util.NoSuchElementException;
     8.6  import java.util.RandomAccess;
     8.7 +import jdk.nashorn.internal.runtime.linker.Bootstrap;
     8.8  import jdk.nashorn.internal.runtime.linker.InvokeByName;
     8.9  
    8.10  /**
    8.11 @@ -157,7 +158,7 @@
    8.12          }
    8.13      }
    8.14      private static void checkFunction(Object fn, InvokeByName invoke) {
    8.15 -        if(!(fn instanceof ScriptFunction)) {
    8.16 +        if(!(Bootstrap.isCallable(fn))) {
    8.17              throw new UnsupportedOperationException("The script object doesn't have a function named " + invoke.getName());
    8.18          }
    8.19      }
     9.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Thu Jul 18 16:47:45 2013 +0200
     9.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Tue Jul 23 18:17:25 2013 +0530
     9.3 @@ -381,9 +381,7 @@
     9.4       */
     9.5      public static Object checkAndConstruct(final ScriptFunction target, final Object... args) {
     9.6          final ScriptObject global = Context.getGlobalTrusted();
     9.7 -        if (! (global instanceof GlobalObject)) {
     9.8 -            throw new IllegalStateException("No current global set");
     9.9 -        }
    9.10 +        assert (global instanceof GlobalObject): "No current global set";
    9.11  
    9.12          if (target.getContext() != global.getContext()) {
    9.13              throw new IllegalArgumentException("'target' function is not from current Context");
    10.1 --- a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java	Thu Jul 18 16:47:45 2013 +0200
    10.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java	Tue Jul 23 18:17:25 2013 +0530
    10.3 @@ -31,6 +31,7 @@
    10.4  import jdk.nashorn.internal.runtime.Context;
    10.5  import jdk.nashorn.internal.runtime.ScriptFunction;
    10.6  import jdk.nashorn.internal.runtime.ScriptRuntime;
    10.7 +import jdk.nashorn.internal.runtime.linker.Bootstrap;
    10.8  
    10.9  /**
   10.10   * Helper class for the various map/apply functions in {@link jdk.nashorn.internal.objects.NativeArray}.
   10.11 @@ -103,6 +104,8 @@
   10.12          } else if (callbackfn instanceof ScriptObjectMirror &&
   10.13              ((ScriptObjectMirror)callbackfn).isFunction()) {
   10.14              strict = ((ScriptObjectMirror)callbackfn).isStrictFunction();
   10.15 +        } else if (Bootstrap.isDynamicMethod(callbackfn) || Bootstrap.isFunctionalInterfaceObject(callbackfn)) {
   10.16 +            strict = false;
   10.17          } else {
   10.18              throw typeError("not.a.function", ScriptRuntime.safeToString(callbackfn));
   10.19          }
    11.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Thu Jul 18 16:47:45 2013 +0200
    11.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Tue Jul 23 18:17:25 2013 +0530
    11.3 @@ -38,8 +38,11 @@
    11.4  import jdk.internal.dynalink.beans.BeansLinker;
    11.5  import jdk.internal.dynalink.linker.GuardedInvocation;
    11.6  import jdk.internal.dynalink.linker.LinkerServices;
    11.7 +import jdk.nashorn.api.scripting.ScriptObjectMirror;
    11.8  import jdk.nashorn.internal.codegen.CompilerConstants.Call;
    11.9  import jdk.nashorn.internal.codegen.RuntimeCallSite;
   11.10 +import jdk.nashorn.internal.runtime.ScriptFunction;
   11.11 +import jdk.nashorn.internal.runtime.ScriptRuntime;
   11.12  import jdk.nashorn.internal.runtime.options.Options;
   11.13  
   11.14  /**
   11.15 @@ -68,6 +71,41 @@
   11.16      }
   11.17  
   11.18      /**
   11.19 +     * Returns if the given object is a "callable"
   11.20 +     * @param obj object to be checked for callability
   11.21 +     * @return true if the obj is callable
   11.22 +     */
   11.23 +    public static boolean isCallable(final Object obj) {
   11.24 +        if (obj == ScriptRuntime.UNDEFINED || obj == null) {
   11.25 +            return false;
   11.26 +        }
   11.27 +
   11.28 +        return obj instanceof ScriptFunction ||
   11.29 +            ((obj instanceof ScriptObjectMirror) && ((ScriptObjectMirror)obj).isFunction()) ||
   11.30 +            isDynamicMethod(obj) ||
   11.31 +            isFunctionalInterfaceObject(obj);
   11.32 +    }
   11.33 +
   11.34 +    /**
   11.35 +     * Returns if the given object is a dynalink Dynamic method
   11.36 +     * @param obj object to be checked
   11.37 +     * @return true if the obj is a dynamic method
   11.38 +     */
   11.39 +    public static boolean isDynamicMethod(final Object obj) {
   11.40 +        return obj instanceof BoundDynamicMethod || BeansLinker.isDynamicMethod(obj);
   11.41 +    }
   11.42 +
   11.43 +    /**
   11.44 +     * Returns if the given object is an instance of an interface annotated with
   11.45 +     * java.lang.FunctionalInterface
   11.46 +     * @param obj object to be checked
   11.47 +     * @return true if the obj is an instance of @FunctionalInterface interface
   11.48 +     */
   11.49 +    public static boolean isFunctionalInterfaceObject(final Object obj) {
   11.50 +        return obj != null && (NashornBottomLinker.getFunctionalInterfaceMethod(obj.getClass()) != null);
   11.51 +    }
   11.52 +
   11.53 +    /**
   11.54       * Create a call site and link it for Nashorn. This version of the method conforms to the invokedynamic bootstrap
   11.55       * method expected signature and is referenced from Nashorn generated bytecode as the bootstrap method for all
   11.56       * invokedynamic instructions.
    12.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Thu Jul 18 16:47:45 2013 +0200
    12.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Tue Jul 23 18:17:25 2013 +0530
    12.3 @@ -924,6 +924,6 @@
    12.4      }
    12.5  
    12.6      private static boolean isCallerSensitive(final AccessibleObject e) {
    12.7 -        return e.getAnnotation(CallerSensitive.class) != null;
    12.8 +        return e.isAnnotationPresent(CallerSensitive.class);
    12.9      }
   12.10  }
    13.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Thu Jul 18 16:47:45 2013 +0200
    13.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Tue Jul 23 18:17:25 2013 +0530
    13.3 @@ -30,6 +30,9 @@
    13.4  import static jdk.nashorn.internal.lookup.Lookup.MH;
    13.5  
    13.6  import java.lang.invoke.MethodHandle;
    13.7 +import java.lang.invoke.MethodType;
    13.8 +import java.lang.reflect.Method;
    13.9 +import java.lang.reflect.Modifier;
   13.10  import jdk.internal.dynalink.CallSiteDescriptor;
   13.11  import jdk.internal.dynalink.beans.BeansLinker;
   13.12  import jdk.internal.dynalink.linker.GuardedInvocation;
   13.13 @@ -37,6 +40,7 @@
   13.14  import jdk.internal.dynalink.linker.LinkRequest;
   13.15  import jdk.internal.dynalink.linker.LinkerServices;
   13.16  import jdk.internal.dynalink.support.Guards;
   13.17 +import jdk.nashorn.internal.runtime.Context;
   13.18  import jdk.nashorn.internal.runtime.ScriptRuntime;
   13.19  
   13.20  /**
   13.21 @@ -73,7 +77,7 @@
   13.22      private static final MethodHandle EMPTY_ELEM_SETTER =
   13.23              MH.dropArguments(EMPTY_PROP_SETTER, 0, Object.class);
   13.24  
   13.25 -    private static GuardedInvocation linkBean(final LinkRequest linkRequest, final LinkerServices linkerServices) {
   13.26 +    private static GuardedInvocation linkBean(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
   13.27          final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor)linkRequest.getCallSiteDescriptor();
   13.28          final Object self = linkRequest.getReceiver();
   13.29          final String operator = desc.getFirstOperator();
   13.30 @@ -84,6 +88,22 @@
   13.31              }
   13.32              throw typeError("not.a.function", ScriptRuntime.safeToString(self));
   13.33          case "call":
   13.34 +            // Support dyn:call on any object that supports some @FunctionalInterface
   13.35 +            // annotated interface. This way Java method, constructor references or
   13.36 +            // implementations of java.util.function.* interfaces can be called as though
   13.37 +            // those are script functions.
   13.38 +            final Method m = getFunctionalInterfaceMethod(self.getClass());
   13.39 +            if (m != null) {
   13.40 +                final MethodType callType = desc.getMethodType();
   13.41 +                // 'callee' and 'thiz' passed from script + actual arguments
   13.42 +                if (callType.parameterCount() != m.getParameterCount() + 2) {
   13.43 +                    throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
   13.44 +                }
   13.45 +                return new GuardedInvocation(
   13.46 +                        // drop 'thiz' passed from the script.
   13.47 +                        MH.dropArguments(desc.getLookup().unreflect(m), 1, callType.parameterType(1)),
   13.48 +                        Guards.getInstanceOfGuard(m.getDeclaringClass())).asType(callType);
   13.49 +            }
   13.50              if(BeansLinker.isDynamicMethod(self)) {
   13.51                  throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
   13.52              }
   13.53 @@ -148,4 +168,32 @@
   13.54          }
   13.55          return ScriptRuntime.safeToString(linkRequest.getArguments()[1]);
   13.56      }
   13.57 +
   13.58 +    // Returns @FunctionalInterface annotated interface's single abstract method.
   13.59 +    // If not found, returns null
   13.60 +    static Method getFunctionalInterfaceMethod(final Class<?> clazz) {
   13.61 +        if (clazz == null) {
   13.62 +            return null;
   13.63 +        }
   13.64 +
   13.65 +        for (Class<?> iface : clazz.getInterfaces()) {
   13.66 +            // check accessiblity up-front
   13.67 +            if (! Context.isAccessibleClass(iface)) {
   13.68 +                continue;
   13.69 +            }
   13.70 +
   13.71 +            // check for @FunctionalInterface
   13.72 +            if (iface.isAnnotationPresent(FunctionalInterface.class)) {
   13.73 +                // return the first abstract method
   13.74 +                for (final Method m : iface.getMethods()) {
   13.75 +                    if (Modifier.isAbstract(m.getModifiers())) {
   13.76 +                        return m;
   13.77 +                    }
   13.78 +                }
   13.79 +            }
   13.80 +        }
   13.81 +
   13.82 +        // did not find here, try super class
   13.83 +        return getFunctionalInterfaceMethod(clazz.getSuperclass());
   13.84 +    }
   13.85  }
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/test/script/basic/JDK-8021122.js	Tue Jul 23 18:17:25 2013 +0530
    14.3 @@ -0,0 +1,93 @@
    14.4 +/*
    14.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + * 
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.
   14.11 + * 
   14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.15 + * version 2 for more details (a copy is included in the LICENSE file that
   14.16 + * accompanied this code).
   14.17 + * 
   14.18 + * You should have received a copy of the GNU General Public License version
   14.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.21 + * 
   14.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   14.23 + * or visit www.oracle.com if you need additional information or have any
   14.24 + * questions.
   14.25 + */
   14.26 +
   14.27 +/**
   14.28 + * JDK-8021122: Not all callables are handled for toString and other function valued properties
   14.29 + *
   14.30 + * @test
   14.31 + * @run
   14.32 + */
   14.33 +
   14.34 +var a = {}
   14.35 +var obj = new java.util.HashMap();
   14.36 +Object.bindProperties(a, obj);
   14.37 +try {
   14.38 +    print(a);
   14.39 +} catch (e) {
   14.40 +    print(e);
   14.41 +}
   14.42 +
   14.43 +var a = {}
   14.44 +var global = loadWithNewGlobal({ name:"xx", script: "this" });
   14.45 +var obj = global.eval("({ toString: function() { return 'hello'; } })");
   14.46 +Object.bindProperties(a, obj);
   14.47 +try {
   14.48 +    print(a);
   14.49 +} catch (e) {
   14.50 +    print(e);
   14.51 +}
   14.52 +
   14.53 +function runLambdaTests() {
   14.54 +    var r = new java.lang.Runnable() {
   14.55 +        run: function() { print("I am runnable"); }
   14.56 +    };
   14.57 +
   14.58 +    // call any @FunctionalInterface object as though it is a function
   14.59 +    r();
   14.60 +
   14.61 +    var twice = new java.util.function.Function() {
   14.62 +        apply: function(x) 2*x
   14.63 +    };
   14.64 +
   14.65 +    print(twice(34));
   14.66 +
   14.67 +    var sum = new java.util.function.BiFunction() {
   14.68 +        apply: function(x, y) x + y
   14.69 +    };
   14.70 +
   14.71 +    print(sum(32, 12))
   14.72 +
   14.73 +    // make toString to be a @FunctionalInterface object
   14.74 +    var a = {};
   14.75 +    a.toString = new java.util.function.Supplier() {
   14.76 +        get: function() { return "MyString"; }
   14.77 +    };
   14.78 +
   14.79 +    try {
   14.80 +        print(a);
   14.81 +    } catch (e) {
   14.82 +        print(e);
   14.83 +    }
   14.84 +}
   14.85 +
   14.86 +try {
   14.87 +    // check for java.util.function.Function class
   14.88 +    Java.type("java.util.function.Function");
   14.89 +    runLambdaTests();
   14.90 +} catch (e) {
   14.91 +    // fake output to match .EXPECTED values
   14.92 +    print("I am runnable");
   14.93 +    print("68");
   14.94 +    print("44");
   14.95 +    print("MyString");
   14.96 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/test/script/basic/JDK-8021122.js.EXPECTED	Tue Jul 23 18:17:25 2013 +0530
    15.3 @@ -0,0 +1,6 @@
    15.4 +{}
    15.5 +hello
    15.6 +I am runnable
    15.7 +68
    15.8 +44
    15.9 +MyString

mercurial