This commit is contained in:
Lana Steuck 2015-07-16 19:30:19 -07:00
commit 600a087671
23 changed files with 192 additions and 44 deletions

View File

@ -23,6 +23,7 @@ report.xml
CC/*
jcov2/*
.idea/*
test/lib/testng*.zip
test/lib/testng.jar
test/script/external/*
.project

View File

@ -55,7 +55,7 @@ import java.util.List;
import jdk.internal.org.objectweb.asm.Handle;
/**
* This class generates constructor class for a @ClassInfo annotated class.
* This class generates constructor class for a @ScriptClass annotated class.
*
*/
public class ConstructorGenerator extends ClassGenerator {
@ -75,7 +75,7 @@ public class ConstructorGenerator extends ClassGenerator {
}
byte[] getClassBytes() {
// new class extensing from ScriptObject
// new class extending from ScriptObject
final String superClass = (constructor != null)? SCRIPTFUNCTIONIMPL_TYPE : SCRIPTOBJECT_TYPE;
cw.visit(V1_7, ACC_FINAL, className, null, superClass, null);
if (memberCount > 0) {

View File

@ -161,7 +161,7 @@ public final class MemberInfo implements Cloneable {
}
/**
* Tag something as optimitic builtin or not
* Tag something as optimistic builtin or not
* @param isOptimistic boolean, true if builtin constructor
*/
public void setIsOptimistic(final boolean isOptimistic) {
@ -178,7 +178,7 @@ public final class MemberInfo implements Cloneable {
}
/**
* Set thre SpecializedFunction link logic class for specializations, i.e. optimistic
* Set the SpecializedFunction link logic class for specializations, i.e. optimistic
* builtins
* @param linkLogicClass link logic class
*/

View File

@ -42,7 +42,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
/**
* This class generates prototype class for a @ClassInfo annotated class.
* This class generates prototype class for a @ScriptClass annotated class.
*
*/
public class PrototypeGenerator extends ClassGenerator {
@ -57,7 +57,7 @@ public class PrototypeGenerator extends ClassGenerator {
}
byte[] getClassBytes() {
// new class extensing from ScriptObject
// new class extending from ScriptObject
cw.visit(V1_7, ACC_FINAL | ACC_SUPER, className, null, PROTOTYPEOBJECT_TYPE, null);
if (memberCount > 0) {
// add fields
@ -155,7 +155,7 @@ public class PrototypeGenerator extends ClassGenerator {
*/
public static void main(final String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: " + ConstructorGenerator.class.getName() + " <class>");
System.err.println("Usage: " + PrototypeGenerator.class.getName() + " <class>");
System.exit(1);
}

View File

@ -48,7 +48,7 @@ import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind;
*
*/
public final class ScriptClassInfo {
// descriptots for various annotations
// descriptors for various annotations
static final String SCRIPT_CLASS_ANNO_DESC = Type.getDescriptor(ScriptClass.class);
static final String CONSTRUCTOR_ANNO_DESC = Type.getDescriptor(Constructor.class);
static final String FUNCTION_ANNO_DESC = Type.getDescriptor(Function.class);
@ -140,7 +140,7 @@ public final class ScriptClassInfo {
}
boolean isPrototypeNeeded() {
// Prototype class generation is needed if we have atleast one
// Prototype class generation is needed if we have at least one
// prototype property or @Constructor defined in the class.
for (final MemberInfo memInfo : members) {
if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) {

View File

@ -118,7 +118,7 @@ public class ScriptClassInfoCollector extends ClassVisitor {
addScriptMember(memInfo);
return new AnnotationVisitor(Main.ASM_VERSION, delegateAV) {
// These could be "null" if values are not suppiled,
// These could be "null" if values are not supplied,
// in which case we have to use the default values.
private String name;
private Integer attributes;
@ -194,7 +194,7 @@ public class ScriptClassInfoCollector extends ClassVisitor {
final MemberInfo memInfo = new MemberInfo();
//annokind == e.g. GETTER or SPECIALIZED_FUNCTION
// annoKind == GETTER or SPECIALIZED_FUNCTION
memInfo.setKind(annoKind);
memInfo.setJavaName(methodName);
memInfo.setJavaDesc(methodDesc);
@ -203,7 +203,7 @@ public class ScriptClassInfoCollector extends ClassVisitor {
addScriptMember(memInfo);
return new AnnotationVisitor(Main.ASM_VERSION, delegateAV) {
// These could be "null" if values are not suppiled,
// These could be "null" if values are not supplied,
// in which case we have to use the default values.
private String name;
private Integer attributes;

View File

@ -64,7 +64,6 @@ import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind;
* 2) add "Map" type static field named "$map".
* 3) add static initializer block to initialize map.
*/
public class ScriptClassInstrumentor extends ClassVisitor {
private final ScriptClassInfo scriptClassInfo;
private final int memberCount;
@ -266,7 +265,7 @@ public class ScriptClassInstrumentor extends ClassVisitor {
*/
public static void main(final String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: " + ScriptClassInfoCollector.class.getName() + " <class>");
System.err.println("Usage: " + ScriptClassInstrumentor.class.getName() + " <class>");
System.exit(1);
}

View File

@ -180,7 +180,7 @@ public abstract class AbstractJSObject implements JSObject {
/**
* Checking whether the given object is an instance of 'this' object.
*
* @param instance instace to check
* @param instance instance to check
* @return true if the given 'instance' is an instance of this 'function' object
*/
@Override

View File

@ -142,7 +142,7 @@ public interface JSObject {
/**
* Checking whether the given object is an instance of 'this' object.
*
* @param instance instace to check
* @param instance instance to check
* @return true if the given 'instance' is an instance of this 'function' object
*/
public boolean isInstance(final Object instance);

View File

@ -2118,17 +2118,18 @@ public final class Global extends Scope {
}
}
final boolean extensible = isExtensible();
for (final jdk.nashorn.internal.runtime.Property property : properties) {
if (property.isLexicalBinding()) {
assert lexScope != null;
lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property);
lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property, true);
if (ownMap.findProperty(property.getKey()) != null) {
// If property exists in the global object invalidate any global constant call sites.
invalidateGlobalConstant(property.getKey());
}
} else {
ownMap = addBoundProperty(ownMap, source, property);
ownMap = addBoundProperty(ownMap, source, property, extensible);
}
}
@ -2730,9 +2731,9 @@ public final class Global extends Scope {
}
@Override
protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property, final boolean extensible) {
// We override this method just to make it callable by Global
return super.addBoundProperty(propMap, source, property);
return super.addBoundProperty(propMap, source, property, extensible);
}
private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {

View File

@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;

View File

@ -108,7 +108,7 @@ public final class NativeFunction {
throw new AssertionError("Should not reach here");
}
/**
/**
* Given an array-like object, converts it into a Java object array suitable for invocation of ScriptRuntime.apply
* or for direct invocation of the applied function.
* @param array the array-like object. Can be null in which case a zero-length array is created.

View File

@ -187,14 +187,14 @@ public final class GlobalFunctions {
double result = 0.0;
int digit;
// we should see atleast one valid digit
// we should see at least one valid digit
boolean entered = false;
while (idx < length) {
digit = fastDigit(str.charAt(idx++), radix);
if (digit < 0) {
break;
}
// we have seen atleast one valid digit in the specified radix
// we have seen at least one valid digit in the specified radix
entered = true;
result *= radix;
result += digit;

View File

@ -104,16 +104,28 @@ public final class JSONFunctions {
final Object val = holder.get(name);
if (val instanceof ScriptObject) {
final ScriptObject valueObj = (ScriptObject)val;
final Iterator<String> iter = valueObj.propertyIterator();
if (valueObj.isArray()) {
final int length = JSType.toInteger(valueObj.getLength());
for (int i = 0; i < length; i++) {
final String key = Integer.toString(i);
final Object newElement = walk(valueObj, key, reviver);
while (iter.hasNext()) {
final String key = iter.next();
final Object newElement = walk(valueObj, key, reviver);
if (newElement == ScriptRuntime.UNDEFINED) {
valueObj.delete(i, false);
} else {
setPropertyValue(valueObj, key, newElement);
}
}
} else {
final String[] keys = valueObj.getOwnKeys(false);
for (final String key : keys) {
final Object newElement = walk(valueObj, key, reviver);
if (newElement == ScriptRuntime.UNDEFINED) {
valueObj.delete(key, false);
} else {
setPropertyValue(valueObj, key, newElement);
if (newElement == ScriptRuntime.UNDEFINED) {
valueObj.delete(key, false);
} else {
setPropertyValue(valueObj, key, newElement);
}
}
}
}

View File

@ -224,7 +224,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
* same combination of prototype and property map.
*
* @param proto the prototype object
* @param map intial {@link PropertyMap}
* @param map initial {@link PropertyMap}
*/
protected ScriptObject(final ScriptObject proto, final PropertyMap map) {
this(map);
@ -287,9 +287,10 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
*/
public void addBoundProperties(final ScriptObject source, final Property[] properties) {
PropertyMap newMap = this.getMap();
final boolean extensible = newMap.isExtensible();
for (final Property property : properties) {
newMap = addBoundProperty(newMap, source, property);
newMap = addBoundProperty(newMap, source, property, extensible);
}
this.setMap(newMap);
@ -302,13 +303,18 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
* @param propMap the property map
* @param source the source object
* @param property the property to be added
* @param extensible whether the current object is extensible or not
* @return the new property map
*/
protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property) {
protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property, final boolean extensible) {
PropertyMap newMap = propMap;
final String key = property.getKey();
final Property oldProp = newMap.findProperty(key);
if (oldProp == null) {
if (! extensible) {
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
}
if (property instanceof UserAccessorProperty) {
// Note: we copy accessor functions to this object which is semantically different from binding.
final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
@ -337,11 +343,15 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
*/
public void addBoundProperties(final Object source, final AccessorProperty[] properties) {
PropertyMap newMap = this.getMap();
final boolean extensible = newMap.isExtensible();
for (final AccessorProperty property : properties) {
final String key = property.getKey();
if (newMap.findProperty(key) == null) {
if (! extensible) {
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
}
newMap = newMap.addPropertyBind(property, source);
}
}
@ -1247,7 +1257,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
if (oldProto != newProto) {
proto = newProto;
// Let current listeners know that the protototype has changed and set our map
// Let current listeners know that the prototype has changed and set our map
final PropertyListeners listeners = getMap().getListeners();
if (listeners != null) {
listeners.protoChanged();
@ -1442,7 +1452,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
* in {@link ScriptFunction} for hasInstance implementation, walks
* the proto chain
*
* @param instance instace to check
* @param instance instance to check
* @return true if 'instance' is an instance of this object
*/
public boolean isInstance(final ScriptObject instance) {
@ -1859,7 +1869,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
* @param desc the call site descriptor.
* @param request the link request
*
* @return GuardedInvocation to be invoed at call site.
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
return notAFunction();

View File

@ -69,7 +69,7 @@ public final class Bootstrap {
private static final MethodHandle VOID_TO_OBJECT = MH.constant(Object.class, ScriptRuntime.UNDEFINED);
/**
* The default dynalink relink threshold for megamorphisism is 8. In the case
* The default dynalink relink threshold for megamorphism is 8. In the case
* of object fields only, it is fine. However, with dual fields, in order to get
* performance on benchmarks with a lot of object instantiation and then field
* reassignment, it can take slightly more relinks to become stable with type
@ -213,7 +213,7 @@ public final class Bootstrap {
* @param type method type
* @param programPoint program point to bind to callsite
*
* @return callsite for a math instrinic node
* @return callsite for a math intrinsic node
*/
public static CallSite mathBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int programPoint) {
final MethodHandle mh;

View File

@ -571,7 +571,7 @@ final class JavaAdapterBytecodeGenerator {
mv.visitVarInsn(ALOAD, 0);
if (fromFunction && !mi.getName().equals(samName)) {
// Constructors initializing from a ScriptFunction only initialize methods with the SAM name.
// NOTE: if there's a concrete overloaded method sharing the SAM name, it'll be overriden too. This
// NOTE: if there's a concrete overloaded method sharing the SAM name, it'll be overridden too. This
// is a deliberate design choice. All other method handles are initialized to null.
mv.visitInsn(ACONST_NULL);
} else {

View File

@ -500,7 +500,7 @@ public class LinkerCallSite extends ChainedCallSite {
* @param desc callsite descriptor string
* @param args arguments to function
*
* @throws Throwable if invocation failes or throws exception/error
* @throws Throwable if invocation fails or throws exception/error
*/
@SuppressWarnings("unused")
public void traceMiss(final String desc, final Object... args) throws Throwable {

View File

@ -169,7 +169,7 @@ public class NashornBeansLinker implements GuardingDynamicLinker {
}
for (final Class<?> iface : clazz.getInterfaces()) {
// check accessiblity up-front
// check accessibility up-front
if (! Context.isAccessibleClass(iface)) {
continue;
}

View File

@ -274,7 +274,7 @@ public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor
* {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
* generated outside of Nashorn.
* @param flag the tested flag
* @return true if the flag is set, false otherwise (it will be false if the decriptor is not a Nashorn call site
* @return true if the flag is set, false otherwise (it will be false if the descriptor is not a Nashorn call site
* descriptor).
*/
private static boolean isFlag(final CallSiteDescriptor desc, final int flag) {

View File

@ -163,7 +163,7 @@ public final class OptionTemplate implements Comparable<OptionTemplate> {
/**
* Does this option automatically enable another option, i.e. a dependency.
* @return the dependecy or null if non exists
* @return the dependency or null if none exists
*/
public String getDependency() {
return this.dependency;

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8130853: Non-extensible global is not handled property
*
* @test
* @run
*/
// don't allow extensions to global
Object.preventExtensions(this);
try {
eval("var x = 34;");
throw new Error("should have thrown TypeError");
} catch (e) {
if (! (e instanceof TypeError)) {
throw e;
}
}
try {
eval("function func() {}");
throw new Error("should have thrown TypeError");
} catch (e) {
if (! (e instanceof TypeError)) {
throw e;
}
}
function checkLoad(code) {
try {
load({ name: "test", script: code });
throw new Error("should have thrown TypeError for load: " + code);
} catch (e) {
if (! (e instanceof TypeError)) {
throw e;
}
}
}
checkLoad("var y = 55");
checkLoad("function f() {}");
// check script engine eval
var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
var e = new ScriptEngineManager().getEngineByName("nashorn");
var global = e.eval("this");
e.eval("Object.preventExtensions(this);");
try {
e.eval("var myVar = 33;");
throw new Error("should have thrown TypeError");
} catch (e) {
if (! (e.cause.ecmaError instanceof global.TypeError)) {
throw e;
}
}
// Object.bindProperties on arbitrary non-extensible object
var obj = {};
Object.preventExtensions(obj);
try {
Object.bindProperties(obj, { foo: 434 });
throw new Error("should have thrown TypeError");
} catch (e) {
if (! (e instanceof TypeError)) {
throw e;
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8131039: after adding a function property to Object.prototype, JSON.parse with reviver function goes into infinite loop
*
* @test
* @run
*/
Object.prototype.func = function() {}
function identity(k, v) { return v };
var obj = JSON.parse('{\"name\" : \"nashorn\"}', identity);
Assert.assertTrue(obj.name, "nashorn");