Merge
This commit is contained in:
commit
3295cea5b9
@ -524,17 +524,19 @@ grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" {
|
|||||||
<!-- only to be invoked as dependency of "test" target -->
|
<!-- only to be invoked as dependency of "test" target -->
|
||||||
<target name="-test-classes-all" depends="jar" unless="test.class">
|
<target name="-test-classes-all" depends="jar" unless="test.class">
|
||||||
<fileset id="test.classes" dir="${build.test.classes.dir}">
|
<fileset id="test.classes" dir="${build.test.classes.dir}">
|
||||||
<include name="**/dynalink/test/*Test.class"/>
|
|
||||||
<include name="**/dynalink/beans/test/*Test.class"/>
|
<include name="**/dynalink/beans/test/*Test.class"/>
|
||||||
|
<include name="**/dynalink/linker/support/test/*Test.class"/>
|
||||||
|
<include name="**/dynalink/support/test/*Test.class"/>
|
||||||
|
<include name="**/dynalink/test/*Test.class"/>
|
||||||
<include name="**/api/javaaccess/test/*Test.class"/>
|
<include name="**/api/javaaccess/test/*Test.class"/>
|
||||||
<include name="**/api/scripting/test/*Test.class"/>
|
<include name="**/api/scripting/test/*Test.class"/>
|
||||||
<include name="**/api/tree/test/*Test.class"/>
|
<include name="**/api/tree/test/*Test.class"/>
|
||||||
<include name="**/codegen/test/*Test.class"/>
|
<include name="**/codegen/test/*Test.class"/>
|
||||||
<include name="**/parser/test/*Test.class"/>
|
<include name="**/parser/test/*Test.class"/>
|
||||||
<include name="**/runtime/test/*Test.class"/>
|
<include name="**/runtime/test/*Test.class"/>
|
||||||
|
<include name="**/runtime/doubleconv/test/*Test.class"/>
|
||||||
<include name="**/runtime/regexp/test/*Test.class"/>
|
<include name="**/runtime/regexp/test/*Test.class"/>
|
||||||
<include name="**/runtime/regexp/joni/test/*Test.class"/>
|
<include name="**/runtime/regexp/joni/test/*Test.class"/>
|
||||||
<include name="**/runtime/doubleconv/test/*Test.class"/>
|
|
||||||
<include name="**/framework/*Test.class"/>
|
<include name="**/framework/*Test.class"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
</target>
|
</target>
|
||||||
@ -550,6 +552,7 @@ grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" {
|
|||||||
<target name="-test-nosecurity" unless="test.class">
|
<target name="-test-nosecurity" unless="test.class">
|
||||||
<fileset id="test.nosecurity.classes" dir="${build.test.classes.dir}">
|
<fileset id="test.nosecurity.classes" dir="${build.test.classes.dir}">
|
||||||
<include name="**/framework/ScriptTest.class"/>
|
<include name="**/framework/ScriptTest.class"/>
|
||||||
|
<include name="**/runtime/linker/test/*Test.class"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
<testng outputdir="${build.nosecurity.test.results.dir}/${testResultsSubDir}" classfilesetref="test.nosecurity.classes"
|
<testng outputdir="${build.nosecurity.test.results.dir}/${testResultsSubDir}" classfilesetref="test.nosecurity.classes"
|
||||||
verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
|
verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
|
||||||
|
@ -88,6 +88,7 @@ import java.lang.invoke.MethodType;
|
|||||||
import java.security.AccessControlContext;
|
import java.security.AccessControlContext;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import jdk.dynalink.internal.AccessControlContextFactory;
|
import jdk.dynalink.internal.AccessControlContextFactory;
|
||||||
@ -149,6 +150,11 @@ final class ClassString {
|
|||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ClassString[" + Arrays.toString(classes) + "]";
|
||||||
|
}
|
||||||
|
|
||||||
boolean isVisibleFrom(final ClassLoader classLoader) {
|
boolean isVisibleFrom(final ClassLoader classLoader) {
|
||||||
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -163,7 +163,7 @@ final class PackagesHelper {
|
|||||||
if (fm != null) {
|
if (fm != null) {
|
||||||
listPackage(StandardLocation.PLATFORM_CLASS_PATH, pkg, props);
|
listPackage(StandardLocation.PLATFORM_CLASS_PATH, pkg, props);
|
||||||
if (this.modulePathSet) {
|
if (this.modulePathSet) {
|
||||||
for (Set<Location> locs : fm.listModuleLocations(StandardLocation.MODULE_PATH)) {
|
for (Set<Location> locs : fm.listLocationsForModules(StandardLocation.MODULE_PATH)) {
|
||||||
for (Location loc : locs) {
|
for (Location loc : locs) {
|
||||||
listPackage(loc, pkg, props);
|
listPackage(loc, pkg, props);
|
||||||
}
|
}
|
||||||
|
@ -31,24 +31,13 @@ import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
|
|||||||
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
|
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
|
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_VARARGS;
|
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_VARARGS;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.AALOAD;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
|
import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.ARRAYLENGTH;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE;
|
import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.D2F;
|
import static jdk.internal.org.objectweb.asm.Opcodes.D2F;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.GETSTATIC;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.GOTO;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
|
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGE;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
|
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.ISTORE;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.I2B;
|
import static jdk.internal.org.objectweb.asm.Opcodes.I2B;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.I2S;
|
import static jdk.internal.org.objectweb.asm.Opcodes.I2S;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.POP;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.PUTSTATIC;
|
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
|
import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
|
||||||
import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
|
import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
|
||||||
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
|
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
|
||||||
@ -66,6 +55,7 @@ import java.lang.reflect.Modifier;
|
|||||||
import java.security.AccessControlContext;
|
import java.security.AccessControlContext;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -73,20 +63,14 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||||
import jdk.internal.org.objectweb.asm.FieldVisitor;
|
|
||||||
import jdk.internal.org.objectweb.asm.Handle;
|
|
||||||
import jdk.internal.org.objectweb.asm.Label;
|
|
||||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
|
||||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
|
||||||
import jdk.internal.org.objectweb.asm.Type;
|
|
||||||
import jdk.internal.org.objectweb.asm.Handle;
|
import jdk.internal.org.objectweb.asm.Handle;
|
||||||
import jdk.internal.org.objectweb.asm.Label;
|
import jdk.internal.org.objectweb.asm.Label;
|
||||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||||
import jdk.internal.org.objectweb.asm.Type;
|
import jdk.internal.org.objectweb.asm.Type;
|
||||||
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
|
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||||
import jdk.nashorn.api.scripting.ScriptUtils;
|
import jdk.nashorn.api.scripting.ScriptUtils;
|
||||||
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
||||||
import jdk.nashorn.internal.runtime.Context;
|
|
||||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||||
import jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome;
|
import jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome;
|
||||||
@ -139,7 +123,8 @@ import jdk.internal.reflect.CallerSensitive;
|
|||||||
* to resemble Java anonymous classes) is actually equivalent to <code>new X(a, b, { ... })</code>.
|
* to resemble Java anonymous classes) is actually equivalent to <code>new X(a, b, { ... })</code>.
|
||||||
* </p><p>
|
* </p><p>
|
||||||
* It is possible to create two different adapter classes: those that can have class-level overrides, and those that can
|
* It is possible to create two different adapter classes: those that can have class-level overrides, and those that can
|
||||||
* have instance-level overrides. When {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject)} is invoked
|
* have instance-level overrides. When {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject, ProtectionDomain)}
|
||||||
|
* or {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject, Lookup)} is invoked
|
||||||
* with non-null {@code classOverrides} parameter, an adapter class is created that can have class-level overrides, and
|
* with non-null {@code classOverrides} parameter, an adapter class is created that can have class-level overrides, and
|
||||||
* the passed script object will be used as the implementations for its methods, just as in the above case of the
|
* the passed script object will be used as the implementations for its methods, just as in the above case of the
|
||||||
* constructor taking a script object. Note that in the case of class-level overrides, a new adapter class is created on
|
* constructor taking a script object. Note that in the case of class-level overrides, a new adapter class is created on
|
||||||
@ -168,6 +153,7 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
private static final Type OBJECT_TYPE = Type.getType(Object.class);
|
private static final Type OBJECT_TYPE = Type.getType(Object.class);
|
||||||
private static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
|
private static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
|
||||||
private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
|
private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
|
||||||
|
private static final Type SCRIPT_OBJECT_MIRROR_TYPE = Type.getType(ScriptObjectMirror.class);
|
||||||
|
|
||||||
// JavaAdapterServices methods used in generated bytecode
|
// JavaAdapterServices methods used in generated bytecode
|
||||||
private static final Call CHECK_FUNCTION = lookupServiceMethod("checkFunction", ScriptFunction.class, Object.class, String.class);
|
private static final Call CHECK_FUNCTION = lookupServiceMethod("checkFunction", ScriptFunction.class, Object.class, String.class);
|
||||||
@ -182,6 +168,7 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
private static final Call TO_CHAR_PRIMITIVE = lookupServiceMethod("toCharPrimitive", char.class, Object.class);
|
private static final Call TO_CHAR_PRIMITIVE = lookupServiceMethod("toCharPrimitive", char.class, Object.class);
|
||||||
private static final Call UNSUPPORTED = lookupServiceMethod("unsupported", UnsupportedOperationException.class);
|
private static final Call UNSUPPORTED = lookupServiceMethod("unsupported", UnsupportedOperationException.class);
|
||||||
private static final Call WRAP_THROWABLE = lookupServiceMethod("wrapThrowable", RuntimeException.class, Throwable.class);
|
private static final Call WRAP_THROWABLE = lookupServiceMethod("wrapThrowable", RuntimeException.class, Throwable.class);
|
||||||
|
private static final Call UNWRAP_MIRROR = lookupServiceMethod("unwrapMirror", ScriptObject.class, Object.class, boolean.class);
|
||||||
|
|
||||||
// Other methods invoked by the generated bytecode
|
// Other methods invoked by the generated bytecode
|
||||||
private static final Call UNWRAP = staticCallNoLookup(ScriptUtils.class, "unwrap", Object.class, Object.class);
|
private static final Call UNWRAP = staticCallNoLookup(ScriptUtils.class, "unwrap", Object.class, Object.class);
|
||||||
@ -216,8 +203,7 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
private static final String GET_METHOD_PROPERTY_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE, SCRIPT_OBJECT_TYPE);
|
private static final String GET_METHOD_PROPERTY_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE, SCRIPT_OBJECT_TYPE);
|
||||||
private static final String VOID_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
|
private static final String VOID_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
|
||||||
|
|
||||||
static final String ADAPTER_PACKAGE_INTERNAL = "jdk/nashorn/javaadapters/";
|
private static final String ADAPTER_PACKAGE_INTERNAL = "jdk/nashorn/javaadapters/";
|
||||||
static final String ADAPTER_PACKAGE = "jdk.nashorn.javaadapters";
|
|
||||||
private static final int MAX_GENERATED_TYPE_NAME_LENGTH = 255;
|
private static final int MAX_GENERATED_TYPE_NAME_LENGTH = 255;
|
||||||
|
|
||||||
// Method name prefix for invoking super-methods
|
// Method name prefix for invoking super-methods
|
||||||
@ -265,7 +251,7 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
* @throws AdaptationException if the adapter can not be generated for some reason.
|
* @throws AdaptationException if the adapter can not be generated for some reason.
|
||||||
*/
|
*/
|
||||||
JavaAdapterBytecodeGenerator(final Class<?> superClass, final List<Class<?>> interfaces,
|
JavaAdapterBytecodeGenerator(final Class<?> superClass, final List<Class<?>> interfaces,
|
||||||
final ClassLoader commonLoader, final boolean classOverride) throws AdaptationException {
|
final ClassLoader commonLoader, final boolean classOverride) throws AdaptationException {
|
||||||
assert superClass != null && !superClass.isInterface();
|
assert superClass != null && !superClass.isInterface();
|
||||||
assert interfaces != null;
|
assert interfaces != null;
|
||||||
|
|
||||||
@ -369,7 +355,7 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
// If the class is a SAM, allow having ScriptFunction passed as class overrides
|
// If the class is a SAM, allow having ScriptFunction passed as class overrides
|
||||||
mv.dup();
|
mv.dup();
|
||||||
mv.instanceOf(SCRIPT_FUNCTION_TYPE);
|
mv.instanceOf(SCRIPT_FUNCTION_TYPE);
|
||||||
mv.dup();
|
mv.dup();
|
||||||
mv.putstatic(generatedClassName, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
|
mv.putstatic(generatedClassName, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
|
||||||
final Label notFunction = new Label();
|
final Label notFunction = new Label();
|
||||||
mv.ifeq(notFunction);
|
mv.ifeq(notFunction);
|
||||||
@ -389,9 +375,9 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
private void emitInitCallThis(final InstructionAdapter mv) {
|
private void emitInitCallThis(final InstructionAdapter mv) {
|
||||||
loadField(mv, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
|
loadField(mv, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
|
||||||
GET_CALL_THIS.invoke(mv);
|
GET_CALL_THIS.invoke(mv);
|
||||||
if(classOverride) {
|
if(classOverride) {
|
||||||
mv.putstatic(generatedClassName, CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
|
mv.putstatic(generatedClassName, CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
|
||||||
} else {
|
} else {
|
||||||
// It is presumed ALOAD 0 was already executed
|
// It is presumed ALOAD 0 was already executed
|
||||||
mv.putfield(generatedClassName, CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
|
mv.putfield(generatedClassName, CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
|
||||||
}
|
}
|
||||||
@ -427,10 +413,10 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
|
|
||||||
if (samName == null) {
|
if (samName == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// If all our abstract methods have a single name, generate an additional constructor, one that takes a
|
// If all our abstract methods have a single name, generate an additional constructor, one that takes a
|
||||||
// ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods.
|
// ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods.
|
||||||
generateOverridingConstructor(ctor, true);
|
generateOverridingConstructor(ctor, true);
|
||||||
// If the original type only has a single abstract method name, as well as a default ctor, then it can
|
// If the original type only has a single abstract method name, as well as a default ctor, then it can
|
||||||
// be automatically converted from JS function.
|
// be automatically converted from JS function.
|
||||||
return ctor.getParameterTypes().length == 0;
|
return ctor.getParameterTypes().length == 0;
|
||||||
@ -456,14 +442,9 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
* constructor passed as the argument here, and delegate to it. However, it will take an additional argument of
|
* constructor passed as the argument here, and delegate to it. However, it will take an additional argument of
|
||||||
* either ScriptObject or ScriptFunction type (based on the value of the "fromFunction" parameter), and initialize
|
* either ScriptObject or ScriptFunction type (based on the value of the "fromFunction" parameter), and initialize
|
||||||
* all the method handle fields of the adapter instance with functions from the script object (or the script
|
* all the method handle fields of the adapter instance with functions from the script object (or the script
|
||||||
* function itself, if that's what's passed). There is one method handle field in the adapter class for every method
|
* function itself, if that's what's passed). Additionally, it will create another constructor with an additional
|
||||||
* that can be implemented or overridden; the name of every field is same as the name of the method, with a number
|
* Object type parameter that can be used for ScriptObjectMirror objects.
|
||||||
* suffix that makes it unique in case of overloaded methods. The generated constructor will invoke
|
* The constructor will also store the Nashorn global that was current at the constructor
|
||||||
* {@link #getHandle(ScriptFunction, MethodType, boolean)} or {@link #getHandle(Object, String, MethodType,
|
|
||||||
* boolean)} to obtain the method handles; these methods make sure to add the necessary conversions and arity
|
|
||||||
* adjustments so that the resulting method handles can be invoked from generated methods using {@code invokeExact}.
|
|
||||||
* The constructor that takes a script function will only initialize the methods with the same name as the single
|
|
||||||
* abstract method. The constructor will also store the Nashorn global that was current at the constructor
|
|
||||||
* invocation time in a field named "global". The generated constructor will be public, regardless of whether the
|
* invocation time in a field named "global". The generated constructor will be public, regardless of whether the
|
||||||
* supertype constructor was public or protected. The generated constructor will not be variable arity, even if the
|
* supertype constructor was public or protected. The generated constructor will not be variable arity, even if the
|
||||||
* supertype constructor was.
|
* supertype constructor was.
|
||||||
@ -524,14 +505,59 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object additional param accepting constructor - generated to handle null and undefined value
|
// Object additional param accepting constructor for handling ScriptObjectMirror objects, which are
|
||||||
// for script adapters. This is effectively to throw TypeError on such script adapters. See
|
// unwrapped to work as ScriptObjects or ScriptFunctions. This also handles null and undefined values for
|
||||||
// JavaAdapterServices.getHandle as well.
|
// script adapters by throwing TypeError on such script adapters.
|
||||||
private void generateOverridingConstructorWithObjectParam(final InstructionAdapter mv, final String ctorDescriptor) {
|
private void generateOverridingConstructorWithObjectParam(final InstructionAdapter mv, final String ctorDescriptor) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
final int extraArgOffset = emitSuperConstructorCall(mv, ctorDescriptor);
|
final int extraArgOffset = emitSuperConstructorCall(mv, ctorDescriptor);
|
||||||
|
|
||||||
|
// Check for ScriptObjectMirror
|
||||||
|
mv.visitVarInsn(ALOAD, extraArgOffset);
|
||||||
|
mv.instanceOf(SCRIPT_OBJECT_MIRROR_TYPE);
|
||||||
|
final Label notMirror = new Label();
|
||||||
|
mv.ifeq(notMirror);
|
||||||
|
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.visitVarInsn(ALOAD, extraArgOffset);
|
||||||
|
mv.iconst(0);
|
||||||
|
UNWRAP_MIRROR.invoke(mv);
|
||||||
|
mv.putfield(generatedClassName, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
|
||||||
|
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.visitVarInsn(ALOAD, extraArgOffset);
|
||||||
|
mv.iconst(1);
|
||||||
|
UNWRAP_MIRROR.invoke(mv);
|
||||||
|
mv.putfield(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
|
||||||
|
|
||||||
|
final Label done = new Label();
|
||||||
|
|
||||||
|
if (samName != null) {
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.getfield(generatedClassName, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
|
||||||
|
mv.instanceOf(SCRIPT_FUNCTION_TYPE);
|
||||||
|
mv.ifeq(done);
|
||||||
|
|
||||||
|
// Assign "isFunction = true"
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.iconst(1);
|
||||||
|
mv.putfield(generatedClassName, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
|
||||||
|
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.dup();
|
||||||
|
mv.getfield(generatedClassName, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
|
||||||
|
mv.checkcast(SCRIPT_FUNCTION_TYPE);
|
||||||
|
emitInitCallThis(mv);
|
||||||
|
mv.goTo(done);
|
||||||
|
}
|
||||||
|
|
||||||
|
mv.visitLabel(notMirror);
|
||||||
|
|
||||||
|
// Throw error if not a ScriptObject
|
||||||
mv.visitVarInsn(ALOAD, extraArgOffset);
|
mv.visitVarInsn(ALOAD, extraArgOffset);
|
||||||
NOT_AN_OBJECT.invoke(mv);
|
NOT_AN_OBJECT.invoke(mv);
|
||||||
|
|
||||||
|
mv.visitLabel(done);
|
||||||
endInitMethod(mv);
|
endInitMethod(mv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,7 +704,7 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
// stack: [callThis, delegate]
|
// stack: [callThis, delegate]
|
||||||
mv.goTo(callCallee);
|
mv.goTo(callCallee);
|
||||||
mv.visitLabel(notFunction);
|
mv.visitLabel(notFunction);
|
||||||
} else {
|
} else {
|
||||||
// If it's not a SAM method, and the delegate is a function,
|
// If it's not a SAM method, and the delegate is a function,
|
||||||
// it'll fall back to default behavior
|
// it'll fall back to default behavior
|
||||||
mv.ifne(defaultBehavior);
|
mv.ifne(defaultBehavior);
|
||||||
@ -818,7 +844,7 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
if (isVarArgCall) {
|
if (isVarArgCall) {
|
||||||
// Variable arity calls are always (Object callee, Object this, Object[] params)
|
// Variable arity calls are always (Object callee, Object this, Object[] params)
|
||||||
callParamTypes = new Class<?>[] { Object.class, Object.class, Object[].class };
|
callParamTypes = new Class<?>[] { Object.class, Object.class, Object[].class };
|
||||||
} else {
|
} else {
|
||||||
// Adjust invocation type signature for conversions we instituted in
|
// Adjust invocation type signature for conversions we instituted in
|
||||||
// convertParam; also, byte and short get passed as ints.
|
// convertParam; also, byte and short get passed as ints.
|
||||||
final Class<?>[] origParamTypes = type.parameterArray();
|
final Class<?>[] origParamTypes = type.parameterArray();
|
||||||
@ -868,13 +894,13 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
|
|
||||||
|
|
||||||
private void loadField(final InstructionAdapter mv, final String name, final String desc) {
|
private void loadField(final InstructionAdapter mv, final String name, final String desc) {
|
||||||
if(classOverride) {
|
if(classOverride) {
|
||||||
mv.getstatic(generatedClassName, name, desc);
|
mv.getstatic(generatedClassName, name, desc);
|
||||||
} else {
|
} else {
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.getfield(generatedClassName, name, desc);
|
mv.getfield(generatedClassName, name, desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void convertReturnValue(final InstructionAdapter mv, final Class<?> origReturnType) {
|
private static void convertReturnValue(final InstructionAdapter mv, final Class<?> origReturnType) {
|
||||||
if (origReturnType == void.class) {
|
if (origReturnType == void.class) {
|
||||||
@ -948,6 +974,7 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit code to restore the previous Nashorn Context when needed.
|
* Emit code to restore the previous Nashorn Context when needed.
|
||||||
* @param mv the instruction adapter
|
* @param mv the instruction adapter
|
||||||
@ -999,9 +1026,9 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Class<?> iface : interfaces) {
|
for (final Class<?> iface : interfaces) {
|
||||||
if (cl.isAssignableFrom(iface)) {
|
if (cl.isAssignableFrom(iface)) {
|
||||||
return iface;
|
return iface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we better that interface that extends the given interface!
|
// we better that interface that extends the given interface!
|
||||||
@ -1122,8 +1149,8 @@ final class JavaAdapterBytecodeGenerator {
|
|||||||
if (Modifier.isFinal(m) || isCallerSensitive(typeMethod)) {
|
if (Modifier.isFinal(m) || isCallerSensitive(typeMethod)) {
|
||||||
finalMethods.add(mi);
|
finalMethods.add(mi);
|
||||||
} else if (!finalMethods.contains(mi) && methodInfos.add(mi) && Modifier.isAbstract(m)) {
|
} else if (!finalMethods.contains(mi) && methodInfos.add(mi) && Modifier.isAbstract(m)) {
|
||||||
abstractMethodNames.add(mi.getName());
|
abstractMethodNames.add(mi.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ public final class JavaAdapterFactory {
|
|||||||
/**
|
/**
|
||||||
* For a given class, create its adapter class and associated info.
|
* For a given class, create its adapter class and associated info.
|
||||||
*
|
*
|
||||||
* @param type the class for which the adapter is created
|
* @param types the class and interfaces for which the adapter is created
|
||||||
*
|
*
|
||||||
* @return the adapter info for the class.
|
* @return the adapter info for the class.
|
||||||
*/
|
*/
|
||||||
|
@ -39,6 +39,7 @@ import java.lang.invoke.MethodHandle;
|
|||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.MethodHandles.Lookup;
|
import java.lang.invoke.MethodHandles.Lookup;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.CodeSigner;
|
import java.security.CodeSigner;
|
||||||
import java.security.CodeSource;
|
import java.security.CodeSource;
|
||||||
@ -51,6 +52,7 @@ import jdk.internal.org.objectweb.asm.ClassWriter;
|
|||||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||||
import jdk.internal.org.objectweb.asm.Type;
|
import jdk.internal.org.objectweb.asm.Type;
|
||||||
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
|
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||||
import jdk.nashorn.internal.objects.Global;
|
import jdk.nashorn.internal.objects.Global;
|
||||||
import jdk.nashorn.internal.runtime.Context;
|
import jdk.nashorn.internal.runtime.Context;
|
||||||
import jdk.nashorn.internal.runtime.ECMAException;
|
import jdk.nashorn.internal.runtime.ECMAException;
|
||||||
@ -175,6 +177,23 @@ public final class JavaAdapterServices {
|
|||||||
return sobj.getMap().findProperty("toString") != null;
|
return sobj.getMap().findProperty("toString") != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ScriptObject or Global field value from a ScriptObjectMirror using reflection.
|
||||||
|
*
|
||||||
|
* @param mirror the mirror object
|
||||||
|
* @param getGlobal true if we want the global object, false to return the script object
|
||||||
|
* @return the script object or global object
|
||||||
|
*/
|
||||||
|
public static ScriptObject unwrapMirror(final Object mirror, final boolean getGlobal) {
|
||||||
|
assert mirror instanceof ScriptObjectMirror;
|
||||||
|
try {
|
||||||
|
final Field field = getGlobal ? MirrorFieldHolder.GLOBAL_FIELD : MirrorFieldHolder.SOBJ_FIELD;
|
||||||
|
return (ScriptObject) field.get(mirror);
|
||||||
|
} catch (final IllegalAccessException x) {
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delegate to {@link Bootstrap#bootstrap(Lookup, String, MethodType, int)}.
|
* Delegate to {@link Bootstrap#bootstrap(Lookup, String, MethodType, int)}.
|
||||||
* @param lookup MethodHandle lookup.
|
* @param lookup MethodHandle lookup.
|
||||||
@ -291,4 +310,24 @@ public final class JavaAdapterServices {
|
|||||||
.asCollector(Object[].class, type.parameterCount())
|
.asCollector(Object[].class, type.parameterCount())
|
||||||
.asType(type));
|
.asType(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialization on demand holder for accessible ScriptObjectMirror fields
|
||||||
|
private static class MirrorFieldHolder {
|
||||||
|
|
||||||
|
private static final Field SOBJ_FIELD = getMirrorField("sobj");
|
||||||
|
private static final Field GLOBAL_FIELD = getMirrorField("global");
|
||||||
|
|
||||||
|
private static Field getMirrorField(final String fieldName) {
|
||||||
|
try {
|
||||||
|
final Field field = ScriptObjectMirror.class.getDeclaredField(fieldName);
|
||||||
|
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||||
|
field.setAccessible(true);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return field;
|
||||||
|
} catch (final NoSuchFieldException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,12 +157,17 @@ final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTyp
|
|||||||
*/
|
*/
|
||||||
private static GuardedInvocation getSamTypeConverter(final Class<?> sourceType, final Class<?> targetType, final Supplier<MethodHandles.Lookup> lookupSupplier) throws Exception {
|
private static GuardedInvocation getSamTypeConverter(final Class<?> sourceType, final Class<?> targetType, final Supplier<MethodHandles.Lookup> lookupSupplier) throws Exception {
|
||||||
// If source type is more generic than ScriptFunction class, we'll need to use a guard
|
// If source type is more generic than ScriptFunction class, we'll need to use a guard
|
||||||
final boolean isSourceTypeGeneric = sourceType.isAssignableFrom(ScriptFunction.class);
|
final boolean isSourceTypeGeneric = sourceType.isAssignableFrom(ScriptObject.class);
|
||||||
|
|
||||||
if ((isSourceTypeGeneric || ScriptFunction.class.isAssignableFrom(sourceType)) && isAutoConvertibleFromFunction(targetType)) {
|
if ((isSourceTypeGeneric || ScriptFunction.class.isAssignableFrom(sourceType)) && isAutoConvertibleFromFunction(targetType)) {
|
||||||
final MethodHandle ctor = JavaAdapterFactory.getConstructor(ScriptFunction.class, targetType, getCurrentLookup(lookupSupplier));
|
final Class<?> paramType = isSourceTypeGeneric ? Object.class : ScriptFunction.class;
|
||||||
|
// Using Object.class as constructor source type means we're getting an overloaded constructor handle,
|
||||||
|
// which is safe but slower than a single constructor handle. If the actual argument is a ScriptFunction it
|
||||||
|
// would be nice if we could change the formal parameter to ScriptFunction.class and add a guard for it
|
||||||
|
// in the main invocation.
|
||||||
|
final MethodHandle ctor = JavaAdapterFactory.getConstructor(paramType, targetType, getCurrentLookup(lookupSupplier));
|
||||||
assert ctor != null; // if isAutoConvertibleFromFunction() returned true, then ctor must exist.
|
assert ctor != null; // if isAutoConvertibleFromFunction() returned true, then ctor must exist.
|
||||||
return new GuardedInvocation(ctor, isSourceTypeGeneric ? IS_SCRIPT_FUNCTION : null);
|
return new GuardedInvocation(ctor, isSourceTypeGeneric ? IS_FUNCTION : null);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -315,7 +320,7 @@ final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTyp
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final MethodHandle IS_SCRIPT_OBJECT = Guards.isInstance(ScriptObject.class, MH.type(Boolean.TYPE, Object.class));
|
private static final MethodHandle IS_SCRIPT_OBJECT = Guards.isInstance(ScriptObject.class, MH.type(Boolean.TYPE, Object.class));
|
||||||
private static final MethodHandle IS_SCRIPT_FUNCTION = Guards.isInstance(ScriptFunction.class, MH.type(Boolean.TYPE, Object.class));
|
private static final MethodHandle IS_FUNCTION = findOwnMH("isFunction", boolean.class, Object.class);
|
||||||
private static final MethodHandle IS_NATIVE_ARRAY = Guards.isOfClass(NativeArray.class, MH.type(Boolean.TYPE, Object.class));
|
private static final MethodHandle IS_NATIVE_ARRAY = Guards.isOfClass(NativeArray.class, MH.type(Boolean.TYPE, Object.class));
|
||||||
|
|
||||||
private static final MethodHandle IS_NASHORN_OR_UNDEFINED_TYPE = findOwnMH("isNashornTypeOrUndefined", Boolean.TYPE, Object.class);
|
private static final MethodHandle IS_NASHORN_OR_UNDEFINED_TYPE = findOwnMH("isNashornTypeOrUndefined", Boolean.TYPE, Object.class);
|
||||||
@ -348,6 +353,11 @@ final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTyp
|
|||||||
return obj instanceof ScriptObject? ScriptUtils.wrap((ScriptObject)obj) : obj;
|
return obj instanceof ScriptObject? ScriptUtils.wrap((ScriptObject)obj) : obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static boolean isFunction(final Object obj) {
|
||||||
|
return obj instanceof ScriptFunction || obj instanceof ScriptObjectMirror && ((ScriptObjectMirror) obj).isFunction();
|
||||||
|
}
|
||||||
|
|
||||||
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
|
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
|
||||||
return MH.findStatic(MethodHandles.lookup(), NashornLinker.class, name, MH.type(rtype, types));
|
return MH.findStatic(MethodHandles.lookup(), NashornLinker.class, name, MH.type(rtype, types));
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,8 @@ ifneq ($(FAILURE_HANDLER_DIR), )
|
|||||||
-timeoutHandlerDir:$(FAILURE_HANDLER_DIR_MIXED)/jtregFailureHandler.jar \
|
-timeoutHandlerDir:$(FAILURE_HANDLER_DIR_MIXED)/jtregFailureHandler.jar \
|
||||||
-observerDir:$(FAILURE_HANDLER_DIR_MIXED)/jtregFailureHandler.jar \
|
-observerDir:$(FAILURE_HANDLER_DIR_MIXED)/jtregFailureHandler.jar \
|
||||||
-timeoutHandler:jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler \
|
-timeoutHandler:jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler \
|
||||||
-observer:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver
|
-observer:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver \
|
||||||
|
-timeoutHandlerTimeout:0
|
||||||
ifeq ($(UNAME_S), CYGWIN)
|
ifeq ($(UNAME_S), CYGWIN)
|
||||||
JTREG_FAILURE_HANDLER_OPTIONS += -J-Djava.library.path="$(FAILURE_HANDLER_DIR_MIXED)"
|
JTREG_FAILURE_HANDLER_OPTIONS += -J-Djava.library.path="$(FAILURE_HANDLER_DIR_MIXED)"
|
||||||
endif
|
endif
|
||||||
|
@ -29,11 +29,14 @@ import java.util.Deque;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import javax.script.Bindings;
|
import javax.script.Bindings;
|
||||||
|
import javax.script.ScriptContext;
|
||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
||||||
import javax.script.ScriptException;
|
import javax.script.ScriptException;
|
||||||
import jdk.nashorn.api.scripting.JSObject;
|
import jdk.nashorn.api.scripting.JSObject;
|
||||||
|
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||||
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
||||||
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||||
import jdk.nashorn.internal.runtime.Context;
|
import jdk.nashorn.internal.runtime.Context;
|
||||||
@ -277,4 +280,37 @@ public class JavaAdapterTest {
|
|||||||
Assert.assertEquals(tla.getQueue().peek(), "Queue");
|
Assert.assertEquals(tla.getQueue().peek(), "Queue");
|
||||||
Assert.assertEquals(tla.getDequeue().peek(), "Dequeue");
|
Assert.assertEquals(tla.getDequeue().peek(), "Dequeue");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public static void testMirrorAdapter() throws ScriptException {
|
||||||
|
final NashornScriptEngine e = (NashornScriptEngine) createEngine();
|
||||||
|
e.setBindings(e.createBindings(), ScriptContext.GLOBAL_SCOPE); // Null by default
|
||||||
|
|
||||||
|
// Referencing functions from across scopes causes them to be wrapped in ScriptObjectMirrors
|
||||||
|
e.eval("function convertObjectFromEngineScope(){ return new java.util.concurrent.Callable(o).call(); }", e.getBindings(ScriptContext.ENGINE_SCOPE));
|
||||||
|
e.eval("function convertObjectFromGlobalScope(){ return new java.util.concurrent.Callable(o).call(); }", e.getBindings(ScriptContext.GLOBAL_SCOPE));
|
||||||
|
e.eval("function convertFuncFromEngineScope(){ return new java.util.concurrent.Callable(g).call(); }", e.getBindings(ScriptContext.ENGINE_SCOPE));
|
||||||
|
e.eval("function convertFuncFromGlobalScope(){ return new java.util.concurrent.Callable(g).call(); }", e.getBindings(ScriptContext.GLOBAL_SCOPE));
|
||||||
|
e.eval("function convertParamFromEngineScope(){ return Java.type('jdk.nashorn.internal.runtime.linker.test.JavaAdapterTest').m(f);}", e.getBindings(ScriptContext.ENGINE_SCOPE));
|
||||||
|
e.eval("function convertParamFromGlobalScope(){ return Java.type('jdk.nashorn.internal.runtime.linker.test.JavaAdapterTest').m(f);}", e.getBindings(ScriptContext.GLOBAL_SCOPE));
|
||||||
|
|
||||||
|
e.eval("var o = { call: function () { return 'ok from o'; } }", e.getBindings(ScriptContext.ENGINE_SCOPE));
|
||||||
|
e.eval("function g() { return 'ok from g'; }", e.getBindings(ScriptContext.ENGINE_SCOPE));
|
||||||
|
e.eval("function f(a) { return a.toUpperCase(); }", e.getBindings(ScriptContext.ENGINE_SCOPE));
|
||||||
|
|
||||||
|
try {
|
||||||
|
Assert.assertEquals(e.invokeFunction("convertObjectFromEngineScope"), "ok from o");
|
||||||
|
Assert.assertEquals(e.invokeFunction("convertObjectFromGlobalScope"), "ok from o");
|
||||||
|
Assert.assertEquals(e.invokeFunction("convertFuncFromEngineScope"), "ok from g");
|
||||||
|
Assert.assertEquals(e.invokeFunction("convertFuncFromGlobalScope"), "ok from g");
|
||||||
|
Assert.assertEquals(e.invokeFunction("convertParamFromEngineScope"), "OK");
|
||||||
|
Assert.assertEquals(e.invokeFunction("convertParamFromGlobalScope"), "OK");
|
||||||
|
} catch (final NoSuchMethodException x) {
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String m(final Function<String, String> f){
|
||||||
|
return f.apply("ok");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user