test/script/trusted/JDK-8006529.js

Wed, 18 Jun 2014 12:35:42 -0700

author
katleman
date
Wed, 18 Jun 2014 12:35:42 -0700
changeset 863
6e9c4e34bc61
parent 845
cdf42b4b8226
child 952
6d5471a497fb
child 962
ac62e33a99b0
permissions
-rw-r--r--

Added tag jdk8u20-b19 for changeset b047df215de4

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  * 
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  * 
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  * 
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  * 
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 /**
    25  * JDK-8006529 : Methods should not always get callee parameter, and they
    26  * should not be too eager in creation of scopes.
    27  *
    28  * @test
    29  * @run
    30  */
    32 /*
    33  * This test script depends on nashorn Compiler internals. It uses reflection
    34  * to get access to private field and many public methods of Compiler and
    35  * FunctionNode classes. Note that this is trusted code and access to such
    36  * internal package classes and methods is okay. But, if you modify any 
    37  * Compiler or FunctionNode class, you may have to revisit this script.
    38  * We cannot use direct Java class (via dynalink bean linker) to Compiler
    39  * and FunctionNode because of package-access check and so reflective calls.
    40  */
    42 var forName = java.lang.Class["forName(String)"];
    43 var Parser              = forName("jdk.nashorn.internal.parser.Parser").static
    44 var Compiler            = forName("jdk.nashorn.internal.codegen.Compiler").static
    45 var Context             = forName("jdk.nashorn.internal.runtime.Context").static
    46 var ScriptEnvironment   = forName("jdk.nashorn.internal.runtime.ScriptEnvironment").static
    47 var Source              = forName("jdk.nashorn.internal.runtime.Source").static
    48 var FunctionNode        = forName("jdk.nashorn.internal.ir.FunctionNode").static
    49 var Block               = forName("jdk.nashorn.internal.ir.Block").static
    50 var VarNode             = forName("jdk.nashorn.internal.ir.VarNode").static
    51 var ExpressionStatement = forName("jdk.nashorn.internal.ir.ExpressionStatement").static
    52 var UnaryNode           = forName("jdk.nashorn.internal.ir.UnaryNode").static
    53 var BinaryNode          = forName("jdk.nashorn.internal.ir.BinaryNode").static
    54 var ThrowErrorManager   = forName("jdk.nashorn.internal.runtime.Context$ThrowErrorManager").static
    55 var ErrorManager        = forName("jdk.nashorn.internal.runtime.ErrorManager").static
    56 var Debug               = forName("jdk.nashorn.internal.runtime.Debug").static
    58 var parseMethod = Parser.class.getMethod("parse");
    59 var compileMethod = Compiler.class.getMethod("compile", FunctionNode.class);
    60 var getBodyMethod = FunctionNode.class.getMethod("getBody");
    61 var getStatementsMethod = Block.class.getMethod("getStatements");
    62 var getInitMethod = VarNode.class.getMethod("getInit");
    63 var getExpressionMethod = ExpressionStatement.class.getMethod("getExpression")
    64 var rhsMethod = UnaryNode.class.getMethod("rhs")
    65 var lhsMethod = BinaryNode.class.getMethod("lhs")
    66 var binaryRhsMethod = BinaryNode.class.getMethod("rhs")
    67 var debugIdMethod = Debug.class.getMethod("id", java.lang.Object.class)
    69 // These are method names of methods in FunctionNode class
    70 var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'needsSelfSymbol', 'isSplit', 'hasEval', 'allVarsInScope', 'isStrict']
    72 // corresponding Method objects of FunctionNode class
    73 var functionNodeMethods = {};
    74 // initialize FunctionNode methods
    75 (function() {
    76     for (var f in allAssertionList) {
    77         var method = allAssertionList[f];
    78         functionNodeMethods[method] = FunctionNode.class.getMethod(method);
    79     }
    80 })();
    82 // returns functionNode.getBody().getStatements().get(0)
    83 function getFirstFunction(functionNode) {
    84     var f = findFunction(getBodyMethod.invoke(functionNode))
    85     if (f == null) {
    86         throw new Error();
    87     }
    88     return f;
    89 }
    91 function findFunction(node) {
    92     if(node instanceof Block) {
    93         var stmts = getStatementsMethod.invoke(node)
    94         for(var i = 0; i < stmts.size(); ++i) {
    95             var retval = findFunction(stmts.get(i))
    96             if(retval != null) {
    97                 return retval;
    98             }
    99         }
   100     } else if(node instanceof VarNode) {
   101         return findFunction(getInitMethod.invoke(node))
   102     } else if(node instanceof UnaryNode) {
   103         return findFunction(rhsMethod.invoke(node))
   104     } else if(node instanceof BinaryNode) {
   105         return findFunction(lhsMethod.invoke(node)) || findFunction(binaryRhsMethod.invoke(node))
   106 	} else if(node instanceof ExpressionStatement) {
   107 		return findFunction(getExpressionMethod.invoke(node))
   108     } else if(node instanceof FunctionNode) {
   109         return node
   110     }
   111 }
   113 var getContextMethod = Context.class.getMethod("getContext")
   114 var getEnvMethod = Context.class.getMethod("getEnv")
   116 var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class)
   117 var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class)
   118 var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class)
   120 // compile(script) -- compiles a script specified as a string with its 
   121 // source code, returns a jdk.nashorn.internal.ir.FunctionNode object 
   122 // representing it.
   123 function compile(source) {
   124     var source = sourceForMethod.invoke(null, "<no name>", source);
   126     var env = getEnvMethod.invoke(getContextMethod.invoke(null))
   128     var parser   = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance());
   129     var func     = parseMethod.invoke(parser);
   131     var compiler = CompilerConstructor.newInstance(env);
   133     return compileMethod.invoke(compiler, func);
   134 };
   136 var allAssertions = (function() {
   137     var allAssertions = {}
   138     for(var assertion in allAssertionList) {
   139         allAssertions[allAssertionList[assertion]] = true
   140     }
   141     return allAssertions;
   142 })();
   145 // test(f[, assertions...]) tests whether all the specified assertions on the
   146 // passed function node are true.
   147 function test(f) {
   148     var assertions = {}
   149     for(var i = 1; i < arguments.length; ++i) {
   150         var assertion = arguments[i]
   151         if(!allAssertions[assertion]) {
   152             throw "Unknown assertion " + assertion + " for " + f;
   153         }
   154         assertions[assertion] = true
   155     }
   156     for(var assertion in allAssertions) {
   157         var expectedValue = !!assertions[assertion]
   158         var actualValue = functionNodeMethods[assertion].invoke(f)
   159         if(actualValue !== expectedValue) {
   160             throw "Expected " + assertion + " === " + expectedValue + ", got " + actualValue + " for " + f + ":" + debugIdMethod.invoke(null, f);
   161         }
   162     }
   163 }
   165 // testFirstFn(script[, assertions...] tests whether all the specified
   166 // assertions are true in the first function in the given script; "script"
   167 // is a string with the source text of the script.
   168 function testFirstFn(script) {
   169     arguments[0] = getFirstFunction(compile(script))
   170     test.apply(null, arguments)
   171 }
   173 // ---------------------------------- ACTUAL TESTS START HERE --------------
   175 // The simplest possible functions have no attributes set
   176 testFirstFn("function f() { }")
   177 testFirstFn("function f(x) { x }")
   179 // A function referencing a global needs parent scope, and it needs callee
   180 // (because parent scope is passed through callee)
   181 testFirstFn("function f() { x }", 'needsCallee', 'needsParentScope')
   183 // A function referencing "arguments" will have to be vararg. It also needs
   184 // the callee, as it needs to fill out "arguments.callee".
   185 testFirstFn("function f() { arguments }", 'needsCallee', 'isVarArg')
   187 // A function referencing "arguments" will have to be vararg. If it is
   188 // strict, it will not have to have a callee, though.
   189 testFirstFn("function f() {'use strict'; arguments }", 'isVarArg', 'isStrict')
   191 // A function defining "arguments" as a parameter will not be vararg.
   192 testFirstFn("function f(arguments) { arguments }")
   194 // A function defining "arguments" as a nested function will not be vararg.
   195 testFirstFn("function f() { function arguments() {}; arguments; }")
   197 // A function defining "arguments" as a local variable will be vararg.
   198 testFirstFn("function f() { var arguments; arguments; }", 'isVarArg', 'needsCallee')
   200 // A self-referencing function defined as a statement doesn't need a self 
   201 // symbol, as it'll rather obtain itself from the parent scope.
   202 testFirstFn("function f() { f() }", 'needsCallee', 'needsParentScope')
   204 // A self-referencing function defined as an expression needs a self symbol,
   205 // as it can't obtain itself from the parent scope.
   206 testFirstFn("(function f() { f() })", 'needsCallee', 'needsSelfSymbol')
   208 // A child function accessing parent's variable triggers the need for scope
   209 // in parent
   210 testFirstFn("(function f() { var x; function g() { x } })", 'hasScopeBlock')
   212 // A child function accessing parent's parameter triggers the need for scope
   213 // in parent
   214 testFirstFn("(function f(x) { function g() { x } })", 'hasScopeBlock')
   216 // A child function accessing a global variable triggers the need for parent
   217 // scope in parent
   218 testFirstFn("(function f() { function g() { x } })", 'needsParentScope', 'needsCallee')
   220 // A child function redefining a local variable from its parent should not 
   221 // affect the parent function in any way
   222 testFirstFn("(function f() { var x; function g() { var x; x } })")
   224 // Using "with" on its own doesn't do much.
   225 testFirstFn("(function f() { var o; with(o) {} })")
   227 // "with" referencing a local variable triggers scoping.
   228 testFirstFn("(function f() { var x; var y; with(x) { y } })", 'hasScopeBlock')
   230 // "with" referencing a non-local variable triggers parent scope.
   231 testFirstFn("(function f() { var x; with(x) { y } })", 'needsCallee', 'needsParentScope')
   233 // Nested function using "with" is pretty much the same as the parent
   234 // function needing with.
   235 testFirstFn("(function f() { function g() { var o; with(o) {} } })")
   237 // Nested function using "with" referencing a local variable.
   238 testFirstFn("(function f() { var x; function g() { var o; with(o) { x } } })", 'hasScopeBlock')
   240 // Using "eval" triggers pretty much everything. The function even needs to be
   241 // vararg, 'cause we don't know if eval will be using "arguments".
   242 testFirstFn("(function f() { eval() })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'hasEval', 'isVarArg', 'allVarsInScope')
   244 // Nested function using "eval" is almost the same as parent function using
   245 // eval, but at least the parent doesn't have to be vararg.
   246 testFirstFn("(function f() { function g() { eval() } })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'allVarsInScope')
   248 // Function with 250 named parameters is ordinary
   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 }")
   251 // Function with 251 named parameters is variable arguments
   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