test/script/trusted/JDK-8006529.js

Wed, 20 Aug 2014 10:25:28 +0200

author
attila
date
Wed, 20 Aug 2014 10:25:28 +0200
changeset 962
ac62e33a99b0
parent 845
cdf42b4b8226
child 963
e2497b11a021
permissions
-rw-r--r--

8044638: Tidy up Nashorn codebase for code standards
8055199: Tidy up Nashorn codebase for code standards (August 2014)
Reviewed-by: lagergren, sundar

attila@62 1 /*
attila@62 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
attila@62 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
attila@962 4 *
attila@62 5 * This code is free software; you can redistribute it and/or modify it
attila@62 6 * under the terms of the GNU General Public License version 2 only, as
attila@62 7 * published by the Free Software Foundation.
attila@962 8 *
attila@62 9 * This code is distributed in the hope that it will be useful, but WITHOUT
attila@62 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
attila@62 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
attila@62 12 * version 2 for more details (a copy is included in the LICENSE file that
attila@62 13 * accompanied this code).
attila@962 14 *
attila@62 15 * You should have received a copy of the GNU General Public License version
attila@62 16 * 2 along with this work; if not, write to the Free Software Foundation,
attila@62 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
attila@962 18 *
attila@62 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
attila@62 20 * or visit www.oracle.com if you need additional information or have any
attila@62 21 * questions.
attila@62 22 */
attila@62 23
attila@62 24 /**
attila@62 25 * JDK-8006529 : Methods should not always get callee parameter, and they
attila@62 26 * should not be too eager in creation of scopes.
attila@62 27 *
attila@62 28 * @test
attila@62 29 * @run
attila@62 30 */
attila@62 31
sundar@82 32 /*
sundar@82 33 * This test script depends on nashorn Compiler internals. It uses reflection
sundar@82 34 * to get access to private field and many public methods of Compiler and
sundar@82 35 * FunctionNode classes. Note that this is trusted code and access to such
attila@962 36 * internal package classes and methods is okay. But, if you modify any
sundar@82 37 * Compiler or FunctionNode class, you may have to revisit this script.
sundar@82 38 * We cannot use direct Java class (via dynalink bean linker) to Compiler
sundar@82 39 * and FunctionNode because of package-access check and so reflective calls.
sundar@82 40 */
sundar@82 41
sundar@468 42 var forName = java.lang.Class["forName(String)"];
sundar@468 43 var Parser = forName("jdk.nashorn.internal.parser.Parser").static
sundar@468 44 var Compiler = forName("jdk.nashorn.internal.codegen.Compiler").static
sundar@468 45 var Context = forName("jdk.nashorn.internal.runtime.Context").static
sundar@468 46 var ScriptEnvironment = forName("jdk.nashorn.internal.runtime.ScriptEnvironment").static
sundar@468 47 var Source = forName("jdk.nashorn.internal.runtime.Source").static
sundar@468 48 var FunctionNode = forName("jdk.nashorn.internal.ir.FunctionNode").static
sundar@468 49 var Block = forName("jdk.nashorn.internal.ir.Block").static
sundar@468 50 var VarNode = forName("jdk.nashorn.internal.ir.VarNode").static
sundar@468 51 var ExpressionStatement = forName("jdk.nashorn.internal.ir.ExpressionStatement").static
sundar@468 52 var UnaryNode = forName("jdk.nashorn.internal.ir.UnaryNode").static
sundar@468 53 var BinaryNode = forName("jdk.nashorn.internal.ir.BinaryNode").static
sundar@468 54 var ThrowErrorManager = forName("jdk.nashorn.internal.runtime.Context$ThrowErrorManager").static
sundar@468 55 var ErrorManager = forName("jdk.nashorn.internal.runtime.ErrorManager").static
sundar@468 56 var Debug = forName("jdk.nashorn.internal.runtime.Debug").static
attila@422 57
lagergren@89 58 var parseMethod = Parser.class.getMethod("parse");
attila@422 59 var compileMethod = Compiler.class.getMethod("compile", FunctionNode.class);
attila@422 60 var getBodyMethod = FunctionNode.class.getMethod("getBody");
attila@422 61 var getStatementsMethod = Block.class.getMethod("getStatements");
attila@422 62 var getInitMethod = VarNode.class.getMethod("getInit");
attila@430 63 var getExpressionMethod = ExpressionStatement.class.getMethod("getExpression")
attila@422 64 var rhsMethod = UnaryNode.class.getMethod("rhs")
attila@422 65 var lhsMethod = BinaryNode.class.getMethod("lhs")
attila@422 66 var binaryRhsMethod = BinaryNode.class.getMethod("rhs")
attila@422 67 var debugIdMethod = Debug.class.getMethod("id", java.lang.Object.class)
sundar@82 68
sundar@82 69 // These are method names of methods in FunctionNode class
attila@422 70 var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'needsSelfSymbol', 'isSplit', 'hasEval', 'allVarsInScope', 'isStrict']
sundar@82 71
sundar@82 72 // corresponding Method objects of FunctionNode class
sundar@82 73 var functionNodeMethods = {};
sundar@82 74 // initialize FunctionNode methods
sundar@82 75 (function() {
sundar@82 76 for (var f in allAssertionList) {
sundar@82 77 var method = allAssertionList[f];
sundar@82 78 functionNodeMethods[method] = FunctionNode.class.getMethod(method);
sundar@82 79 }
sundar@82 80 })();
sundar@82 81
attila@422 82 // returns functionNode.getBody().getStatements().get(0)
attila@422 83 function getFirstFunction(functionNode) {
attila@422 84 var f = findFunction(getBodyMethod.invoke(functionNode))
attila@422 85 if (f == null) {
attila@422 86 throw new Error();
attila@422 87 }
attila@422 88 return f;
sundar@82 89 }
sundar@82 90
attila@422 91 function findFunction(node) {
attila@422 92 if(node instanceof Block) {
attila@422 93 var stmts = getStatementsMethod.invoke(node)
attila@422 94 for(var i = 0; i < stmts.size(); ++i) {
attila@422 95 var retval = findFunction(stmts.get(i))
attila@422 96 if(retval != null) {
attila@422 97 return retval;
attila@422 98 }
attila@422 99 }
attila@422 100 } else if(node instanceof VarNode) {
attila@422 101 return findFunction(getInitMethod.invoke(node))
attila@422 102 } else if(node instanceof UnaryNode) {
attila@422 103 return findFunction(rhsMethod.invoke(node))
attila@422 104 } else if(node instanceof BinaryNode) {
attila@422 105 return findFunction(lhsMethod.invoke(node)) || findFunction(binaryRhsMethod.invoke(node))
attila@962 106 } else if(node instanceof ExpressionStatement) {
attila@962 107 return findFunction(getExpressionMethod.invoke(node))
attila@422 108 } else if(node instanceof FunctionNode) {
attila@422 109 return node
attila@422 110 }
sundar@82 111 }
sundar@82 112
attila@422 113 var getContextMethod = Context.class.getMethod("getContext")
attila@422 114 var getEnvMethod = Context.class.getMethod("getEnv")
attila@422 115
hannesw@845 116 var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class)
attila@464 117 var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class)
attila@464 118 var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class)
attila@464 119
attila@962 120 // compile(script) -- compiles a script specified as a string with its
attila@962 121 // source code, returns a jdk.nashorn.internal.ir.FunctionNode object
attila@62 122 // representing it.
sundar@82 123 function compile(source) {
hannesw@845 124 var source = sourceForMethod.invoke(null, "<no name>", source);
attila@422 125
attila@422 126 var env = getEnvMethod.invoke(getContextMethod.invoke(null))
attila@422 127
attila@465 128 var parser = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance());
lagergren@89 129 var func = parseMethod.invoke(parser);
lagergren@89 130
attila@464 131 var compiler = CompilerConstructor.newInstance(env);
lagergren@89 132
attila@422 133 return compileMethod.invoke(compiler, func);
sundar@82 134 };
attila@62 135
attila@62 136 var allAssertions = (function() {
attila@62 137 var allAssertions = {}
attila@62 138 for(var assertion in allAssertionList) {
attila@62 139 allAssertions[allAssertionList[assertion]] = true
attila@62 140 }
attila@62 141 return allAssertions;
attila@62 142 })();
attila@62 143
sundar@82 144
attila@62 145 // test(f[, assertions...]) tests whether all the specified assertions on the
attila@62 146 // passed function node are true.
attila@62 147 function test(f) {
attila@62 148 var assertions = {}
attila@62 149 for(var i = 1; i < arguments.length; ++i) {
attila@62 150 var assertion = arguments[i]
attila@62 151 if(!allAssertions[assertion]) {
attila@62 152 throw "Unknown assertion " + assertion + " for " + f;
attila@62 153 }
attila@62 154 assertions[assertion] = true
attila@62 155 }
attila@62 156 for(var assertion in allAssertions) {
attila@62 157 var expectedValue = !!assertions[assertion]
attila@422 158 var actualValue = functionNodeMethods[assertion].invoke(f)
attila@422 159 if(actualValue !== expectedValue) {
attila@422 160 throw "Expected " + assertion + " === " + expectedValue + ", got " + actualValue + " for " + f + ":" + debugIdMethod.invoke(null, f);
attila@62 161 }
attila@62 162 }
attila@62 163 }
attila@62 164
attila@62 165 // testFirstFn(script[, assertions...] tests whether all the specified
attila@62 166 // assertions are true in the first function in the given script; "script"
attila@62 167 // is a string with the source text of the script.
attila@62 168 function testFirstFn(script) {
sundar@82 169 arguments[0] = getFirstFunction(compile(script))
attila@62 170 test.apply(null, arguments)
attila@62 171 }
attila@62 172
attila@62 173 // ---------------------------------- ACTUAL TESTS START HERE --------------
attila@62 174
attila@62 175 // The simplest possible functions have no attributes set
attila@62 176 testFirstFn("function f() { }")
attila@62 177 testFirstFn("function f(x) { x }")
attila@62 178
attila@62 179 // A function referencing a global needs parent scope, and it needs callee
attila@62 180 // (because parent scope is passed through callee)
attila@62 181 testFirstFn("function f() { x }", 'needsCallee', 'needsParentScope')
attila@62 182
attila@62 183 // A function referencing "arguments" will have to be vararg. It also needs
attila@62 184 // the callee, as it needs to fill out "arguments.callee".
attila@62 185 testFirstFn("function f() { arguments }", 'needsCallee', 'isVarArg')
attila@62 186
attila@62 187 // A function referencing "arguments" will have to be vararg. If it is
attila@62 188 // strict, it will not have to have a callee, though.
attila@422 189 testFirstFn("function f() {'use strict'; arguments }", 'isVarArg', 'isStrict')
attila@62 190
attila@62 191 // A function defining "arguments" as a parameter will not be vararg.
attila@62 192 testFirstFn("function f(arguments) { arguments }")
attila@62 193
attila@62 194 // A function defining "arguments" as a nested function will not be vararg.
attila@62 195 testFirstFn("function f() { function arguments() {}; arguments; }")
attila@62 196
attila@62 197 // A function defining "arguments" as a local variable will be vararg.
attila@62 198 testFirstFn("function f() { var arguments; arguments; }", 'isVarArg', 'needsCallee')
attila@62 199
attila@962 200 // A self-referencing function defined as a statement doesn't need a self
attila@62 201 // symbol, as it'll rather obtain itself from the parent scope.
attila@62 202 testFirstFn("function f() { f() }", 'needsCallee', 'needsParentScope')
attila@62 203
attila@62 204 // A self-referencing function defined as an expression needs a self symbol,
attila@62 205 // as it can't obtain itself from the parent scope.
attila@62 206 testFirstFn("(function f() { f() })", 'needsCallee', 'needsSelfSymbol')
attila@62 207
attila@62 208 // A child function accessing parent's variable triggers the need for scope
attila@62 209 // in parent
attila@422 210 testFirstFn("(function f() { var x; function g() { x } })", 'hasScopeBlock')
attila@62 211
attila@62 212 // A child function accessing parent's parameter triggers the need for scope
attila@62 213 // in parent
attila@422 214 testFirstFn("(function f(x) { function g() { x } })", 'hasScopeBlock')
attila@62 215
attila@62 216 // A child function accessing a global variable triggers the need for parent
attila@62 217 // scope in parent
attila@62 218 testFirstFn("(function f() { function g() { x } })", 'needsParentScope', 'needsCallee')
attila@62 219
attila@962 220 // A child function redefining a local variable from its parent should not
attila@62 221 // affect the parent function in any way
attila@62 222 testFirstFn("(function f() { var x; function g() { var x; x } })")
attila@62 223
attila@422 224 // Using "with" on its own doesn't do much.
attila@422 225 testFirstFn("(function f() { var o; with(o) {} })")
attila@62 226
attila@422 227 // "with" referencing a local variable triggers scoping.
attila@422 228 testFirstFn("(function f() { var x; var y; with(x) { y } })", 'hasScopeBlock')
attila@422 229
attila@422 230 // "with" referencing a non-local variable triggers parent scope.
attila@422 231 testFirstFn("(function f() { var x; with(x) { y } })", 'needsCallee', 'needsParentScope')
attila@62 232
attila@62 233 // Nested function using "with" is pretty much the same as the parent
attila@62 234 // function needing with.
attila@422 235 testFirstFn("(function f() { function g() { var o; with(o) {} } })")
attila@422 236
attila@422 237 // Nested function using "with" referencing a local variable.
attila@422 238 testFirstFn("(function f() { var x; function g() { var o; with(o) { x } } })", 'hasScopeBlock')
attila@422 239
attila@422 240 // Using "eval" triggers pretty much everything. The function even needs to be
attila@422 241 // vararg, 'cause we don't know if eval will be using "arguments".
attila@422 242 testFirstFn("(function f() { eval() })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'hasEval', 'isVarArg', 'allVarsInScope')
attila@422 243
attila@62 244 // Nested function using "eval" is almost the same as parent function using
attila@62 245 // eval, but at least the parent doesn't have to be vararg.
attila@422 246 testFirstFn("(function f() { function g() { eval() } })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'allVarsInScope')
attila@62 247
attila@62 248 // Function with 250 named parameters is ordinary
attila@62 249 testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250) { p250 = p249 }")
attila@62 250
attila@62 251 // Function with 251 named parameters is variable arguments
attila@62 252 testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250, p251) { p250 = p251 }", 'isVarArg')

mercurial