Thu, 30 Jan 2014 20:14:29 +0100
8032681: Issues with Nashorn
Reviewed-by: ahgross, jlaskey, sundar
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java Thu Jan 30 20:14:29 2014 +0100 1.3 @@ -0,0 +1,102 @@ 1.4 +/* 1.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +/* 1.30 + * This file is available under and governed by the GNU General Public 1.31 + * License version 2 only, as published by the Free Software Foundation. 1.32 + * However, the following notice accompanied the original version of this 1.33 + * file, and Oracle licenses the original version of this file under the BSD 1.34 + * license: 1.35 + */ 1.36 +/* 1.37 + Copyright 2009-2013 Attila Szegedi 1.38 + 1.39 + Licensed under both the Apache License, Version 2.0 (the "Apache License") 1.40 + and the BSD License (the "BSD License"), with licensee being free to 1.41 + choose either of the two at their discretion. 1.42 + 1.43 + You may not use this file except in compliance with either the Apache 1.44 + License or the BSD License. 1.45 + 1.46 + If you choose to use this file in compliance with the Apache License, the 1.47 + following notice applies to you: 1.48 + 1.49 + You may obtain a copy of the Apache License at 1.50 + 1.51 + http://www.apache.org/licenses/LICENSE-2.0 1.52 + 1.53 + Unless required by applicable law or agreed to in writing, software 1.54 + distributed under the License is distributed on an "AS IS" BASIS, 1.55 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1.56 + implied. See the License for the specific language governing 1.57 + permissions and limitations under the License. 1.58 + 1.59 + If you choose to use this file in compliance with the BSD License, the 1.60 + following notice applies to you: 1.61 + 1.62 + Redistribution and use in source and binary forms, with or without 1.63 + modification, are permitted provided that the following conditions are 1.64 + met: 1.65 + * Redistributions of source code must retain the above copyright 1.66 + notice, this list of conditions and the following disclaimer. 1.67 + * Redistributions in binary form must reproduce the above copyright 1.68 + notice, this list of conditions and the following disclaimer in the 1.69 + documentation and/or other materials provided with the distribution. 1.70 + * Neither the name of the copyright holder nor the names of 1.71 + contributors may be used to endorse or promote products derived from 1.72 + this software without specific prior written permission. 1.73 + 1.74 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 1.75 + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 1.76 + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 1.77 + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER 1.78 + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.79 + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.80 + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 1.81 + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 1.82 + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 1.83 + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 1.84 + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.85 +*/ 1.86 + 1.87 +package jdk.internal.dynalink.linker; 1.88 + 1.89 +public class GuardedTypeConversion { 1.90 + private final GuardedInvocation conversionInvocation; 1.91 + private final boolean cacheable; 1.92 + 1.93 + public GuardedTypeConversion(final GuardedInvocation conversionInvocation, final boolean cacheable) { 1.94 + this.conversionInvocation = conversionInvocation; 1.95 + this.cacheable = cacheable; 1.96 + } 1.97 + 1.98 + public GuardedInvocation getConversionInvocation() { 1.99 + return conversionInvocation; 1.100 + } 1.101 + 1.102 + public boolean isCacheable() { 1.103 + return cacheable; 1.104 + } 1.105 +}
2.1 --- a/src/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java Thu Jan 30 19:45:20 2014 +0530 2.2 +++ b/src/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java Thu Jan 30 20:14:29 2014 +0100 2.3 @@ -96,19 +96,19 @@ 2.4 */ 2.5 public interface GuardingTypeConverterFactory { 2.6 /** 2.7 - * Returns a guarded invocation that receives an Object of the specified source type and returns an Object converted 2.8 - * to the specified target type. The type of the invocation is targetType(sourceType), while the type of the guard 2.9 - * is boolean(sourceType). Note that this will never be invoked for type conversions allowed by the JLS 5.3 "Method 2.10 - * Invocation Conversion", see {@link TypeUtilities#isMethodInvocationConvertible(Class, Class)} for details. An 2.11 - * implementation can assume it is never requested to produce a converter for these conversions. 2.12 + * Returns a guarded type conversion that receives an Object of the specified source type and returns an Object 2.13 + * converted to the specified target type. The type of the invocation is targetType(sourceType), while the type of 2.14 + * the guard is boolean(sourceType). Note that this will never be invoked for type conversions allowed by the JLS 2.15 + * 5.3 "Method Invocation Conversion", see {@link TypeUtilities#isMethodInvocationConvertible(Class, Class)} for 2.16 + * details. An implementation can assume it is never requested to produce a converter for these conversions. 2.17 * 2.18 * @param sourceType source type 2.19 * @param targetType the target type. 2.20 - * @return a guarded invocation that can take an object (if it passes guard) and returns another object that is its 2.21 - * representation coerced into the target type. In case the factory is certain it is unable to handle a conversion, 2.22 - * it can return null. In case the factory is certain that it can always handle the conversion, it can return an 2.23 - * unconditional invocation (one whose guard is null). 2.24 + * @return a guarded type conversion that contains a guarded invocation that can take an object (if it passes guard) 2.25 + * and return another object that is its representation coerced into the target type. In case the factory is certain 2.26 + * it is unable to handle a conversion, it can return null. In case the factory is certain that it can always handle 2.27 + * the conversion, it can return an unconditional invocation (one whose guard is null). 2.28 * @throws Exception if there was an error during creation of the converter 2.29 */ 2.30 - public GuardedInvocation convertToType(Class<?> sourceType, Class<?> targetType) throws Exception; 2.31 + public GuardedTypeConversion convertToType(Class<?> sourceType, Class<?> targetType) throws Exception; 2.32 }
3.1 --- a/src/jdk/internal/dynalink/support/LinkerServicesImpl.java Thu Jan 30 19:45:20 2014 +0530 3.2 +++ b/src/jdk/internal/dynalink/support/LinkerServicesImpl.java Thu Jan 30 20:14:29 2014 +0100 3.3 @@ -98,6 +98,9 @@ 3.4 */ 3.5 public class LinkerServicesImpl implements LinkerServices { 3.6 3.7 + private static final RuntimePermission GET_CURRENT_LINK_REQUEST = new RuntimePermission("dynalink.getCurrentLinkRequest"); 3.8 + private static final ThreadLocal<LinkRequest> threadLinkRequest = new ThreadLocal<>(); 3.9 + 3.10 private final TypeConverterFactory typeConverterFactory; 3.11 private final GuardingDynamicLinker topLevelLinker; 3.12 3.13 @@ -135,6 +138,26 @@ 3.14 3.15 @Override 3.16 public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest) throws Exception { 3.17 - return topLevelLinker.getGuardedInvocation(linkRequest, this); 3.18 + final LinkRequest prevLinkRequest = threadLinkRequest.get(); 3.19 + threadLinkRequest.set(linkRequest); 3.20 + try { 3.21 + return topLevelLinker.getGuardedInvocation(linkRequest, this); 3.22 + } finally { 3.23 + threadLinkRequest.set(prevLinkRequest); 3.24 + } 3.25 + } 3.26 + 3.27 + /** 3.28 + * Returns the currently processed link request, or null if the method is invoked outside of the linking process. 3.29 + * @return the currently processed link request, or null. 3.30 + * @throws SecurityException if the calling code doesn't have the {@code "dynalink.getCurrentLinkRequest"} runtime 3.31 + * permission. 3.32 + */ 3.33 + public static LinkRequest getCurrentLinkRequest() { 3.34 + SecurityManager sm = System.getSecurityManager(); 3.35 + if(sm != null) { 3.36 + sm.checkPermission(GET_CURRENT_LINK_REQUEST); 3.37 + } 3.38 + return threadLinkRequest.get(); 3.39 } 3.40 }
4.1 --- a/src/jdk/internal/dynalink/support/TypeConverterFactory.java Thu Jan 30 19:45:20 2014 +0530 4.2 +++ b/src/jdk/internal/dynalink/support/TypeConverterFactory.java Thu Jan 30 20:14:29 2014 +0100 4.3 @@ -94,6 +94,7 @@ 4.4 import jdk.internal.dynalink.linker.ConversionComparator; 4.5 import jdk.internal.dynalink.linker.ConversionComparator.Comparison; 4.6 import jdk.internal.dynalink.linker.GuardedInvocation; 4.7 +import jdk.internal.dynalink.linker.GuardedTypeConversion; 4.8 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; 4.9 import jdk.internal.dynalink.linker.LinkerServices; 4.10 4.11 @@ -134,8 +135,8 @@ 4.12 @Override 4.13 protected MethodHandle computeValue(Class<?> targetType) { 4.14 if(!canAutoConvert(sourceType, targetType)) { 4.15 - final MethodHandle converter = getTypeConverterNull(sourceType, targetType); 4.16 - if(converter != null) { 4.17 + final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); 4.18 + if(converter != IDENTITY_CONVERSION) { 4.19 return converter; 4.20 } 4.21 } 4.22 @@ -145,6 +146,24 @@ 4.23 } 4.24 }; 4.25 4.26 + private final ClassValue<ClassMap<Boolean>> canConvert = new ClassValue<ClassMap<Boolean>>() { 4.27 + @Override 4.28 + protected ClassMap<Boolean> computeValue(final Class<?> sourceType) { 4.29 + return new ClassMap<Boolean>(getClassLoader(sourceType)) { 4.30 + @Override 4.31 + protected Boolean computeValue(Class<?> targetType) { 4.32 + try { 4.33 + return getTypeConverterNull(sourceType, targetType) != null; 4.34 + } catch (RuntimeException e) { 4.35 + throw e; 4.36 + } catch (Exception e) { 4.37 + throw new RuntimeException(e); 4.38 + } 4.39 + } 4.40 + }; 4.41 + } 4.42 + }; 4.43 + 4.44 private static final ClassLoader getClassLoader(final Class<?> clazz) { 4.45 return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { 4.46 @Override 4.47 @@ -253,7 +272,7 @@ 4.48 * @return true if there can be a conversion, false if there can not. 4.49 */ 4.50 public boolean canConvert(final Class<?> from, final Class<?> to) { 4.51 - return canAutoConvert(from, to) || getTypeConverterNull(from, to) != null; 4.52 + return canAutoConvert(from, to) || canConvert.get(from).get(to).booleanValue(); 4.53 } 4.54 4.55 /** 4.56 @@ -294,9 +313,21 @@ 4.57 return TypeUtilities.isMethodInvocationConvertible(fromType, toType); 4.58 } 4.59 4.60 + /*private*/ MethodHandle getCacheableTypeConverterNull(Class<?> sourceType, Class<?> targetType) { 4.61 + final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); 4.62 + return converter == IDENTITY_CONVERSION ? null : converter; 4.63 + } 4.64 + 4.65 /*private*/ MethodHandle getTypeConverterNull(Class<?> sourceType, Class<?> targetType) { 4.66 - final MethodHandle converter = converterMap.get(sourceType).get(targetType); 4.67 - return converter == IDENTITY_CONVERSION ? null : converter; 4.68 + try { 4.69 + return getCacheableTypeConverterNull(sourceType, targetType); 4.70 + } catch(NotCacheableConverter e) { 4.71 + return e.converter; 4.72 + } 4.73 + } 4.74 + 4.75 + /*private*/ MethodHandle getCacheableTypeConverter(Class<?> sourceType, Class<?> targetType) { 4.76 + return converterMap.get(sourceType).get(targetType); 4.77 } 4.78 4.79 /** 4.80 @@ -309,22 +340,44 @@ 4.81 * @return a method handle performing the conversion. 4.82 */ 4.83 public MethodHandle getTypeConverter(Class<?> sourceType, Class<?> targetType) { 4.84 - return converterIdentityMap.get(sourceType).get(targetType); 4.85 + try { 4.86 + return converterIdentityMap.get(sourceType).get(targetType); 4.87 + } catch(NotCacheableConverter e) { 4.88 + return e.converter; 4.89 + } 4.90 } 4.91 4.92 /*private*/ MethodHandle createConverter(Class<?> sourceType, Class<?> targetType) throws Exception { 4.93 final MethodType type = MethodType.methodType(targetType, sourceType); 4.94 final MethodHandle identity = IDENTITY_CONVERSION.asType(type); 4.95 MethodHandle last = identity; 4.96 + boolean cacheable = true; 4.97 for(int i = factories.length; i-- > 0;) { 4.98 - final GuardedInvocation next = factories[i].convertToType(sourceType, targetType); 4.99 + final GuardedTypeConversion next = factories[i].convertToType(sourceType, targetType); 4.100 if(next != null) { 4.101 - next.assertType(type); 4.102 - last = next.compose(last); 4.103 + cacheable = cacheable && next.isCacheable(); 4.104 + final GuardedInvocation conversionInvocation = next.getConversionInvocation(); 4.105 + conversionInvocation.assertType(type); 4.106 + last = conversionInvocation.compose(last); 4.107 } 4.108 } 4.109 - return last == identity ? IDENTITY_CONVERSION : last; 4.110 + if(last == identity) { 4.111 + return IDENTITY_CONVERSION; 4.112 + } 4.113 + if(cacheable) { 4.114 + return last; 4.115 + } 4.116 + throw new NotCacheableConverter(last); 4.117 } 4.118 4.119 /*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class); 4.120 + 4.121 + private static class NotCacheableConverter extends RuntimeException { 4.122 + final MethodHandle converter; 4.123 + 4.124 + NotCacheableConverter(final MethodHandle converter) { 4.125 + super("", null, false, false); 4.126 + this.converter = converter; 4.127 + } 4.128 + } 4.129 }
5.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Jan 30 19:45:20 2014 +0530 5.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Jan 30 20:14:29 2014 +0100 5.3 @@ -32,6 +32,7 @@ 5.4 import java.io.InputStream; 5.5 import java.io.InputStreamReader; 5.6 import java.io.Reader; 5.7 +import java.lang.invoke.MethodHandles; 5.8 import java.lang.reflect.Method; 5.9 import java.lang.reflect.Modifier; 5.10 import java.net.URL; 5.11 @@ -104,7 +105,7 @@ 5.12 private volatile Property contextProperty; 5.13 5.14 // default options passed to Nashorn Options object 5.15 - private static final String[] DEFAULT_OPTIONS = new String[] { "-scripting", "-doe" }; 5.16 + private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" }; 5.17 5.18 // Nashorn script engine error message management 5.19 private static final String MESSAGES_RESOURCE = "jdk.nashorn.api.scripting.resources.Messages"; 5.20 @@ -355,7 +356,8 @@ 5.21 if (! isInterfaceImplemented(clazz, realSelf)) { 5.22 return null; 5.23 } 5.24 - return clazz.cast(JavaAdapterFactory.getConstructor(realSelf.getClass(), clazz).invoke(realSelf)); 5.25 + return clazz.cast(JavaAdapterFactory.getConstructor(realSelf.getClass(), clazz, 5.26 + MethodHandles.publicLookup()).invoke(realSelf)); 5.27 } finally { 5.28 if (globalChanged) { 5.29 Context.setGlobal(oldGlobal);
6.1 --- a/src/jdk/nashorn/internal/objects/NativeJava.java Thu Jan 30 19:45:20 2014 +0530 6.2 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java Thu Jan 30 20:14:29 2014 +0100 6.3 @@ -28,6 +28,7 @@ 6.4 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 6.5 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 6.6 6.7 +import java.lang.invoke.MethodHandles; 6.8 import java.lang.reflect.Array; 6.9 import java.util.Collection; 6.10 import java.util.Deque; 6.11 @@ -463,12 +464,14 @@ 6.12 * </pre> 6.13 * We can see several important concepts in the above example: 6.14 * <ul> 6.15 - * <li>Every specified list of Java types will have exactly one extender subclass in Nashorn - repeated invocations 6.16 - * of {@code extend} for the same list of types will yield the same extender type. It's a generic adapter that 6.17 - * delegates to whatever JavaScript functions its implementation object has on a per-instance basis.</li> 6.18 + * <li>Every specified list of Java types will have one extender subclass in Nashorn per caller protection domain - 6.19 + * repeated invocations of {@code extend} for the same list of types for scripts same protection domain will yield 6.20 + * the same extender type. It's a generic adapter that delegates to whatever JavaScript functions its implementation 6.21 + * object has on a per-instance basis.</li> 6.22 * <li>If the Java method is overloaded (as in the above example {@code List.add()}), then your JavaScript adapter 6.23 * must be prepared to deal with all overloads.</li> 6.24 - * <li>You can't invoke {@code super.*()} from adapters for now.</li> 6.25 + * <li>To invoke super methods from adapters, call them on the adapter instance prefixing them with {@code super$}, 6.26 + * or use the special {@link #_super(Object, Object) super-adapter}.</li> 6.27 * <li>It is also possible to specify an ordinary JavaScript object as the last argument to {@code extend}. In that 6.28 * case, it is treated as a class-level override. {@code extend} will return an extender class where all instances 6.29 * will have the methods implemented by functions on that object, just as if that object were passed as the last 6.30 @@ -486,15 +489,18 @@ 6.31 * t.join() 6.32 * </pre> 6.33 * As you can see, you don't have to pass any object when you create a new instance of {@code R1} as its 6.34 - * {@code run()} function was defined already when extending the class. Of course, you can still provide 6.35 - * instance-level overrides on these objects. The order of precedence is instance-level method, class-level method, 6.36 - * superclass method, or {@code UnsupportedOperationException} if the superclass method is abstract. If we continue 6.37 - * our previous example: 6.38 + * {@code run()} function was defined already when extending the class. If you also want to add instance-level 6.39 + * overrides on these objects, you will have to repeatedly use {@code extend()} to subclass the class-level adapter. 6.40 + * For such adapters, the order of precedence is instance-level method, class-level method, superclass method, or 6.41 + * {@code UnsupportedOperationException} if the superclass method is abstract. If we continue our previous example: 6.42 * <pre> 6.43 - * var r2 = new R1(function() { print("r2.run() invoked!") }) 6.44 + * var R2 = Java.extend(R1); 6.45 + * var r2 = new R2(function() { print("r2.run() invoked!") }) 6.46 * r2.run() 6.47 * </pre> 6.48 * We'll see it'll print {@code "r2.run() invoked!"}, thus overriding on instance-level the class-level behavior. 6.49 + * Note that you must use {@code Java.extend} to explicitly create an instance-override adapter class from a 6.50 + * class-override adapter class, as the class-override adapter class is no longer abstract. 6.51 * </li> 6.52 * </ul> 6.53 * @param self not used 6.54 @@ -541,7 +547,18 @@ 6.55 } catch(final ClassCastException e) { 6.56 throw typeError("extend.expects.java.types"); 6.57 } 6.58 - return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides); 6.59 + // Note that while the public API documentation claims self is not used, we actually use it. 6.60 + // ScriptFunction.findCallMethod will bind the lookup object into it, and we can then use that lookup when 6.61 + // requesting the adapter class. Note that if Java.extend is invoked with no lookup object, it'll pass the 6.62 + // public lookup which'll result in generation of a no-permissions adapter. A typical situation this can happen 6.63 + // is when the extend function is bound. 6.64 + final MethodHandles.Lookup lookup; 6.65 + if(self instanceof MethodHandles.Lookup) { 6.66 + lookup = (MethodHandles.Lookup)self; 6.67 + } else { 6.68 + lookup = MethodHandles.publicLookup(); 6.69 + } 6.70 + return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides, lookup); 6.71 } 6.72 6.73 /**
7.1 --- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Thu Jan 30 19:45:20 2014 +0530 7.2 +++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Thu Jan 30 20:14:29 2014 +0100 7.3 @@ -33,6 +33,7 @@ 7.4 import jdk.nashorn.internal.objects.annotations.Constructor; 7.5 import jdk.nashorn.internal.objects.annotations.Function; 7.6 import jdk.nashorn.internal.objects.annotations.ScriptClass; 7.7 +import jdk.nashorn.internal.runtime.Context; 7.8 import jdk.nashorn.internal.runtime.NativeJavaPackage; 7.9 import jdk.nashorn.internal.runtime.PropertyMap; 7.10 import jdk.nashorn.internal.runtime.ScriptObject; 7.11 @@ -156,8 +157,9 @@ 7.12 } else if (obj instanceof NativeJavaPackage) { 7.13 final String pkgName = ((NativeJavaPackage)obj).getName(); 7.14 final String fullName = pkgName.isEmpty() ? name : (pkgName + "." + name); 7.15 + final Context context = Global.instance().getContext(); 7.16 try { 7.17 - return StaticClass.forClass(Class.forName(fullName)); 7.18 + return StaticClass.forClass(context.findClass(fullName)); 7.19 } catch (final ClassNotFoundException e) { 7.20 // IGNORE 7.21 }
8.1 --- a/src/jdk/nashorn/internal/runtime/Context.java Thu Jan 30 19:45:20 2014 +0530 8.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java Thu Jan 30 20:14:29 2014 +0100 8.3 @@ -647,6 +647,19 @@ 8.4 } 8.5 8.6 /** 8.7 + * Checks that the given package name can be accessed from no permissions context. 8.8 + * 8.9 + * @param pkgName package name 8.10 + * @throw SecurityException if not accessible 8.11 + */ 8.12 + public static void checkPackageAccess(final String pkgName) { 8.13 + final SecurityManager sm = System.getSecurityManager(); 8.14 + if (sm != null) { 8.15 + checkPackageAccess(sm, pkgName.endsWith(".")? pkgName : pkgName + "."); 8.16 + } 8.17 + } 8.18 + 8.19 + /** 8.20 * Checks that the given package can be accessed from no permissions context. 8.21 * 8.22 * @param sm current security manager instance
9.1 --- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Thu Jan 30 19:45:20 2014 +0530 9.2 +++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Thu Jan 30 20:14:29 2014 +0100 9.3 @@ -85,6 +85,8 @@ 9.4 */ 9.5 public NativeJavaPackage(final String name, final ScriptObject proto) { 9.6 super(proto, null); 9.7 + // defense-in-path, check here for sensitive packages 9.8 + Context.checkPackageAccess(name); 9.9 this.name = name; 9.10 } 9.11
10.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Jan 30 19:45:20 2014 +0530 10.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Jan 30 20:14:29 2014 +0100 10.3 @@ -26,14 +26,13 @@ 10.4 package jdk.nashorn.internal.runtime; 10.5 10.6 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; 10.7 +import static jdk.nashorn.internal.lookup.Lookup.MH; 10.8 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 10.9 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 10.10 -import static jdk.nashorn.internal.lookup.Lookup.MH; 10.11 10.12 import java.lang.invoke.MethodHandle; 10.13 import java.lang.invoke.MethodHandles; 10.14 import java.lang.invoke.MethodType; 10.15 - 10.16 import jdk.internal.dynalink.CallSiteDescriptor; 10.17 import jdk.internal.dynalink.linker.GuardedInvocation; 10.18 import jdk.internal.dynalink.linker.LinkRequest; 10.19 @@ -524,7 +523,11 @@ 10.20 } 10.21 } else { 10.22 final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1), request.getArguments()); 10.23 - if (scopeCall) { 10.24 + if (data.isBuiltin() && "extend".equals(data.getName())) { 10.25 + // NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the 10.26 + // current lookup as its "this" so it can do security-sensitive creation of adapter classes. 10.27 + boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class); 10.28 + } else if (scopeCall) { 10.29 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined 10.30 // (this, args...) => (args...) 10.31 boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
11.1 --- a/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java Thu Jan 30 19:45:20 2014 +0530 11.2 +++ b/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java Thu Jan 30 20:14:29 2014 +0100 11.3 @@ -47,7 +47,8 @@ 11.4 ERROR_NON_PUBLIC_CLASS, 11.5 ERROR_NO_ACCESSIBLE_CONSTRUCTOR, 11.6 ERROR_MULTIPLE_SUPERCLASSES, 11.7 - ERROR_NO_COMMON_LOADER 11.8 + ERROR_NO_COMMON_LOADER, 11.9 + ERROR_FINAL_FINALIZER 11.10 } 11.11 11.12 static final AdaptationResult SUCCESSFUL_RESULT = new AdaptationResult(Outcome.SUCCESS, "");
12.1 --- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Jan 30 19:45:20 2014 +0530 12.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Jan 30 20:14:29 2014 +0100 12.3 @@ -32,6 +32,7 @@ 12.4 import java.util.Map; 12.5 import jdk.internal.dynalink.CallSiteDescriptor; 12.6 import jdk.internal.dynalink.linker.GuardedInvocation; 12.7 +import jdk.internal.dynalink.linker.GuardedTypeConversion; 12.8 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; 12.9 import jdk.internal.dynalink.linker.LinkRequest; 12.10 import jdk.internal.dynalink.linker.LinkerServices; 12.11 @@ -79,7 +80,7 @@ 12.12 } 12.13 12.14 @Override 12.15 - public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { 12.16 + public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { 12.17 final boolean sourceIsAlwaysJSObject = JSObject.class.isAssignableFrom(sourceType); 12.18 if(!sourceIsAlwaysJSObject && !sourceType.isAssignableFrom(JSObject.class)) { 12.19 return null; 12.20 @@ -90,7 +91,7 @@ 12.21 return null; 12.22 } 12.23 12.24 - return new GuardedInvocation(converter, sourceIsAlwaysJSObject ? null : IS_JSOBJECT_GUARD).asType(MethodType.methodType(targetType, sourceType)); 12.25 + return new GuardedTypeConversion(new GuardedInvocation(converter, sourceIsAlwaysJSObject ? null : IS_JSOBJECT_GUARD).asType(MethodType.methodType(targetType, sourceType)), true); 12.26 } 12.27 12.28
13.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Thu Jan 30 19:45:20 2014 +0530 13.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Thu Jan 30 20:14:29 2014 +0100 13.3 @@ -59,6 +59,7 @@ 13.4 import java.util.List; 13.5 import java.util.Set; 13.6 import jdk.internal.org.objectweb.asm.ClassWriter; 13.7 +import jdk.internal.org.objectweb.asm.Handle; 13.8 import jdk.internal.org.objectweb.asm.Label; 13.9 import jdk.internal.org.objectweb.asm.Opcodes; 13.10 import jdk.internal.org.objectweb.asm.Type; 13.11 @@ -66,21 +67,23 @@ 13.12 import jdk.nashorn.internal.runtime.Context; 13.13 import jdk.nashorn.internal.runtime.ScriptFunction; 13.14 import jdk.nashorn.internal.runtime.ScriptObject; 13.15 +import jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome; 13.16 import sun.reflect.CallerSensitive; 13.17 13.18 /** 13.19 * Generates bytecode for a Java adapter class. Used by the {@link JavaAdapterFactory}. 13.20 * </p><p> 13.21 - * For every protected or public constructor in the extended class, the adapter class will have between one to three 13.22 + * For every protected or public constructor in the extended class, the adapter class will have either one or two 13.23 * public constructors (visibility of protected constructors in the extended class is promoted to public). 13.24 - * <ul> 13.25 - * <li>In every case, a constructor taking a trailing ScriptObject argument preceded by original constructor arguments 13.26 - * is always created on the adapter class. When such a constructor is invoked, the passed ScriptObject's member 13.27 - * functions are used to implement and/or override methods on the original class, dispatched by name. A single 13.28 - * JavaScript function will act as the implementation for all overloaded methods of the same name. When methods on an 13.29 - * adapter instance are invoked, the functions are invoked having the ScriptObject passed in the instance constructor as 13.30 - * their "this". Subsequent changes to the ScriptObject (reassignment or removal of its functions) are not reflected in 13.31 - * the adapter instance; the method implementations are bound to functions at constructor invocation time. 13.32 + * <li> 13.33 + * <li>For adapter classes with instance-level overrides, a constructor taking a trailing ScriptObject argument preceded 13.34 + * by original constructor arguments is always created on the adapter class. When such a constructor is invoked, the 13.35 + * passed ScriptObject's member functions are used to implement and/or override methods on the original class, 13.36 + * dispatched by name. A single JavaScript function will act as the implementation for all overloaded methods of the 13.37 + * same name. When methods on an adapter instance are invoked, the functions are invoked having the ScriptObject passed 13.38 + * in the instance constructor as their "this". Subsequent changes to the ScriptObject (reassignment or removal of its 13.39 + * functions) are not reflected in the adapter instance; the method implementations are bound to functions at 13.40 + * constructor invocation time. 13.41 * {@code java.lang.Object} methods {@code equals}, {@code hashCode}, and {@code toString} can also be overridden. The 13.42 * only restriction is that since every JavaScript object already has a {@code toString} function through the 13.43 * {@code Object.prototype}, the {@code toString} in the adapter is only overridden if the passed ScriptObject has a 13.44 @@ -89,16 +92,17 @@ 13.45 * </li> 13.46 * <li> 13.47 * If the original types collectively have only one abstract method, or have several of them, but all share the 13.48 - * same name, an additional constructor is provided for every original constructor; this one takes a ScriptFunction as 13.49 - * its last argument preceded by original constructor arguments. This constructor will use the passed function as the 13.50 - * implementation for all abstract methods. For consistency, any concrete methods sharing the single abstract method 13.51 - * name will also be overridden by the function. When methods on the adapter instance are invoked, the ScriptFunction is 13.52 - * invoked with global or UNDEFINED as its "this" depending whether the function is non-strict or not. 13.53 + * same name, an additional constructor for instance-level override adapter is provided for every original constructor; 13.54 + * this one takes a ScriptFunction as its last argument preceded by original constructor arguments. This constructor 13.55 + * will use the passed function as the implementation for all abstract methods. For consistency, any concrete methods 13.56 + * sharing the single abstract method name will also be overridden by the function. When methods on the adapter instance 13.57 + * are invoked, the ScriptFunction is invoked with UNDEFINED or Global as its "this" depending whether the function is 13.58 + * strict or not. 13.59 * </li> 13.60 * <li> 13.61 * If the adapter being generated can have class-level overrides, constructors taking same arguments as the superclass 13.62 - * constructors are also created. These constructors simply delegate to the superclass constructor. They are used to 13.63 - * create instances of the adapter class with no instance-level overrides. 13.64 + * constructors are created. These constructors simply delegate to the superclass constructor. They are simply used to 13.65 + * create instances of the adapter class, with no instance-level overrides, as they don't have them. 13.66 * </li> 13.67 * </ul> 13.68 * </p><p> 13.69 @@ -111,16 +115,20 @@ 13.70 * source-level script expression <code>new X(a, b) { ... }</code> (which is a proprietary syntax extension Nashorn uses 13.71 * to resemble Java anonymous classes) is actually equivalent to <code>new X(a, b, { ... })</code>. 13.72 * </p><p> 13.73 - * It is possible to create two different classes: those that can have both class-level and instance-level overrides, 13.74 - * and those that can only have instance-level overrides. When 13.75 - * {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject)} is invoked with non-null {@code classOverrides} 13.76 - * parameter, an adapter class is created that can have class-level overrides, and the passed script object will be used 13.77 - * as the implementations for its methods, just as in the above case of the constructor taking a script object. Note 13.78 - * that in the case of class-level overrides, a new adapter class is created on every invocation, and the implementation 13.79 - * object is bound to the class, not to any instance. All created instances will share these functions. Of course, when 13.80 - * instances of such a class are being created, they can still take another object (or possibly a function) in their 13.81 - * constructor's trailing position and thus provide further instance-specific overrides. The order of invocation is 13.82 - * always instance-specified method, then a class-specified method, and finally the superclass method. 13.83 + * It is possible to create two different adapter classes: those that can have class-level overrides, and those that can 13.84 + * have instance-level overrides. When {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject)} is invoked 13.85 + * with non-null {@code classOverrides} parameter, an adapter class is created that can have class-level overrides, and 13.86 + * the passed script object will be used as the implementations for its methods, just as in the above case of the 13.87 + * constructor taking a script object. Note that in the case of class-level overrides, a new adapter class is created on 13.88 + * every invocation, and the implementation object is bound to the class, not to any instance. All created instances 13.89 + * will share these functions. If it is required to have both class-level overrides and instance-level overrides, the 13.90 + * class-level override adapter class should be subclassed with an instance-override adapter. Since adapters delegate to 13.91 + * super class when an overriding method handle is not specified, this will behave as expected. It is not possible to 13.92 + * have both class-level and instance-level overrides in the same class for security reasons: adapter classes are 13.93 + * defined with a protection domain of their creator code, and an adapter class that has both class and instance level 13.94 + * overrides would need to have two potentially different protection domains: one for class-based behavior and one for 13.95 + * instance-based behavior; since Java classes can only belong to a single protection domain, this could not be 13.96 + * implemented securely. 13.97 */ 13.98 final class JavaAdapterBytecodeGenerator { 13.99 static final Type CONTEXT_TYPE = Type.getType(Context.class); 13.100 @@ -171,7 +179,6 @@ 13.101 private static final int MAX_GENERATED_TYPE_NAME_LENGTH = 255; 13.102 13.103 private static final String CLASS_INIT = "<clinit>"; 13.104 - private static final String STATIC_GLOBAL_FIELD_NAME = "staticGlobal"; 13.105 13.106 // Method name prefix for invoking super-methods 13.107 static final String SUPER_PREFIX = "super$"; 13.108 @@ -199,6 +206,7 @@ 13.109 private final Set<MethodInfo> finalMethods = new HashSet<>(EXCLUDED); 13.110 private final Set<MethodInfo> methodInfos = new HashSet<>(); 13.111 private boolean autoConvertibleFromFunction = false; 13.112 + private boolean hasExplicitFinalizer = false; 13.113 13.114 private final ClassWriter cw; 13.115 13.116 @@ -207,8 +215,8 @@ 13.117 * @param superClass the superclass the adapter will extend. 13.118 * @param interfaces the interfaces the adapter will implement. 13.119 * @param commonLoader the class loader that can see all of superClass, interfaces, and Nashorn classes. 13.120 - * @param classOverride true to generate the bytecode for the adapter that has both class-level and instance-level 13.121 - * overrides, false to generate the bytecode for the adapter that only has instance-level overrides. 13.122 + * @param classOverride true to generate the bytecode for the adapter that has class-level overrides, false to 13.123 + * generate the bytecode for the adapter that has instance-level overrides. 13.124 * @throws AdaptationException if the adapter can not be generated for some reason. 13.125 */ 13.126 JavaAdapterBytecodeGenerator(final Class<?> superClass, final List<Class<?>> interfaces, 13.127 @@ -230,8 +238,7 @@ 13.128 superClassName = Type.getInternalName(superClass); 13.129 generatedClassName = getGeneratedClassName(superClass, interfaces); 13.130 13.131 - cw.visit(Opcodes.V1_7, ACC_PUBLIC | ACC_SUPER | ACC_FINAL, generatedClassName, null, superClassName, getInternalTypeNames(interfaces)); 13.132 - 13.133 + cw.visit(Opcodes.V1_7, ACC_PUBLIC | ACC_SUPER, generatedClassName, null, superClassName, getInternalTypeNames(interfaces)); 13.134 generateGlobalFields(); 13.135 13.136 gatherMethods(superClass); 13.137 @@ -244,17 +251,16 @@ 13.138 generateConstructors(); 13.139 generateMethods(); 13.140 generateSuperMethods(); 13.141 + if (hasExplicitFinalizer) { 13.142 + generateFinalizerMethods(); 13.143 + } 13.144 // } 13.145 cw.visitEnd(); 13.146 } 13.147 13.148 private void generateGlobalFields() { 13.149 - cw.visitField(ACC_PRIVATE | ACC_FINAL, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR, null, null).visitEnd(); 13.150 + cw.visitField(ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0), GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR, null, null).visitEnd(); 13.151 usedFieldNames.add(GLOBAL_FIELD_NAME); 13.152 - if(classOverride) { 13.153 - cw.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR, null, null).visitEnd(); 13.154 - usedFieldNames.add(STATIC_GLOBAL_FIELD_NAME); 13.155 - } 13.156 } 13.157 13.158 JavaAdapterClassLoader createAdapterClassLoader() { 13.159 @@ -305,11 +311,9 @@ 13.160 } 13.161 13.162 private void generateHandleFields() { 13.163 + final int flags = ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0); 13.164 for (final MethodInfo mi: methodInfos) { 13.165 - cw.visitField(ACC_PRIVATE | ACC_FINAL, mi.methodHandleInstanceFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR, null, null).visitEnd(); 13.166 - if(classOverride) { 13.167 - cw.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR, null, null).visitEnd(); 13.168 - } 13.169 + cw.visitField(flags, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR, null, null).visitEnd(); 13.170 } 13.171 } 13.172 13.173 @@ -337,7 +341,7 @@ 13.174 } else { 13.175 mv.visitInsn(ACONST_NULL); 13.176 } 13.177 - mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.178 + mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.179 } 13.180 initGlobal = new Label(); 13.181 mv.goTo(initGlobal); 13.182 @@ -351,15 +355,15 @@ 13.183 mv.aconst(mi.getName()); 13.184 mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString())); 13.185 mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR); 13.186 - mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.187 + mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.188 } 13.189 13.190 if(initGlobal != null) { 13.191 mv.visitLabel(initGlobal); 13.192 } 13.193 - // Assign "staticGlobal = Context.getGlobal()" 13.194 + // Assign "global = Context.getGlobal()" 13.195 invokeGetGlobalWithNullCheck(mv); 13.196 - mv.putstatic(generatedClassName, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR); 13.197 + mv.putstatic(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR); 13.198 13.199 endInitMethod(mv); 13.200 } 13.201 @@ -390,21 +394,21 @@ 13.202 // Generate a constructor that just delegates to ctor. This is used with class-level overrides, when we want 13.203 // to create instances without further per-instance overrides. 13.204 generateDelegatingConstructor(ctor); 13.205 - } 13.206 + } else { 13.207 + // Generate a constructor that delegates to ctor, but takes an additional ScriptObject parameter at the 13.208 + // beginning of its parameter list. 13.209 + generateOverridingConstructor(ctor, false); 13.210 13.211 - // Generate a constructor that delegates to ctor, but takes an additional ScriptObject parameter at the 13.212 - // beginning of its parameter list. 13.213 - generateOverridingConstructor(ctor, false); 13.214 - 13.215 - if (samName != null) { 13.216 - if (!autoConvertibleFromFunction && ctor.getParameterTypes().length == 0) { 13.217 - // If the original type only has a single abstract method name, as well as a default ctor, then it can 13.218 - // be automatically converted from JS function. 13.219 - autoConvertibleFromFunction = true; 13.220 + if (samName != null) { 13.221 + if (!autoConvertibleFromFunction && ctor.getParameterTypes().length == 0) { 13.222 + // If the original type only has a single abstract method name, as well as a default ctor, then it can 13.223 + // be automatically converted from JS function. 13.224 + autoConvertibleFromFunction = true; 13.225 + } 13.226 + // If all our abstract methods have a single name, generate an additional constructor, one that takes a 13.227 + // ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods. 13.228 + generateOverridingConstructor(ctor, true); 13.229 } 13.230 - // If all our abstract methods have a single name, generate an additional constructor, one that takes a 13.231 - // ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods. 13.232 - generateOverridingConstructor(ctor, true); 13.233 } 13.234 } 13.235 13.236 @@ -430,7 +434,7 @@ 13.237 } 13.238 13.239 /** 13.240 - * Generates a constructor for the adapter class. This constructor will take the same arguments as the supertype 13.241 + * Generates a constructor for the instance adapter class. This constructor will take the same arguments as the supertype 13.242 * constructor passed as the argument here, and delegate to it. However, it will take an additional argument of 13.243 * either ScriptObject or ScriptFunction type (based on the value of the "fromFunction" parameter), and initialize 13.244 * all the method handle fields of the adapter instance with functions from the script object (or the script 13.245 @@ -498,7 +502,7 @@ 13.246 mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString())); 13.247 mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor); 13.248 } 13.249 - mv.putfield(generatedClassName, mi.methodHandleInstanceFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.250 + mv.putfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.251 } 13.252 13.253 // Assign "this.global = Context.getGlobal()" 13.254 @@ -536,8 +540,7 @@ 13.255 private static class MethodInfo { 13.256 private final Method method; 13.257 private final MethodType type; 13.258 - private String methodHandleInstanceFieldName; 13.259 - private String methodHandleClassFieldName; 13.260 + private String methodHandleFieldName; 13.261 13.262 private MethodInfo(final Class<?> clazz, final String name, final Class<?>... argTypes) throws NoSuchMethodException { 13.263 this(clazz.getDeclaredMethod(name, argTypes)); 13.264 @@ -567,25 +570,20 @@ 13.265 return getName().hashCode() ^ type.hashCode(); 13.266 } 13.267 13.268 - void setIsCanonical(final Set<String> usedFieldNames, boolean classOverride) { 13.269 - methodHandleInstanceFieldName = nextName(usedFieldNames); 13.270 - if(classOverride) { 13.271 - methodHandleClassFieldName = nextName(usedFieldNames); 13.272 - } 13.273 + void setIsCanonical(final JavaAdapterBytecodeGenerator self) { 13.274 + methodHandleFieldName = self.nextName(getName()); 13.275 } 13.276 + } 13.277 13.278 - String nextName(final Set<String> usedFieldNames) { 13.279 - int i = 0; 13.280 - final String name = getName(); 13.281 - String nextName = name; 13.282 - while (!usedFieldNames.add(nextName)) { 13.283 - final String ordinal = String.valueOf(i++); 13.284 - final int maxNameLen = 255 - ordinal.length(); 13.285 - nextName = (name.length() <= maxNameLen ? name : name.substring(0, maxNameLen)).concat(ordinal); 13.286 - } 13.287 - return nextName; 13.288 + private String nextName(final String name) { 13.289 + int i = 0; 13.290 + String nextName = name; 13.291 + while (!usedFieldNames.add(nextName)) { 13.292 + final String ordinal = String.valueOf(i++); 13.293 + final int maxNameLen = 255 - ordinal.length(); 13.294 + nextName = (name.length() <= maxNameLen ? name : name.substring(0, maxNameLen)).concat(ordinal); 13.295 } 13.296 - 13.297 + return nextName; 13.298 } 13.299 13.300 private void generateMethods() { 13.301 @@ -624,23 +622,19 @@ 13.302 methodDesc, null, exceptionNames)); 13.303 mv.visitCode(); 13.304 13.305 - final Label instanceHandleDefined = new Label(); 13.306 - final Label classHandleDefined = new Label(); 13.307 + final Label handleDefined = new Label(); 13.308 13.309 final Type asmReturnType = Type.getType(type.returnType()); 13.310 13.311 - // See if we have instance handle defined 13.312 - mv.visitVarInsn(ALOAD, 0); 13.313 - mv.getfield(generatedClassName, mi.methodHandleInstanceFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.314 - // stack: [instanceHandle] 13.315 - jumpIfNonNullKeepOperand(mv, instanceHandleDefined); 13.316 - 13.317 + // See if we have overriding method handle defined 13.318 if(classOverride) { 13.319 - // See if we have the static handle 13.320 - mv.getstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.321 - // stack: [classHandle] 13.322 - jumpIfNonNullKeepOperand(mv, classHandleDefined); 13.323 + mv.getstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.324 + } else { 13.325 + mv.visitVarInsn(ALOAD, 0); 13.326 + mv.getfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); 13.327 } 13.328 + // stack: [handle] 13.329 + jumpIfNonNullKeepOperand(mv, handleDefined); 13.330 13.331 // No handle is available, fall back to default behavior 13.332 if(Modifier.isAbstract(method.getModifiers())) { 13.333 @@ -654,25 +648,17 @@ 13.334 emitSuperCall(mv, name, methodDesc); 13.335 } 13.336 13.337 + mv.visitLabel(handleDefined); 13.338 + // Load the creatingGlobal object 13.339 + if(classOverride) { 13.340 + // If class handle is defined, load the static defining global 13.341 + mv.getstatic(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR); 13.342 + } else { 13.343 + mv.visitVarInsn(ALOAD, 0); 13.344 + mv.getfield(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR); 13.345 + } 13.346 + // stack: [creatingGlobal, handle] 13.347 final Label setupGlobal = new Label(); 13.348 - 13.349 - if(classOverride) { 13.350 - mv.visitLabel(classHandleDefined); 13.351 - // If class handle is defined, load the static defining global 13.352 - mv.getstatic(generatedClassName, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR); 13.353 - // stack: [creatingGlobal := classGlobal, classHandle] 13.354 - mv.goTo(setupGlobal); 13.355 - } 13.356 - 13.357 - mv.visitLabel(instanceHandleDefined); 13.358 - // If instance handle is defined, load the instance defining global 13.359 - mv.visitVarInsn(ALOAD, 0); 13.360 - mv.getfield(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR); 13.361 - // stack: [creatingGlobal := instanceGlobal, instanceHandle] 13.362 - 13.363 - // fallthrough to setupGlobal 13.364 - 13.365 - // stack: [creatingGlobal, someHandle] 13.366 mv.visitLabel(setupGlobal); 13.367 13.368 // Determine the first index for a local variable 13.369 @@ -685,38 +671,39 @@ 13.370 final int globalsDifferVar = nextLocalVar++; 13.371 13.372 mv.dup(); 13.373 - // stack: [creatingGlobal, creatingGlobal, someHandle] 13.374 + // stack: [creatingGlobal, creatingGlobal, handle] 13.375 13.376 // Emit code for switching to the creating global 13.377 // ScriptObject currentGlobal = Context.getGlobal(); 13.378 invokeGetGlobal(mv); 13.379 mv.dup(); 13.380 + 13.381 mv.visitVarInsn(ASTORE, currentGlobalVar); 13.382 - // stack: [currentGlobal, creatingGlobal, creatingGlobal, someHandle] 13.383 + // stack: [currentGlobal, creatingGlobal, creatingGlobal, handle] 13.384 // if(definingGlobal == currentGlobal) { 13.385 final Label globalsDiffer = new Label(); 13.386 mv.ifacmpne(globalsDiffer); 13.387 - // stack: [someGlobal, someHandle] 13.388 + // stack: [creatingGlobal, handle] 13.389 // globalsDiffer = false 13.390 mv.pop(); 13.391 - // stack: [someHandle] 13.392 + // stack: [handle] 13.393 mv.iconst(0); // false 13.394 - // stack: [false, someHandle] 13.395 + // stack: [false, handle] 13.396 final Label invokeHandle = new Label(); 13.397 mv.goTo(invokeHandle); 13.398 mv.visitLabel(globalsDiffer); 13.399 // } else { 13.400 // Context.setGlobal(definingGlobal); 13.401 - // stack: [someGlobal, someHandle] 13.402 + // stack: [creatingGlobal, handle] 13.403 invokeSetGlobal(mv); 13.404 - // stack: [someHandle] 13.405 + // stack: [handle] 13.406 // globalsDiffer = true 13.407 mv.iconst(1); 13.408 - // stack: [true, someHandle] 13.409 + // stack: [true, handle] 13.410 13.411 mv.visitLabel(invokeHandle); 13.412 mv.visitVarInsn(ISTORE, globalsDifferVar); 13.413 - // stack: [someHandle] 13.414 + // stack: [handle] 13.415 13.416 // Load all parameters back on stack for dynamic invocation. 13.417 int varOffset = 1; 13.418 @@ -847,6 +834,42 @@ 13.419 mv.areturn(methodType.getReturnType()); 13.420 } 13.421 13.422 + private void generateFinalizerMethods() { 13.423 + final String finalizerDelegateName = nextName("access$"); 13.424 + generateFinalizerDelegate(finalizerDelegateName); 13.425 + generateFinalizerOverride(finalizerDelegateName); 13.426 + } 13.427 + 13.428 + private void generateFinalizerDelegate(final String finalizerDelegateName) { 13.429 + // Generate a delegate that will be invoked from the no-permission trampoline. Note it can be private, as we'll 13.430 + // refer to it with a MethodHandle constant pool entry in the overridden finalize() method (see 13.431 + // generateFinalizerOverride()). 13.432 + final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PRIVATE | ACC_STATIC, 13.433 + finalizerDelegateName, Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE), null, null)); 13.434 + 13.435 + // Simply invoke super.finalize() 13.436 + mv.visitVarInsn(ALOAD, 0); 13.437 + mv.checkcast(Type.getType(generatedClassName)); 13.438 + mv.invokespecial(superClassName, "finalize", Type.getMethodDescriptor(Type.VOID_TYPE), false); 13.439 + 13.440 + mv.visitInsn(RETURN); 13.441 + endMethod(mv); 13.442 + } 13.443 + 13.444 + private void generateFinalizerOverride(final String finalizerDelegateName) { 13.445 + final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, "finalize", 13.446 + VOID_NOARG_METHOD_DESCRIPTOR, null, null)); 13.447 + // Overridden finalizer will take a MethodHandle to the finalizer delegating method, ... 13.448 + mv.aconst(new Handle(Opcodes.H_INVOKESTATIC, generatedClassName, finalizerDelegateName, 13.449 + Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE))); 13.450 + mv.visitVarInsn(ALOAD, 0); 13.451 + // ...and invoke it through JavaAdapterServices.invokeNoPermissions 13.452 + mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "invokeNoPermissions", 13.453 + Type.getMethodDescriptor(METHOD_HANDLE_TYPE, OBJECT_TYPE), false); 13.454 + mv.visitInsn(RETURN); 13.455 + endMethod(mv); 13.456 + } 13.457 + 13.458 private static String[] getExceptionNames(final Class<?>[] exceptions) { 13.459 final String[] exceptionNames = new String[exceptions.length]; 13.460 for (int i = 0; i < exceptions.length; ++i) { 13.461 @@ -867,16 +890,32 @@ 13.462 * class. 13.463 * @param type the type defining the methods. 13.464 */ 13.465 - private void gatherMethods(final Class<?> type) { 13.466 + private void gatherMethods(final Class<?> type) throws AdaptationException { 13.467 if (Modifier.isPublic(type.getModifiers())) { 13.468 final Method[] typeMethods = type.isInterface() ? type.getMethods() : type.getDeclaredMethods(); 13.469 13.470 for (final Method typeMethod: typeMethods) { 13.471 + final String name = typeMethod.getName(); 13.472 + if(name.startsWith(SUPER_PREFIX)) { 13.473 + continue; 13.474 + } 13.475 final int m = typeMethod.getModifiers(); 13.476 if (Modifier.isStatic(m)) { 13.477 continue; 13.478 } 13.479 if (Modifier.isPublic(m) || Modifier.isProtected(m)) { 13.480 + // Is it a "finalize()"? 13.481 + if(name.equals("finalize") && typeMethod.getParameterCount() == 0) { 13.482 + if(type != Object.class) { 13.483 + hasExplicitFinalizer = true; 13.484 + if(Modifier.isFinal(m)) { 13.485 + // Must be able to override an explicit finalizer 13.486 + throw new AdaptationException(Outcome.ERROR_FINAL_FINALIZER, type.getCanonicalName()); 13.487 + } 13.488 + } 13.489 + continue; 13.490 + } 13.491 + 13.492 final MethodInfo mi = new MethodInfo(typeMethod); 13.493 if (Modifier.isFinal(m) || isCallerSensitive(typeMethod)) { 13.494 finalMethods.add(mi); 13.495 @@ -884,7 +923,7 @@ 13.496 if (Modifier.isAbstract(m)) { 13.497 abstractMethodNames.add(mi.getName()); 13.498 } 13.499 - mi.setIsCanonical(usedFieldNames, classOverride); 13.500 + mi.setIsCanonical(this); 13.501 } 13.502 } 13.503 } 13.504 @@ -905,7 +944,7 @@ 13.505 } 13.506 } 13.507 13.508 - private void gatherMethods(final List<Class<?>> classes) { 13.509 + private void gatherMethods(final List<Class<?>> classes) throws AdaptationException { 13.510 for(final Class<?> c: classes) { 13.511 gatherMethods(c); 13.512 }
14.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Thu Jan 30 19:45:20 2014 +0530 14.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Thu Jan 30 20:14:29 2014 +0100 14.3 @@ -27,10 +27,6 @@ 14.4 14.5 import java.security.AccessControlContext; 14.6 import java.security.AccessController; 14.7 -import java.security.AllPermission; 14.8 -import java.security.CodeSigner; 14.9 -import java.security.CodeSource; 14.10 -import java.security.Permissions; 14.11 import java.security.PrivilegedAction; 14.12 import java.security.ProtectionDomain; 14.13 import java.security.SecureClassLoader; 14.14 @@ -45,11 +41,10 @@ 14.15 */ 14.16 @SuppressWarnings("javadoc") 14.17 final class JavaAdapterClassLoader { 14.18 - private static final ProtectionDomain GENERATED_PROTECTION_DOMAIN = createGeneratedProtectionDomain(); 14.19 private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader"); 14.20 14.21 private final String className; 14.22 - private volatile byte[] classBytes; 14.23 + private final byte[] classBytes; 14.24 14.25 JavaAdapterClassLoader(String className, byte[] classBytes) { 14.26 this.className = className.replace('/', '.'); 14.27 @@ -57,23 +52,18 @@ 14.28 } 14.29 14.30 /** 14.31 - * clear classBytes after loading class. 14.32 - */ 14.33 - void clearClassBytes() { 14.34 - this.classBytes = null; 14.35 - } 14.36 - 14.37 - /** 14.38 * Loads the generated adapter class into the JVM. 14.39 * @param parentLoader the parent class loader for the generated class loader 14.40 + * @param protectionDomain the protection domain for the generated class 14.41 * @return the generated adapter class 14.42 */ 14.43 - StaticClass generateClass(final ClassLoader parentLoader) { 14.44 + StaticClass generateClass(final ClassLoader parentLoader, final ProtectionDomain protectionDomain) { 14.45 + assert protectionDomain != null; 14.46 return AccessController.doPrivileged(new PrivilegedAction<StaticClass>() { 14.47 @Override 14.48 public StaticClass run() { 14.49 try { 14.50 - return StaticClass.forClass(Class.forName(className, true, createClassLoader(parentLoader))); 14.51 + return StaticClass.forClass(Class.forName(className, true, createClassLoader(parentLoader, protectionDomain))); 14.52 } catch (final ClassNotFoundException e) { 14.53 throw new AssertionError(e); // cannot happen 14.54 } 14.55 @@ -88,7 +78,7 @@ 14.56 // it even more by separating its invocation into a separate static method on the adapter class, but then someone 14.57 // with ability to introspect on the class and use setAccessible(true) on it could invoke the method. It's a 14.58 // security tradeoff... 14.59 - private ClassLoader createClassLoader(final ClassLoader parentLoader) { 14.60 + private ClassLoader createClassLoader(final ClassLoader parentLoader, final ProtectionDomain protectionDomain) { 14.61 return new SecureClassLoader(parentLoader) { 14.62 private final ClassLoader myLoader = getClass().getClassLoader(); 14.63 14.64 @@ -112,21 +102,10 @@ 14.65 protected Class<?> findClass(final String name) throws ClassNotFoundException { 14.66 if(name.equals(className)) { 14.67 assert classBytes != null : "what? already cleared .class bytes!!"; 14.68 - return defineClass(name, classBytes, 0, classBytes.length, GENERATED_PROTECTION_DOMAIN); 14.69 + return defineClass(name, classBytes, 0, classBytes.length, protectionDomain); 14.70 } 14.71 throw new ClassNotFoundException(name); 14.72 } 14.73 }; 14.74 } 14.75 - 14.76 - private static ProtectionDomain createGeneratedProtectionDomain() { 14.77 - // Generated classes need to have AllPermission. Since we require the "createClassLoader" RuntimePermission, we 14.78 - // can create a class loader that'll load new classes with any permissions. Our generated classes are just 14.79 - // delegating adapters, so having AllPermission can't cause anything wrong; the effective set of permissions for 14.80 - // the executing script functions will still be limited by the permissions of the caller and the permissions of 14.81 - // the script. 14.82 - final Permissions permissions = new Permissions(); 14.83 - permissions.add(new AllPermission()); 14.84 - return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions); 14.85 - } 14.86 }
15.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu Jan 30 19:45:20 2014 +0530 15.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu Jan 30 20:14:29 2014 +0100 15.3 @@ -29,17 +29,23 @@ 15.4 15.5 import java.lang.invoke.MethodHandle; 15.6 import java.lang.invoke.MethodHandles; 15.7 +import java.lang.invoke.MethodHandles.Lookup; 15.8 import java.lang.invoke.MethodType; 15.9 import java.lang.reflect.Modifier; 15.10 import java.security.AccessControlContext; 15.11 import java.security.AccessController; 15.12 +import java.security.CodeSigner; 15.13 +import java.security.CodeSource; 15.14 +import java.security.Permissions; 15.15 import java.security.PrivilegedAction; 15.16 +import java.security.ProtectionDomain; 15.17 import java.util.ArrayList; 15.18 import java.util.Arrays; 15.19 import java.util.Collections; 15.20 import java.util.HashMap; 15.21 import java.util.List; 15.22 import java.util.Map; 15.23 +import java.util.concurrent.ConcurrentHashMap; 15.24 import jdk.internal.dynalink.beans.StaticClass; 15.25 import jdk.internal.dynalink.support.LinkRequestImpl; 15.26 import jdk.nashorn.internal.objects.NativeJava; 15.27 @@ -70,6 +76,8 @@ 15.28 15.29 @SuppressWarnings("javadoc") 15.30 public final class JavaAdapterFactory { 15.31 + private static final ProtectionDomain MINIMAL_PERMISSION_DOMAIN = createMinimalPermissionDomain(); 15.32 + 15.33 // context with permissions needs for AdapterInfo creation 15.34 private static final AccessControlContext CREATE_ADAPTER_INFO_ACC_CTXT = 15.35 ClassAndLoader.createPermAccCtxt("createClassLoader", "getClassLoader", 15.36 @@ -99,11 +107,18 @@ 15.37 * @param classOverrides a JavaScript object with functions serving as the class-level overrides and 15.38 * implementations. These overrides are defined for all instances of the class, and can be further overridden on a 15.39 * per-instance basis by passing additional objects in the constructor. 15.40 + * @param lookup the lookup object identifying the caller class. The generated adapter class will have the 15.41 + * protection domain of the caller class iff the lookup object is full-strength, otherwise it will be completely 15.42 + * unprivileged. 15.43 * @return an adapter class. See this class' documentation for details on the generated adapter class. 15.44 * @throws ECMAException with a TypeError if the adapter class can not be generated because the original class is 15.45 * final, non-public, or has no public or protected constructors. 15.46 */ 15.47 - public static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides) { 15.48 + public static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides, final MethodHandles.Lookup lookup) { 15.49 + return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup)); 15.50 + } 15.51 + 15.52 + private static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides, final ProtectionDomain protectionDomain) { 15.53 assert types != null && types.length > 0; 15.54 final SecurityManager sm = System.getSecurityManager(); 15.55 if (sm != null) { 15.56 @@ -114,7 +129,23 @@ 15.57 ReflectionCheckLinker.checkReflectionAccess(type, true); 15.58 } 15.59 } 15.60 - return getAdapterInfo(types).getAdapterClassFor(classOverrides); 15.61 + return getAdapterInfo(types).getAdapterClass(classOverrides, protectionDomain); 15.62 + } 15.63 + 15.64 + private static ProtectionDomain getProtectionDomain(final MethodHandles.Lookup lookup) { 15.65 + if((lookup.lookupModes() & Lookup.PRIVATE) == 0) { 15.66 + return MINIMAL_PERMISSION_DOMAIN; 15.67 + } 15.68 + return getProtectionDomain(lookup.lookupClass()); 15.69 + } 15.70 + 15.71 + private static ProtectionDomain getProtectionDomain(final Class<?> clazz) { 15.72 + return AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() { 15.73 + @Override 15.74 + public ProtectionDomain run() { 15.75 + return clazz.getProtectionDomain(); 15.76 + } 15.77 + }); 15.78 } 15.79 15.80 /** 15.81 @@ -129,10 +160,10 @@ 15.82 * @return the constructor method handle. 15.83 * @throws Exception if anything goes wrong 15.84 */ 15.85 - public static MethodHandle getConstructor(final Class<?> sourceType, final Class<?> targetType) throws Exception { 15.86 - final StaticClass adapterClass = getAdapterClassFor(new Class<?>[] { targetType }, null); 15.87 + public static MethodHandle getConstructor(final Class<?> sourceType, final Class<?> targetType, final MethodHandles.Lookup lookup) throws Exception { 15.88 + final StaticClass adapterClass = getAdapterClassFor(new Class<?>[] { targetType }, null, lookup); 15.89 return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl( 15.90 - NashornCallSiteDescriptor.get(MethodHandles.publicLookup(), "dyn:new", 15.91 + NashornCallSiteDescriptor.get(lookup, "dyn:new", 15.92 MethodType.methodType(targetType, StaticClass.class, sourceType), 0), false, 15.93 adapterClass, null)).getInvocation(), adapterClass); 15.94 } 15.95 @@ -220,10 +251,10 @@ 15.96 private static final ClassAndLoader SCRIPT_OBJECT_LOADER = new ClassAndLoader(ScriptObject.class, true); 15.97 15.98 private final ClassLoader commonLoader; 15.99 - private final JavaAdapterClassLoader adapterGenerator; 15.100 - // Cacheable adapter class that is shared by all adapter instances that don't have class overrides, only 15.101 - // instance overrides. 15.102 - final StaticClass instanceAdapterClass; 15.103 + // TODO: soft reference the JavaAdapterClassLoader objects. They can be recreated when needed. 15.104 + private final JavaAdapterClassLoader classAdapterGenerator; 15.105 + private final JavaAdapterClassLoader instanceAdapterGenerator; 15.106 + private final Map<CodeSource, StaticClass> instanceAdapters = new ConcurrentHashMap<>(); 15.107 final boolean autoConvertibleFromFunction; 15.108 final AdaptationResult adaptationResult; 15.109 15.110 @@ -231,11 +262,8 @@ 15.111 this.commonLoader = findCommonLoader(definingLoader); 15.112 final JavaAdapterBytecodeGenerator gen = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, false); 15.113 this.autoConvertibleFromFunction = gen.isAutoConvertibleFromFunction(); 15.114 - final JavaAdapterClassLoader jacl = gen.createAdapterClassLoader(); 15.115 - this.instanceAdapterClass = jacl.generateClass(commonLoader); 15.116 - // loaded Class - no need to keep class bytes around 15.117 - jacl.clearClassBytes(); 15.118 - this.adapterGenerator = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, true).createAdapterClassLoader(); 15.119 + instanceAdapterGenerator = gen.createAdapterClassLoader(); 15.120 + this.classAdapterGenerator = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, true).createAdapterClassLoader(); 15.121 this.adaptationResult = AdaptationResult.SUCCESSFUL_RESULT; 15.122 } 15.123 15.124 @@ -245,22 +273,42 @@ 15.125 15.126 AdapterInfo(final AdaptationResult adaptationResult) { 15.127 this.commonLoader = null; 15.128 - this.adapterGenerator = null; 15.129 - this.instanceAdapterClass = null; 15.130 + this.classAdapterGenerator = null; 15.131 + this.instanceAdapterGenerator = null; 15.132 this.autoConvertibleFromFunction = false; 15.133 this.adaptationResult = adaptationResult; 15.134 } 15.135 15.136 - StaticClass getAdapterClassFor(ScriptObject classOverrides) { 15.137 + StaticClass getAdapterClass(final ScriptObject classOverrides, final ProtectionDomain protectionDomain) { 15.138 if(adaptationResult.getOutcome() != AdaptationResult.Outcome.SUCCESS) { 15.139 throw adaptationResult.typeError(); 15.140 } 15.141 - if(classOverrides == null) { 15.142 + return classOverrides == null ? getInstanceAdapterClass(protectionDomain) : 15.143 + getClassAdapterClass(classOverrides, protectionDomain); 15.144 + } 15.145 + 15.146 + private StaticClass getInstanceAdapterClass(final ProtectionDomain protectionDomain) { 15.147 + CodeSource codeSource = protectionDomain.getCodeSource(); 15.148 + if(codeSource == null) { 15.149 + codeSource = MINIMAL_PERMISSION_DOMAIN.getCodeSource(); 15.150 + } 15.151 + StaticClass instanceAdapterClass = instanceAdapters.get(codeSource); 15.152 + if(instanceAdapterClass != null) { 15.153 return instanceAdapterClass; 15.154 } 15.155 + // Any "unknown source" code source will default to no permission domain. 15.156 + final ProtectionDomain effectiveDomain = codeSource.equals(MINIMAL_PERMISSION_DOMAIN.getCodeSource()) ? 15.157 + MINIMAL_PERMISSION_DOMAIN : protectionDomain; 15.158 + 15.159 + instanceAdapterClass = instanceAdapterGenerator.generateClass(commonLoader, effectiveDomain); 15.160 + final StaticClass existing = instanceAdapters.putIfAbsent(codeSource, instanceAdapterClass); 15.161 + return existing == null ? instanceAdapterClass : existing; 15.162 + } 15.163 + 15.164 + private StaticClass getClassAdapterClass(final ScriptObject classOverrides, final ProtectionDomain protectionDomain) { 15.165 JavaAdapterServices.setClassOverrides(classOverrides); 15.166 try { 15.167 - return adapterGenerator.generateClass(commonLoader); 15.168 + return classAdapterGenerator.generateClass(commonLoader, protectionDomain); 15.169 } finally { 15.170 JavaAdapterServices.setClassOverrides(null); 15.171 } 15.172 @@ -285,4 +333,12 @@ 15.173 throw new AdaptationException(AdaptationResult.Outcome.ERROR_NO_COMMON_LOADER, classAndLoader.getRepresentativeClass().getCanonicalName()); 15.174 } 15.175 } 15.176 + 15.177 + private static ProtectionDomain createMinimalPermissionDomain() { 15.178 + // Generated classes need to have at least the permission to access Nashorn runtime and runtime.linker packages. 15.179 + final Permissions permissions = new Permissions(); 15.180 + permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime")); 15.181 + permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime.linker")); 15.182 + return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions); 15.183 + } 15.184 }
16.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java Thu Jan 30 19:45:20 2014 +0530 16.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java Thu Jan 30 20:14:29 2014 +0100 16.3 @@ -25,10 +25,28 @@ 16.4 16.5 package jdk.nashorn.internal.runtime.linker; 16.6 16.7 +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_FINAL; 16.8 +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; 16.9 +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC; 16.10 +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER; 16.11 +import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD; 16.12 +import static jdk.internal.org.objectweb.asm.Opcodes.RETURN; 16.13 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 16.14 16.15 import java.lang.invoke.MethodHandle; 16.16 +import java.lang.invoke.MethodHandles; 16.17 import java.lang.invoke.MethodType; 16.18 +import java.security.AccessController; 16.19 +import java.security.CodeSigner; 16.20 +import java.security.CodeSource; 16.21 +import java.security.Permissions; 16.22 +import java.security.PrivilegedAction; 16.23 +import java.security.ProtectionDomain; 16.24 +import java.security.SecureClassLoader; 16.25 +import jdk.internal.org.objectweb.asm.ClassWriter; 16.26 +import jdk.internal.org.objectweb.asm.Opcodes; 16.27 +import jdk.internal.org.objectweb.asm.Type; 16.28 +import jdk.internal.org.objectweb.asm.commons.InstructionAdapter; 16.29 import jdk.nashorn.internal.runtime.Context; 16.30 import jdk.nashorn.internal.runtime.ScriptFunction; 16.31 import jdk.nashorn.internal.runtime.ScriptObject; 16.32 @@ -40,6 +58,7 @@ 16.33 */ 16.34 public final class JavaAdapterServices { 16.35 private static final ThreadLocal<ScriptObject> classOverrides = new ThreadLocal<>(); 16.36 + private static final MethodHandle NO_PERMISSIONS_INVOKER = createNoPermissionsInvoker(); 16.37 16.38 private JavaAdapterServices() { 16.39 } 16.40 @@ -55,7 +74,7 @@ 16.41 */ 16.42 public static MethodHandle getHandle(final ScriptFunction fn, final MethodType type) { 16.43 // JS "this" will be global object or undefined depending on if 'fn' is strict or not 16.44 - return adaptHandle(fn.getBoundInvokeHandle(fn.isStrict()? ScriptRuntime.UNDEFINED : Context.getGlobal()), type); 16.45 + return bindAndAdaptHandle(fn, fn.isStrict()? ScriptRuntime.UNDEFINED : Context.getGlobal(), type); 16.46 } 16.47 16.48 /** 16.49 @@ -83,7 +102,7 @@ 16.50 16.51 final Object fnObj = sobj.get(name); 16.52 if (fnObj instanceof ScriptFunction) { 16.53 - return adaptHandle(((ScriptFunction)fnObj).getBoundInvokeHandle(sobj), type); 16.54 + return bindAndAdaptHandle((ScriptFunction)fnObj, sobj, type); 16.55 } else if(fnObj == null || fnObj instanceof Undefined) { 16.56 return null; 16.57 } else { 16.58 @@ -103,11 +122,67 @@ 16.59 return overrides; 16.60 } 16.61 16.62 + /** 16.63 + * Takes a method handle and an argument to it, and invokes the method handle passing it the argument. Basically 16.64 + * equivalent to {@code method.invokeExact(arg)}, except that the method handle will be invoked in a protection 16.65 + * domain with absolutely no permissions. 16.66 + * @param method the method handle to invoke. The handle must have the exact type of {@code void(Object)}. 16.67 + * @param arg the argument to pass to the handle. 16.68 + * @throws Throwable if anything goes wrong. 16.69 + */ 16.70 + public static void invokeNoPermissions(final MethodHandle method, final Object arg) throws Throwable { 16.71 + NO_PERMISSIONS_INVOKER.invokeExact(method, arg); 16.72 + } 16.73 + 16.74 static void setClassOverrides(ScriptObject overrides) { 16.75 classOverrides.set(overrides); 16.76 } 16.77 16.78 - private static MethodHandle adaptHandle(final MethodHandle handle, final MethodType type) { 16.79 - return Bootstrap.getLinkerServices().asType(ScriptObject.pairArguments(handle, type, false), type); 16.80 + private static MethodHandle bindAndAdaptHandle(final ScriptFunction fn, final Object self, final MethodType type) { 16.81 + return Bootstrap.getLinkerServices().asType(ScriptObject.pairArguments(fn.getBoundInvokeHandle(self), type, false), type); 16.82 + } 16.83 + 16.84 + private static MethodHandle createNoPermissionsInvoker() { 16.85 + final String className = "NoPermissionsInvoker"; 16.86 + 16.87 + final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); 16.88 + cw.visit(Opcodes.V1_7, ACC_PUBLIC | ACC_SUPER | ACC_FINAL, className, null, "java/lang/Object", null); 16.89 + final Type objectType = Type.getType(Object.class); 16.90 + final Type methodHandleType = Type.getType(MethodHandle.class); 16.91 + final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "invoke", 16.92 + Type.getMethodDescriptor(Type.VOID_TYPE, methodHandleType, objectType), null, null)); 16.93 + mv.visitCode(); 16.94 + mv.visitVarInsn(ALOAD, 0); 16.95 + mv.visitVarInsn(ALOAD, 1); 16.96 + mv.invokevirtual(methodHandleType.getInternalName(), "invokeExact", Type.getMethodDescriptor( 16.97 + Type.VOID_TYPE, objectType), false); 16.98 + mv.visitInsn(RETURN); 16.99 + mv.visitMaxs(0, 0); 16.100 + mv.visitEnd(); 16.101 + cw.visitEnd(); 16.102 + final byte[] bytes = cw.toByteArray(); 16.103 + 16.104 + final ClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { 16.105 + @Override 16.106 + public ClassLoader run() { 16.107 + return new SecureClassLoader(null) { 16.108 + @Override 16.109 + protected Class<?> findClass(String name) throws ClassNotFoundException { 16.110 + if(name.equals(className)) { 16.111 + return defineClass(name, bytes, 0, bytes.length, new ProtectionDomain( 16.112 + new CodeSource(null, (CodeSigner[])null), new Permissions())); 16.113 + } 16.114 + throw new ClassNotFoundException(name); 16.115 + } 16.116 + }; 16.117 + } 16.118 + }); 16.119 + 16.120 + try { 16.121 + return MethodHandles.lookup().findStatic(Class.forName(className, true, loader), "invoke", 16.122 + MethodType.methodType(void.class, MethodHandle.class, Object.class)); 16.123 + } catch(ReflectiveOperationException e) { 16.124 + throw new AssertionError(e.getMessage(), e); 16.125 + } 16.126 } 16.127 }
17.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Thu Jan 30 19:45:20 2014 +0530 17.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Thu Jan 30 20:14:29 2014 +0100 17.3 @@ -25,19 +25,20 @@ 17.4 17.5 package jdk.nashorn.internal.runtime.linker; 17.6 17.7 +import static jdk.nashorn.internal.lookup.Lookup.MH; 17.8 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 17.9 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 17.10 -import static jdk.nashorn.internal.lookup.Lookup.MH; 17.11 17.12 import java.lang.invoke.MethodHandle; 17.13 import java.lang.invoke.MethodType; 17.14 import java.lang.reflect.Method; 17.15 import java.lang.reflect.Modifier; 17.16 +import java.util.HashMap; 17.17 import java.util.Map; 17.18 -import java.util.HashMap; 17.19 import jdk.internal.dynalink.CallSiteDescriptor; 17.20 import jdk.internal.dynalink.beans.BeansLinker; 17.21 import jdk.internal.dynalink.linker.GuardedInvocation; 17.22 +import jdk.internal.dynalink.linker.GuardedTypeConversion; 17.23 import jdk.internal.dynalink.linker.GuardingDynamicLinker; 17.24 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; 17.25 import jdk.internal.dynalink.linker.LinkRequest; 17.26 @@ -134,9 +135,9 @@ 17.27 } 17.28 17.29 @Override 17.30 - public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { 17.31 + public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { 17.32 final GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType); 17.33 - return gi == null ? null : gi.asType(MH.type(targetType, sourceType)); 17.34 + return gi == null ? null : new GuardedTypeConversion(gi.asType(MH.type(targetType, sourceType)), true); 17.35 } 17.36 17.37 /**
18.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Thu Jan 30 19:45:20 2014 +0530 18.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Thu Jan 30 20:14:29 2014 +0100 18.3 @@ -29,7 +29,10 @@ 18.4 18.5 import java.lang.invoke.MethodHandle; 18.6 import java.lang.invoke.MethodHandles; 18.7 +import java.lang.invoke.MethodHandles.Lookup; 18.8 import java.lang.reflect.Modifier; 18.9 +import java.security.AccessController; 18.10 +import java.security.PrivilegedAction; 18.11 import java.util.Deque; 18.12 import java.util.List; 18.13 import java.util.Map; 18.14 @@ -37,16 +40,17 @@ 18.15 import jdk.internal.dynalink.CallSiteDescriptor; 18.16 import jdk.internal.dynalink.linker.ConversionComparator; 18.17 import jdk.internal.dynalink.linker.GuardedInvocation; 18.18 +import jdk.internal.dynalink.linker.GuardedTypeConversion; 18.19 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; 18.20 import jdk.internal.dynalink.linker.LinkRequest; 18.21 import jdk.internal.dynalink.linker.LinkerServices; 18.22 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; 18.23 import jdk.internal.dynalink.support.Guards; 18.24 +import jdk.internal.dynalink.support.LinkerServicesImpl; 18.25 import jdk.nashorn.api.scripting.JSObject; 18.26 import jdk.nashorn.api.scripting.ScriptObjectMirror; 18.27 import jdk.nashorn.api.scripting.ScriptUtils; 18.28 import jdk.nashorn.internal.objects.NativeArray; 18.29 -import jdk.nashorn.internal.runtime.Context; 18.30 import jdk.nashorn.internal.runtime.JSType; 18.31 import jdk.nashorn.internal.runtime.ScriptFunction; 18.32 import jdk.nashorn.internal.runtime.ScriptObject; 18.33 @@ -100,9 +104,16 @@ 18.34 } 18.35 18.36 @Override 18.37 - public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { 18.38 - final GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType); 18.39 - return gi == null ? null : gi.asType(MH.type(targetType, sourceType)); 18.40 + public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { 18.41 + GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType); 18.42 + if(gi != null) { 18.43 + return new GuardedTypeConversion(gi.asType(MH.type(targetType, sourceType)), true); 18.44 + } 18.45 + gi = getSamTypeConverter(sourceType, targetType); 18.46 + if(gi != null) { 18.47 + return new GuardedTypeConversion(gi.asType(MH.type(targetType, sourceType)), false); 18.48 + } 18.49 + return null; 18.50 } 18.51 18.52 /** 18.53 @@ -126,12 +137,7 @@ 18.54 return arrayConverter; 18.55 } 18.56 18.57 - final GuardedInvocation mirrorConverter = getMirrorConverter(sourceType, targetType); 18.58 - if(mirrorConverter != null) { 18.59 - return mirrorConverter; 18.60 - } 18.61 - 18.62 - return getSamTypeConverter(sourceType, targetType); 18.63 + return getMirrorConverter(sourceType, targetType); 18.64 } 18.65 18.66 /** 18.67 @@ -150,13 +156,23 @@ 18.68 final boolean isSourceTypeGeneric = sourceType.isAssignableFrom(ScriptFunction.class); 18.69 18.70 if ((isSourceTypeGeneric || ScriptFunction.class.isAssignableFrom(sourceType)) && isAutoConvertibleFromFunction(targetType)) { 18.71 - final MethodHandle ctor = JavaAdapterFactory.getConstructor(ScriptFunction.class, targetType); 18.72 + final MethodHandle ctor = JavaAdapterFactory.getConstructor(ScriptFunction.class, targetType, getCurrentLookup()); 18.73 assert ctor != null; // if isAutoConvertibleFromFunction() returned true, then ctor must exist. 18.74 return new GuardedInvocation(ctor, isSourceTypeGeneric ? IS_SCRIPT_FUNCTION : null); 18.75 } 18.76 return null; 18.77 } 18.78 18.79 + private static Lookup getCurrentLookup() { 18.80 + final LinkRequest currentRequest = AccessController.doPrivileged(new PrivilegedAction<LinkRequest>() { 18.81 + @Override 18.82 + public LinkRequest run() { 18.83 + return LinkerServicesImpl.getCurrentLinkRequest(); 18.84 + } 18.85 + }); 18.86 + return currentRequest == null ? MethodHandles.publicLookup() : currentRequest.getCallSiteDescriptor().getLookup(); 18.87 + } 18.88 + 18.89 /** 18.90 * Returns a guarded invocation that converts from a source type that is NativeArray to a Java array or List or 18.91 * Deque type.
19.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Thu Jan 30 19:45:20 2014 +0530 19.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Thu Jan 30 20:14:29 2014 +0100 19.3 @@ -31,6 +31,7 @@ 19.4 import java.lang.invoke.MethodHandles; 19.5 import jdk.internal.dynalink.linker.ConversionComparator; 19.6 import jdk.internal.dynalink.linker.GuardedInvocation; 19.7 +import jdk.internal.dynalink.linker.GuardedTypeConversion; 19.8 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; 19.9 import jdk.internal.dynalink.linker.LinkRequest; 19.10 import jdk.internal.dynalink.linker.LinkerServices; 19.11 @@ -75,13 +76,13 @@ 19.12 * @return a conditional converter from source to target type 19.13 */ 19.14 @Override 19.15 - public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) { 19.16 + public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) { 19.17 final MethodHandle mh = JavaArgumentConverters.getConverter(targetType); 19.18 if (mh == null) { 19.19 return null; 19.20 } 19.21 19.22 - return new GuardedInvocation(mh, canLinkTypeStatic(sourceType) ? null : GUARD_PRIMITIVE).asType(mh.type().changeParameterType(0, sourceType)); 19.23 + return new GuardedTypeConversion(new GuardedInvocation(mh, canLinkTypeStatic(sourceType) ? null : GUARD_PRIMITIVE).asType(mh.type().changeParameterType(0, sourceType)), true); 19.24 } 19.25 19.26 /**
20.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Thu Jan 30 19:45:20 2014 +0530 20.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Thu Jan 30 20:14:29 2014 +0100 20.3 @@ -76,7 +76,8 @@ 20.4 if (NashornLinker.isAbstractClass(receiverClass)) { 20.5 // Change this link request into a link request on the adapter class. 20.6 final Object[] args = request.getArguments(); 20.7 - args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null); 20.8 + args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null, 20.9 + linkRequest.getCallSiteDescriptor().getLookup()); 20.10 final LinkRequest adapterRequest = request.replaceArguments(request.getCallSiteDescriptor(), args); 20.11 final GuardedInvocation gi = checkNullConstructor(delegate(linkerServices, adapterRequest), receiverClass); 20.12 // Finally, modify the guard to test for the original abstract class.
21.1 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Jan 30 19:45:20 2014 +0530 21.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Jan 30 20:14:29 2014 +0100 21.3 @@ -130,6 +130,7 @@ 21.4 type.error.extend.ERROR_NO_ACCESSIBLE_CONSTRUCTOR=Can not extend class {0} as it has no public or protected constructors. 21.5 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. 21.6 type.error.extend.ERROR_NO_COMMON_LOADER=Can not find a common class loader for ScriptObject and {0}. 21.7 +type.error.extend.ERROR_FINAL_FINALIZER=Can not extend class because {0} has a final finalize method. 21.8 type.error.no.constructor.matches.args=Can not construct {0} with the passed arguments; they do not match any of its constructor signatures. 21.9 type.error.no.method.matches.args=Can not invoke method {0} with the passed arguments; they do not match any of its method signatures. 21.10 type.error.method.not.constructor=Java method {0} can't be used as a constructor.
22.1 --- a/test/script/basic/JDK-8014647.js Thu Jan 30 19:45:20 2014 +0530 22.2 +++ b/test/script/basic/JDK-8014647.js Thu Jan 30 20:14:29 2014 +0100 22.3 @@ -32,9 +32,10 @@ 22.4 var RunnableImpl2 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 2!") }) 22.5 var r1 = new RunnableImpl1() 22.6 var r2 = new RunnableImpl2() 22.7 -var r3 = new RunnableImpl2(function() { print("I'm runnable 3!") }) 22.8 +var RunnableImpl3 = Java.extend(RunnableImpl2); 22.9 +var r3 = new RunnableImpl3({ run: function() { print("I'm runnable 3!") }}) 22.10 r1.run() 22.11 r2.run() 22.12 r3.run() 22.13 -print("r1.class === r2.class: " + (r1.class === r2.class)) 22.14 -print("r2.class === r3.class: " + (r2.class === r3.class)) 22.15 +print("r1.class !== r2.class: " + (r1.class !== r2.class)) 22.16 +print("r2.class !== r3.class: " + (r2.class !== r3.class))
23.1 --- a/test/script/basic/JDK-8014647.js.EXPECTED Thu Jan 30 19:45:20 2014 +0530 23.2 +++ b/test/script/basic/JDK-8014647.js.EXPECTED Thu Jan 30 20:14:29 2014 +0100 23.3 @@ -1,5 +1,5 @@ 23.4 I'm runnable 1! 23.5 I'm runnable 2! 23.6 I'm runnable 3! 23.7 -r1.class === r2.class: false 23.8 -r2.class === r3.class: true 23.9 +r1.class !== r2.class: true 23.10 +r2.class !== r3.class: true
24.1 --- a/test/script/basic/javaclassoverrides.js Thu Jan 30 19:45:20 2014 +0530 24.2 +++ b/test/script/basic/javaclassoverrides.js Thu Jan 30 20:14:29 2014 +0100 24.3 @@ -46,7 +46,8 @@ 24.4 var r1 = new R1 24.5 var r2 = new R2 24.6 // Create one with an instance-override too 24.7 -var r3 = new R2(function() { print("r3.run() invoked") }) 24.8 +var R3 = Java.extend(R2) 24.9 +var r3 = new R3({ run: function() { print("r3.run() invoked") }}) 24.10 24.11 // Run 'em - we're passing them through a Thread to make sure they indeed 24.12 // are full-blown Runnables 24.13 @@ -60,9 +61,9 @@ 24.14 runInThread(r3) 24.15 24.16 // Two class-override classes differ 24.17 -print("r1.class != r2.class: " + (r1.class != r2.class)) 24.18 -// However, adding instance-overrides doesn't change the class 24.19 -print("r2.class == r3.class: " + (r2.class == r3.class)) 24.20 +print("r1.class !== r2.class: " + (r1.class !== r2.class)) 24.21 +// instance-override class also differs 24.22 +print("r2.class !== r3.class: " + (r2.class !== r3.class)) 24.23 24.24 function checkAbstract(r) { 24.25 try { 24.26 @@ -77,10 +78,10 @@ 24.27 // overrides nor instance overrides are present 24.28 var RAbstract = Java.extend(java.lang.Runnable, {}) 24.29 checkAbstract(new RAbstract()) // class override (empty) 24.30 -checkAbstract(new RAbstract() {}) // class+instance override (empty) 24.31 +checkAbstract(new (Java.extend(RAbstract))() {}) // class+instance override (empty) 24.32 24.33 // Check we delegate to superclass if neither class 24.34 // overrides nor instance overrides are present 24.35 var ExtendsList = Java.extend(java.util.ArrayList, {}) 24.36 print("(new ExtendsList).size() = " + (new ExtendsList).size()) 24.37 -print("(new ExtendsList(){}).size() = " + (new ExtendsList(){}).size()) 24.38 \ No newline at end of file 24.39 +print("(new (Java.extend(ExtendsList)){}).size() = " + (new (Java.extend(ExtendsList)){}).size())
25.1 --- a/test/script/basic/javaclassoverrides.js.EXPECTED Thu Jan 30 19:45:20 2014 +0530 25.2 +++ b/test/script/basic/javaclassoverrides.js.EXPECTED Thu Jan 30 20:14:29 2014 +0100 25.3 @@ -1,9 +1,9 @@ 25.4 R1.run() invoked 25.5 R2.run() invoked 25.6 r3.run() invoked 25.7 -r1.class != r2.class: true 25.8 -r2.class == r3.class: true 25.9 +r1.class !== r2.class: true 25.10 +r2.class !== r3.class: true 25.11 Got exception: java.lang.UnsupportedOperationException 25.12 Got exception: java.lang.UnsupportedOperationException 25.13 (new ExtendsList).size() = 0 25.14 -(new ExtendsList(){}).size() = 0 25.15 +(new (Java.extend(ExtendsList)){}).size() = 0
26.1 --- a/test/script/sandbox/javaextend.js Thu Jan 30 19:45:20 2014 +0530 26.2 +++ b/test/script/sandbox/javaextend.js Thu Jan 30 20:14:29 2014 +0100 26.3 @@ -51,6 +51,21 @@ 26.4 print(e) 26.5 } 26.6 26.7 +// Can't extend a class with explicit non-overridable finalizer 26.8 +try { 26.9 + Java.extend(model("ClassWithFinalFinalizer")) 26.10 +} catch(e) { 26.11 + print(e) 26.12 +} 26.13 + 26.14 +// Can't extend a class with inherited non-overridable finalizer 26.15 +try { 26.16 + Java.extend(model("ClassWithInheritedFinalFinalizer")) 26.17 +} catch(e) { 26.18 + print(e) 26.19 +} 26.20 + 26.21 + 26.22 // Can't extend two classes 26.23 try { 26.24 Java.extend(java.lang.Thread,java.lang.Number)
27.1 --- a/test/script/sandbox/javaextend.js.EXPECTED Thu Jan 30 19:45:20 2014 +0530 27.2 +++ b/test/script/sandbox/javaextend.js.EXPECTED Thu Jan 30 20:14:29 2014 +0100 27.3 @@ -1,6 +1,8 @@ 27.4 TypeError: Can not extend final class jdk.nashorn.test.models.FinalClass. 27.5 TypeError: Can not extend class jdk.nashorn.test.models.NoAccessibleConstructorClass as it has no public or protected constructors. 27.6 TypeError: Can not extend/implement non-public class/interface jdk.nashorn.test.models.NonPublicClass. 27.7 +TypeError: Can not extend class because jdk.nashorn.test.models.ClassWithFinalFinalizer has a final finalize method. 27.8 +TypeError: Can not extend class because jdk.nashorn.test.models.ClassWithFinalFinalizer has a final finalize method. 27.9 TypeError: Can not extend multiple classes java.lang.Number and java.lang.Thread. At most one of the specified types can be a class, the rest must all be interfaces. 27.10 abcdabcd 27.11 run-object
28.1 --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java Thu Jan 30 19:45:20 2014 +0530 28.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java Thu Jan 30 20:14:29 2014 +0100 28.3 @@ -33,8 +33,8 @@ 28.4 import java.util.Objects; 28.5 import javax.script.Invocable; 28.6 import javax.script.ScriptEngine; 28.7 +import javax.script.ScriptEngineManager; 28.8 import javax.script.ScriptException; 28.9 -import javax.script.ScriptEngineManager; 28.10 import org.testng.annotations.Test; 28.11 28.12 /** 28.13 @@ -130,6 +130,23 @@ 28.14 } 28.15 } 28.16 28.17 + 28.18 + @Test 28.19 + public void securitySystemExitFromFinalizerThread() throws ScriptException { 28.20 + if (System.getSecurityManager() == null) { 28.21 + // pass vacuously 28.22 + return; 28.23 + } 28.24 + 28.25 + final ScriptEngineManager m = new ScriptEngineManager(); 28.26 + final ScriptEngine e = m.getEngineByName("nashorn"); 28.27 + e.eval("var o = Java.extend(Java.type('javax.imageio.spi.ServiceRegistry'), { deregisterAll: this.exit.bind(null, 1234)});\n" + 28.28 + "new o(new java.util.ArrayList().iterator())"); 28.29 + System.gc(); 28.30 + System.runFinalization(); 28.31 + // NOTE: this test just exits the VM if it fails. 28.32 + } 28.33 + 28.34 @Test 28.35 public void securitySystemLoadLibrary() { 28.36 if (System.getSecurityManager() == null) {
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java Thu Jan 30 20:14:29 2014 +0100 29.3 @@ -0,0 +1,31 @@ 29.4 +/* 29.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 29.7 + * 29.8 + * This code is free software; you can redistribute it and/or modify it 29.9 + * under the terms of the GNU General Public License version 2 only, as 29.10 + * published by the Free Software Foundation. Oracle designates this 29.11 + * particular file as subject to the "Classpath" exception as provided 29.12 + * by Oracle in the LICENSE file that accompanied this code. 29.13 + * 29.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 29.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 29.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 29.17 + * version 2 for more details (a copy is included in the LICENSE file that 29.18 + * accompanied this code). 29.19 + * 29.20 + * You should have received a copy of the GNU General Public License version 29.21 + * 2 along with this work; if not, write to the Free Software Foundation, 29.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 29.23 + * 29.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 29.25 + * or visit www.oracle.com if you need additional information or have any 29.26 + * questions. 29.27 + */ 29.28 + 29.29 +package jdk.nashorn.test.models; 29.30 + 29.31 +public class ClassWithFinalFinalizer { 29.32 + protected final void finalize() { 29.33 + } 29.34 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java Thu Jan 30 20:14:29 2014 +0100 30.3 @@ -0,0 +1,29 @@ 30.4 +/* 30.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 30.7 + * 30.8 + * This code is free software; you can redistribute it and/or modify it 30.9 + * under the terms of the GNU General Public License version 2 only, as 30.10 + * published by the Free Software Foundation. Oracle designates this 30.11 + * particular file as subject to the "Classpath" exception as provided 30.12 + * by Oracle in the LICENSE file that accompanied this code. 30.13 + * 30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 30.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 30.17 + * version 2 for more details (a copy is included in the LICENSE file that 30.18 + * accompanied this code). 30.19 + * 30.20 + * You should have received a copy of the GNU General Public License version 30.21 + * 2 along with this work; if not, write to the Free Software Foundation, 30.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 30.23 + * 30.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30.25 + * or visit www.oracle.com if you need additional information or have any 30.26 + * questions. 30.27 + */ 30.28 + 30.29 +package jdk.nashorn.test.models; 30.30 + 30.31 +public class ClassWithInheritedFinalFinalizer extends ClassWithFinalFinalizer { 30.32 +}