--- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java 2014-12-08 15:58:14.961725873 +0100 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java 2014-12-08 15:58:14.841725875 +0100 @@ -34,6 +34,8 @@ import java.util.Collections; import java.util.List; import java.util.ListIterator; +import java.util.regex.Pattern; +import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.BaseNode; import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Block; @@ -52,6 +54,7 @@ import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.IfNode; +import jdk.nashorn.internal.ir.IndexNode; import jdk.nashorn.internal.ir.JumpStatement; import jdk.nashorn.internal.ir.LabelNode; import jdk.nashorn.internal.ir.LexicalContext; @@ -93,6 +96,10 @@ private final DebugLogger log; + // Conservative pattern to test if element names consist of characters valid for identifiers. + // This matches any non-zero length alphanumeric string including _ and $ and not starting with a digit. + private static Pattern SAFE_PROPERTY_NAME = Pattern.compile("[a-zA-Z_$][\\w$]*"); + /** * Constructor. */ @@ -140,7 +147,7 @@ } }); - this.log = initLogger(compiler.getContext()); + this.log = initLogger(compiler.getContext()); } @Override @@ -181,6 +188,31 @@ } @Override + public Node leaveIndexNode(final IndexNode indexNode) { + final String name = getConstantPropertyName(indexNode.getIndex()); + if (name != null) { + // If index node is a constant property name convert index node to access node. + assert Token.descType(indexNode.getToken()) == TokenType.LBRACKET; + return new AccessNode(indexNode.getToken(), indexNode.getFinish(), indexNode.getBase(), name); + } + return super.leaveIndexNode(indexNode); + } + + // If expression is a primitive literal that is not an array index and does return its string value. Else return null. + private static String getConstantPropertyName(final Expression expression) { + if (expression instanceof LiteralNode.PrimitiveLiteralNode) { + final LiteralNode literal = (LiteralNode) expression; + if (!literal.isNumeric()) { + final String str = literal.getString(); + if (SAFE_PROPERTY_NAME.matcher(str).matches()) { + return str; + } + } + } + return null; + } + + @Override public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) { final Expression expr = expressionStatement.getExpression(); ExpressionStatement node = expressionStatement;