8075448: nashorn parser API returns init variable tree object of a for loop after for loop statement tree object

Reviewed-by: lagergren, hannesw, attila
This commit is contained in:
Athijegannathan Sundararajan 2015-03-18 21:54:58 +05:30
parent 74e2514b51
commit f75ee76af6
6 changed files with 120 additions and 24 deletions

View File

@ -477,7 +477,7 @@ final class IRTranslator extends NodeVisitor<LexicalContext> {
private List<? extends Statement> getOrderedStatements(final List<? extends Statement> stats) {
final List<? extends Statement> statList = new ArrayList<>(stats);
statList.sort(Comparator.comparingInt(Node::getStart));
statList.sort(Comparator.comparingInt(Node::getSourceOrder));
return statList;
}

View File

@ -183,6 +183,17 @@ public abstract class Node implements Cloneable, Serializable {
return start;
}
/**
* Integer to sort nodes in source order. This order is
* used by parser API to sort statements in correct order.
* By default, this is the start position of this node.
*
* @return int code to sort this node.
*/
public int getSourceOrder() {
return getStart();
}
@Override
protected Object clone() {
try {

View File

@ -45,6 +45,13 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
/** Is this a var statement (as opposed to a "var" in a for loop statement) */
private final int flags;
/**
* source order id to be used for this node. If this is -1, then we
* the default which is start position of this node. See also the
* method Node::getSourceOrder.
*/
private final int sourceOrder;
/** Flag for ES6 LET declaration */
public static final int IS_LET = 1 << 0;
@ -71,6 +78,7 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
private VarNode(final VarNode varNode, final IdentNode name, final Expression init, final int flags) {
super(varNode);
this.sourceOrder = -1;
this.name = init == null ? name : name.setIsInitializedHere();
this.init = init;
this.flags = flags;
@ -79,21 +87,41 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
/**
* Constructor
*
* @param lineNumber line number
* @param token token
* @param finish finish
* @param name name of variable
* @param init init node or null if just a declaration
* @param flags flags
* @param lineNumber line number
* @param token token
* @param finish finish
* @param name name of variable
* @param init init node or null if just a declaration
* @param flags flags
*/
public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Expression init, final int flags) {
super(lineNumber, token, finish);
this(lineNumber, token, -1, finish, name, init, flags);
}
/**
* Constructor
*
* @param lineNumber line number
* @param token token
* @param sourceOrder source order
* @param finish finish
* @param name name of variable
* @param init init node or null if just a declaration
* @param flags flags
*/
public VarNode(final int lineNumber, final long token, final int sourceOrder, final int finish, final IdentNode name, final Expression init, final int flags) {
super(lineNumber, token, finish);
this.sourceOrder = sourceOrder;
this.name = init == null ? name : name.setIsInitializedHere();
this.init = init;
this.flags = flags;
}
@Override
public int getSourceOrder() {
return sourceOrder == -1? super.getSourceOrder() : sourceOrder;
}
@Override
public boolean isAssignment() {
return hasInit();

View File

@ -1066,6 +1066,10 @@ loop:
* @param isStatement True if a statement (not used in a FOR.)
*/
private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
return variableStatement(varType, isStatement, -1);
}
private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
// VAR tested in caller.
next();
@ -1104,7 +1108,7 @@ loop:
}
// Allocate var node.
final VarNode var = new VarNode(varLine, varToken, finish, name.setIsDeclaredHere(), init, varFlags);
final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name.setIsDeclaredHere(), init, varFlags);
vars.add(var);
appendStatement(var);
@ -1211,6 +1215,10 @@ loop:
private void forStatement() {
final long forToken = token;
final int forLine = line;
// start position of this for statement. This is used
// for sort order for variables declared in the initialzer
// part of this 'for' statement (if any).
final int forStart = Token.descPosition(forToken);
// When ES6 for-let is enabled we create a container block to capture the LET.
final int startLine = start;
final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
@ -1243,7 +1251,7 @@ loop:
switch (type) {
case VAR:
// Var declaration captured in for outer block.
vars = variableStatement(type, false);
vars = variableStatement(type, false, forStart);
break;
case SEMICOLON:
break;
@ -1253,12 +1261,12 @@ loop:
flags |= ForNode.PER_ITERATION_SCOPE;
}
// LET/CONST declaration captured in container block created above.
vars = variableStatement(type, false);
vars = variableStatement(type, false, forStart);
break;
}
if (env._const_as_var && type == CONST) {
// Var declaration captured in for outer block.
vars = variableStatement(TokenType.VAR, false);
vars = variableStatement(TokenType.VAR, false, forStart);
break;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2015, 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-8075448: nashorn parser API returns init variable tree object of a for
* loop after for loop statement tree object
*
* @test
* @option -scripting
* @run
*/
var Parser = Java.type("jdk.nashorn.api.tree.Parser");
var ForLoopTree = Java.type("jdk.nashorn.api.tree.ForLoopTree");
var VariableTree = Java.type("jdk.nashorn.api.tree.VariableTree");
var parser = Parser.create();
var code = <<EOF
for (var i = 0; i < 10; i++)
print("hello");
EOF;
var ast = parser.parse("test.js", code, print);
var stats = ast.sourceElements;
Assert.assertTrue(stats[0] instanceof VariableTree);
Assert.assertEquals(stats[0].name, "i");
Assert.assertTrue(stats[1] instanceof ForLoopTree);

View File

@ -5542,6 +5542,12 @@
"properties": []
}
},
{
"endPosition": "2170",
"kind": "VARIABLE",
"name": "i",
"startPosition": "2169"
},
{
"expression": {
"endPosition": "2177",
@ -6131,12 +6137,6 @@
},
"startPosition": "2160"
},
{
"endPosition": "2170",
"kind": "VARIABLE",
"name": "i",
"startPosition": "2169"
},
{
"expression": {
"endPosition": "2862",
@ -6322,6 +6322,12 @@
"kind": "EXPRESSION_STATEMENT",
"startPosition": "2998"
},
{
"endPosition": "3049",
"kind": "VARIABLE",
"name": "file",
"startPosition": "3045"
},
{
"expression": {
"endPosition": "3058",
@ -6726,12 +6732,6 @@
"startPosition": "3060"
},
"startPosition": "3031"
},
{
"endPosition": "3049",
"kind": "VARIABLE",
"name": "file",
"startPosition": "3045"
}
],
"startPosition": "2897"