This commit is contained in:
Lana Steuck 2015-01-12 12:24:14 -08:00
commit b237c3a926
19 changed files with 4931 additions and 36 deletions

94
nashorn/samples/jd.js Normal file
View File

@ -0,0 +1,94 @@
#// Usage: jjs -cp <asmtools.jar> jd.js -- <classname> [jdis|jdec]
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// javap-like disassembler/decoder tool that disassembles/decodes
// java classes but with OpenJDK AsmTools disassembler/decoder syntax.
// You need to build asmtool.jar from OpenJDK codetools project
// specify it with -cp option.
// See also https://wiki.openjdk.java.net/display/CodeTools/AsmTools
function usage() {
print("Usage: jjs -cp <asmtools.jar> jd.js -- <classname> [jdis|jdec]");
exit(1);
}
if (arguments.length == 0) {
usage();
}
// argument handling
// convert to internal class name
var className = arguments[0].replaceAll('\\.', '/');
var tool;
if (arguments.length > 1) {
tool = arguments[1];
switch (tool) {
case 'jdis':
case 'jdec':
break;
default:
usage();
}
} else {
tool = "jdis"; // default tool
}
// Java classes used
var AsmTools = Java.type("org.openjdk.asmtools.Main");
var Files = Java.type("java.nio.file.Files");
var StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
// retrive input stream for .class bytes
var cl = AsmTools.class.classLoader;
var res = cl.getResource(className + ".class");
if (res) {
var is = res.openStream();
var tmpPath;
try {
// copy the content of the .class to a temp file
tmpPath = Files.createTempFile("asmtools-", ".class");
// mark as delete-on-exit
tmpPath.toFile().deleteOnExit();
Files.copy(is, tmpPath, [ StandardCopyOption.REPLACE_EXISTING ]);
} finally {
is.close();
}
// invoke asmtools Main
AsmTools.main([ tool, tmpPath.toString() ]);
} else {
print("no such class: " + arguments[0]);
exit(1);
}

View File

@ -36,7 +36,10 @@ import java.util.Set;
* treat objects of such classes just like nashorn script objects. Usual nashorn
* operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued
* to appropriate method call of this class.
*
* @since 1.8u40
*/
@jdk.Exported
public abstract class AbstractJSObject implements JSObject {
/**
* Call this object as a JavaScript function. This is equivalent to

View File

@ -28,7 +28,10 @@ package jdk.nashorn.api.scripting;
* Class filter (optional) to be used by nashorn script engine.
* jsr-223 program embedding nashorn script can set ClassFilter instance
* to be used when an engine instance is created.
*
* @since 1.8u40
*/
@jdk.Exported
public interface ClassFilter {
/**
* Should the Java class of the specified name be exposed to scripts?

View File

@ -33,7 +33,10 @@ import java.util.Set;
* treat objects of such classes just like nashorn script objects. Usual nashorn
* operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued
* to appropriate method call of this interface.
*
* @since 1.8u40
*/
@jdk.Exported
public interface JSObject {
/**
* Call this object as a JavaScript function. This is equivalent to

View File

@ -41,7 +41,10 @@ import jdk.nashorn.internal.runtime.ScriptObject;
* script object or Java access to script object properties via java.util.Map
* interface. In these cases, user code will get an instance of this or
* implementation defined subclass.
*
* @since 1.8u40
*/
@jdk.Exported
@SuppressWarnings("serial")
public abstract class NashornException extends RuntimeException {
// script file name

View File

@ -65,8 +65,10 @@ import jdk.nashorn.internal.runtime.options.Options;
* {@link NashornScriptEngineFactory#getScriptEngine()}. Note that this engine implements the {@link Compilable} and
* {@link Invocable} interfaces, allowing for efficient precompilation and repeated execution of scripts.
* @see NashornScriptEngineFactory
*
* @since 1.8u40
*/
@jdk.Exported
public final class NashornScriptEngine extends AbstractScriptEngine implements Compilable, Invocable {
/**
* Key used to associate Nashorn global object mirror with arbitrary Bindings instance.

View File

@ -44,7 +44,10 @@ import jdk.nashorn.internal.runtime.Version;
* </ul>
* Programs executing in engines created using {@link #getScriptEngine(String[])} will have the passed arguments
* accessible as a global variable named {@code "arguments"}.
*
* @since 1.8u40
*/
@jdk.Exported
public final class NashornScriptEngineFactory implements ScriptEngineFactory {
@Override
public String getEngineName() {
@ -120,7 +123,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory {
// used to execute scripts concurrently on multiple threads.
return null;
default:
throw new IllegalArgumentException("Invalid key");
return null;
}
}

View File

@ -54,7 +54,10 @@ import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
/**
* Mirror object that wraps a given Nashorn Script object.
*
* @since 1.8u40
*/
@jdk.Exported
public final class ScriptObjectMirror extends AbstractJSObject implements Bindings {
private static AccessControlContext getContextAccCtxt() {
final Permissions perms = new Permissions();

View File

@ -36,7 +36,10 @@ import jdk.nashorn.internal.runtime.linker.Bootstrap;
/**
* Utilities that are to be called from script code.
*
* @since 1.8u40
*/
@jdk.Exported
public final class ScriptUtils {
private ScriptUtils() {}

View File

@ -35,7 +35,10 @@ import jdk.nashorn.internal.runtime.Source;
/**
* A Reader that reads from a URL. Used to make sure that the reader
* reads content from given URL and can be trusted to do so.
*
* @since 1.8u40
*/
@jdk.Exported
public final class URLReader extends Reader {
// underlying URL
private final URL url;

View File

@ -35,5 +35,8 @@
* interfaces, allowing for efficient pre-compilation and repeated execution of scripts. In addition,
* this package provides nashorn specific extension classes, interfaces and methods. See
* {@link jdk.nashorn.api.scripting.NashornScriptEngineFactory} for further details.
*
* @since 1.8u40
*/
@jdk.Exported
package jdk.nashorn.api.scripting;

View File

@ -38,7 +38,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
@ -186,9 +185,6 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
private static final String GLOBAL_OBJECT = Type.getInternalName(Global.class);
private static final String SCRIPTFUNCTION_IMPL_NAME = Type.getInternalName(ScriptFunctionImpl.class);
private static final Type SCRIPTFUNCTION_IMPL_TYPE = Type.typeFor(ScriptFunction.class);
private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class,
"create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class);
private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class,
@ -201,6 +197,11 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
"ensureNumber", double.class, Object.class, int.class);
private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
"create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class);
private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
"create", ScriptFunction.class, Object[].class, int.class);
private static final Class<?> ITERATOR_CLASS = Iterator.class;
static {
assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
@ -2242,7 +2243,6 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
} else {
methodEmitter.loadConstants().load(index).arrayload();
if (object instanceof ArrayData) {
// avoid cast to non-public ArrayData subclass
methodEmitter.checkcast(ArrayData.class);
methodEmitter.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class));
} else if (cls != Object.class) {
@ -2251,6 +2251,10 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
}
private void loadConstantsAndIndex(final Object object, final MethodEmitter methodEmitter) {
methodEmitter.loadConstants().load(compiler.getConstantData().add(object));
}
// literal values
private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) {
final Object value = node.getValue();
@ -4323,15 +4327,13 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(functionNode.getId());
if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
final CompileUnit fnUnit = functionNode.getCompileUnit();
final MethodEmitter createFunction = fnUnit.getClassEmitter().method(
final MethodEmitter createFunction = functionNode.getCompileUnit().getClassEmitter().method(
EnumSet.of(Flag.PUBLIC, Flag.STATIC), CREATE_PROGRAM_FUNCTION.symbolName(),
ScriptFunction.class, ScriptObject.class);
createFunction.begin();
createFunction._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup();
loadConstant(data, fnUnit, createFunction);
loadConstantsAndIndex(data, createFunction);
createFunction.load(SCOPE_TYPE, 0);
createFunction.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
createFunction.invoke(CREATE_FUNCTION_OBJECT);
createFunction._return();
createFunction.end();
}
@ -4346,15 +4348,14 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
return;
}
method._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup();
loadConstant(data);
loadConstantsAndIndex(data, method);
if (functionNode.needsParentScope()) {
method.loadCompilerConstant(SCOPE);
method.invoke(CREATE_FUNCTION_OBJECT);
} else {
method.loadNull();
method.invoke(CREATE_FUNCTION_OBJECT_NO_SCOPE);
}
method.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
}
// calls on Global class.

View File

@ -118,13 +118,26 @@ public class ScriptFunctionImpl extends ScriptFunction {
}
/**
* Constructor called by (compiler) generated code for {@link ScriptObject}s.
* Factory method called by compiler generated code for functions that need parent scope.
*
* @param data static function data
* @param scope scope object
* @param constants the generated class' constant array
* @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array.
* @param scope the parent scope object
* @return a newly created function object
*/
public ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope) {
this(data, scope, Global.instance());
public static ScriptFunction create(final Object[] constants, final int index, final ScriptObject scope) {
return new ScriptFunctionImpl((RecompilableScriptFunctionData)constants[index], scope, Global.instance());
}
/**
* Factory method called by compiler generated code for functions that don't need parent scope.
*
* @param constants the generated class' constant array
* @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array.
* @return a newly created function object
*/
public static ScriptFunction create(final Object[] constants, final int index) {
return create(constants, index, null);
}
/**

View File

@ -48,28 +48,25 @@ final class AdaptationResult {
ERROR_NO_ACCESSIBLE_CONSTRUCTOR,
ERROR_MULTIPLE_SUPERCLASSES,
ERROR_NO_COMMON_LOADER,
ERROR_FINAL_FINALIZER
ERROR_FINAL_FINALIZER,
ERROR_OTHER
}
static final AdaptationResult SUCCESSFUL_RESULT = new AdaptationResult(Outcome.SUCCESS, "");
private final Outcome outcome;
private final String classList;
private final String[] messageArgs;
AdaptationResult(final Outcome outcome, final String classList) {
AdaptationResult(final Outcome outcome, final String... messageArgs) {
this.outcome = outcome;
this.classList = classList;
this.messageArgs = messageArgs;
}
Outcome getOutcome() {
return outcome;
}
String getClassList() {
return classList;
}
ECMAException typeError() {
return ECMAErrors.typeError("extend." + outcome, classList);
return ECMAErrors.typeError("extend." + outcome, messageArgs);
}
}

View File

@ -184,7 +184,7 @@ public final class JavaAdapterFactory {
final ClassAndLoader definingClassAndLoader = ClassAndLoader.getDefiningClassAndLoader(types);
final Map<List<Class<?>>, AdapterInfo> adapterInfoMap = ADAPTER_INFO_MAPS.get(definingClassAndLoader.getRepresentativeClass());
final List<Class<?>> typeList = types.length == 1 ? getSingletonClassList(types[0]) : Arrays.asList(types.clone());
final List<Class<?>> typeList = types.length == 1 ? Collections.<Class<?>>singletonList(types[0]) : Arrays.asList(types.clone());
AdapterInfo adapterInfo;
synchronized(adapterInfoMap) {
adapterInfo = adapterInfoMap.get(typeList);
@ -196,11 +196,6 @@ public final class JavaAdapterFactory {
return adapterInfo;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static List<Class<?>> getSingletonClassList(final Class<?> clazz) {
return (List)Collections.singletonList(clazz);
}
/**
* For a given class, create its adapter class and associated info.
* @param type the class for which the adapter is created
@ -241,6 +236,8 @@ public final class JavaAdapterFactory {
return new AdapterInfo(effectiveSuperClass, interfaces, definingClassAndLoader);
} catch (final AdaptationException e) {
return new AdapterInfo(e.getAdaptationResult());
} catch (final RuntimeException e) {
return new AdapterInfo(new AdaptationResult(AdaptationResult.Outcome.ERROR_OTHER, Arrays.toString(types), e.toString()));
}
}
}, CREATE_ADAPTER_INFO_ACC_CTXT);

View File

@ -141,6 +141,7 @@ type.error.extend.ERROR_NO_ACCESSIBLE_CONSTRUCTOR=Can not extend class {0} as it
type.error.extend.ERROR_MULTIPLE_SUPERCLASSES=Can not extend multiple classes {0}. At most one of the specified types can be a class, the rest must all be interfaces.
type.error.extend.ERROR_NO_COMMON_LOADER=Can not find a common class loader for ScriptObject and {0}.
type.error.extend.ERROR_FINAL_FINALIZER=Can not extend class because {0} has a final finalize method.
type.error.extend.ERROR_OTHER=Can not extend/implement {0} because of {1}
type.error.no.constructor.matches.args=Can not construct {0} with the passed arguments; they do not match any of its constructor signatures.
type.error.no.method.matches.args=Can not invoke method {0} with the passed arguments; they do not match any of its method signatures.
type.error.method.not.constructor=Java method {0} cannot be used as a constructor.

View File

@ -0,0 +1,42 @@
/*
* 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-8068580: make JavaAdapterFactory.isAutoConvertibleFromFunction more robust
*
* @test
* @run
*/
var BigAbstract = Java.type("jdk.nashorn.test.models.BigAbstract")
try {
new BigAbstract({});
} catch (e) {
Assert.assertTrue(e instanceof TypeError);
Assert.assertEquals(e.message, "Can not extend/implement [class jdk.nashorn.test.models.BigAbstract] because of java.lang.RuntimeException: Method code too large!");
}
try {
BigAbstract.accept(function() { });
} catch (e) {
Assert.assertSame(e.class, java.lang.ClassCastException.class);
}

View File

@ -27,6 +27,7 @@ package jdk.nashorn.api.scripting;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.io.StringReader;
@ -668,6 +669,17 @@ public class ScriptEngineTest {
assertEquals("helloworld", inv.invokeMethod(ctx.get(), "join", ""));
}
// @bug 8068524: NashornScriptEngineFactory.getParameter() throws IAE
// for an unknown key, doesn't conform to the general spec
@Test
public void getParameterInvalidKeyTest() throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine e = manager.getEngineByName("nashorn");
// no exception expected here!
Object value = e.getFactory().getParameter("no value assigned to this key");
assertNull(value);
}
private static void checkProperty(final ScriptEngine e, final String name)
throws ScriptException {
final String value = System.getProperty(name);

File diff suppressed because it is too large Load Diff