8049086: Minor API convenience functions on "Java" object

Reviewed-by: attila, hannesw
This commit is contained in:
Athijegannathan Sundararajan 2014-07-04 15:56:53 +05:30
parent 14eb01cb47
commit ca212c0d9e
5 changed files with 275 additions and 3 deletions

View File

@ -25,6 +25,8 @@
package jdk.nashorn.api.scripting;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import java.lang.invoke.MethodHandle;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.LinkerServices;
@ -69,12 +71,15 @@ public final class ScriptUtils {
* Create a wrapper function that calls {@code func} synchronized on {@code sync} or, if that is undefined,
* {@code self}. Used to implement "sync" function in resources/mozilla_compat.js.
*
* @param func the function to invoke
* @param func the function to wrap
* @param sync the object to synchronize on
* @return a synchronizing wrapper function
*/
public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) {
return func.makeSynchronizedFunction(sync);
public static Object makeSynchronizedFunction(final Object func, final Object sync) {
if (func instanceof ScriptFunction) {
return ((ScriptFunction)func).makeSynchronizedFunction(sync);
}
throw typeError("not.a.function", ScriptRuntime.safeToString(func));
}
/**

View File

@ -36,6 +36,7 @@ import java.util.List;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.support.TypeUtilities;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.api.scripting.ScriptUtils;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
@ -45,6 +46,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ListAdapter;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
@ -79,6 +81,73 @@ public final class NativeJava {
return type instanceof StaticClass;
}
/**
* Returns synchronized wrapper version of the given ECMAScript function.
* @param self not used
* @param func the ECMAScript function whose synchronized version is returned.
* @param obj the object (i.e, lock) on which the function synchronizes.
* @return synchronized wrapper version of the given ECMAScript function.
*/
@Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
return ScriptUtils.makeSynchronizedFunction(func, obj);
}
/**
* Returns true if the specified object is a Java method.
* @param self not used
* @param obj the object that is checked if it is a Java method object or not
* @return tells whether given object is a Java method object or not.
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static boolean isJavaMethod(final Object self, final Object obj) {
return Bootstrap.isDynamicMethod(obj);
}
/**
* Returns true if the specified object is a java function (but not script function)
* @param self not used
* @param obj the object that is checked if it is a Java function or not
* @return tells whether given object is a Java function or not
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static boolean isJavaFunction(final Object self, final Object obj) {
return Bootstrap.isCallable(obj) && !(obj instanceof ScriptFunction);
}
/**
* Returns true if the specified object is a Java object but not a script object
* @param self not used
* @param obj the object that is checked
* @return tells whether given object is a Java object but not a script object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static boolean isJavaObject(final Object self, final Object obj) {
return obj != null && !(obj instanceof ScriptObject);
}
/**
* Returns true if the specified object is a ECMAScript object, that is an instance of {@link ScriptObject}.
* @param self not used
* @param obj the object that is checked if it is a ECMAScript object or not
* @return tells whether given object is a ECMAScript object or not.
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static boolean isScriptObject(final Object self, final Object obj) {
return obj instanceof ScriptObject;
}
/**
* Returns true if the specified object is a ECMAScript function, that is an instance of {@link ScriptFunction}.
* @param self not used
* @param obj the object that is checked if it is a ECMAScript function or not
* @return tells whether given object is a ECMAScript function or not.
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static boolean isScriptFunction(final Object self, final Object obj) {
return obj instanceof ScriptFunction;
}
/**
* <p>
* Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects

View File

@ -25,6 +25,7 @@
package jdk.nashorn.internal.runtime.linker;
import java.util.Objects;
import jdk.internal.dynalink.beans.BeansLinker;
/**
@ -48,4 +49,9 @@ final class BoundDynamicMethod {
Object getBoundThis() {
return boundThis;
}
@Override
public String toString() {
return dynamicMethod.toString() + " on " + Objects.toString(boundThis);
}
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8049086: Minor API convenience functions on "Java" object
*
* @test
* @run
*/
var System = Java.type("java.lang.System");
var out = System.out;
var println = out.println;
var getProperty = System.getProperty;
var File = Java.type("java.io.File")["(String)"];
print("println is java method? " + Java.isJavaMethod(println));
print("println is script function? " + Java.isScriptFunction(println));
print("getProperty is java method? " + Java.isJavaMethod(getProperty));
print("getProperty is script function? " + Java.isScriptFunction(getProperty));
print("File is java method? " + Java.isJavaMethod(File));
print("File is script function? " + Java.isScriptFunction(File));
print("eval is script function? " + Java.isScriptFunction(eval));
print("eval is java method? " + Java.isJavaMethod(eval));
function hello() {}
print("hello is script function? " + Java.isScriptFunction(hello));
print("hello is java method? " + Java.isJavaMethod(hello));
print("out is script object? " + Java.isScriptObject(out));
print("System is script object? " + Java.isScriptObject(System));
print("Object is script object? " + Java.isScriptObject(Object));
print("{} is script object? " + Java.isScriptObject({}));
print("/foo/ is script object? " + Java.isScriptObject(/foo/));
// Java function is anything whose 'typeof' is 'function' but it is not
// a script function! This includes:
// (a) Java methods (b) Java classes (as these respond to new)
// (c) FunctionalInterface objects (d) JSObjects that are 'functions'
print("java.awt.Color is java function? " + Java.isJavaFunction(java.awt.Color));
print("java.lang.Runnable instance is java function? "
+ Java.isJavaFunction(new java.lang.Runnable(function() {})));
print("eval is java function? " + Java.isJavaFunction(eval));
print("println is java function? " + Java.isJavaFunction(println));
print("getProperty is java function? " + Java.isJavaFunction(getProperty));
var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject");
print("callable JSObject is function? " +
Java.isJavaFunction(new JSObject() {
isFunction: function() true,
call: function() {}
})
);
print("Non callable JSObject is function? " +
Java.isJavaFunction(new JSObject() {
isFunction: function() false,
})
);
// synchronized function
var lock = new java.lang.Object();
print("lock is java object? " + Java.isJavaObject(lock));
print("eval is java object? " + Java.isJavaObject(eval));
print("{} is java object? " + Java.isJavaObject({}));
print("/foo/ is java object? " + Java.isJavaObject(/foo/));
print("[] is java object? " + Java.isJavaObject([]));
print("java.io.File is java object? " + Java.isJavaObject(java.io.File));
// synchornized function checks
Java.synchronized(function() {
var th = new java.lang.Thread(Java.synchronized(function() {
print("new thread");
print("notifying..");
lock.notifyAll();
}, lock));
th.start();
print("about to wait..");
lock.wait();
th.join();
print("done waiting!");
}, lock)();
// try Mozilla "sync" as well
load("nashorn:mozilla_compat.js");
sync(function() {
var th = new java.lang.Thread(sync(function() {
print("new thread");
print("notifying..");
lock.notifyAll();
}, lock));
th.start();
print("about to wait..");
lock.wait();
th.join();
print("done waiting!");
}, lock)();
function expectTypeError(func) {
try {
func();
throw new Error("should have thrown TypeError");
} catch (e) {
if (! (e instanceof TypeError)) {
fail("Expected TypeError, got " +e);
}
print(e);
}
}
expectTypeError(function() Java.synchronized(232));
expectTypeError(function() sync(232));
expectTypeError(function() Java.synchronized({}));
expectTypeError(function() sync({}));
expectTypeError(function() Java.synchronized([]));
expectTypeError(function() sync([]));
expectTypeError(function() Java.synchronized("hello"));
expectTypeError(function() sync("hello"));
expectTypeError(function() Java.synchronized(null));
expectTypeError(function() sync(null));
expectTypeError(function() Java.synchronized(undefined));
expectTypeError(function() sync(undefined));

View File

@ -0,0 +1,48 @@
println is java method? true
println is script function? false
getProperty is java method? true
getProperty is script function? false
File is java method? true
File is script function? false
eval is script function? true
eval is java method? false
hello is script function? true
hello is java method? false
out is script object? false
System is script object? false
Object is script object? true
{} is script object? true
/foo/ is script object? true
java.awt.Color is java function? true
java.lang.Runnable instance is java function? true
eval is java function? false
println is java function? true
getProperty is java function? true
callable JSObject is function? true
Non callable JSObject is function? false
lock is java object? true
eval is java object? false
{} is java object? false
/foo/ is java object? false
[] is java object? false
java.io.File is java object? true
about to wait..
new thread
notifying..
done waiting!
about to wait..
new thread
notifying..
done waiting!
TypeError: 232 is not a function
TypeError: 232 is not a function
TypeError: [object Object] is not a function
TypeError: [object Object] is not a function
TypeError: [object Array] is not a function
TypeError: [object Array] is not a function
TypeError: hello is not a function
TypeError: hello is not a function
TypeError: null is not a function
TypeError: null is not a function
TypeError: undefined is not a function
TypeError: undefined is not a function