8066222: too strong assertion on function expression names

Reviewed-by: hannesw, lagergren
This commit is contained in:
Attila Szegedi 2014-12-03 16:31:15 +01:00
parent 8d3af43a7c
commit deabb040d5
4 changed files with 73 additions and 19 deletions

View File

@ -135,15 +135,11 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
}
// Named function expressions that end up not referencing themselves won't need a local slot for the self symbol.
if(!functionNode.isDeclared() && !functionNode.usesSelfSymbol() && !functionNode.isAnonymous()) {
if(functionNode.isNamedFunctionExpression() && !functionNode.usesSelfSymbol()) {
final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName());
if(selfSymbol != null) {
if(selfSymbol.isFunctionSelf()) {
selfSymbol.setNeedsSlot(false);
selfSymbol.clearFlag(Symbol.IS_VAR);
}
} else {
assert functionNode.isProgram();
if(selfSymbol != null && selfSymbol.isFunctionSelf()) {
selfSymbol.setNeedsSlot(false);
selfSymbol.clearFlag(Symbol.IS_VAR);
}
}
return functionNode;
@ -490,20 +486,31 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
final Block body = lc.getCurrentBlock();
initFunctionWideVariables(functionNode, body);
acceptDeclarations(functionNode, body);
defineFunctionSelfSymbol(functionNode, body);
}
if (!functionNode.isProgram() && !functionNode.isDeclared() && !functionNode.isAnonymous()) {
// It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's
// anonymous.
final String name = functionNode.getIdent().getName();
assert name != null;
assert body.getExistingSymbol(name) == null;
defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
if(functionNode.allVarsInScope()) { // basically, has deep eval
lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
}
private void defineFunctionSelfSymbol(final FunctionNode functionNode, final Block body) {
// Function self-symbol is only declared as a local variable for named function expressions. Declared functions
// don't need it as they are local variables in their declaring scope.
if (!functionNode.isNamedFunctionExpression()) {
return;
}
acceptDeclarations(functionNode, body);
final String name = functionNode.getIdent().getName();
assert name != null; // As it's a named function expression.
if (body.getExistingSymbol(name) != null) {
// Body already has a declaration for the name. It's either a parameter "function x(x)" or a
// top-level variable "function x() { ... var x; ... }".
return;
}
defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
if(functionNode.allVarsInScope()) { // basically, has deep eval
// We must conservatively presume that eval'd code can dynamically use the function symbol.
lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
}
}
@Override

View File

@ -1091,6 +1091,15 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
return getFlag(USES_SELF_SYMBOL);
}
/**
* Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an
* anonymous function expression, and it isn't a program).
* @return true if this is a named function expression
*/
public boolean isNamedFunctionExpression() {
return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED);
}
@Override
public Type getType(final Function<Symbol, Type> localVariableTypes) {
return FUNCTION_TYPE;

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2014 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-8066222: too strong assertion on function expression names
*
* @test
* @run
*/
// Has to print "SUCCESS"
(function x (x){print(x)})("SUCCESS");
// Has to print "undefined" and "1", not the function source in any case.
(function x(){print(x); var x=1; print(x)})();

View File

@ -0,0 +1,3 @@
SUCCESS
undefined
1