mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-19 04:13:07 +00:00
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:
parent
74e2514b51
commit
f75ee76af6
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
49
nashorn/test/script/basic/JDK-8075448.js
Normal file
49
nashorn/test/script/basic/JDK-8075448.js
Normal 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);
|
||||
|
||||
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user