This commit is contained in:
Lana Steuck 2014-07-10 12:41:23 -07:00
commit f03bea190f
21 changed files with 525 additions and 367 deletions

View File

@ -53,9 +53,6 @@ public abstract class NashornException extends RuntimeException {
// underlying ECMA error object - lazily initialized
private Object ecmaError;
/** script source name used for "engine.js" */
public static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js";
/**
* Constructor
*

View File

@ -25,8 +25,6 @@
package jdk.nashorn.api.scripting;
import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.Source.sourceFor;
import java.io.IOException;
@ -34,13 +32,10 @@ import java.io.Reader;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.text.MessageFormat;
import java.util.Locale;
@ -58,7 +53,6 @@ import javax.script.SimpleBindings;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
@ -98,9 +92,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
// This is the initial default Nashorn global object.
// This is used as "shared" global if above option is true.
private final Global global;
// initialized bit late to be made 'final'.
// Property object for "context" property of global object.
private volatile Property contextProperty;
// default options passed to Nashorn Options object
private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" };
@ -122,30 +113,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
}
// load engine.js
private static Source loadEngineJSSource() {
final String script = "resources/engine.js";
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<Source>() {
@Override
public Source run() throws IOException {
final URL url = NashornScriptEngine.class.getResource(script);
return sourceFor(NashornException.ENGINE_SCRIPT_SOURCE_NAME, url);
}
}
);
} catch (final PrivilegedActionException e) {
if (Context.DEBUG) {
e.printStackTrace();
}
throw new RuntimeException(e);
}
}
// Source object for engine.js
private static final Source ENGINE_SCRIPT_SRC = loadEngineJSSource();
NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) {
this(factory, DEFAULT_OPTIONS, appLoader);
}
@ -248,33 +215,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
return getInterfaceInner(thiz, clazz);
}
// These are called from the "engine.js" script
/**
* This hook is used to search js global variables exposed from Java code.
*
* @param self 'this' passed from the script
* @param ctxt current ScriptContext in which name is searched
* @param name name of the variable searched
* @return the value of the named variable
*/
public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
if (ctxt != null) {
final int scope = ctxt.getAttributesScope(name);
final Global ctxtGlobal = getNashornGlobalFrom(ctxt);
if (scope != -1) {
return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
}
if (self == UNDEFINED) {
// scope access and so throw ReferenceError
throw referenceError(ctxtGlobal, "not.defined", name);
}
}
return UNDEFINED;
}
// Implementation only below this point
private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException {
@ -426,47 +366,12 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
}, CREATE_GLOBAL_ACC_CTXT);
nashornContext.initGlobal(newGlobal);
nashornContext.initGlobal(newGlobal, this);
newGlobal.setScriptContext(ctxt);
final int NON_ENUMERABLE_CONSTANT = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE;
// current ScriptContext exposed as "context"
// "context" is non-writable from script - but script engine still
// needs to set it and so save the context Property object
contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, ctxt);
// current ScriptEngine instance exposed as "engine". We added @SuppressWarnings("LeakingThisInConstructor") as
// NetBeans identifies this assignment as such a leak - this is a false positive as we're setting this property
// in the Global of a Context we just created - both the Context and the Global were just created and can not be
// seen from another thread outside of this constructor.
newGlobal.addOwnProperty("engine", NON_ENUMERABLE_CONSTANT, this);
// global script arguments with undefined value
newGlobal.addOwnProperty("arguments", Property.NOT_ENUMERABLE, UNDEFINED);
// file name default is null
newGlobal.addOwnProperty(ScriptEngine.FILENAME, Property.NOT_ENUMERABLE, null);
// evaluate engine.js initialization script this new global object
try {
evalImpl(compileImpl(ENGINE_SCRIPT_SRC, newGlobal), ctxt, newGlobal);
} catch (final ScriptException exp) {
throw new RuntimeException(exp);
}
return newGlobal;
}
// scripts should see "context" and "engine" as variables in the given global object
private void setContextVariables(final Global ctxtGlobal, final ScriptContext ctxt) {
// set "context" global variable via contextProperty - because this
// property is non-writable
contextProperty.setValue(ctxtGlobal, ctxtGlobal, ctxt, false);
Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal);
if (args == null || args == UNDEFINED) {
args = ScriptRuntime.EMPTY_ARRAY;
}
// if no arguments passed, expose it
if (! (args instanceof ScriptObject)) {
args = ctxtGlobal.wrapAsObject(args);
ctxtGlobal.set("arguments", args, false);
}
}
private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
name.getClass(); // null check
@ -533,11 +438,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
// set ScriptContext variables if ctxt is non-null
if (ctxt != null) {
setContextVariables(ctxtGlobal, ctxt);
}
ctxtGlobal.setScriptContext(ctxt);
return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
} catch (final Exception e) {
throwAsScriptException(e, ctxtGlobal);
@ -560,10 +461,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
Context.setGlobal(ctxtGlobal);
}
// set ScriptContext variables if ctxt is non-null
if (ctxt != null) {
setContextVariables(ctxtGlobal, ctxt);
}
ctxtGlobal.setScriptContext(ctxt);
return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
} catch (final Exception e) {
throwAsScriptException(e, ctxtGlobal);

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

@ -1,101 +0,0 @@
/*
* Copyright (c) 2010, 2013, 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.
*/
/**
* This script file is executed by script engine at the construction
* of the every new Global object. The functions here assume global variables
* "context" of type javax.script.ScriptContext and "engine" of the type
* jdk.nashorn.api.scripting.NashornScriptEngine.
**/
Object.defineProperty(this, "__noSuchProperty__", {
configurable: true,
enumerable: false,
writable: true,
value: function (name) {
'use strict';
return engine.__noSuchProperty__(this, context, name);
}
});
function print() {
var writer = context != null? context.writer : engine.context.writer;
if (! (writer instanceof java.io.PrintWriter)) {
writer = new java.io.PrintWriter(writer);
}
var buf = new java.lang.StringBuilder();
for (var i = 0; i < arguments.length; i++) {
if (i != 0) {
buf.append(' ');
}
buf.append(String(arguments[i]));
}
writer.println(buf.toString());
}
/**
* This is C-like printf
*
* @param format string to format the rest of the print items
* @param args variadic argument list
*/
Object.defineProperty(this, "printf", {
configurable: true,
enumerable: false,
writable: true,
value: function (format, args/*, more args*/) {
print(sprintf.apply(this, arguments));
}
});
/**
* This is C-like sprintf
*
* @param format string to format the rest of the print items
* @param args variadic argument list
*/
Object.defineProperty(this, "sprintf", {
configurable: true,
enumerable: false,
writable: true,
value: function (format, args/*, more args*/) {
var len = arguments.length - 1;
var array = [];
if (len < 0) {
return "";
}
for (var i = 0; i < len; i++) {
if (arguments[i+1] instanceof Date) {
array[i] = arguments[i+1].getTime();
} else {
array[i] = arguments[i+1];
}
}
array = Java.to(array);
return Packages.jdk.nashorn.api.scripting.ScriptUtils.format(format, array);
}
});

View File

@ -1317,20 +1317,14 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// Load up self (scope).
method.loadCompilerConstant(SCOPE);
final CallNode.EvalArgs evalArgs = callNode.getEvalArgs();
final List<Expression> evalArgs = callNode.getEvalArgs().getArgs();
// load evaluated code
loadExpressionAsObject(evalArgs.getCode());
loadExpressionAsObject(evalArgs.get(0));
// load second and subsequent args for side-effect
final List<Expression> callArgs = callNode.getArgs();
final int numArgs = callArgs.size();
final int numArgs = evalArgs.size();
for (int i = 1; i < numArgs; i++) {
loadExpressionUnbounded(callArgs.get(i)).pop();
loadAndDiscard(evalArgs.get(i));
}
// special/extra 'eval' arguments
loadExpressionUnbounded(evalArgs.getThis());
method.load(evalArgs.getLocation());
method.load(evalArgs.getStrictMode());
method.convert(Type.OBJECT);
method._goto(invoke_direct_eval);
method.label(is_not_eval);
@ -1339,7 +1333,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// This is some scope 'eval' or global eval replaced by user
// but not the built-in ECMAScript 'eval' function call
method.loadNull();
argsCount = loadArgs(callArgs);
argsCount = loadArgs(callNode.getArgs());
}
@Override
@ -1349,6 +1343,11 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
method._goto(eval_done);
method.label(invoke_direct_eval);
// Special/extra 'eval' arguments. These can be loaded late (in consumeStack) as we know none of
// them can ever be optimistic.
method.loadCompilerConstant(THIS);
method.load(callNode.getEvalArgs().getLocation());
method.load(CodeGenerator.this.lc.getCurrentFunction().isStrict());
// direct call to Global.directEval
globalDirectEval();
convertOptimisticReturnValue();
@ -4438,7 +4437,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
private MethodEmitter globalDirectEval() {
return method.invokestatic(GLOBAL_OBJECT, "directEval",
methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class));
methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, boolean.class));
}
private abstract class OptimisticOperation {

View File

@ -27,7 +27,6 @@ package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue;
import java.util.ArrayList;
@ -603,13 +602,11 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> implements Lo
// 'eval' call with at least one argument
if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) {
final FunctionNode currentFunction = lc.getCurrentFunction();
return callNode.setEvalArgs(
new CallNode.EvalArgs(
(Expression)ensureUniqueNamesIn(args.get(0)).accept(this),
compilerConstant(THIS),
evalLocation(callee),
currentFunction.isStrict()));
final List<Expression> evalArgs = new ArrayList<>(args.size());
for(final Expression arg: args) {
evalArgs.add((Expression)ensureUniqueNamesIn(arg).accept(this));
}
return callNode.setEvalArgs(new CallNode.EvalArgs(evalArgs, evalLocation(callee)));
}
}

View File

@ -65,61 +65,35 @@ public final class CallNode extends LexicalContextExpression implements Optimist
* Arguments to be passed to builtin {@code eval} function
*/
public static class EvalArgs {
/** evaluated code */
private final Expression code;
/** 'this' passed to evaluated code */
private final IdentNode evalThis;
private final List<Expression> args;
/** location string for the eval call */
private final String location;
/** is this call from a strict context? */
private final boolean strictMode;
/**
* Constructor
*
* @param code code to evaluate
* @param evalThis this node
* @param location location for the eval call
* @param strictMode is this a call from a strict context?
* @param args arguments to eval
* @param location location for the eval call
*/
public EvalArgs(final Expression code, final IdentNode evalThis, final String location, final boolean strictMode) {
this.code = code;
this.evalThis = evalThis;
public EvalArgs(final List<Expression> args, final String location) {
this.args = args;
this.location = location;
this.strictMode = strictMode;
}
/**
* Return the code that is to be eval:ed by this eval function
* @return code as an AST node
*/
public Expression getCode() {
return code;
public List<Expression> getArgs() {
return Collections.unmodifiableList(args);
}
private EvalArgs setCode(final Expression code) {
if (this.code == code) {
private EvalArgs setArgs(final List<Expression> args) {
if (this.args == args) {
return this;
}
return new EvalArgs(code, evalThis, location, strictMode);
}
/**
* Get the {@code this} symbol used to invoke this eval call
* @return the {@code this} symbol
*/
public IdentNode getThis() {
return this.evalThis;
}
private EvalArgs setThis(final IdentNode evalThis) {
if (this.evalThis == evalThis) {
return this;
}
return new EvalArgs(code, evalThis, location, strictMode);
return new EvalArgs(args, location);
}
/**
@ -129,14 +103,6 @@ public final class CallNode extends LexicalContextExpression implements Optimist
public String getLocation() {
return this.location;
}
/**
* Check whether this eval call is executed in strict mode
* @return true if executed in strict mode, false otherwise
*/
public boolean getStrictMode() {
return this.strictMode;
}
}
/** arguments for 'eval' call. Non-null only if this call node is 'eval' */
@ -212,8 +178,7 @@ public final class CallNode extends LexicalContextExpression implements Optimist
setArgs(Node.accept(visitor, Expression.class, args)).
setEvalArgs(evalArgs == null ?
null :
evalArgs.setCode((Expression)evalArgs.getCode().accept(visitor)).
setThis((IdentNode)evalArgs.getThis().accept(visitor))));
evalArgs.setArgs(Node.accept(visitor, Expression.class, evalArgs.getArgs()))));
// Theoretically, we'd need to instead pass lc to every setter and do a replacement on each. In practice,
// setType from TypeOverride can't accept a lc, and we don't necessarily want to go there now.
if (this != newCallNode) {

View File

@ -27,6 +27,7 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
@ -45,8 +46,11 @@ import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.codegen.ApplySpecialization;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.lookup.Lookup;
@ -107,6 +111,10 @@ public final class Global extends ScriptObject implements Scope {
/** Name invalidator for things like call/apply */
public static final Call BOOTSTRAP = staticCall(MethodHandles.lookup(), Global.class, "invalidateNameBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
/** Nashorn extension: arguments array */
@Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
public Object arguments;
/** ECMA 15.1.2.2 parseInt (string , radix) */
@Property(attributes = Attribute.NOT_ENUMERABLE)
public Object parseInt;
@ -411,12 +419,13 @@ public final class Global extends ScriptObject implements Scope {
// Used to store the last RegExp result to support deprecated RegExp constructor properties
private RegExpResult lastRegExpResult;
private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class);
private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class);
private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class);
private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class);
private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class);
private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class);
private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class);
private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class);
private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class);
private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class);
private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class);
private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class);
/** Invalidate a reserved name, such as "apply" or "call" if assigned */
public MethodHandle INVALIDATE_RESERVED_NAME = MH.bindTo(findOwnMH_V("invalidateReservedName", void.class, String.class), this);
@ -427,6 +436,20 @@ public final class Global extends ScriptObject implements Scope {
// context to which this global belongs to
private final Context context;
// current ScriptContext to use - can be null.
private ScriptContext scontext;
// associated Property object for "context" property.
private jdk.nashorn.internal.runtime.Property scontextProperty;
/**
* Set the current script context
* @param scontext script context
*/
public void setScriptContext(final ScriptContext scontext) {
this.scontext = scontext;
scontextProperty.setValue(this, this, scontext, false);
}
// global constants for this global - they can be replaced with MethodHandle.constant until invalidated
private static AtomicReference<GlobalConstants> gcsInstance = new AtomicReference<>();
@ -447,12 +470,7 @@ public final class Global extends ScriptObject implements Scope {
// null check on context
context.getClass();
/*
* Duplicate global's map and use it. This way the initial Map filled
* by nasgen (referenced from static field in this class) is retained
* 'as is' (as that one is process wide singleton.
*/
return $nasgenmap$.duplicate();
return $nasgenmap$;
}
/**
@ -483,6 +501,10 @@ public final class Global extends ScriptObject implements Scope {
return global;
}
private static Global instanceFrom(final Object self) {
return self instanceof Global? (Global)self : instance();
}
/**
* Return the global constants map for fields that
* can be accessed as MethodHandle.constant
@ -542,13 +564,13 @@ public final class Global extends ScriptObject implements Scope {
* as well as our extension builtin objects like "Java", "JSAdapter" as properties
* of the global scope object.
*/
public void initBuiltinObjects() {
public void initBuiltinObjects(final ScriptEngine engine) {
if (this.builtinObject != null) {
// already initialized, just return
return;
}
init();
init(engine);
}
/**
@ -848,6 +870,32 @@ public final class Global extends ScriptObject implements Scope {
return getLazilyCreatedValue(key, creator, dynamicInvokers);
}
/**
* Hook to search missing variables in ScriptContext if available
* @param self used to detect if scope call or not (this function is 'strict')
* @param name name of the variable missing
* @return value of the missing variable or undefined (or TypeError for scope search)
*/
public static Object __noSuchProperty__(final Object self, final Object name) {
final Global global = Global.instance();
final ScriptContext sctxt = global.scontext;
final String nameStr = name.toString();
if (sctxt != null) {
final int scope = sctxt.getAttributesScope(nameStr);
if (scope != -1) {
return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
}
}
if (self == UNDEFINED) {
// scope access and so throw ReferenceError
throw referenceError(global, "not.defined", nameStr);
}
return UNDEFINED;
}
/**
* This is the eval used when 'indirect' eval call is made.
*
@ -860,7 +908,7 @@ public final class Global extends ScriptObject implements Scope {
* @return the result of eval
*/
public static Object eval(final Object self, final Object str) {
return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
return directEval(self, str, UNDEFINED, UNDEFINED, false);
}
/**
@ -876,14 +924,14 @@ public final class Global extends ScriptObject implements Scope {
*
* This is directly invoked from generated when eval(code) is called in user code
*/
public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
if (!(str instanceof String || str instanceof ConsString)) {
return str;
}
final Global global = Global.instance();
final Global global = Global.instanceFrom(self);
final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict), true);
return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
}
/**
@ -895,7 +943,7 @@ public final class Global extends ScriptObject implements Scope {
* @return result of print (undefined)
*/
public static Object print(final Object self, final Object... objects) {
return printImpl(false, objects);
return Global.instanceFrom(self).printImpl(false, objects);
}
/**
@ -907,7 +955,7 @@ public final class Global extends ScriptObject implements Scope {
* @return result of println (undefined)
*/
public static Object println(final Object self, final Object... objects) {
return printImpl(true, objects);
return Global.instanceFrom(self).printImpl(true, objects);
}
/**
@ -921,7 +969,7 @@ public final class Global extends ScriptObject implements Scope {
* @throws IOException if source could not be read
*/
public static Object load(final Object self, final Object source) throws IOException {
final Global global = Global.instance();
final Global global = Global.instanceFrom(self);
final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
return global.getContext().load(scope, source);
}
@ -937,7 +985,7 @@ public final class Global extends ScriptObject implements Scope {
* @throws IOException if source could not be read
*/
public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
final Global global = Global.instance();
final Global global = Global.instanceFrom(self);
final int length = args.length;
final boolean hasArgs = 0 < length;
final Object from = hasArgs ? args[0] : UNDEFINED;
@ -1604,7 +1652,7 @@ public final class Global extends ScriptObject implements Scope {
splitState = state;
}
private void init() {
private void init(final ScriptEngine engine) {
assert Context.getGlobal() == this : "this global is not set as current";
final ScriptEnvironment env = getContext().getEnv();
@ -1705,12 +1753,19 @@ public final class Global extends ScriptObject implements Scope {
copyBuiltins();
// expose script (command line) arguments as "arguments" property of global
final Object argumentsObject = wrapAsObject(env.getArguments().toArray());
final int argumentsFlags = Attribute.NOT_ENUMERABLE;
addOwnProperty("arguments", argumentsFlags, argumentsObject);
arguments = wrapAsObject(env.getArguments().toArray());
if (env._scripting) {
// synonym for "arguments" in scripting mode
addOwnProperty("$ARG", argumentsFlags, argumentsObject);
addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
}
if (engine != null) {
final int NOT_ENUMERABLE_NOT_CONFIG = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE;
scontextProperty = addOwnProperty("context", NOT_ENUMERABLE_NOT_CONFIG, null);
addOwnProperty("engine", NOT_ENUMERABLE_NOT_CONFIG, engine);
// __noSuchProperty__ hook for ScriptContext search of missing variables
final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
}
}
@ -1878,8 +1933,8 @@ public final class Global extends ScriptObject implements Scope {
this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
}
private static Object printImpl(final boolean newLine, final Object... objects) {
final PrintWriter out = Global.getEnv().getOut();
private Object printImpl(final boolean newLine, final Object... objects) {
final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
final StringBuilder sb = new StringBuilder();
for (final Object object : objects) {
@ -2023,12 +2078,11 @@ public final class Global extends ScriptObject implements Scope {
for (final jdk.nashorn.internal.runtime.Property property : properties) {
final Object key = property.getKey();
final Object value = ObjectPrototype.get(key);
if (key.equals("constructor")) {
continue;
}
final Object value = ObjectPrototype.get(key);
if (value instanceof ScriptFunction) {
final ScriptFunction func = (ScriptFunction)value;
final ScriptObject prototype = ScriptFunction.getPrototype(func);

View File

@ -222,7 +222,6 @@ public final class NativeDebug extends ScriptObject {
out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
out.println("PropertyMap count " + PropertyMap.getCount());
out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
out.println("PropertyMap proto history hit " + PropertyMap.getProtoHistoryHit());

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

@ -184,6 +184,15 @@ public class ScriptFunctionImpl extends ScriptFunction {
return new AnonymousFunction();
}
private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs, final int flags) {
final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags);
func.setPrototype(UNDEFINED);
// Non-constructor built-in functions do not have "prototype" property
func.deleteOwnProperty(func.getMap().findProperty("prototype"));
return func;
}
/**
* Factory method for non-constructor built-in functions
*
@ -193,12 +202,18 @@ public class ScriptFunctionImpl extends ScriptFunction {
* @return new ScriptFunction
*/
static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) {
final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN);
func.setPrototype(UNDEFINED);
// Non-constructor built-in functions do not have "prototype" property
func.deleteOwnProperty(func.getMap().findProperty("prototype"));
return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN);
}
return func;
/**
* Factory method for non-constructor built-in, strict functions
*
* @param name function name
* @param methodHandle handle for invocation
* @return new ScriptFunction
*/
static ScriptFunction makeStrictFunction(final String name, final MethodHandle methodHandle) {
return makeFunction(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT );
}
/**

View File

@ -62,6 +62,7 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
import javax.script.ScriptEngine;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
@ -954,16 +955,17 @@ public final class Context {
* Initialize given global scope object.
*
* @param global the global
* @param engine the associated ScriptEngine instance, can be null
* @return the initialized global scope object.
*/
public Global initGlobal(final Global global) {
public Global initGlobal(final Global global, final ScriptEngine engine) {
// Need only minimal global object, if we are just compiling.
if (!env._compile_only) {
final Global oldGlobal = Context.getGlobal();
try {
Context.setGlobal(global);
// initialize global scope with builtin global objects
global.initBuiltinObjects();
global.initBuiltinObjects(engine);
} finally {
Context.setGlobal(oldGlobal);
}
@ -972,6 +974,16 @@ public final class Context {
return global;
}
/**
* Initialize given global scope object.
*
* @param global the global
* @return the initialized global scope object.
*/
public Global initGlobal(final Global global) {
return initGlobal(global, null);
}
/**
* Return the current global's context
* @return current global's context

View File

@ -405,12 +405,8 @@ public final class ECMAErrors {
// Look for script package in class name (into which compiler puts generated code)
if (className.startsWith(scriptPackage) && !CompilerConstants.isInternalMethodName(frame.getMethodName())) {
final String source = frame.getFileName();
/*
* Make sure that it is not some Java code that Nashorn has in that package!
* also, we don't want to report JavaScript code that lives in script engine implementation
* We want to report only user's own scripts and not any of our own scripts like "engine.js"
*/
return source != null && !source.endsWith(".java") && !source.contains(NashornException.ENGINE_SCRIPT_SOURCE_NAME);
// Make sure that it is not some Java code that Nashorn has in that package!
return source != null && !source.endsWith(".java");
}
return false;
}

View File

@ -145,21 +145,6 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
this(propertyMap, propertyMap.properties);
}
/**
* Duplicates this PropertyMap instance. This is used to duplicate 'shared'
* maps {@link PropertyMap} used as process wide singletons. Shared maps are
* duplicated for every global scope object. That way listeners, proto and property
* histories are scoped within a global scope.
*
* @return Duplicated {@link PropertyMap}.
*/
public PropertyMap duplicate() {
if (Context.DEBUG) {
duplicatedCount++;
}
return new PropertyMap(this.properties, this.className, 0, 0, 0, containsArrayKeys());
}
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(properties.getProperties());
@ -968,7 +953,6 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
// counters updated only in debug mode
private static int count;
private static int clonedCount;
private static int duplicatedCount;
private static int historyHit;
private static int protoInvalidations;
private static int protoHistoryHit;
@ -988,13 +972,6 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
return clonedCount;
}
/**
* @return The number of maps that are duplicated.
*/
public static int getDuplicatedCount() {
return duplicatedCount;
}
/**
* @return The number of times history was successfully used.
*/

View File

@ -103,10 +103,10 @@ public abstract class ScriptObject implements PropertyAccess {
public static final String PROTO_PROPERTY_NAME = "__proto__";
/** Search fall back routine name for "no such method" */
static final String NO_SUCH_METHOD_NAME = "__noSuchMethod__";
public static final String NO_SUCH_METHOD_NAME = "__noSuchMethod__";
/** Search fall back routine name for "no such property" */
static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
public static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
/** Per ScriptObject flag - is this a scope object? */
public static final int IS_SCOPE = 1 << 0;
@ -160,7 +160,8 @@ public abstract class ScriptObject implements PropertyAccess {
static final MethodHandle GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class);
private static final MethodHandle TRUNCATINGFILTER = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class);
private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH_S("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class);
private static final MethodHandle KNOWNFUNCPROPGUARDPROTO = findOwnMH_S("knownFunctionPropertyGuardProto", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, int.class, ScriptFunction.class);
private static final ArrayList<MethodHandle> PROTO_FILTERS = new ArrayList<>();
@ -2271,13 +2272,20 @@ public abstract class ScriptObject implements PropertyAccess {
if (scopeAccess && func.isStrict()) {
mh = bindTo(mh, UNDEFINED);
}
return new GuardedInvocation(
mh,
//TODO this always does a scriptobject check
getKnownFunctionPropertyGuard(
find.isSelf()?
getKnownFunctionPropertyGuardSelf(
getMap(),
find.getGetter(Object.class, INVALID_PROGRAM_POINT),
find.getOwner(),
func)
:
//TODO this always does a scriptobject check
getKnownFunctionPropertyGuardProto(
getMap(),
find.getGetter(Object.class, INVALID_PROGRAM_POINT),
find.getProtoChainLength(),
func),
getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
//TODO this doesn't need a ClassCastException as guard always checks script object
@ -3595,15 +3603,51 @@ public abstract class ScriptObject implements PropertyAccess {
return MH.findStatic(MethodHandles.lookup(), ScriptObject.class, name, MH.type(rtype, types));
}
private static MethodHandle getKnownFunctionPropertyGuard(final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
return MH.insertArguments(KNOWNFUNCPROPGUARD, 1, map, getter, where, func);
private static MethodHandle getKnownFunctionPropertyGuardSelf(final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
return MH.insertArguments(KNOWNFUNCPROPGUARDSELF, 1, map, getter, func);
}
@SuppressWarnings("unused")
private static boolean knownFunctionPropertyGuard(final Object self, final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
private static boolean knownFunctionPropertyGuardSelf(final Object self, final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
try {
return getter.invokeExact(where) == func;
return getter.invokeExact(self) == func;
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
throw new RuntimeException(t);
}
}
return false;
}
private static MethodHandle getKnownFunctionPropertyGuardProto(final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
return MH.insertArguments(KNOWNFUNCPROPGUARDPROTO, 1, map, getter, depth, func);
}
@SuppressWarnings("unused")
private static ScriptObject getProto(final ScriptObject self, final int depth) {
ScriptObject proto = self;
for (int d = 0; d < depth; d++) {
proto = proto.getProto();
if (proto == null) {
return null;
}
}
return proto;
}
@SuppressWarnings("unused")
private static boolean knownFunctionPropertyGuardProto(final Object self, final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
final ScriptObject proto = getProto((ScriptObject)self, depth);
if (proto == null) {
return false;
}
try {
return getter.invokeExact((Object)proto) == func;
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {

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

@ -49,7 +49,7 @@ makeFuncAndCall("switch(0) { default: {break;} return }");
makeFuncAndCall("L: { { break L; } return; }");
makeFuncAndCall("L: { while(0) break L; return; }");
makeFuncExpectError("L: {while(0) break L; return [](); }", TypeError);
// makeFuncAndCall("do with({}) break ; while(0);");
makeFuncAndCall("do with({}) break ; while(0);");
makeFuncAndCall("while(0) with({}) continue ;");
makeFuncAndCall("eval([]);");
makeFuncAndCall("try{} finally{[]}");
@ -59,10 +59,10 @@ makeFuncAndCall("Error() * (false)[-0]--");
makeFuncAndCall("try { var x = 1, x = null; } finally { }");
makeFuncAndCall("try { var x = {}, x = []; } catch(x3) { }");
makeFuncAndCall("[delete this]");
// makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
// makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
// makeFuncAndCall("eval(\"[,,];\", [11,12,13,14].some)");
// makeFuncAndCall("eval(\"1.2e3\", ({})[ /x/ ])");
makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
makeFuncAndCall("eval(\"[,,];\", [11,12,13,14].some)");
makeFuncAndCall("eval(\"1.2e3\", ({})[ /x/ ])");
makeFuncExpectError("eval(\"x4\", x3);", ReferenceError);
makeFuncAndCall("with({5.0000000000000000000000: String()}){(false); }");
makeFuncAndCall("try { var x = undefined, x = 5.0000000000000000000000; } catch(x) { x = undefined; }");
@ -72,4 +72,4 @@ makeFuncAndCall("(false % !this) && 0");
makeFuncAndCall("with({8: 'fafafa'.replace()}){ }");
makeFuncAndCall("(function (x) '' )(true)");
makeFuncExpectError("new eval(function(){})", TypeError);
//** makeFuncAndCall('eval("23", ({})[/x/])');
makeFuncAndCall('eval("23", ({})[/x/])');

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2010, 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-8047067: all eval arguments need to be copied in Lower
*
* @test
* @run
*/
// The second expression triggers optimistic deoptimization, and if not
// all eval arguments were copied in Lower, we'd end up with duplicate
// program points that'd cause incorrect continuation program point in
// the rest-of, and therefore a bad stack, and therefore an AIOOBE in
// the continuation setup code.
eval("23", ({})[/x/])

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

View File

@ -136,8 +136,7 @@ public class CodeStoreAndPathTest {
// Check that a new compiled script is stored in existing code cache
e.eval(code1);
final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
// Already one compiled script has been stored in the cache during initialization
checkCompiledScripts(stream, 2);
checkCompiledScripts(stream, 1);
// Setting to default current working dir
} finally {
System.setProperty("user.dir", oldUserDir);
@ -154,9 +153,8 @@ public class CodeStoreAndPathTest {
e.eval(code1);
e.eval(code2);
e.eval(code3);// less than minimum size for storing
// Already one compiled script has been stored in the cache during initialization
// adding code1 and code2.
final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
checkCompiledScripts(stream, 3);
checkCompiledScripts(stream, 2);
}
}