This commit is contained in:
Lana Steuck 2017-01-26 21:20:32 +00:00
commit 07f78bf4d2
11 changed files with 223 additions and 37 deletions

View File

@ -18,7 +18,7 @@ Information about the forest extension can be found at
http://mercurial.selenic.com/wiki/ForestExtension
and downlaoded using
and downloaded using
hg clone https://bitbucket.org/gxti/hgforest
@ -39,7 +39,7 @@ To learn about Mercurial in detail, please visit http://hgbook.red-bean.com.
- How to build?
To build Nashorn, you need to install JDK 9. You may use the Nashorn
forest build (recommended) or down load from java.net. You will need to
forest build (recommended) or download from java.net. You will need to
set JAVA_HOME environmental variable to point to your JDK installation
directory.

View File

@ -394,6 +394,18 @@
</target>
<target name="generate-security-config" depends="generate-policy-file, generate-security-properties-file"/>
<target name="generate-security-properties-file" depends="prepare">
<echo file="${build.dir}/nashorn.security.properties">
package.access=sun.misc.,\
sun.reflect.,\
jdk.nashorn.internal.
</echo>
</target>
<target name="generate-policy-file" depends="prepare">
<echo file="${build.dir}/nashorn.policy">
@ -600,7 +612,7 @@ grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" {
<target name="test" depends="prepare, javadoc, test-pessimistic, test-optimistic"/>
<target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
<target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<echo message="Running test suite in OPTIMISTIC mode..."/>
<antcall target="-test-nosecurity" inheritRefs="true">
<param name="optimistic" value="true"/>
@ -612,7 +624,7 @@ grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" {
</antcall>
</target>
<target name="test-pessimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
<target name="test-pessimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<echo message="Running test suite in PESSIMISTIC mode..."/>
<antcall target="-test-nosecurity" inheritRefs="true">
<param name="optimistic" value="false"/>
@ -655,7 +667,7 @@ grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" {
</testng>
</target>
<target name="testmarkdown" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
<target name="testmarkdown" depends="jar, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<fileset id="test.classes" dir="${build.test.classes.dir}">
<include name="**/framework/*Test.class"/>
</fileset>
@ -673,7 +685,7 @@ grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" {
</testng>
</target>
<target name="test262" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
<target name="test262" depends="jar, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<fileset id="test.classes" dir="${build.test.classes.dir}">
<include name="**/framework/*Test.class"/>
</fileset>
@ -696,7 +708,7 @@ grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" {
<target name="test262parallel" depends="test262-parallel"/>
<target name="test262-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
<target name="test262-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<!-- use just build.test.classes.dir to avoid referring to TestNG -->
<java classname="${parallel.test.runner}" dir="${basedir}" fork="true" failonerror="true">
<jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
@ -714,7 +726,7 @@ grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" {
<target name="testparallel" depends="test-parallel"/>
<target name="test-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
<target name="test-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<!-- use just build.test.classes.dir to avoid referring to TestNG -->
<java classname="${parallel.test.runner}" dir="${basedir}"
failonerror="true"

View File

@ -408,7 +408,7 @@ run.test.jvmargs.main=${run.test.jvmargs.common} -esa -ea
run.test.jvmargs.octane.main=${run.test.jvmargs.common} -XX:TypeProfileLevel=222
# Security manager args - make sure that we run with the nashorn.policy that the build creates
run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${build.dir}/nashorn.policy
run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${build.dir}/nashorn.policy -Djava.security.properties=${build.dir}/nashorn.security.properties
# VM options for script tests with @fork option
test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -cp ${run.test.classpath}

View File

@ -395,39 +395,45 @@ public class GuardedInvocation {
}
/**
* Applies argument filters to both the invocation and the guard (if there
* is one) with {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}.
* Applies argument filters to both the invocation and the guard
* (if it exists and has at least {@code pos + 1} parameters) with
* {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}.
* @param pos the position of the first argument being filtered
* @param filters the argument filters
* @return a filtered invocation
*/
public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) {
return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null :
MethodHandles.filterArguments(guard, pos, filters));
return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters),
guard == null || pos >= guard.type().parameterCount() ?
guard : MethodHandles.filterArguments(guard, pos, filters));
}
/**
* Makes an invocation that drops arguments in both the invocation and the
* guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, List)}.
* guard (if it exists and has at least {@code pos} parameters) with
* {@link MethodHandles#dropArguments(MethodHandle, int, List)}.
* @param pos the position of the first argument being dropped
* @param valueTypes the types of the values being dropped
* @return an invocation that drops arguments
*/
public GuardedInvocation dropArguments(final int pos, final List<Class<?>> valueTypes) {
return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
MethodHandles.dropArguments(guard, pos, valueTypes));
return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes),
guard == null || pos > guard.type().parameterCount() ?
guard : MethodHandles.dropArguments(guard, pos, valueTypes));
}
/**
* Makes an invocation that drops arguments in both the invocation and the
* guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, Class...)}.
* guard (if it exists and has at least {@code pos} parameters) with
* {@link MethodHandles#dropArguments(MethodHandle, int, Class...)}.
* @param pos the position of the first argument being dropped
* @param valueTypes the types of the values being dropped
* @return an invocation that drops arguments
*/
public GuardedInvocation dropArguments(final int pos, final Class<?>... valueTypes) {
return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
MethodHandles.dropArguments(guard, pos, valueTypes));
return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes),
guard == null || pos > guard.type().parameterCount() ?
guard : MethodHandles.dropArguments(guard, pos, valueTypes));
}

View File

@ -38,7 +38,7 @@ import jdk.nashorn.internal.runtime.linker.Bootstrap;
/**
* This linker exporter is a service provider that exports Nashorn Dynalink
* linkers to external users. Other languague runtimes that use Dynalink
* linkers to external users. Other language runtimes that use Dynalink
* can use the linkers exported by this provider to support tight integration
* of Nashorn objects.
*/

View File

@ -735,7 +735,7 @@ public class ScriptFunction extends ScriptObject {
/**
* Name getter - ECMA Function.name
*
* @param self self refence
* @param self self reference
* @return the name, or undefined if none
*/
public static Object G$name(final Object self) {
@ -1120,12 +1120,19 @@ public class ScriptFunction extends ScriptObject {
assert appliedRequest != null; // Bootstrap.isCallable() returned true for args[1], so it must produce a linkage.
final Class<?> applyFnType = descType.parameterType(0);
MethodHandle inv = appliedInvocation.getInvocation(); //method handle from apply invocation. the applied function invocation
// Invocation and guard handles from apply invocation.
MethodHandle inv = appliedInvocation.getInvocation();
MethodHandle guard = appliedInvocation.getGuard();
if (isApply && !isFailedApplyToCall) {
if (passesArgs) {
// Make sure that the passed argArray is converted to Object[] the same way NativeFunction.apply() would do it.
inv = MH.filterArguments(inv, 2, NativeFunction.TO_APPLY_ARGS);
// Some guards (non-strict functions with non-primitive this) have a this-object parameter, so we
// need to apply this transformations to them as well.
if (guard.type().parameterCount() > 2) {
guard = MH.filterArguments(guard, 2, NativeFunction.TO_APPLY_ARGS);
}
} else {
// If the original call site doesn't pass argArray, pass in an empty array
inv = MH.insertArguments(inv, 2, (Object) ScriptRuntime.EMPTY_ARRAY);
@ -1144,12 +1151,25 @@ public class ScriptFunction extends ScriptObject {
if (!passesThis) {
// If the original call site doesn't pass in a thisArg, pass in Global/undefined as needed
inv = bindImplicitThis(appliedFn, inv);
inv = bindImplicitThis(appliedFnNeedsWrappedThis, inv);
// guard may have this-parameter that needs to be inserted
if (guard.type().parameterCount() > 1) {
guard = bindImplicitThis(appliedFnNeedsWrappedThis, guard);
}
} else if (appliedFnNeedsWrappedThis) {
// target function needs a wrapped this, so make sure we filter for that
inv = MH.filterArguments(inv, 1, WRAP_THIS);
// guard may have this-parameter that needs to be wrapped
if (guard.type().parameterCount() > 1) {
guard = MH.filterArguments(guard, 1, WRAP_THIS);
}
}
final MethodType guardType = guard.type(); // Needed for combining guards below
// We need to account for the dropped (apply|call) function argument.
inv = MH.dropArguments(inv, 0, applyFnType);
guard = MH.dropArguments(guard, 0, applyFnType);
/*
* Dropargs can only be non-()V in the case of isApply && !isFailedApplyToCall, which
@ -1160,15 +1180,6 @@ public class ScriptFunction extends ScriptObject {
inv = MH.dropArguments(inv, 4 + i, dropArgs.parameterType(i));
}
MethodHandle guard = appliedInvocation.getGuard();
// If the guard checks the value of "this" but we aren't passing thisArg, insert the default one
if (!passesThis && guard.type().parameterCount() > 1) {
guard = bindImplicitThis(appliedFn, guard);
}
final MethodType guardType = guard.type();
// We need to account for the dropped (apply|call) function argument.
guard = MH.dropArguments(guard, 0, descType.parameterType(0));
// Take the "isApplyFunction" guard, and bind it to this function.
MethodHandle applyFnGuard = MH.insertArguments(IS_APPLY_FUNCTION, 2, this); //TODO replace this with switchpoint
// Adapt the guard to receive all the arguments that the original guard does.
@ -1244,9 +1255,9 @@ public class ScriptFunction extends ScriptObject {
return ScriptObject.adaptHandleToVarArgCallSite(arrayConvertingGuard, descParamCount);
}
private static MethodHandle bindImplicitThis(final Object fn, final MethodHandle mh) {
private static MethodHandle bindImplicitThis(final boolean needsWrappedThis, final MethodHandle mh) {
final MethodHandle bound;
if (fn instanceof ScriptFunction && ((ScriptFunction) fn).needsWrappedThis()) {
if (needsWrappedThis) {
bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER);
} else {
bound = mh;

View File

@ -147,9 +147,8 @@ public class NashornBeansLinker implements GuardingDynamicLinker {
new NashornBeansLinkerServices(linkerServices));
// Bind to the method, drop the original "this" and use original "callee" as this:
final MethodHandle inv = linkerServices.filterInternalObjects(gi
.getInvocation() // (method, this, args...)
.bindTo(method)); // (this, args...)
final MethodHandle inv = gi.getInvocation() // (method, this, args...)
.bindTo(method); // (this, args...)
final MethodHandle calleeToThis = MH.dropArguments(inv, 1, callType.parameterType(1)); // (callee->this, <drop>, args...)
return gi.replaceMethods(calleeToThis, gi.getGuard());
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2017, 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.
*/
/**
* 8166186: ClassCastException with arguments usage
*
* @test
* @run
*/
function F (arg) {
print("F called");
Function.prototype.call.apply(G, arguments);
}
function G (){
print("G called");
print(this);
if (C++ > 5) return;
F("argument " + C);
}
var C = 0;
G();

View File

@ -0,0 +1,20 @@
G called
[object global]
F called
G called
argument 1
F called
G called
argument 2
F called
G called
argument 3
F called
G called
argument 4
F called
G called
argument 5
F called
G called
argument 6

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2017, 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-8172006: Nashorn JavaScript engine fails to call @FunctionalInterface with a java.util.List argument
*
* @test
* @run
*/
var f = Java.type("jdk.nashorn.test.models.FunctionalInterfaceProvider").getImpl();
var s = "a";
s += "b";
var o = { p: 10 };
var a = [1, 2, 3];
f([ f([]), f([]), f([]), f([]), f([]), f([]), f([]), f([]) ]);
f([ f([]), f([ f([]), f([f([]), f([]), f([]) ]), f([])]), f([]) ]);
f([ f([s]), f([o]), f([a]), f([s + "c"]), f([o]), f([a]) ]);

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2017, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package jdk.nashorn.test.models;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.testng.Assert;
import java.util.List;
public class FunctionalInterfaceProvider {
private final static Object RETURN_TOKEN = new Object();
public static Functional getImpl() {
return (l) -> {
// Make sure parameters are properly exported
for (final Object o : l) {
Assert.assertTrue(o == RETURN_TOKEN
|| o instanceof ScriptObjectMirror
|| o instanceof String);
}
return RETURN_TOKEN;
};
}
@FunctionalInterface
public interface Functional {
Object method(List<Object> args);
}
}