rhino1.7.7.testsrc.org.mozilla.javascript.tests.Bug708801Test Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rhino Show documentation
Show all versions of rhino Show documentation
Rhino is an open-source implementation of JavaScript written entirely in Java. It is typically
embedded into Java applications to provide scripting to end users.
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
*
*/
package org.mozilla.javascript.tests;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextAction;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.IRFactory;
import org.mozilla.javascript.Parser;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.ast.AstRoot;
import org.mozilla.javascript.ast.FunctionNode;
import org.mozilla.javascript.ast.ScriptNode;
import org.mozilla.javascript.optimizer.Codegen;
import org.mozilla.javascript.optimizer.OptFunctionNode;
/**
* @author André Bargull
*
*/
public class Bug708801Test {
private static final ContextFactory factory = new ContextFactory() {
static final int COMPILER_MODE = 9;
@Override
protected Context makeContext() {
Context cx = super.makeContext();
cx.setLanguageVersion(Context.VERSION_1_8);
cx.setOptimizationLevel(COMPILER_MODE);
return cx;
}
};
private static abstract class Action implements ContextAction {
protected Context cx;
protected ScriptableObject scope;
@SuppressWarnings("unused")
protected Object evaluate(String s) {
return cx.evaluateString(scope, s, "", 1, null);
}
/**
* Compiles {@code source} and returns the transformed and optimized
* {@link ScriptNode}
*/
protected ScriptNode compile(CharSequence source) {
final String mainMethodClassName = "Main";
final String scriptClassName = "Main";
CompilerEnvirons compilerEnv = new CompilerEnvirons();
compilerEnv.initFromContext(cx);
ErrorReporter compilationErrorReporter = compilerEnv
.getErrorReporter();
Parser p = new Parser(compilerEnv, compilationErrorReporter);
AstRoot ast = p.parse(source.toString(), "", 1);
IRFactory irf = new IRFactory(compilerEnv);
ScriptNode tree = irf.transformTree(ast);
Codegen codegen = new Codegen();
codegen.setMainMethodClass(mainMethodClassName);
codegen.compileToClassFile(compilerEnv, scriptClassName, tree,
tree.getEncodedSource(), false);
return tree;
}
/**
* Checks every variable {@code v} in {@code source} is marked as a
* number-variable iff {@code numbers} contains {@code v}
*/
protected void assertNumberVars(CharSequence source, String... numbers) {
// wrap source in function
ScriptNode tree = compile("function f(o, fn){" + source + "}");
FunctionNode fnode = tree.getFunctionNode(0);
assertNotNull(fnode);
OptFunctionNode opt = OptFunctionNode.get(fnode);
assertNotNull(opt);
assertSame(fnode, opt.fnode);
for (int i = 0, c = fnode.getParamCount(); i < c; ++i) {
assertTrue(opt.isParameter(i));
assertFalse(opt.isNumberVar(i));
}
Set set = new HashSet(asList(numbers));
for (int i = fnode.getParamCount(), c = fnode.getParamAndVarCount(); i < c; ++i) {
assertFalse(opt.isParameter(i));
String name = fnode.getParamOrVarName(i);
String msg = format("{%s -> number? = %b}", name, opt.isNumberVar(i));
assertEquals(msg, set.contains(name), opt.isNumberVar(i));
}
}
public final Object run(Context cx) {
this.cx = cx;
scope = cx.initStandardObjects(null, true);
return run();
}
protected abstract Object run();
}
@Test
public void testIncDec() {
factory.call(new Action() {
@Override
protected Object run() {
// pre-inc
assertNumberVars("var b; ++b");
assertNumberVars("var b=0; ++b", "b");
assertNumberVars("var b; ++[1][++b]");
assertNumberVars("var b=0; ++[1][++b]", "b");
assertNumberVars("var b; ++[1][b=0,++b]", "b");
// pre-dec
assertNumberVars("var b; --b");
assertNumberVars("var b=0; --b", "b");
assertNumberVars("var b; --[1][--b]");
assertNumberVars("var b=0; --[1][--b]", "b");
assertNumberVars("var b; --[1][b=0,--b]", "b");
// post-inc
assertNumberVars("var b; b++");
assertNumberVars("var b=0; b++", "b");
assertNumberVars("var b; [1][b++]++");
assertNumberVars("var b=0; [1][b++]++", "b");
assertNumberVars("var b; [1][b=0,b++]++", "b");
// post-dec
assertNumberVars("var b; b--");
assertNumberVars("var b=0; b--", "b");
assertNumberVars("var b; [1][b--]--");
assertNumberVars("var b=0; [1][b--]--", "b");
assertNumberVars("var b; [1][b=0,b--]--", "b");
return null;
}
});
}
@Test
public void testTypeofName() {
factory.call(new Action() {
@Override
protected Object run() {
// Token.TYPEOFNAME
assertNumberVars("var b; typeof b");
assertNumberVars("var b=0; typeof b", "b");
assertNumberVars("var b; if(new Date()<0){b=0} typeof b");
// Token.TYPEOF
assertNumberVars("var b; typeof (b,b)");
assertNumberVars("var b=0; typeof (b,b)", "b");
assertNumberVars("var b; if(new Date()<0){b=0} typeof (b,b)");
return null;
}
});
}
@Test
public void testEval() {
factory.call(new Action() {
@Override
protected Object run() {
// direct eval => requires activation
assertNumberVars("var b; eval('typeof b')");
assertNumberVars("var b=0; eval('typeof b')");
assertNumberVars("var b; if(new Date()<0){b=0} eval('typeof b')");
// indirect eval => requires no activation
assertNumberVars("var b; (1,eval)('typeof b');");
assertNumberVars("var b=0; (1,eval)('typeof b')", "b");
assertNumberVars(
"var b; if(new Date()<0){b=0} (1,eval)('typeof b')",
"b");
return null;
}
});
}
@Test
public void testRelOp() {
factory.call(new Action() {
@Override
protected Object run() {
// relational operators: <, <=, >, >=
assertNumberVars("var b = 1 < 1");
assertNumberVars("var b = 1 <= 1");
assertNumberVars("var b = 1 > 1");
assertNumberVars("var b = 1 >= 1");
// equality operators: ==, !=, ===, !==
assertNumberVars("var b = 1 == 1");
assertNumberVars("var b = 1 != 1");
assertNumberVars("var b = 1 === 1");
assertNumberVars("var b = 1 !== 1");
return null;
}
});
}
@Test
public void testMore() {
factory.call(new Action() {
@Override
protected Object run() {
// simple assignment:
assertNumberVars("var b");
assertNumberVars("var b = 1", "b");
assertNumberVars("var b = 'a'");
assertNumberVars("var b = true");
assertNumberVars("var b = /(?:)/");
assertNumberVars("var b = o");
assertNumberVars("var b = fn");
// use before assignment
assertNumberVars("b; var b = 1");
assertNumberVars("b || c; var b = 1, c = 2");
assertNumberVars("if(b) var b = 1");
assertNumberVars("typeof b; var b=1");
assertNumberVars("typeof (b,b); var b=1");
// relational operators: in, instanceof
assertNumberVars("var b = 1 instanceof 1");
assertNumberVars("var b = 1 in 1");
// other operators with nested comma expression:
assertNumberVars("var b = !(1,1)");
assertNumberVars("var b = typeof(1,1)");
assertNumberVars("var b = void(1,1)");
// nested assignment
assertNumberVars("var b = 1; var f = (b = 'a')");
// let expression:
assertNumberVars("var b = let(x=1) x", "b", "x");
assertNumberVars("var b = let(x=1,y=1) x,y", "b", "x", "y");
// conditional operator:
assertNumberVars("var b = 0 ? 1 : 2", "b");
assertNumberVars("var b = 'a' ? 1 : 2", "b");
// comma expression:
assertNumberVars("var b = (0,1)", "b");
assertNumberVars("var b = ('a',1)", "b");
// assignment operations:
assertNumberVars("var b; var c=0; b=c", "b", "c");
assertNumberVars("var b; var c=0; b=(c=1)", "b", "c");
assertNumberVars("var b; var c=0; b=(c='a')");
assertNumberVars("var b; var c=0; b=(c+=1)", "b", "c");
assertNumberVars("var b; var c=0; b=(c*=1)", "b", "c");
assertNumberVars("var b; var c=0; b=(c%=1)", "b", "c");
assertNumberVars("var b; var c=0; b=(c/=1)", "b", "c");
// property access:
assertNumberVars("var b; b=(o.p)");
assertNumberVars("var b; b=(o.p=1)", "b");
assertNumberVars("var b; b=(o.p+=1)");
assertNumberVars("var b; b=(o['p']=1)", "b");
assertNumberVars("var b; b=(o['p']+=1)");
assertNumberVars("var b; var o = {p:0}; b=(o.p=1)", "b");
assertNumberVars("var b; var o = {p:0}; b=(o.p+=1)");
assertNumberVars("var b; var o = {p:0}; b=(o['p']=1)", "b");
assertNumberVars("var b; var o = {p:0}; b=(o['p']+=1)");
assertNumberVars("var b = 1; b.p = true", "b");
assertNumberVars("var b = 1; b.p", "b");
assertNumberVars("var b = 1; b.p()", "b");
assertNumberVars("var b = 1; b[0] = true", "b");
assertNumberVars("var b = 1; b[0]", "b");
assertNumberVars("var b = 1; b[0]()", "b");
// assignment (global)
assertNumberVars("var b = foo");
assertNumberVars("var b = foo1=1", "b");
assertNumberVars("var b = foo2+=1");
// boolean operators:
assertNumberVars("var b = 1||2", "b");
assertNumberVars("var b; var c=1; b=c||2", "b", "c");
assertNumberVars("var b; var c=1; b=c||c||2", "b", "c");
assertNumberVars("var b = 1&&2", "b");
assertNumberVars("var b; var c=1; b=c&&2", "b", "c");
assertNumberVars("var b; var c=1; b=c&&c&&2", "b", "c");
// bit not:
assertNumberVars("var b = ~0", "b");
assertNumberVars("var b = ~o", "b");
assertNumberVars("var b; var c=1; b=~c", "b", "c");
// increment, function call:
assertNumberVars("var b; var g; b = (g=0,g++)", "b", "g");
assertNumberVars("var b; var x = fn(b=1)", "b");
assertNumberVars("var b; var x = fn(b=1).p++", "b", "x");
assertNumberVars("var b; ({1:{}})[b=1].p++", "b");
assertNumberVars("var b; o[b=1]++", "b");
// destructuring
assertNumberVars("var r,s; [r,s] = [1,1]");
assertNumberVars("var r=0, s=0; [r,s] = [1,1]");
assertNumberVars("var r,s; ({a: r, b: s}) = {a:1, b:1}");
assertNumberVars("var r=0, s=0; ({a: r, b: s}) = {a:1, b:1}");
// array comprehension
assertNumberVars("var b=[i*i for each (i in [1,2,3])]");
assertNumberVars("var b=[j*j for each (j in [1,2,3]) if (j>1)]");
return null;
}
});
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy