This commit is contained in:
Lana Steuck 2016-06-23 21:13:33 +00:00
commit 803a8d9310
12 changed files with 235 additions and 61 deletions

View File

@ -280,12 +280,11 @@ public class ClassGenerator {
addField(cv, name, OBJECT_DESC);
}
@SuppressWarnings("deprecation")
static void newFunction(final MethodGenerator mi, final String objName, final String className, final MemberInfo memInfo, final List<MemberInfo> specs) {
final boolean arityFound = (memInfo.getArity() != MemberInfo.DEFAULT_ARITY);
loadFunctionName(mi, memInfo.getName());
mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className, memInfo.getJavaName(), memInfo.getJavaDesc()));
mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className, memInfo.getJavaName(), memInfo.getJavaDesc(), false));
assert specs != null;
if (!specs.isEmpty()) {
@ -306,7 +305,6 @@ public class ClassGenerator {
mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETDOCUMENTATIONKEY, SCRIPTFUNCTION_SETDOCUMENTATIONKEY_DESC);
}
@SuppressWarnings("deprecation")
static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo memInfo) {
final String propertyName = memInfo.getName();
// stack: Collection
@ -319,13 +317,13 @@ public class ClassGenerator {
mi.push(memInfo.getAttributes());
// setup getter method handle
String javaName = GETTER_PREFIX + memInfo.getJavaName();
mi.visitLdcInsn(new Handle(H_INVOKEVIRTUAL, className, javaName, getterDesc(memInfo)));
mi.visitLdcInsn(new Handle(H_INVOKEVIRTUAL, className, javaName, getterDesc(memInfo), false));
// setup setter method handle
if (memInfo.isFinal()) {
mi.pushNull();
} else {
javaName = SETTER_PREFIX + memInfo.getJavaName();
mi.visitLdcInsn(new Handle(H_INVOKEVIRTUAL, className, javaName, setterDesc(memInfo)));
mi.visitLdcInsn(new Handle(H_INVOKEVIRTUAL, className, javaName, setterDesc(memInfo), false));
}
// property = AccessorProperty.create(key, flags, getter, setter);
mi.invokeStatic(ACCESSORPROPERTY_TYPE, ACCESSORPROPERTY_CREATE, ACCESSORPROPERTY_CREATE_DESC);
@ -336,7 +334,6 @@ public class ClassGenerator {
// stack: Collection
}
@SuppressWarnings("deprecation")
static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo getter, final MemberInfo setter) {
final String propertyName = getter.getName();
// stack: Collection
@ -349,13 +346,13 @@ public class ClassGenerator {
mi.push(getter.getAttributes());
// setup getter method handle
mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className,
getter.getJavaName(), getter.getJavaDesc()));
getter.getJavaName(), getter.getJavaDesc(), false));
// setup setter method handle
if (setter == null) {
mi.pushNull();
} else {
mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className,
setter.getJavaName(), setter.getJavaDesc()));
setter.getJavaName(), setter.getJavaDesc(), false));
}
// property = AccessorProperty.create(key, flags, getter, setter);
mi.invokeStatic(ACCESSORPROPERTY_TYPE, ACCESSORPROPERTY_CREATE, ACCESSORPROPERTY_CREATE_DESC);

View File

@ -178,7 +178,6 @@ public class ConstructorGenerator extends ClassGenerator {
}
}
@SuppressWarnings("deprecation")
private void callSuper(final MethodGenerator mi) {
String superClass, superDesc;
mi.loadThis();
@ -192,7 +191,7 @@ public class ConstructorGenerator extends ClassGenerator {
superClass = SCRIPTFUNCTION_TYPE;
superDesc = (memberCount > 0) ? SCRIPTFUNCTION_INIT_DESC4 : SCRIPTFUNCTION_INIT_DESC3;
mi.loadLiteral(constructor.getName());
mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc()));
mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc(), false));
loadMap(mi);
mi.memberInfoArray(scriptClassInfo.getJavaName(), specs); //pushes null if specs empty
}

View File

@ -390,7 +390,6 @@ public class MethodGenerator extends MethodVisitor {
return EMPTY_LINK_LOGIC_TYPE.equals(type);
}
@SuppressWarnings("deprecation")
void memberInfoArray(final String className, final List<MemberInfo> mis) {
if (mis.isEmpty()) {
pushNull();
@ -405,7 +404,7 @@ public class MethodGenerator extends MethodVisitor {
push(pos++);
visitTypeInsn(NEW, SPECIALIZATION_TYPE);
dup();
visitLdcInsn(new Handle(H_INVOKESTATIC, className, mi.getJavaName(), mi.getJavaDesc()));
visitLdcInsn(new Handle(H_INVOKESTATIC, className, mi.getJavaName(), mi.getJavaDesc(), false));
final Type linkLogicClass = mi.getLinkLogicClass();
final boolean linkLogic = !linkLogicIsEmpty(linkLogicClass);
final String ctor = linkLogic ? SPECIALIZATION_INIT3 : SPECIALIZATION_INIT2;

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Simple Java identifier name pattern checker. You can check
// class, method and variable names in java sources to confirm
// to specified patterns. Default check functions just check for
// 'too short' names. You can customize checkXYZName functions to
// have arbitrary name pattern checks.
// Usage: jjs checknames.js -- <directory>
if (arguments.length == 0) {
print("Usage: jjs checknames.js -- <directory>");
exit(1);
}
// Java types used
var File = Java.type("java.io.File");
var Files = Java.type("java.nio.file.Files");
var StringArray = Java.type("java.lang.String[]");
var ToolProvider = Java.type("javax.tools.ToolProvider");
var Tree = Java.type("com.sun.source.tree.Tree");
var Trees = Java.type("com.sun.source.util.Trees");
var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
// replace these checkXYZ functions with checks you want!
function checkClassName(name) {
return name.length < 3;
}
function checkMethodName(name) {
return name.length < 3;
}
function checkVarName(name) {
return name.length < 3;
}
function checkNames() {
// get the system compiler tool
var compiler = ToolProvider.systemJavaCompiler;
// get standard file manager
var fileMgr = compiler.getStandardFileManager(null, null, null);
// Using Java.to convert script array (arguments) to a Java String[]
var compUnits = fileMgr.getJavaFileObjects(Java.to(arguments, StringArray));
// create a new compilation task
var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
var sourcePositions = Trees.instance(task).sourcePositions;
// subclass SimpleTreeVisitor
var NameChecker = Java.extend(TreeScanner);
var visitor = new NameChecker() {
report: function(node) {
var pos = sourcePositions.getStartPosition(this.compUnit, node);
var line = this.lineMap.getLineNumber(pos);
var col = this.lineMap.getColumnNumber(pos);
print("Too short name: " + node.name + " @ " + this.fileName + ":" + line + ":" + col);
},
// override to capture information on current compilation unit
visitCompilationUnit: function(compUnit, p) {
this.compUnit = compUnit;
this.lineMap = compUnit.lineMap;
this.fileName = compUnit.sourceFile.name;
return Java.super(visitor).visitCompilationUnit(compUnit, p);
},
// override to check class name
visitClass: function(node, p) {
if (checkClassName(node.simpleName.toString())) {
this.report(node);
}
return Java.super(visitor).visitClass(node, p);
},
// override to check method name
visitMethod: function(node, p) {
if (checkMethodName(node.name.toString())) {
this.report(node);
}
return Java.super(visitor).visitMethod(node, p);
},
// override to check variable name
visitVariable: function(node, p) {
if (checkVarName(node.name.toString())) {
this.report(node);
}
return Java.super(visitor).visitVariable(node, p);
}
}
for each (var cu in task.parse()) {
cu.accept(visitor, null);
}
}
// for each ".java" file in directory (recursively).
function main(dir) {
var totalCount = 0;
Files.walk(dir.toPath()).
forEach(function(p) {
var name = p.toFile().absolutePath;
if (name.endsWith(".java")) {
checkNames(p);
}
});
}
main(new File(arguments[0]));

View File

@ -28,7 +28,6 @@ package jdk.nashorn.internal;
/**
* Class that exposes the current state of asserts.
*/
@SuppressWarnings("all")
public final class AssertsEnabled {
private static boolean assertsEnabled = false;
static {

View File

@ -32,6 +32,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.GETFIELD;
import static jdk.internal.org.objectweb.asm.Opcodes.GETSTATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.GOTO;
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEINTERFACE;
import static jdk.internal.org.objectweb.asm.Opcodes.IFEQ;
import static jdk.internal.org.objectweb.asm.Opcodes.IFGE;
import static jdk.internal.org.objectweb.asm.Opcodes.IFGT;
@ -170,12 +171,10 @@ public class MethodEmitter {
}
/** Bootstrap for normal indy:s */
@SuppressWarnings("deprecation")
private static final Handle LINKERBOOTSTRAP = new Handle(H_INVOKESTATIC, Bootstrap.BOOTSTRAP.className(), Bootstrap.BOOTSTRAP.name(), Bootstrap.BOOTSTRAP.descriptor());
private static final Handle LINKERBOOTSTRAP = new Handle(H_INVOKESTATIC, Bootstrap.BOOTSTRAP.className(), Bootstrap.BOOTSTRAP.name(), Bootstrap.BOOTSTRAP.descriptor(), false);
/** Bootstrap for array populators */
@SuppressWarnings("deprecation")
private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor());
private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor(), false);
/**
* Constructor - internal use from ClassEmitter only
@ -1007,10 +1006,10 @@ public class MethodEmitter {
*
* @return the method emitter
*/
@SuppressWarnings("deprecation")
MethodEmitter loadHandle(final String className, final String methodName, final String descName, final EnumSet<Flag> flags) {
final int flag = Flag.getValue(flags);
debug("load handle ");
pushType(Type.OBJECT.ldc(method, new Handle(Flag.getValue(flags), className, methodName, descName)));
pushType(Type.OBJECT.ldc(method, new Handle(flag, className, methodName, descName, flag == H_INVOKEINTERFACE)));
return this;
}

View File

@ -2474,14 +2474,14 @@ public final class Global extends Scope {
}
@Override
protected FindProperty findProperty(final Object key, final boolean deep, final ScriptObject start) {
if (lexicalScope != null && start != this && start.isScope()) {
protected FindProperty findProperty(final Object key, final boolean deep, boolean isScope, final ScriptObject start) {
if (lexicalScope != null && isScope) {
final FindProperty find = lexicalScope.findProperty(key, false);
if (find != null) {
return find;
}
}
return super.findProperty(key, deep, start);
return super.findProperty(key, deep, isScope, start);
}
@Override
@ -2854,8 +2854,7 @@ public final class Global extends Scope {
sb.append("$Constructor");
final Class<?> funcClass = Class.forName(sb.toString());
@SuppressWarnings("deprecation")
final T res = clazz.cast(funcClass.newInstance());
final T res = clazz.cast(funcClass.getDeclaredConstructor().newInstance());
if (res instanceof ScriptFunction) {
// All global constructor prototypes are not-writable,
@ -2871,8 +2870,12 @@ public final class Global extends Scope {
res.setIsBuiltin();
return res;
} catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
} catch (final Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException)e;
} else {
throw new RuntimeException(e);
}
}
}
@ -2882,14 +2885,17 @@ public final class Global extends Scope {
final String className = PACKAGE_PREFIX + name + "$Prototype";
final Class<?> funcClass = Class.forName(className);
@SuppressWarnings("deprecation")
final ScriptObject res = (ScriptObject) funcClass.newInstance();
final ScriptObject res = (ScriptObject) funcClass.getDeclaredConstructor().newInstance();
res.setIsBuiltin();
res.setInitialProto(prototype);
return res;
} catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
} catch (final Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException)e;
} else {
throw new RuntimeException(e);
}
}
}

View File

@ -775,7 +775,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
* @return FindPropertyData or null if not found.
*/
public final FindProperty findProperty(final Object key, final boolean deep) {
return findProperty(key, deep, this);
return findProperty(key, deep, false, this);
}
/**
@ -791,12 +791,12 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
* @see jdk.nashorn.internal.objects.NativeArray
*
* @param key Property key.
* @param deep Whether the search should look up proto chain.
* @param deep true if the search should look up proto chain
* @param isScope true if this is a scope access
* @param start the object on which the lookup was originally initiated
*
* @return FindPropertyData or null if not found.
*/
protected FindProperty findProperty(final Object key, final boolean deep, final ScriptObject start) {
protected FindProperty findProperty(final Object key, final boolean deep, boolean isScope, final ScriptObject start) {
final PropertyMap selfMap = getMap();
final Property property = selfMap.findProperty(key);
@ -807,7 +807,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
if (deep) {
final ScriptObject myProto = getProto();
final FindProperty find = myProto == null ? null : myProto.findProperty(key, true, start);
final FindProperty find = myProto == null ? null : myProto.findProperty(key, true, isScope, start);
// checkSharedProtoMap must be invoked after myProto.checkSharedProtoMap to propagate
// shared proto invalidation up the prototype chain. It also must be invoked when prototype is null.
checkSharedProtoMap();
@ -1977,7 +1977,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
return findMegaMorphicGetMethod(desc, name, operation == StandardOperation.GET_METHOD);
}
final FindProperty find = findProperty(name, true);
final FindProperty find = findProperty(name, true, NashornCallSiteDescriptor.isScope(desc), this);
MethodHandle mh;
if (find == null) {
@ -2035,7 +2035,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
}
private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: ", desc, " ", name + " ", isMethod);
final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, NashornCallSiteDescriptor.isScope(desc));
final MethodHandle guard = getScriptObjectGuard(desc.getMethodType(), true);
return new GuardedInvocation(invoker, guard);
@ -2043,7 +2043,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
@SuppressWarnings("unused")
private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
final FindProperty find = findProperty(key, true);
final FindProperty find = findProperty(key, true, isScope, this);
if (find != null) {
return find.getObjectValue();
}
@ -2181,7 +2181,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
*
* toString = function() { print("global toString"); } // don't affect Object.prototype.toString
*/
FindProperty find = findProperty(name, true, this);
FindProperty find = findProperty(name, true, NashornCallSiteDescriptor.isScope(desc), this);
// If it's not a scope search, then we don't want any inherited properties except those with user defined accessors.
if (find != null && find.isInherited() && !find.getProperty().isAccessorProperty()) {
@ -2258,6 +2258,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
}
private GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic setter: ", desc, " ", name);
final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
//never bother with ClassCastExceptionGuard for megamorphic callsites
final GuardedInvocation inv = findSetIndexMethod(getClass(), desc, false, type);
@ -2734,7 +2735,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
if (isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
if (object.getMap().containsArrayKeys()) {
final FindProperty find = object.findProperty(key, false, this);
final FindProperty find = object.findProperty(key, false);
if (find != null) {
return getIntValue(find, programPoint);
@ -2805,7 +2806,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
if (isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
if (object.getMap().containsArrayKeys()) {
final FindProperty find = object.findProperty(key, false, this);
final FindProperty find = object.findProperty(key, false);
if (find != null) {
return getDoubleValue(find, programPoint);
}
@ -2875,7 +2876,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
if (isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
if (object.getMap().containsArrayKeys()) {
final FindProperty find = object.findProperty(key, false, this);
final FindProperty find = object.findProperty(key, false);
if (find != null) {
return find.getObjectValue();

View File

@ -704,7 +704,17 @@ public final class ScriptRuntime {
if (property != null) {
if (obj instanceof ScriptObject) {
obj = ((ScriptObject)obj).get(property);
// this is a scope identifier
assert property instanceof String;
final ScriptObject sobj = (ScriptObject) obj;
final FindProperty find = sobj.findProperty(property, true, true, sobj);
if (find != null) {
obj = find.getObjectValue();
} else {
obj = sobj.invokeNoSuchProperty(property, false, UnwarrantedOptimismException.INVALID_PROGRAM_POINT);
}
if(Global.isLocationPropertyPlaceholder(obj)) {
if(CompilerConstants.__LINE__.name().equals(property)) {
obj = 0;

View File

@ -193,20 +193,20 @@ public final class WithObject extends Scope {
*
* @param key Property key.
* @param deep Whether the search should look up proto chain.
* @param isScope true if is this a scope access
* @param start the object on which the lookup was originally initiated
*
* @return FindPropertyData or null if not found.
*/
@Override
protected FindProperty findProperty(final Object key, final boolean deep, final ScriptObject start) {
protected FindProperty findProperty(final Object key, final boolean deep, boolean isScope, final ScriptObject start) {
// We call findProperty on 'expression' with 'expression' itself as start parameter.
// This way in ScriptObject.setObject we can tell the property is from a 'with' expression
// (as opposed from another non-scope object in the proto chain such as Object.prototype).
final FindProperty exprProperty = expression.findProperty(key, true, expression);
final FindProperty exprProperty = expression.findProperty(key, true, false, expression);
if (exprProperty != null) {
return exprProperty;
}
return super.findProperty(key, deep, start);
return super.findProperty(key, deep, isScope, start);
}
@Override

View File

@ -191,18 +191,16 @@ final class JavaAdapterBytecodeGenerator {
private static final Call RUN = interfaceCallNoLookup(Runnable.class, "run", void.class);
// ASM handle to the bootstrap method
@SuppressWarnings("deprecation")
private static final Handle BOOTSTRAP_HANDLE = new Handle(H_INVOKESTATIC,
Type.getInternalName(JavaAdapterServices.class), "bootstrap",
MethodType.methodType(CallSite.class, Lookup.class, String.class,
MethodType.class, int.class).toMethodDescriptorString());
MethodType.class, int.class).toMethodDescriptorString(), false);
// ASM handle to the bootstrap method for array populator
@SuppressWarnings("deprecation")
private static final Handle CREATE_ARRAY_BOOTSTRAP_HANDLE = new Handle(H_INVOKESTATIC,
Type.getInternalName(JavaAdapterServices.class), "createArrayBootstrap",
MethodType.methodType(CallSite.class, Lookup.class, String.class,
MethodType.class).toMethodDescriptorString());
MethodType.class).toMethodDescriptorString(), false);
// Field type names used in the generated bytecode
private static final String SCRIPT_OBJECT_TYPE_DESCRIPTOR = SCRIPT_OBJECT_TYPE.getDescriptor();
@ -1061,13 +1059,12 @@ final class JavaAdapterBytecodeGenerator {
endMethod(mv);
}
@SuppressWarnings("deprecation")
private void generateFinalizerOverride() {
final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, "finalize",
VOID_METHOD_DESCRIPTOR, null, null));
// Overridden finalizer will take a MethodHandle to the finalizer delegating method, ...
mv.aconst(new Handle(Opcodes.H_INVOKESTATIC, generatedClassName, FINALIZER_DELEGATE_NAME,
FINALIZER_DELEGATE_METHOD_DESCRIPTOR));
FINALIZER_DELEGATE_METHOD_DESCRIPTOR, false));
mv.visitVarInsn(ALOAD, 0);
// ...and invoke it through JavaAdapterServices.invokeNoPermissions
INVOKE_NO_PERMISSIONS.invoke(mv);

View File

@ -46,8 +46,8 @@ import static org.testng.Assert.assertEquals;
public class LexicalBindingTest {
final static String LANGUAGE_ES6 = "--language=es6";
final static int NUMBER_OF_CONTEXTS = 20;
final static int MEGAMORPHIC_LOOP_COUNT = 20;
final static int NUMBER_OF_CONTEXTS = 40;
final static int MEGAMORPHIC_LOOP_COUNT = 40;
/**
* Test access to global var-declared variables for shared script classes with multiple globals.
@ -57,19 +57,21 @@ public class LexicalBindingTest {
final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
final ScriptEngine e = factory.getScriptEngine();
final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
final String sharedScript = "foo";
final String sharedScript1 = "foo";
final String sharedScript2 = "bar = foo; bar";
for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
final ScriptContext context = contexts[i] = new SimpleScriptContext();
final Bindings b = e.createBindings();
context.setBindings(b, ScriptContext.ENGINE_SCOPE);
assertEquals(e.eval("var foo = '" + i + "';", context), null);
assertEquals(e.eval("var foo = '" + i + "'; var bar;", context), null);
}
for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
final ScriptContext context = contexts[i];
assertEquals(e.eval(sharedScript, context), String.valueOf(i));
assertEquals(e.eval(sharedScript1, context), String.valueOf(i));
assertEquals(e.eval(sharedScript2, context), String.valueOf(i));
}
}
@ -81,19 +83,21 @@ public class LexicalBindingTest {
final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
final String sharedScript = "foo";
final String sharedScript1 = "foo";
final String sharedScript2 = "bar = foo; bar";
for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
final ScriptContext context = contexts[i] = new SimpleScriptContext();
final Bindings b = e.createBindings();
context.setBindings(b, ScriptContext.ENGINE_SCOPE);
assertEquals(e.eval("let foo = '" + i + "';", context), null);
assertEquals(e.eval("let foo = '" + i + "'; let bar; ", context), null);
}
for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
final ScriptContext context = contexts[i];
assertEquals(e.eval(sharedScript, context), String.valueOf(i));
assertEquals(e.eval(sharedScript1, context), String.valueOf(i));
assertEquals(e.eval(sharedScript2, context), String.valueOf(i));
}
}
@ -182,6 +186,27 @@ public class LexicalBindingTest {
assertEquals(e.eval(sharedScript, newCtxt), "newer context");
}
/**
* Make sure lexically defined variables are accessible in other scripts.
*/
@Test
public void lexicalScopeTest() throws ScriptException {
final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
e.eval("let x; const y = 'world';");
assertEquals(e.eval("x = 'hello'"), "hello");
assertEquals(e.eval("typeof x"), "string");
assertEquals(e.eval("typeof y"), "string");
assertEquals(e.eval("x"), "hello");
assertEquals(e.eval("y"), "world");
assertEquals(e.eval("typeof this.x"), "undefined");
assertEquals(e.eval("typeof this.y"), "undefined");
assertEquals(e.eval("this.x"), null);
assertEquals(e.eval("this.y"), null);
}
private static class ScriptRunner implements Runnable {
final ScriptEngine engine;