8075448: nashorn parser API returns init variable tree object of a for loop after for loop statement tree object
Reviewed-by: lagergren, hannesw, attila
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java Mon Mar 16 18:13:38 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java Wed Mar 18 21:54:58 2015 +0530
@@ -477,7 +477,7 @@
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;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java Mon Mar 16 18:13:38 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java Wed Mar 18 21:54:58 2015 +0530
@@ -183,6 +183,17 @@
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 {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java Mon Mar 16 18:13:38 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java Wed Mar 18 21:54:58 2015 +0530
@@ -45,6 +45,13 @@
/** 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 @@
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,22 +87,42 @@
/**
* 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) {
+ 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();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Mon Mar 16 18:13:38 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Mar 18 21:54:58 2015 +0530
@@ -1066,6 +1066,10 @@
* @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 @@
}
// 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 @@
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 @@
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 @@
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;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8075448.js Wed Mar 18 21:54:58 2015 +0530
@@ -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);
+
--- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Mon Mar 16 18:13:38 2015 +0100
+++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Wed Mar 18 21:54:58 2015 +0530
@@ -5543,6 +5543,12 @@
}
},
{
+ "endPosition": "2170",
+ "kind": "VARIABLE",
+ "name": "i",
+ "startPosition": "2169"
+ },
+ {
"expression": {
"endPosition": "2177",
"kind": "IDENTIFIER",
@@ -6132,12 +6138,6 @@
"startPosition": "2160"
},
{
- "endPosition": "2170",
- "kind": "VARIABLE",
- "name": "i",
- "startPosition": "2169"
- },
- {
"expression": {
"endPosition": "2862",
"kind": "IDENTIFIER",
@@ -6323,6 +6323,12 @@
"startPosition": "2998"
},
{
+ "endPosition": "3049",
+ "kind": "VARIABLE",
+ "name": "file",
+ "startPosition": "3045"
+ },
+ {
"expression": {
"endPosition": "3058",
"kind": "IDENTIFIER",
@@ -6726,12 +6732,6 @@
"startPosition": "3060"
},
"startPosition": "3031"
- },
- {
- "endPosition": "3049",
- "kind": "VARIABLE",
- "name": "file",
- "startPosition": "3045"
}
],
"startPosition": "2897"