8075448: nashorn parser API returns init variable tree object of a for loop after for loop statement tree object
authorsundar
Wed, 18 Mar 2015 21:54:58 +0530
changeset 29539 b2a8fb583979
parent 29538 a1bfbabf475c
child 29540 b8c821a13ffb
8075448: nashorn parser API returns init variable tree object of a for loop after for loop statement tree object Reviewed-by: lagergren, hannesw, attila
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
nashorn/test/script/basic/JDK-8075448.js
nashorn/test/script/nosecurity/parserapi.js.EXPECTED
--- 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"