542 if (needsBraces) {
543 expect(RBRACE);
544 }
545
546 newBlock.setFinish(possibleEnd);
547
548 return newBlock;
549 }
550
551 /**
552 * Get all the statements generated by a single statement.
553 * @return Statements.
554 */
555 private Block getStatement() {
556 if (type == LBRACE) {
557 return getBlock(true);
558 }
559 // Set up new block. Captures first token.
560 Block newBlock = newBlock();
561 try {
562 statement();
563 } finally {
564 newBlock = restoreBlock(newBlock);
565 }
566 return newBlock;
567 }
568
569 /**
570 * Detect calls to special functions.
571 * @param ident Called function.
572 */
573 private void detectSpecialFunction(final IdentNode ident) {
574 final String name = ident.getName();
575
576 if (EVAL.symbolName().equals(name)) {
577 markEval(lc);
578 }
579 }
580
581 /**
582 * Detect use of special properties.
755 *
756 * Parse the elements of the script or function.
757 */
758 private void sourceElements(final boolean shouldAllowPropertyFunction) {
759 List<Node> directiveStmts = null;
760 boolean checkDirective = true;
761 boolean allowPropertyFunction = shouldAllowPropertyFunction;
762 final boolean oldStrictMode = isStrictMode;
763
764
765 try {
766 // If is a script, then process until the end of the script.
767 while (type != EOF) {
768 // Break if the end of a code block.
769 if (type == RBRACE) {
770 break;
771 }
772
773 try {
774 // Get the next element.
775 statement(true, allowPropertyFunction);
776 allowPropertyFunction = false;
777
778 // check for directive prologues
779 if (checkDirective) {
780 // skip any debug statement like line number to get actual first line
781 final Node lastStatement = lc.getLastStatement();
782
783 // get directive prologue, if any
784 final String directive = getDirective(lastStatement);
785
786 // If we have seen first non-directive statement,
787 // no more directive statements!!
788 checkDirective = directive != null;
789
790 if (checkDirective) {
791 if (!oldStrictMode) {
792 if (directiveStmts == null) {
793 directiveStmts = new ArrayList<>();
794 }
795 directiveStmts.add(lastStatement);
845 * VariableStatement
846 * EmptyStatement
847 * ExpressionStatement
848 * IfStatement
849 * IterationStatement
850 * ContinueStatement
851 * BreakStatement
852 * ReturnStatement
853 * WithStatement
854 * LabelledStatement
855 * SwitchStatement
856 * ThrowStatement
857 * TryStatement
858 * DebuggerStatement
859 *
860 * see 12
861 *
862 * Parse any of the basic statement types.
863 */
864 private void statement() {
865 statement(false, false);
866 }
867
868 /**
869 * @param topLevel does this statement occur at the "top level" of a script or a function?
870 */
871 private void statement(final boolean topLevel, final boolean allowPropertyFunction) {
872 if (type == FUNCTION) {
873 // As per spec (ECMA section 12), function declarations as arbitrary statement
874 // is not "portable". Implementation can issue a warning or disallow the same.
875 functionExpression(true, topLevel);
876 return;
877 }
878
879 switch (type) {
880 case LBRACE:
881 block();
882 break;
883 case VAR:
884 variableStatement(type, true);
885 break;
886 case SEMICOLON:
887 emptyStatement();
888 break;
889 case IF:
890 ifStatement();
891 break;
915 break;
916 case SWITCH:
917 switchStatement();
918 break;
919 case THROW:
920 throwStatement();
921 break;
922 case TRY:
923 tryStatement();
924 break;
925 case DEBUGGER:
926 debuggerStatement();
927 break;
928 case RPAREN:
929 case RBRACKET:
930 case EOF:
931 expect(SEMICOLON);
932 break;
933 default:
934 if (useBlockScope() && (type == LET || type == CONST)) {
935 variableStatement(type, true);
936 break;
937 }
938 if (env._const_as_var && type == CONST) {
939 variableStatement(TokenType.VAR, true);
940 break;
941 }
942
943 if (type == IDENT || isNonStrictModeIdent()) {
944 if (T(k + 1) == COLON) {
945 labelStatement();
946 return;
947 }
948 if(allowPropertyFunction) {
949 final String ident = (String)getValue();
950 final long propertyToken = token;
951 final int propertyLine = line;
952 if("get".equals(ident)) {
953 next();
954 addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
1040 * VariableDeclarationList :
1041 * VariableDeclaration
1042 * VariableDeclarationList , VariableDeclaration
1043 *
1044 * VariableDeclaration :
1045 * Identifier Initializer?
1046 *
1047 * Initializer :
1048 * = AssignmentExpression
1049 *
1050 * See 12.2
1051 *
1052 * Parse a VAR statement.
1053 * @param isStatement True if a statement (not used in a FOR.)
1054 */
1055 private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
1056 // VAR tested in caller.
1057 next();
1058
1059 final List<VarNode> vars = new ArrayList<>();
1060 int varFlags = VarNode.IS_STATEMENT;
1061 if (varType == LET) {
1062 varFlags |= VarNode.IS_LET;
1063 } else if (varType == CONST) {
1064 varFlags |= VarNode.IS_CONST;
1065 }
1066
1067 while (true) {
1068 // Get starting token.
1069 final int varLine = line;
1070 final long varToken = token;
1071 // Get name of var.
1072 final IdentNode name = getIdent();
1073 verifyStrictIdent(name, "variable name");
1074
1075 // Assume no init.
1076 Expression init = null;
1077
1078 // Look for initializer assignment.
1079 if (type == ASSIGN) {
1080 next();
1193 }
1194
1195 /**
1196 * ... IterationStatement:
1197 * ...
1198 * for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1199 * for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1200 * for ( LeftHandSideExpression in Expression ) Statement
1201 * for ( var VariableDeclaration[NoIn] in Expression ) Statement
1202 *
1203 * See 12.6
1204 *
1205 * Parse a FOR statement.
1206 */
1207 private void forStatement() {
1208 // When ES6 for-let is enabled we create a container block to capture the LET.
1209 final int startLine = start;
1210 Block outer = useBlockScope() ? newBlock() : null;
1211
1212 // Create FOR node, capturing FOR token.
1213 ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, ForNode.IS_FOR);
1214 lc.push(forNode);
1215
1216 try {
1217 // FOR tested in caller.
1218 next();
1219
1220 // Nashorn extension: for each expression.
1221 // iterate property values rather than property names.
1222 if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1223 forNode = forNode.setIsForEach(lc);
1224 next();
1225 }
1226
1227 expect(LPAREN);
1228
1229 List<VarNode> vars = null;
1230
1231 switch (type) {
1232 case VAR:
1233 // Var statements captured in for outer block.
1234 vars = variableStatement(type, false);
1235 break;
1236 case SEMICOLON:
1237 break;
1238 default:
1239 if (useBlockScope() && (type == LET || type == CONST)) {
1240 // LET/CONST captured in container block created above.
1241 vars = variableStatement(type, false);
1242 break;
1243 }
1244 if (env._const_as_var && type == CONST) {
1245 // Var statements captured in for outer block.
1246 vars = variableStatement(TokenType.VAR, false);
1247 break;
1248 }
1249
1250 final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1251 forNode = forNode.setInit(lc, expression);
1252 break;
1253 }
1254
1255 switch (type) {
1256 case SEMICOLON:
1257 // for (init; test; modify)
1258
1259 // for each (init; test; modify) is invalid
1260 if (forNode.isForEach()) {
1261 throw error(AbstractParser.message("for.each.without.in"), token);
1262 }
1263
1264 expect(SEMICOLON);
1265 if (type != SEMICOLON) {
1306
1307 // Get the collection expression.
1308 forNode = forNode.setModify(lc, joinPredecessorExpression());
1309 break;
1310
1311 default:
1312 expect(SEMICOLON);
1313 break;
1314 }
1315
1316 expect(RPAREN);
1317
1318 // Set the for body.
1319 final Block body = getStatement();
1320 forNode = forNode.setBody(lc, body);
1321 forNode.setFinish(body.getFinish());
1322
1323 appendStatement(forNode);
1324 } finally {
1325 lc.pop(forNode);
1326 if (outer != null) {
1327 outer.setFinish(forNode.getFinish());
1328 outer = restoreBlock(outer);
1329 appendStatement(new BlockStatement(startLine, outer));
1330 }
1331 }
1332 }
1333
1334 /**
1335 * ... IterationStatement :
1336 * ...
1337 * Expression[NoIn]?; Expression? ; Expression?
1338 * var VariableDeclarationList[NoIn]; Expression? ; Expression?
1339 * LeftHandSideExpression in Expression
1340 * var VariableDeclaration[NoIn] in Expression
1341 *
1342 * See 12.6
1343 *
1344 * Parse the control section of a FOR statement. Also used for
1345 * comprehensions.
1346 * @param forNode Owning FOR.
1347 */
1348
1349
1350 /**
1351 * ...IterationStatement :
1352 * ...
2682 if (parametersSet.contains(parameterName)) {
2683 // redefinition of parameter name
2684 if (strict) {
2685 throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2686 }
2687 // rename in non-strict mode
2688 parameterName = functionNode.uniqueName(parameterName);
2689 final long parameterToken = parameter.getToken();
2690 parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2691 }
2692
2693 parametersSet.add(parameterName);
2694 }
2695 } else if (arity == 1) {
2696 if (isArguments(parameters.get(0))) {
2697 functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS);
2698 }
2699 }
2700
2701 if (isStatement) {
2702 int varFlags = VarNode.IS_STATEMENT;
2703 if (!topLevel && useBlockScope()) {
2704 // mark ES6 block functions as lexically scoped
2705 varFlags |= VarNode.IS_LET;
2706 }
2707 final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags);
2708 if (topLevel) {
2709 functionDeclarations.add(varNode);
2710 } else if (useBlockScope()) {
2711 prependStatement(varNode); // Hoist to beginning of current block
2712 } else {
2713 appendStatement(varNode);
2714 }
2715 }
2716
2717 return functionNode;
2718 }
2719
2720 private String getDefaultValidFunctionName(final int functionLine) {
2721 final String defaultFunctionName = getDefaultFunctionName();
2722 return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2723 }
2724
2725 private static boolean isValidIdentifier(final String name) {
2726 if(name == null || name.isEmpty()) {
|
542 if (needsBraces) {
543 expect(RBRACE);
544 }
545
546 newBlock.setFinish(possibleEnd);
547
548 return newBlock;
549 }
550
551 /**
552 * Get all the statements generated by a single statement.
553 * @return Statements.
554 */
555 private Block getStatement() {
556 if (type == LBRACE) {
557 return getBlock(true);
558 }
559 // Set up new block. Captures first token.
560 Block newBlock = newBlock();
561 try {
562 statement(false, false, true);
563 } finally {
564 newBlock = restoreBlock(newBlock);
565 }
566 return newBlock;
567 }
568
569 /**
570 * Detect calls to special functions.
571 * @param ident Called function.
572 */
573 private void detectSpecialFunction(final IdentNode ident) {
574 final String name = ident.getName();
575
576 if (EVAL.symbolName().equals(name)) {
577 markEval(lc);
578 }
579 }
580
581 /**
582 * Detect use of special properties.
755 *
756 * Parse the elements of the script or function.
757 */
758 private void sourceElements(final boolean shouldAllowPropertyFunction) {
759 List<Node> directiveStmts = null;
760 boolean checkDirective = true;
761 boolean allowPropertyFunction = shouldAllowPropertyFunction;
762 final boolean oldStrictMode = isStrictMode;
763
764
765 try {
766 // If is a script, then process until the end of the script.
767 while (type != EOF) {
768 // Break if the end of a code block.
769 if (type == RBRACE) {
770 break;
771 }
772
773 try {
774 // Get the next element.
775 statement(true, allowPropertyFunction, false);
776 allowPropertyFunction = false;
777
778 // check for directive prologues
779 if (checkDirective) {
780 // skip any debug statement like line number to get actual first line
781 final Node lastStatement = lc.getLastStatement();
782
783 // get directive prologue, if any
784 final String directive = getDirective(lastStatement);
785
786 // If we have seen first non-directive statement,
787 // no more directive statements!!
788 checkDirective = directive != null;
789
790 if (checkDirective) {
791 if (!oldStrictMode) {
792 if (directiveStmts == null) {
793 directiveStmts = new ArrayList<>();
794 }
795 directiveStmts.add(lastStatement);
845 * VariableStatement
846 * EmptyStatement
847 * ExpressionStatement
848 * IfStatement
849 * IterationStatement
850 * ContinueStatement
851 * BreakStatement
852 * ReturnStatement
853 * WithStatement
854 * LabelledStatement
855 * SwitchStatement
856 * ThrowStatement
857 * TryStatement
858 * DebuggerStatement
859 *
860 * see 12
861 *
862 * Parse any of the basic statement types.
863 */
864 private void statement() {
865 statement(false, false, false);
866 }
867
868 /**
869 * @param topLevel does this statement occur at the "top level" of a script or a function?
870 * @param allowPropertyFunction allow property "get" and "set" functions?
871 * @param singleStatement are we in a single statement context?
872 */
873 private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
874 if (type == FUNCTION) {
875 // As per spec (ECMA section 12), function declarations as arbitrary statement
876 // is not "portable". Implementation can issue a warning or disallow the same.
877 functionExpression(true, topLevel);
878 return;
879 }
880
881 switch (type) {
882 case LBRACE:
883 block();
884 break;
885 case VAR:
886 variableStatement(type, true);
887 break;
888 case SEMICOLON:
889 emptyStatement();
890 break;
891 case IF:
892 ifStatement();
893 break;
917 break;
918 case SWITCH:
919 switchStatement();
920 break;
921 case THROW:
922 throwStatement();
923 break;
924 case TRY:
925 tryStatement();
926 break;
927 case DEBUGGER:
928 debuggerStatement();
929 break;
930 case RPAREN:
931 case RBRACKET:
932 case EOF:
933 expect(SEMICOLON);
934 break;
935 default:
936 if (useBlockScope() && (type == LET || type == CONST)) {
937 if (singleStatement) {
938 throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
939 }
940 variableStatement(type, true);
941 break;
942 }
943 if (env._const_as_var && type == CONST) {
944 variableStatement(TokenType.VAR, true);
945 break;
946 }
947
948 if (type == IDENT || isNonStrictModeIdent()) {
949 if (T(k + 1) == COLON) {
950 labelStatement();
951 return;
952 }
953 if(allowPropertyFunction) {
954 final String ident = (String)getValue();
955 final long propertyToken = token;
956 final int propertyLine = line;
957 if("get".equals(ident)) {
958 next();
959 addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
1045 * VariableDeclarationList :
1046 * VariableDeclaration
1047 * VariableDeclarationList , VariableDeclaration
1048 *
1049 * VariableDeclaration :
1050 * Identifier Initializer?
1051 *
1052 * Initializer :
1053 * = AssignmentExpression
1054 *
1055 * See 12.2
1056 *
1057 * Parse a VAR statement.
1058 * @param isStatement True if a statement (not used in a FOR.)
1059 */
1060 private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
1061 // VAR tested in caller.
1062 next();
1063
1064 final List<VarNode> vars = new ArrayList<>();
1065 int varFlags = 0;
1066 if (varType == LET) {
1067 varFlags |= VarNode.IS_LET;
1068 } else if (varType == CONST) {
1069 varFlags |= VarNode.IS_CONST;
1070 }
1071
1072 while (true) {
1073 // Get starting token.
1074 final int varLine = line;
1075 final long varToken = token;
1076 // Get name of var.
1077 final IdentNode name = getIdent();
1078 verifyStrictIdent(name, "variable name");
1079
1080 // Assume no init.
1081 Expression init = null;
1082
1083 // Look for initializer assignment.
1084 if (type == ASSIGN) {
1085 next();
1198 }
1199
1200 /**
1201 * ... IterationStatement:
1202 * ...
1203 * for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1204 * for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1205 * for ( LeftHandSideExpression in Expression ) Statement
1206 * for ( var VariableDeclaration[NoIn] in Expression ) Statement
1207 *
1208 * See 12.6
1209 *
1210 * Parse a FOR statement.
1211 */
1212 private void forStatement() {
1213 // When ES6 for-let is enabled we create a container block to capture the LET.
1214 final int startLine = start;
1215 Block outer = useBlockScope() ? newBlock() : null;
1216
1217 // Create FOR node, capturing FOR token.
1218 ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, 0);
1219 lc.push(forNode);
1220
1221 try {
1222 // FOR tested in caller.
1223 next();
1224
1225 // Nashorn extension: for each expression.
1226 // iterate property values rather than property names.
1227 if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1228 forNode = forNode.setIsForEach(lc);
1229 next();
1230 }
1231
1232 expect(LPAREN);
1233
1234 List<VarNode> vars = null;
1235
1236 switch (type) {
1237 case VAR:
1238 // Var declaration captured in for outer block.
1239 vars = variableStatement(type, false);
1240 break;
1241 case SEMICOLON:
1242 break;
1243 default:
1244 if (useBlockScope() && (type == LET || type == CONST)) {
1245 if (type == LET) {
1246 forNode = forNode.setPerIterationScope(lc);
1247 }
1248 // LET/CONST declaration captured in container block created above.
1249 vars = variableStatement(type, false);
1250 break;
1251 }
1252 if (env._const_as_var && type == CONST) {
1253 // Var declaration captured in for outer block.
1254 vars = variableStatement(TokenType.VAR, false);
1255 break;
1256 }
1257
1258 final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1259 forNode = forNode.setInit(lc, expression);
1260 break;
1261 }
1262
1263 switch (type) {
1264 case SEMICOLON:
1265 // for (init; test; modify)
1266
1267 // for each (init; test; modify) is invalid
1268 if (forNode.isForEach()) {
1269 throw error(AbstractParser.message("for.each.without.in"), token);
1270 }
1271
1272 expect(SEMICOLON);
1273 if (type != SEMICOLON) {
1314
1315 // Get the collection expression.
1316 forNode = forNode.setModify(lc, joinPredecessorExpression());
1317 break;
1318
1319 default:
1320 expect(SEMICOLON);
1321 break;
1322 }
1323
1324 expect(RPAREN);
1325
1326 // Set the for body.
1327 final Block body = getStatement();
1328 forNode = forNode.setBody(lc, body);
1329 forNode.setFinish(body.getFinish());
1330
1331 appendStatement(forNode);
1332 } finally {
1333 lc.pop(forNode);
1334 }
1335
1336 if (outer != null) {
1337 outer.setFinish(forNode.getFinish());
1338 outer = restoreBlock(outer);
1339 appendStatement(new BlockStatement(startLine, outer));
1340 }
1341 }
1342
1343 /**
1344 * ... IterationStatement :
1345 * ...
1346 * Expression[NoIn]?; Expression? ; Expression?
1347 * var VariableDeclarationList[NoIn]; Expression? ; Expression?
1348 * LeftHandSideExpression in Expression
1349 * var VariableDeclaration[NoIn] in Expression
1350 *
1351 * See 12.6
1352 *
1353 * Parse the control section of a FOR statement. Also used for
1354 * comprehensions.
1355 * @param forNode Owning FOR.
1356 */
1357
1358
1359 /**
1360 * ...IterationStatement :
1361 * ...
2691 if (parametersSet.contains(parameterName)) {
2692 // redefinition of parameter name
2693 if (strict) {
2694 throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2695 }
2696 // rename in non-strict mode
2697 parameterName = functionNode.uniqueName(parameterName);
2698 final long parameterToken = parameter.getToken();
2699 parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2700 }
2701
2702 parametersSet.add(parameterName);
2703 }
2704 } else if (arity == 1) {
2705 if (isArguments(parameters.get(0))) {
2706 functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS);
2707 }
2708 }
2709
2710 if (isStatement) {
2711 final int varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
2712 final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags);
2713 if (topLevel) {
2714 functionDeclarations.add(varNode);
2715 } else if (useBlockScope()) {
2716 prependStatement(varNode); // Hoist to beginning of current block
2717 } else {
2718 appendStatement(varNode);
2719 }
2720 }
2721
2722 return functionNode;
2723 }
2724
2725 private String getDefaultValidFunctionName(final int functionLine) {
2726 final String defaultFunctionName = getDefaultFunctionName();
2727 return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2728 }
2729
2730 private static boolean isValidIdentifier(final String name) {
2731 if(name == null || name.isEmpty()) {
|