1 /* 2 * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.parser; 27 28 import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX; 29 import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL; 30 import static jdk.nashorn.internal.codegen.CompilerConstants.PROGRAM; 31 import static jdk.nashorn.internal.parser.TokenType.ARROW; 32 import static jdk.nashorn.internal.parser.TokenType.ASSIGN; 33 import static jdk.nashorn.internal.parser.TokenType.CASE; 34 import static jdk.nashorn.internal.parser.TokenType.CATCH; 35 import static jdk.nashorn.internal.parser.TokenType.CLASS; 36 import static jdk.nashorn.internal.parser.TokenType.COLON; 37 import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT; 38 import static jdk.nashorn.internal.parser.TokenType.COMMENT; 39 import static jdk.nashorn.internal.parser.TokenType.CONST; 40 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX; 41 import static jdk.nashorn.internal.parser.TokenType.DECPREFIX; 42 import static jdk.nashorn.internal.parser.TokenType.ELLIPSIS; 43 import static jdk.nashorn.internal.parser.TokenType.ELSE; 44 import static jdk.nashorn.internal.parser.TokenType.EOF; 45 import static jdk.nashorn.internal.parser.TokenType.EOL; 46 import static jdk.nashorn.internal.parser.TokenType.EQ_STRICT; 47 import static jdk.nashorn.internal.parser.TokenType.ESCSTRING; 48 import static jdk.nashorn.internal.parser.TokenType.EXPORT; 49 import static jdk.nashorn.internal.parser.TokenType.EXTENDS; 50 import static jdk.nashorn.internal.parser.TokenType.FINALLY; 51 import static jdk.nashorn.internal.parser.TokenType.FUNCTION; 52 import static jdk.nashorn.internal.parser.TokenType.IDENT; 53 import static jdk.nashorn.internal.parser.TokenType.IF; 54 import static jdk.nashorn.internal.parser.TokenType.IMPORT; 55 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX; 56 import static jdk.nashorn.internal.parser.TokenType.LBRACE; 57 import static jdk.nashorn.internal.parser.TokenType.LBRACKET; 58 import static jdk.nashorn.internal.parser.TokenType.LET; 59 import static jdk.nashorn.internal.parser.TokenType.LPAREN; 60 import static jdk.nashorn.internal.parser.TokenType.MUL; 61 import static jdk.nashorn.internal.parser.TokenType.PERIOD; 62 import static jdk.nashorn.internal.parser.TokenType.RBRACE; 63 import static jdk.nashorn.internal.parser.TokenType.RBRACKET; 64 import static jdk.nashorn.internal.parser.TokenType.RPAREN; 65 import static jdk.nashorn.internal.parser.TokenType.SEMICOLON; 66 import static jdk.nashorn.internal.parser.TokenType.SPREAD_ARRAY; 67 import static jdk.nashorn.internal.parser.TokenType.STATIC; 68 import static jdk.nashorn.internal.parser.TokenType.STRING; 69 import static jdk.nashorn.internal.parser.TokenType.SUPER; 70 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE; 71 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_HEAD; 72 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_MIDDLE; 73 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_TAIL; 74 import static jdk.nashorn.internal.parser.TokenType.TERNARY; 75 import static jdk.nashorn.internal.parser.TokenType.VAR; 76 import static jdk.nashorn.internal.parser.TokenType.VOID; 77 import static jdk.nashorn.internal.parser.TokenType.WHILE; 78 import static jdk.nashorn.internal.parser.TokenType.YIELD; 79 import static jdk.nashorn.internal.parser.TokenType.YIELD_STAR; 80 81 import java.io.Serializable; 82 import java.util.ArrayDeque; 83 import java.util.ArrayList; 84 import java.util.Collections; 85 import java.util.Deque; 86 import java.util.HashMap; 87 import java.util.HashSet; 88 import java.util.Iterator; 89 import java.util.List; 90 import java.util.Map; 91 import java.util.Objects; 92 import java.util.function.Consumer; 93 import jdk.nashorn.internal.codegen.CompilerConstants; 94 import jdk.nashorn.internal.codegen.Namespace; 95 import jdk.nashorn.internal.ir.AccessNode; 96 import jdk.nashorn.internal.ir.BaseNode; 97 import jdk.nashorn.internal.ir.BinaryNode; 98 import jdk.nashorn.internal.ir.Block; 99 import jdk.nashorn.internal.ir.BlockStatement; 100 import jdk.nashorn.internal.ir.BreakNode; 101 import jdk.nashorn.internal.ir.CallNode; 102 import jdk.nashorn.internal.ir.CaseNode; 103 import jdk.nashorn.internal.ir.CatchNode; 104 import jdk.nashorn.internal.ir.ClassNode; 105 import jdk.nashorn.internal.ir.ContinueNode; 106 import jdk.nashorn.internal.ir.DebuggerNode; 107 import jdk.nashorn.internal.ir.EmptyNode; 108 import jdk.nashorn.internal.ir.ErrorNode; 109 import jdk.nashorn.internal.ir.Expression; 110 import jdk.nashorn.internal.ir.ExpressionList; 111 import jdk.nashorn.internal.ir.ExpressionStatement; 112 import jdk.nashorn.internal.ir.ForNode; 113 import jdk.nashorn.internal.ir.FunctionNode; 114 import jdk.nashorn.internal.ir.IdentNode; 115 import jdk.nashorn.internal.ir.IfNode; 116 import jdk.nashorn.internal.ir.IndexNode; 117 import jdk.nashorn.internal.ir.JoinPredecessorExpression; 118 import jdk.nashorn.internal.ir.LabelNode; 119 import jdk.nashorn.internal.ir.LexicalContext; 120 import jdk.nashorn.internal.ir.LiteralNode; 121 import jdk.nashorn.internal.ir.Module; 122 import jdk.nashorn.internal.ir.Node; 123 import jdk.nashorn.internal.ir.ObjectNode; 124 import jdk.nashorn.internal.ir.PropertyKey; 125 import jdk.nashorn.internal.ir.PropertyNode; 126 import jdk.nashorn.internal.ir.ReturnNode; 127 import jdk.nashorn.internal.ir.RuntimeNode; 128 import jdk.nashorn.internal.ir.Statement; 129 import jdk.nashorn.internal.ir.SwitchNode; 130 import jdk.nashorn.internal.ir.TemplateLiteral; 131 import jdk.nashorn.internal.ir.TernaryNode; 132 import jdk.nashorn.internal.ir.ThrowNode; 133 import jdk.nashorn.internal.ir.TryNode; 134 import jdk.nashorn.internal.ir.UnaryNode; 135 import jdk.nashorn.internal.ir.VarNode; 136 import jdk.nashorn.internal.ir.WhileNode; 137 import jdk.nashorn.internal.ir.WithNode; 138 import jdk.nashorn.internal.ir.debug.ASTWriter; 139 import jdk.nashorn.internal.ir.debug.PrintVisitor; 140 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 141 import jdk.nashorn.internal.runtime.Context; 142 import jdk.nashorn.internal.runtime.ErrorManager; 143 import jdk.nashorn.internal.runtime.JSErrorType; 144 import jdk.nashorn.internal.runtime.ParserException; 145 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 146 import jdk.nashorn.internal.runtime.ScriptEnvironment; 147 import jdk.nashorn.internal.runtime.ScriptFunctionData; 148 import jdk.nashorn.internal.runtime.ScriptingFunctions; 149 import jdk.nashorn.internal.runtime.Source; 150 import jdk.nashorn.internal.runtime.Timing; 151 import jdk.nashorn.internal.runtime.linker.NameCodec; 152 import jdk.nashorn.internal.runtime.logging.DebugLogger; 153 import jdk.nashorn.internal.runtime.logging.Loggable; 154 import jdk.nashorn.internal.runtime.logging.Logger; 155 156 /** 157 * Builds the IR. 158 */ 159 @Logger(name="parser") 160 public class Parser extends AbstractParser implements Loggable { 161 private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName(); 162 private static final String CONSTRUCTOR_NAME = "constructor"; 163 private static final String GET_NAME = "get"; 164 private static final String SET_NAME = "set"; 165 166 /** Current env. */ 167 private final ScriptEnvironment env; 168 169 /** Is scripting mode. */ 170 private final boolean scripting; 171 172 private List<Statement> functionDeclarations; 173 174 private final ParserContext lc; 175 private final Deque<Object> defaultNames; 176 177 /** Namespace for function names where not explicitly given */ 178 private final Namespace namespace; 179 180 private final DebugLogger log; 181 182 /** to receive line information from Lexer when scanning multine literals. */ 183 protected final Lexer.LineInfoReceiver lineInfoReceiver; 184 185 private RecompilableScriptFunctionData reparsedFunction; 186 187 /** 188 * Constructor 189 * 190 * @param env script environment 191 * @param source source to parse 192 * @param errors error manager 193 */ 194 public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) { 195 this(env, source, errors, env._strict, null); 196 } 197 198 /** 199 * Constructor 200 * 201 * @param env script environment 202 * @param source source to parse 203 * @param errors error manager 204 * @param strict strict 205 * @param log debug logger if one is needed 206 */ 207 public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) { 208 this(env, source, errors, strict, 0, log); 209 } 210 211 /** 212 * Construct a parser. 213 * 214 * @param env script environment 215 * @param source source to parse 216 * @param errors error manager 217 * @param strict parser created with strict mode enabled. 218 * @param lineOffset line offset to start counting lines from 219 * @param log debug logger if one is needed 220 */ 221 public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) { 222 super(source, errors, strict, lineOffset); 223 this.lc = new ParserContext(); 224 this.defaultNames = new ArrayDeque<>(); 225 this.env = env; 226 this.namespace = new Namespace(env.getNamespace()); 227 this.scripting = env._scripting; 228 if (this.scripting) { 229 this.lineInfoReceiver = new Lexer.LineInfoReceiver() { 230 @Override 231 public void lineInfo(final int receiverLine, final int receiverLinePosition) { 232 // update the parser maintained line information 233 Parser.this.line = receiverLine; 234 Parser.this.linePosition = receiverLinePosition; 235 } 236 }; 237 } else { 238 // non-scripting mode script can't have multi-line literals 239 this.lineInfoReceiver = null; 240 } 241 242 this.log = log == null ? DebugLogger.DISABLED_LOGGER : log; 243 } 244 245 @Override 246 public DebugLogger getLogger() { 247 return log; 248 } 249 250 @Override 251 public DebugLogger initLogger(final Context context) { 252 return context.getLogger(this.getClass()); 253 } 254 255 /** 256 * Sets the name for the first function. This is only used when reparsing anonymous functions to ensure they can 257 * preserve their already assigned name, as that name doesn't appear in their source text. 258 * @param name the name for the first parsed function. 259 */ 260 public void setFunctionName(final String name) { 261 defaultNames.push(createIdentNode(0, 0, name)); 262 } 263 264 /** 265 * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this 266 * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation). 267 * This will trigger various special behaviors, such as skipping nested function bodies. 268 * @param reparsedFunction the function being reparsed. 269 */ 270 public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) { 271 this.reparsedFunction = reparsedFunction; 272 } 273 274 /** 275 * Execute parse and return the resulting function node. 276 * Errors will be thrown and the error manager will contain information 277 * if parsing should fail 278 * 279 * This is the default parse call, which will name the function node 280 * {code :program} {@link CompilerConstants#PROGRAM} 281 * 282 * @return function node resulting from successful parse 283 */ 284 public FunctionNode parse() { 285 return parse(PROGRAM.symbolName(), 0, source.getLength(), 0); 286 } 287 288 /** 289 * Set up first token. Skips opening EOL. 290 */ 291 private void scanFirstToken() { 292 k = -1; 293 next(); 294 } 295 296 /** 297 * Execute parse and return the resulting function node. 298 * Errors will be thrown and the error manager will contain information 299 * if parsing should fail 300 * 301 * This should be used to create one and only one function node 302 * 303 * @param scriptName name for the script, given to the parsed FunctionNode 304 * @param startPos start position in source 305 * @param len length of parse 306 * @param reparseFlags flags provided by {@link RecompilableScriptFunctionData} as context for 307 * the code being reparsed. This allows us to recognize special forms of functions such 308 * as property getters and setters or instances of ES6 method shorthand in object literals. 309 * 310 * @return function node resulting from successful parse 311 */ 312 public FunctionNode parse(final String scriptName, final int startPos, final int len, final int reparseFlags) { 313 final boolean isTimingEnabled = env.isTimingEnabled(); 314 final long t0 = isTimingEnabled ? System.nanoTime() : 0L; 315 log.info(this, " begin for '", scriptName, "'"); 316 317 try { 318 stream = new TokenStream(); 319 lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null); 320 lexer.line = lexer.pendingLine = lineOffset + 1; 321 line = lineOffset; 322 323 scanFirstToken(); 324 // Begin parse. 325 return program(scriptName, reparseFlags); 326 } catch (final Exception e) { 327 handleParseException(e); 328 329 return null; 330 } finally { 331 final String end = this + " end '" + scriptName + "'"; 332 if (isTimingEnabled) { 333 env._timing.accumulateTime(toString(), System.nanoTime() - t0); 334 log.info(end, "' in ", Timing.toMillisPrint(System.nanoTime() - t0), " ms"); 335 } else { 336 log.info(end); 337 } 338 } 339 } 340 341 /** 342 * Parse and return the resulting module. 343 * Errors will be thrown and the error manager will contain information 344 * if parsing should fail 345 * 346 * @param moduleName name for the module, given to the parsed FunctionNode 347 * @param startPos start position in source 348 * @param len length of parse 349 * 350 * @return function node resulting from successful parse 351 */ 352 public FunctionNode parseModule(final String moduleName, final int startPos, final int len) { 353 try { 354 stream = new TokenStream(); 355 lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null); 356 lexer.line = lexer.pendingLine = lineOffset + 1; 357 line = lineOffset; 358 359 scanFirstToken(); 360 // Begin parse. 361 return module(moduleName); 362 } catch (final Exception e) { 363 handleParseException(e); 364 365 return null; 366 } 367 } 368 369 /** 370 * Entry point for parsing a module. 371 * 372 * @param moduleName the module name 373 * @return the parsed module 374 */ 375 public FunctionNode parseModule(final String moduleName) { 376 return parseModule(moduleName, 0, source.getLength()); 377 } 378 379 /** 380 * Parse and return the list of function parameter list. A comma 381 * separated list of function parameter identifiers is expected to be parsed. 382 * Errors will be thrown and the error manager will contain information 383 * if parsing should fail. This method is used to check if parameter Strings 384 * passed to "Function" constructor is a valid or not. 385 * 386 * @return the list of IdentNodes representing the formal parameter list 387 */ 388 public List<IdentNode> parseFormalParameterList() { 389 try { 390 stream = new TokenStream(); 391 lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6); 392 393 scanFirstToken(); 394 395 return formalParameterList(TokenType.EOF, false); 396 } catch (final Exception e) { 397 handleParseException(e); 398 return null; 399 } 400 } 401 402 /** 403 * Execute parse and return the resulting function node. 404 * Errors will be thrown and the error manager will contain information 405 * if parsing should fail. This method is used to check if code String 406 * passed to "Function" constructor is a valid function body or not. 407 * 408 * @return function node resulting from successful parse 409 */ 410 public FunctionNode parseFunctionBody() { 411 try { 412 stream = new TokenStream(); 413 lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6); 414 final int functionLine = line; 415 416 scanFirstToken(); 417 418 // Make a fake token for the function. 419 final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength()); 420 // Set up the function to append elements. 421 422 final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName()); 423 final ParserContextFunctionNode function = createParserContextFunctionNode(ident, functionToken, FunctionNode.Kind.NORMAL, functionLine, Collections.<IdentNode>emptyList()); 424 lc.push(function); 425 426 final ParserContextBlockNode body = newBlock(); 427 428 functionDeclarations = new ArrayList<>(); 429 sourceElements(0); 430 addFunctionDeclarations(function); 431 functionDeclarations = null; 432 433 restoreBlock(body); 434 body.setFlag(Block.NEEDS_SCOPE); 435 436 final Block functionBody = new Block(functionToken, source.getLength() - 1, 437 body.getFlags() | Block.IS_SYNTHETIC, body.getStatements()); 438 lc.pop(function); 439 440 expect(EOF); 441 442 final FunctionNode functionNode = createFunctionNode( 443 function, 444 functionToken, 445 ident, 446 Collections.<IdentNode>emptyList(), 447 FunctionNode.Kind.NORMAL, 448 functionLine, 449 functionBody); 450 printAST(functionNode); 451 return functionNode; 452 } catch (final Exception e) { 453 handleParseException(e); 454 return null; 455 } 456 } 457 458 private void handleParseException(final Exception e) { 459 // Extract message from exception. The message will be in error 460 // message format. 461 String message = e.getMessage(); 462 463 // If empty message. 464 if (message == null) { 465 message = e.toString(); 466 } 467 468 // Issue message. 469 if (e instanceof ParserException) { 470 errors.error((ParserException)e); 471 } else { 472 errors.error(message); 473 } 474 475 if (env._dump_on_error) { 476 e.printStackTrace(env.getErr()); 477 } 478 } 479 480 /** 481 * Skip to a good parsing recovery point. 482 */ 483 private void recover(final Exception e) { 484 if (e != null) { 485 // Extract message from exception. The message will be in error 486 // message format. 487 String message = e.getMessage(); 488 489 // If empty message. 490 if (message == null) { 491 message = e.toString(); 492 } 493 494 // Issue message. 495 if (e instanceof ParserException) { 496 errors.error((ParserException)e); 497 } else { 498 errors.error(message); 499 } 500 501 if (env._dump_on_error) { 502 e.printStackTrace(env.getErr()); 503 } 504 } 505 506 // Skip to a recovery point. 507 loop: 508 while (true) { 509 switch (type) { 510 case EOF: 511 // Can not go any further. 512 break loop; 513 case EOL: 514 case SEMICOLON: 515 case RBRACE: 516 // Good recovery points. 517 next(); 518 break loop; 519 default: 520 // So we can recover after EOL. 521 nextOrEOL(); 522 break; 523 } 524 } 525 } 526 527 /** 528 * Set up a new block. 529 * 530 * @return New block. 531 */ 532 private ParserContextBlockNode newBlock() { 533 return lc.push(new ParserContextBlockNode(token)); 534 } 535 536 private ParserContextFunctionNode createParserContextFunctionNode(final IdentNode ident, final long functionToken, final FunctionNode.Kind kind, final int functionLine, final List<IdentNode> parameters) { 537 // Build function name. 538 final StringBuilder sb = new StringBuilder(); 539 540 final ParserContextFunctionNode parentFunction = lc.getCurrentFunction(); 541 if (parentFunction != null && !parentFunction.isProgram()) { 542 sb.append(parentFunction.getName()).append(CompilerConstants.NESTED_FUNCTION_SEPARATOR.symbolName()); 543 } 544 545 assert ident.getName() != null; 546 sb.append(ident.getName()); 547 548 final String name = namespace.uniqueName(sb.toString()); 549 assert parentFunction != null || kind == FunctionNode.Kind.MODULE || name.equals(PROGRAM.symbolName()) : "name = " + name; 550 551 int flags = 0; 552 if (isStrictMode) { 553 flags |= FunctionNode.IS_STRICT; 554 } 555 if (parentFunction == null) { 556 flags |= FunctionNode.IS_PROGRAM; 557 } 558 559 final ParserContextFunctionNode functionNode = new ParserContextFunctionNode(functionToken, ident, name, namespace, functionLine, kind, parameters); 560 functionNode.setFlag(flags); 561 return functionNode; 562 } 563 564 private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine, final Block body) { 565 // assert body.isFunctionBody() || body.getFlag(Block.IS_PARAMETER_BLOCK) && ((BlockStatement) body.getLastStatement()).getBlock().isFunctionBody(); 566 // Start new block. 567 final FunctionNode functionNode = 568 new FunctionNode( 569 source, 570 functionLine, 571 body.getToken(), 572 Token.descPosition(body.getToken()), 573 startToken, 574 function.getLastToken(), 575 namespace, 576 ident, 577 function.getName(), 578 parameters, 579 function.getParameterExpressions(), 580 kind, 581 function.getFlags(), 582 body, 583 function.getEndParserState(), 584 function.getModule(), 585 function.getDebugFlags()); 586 587 printAST(functionNode); 588 589 return functionNode; 590 } 591 592 /** 593 * Restore the current block. 594 */ 595 private ParserContextBlockNode restoreBlock(final ParserContextBlockNode block) { 596 return lc.pop(block); 597 } 598 599 /** 600 * Get the statements in a block. 601 * @return Block statements. 602 */ 603 private Block getBlock(final boolean needsBraces) { 604 final long blockToken = token; 605 final ParserContextBlockNode newBlock = newBlock(); 606 try { 607 // Block opening brace. 608 if (needsBraces) { 609 expect(LBRACE); 610 } 611 // Accumulate block statements. 612 statementList(); 613 614 } finally { 615 restoreBlock(newBlock); 616 } 617 618 // Block closing brace. 619 if (needsBraces) { 620 expect(RBRACE); 621 } 622 623 final int flags = newBlock.getFlags() | (needsBraces ? 0 : Block.IS_SYNTHETIC); 624 return new Block(blockToken, finish, flags, newBlock.getStatements()); 625 } 626 627 /** 628 * Get all the statements generated by a single statement. 629 * @return Statements. 630 */ 631 private Block getStatement() { 632 return getStatement(false); 633 } 634 635 private Block getStatement(final boolean labelledStatement) { 636 if (type == LBRACE) { 637 return getBlock(true); 638 } 639 // Set up new block. Captures first token. 640 final ParserContextBlockNode newBlock = newBlock(); 641 try { 642 statement(false, 0, true, labelledStatement); 643 } finally { 644 restoreBlock(newBlock); 645 } 646 return new Block(newBlock.getToken(), finish, newBlock.getFlags() | Block.IS_SYNTHETIC, newBlock.getStatements()); 647 } 648 649 /** 650 * Detect calls to special functions. 651 * @param ident Called function. 652 */ 653 private void detectSpecialFunction(final IdentNode ident) { 654 final String name = ident.getName(); 655 656 if (EVAL.symbolName().equals(name)) { 657 markEval(lc); 658 } else if (SUPER.getName().equals(name)) { 659 assert ident.isDirectSuper(); 660 markSuperCall(lc); 661 } 662 } 663 664 /** 665 * Detect use of special properties. 666 * @param ident Referenced property. 667 */ 668 private void detectSpecialProperty(final IdentNode ident) { 669 if (isArguments(ident)) { 670 // skip over arrow functions, e.g. function f() { return (() => arguments.length)(); } 671 getCurrentNonArrowFunction().setFlag(FunctionNode.USES_ARGUMENTS); 672 } 673 } 674 675 private boolean useBlockScope() { 676 return env._es6; 677 } 678 679 private boolean isES6() { 680 return env._es6; 681 } 682 683 private static boolean isArguments(final String name) { 684 return ARGUMENTS_NAME.equals(name); 685 } 686 687 static boolean isArguments(final IdentNode ident) { 688 return isArguments(ident.getName()); 689 } 690 691 /** 692 * Tells whether a IdentNode can be used as L-value of an assignment 693 * 694 * @param ident IdentNode to be checked 695 * @return whether the ident can be used as L-value 696 */ 697 private static boolean checkIdentLValue(final IdentNode ident) { 698 return ident.tokenType().getKind() != TokenKind.KEYWORD; 699 } 700 701 /** 702 * Verify an assignment expression. 703 * @param op Operation token. 704 * @param lhs Left hand side expression. 705 * @param rhs Right hand side expression. 706 * @return Verified expression. 707 */ 708 private Expression verifyAssignment(final long op, final Expression lhs, final Expression rhs) { 709 final TokenType opType = Token.descType(op); 710 711 switch (opType) { 712 case ASSIGN: 713 case ASSIGN_ADD: 714 case ASSIGN_BIT_AND: 715 case ASSIGN_BIT_OR: 716 case ASSIGN_BIT_XOR: 717 case ASSIGN_DIV: 718 case ASSIGN_MOD: 719 case ASSIGN_MUL: 720 case ASSIGN_SAR: 721 case ASSIGN_SHL: 722 case ASSIGN_SHR: 723 case ASSIGN_SUB: 724 if (lhs instanceof IdentNode) { 725 if (!checkIdentLValue((IdentNode)lhs)) { 726 return referenceError(lhs, rhs, false); 727 } 728 verifyIdent((IdentNode)lhs, "assignment"); 729 break; 730 } else if (lhs instanceof AccessNode || lhs instanceof IndexNode) { 731 break; 732 } else if (opType == ASSIGN && isDestructuringLhs(lhs)) { 733 verifyDestructuringAssignmentPattern(lhs, "assignment"); 734 break; 735 } else { 736 return referenceError(lhs, rhs, env._early_lvalue_error); 737 } 738 default: 739 break; 740 } 741 742 // Build up node. 743 if(BinaryNode.isLogical(opType)) { 744 return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs)); 745 } 746 return new BinaryNode(op, lhs, rhs); 747 } 748 749 private boolean isDestructuringLhs(final Expression lhs) { 750 if (lhs instanceof ObjectNode || lhs instanceof LiteralNode.ArrayLiteralNode) { 751 return isES6(); 752 } 753 return false; 754 } 755 756 private void verifyDestructuringAssignmentPattern(final Expression pattern, final String contextString) { 757 assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode; 758 pattern.accept(new VerifyDestructuringPatternNodeVisitor(new LexicalContext()) { 759 @Override 760 protected void verifySpreadElement(final Expression lvalue) { 761 if (!checkValidLValue(lvalue, contextString)) { 762 throw error(AbstractParser.message("invalid.lvalue"), lvalue.getToken()); 763 } 764 } 765 766 @Override 767 public boolean enterIdentNode(final IdentNode identNode) { 768 verifyIdent(identNode, contextString); 769 if (!checkIdentLValue(identNode)) { 770 referenceError(identNode, null, true); 771 return false; 772 } 773 return false; 774 } 775 776 @Override 777 public boolean enterAccessNode(final AccessNode accessNode) { 778 return false; 779 } 780 781 @Override 782 public boolean enterIndexNode(final IndexNode indexNode) { 783 return false; 784 } 785 786 @Override 787 protected boolean enterDefault(final Node node) { 788 throw error(String.format("unexpected node in AssignmentPattern: %s", node)); 789 } 790 }); 791 } 792 793 /** 794 * Reduce increment/decrement to simpler operations. 795 * @param firstToken First token. 796 * @param tokenType Operation token (INCPREFIX/DEC.) 797 * @param expression Left hand side expression. 798 * @param isPostfix Prefix or postfix. 799 * @return Reduced expression. 800 */ 801 private static UnaryNode incDecExpression(final long firstToken, final TokenType tokenType, final Expression expression, final boolean isPostfix) { 802 if (isPostfix) { 803 return new UnaryNode(Token.recast(firstToken, tokenType == DECPREFIX ? DECPOSTFIX : INCPOSTFIX), expression.getStart(), Token.descPosition(firstToken) + Token.descLength(firstToken), expression); 804 } 805 806 return new UnaryNode(firstToken, expression); 807 } 808 809 /** 810 * ----------------------------------------------------------------------- 811 * 812 * Grammar based on 813 * 814 * ECMAScript Language Specification 815 * ECMA-262 5th Edition / December 2009 816 * 817 * ----------------------------------------------------------------------- 818 */ 819 820 /** 821 * Program : 822 * SourceElements? 823 * 824 * See 14 825 * 826 * Parse the top level script. 827 */ 828 private FunctionNode program(final String scriptName, final int reparseFlags) { 829 // Make a pseudo-token for the script holding its start and length. 830 final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength()); 831 final int functionLine = line; 832 833 final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), scriptName); 834 final ParserContextFunctionNode script = createParserContextFunctionNode( 835 ident, 836 functionToken, 837 FunctionNode.Kind.SCRIPT, 838 functionLine, 839 Collections.<IdentNode>emptyList()); 840 lc.push(script); 841 final ParserContextBlockNode body = newBlock(); 842 843 functionDeclarations = new ArrayList<>(); 844 sourceElements(reparseFlags); 845 addFunctionDeclarations(script); 846 functionDeclarations = null; 847 848 restoreBlock(body); 849 body.setFlag(Block.NEEDS_SCOPE); 850 final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements()); 851 lc.pop(script); 852 script.setLastToken(token); 853 854 expect(EOF); 855 856 return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.SCRIPT, functionLine, programBody); 857 } 858 859 /** 860 * Directive value or null if statement is not a directive. 861 * 862 * @param stmt Statement to be checked 863 * @return Directive value if the given statement is a directive 864 */ 865 private String getDirective(final Node stmt) { 866 if (stmt instanceof ExpressionStatement) { 867 final Node expr = ((ExpressionStatement)stmt).getExpression(); 868 if (expr instanceof LiteralNode) { 869 final LiteralNode<?> lit = (LiteralNode<?>)expr; 870 final long litToken = lit.getToken(); 871 final TokenType tt = Token.descType(litToken); 872 // A directive is either a string or an escape string 873 if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) { 874 // Make sure that we don't unescape anything. Return as seen in source! 875 return source.getString(lit.getStart(), Token.descLength(litToken)); 876 } 877 } 878 } 879 880 return null; 881 } 882 883 /** 884 * SourceElements : 885 * SourceElement 886 * SourceElements SourceElement 887 * 888 * See 14 889 * 890 * Parse the elements of the script or function. 891 */ 892 private void sourceElements(final int reparseFlags) { 893 List<Node> directiveStmts = null; 894 boolean checkDirective = true; 895 int functionFlags = reparseFlags; 896 final boolean oldStrictMode = isStrictMode; 897 898 899 try { 900 // If is a script, then process until the end of the script. 901 while (type != EOF) { 902 // Break if the end of a code block. 903 if (type == RBRACE) { 904 break; 905 } 906 907 try { 908 // Get the next element. 909 statement(true, functionFlags, false, false); 910 functionFlags = 0; 911 912 // check for directive prologues 913 if (checkDirective) { 914 // skip any debug statement like line number to get actual first line 915 final Statement lastStatement = lc.getLastStatement(); 916 917 // get directive prologue, if any 918 final String directive = getDirective(lastStatement); 919 920 // If we have seen first non-directive statement, 921 // no more directive statements!! 922 checkDirective = directive != null; 923 924 if (checkDirective) { 925 if (!oldStrictMode) { 926 if (directiveStmts == null) { 927 directiveStmts = new ArrayList<>(); 928 } 929 directiveStmts.add(lastStatement); 930 } 931 932 // handle use strict directive 933 if ("use strict".equals(directive)) { 934 isStrictMode = true; 935 final ParserContextFunctionNode function = lc.getCurrentFunction(); 936 function.setFlag(FunctionNode.IS_STRICT); 937 938 // We don't need to check these, if lexical environment is already strict 939 if (!oldStrictMode && directiveStmts != null) { 940 // check that directives preceding this one do not violate strictness 941 for (final Node statement : directiveStmts) { 942 // the get value will force unescape of preceding 943 // escaped string directives 944 getValue(statement.getToken()); 945 } 946 947 // verify that function name as well as parameter names 948 // satisfy strict mode restrictions. 949 verifyIdent(function.getIdent(), "function name"); 950 for (final IdentNode param : function.getParameters()) { 951 verifyIdent(param, "function parameter"); 952 } 953 } 954 } else if (Context.DEBUG) { 955 final int debugFlag = FunctionNode.getDirectiveFlag(directive); 956 if (debugFlag != 0) { 957 final ParserContextFunctionNode function = lc.getCurrentFunction(); 958 function.setDebugFlag(debugFlag); 959 } 960 } 961 } 962 } 963 } catch (final Exception e) { 964 final int errorLine = line; 965 final long errorToken = token; 966 //recover parsing 967 recover(e); 968 final ErrorNode errorExpr = new ErrorNode(errorToken, finish); 969 final ExpressionStatement expressionStatement = new ExpressionStatement(errorLine, errorToken, finish, errorExpr); 970 appendStatement(expressionStatement); 971 } 972 973 // No backtracking from here on. 974 stream.commit(k); 975 } 976 } finally { 977 isStrictMode = oldStrictMode; 978 } 979 } 980 981 /** 982 * Parse any of the basic statement types. 983 * 984 * Statement : 985 * BlockStatement 986 * VariableStatement 987 * EmptyStatement 988 * ExpressionStatement 989 * IfStatement 990 * BreakableStatement 991 * ContinueStatement 992 * BreakStatement 993 * ReturnStatement 994 * WithStatement 995 * LabelledStatement 996 * ThrowStatement 997 * TryStatement 998 * DebuggerStatement 999 * 1000 * BreakableStatement : 1001 * IterationStatement 1002 * SwitchStatement 1003 * 1004 * BlockStatement : 1005 * Block 1006 * 1007 * Block : 1008 * { StatementList opt } 1009 * 1010 * StatementList : 1011 * StatementListItem 1012 * StatementList StatementListItem 1013 * 1014 * StatementItem : 1015 * Statement 1016 * Declaration 1017 * 1018 * Declaration : 1019 * HoistableDeclaration 1020 * ClassDeclaration 1021 * LexicalDeclaration 1022 * 1023 * HoistableDeclaration : 1024 * FunctionDeclaration 1025 * GeneratorDeclaration 1026 */ 1027 private void statement() { 1028 statement(false, 0, false, false); 1029 } 1030 1031 /** 1032 * @param topLevel does this statement occur at the "top level" of a script or a function? 1033 * @param reparseFlags reparse flags to decide whether to allow property "get" and "set" functions or ES6 methods. 1034 * @param singleStatement are we in a single statement context? 1035 */ 1036 private void statement(final boolean topLevel, final int reparseFlags, final boolean singleStatement, final boolean labelledStatement) { 1037 switch (type) { 1038 case LBRACE: 1039 block(); 1040 break; 1041 case VAR: 1042 variableStatement(type); 1043 break; 1044 case SEMICOLON: 1045 emptyStatement(); 1046 break; 1047 case IF: 1048 ifStatement(); 1049 break; 1050 case FOR: 1051 forStatement(); 1052 break; 1053 case WHILE: 1054 whileStatement(); 1055 break; 1056 case DO: 1057 doStatement(); 1058 break; 1059 case CONTINUE: 1060 continueStatement(); 1061 break; 1062 case BREAK: 1063 breakStatement(); 1064 break; 1065 case RETURN: 1066 returnStatement(); 1067 break; 1068 case WITH: 1069 withStatement(); 1070 break; 1071 case SWITCH: 1072 switchStatement(); 1073 break; 1074 case THROW: 1075 throwStatement(); 1076 break; 1077 case TRY: 1078 tryStatement(); 1079 break; 1080 case DEBUGGER: 1081 debuggerStatement(); 1082 break; 1083 case RPAREN: 1084 case RBRACKET: 1085 case EOF: 1086 expect(SEMICOLON); 1087 break; 1088 case FUNCTION: 1089 // As per spec (ECMA section 12), function declarations as arbitrary statement 1090 // is not "portable". Implementation can issue a warning or disallow the same. 1091 if (singleStatement) { 1092 // ES6 B.3.2 Labelled Function Declarations 1093 // It is a Syntax Error if any strict mode source code matches this rule: 1094 // LabelledItem : FunctionDeclaration. 1095 if (!labelledStatement || isStrictMode) { 1096 throw error(AbstractParser.message("expected.stmt", "function declaration"), token); 1097 } 1098 } 1099 functionExpression(true, topLevel || labelledStatement); 1100 return; 1101 default: 1102 if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(false) || type == CONST)) { 1103 if (singleStatement) { 1104 throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token); 1105 } 1106 variableStatement(type); 1107 break; 1108 } else if (type == CLASS && isES6()) { 1109 if (singleStatement) { 1110 throw error(AbstractParser.message("expected.stmt", "class declaration"), token); 1111 } 1112 classDeclaration(false); 1113 break; 1114 } 1115 if (env._const_as_var && type == CONST) { 1116 variableStatement(TokenType.VAR); 1117 break; 1118 } 1119 1120 if (type == IDENT || isNonStrictModeIdent()) { 1121 if (T(k + 1) == COLON) { 1122 labelStatement(); 1123 return; 1124 } 1125 1126 if ((reparseFlags & ScriptFunctionData.IS_PROPERTY_ACCESSOR) != 0) { 1127 final String ident = (String) getValue(); 1128 final long propertyToken = token; 1129 final int propertyLine = line; 1130 if (GET_NAME.equals(ident)) { 1131 next(); 1132 addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine)); 1133 return; 1134 } else if (SET_NAME.equals(ident)) { 1135 next(); 1136 addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine)); 1137 return; 1138 } 1139 } 1140 } 1141 1142 if ((reparseFlags & ScriptFunctionData.IS_ES6_METHOD) != 0 1143 && (type == IDENT || type == LBRACKET || isNonStrictModeIdent())) { 1144 final String ident = (String)getValue(); 1145 final long propertyToken = token; 1146 final int propertyLine = line; 1147 final Expression propertyKey = propertyName(); 1148 1149 // Code below will need refinement once we fully support ES6 class syntax 1150 final int flags = CONSTRUCTOR_NAME.equals(ident) ? FunctionNode.ES6_IS_CLASS_CONSTRUCTOR : FunctionNode.ES6_IS_METHOD; 1151 addPropertyFunctionStatement(propertyMethodFunction(propertyKey, propertyToken, propertyLine, false, flags, false)); 1152 return; 1153 } 1154 1155 expressionStatement(); 1156 break; 1157 } 1158 } 1159 1160 private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) { 1161 final FunctionNode fn = propertyFunction.functionNode; 1162 functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn)); 1163 } 1164 1165 /** 1166 * ClassDeclaration[Yield, Default] : 1167 * class BindingIdentifier[?Yield] ClassTail[?Yield] 1168 * [+Default] class ClassTail[?Yield] 1169 */ 1170 private ClassNode classDeclaration(final boolean isDefault) { 1171 final int classLineNumber = line; 1172 1173 final ClassNode classExpression = classExpression(!isDefault); 1174 1175 if (!isDefault) { 1176 final VarNode classVar = new VarNode(classLineNumber, classExpression.getToken(), classExpression.getIdent().getFinish(), classExpression.getIdent(), classExpression, VarNode.IS_CONST); 1177 appendStatement(classVar); 1178 } 1179 return classExpression; 1180 } 1181 1182 /** 1183 * ClassExpression[Yield] : 1184 * class BindingIdentifier[?Yield]opt ClassTail[?Yield] 1185 */ 1186 private ClassNode classExpression(final boolean isStatement) { 1187 assert type == CLASS; 1188 final int classLineNumber = line; 1189 final long classToken = token; 1190 next(); 1191 1192 IdentNode className = null; 1193 if (isStatement || type == IDENT) { 1194 className = getIdent(); 1195 } 1196 1197 return classTail(classLineNumber, classToken, className, isStatement); 1198 } 1199 1200 private static final class ClassElementKey { 1201 private final boolean isStatic; 1202 private final String propertyName; 1203 1204 private ClassElementKey(final boolean isStatic, final String propertyName) { 1205 this.isStatic = isStatic; 1206 this.propertyName = propertyName; 1207 } 1208 1209 @Override 1210 public int hashCode() { 1211 final int prime = 31; 1212 int result = 1; 1213 result = prime * result + (isStatic ? 1231 : 1237); 1214 result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode()); 1215 return result; 1216 } 1217 1218 @Override 1219 public boolean equals(final Object obj) { 1220 if (obj instanceof ClassElementKey) { 1221 final ClassElementKey other = (ClassElementKey) obj; 1222 return this.isStatic == other.isStatic && Objects.equals(this.propertyName, other.propertyName); 1223 } 1224 return false; 1225 } 1226 } 1227 1228 /** 1229 * Parse ClassTail and ClassBody. 1230 * 1231 * ClassTail[Yield] : 1232 * ClassHeritage[?Yield]opt { ClassBody[?Yield]opt } 1233 * ClassHeritage[Yield] : 1234 * extends LeftHandSideExpression[?Yield] 1235 * 1236 * ClassBody[Yield] : 1237 * ClassElementList[?Yield] 1238 * ClassElementList[Yield] : 1239 * ClassElement[?Yield] 1240 * ClassElementList[?Yield] ClassElement[?Yield] 1241 * ClassElement[Yield] : 1242 * MethodDefinition[?Yield] 1243 * static MethodDefinition[?Yield] 1244 * ; 1245 */ 1246 private ClassNode classTail(final int classLineNumber, final long classToken, 1247 final IdentNode className, final boolean isStatement) { 1248 final boolean oldStrictMode = isStrictMode; 1249 isStrictMode = true; 1250 try { 1251 Expression classHeritage = null; 1252 if (type == EXTENDS) { 1253 next(); 1254 classHeritage = leftHandSideExpression(); 1255 } 1256 1257 expect(LBRACE); 1258 1259 PropertyNode constructor = null; 1260 final ArrayList<PropertyNode> classElements = new ArrayList<>(); 1261 final Map<ClassElementKey, Integer> keyToIndexMap = new HashMap<>(); 1262 for (;;) { 1263 if (type == SEMICOLON) { 1264 next(); 1265 continue; 1266 } 1267 if (type == RBRACE) { 1268 break; 1269 } 1270 final long classElementToken = token; 1271 boolean isStatic = false; 1272 if (type == STATIC) { 1273 isStatic = true; 1274 next(); 1275 } 1276 boolean generator = false; 1277 if (isES6() && type == MUL) { 1278 generator = true; 1279 next(); 1280 } 1281 final PropertyNode classElement = methodDefinition(isStatic, classHeritage != null, generator); 1282 if (classElement.isComputed()) { 1283 classElements.add(classElement); 1284 } else if (!classElement.isStatic() && classElement.getKeyName().equals(CONSTRUCTOR_NAME)) { 1285 if (constructor == null) { 1286 constructor = classElement; 1287 } else { 1288 throw error(AbstractParser.message("multiple.constructors"), classElementToken); 1289 } 1290 } else { 1291 // Check for duplicate method definitions and combine accessor methods. 1292 // In ES6, a duplicate is never an error regardless of strict mode (in consequence of computed property names). 1293 1294 final ClassElementKey key = new ClassElementKey(classElement.isStatic(), classElement.getKeyName()); 1295 final Integer existing = keyToIndexMap.get(key); 1296 1297 if (existing == null) { 1298 keyToIndexMap.put(key, classElements.size()); 1299 classElements.add(classElement); 1300 } else { 1301 final PropertyNode existingProperty = classElements.get(existing); 1302 1303 final Expression value = classElement.getValue(); 1304 final FunctionNode getter = classElement.getGetter(); 1305 final FunctionNode setter = classElement.getSetter(); 1306 1307 if (value != null || existingProperty.getValue() != null) { 1308 keyToIndexMap.put(key, classElements.size()); 1309 classElements.add(classElement); 1310 } else if (getter != null) { 1311 assert existingProperty.getGetter() != null || existingProperty.getSetter() != null; 1312 classElements.set(existing, existingProperty.setGetter(getter)); 1313 } else if (setter != null) { 1314 assert existingProperty.getGetter() != null || existingProperty.getSetter() != null; 1315 classElements.set(existing, existingProperty.setSetter(setter)); 1316 } 1317 } 1318 } 1319 } 1320 1321 final long lastToken = token; 1322 expect(RBRACE); 1323 1324 if (constructor == null) { 1325 constructor = createDefaultClassConstructor(classLineNumber, classToken, lastToken, className, classHeritage != null); 1326 } 1327 1328 classElements.trimToSize(); 1329 return new ClassNode(classLineNumber, classToken, finish, className, classHeritage, constructor, classElements, isStatement); 1330 } finally { 1331 isStrictMode = oldStrictMode; 1332 } 1333 } 1334 1335 private PropertyNode createDefaultClassConstructor(final int classLineNumber, final long classToken, final long lastToken, final IdentNode className, final boolean subclass) { 1336 final int ctorFinish = finish; 1337 final List<Statement> statements; 1338 final List<IdentNode> parameters; 1339 final long identToken = Token.recast(classToken, TokenType.IDENT); 1340 if (subclass) { 1341 final IdentNode superIdent = createIdentNode(identToken, ctorFinish, SUPER.getName()).setIsDirectSuper(); 1342 final IdentNode argsIdent = createIdentNode(identToken, ctorFinish, "args").setIsRestParameter(); 1343 final Expression spreadArgs = new UnaryNode(Token.recast(classToken, TokenType.SPREAD_ARGUMENT), argsIdent); 1344 final CallNode superCall = new CallNode(classLineNumber, classToken, ctorFinish, superIdent, Collections.singletonList(spreadArgs), false); 1345 statements = Collections.singletonList(new ExpressionStatement(classLineNumber, classToken, ctorFinish, superCall)); 1346 parameters = Collections.singletonList(argsIdent); 1347 } else { 1348 statements = Collections.emptyList(); 1349 parameters = Collections.emptyList(); 1350 } 1351 1352 final Block body = new Block(classToken, ctorFinish, Block.IS_BODY, statements); 1353 final IdentNode ctorName = className != null ? className : createIdentNode(identToken, ctorFinish, CONSTRUCTOR_NAME); 1354 final ParserContextFunctionNode function = createParserContextFunctionNode(ctorName, classToken, FunctionNode.Kind.NORMAL, classLineNumber, parameters); 1355 function.setLastToken(lastToken); 1356 1357 function.setFlag(FunctionNode.ES6_IS_METHOD); 1358 function.setFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR); 1359 if (subclass) { 1360 function.setFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR); 1361 function.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER); 1362 } 1363 if (className == null) { 1364 function.setFlag(FunctionNode.IS_ANONYMOUS); 1365 } 1366 1367 final PropertyNode constructor = new PropertyNode(classToken, ctorFinish, ctorName, createFunctionNode( 1368 function, 1369 classToken, 1370 ctorName, 1371 parameters, 1372 FunctionNode.Kind.NORMAL, 1373 classLineNumber, 1374 body 1375 ), null, null, false, false); 1376 return constructor; 1377 } 1378 1379 private PropertyNode methodDefinition(final boolean isStatic, final boolean subclass, final boolean generator) { 1380 final long methodToken = token; 1381 final int methodLine = line; 1382 final boolean computed = type == LBRACKET; 1383 final boolean isIdent = type == IDENT; 1384 final Expression propertyName = propertyName(); 1385 int flags = FunctionNode.ES6_IS_METHOD; 1386 if (!computed) { 1387 final String name = ((PropertyKey)propertyName).getPropertyName(); 1388 if (!generator && isIdent && type != LPAREN && name.equals(GET_NAME)) { 1389 final PropertyFunction methodDefinition = propertyGetterFunction(methodToken, methodLine, flags); 1390 verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true); 1391 return new PropertyNode(methodToken, finish, methodDefinition.key, null, methodDefinition.functionNode, null, isStatic, methodDefinition.computed); 1392 } else if (!generator && isIdent && type != LPAREN && name.equals(SET_NAME)) { 1393 final PropertyFunction methodDefinition = propertySetterFunction(methodToken, methodLine, flags); 1394 verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true); 1395 return new PropertyNode(methodToken, finish, methodDefinition.key, null, null, methodDefinition.functionNode, isStatic, methodDefinition.computed); 1396 } else { 1397 if (!isStatic && !generator && name.equals(CONSTRUCTOR_NAME)) { 1398 flags |= FunctionNode.ES6_IS_CLASS_CONSTRUCTOR; 1399 if (subclass) { 1400 flags |= FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR; 1401 } 1402 } 1403 verifyAllowedMethodName(propertyName, isStatic, computed, generator, false); 1404 } 1405 } 1406 final PropertyFunction methodDefinition = propertyMethodFunction(propertyName, methodToken, methodLine, generator, flags, computed); 1407 return new PropertyNode(methodToken, finish, methodDefinition.key, methodDefinition.functionNode, null, null, isStatic, computed); 1408 } 1409 1410 /** 1411 * ES6 14.5.1 Static Semantics: Early Errors. 1412 */ 1413 private void verifyAllowedMethodName(final Expression key, final boolean isStatic, final boolean computed, final boolean generator, final boolean accessor) { 1414 if (!computed) { 1415 if (!isStatic && generator && ((PropertyKey) key).getPropertyName().equals(CONSTRUCTOR_NAME)) { 1416 throw error(AbstractParser.message("generator.constructor"), key.getToken()); 1417 } 1418 if (!isStatic && accessor && ((PropertyKey) key).getPropertyName().equals(CONSTRUCTOR_NAME)) { 1419 throw error(AbstractParser.message("accessor.constructor"), key.getToken()); 1420 } 1421 if (isStatic && ((PropertyKey) key).getPropertyName().equals("prototype")) { 1422 throw error(AbstractParser.message("static.prototype.method"), key.getToken()); 1423 } 1424 } 1425 } 1426 1427 /** 1428 * block : 1429 * { StatementList? } 1430 * 1431 * see 12.1 1432 * 1433 * Parse a statement block. 1434 */ 1435 private void block() { 1436 appendStatement(new BlockStatement(line, getBlock(true))); 1437 } 1438 1439 /** 1440 * StatementList : 1441 * Statement 1442 * StatementList Statement 1443 * 1444 * See 12.1 1445 * 1446 * Parse a list of statements. 1447 */ 1448 private void statementList() { 1449 // Accumulate statements until end of list. */ 1450 loop: 1451 while (type != EOF) { 1452 switch (type) { 1453 case EOF: 1454 case CASE: 1455 case DEFAULT: 1456 case RBRACE: 1457 break loop; 1458 default: 1459 break; 1460 } 1461 1462 // Get next statement. 1463 statement(); 1464 } 1465 } 1466 1467 /** 1468 * Make sure that the identifier name used is allowed. 1469 * 1470 * @param ident Identifier that is verified 1471 * @param contextString String used in error message to give context to the user 1472 */ 1473 private void verifyIdent(final IdentNode ident, final String contextString) { 1474 verifyStrictIdent(ident, contextString); 1475 if (isES6()) { 1476 final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length()); 1477 if (tokenType != IDENT && tokenType.getKind() != TokenKind.FUTURESTRICT) { 1478 throw error(expectMessage(IDENT)); 1479 } 1480 } 1481 } 1482 1483 /** 1484 * Make sure that in strict mode, the identifier name used is allowed. 1485 * 1486 * @param ident Identifier that is verified 1487 * @param contextString String used in error message to give context to the user 1488 */ 1489 private void verifyStrictIdent(final IdentNode ident, final String contextString) { 1490 if (isStrictMode) { 1491 switch (ident.getName()) { 1492 case "eval": 1493 case "arguments": 1494 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken()); 1495 default: 1496 break; 1497 } 1498 1499 if (ident.isFutureStrictName()) { 1500 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken()); 1501 } 1502 } 1503 } 1504 1505 /* 1506 * VariableStatement : 1507 * var VariableDeclarationList ; 1508 * 1509 * VariableDeclarationList : 1510 * VariableDeclaration 1511 * VariableDeclarationList , VariableDeclaration 1512 * 1513 * VariableDeclaration : 1514 * Identifier Initializer? 1515 * 1516 * Initializer : 1517 * = AssignmentExpression 1518 * 1519 * See 12.2 1520 * 1521 * Parse a VAR statement. 1522 * @param isStatement True if a statement (not used in a FOR.) 1523 */ 1524 private void variableStatement(final TokenType varType) { 1525 variableDeclarationList(varType, true, -1); 1526 } 1527 1528 private static final class ForVariableDeclarationListResult { 1529 /** First missing const or binding pattern initializer. */ 1530 Expression missingAssignment; 1531 /** First declaration with an initializer. */ 1532 long declarationWithInitializerToken; 1533 /** Destructuring assignments. */ 1534 Expression init; 1535 Expression firstBinding; 1536 Expression secondBinding; 1537 1538 void recordMissingAssignment(final Expression binding) { 1539 if (missingAssignment == null) { 1540 missingAssignment = binding; 1541 } 1542 } 1543 1544 void recordDeclarationWithInitializer(final long token) { 1545 if (declarationWithInitializerToken == 0L) { 1546 declarationWithInitializerToken = token; 1547 } 1548 } 1549 1550 void addBinding(final Expression binding) { 1551 if (firstBinding == null) { 1552 firstBinding = binding; 1553 } else if (secondBinding == null) { 1554 secondBinding = binding; 1555 } 1556 // ignore the rest 1557 } 1558 1559 void addAssignment(final Expression assignment) { 1560 if (init == null) { 1561 init = assignment; 1562 } else { 1563 init = new BinaryNode(Token.recast(init.getToken(), COMMARIGHT), init, assignment); 1564 } 1565 } 1566 } 1567 1568 /** 1569 * @param isStatement {@code true} if a VariableStatement, {@code false} if a {@code for} loop VariableDeclarationList 1570 */ 1571 private ForVariableDeclarationListResult variableDeclarationList(final TokenType varType, final boolean isStatement, final int sourceOrder) { 1572 // VAR tested in caller. 1573 assert varType == VAR || varType == LET || varType == CONST; 1574 final int varLine = line; 1575 final long varToken = token; 1576 1577 next(); 1578 1579 int varFlags = 0; 1580 if (varType == LET) { 1581 varFlags |= VarNode.IS_LET; 1582 } else if (varType == CONST) { 1583 varFlags |= VarNode.IS_CONST; 1584 } 1585 1586 final ForVariableDeclarationListResult forResult = isStatement ? null : new ForVariableDeclarationListResult(); 1587 while (true) { 1588 // Get name of var. 1589 if (type == YIELD && inGeneratorFunction()) { 1590 expect(IDENT); 1591 } 1592 1593 final String contextString = "variable name"; 1594 final Expression binding = bindingIdentifierOrPattern(contextString); 1595 final boolean isDestructuring = !(binding instanceof IdentNode); 1596 if (isDestructuring) { 1597 final int finalVarFlags = varFlags; 1598 verifyDestructuringBindingPattern(binding, new Consumer<IdentNode>() { 1599 @Override 1600 public void accept(final IdentNode identNode) { 1601 verifyIdent(identNode, contextString); 1602 if (!env._parse_only) { 1603 // don't bother adding a variable if we are just parsing! 1604 final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags); 1605 appendStatement(var); 1606 } 1607 } 1608 }); 1609 } 1610 1611 // Assume no init. 1612 Expression init = null; 1613 1614 // Look for initializer assignment. 1615 if (type == ASSIGN) { 1616 if (!isStatement) { 1617 forResult.recordDeclarationWithInitializer(varToken); 1618 } 1619 next(); 1620 1621 // Get initializer expression. Suppress IN if not statement. 1622 if (!isDestructuring) { 1623 defaultNames.push(binding); 1624 } 1625 try { 1626 init = assignmentExpression(!isStatement); 1627 } finally { 1628 if (!isDestructuring) { 1629 defaultNames.pop(); 1630 } 1631 } 1632 } else if (isStatement) { 1633 if (isDestructuring) { 1634 throw error(AbstractParser.message("missing.destructuring.assignment"), token); 1635 } else if (varType == CONST) { 1636 throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)binding).getName())); 1637 } 1638 // else, if we are in a for loop, delay checking until we know the kind of loop 1639 } 1640 1641 if (!isDestructuring) { 1642 assert init != null || varType != CONST || !isStatement; 1643 final IdentNode ident = (IdentNode)binding; 1644 if (!isStatement && ident.getName().equals("let")) { 1645 throw error(AbstractParser.message("let.binding.for")); //ES6 13.7.5.1 1646 } 1647 // Only set declaration flag on lexically scoped let/const as it adds runtime overhead. 1648 final IdentNode name = varType == LET || varType == CONST ? ident.setIsDeclaredHere() : ident; 1649 if (!isStatement) { 1650 if (init == null && varType == CONST) { 1651 forResult.recordMissingAssignment(name); 1652 } 1653 forResult.addBinding(new IdentNode(name)); 1654 } 1655 final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name, init, varFlags); 1656 appendStatement(var); 1657 } else { 1658 assert init != null || !isStatement; 1659 if (init != null) { 1660 final Expression assignment = verifyAssignment(Token.recast(varToken, ASSIGN), binding, init); 1661 if (isStatement) { 1662 appendStatement(new ExpressionStatement(varLine, assignment.getToken(), finish, assignment, varType)); 1663 } else { 1664 forResult.addAssignment(assignment); 1665 forResult.addBinding(assignment); 1666 } 1667 } else if (!isStatement) { 1668 forResult.recordMissingAssignment(binding); 1669 forResult.addBinding(binding); 1670 } 1671 } 1672 1673 if (type != COMMARIGHT) { 1674 break; 1675 } 1676 next(); 1677 } 1678 1679 // If is a statement then handle end of line. 1680 if (isStatement) { 1681 endOfLine(); 1682 } 1683 1684 return forResult; 1685 } 1686 1687 private boolean isBindingIdentifier() { 1688 return type == IDENT || isNonStrictModeIdent(); 1689 } 1690 1691 private IdentNode bindingIdentifier(final String contextString) { 1692 final IdentNode name = getIdent(); 1693 verifyIdent(name, contextString); 1694 return name; 1695 } 1696 1697 private Expression bindingPattern() { 1698 if (type == LBRACKET) { 1699 return arrayLiteral(); 1700 } else if (type == LBRACE) { 1701 return objectLiteral(); 1702 } else { 1703 throw error(AbstractParser.message("expected.binding")); 1704 } 1705 } 1706 1707 private Expression bindingIdentifierOrPattern(final String contextString) { 1708 if (isBindingIdentifier() || !isES6()) { 1709 return bindingIdentifier(contextString); 1710 } else { 1711 return bindingPattern(); 1712 } 1713 } 1714 1715 private abstract class VerifyDestructuringPatternNodeVisitor extends NodeVisitor<LexicalContext> { 1716 VerifyDestructuringPatternNodeVisitor(final LexicalContext lc) { 1717 super(lc); 1718 } 1719 1720 @Override 1721 public boolean enterLiteralNode(final LiteralNode<?> literalNode) { 1722 if (literalNode.isArray()) { 1723 if (((LiteralNode.ArrayLiteralNode)literalNode).hasSpread() && ((LiteralNode.ArrayLiteralNode)literalNode).hasTrailingComma()) { 1724 throw error("Rest element must be last", literalNode.getElementExpressions().get(literalNode.getElementExpressions().size() - 1).getToken()); 1725 } 1726 boolean restElement = false; 1727 for (final Expression element : literalNode.getElementExpressions()) { 1728 if (element != null) { 1729 if (restElement) { 1730 throw error("Unexpected element after rest element", element.getToken()); 1731 } 1732 if (element.isTokenType(SPREAD_ARRAY)) { 1733 restElement = true; 1734 final Expression lvalue = ((UnaryNode) element).getExpression(); 1735 verifySpreadElement(lvalue); 1736 } 1737 element.accept(this); 1738 } 1739 } 1740 return false; 1741 } else { 1742 return enterDefault(literalNode); 1743 } 1744 } 1745 1746 protected abstract void verifySpreadElement(Expression lvalue); 1747 1748 @Override 1749 public boolean enterObjectNode(final ObjectNode objectNode) { 1750 return true; 1751 } 1752 1753 @Override 1754 public boolean enterPropertyNode(final PropertyNode propertyNode) { 1755 if (propertyNode.getValue() != null) { 1756 propertyNode.getValue().accept(this); 1757 return false; 1758 } else { 1759 return enterDefault(propertyNode); 1760 } 1761 } 1762 1763 @Override 1764 public boolean enterBinaryNode(final BinaryNode binaryNode) { 1765 if (binaryNode.isTokenType(ASSIGN)) { 1766 binaryNode.lhs().accept(this); 1767 // Initializer(rhs) can be any AssignmentExpression 1768 return false; 1769 } else { 1770 return enterDefault(binaryNode); 1771 } 1772 } 1773 1774 @Override 1775 public boolean enterUnaryNode(final UnaryNode unaryNode) { 1776 if (unaryNode.isTokenType(SPREAD_ARRAY)) { 1777 // rest element 1778 return true; 1779 } else { 1780 return enterDefault(unaryNode); 1781 } 1782 } 1783 } 1784 1785 /** 1786 * Verify destructuring variable declaration binding pattern and extract bound variable declarations. 1787 */ 1788 private void verifyDestructuringBindingPattern(final Expression pattern, final Consumer<IdentNode> identifierCallback) { 1789 assert (pattern instanceof BinaryNode && pattern.isTokenType(ASSIGN)) || 1790 pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode; 1791 pattern.accept(new VerifyDestructuringPatternNodeVisitor(new LexicalContext()) { 1792 @Override 1793 protected void verifySpreadElement(final Expression lvalue) { 1794 if (lvalue instanceof IdentNode) { 1795 // checked in identifierCallback 1796 } else if (isDestructuringLhs(lvalue)) { 1797 verifyDestructuringBindingPattern(lvalue, identifierCallback); 1798 } else { 1799 throw error("Expected a valid binding identifier", lvalue.getToken()); 1800 } 1801 } 1802 1803 @Override 1804 public boolean enterIdentNode(final IdentNode identNode) { 1805 identifierCallback.accept(identNode); 1806 return false; 1807 } 1808 1809 @Override 1810 protected boolean enterDefault(final Node node) { 1811 throw error(String.format("unexpected node in BindingPattern: %s", node)); 1812 } 1813 }); 1814 } 1815 1816 /** 1817 * EmptyStatement : 1818 * ; 1819 * 1820 * See 12.3 1821 * 1822 * Parse an empty statement. 1823 */ 1824 private void emptyStatement() { 1825 if (env._empty_statements) { 1826 appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token))); 1827 } 1828 1829 // SEMICOLON checked in caller. 1830 next(); 1831 } 1832 1833 /** 1834 * ExpressionStatement : 1835 * Expression ; // [lookahead ~({ or function )] 1836 * 1837 * See 12.4 1838 * 1839 * Parse an expression used in a statement block. 1840 */ 1841 private void expressionStatement() { 1842 // Lookahead checked in caller. 1843 final int expressionLine = line; 1844 final long expressionToken = token; 1845 1846 // Get expression and add as statement. 1847 final Expression expression = expression(); 1848 1849 if (expression != null) { 1850 final ExpressionStatement expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression); 1851 appendStatement(expressionStatement); 1852 } else { 1853 expect(null); 1854 } 1855 1856 endOfLine(); 1857 } 1858 1859 /** 1860 * IfStatement : 1861 * if ( Expression ) Statement else Statement 1862 * if ( Expression ) Statement 1863 * 1864 * See 12.5 1865 * 1866 * Parse an IF statement. 1867 */ 1868 private void ifStatement() { 1869 // Capture IF token. 1870 final int ifLine = line; 1871 final long ifToken = token; 1872 // IF tested in caller. 1873 next(); 1874 1875 expect(LPAREN); 1876 final Expression test = expression(); 1877 expect(RPAREN); 1878 final Block pass = getStatement(); 1879 1880 Block fail = null; 1881 if (type == ELSE) { 1882 next(); 1883 fail = getStatement(); 1884 } 1885 1886 appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail)); 1887 } 1888 1889 /** 1890 * ... IterationStatement: 1891 * ... 1892 * for ( Expression[NoIn]?; Expression? ; Expression? ) Statement 1893 * for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement 1894 * for ( LeftHandSideExpression in Expression ) Statement 1895 * for ( var VariableDeclaration[NoIn] in Expression ) Statement 1896 * 1897 * See 12.6 1898 * 1899 * Parse a FOR statement. 1900 */ 1901 @SuppressWarnings("fallthrough") 1902 private void forStatement() { 1903 final long forToken = token; 1904 final int forLine = line; 1905 // start position of this for statement. This is used 1906 // for sort order for variables declared in the initializer 1907 // part of this 'for' statement (if any). 1908 final int forStart = Token.descPosition(forToken); 1909 // When ES6 for-let is enabled we create a container block to capture the LET. 1910 final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null; 1911 1912 // Create FOR node, capturing FOR token. 1913 final ParserContextLoopNode forNode = new ParserContextLoopNode(); 1914 lc.push(forNode); 1915 Block body = null; 1916 Expression init = null; 1917 JoinPredecessorExpression test = null; 1918 JoinPredecessorExpression modify = null; 1919 ForVariableDeclarationListResult varDeclList = null; 1920 1921 int flags = 0; 1922 boolean isForOf = false; 1923 1924 try { 1925 // FOR tested in caller. 1926 next(); 1927 1928 // Nashorn extension: for each expression. 1929 // iterate property values rather than property names. 1930 if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) { 1931 flags |= ForNode.IS_FOR_EACH; 1932 next(); 1933 } 1934 1935 expect(LPAREN); 1936 1937 TokenType varType = null; 1938 switch (type) { 1939 case VAR: 1940 // Var declaration captured in for outer block. 1941 varDeclList = variableDeclarationList(varType = type, false, forStart); 1942 break; 1943 case SEMICOLON: 1944 break; 1945 default: 1946 if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(true) || type == CONST)) { 1947 flags |= ForNode.PER_ITERATION_SCOPE; 1948 // LET/CONST declaration captured in container block created above. 1949 varDeclList = variableDeclarationList(varType = type, false, forStart); 1950 break; 1951 } 1952 if (env._const_as_var && type == CONST) { 1953 // Var declaration captured in for outer block. 1954 varDeclList = variableDeclarationList(varType = TokenType.VAR, false, forStart); 1955 break; 1956 } 1957 1958 init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true); 1959 break; 1960 } 1961 1962 switch (type) { 1963 case SEMICOLON: 1964 // for (init; test; modify) 1965 if (varDeclList != null) { 1966 assert init == null; 1967 init = varDeclList.init; 1968 // late check for missing assignment, now we know it's a for (init; test; modify) loop 1969 if (varDeclList.missingAssignment != null) { 1970 if (varDeclList.missingAssignment instanceof IdentNode) { 1971 throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)varDeclList.missingAssignment).getName())); 1972 } else { 1973 throw error(AbstractParser.message("missing.destructuring.assignment"), varDeclList.missingAssignment.getToken()); 1974 } 1975 } 1976 } 1977 1978 // for each (init; test; modify) is invalid 1979 if ((flags & ForNode.IS_FOR_EACH) != 0) { 1980 throw error(AbstractParser.message("for.each.without.in"), token); 1981 } 1982 1983 expect(SEMICOLON); 1984 if (type != SEMICOLON) { 1985 test = joinPredecessorExpression(); 1986 } 1987 expect(SEMICOLON); 1988 if (type != RPAREN) { 1989 modify = joinPredecessorExpression(); 1990 } 1991 break; 1992 1993 case IDENT: 1994 if (env._es6 && "of".equals(getValue())) { 1995 isForOf = true; 1996 // fall through 1997 } else { 1998 expect(SEMICOLON); // fail with expected message 1999 break; 2000 } 2001 case IN: 2002 flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN; 2003 test = new JoinPredecessorExpression(); 2004 if (varDeclList != null) { 2005 // for (var|let|const ForBinding in|of expression) 2006 if (varDeclList.secondBinding != null) { 2007 // for (var i, j in obj) is invalid 2008 throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), varDeclList.secondBinding.getToken()); 2009 } 2010 if (varDeclList.declarationWithInitializerToken != 0 && (isStrictMode || type != TokenType.IN || varType != VAR || varDeclList.init != null)) { 2011 // ES5 legacy: for (var i = AssignmentExpressionNoIn in Expression) 2012 // Invalid in ES6, but allow it in non-strict mode if no ES6 features used, 2013 // i.e., error if strict, for-of, let/const, or destructuring 2014 throw error(AbstractParser.message("for.in.loop.initializer", isForOf ? "of" : "in"), varDeclList.declarationWithInitializerToken); 2015 } 2016 init = varDeclList.firstBinding; 2017 assert init instanceof IdentNode || isDestructuringLhs(init); 2018 } else { 2019 // for (expr in obj) 2020 assert init != null : "for..in/of init expression can not be null here"; 2021 2022 // check if initial expression is a valid L-value 2023 if (!checkValidLValue(init, isForOf ? "for-of iterator" : "for-in iterator")) { 2024 throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken()); 2025 } 2026 } 2027 2028 next(); 2029 2030 // For-of only allows AssignmentExpression. 2031 modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression(); 2032 break; 2033 2034 default: 2035 expect(SEMICOLON); 2036 break; 2037 } 2038 2039 expect(RPAREN); 2040 2041 // Set the for body. 2042 body = getStatement(); 2043 } finally { 2044 lc.pop(forNode); 2045 2046 for (final Statement var : forNode.getStatements()) { 2047 assert var instanceof VarNode; 2048 appendStatement(var); 2049 } 2050 if (body != null) { 2051 appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify)); 2052 } 2053 if (outer != null) { 2054 restoreBlock(outer); 2055 if (body != null) { 2056 List<Statement> statements = new ArrayList<>(); 2057 for (final Statement var : outer.getStatements()) { 2058 if(var instanceof VarNode && !((VarNode)var).isBlockScoped()) { 2059 appendStatement(var); 2060 }else { 2061 statements.add(var); 2062 } 2063 } 2064 appendStatement(new BlockStatement(forLine, new Block( 2065 outer.getToken(), 2066 body.getFinish(), 2067 statements))); 2068 } 2069 } 2070 } 2071 } 2072 2073 private boolean checkValidLValue(final Expression init, final String contextString) { 2074 if (init instanceof IdentNode) { 2075 if (!checkIdentLValue((IdentNode)init)) { 2076 return false; 2077 } 2078 verifyIdent((IdentNode)init, contextString); 2079 return true; 2080 } else if (init instanceof AccessNode || init instanceof IndexNode) { 2081 return true; 2082 } else if (isDestructuringLhs(init)) { 2083 verifyDestructuringAssignmentPattern(init, contextString); 2084 return true; 2085 } else { 2086 return false; 2087 } 2088 } 2089 2090 @SuppressWarnings("fallthrough") 2091 private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) { 2092 assert type == LET; 2093 for (int i = 1;; i++) { 2094 final TokenType t = T(k + i); 2095 switch (t) { 2096 case EOL: 2097 case COMMENT: 2098 continue; 2099 case IDENT: 2100 if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) { 2101 return false; 2102 } 2103 // fall through 2104 case LBRACKET: 2105 case LBRACE: 2106 return true; 2107 default: 2108 // accept future strict tokens in non-strict mode (including LET) 2109 if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) { 2110 return true; 2111 } 2112 return false; 2113 } 2114 } 2115 } 2116 2117 /** 2118 * ...IterationStatement : 2119 * ... 2120 * while ( Expression ) Statement 2121 * ... 2122 * 2123 * See 12.6 2124 * 2125 * Parse while statement. 2126 */ 2127 private void whileStatement() { 2128 // Capture WHILE token. 2129 final long whileToken = token; 2130 final int whileLine = line; 2131 // WHILE tested in caller. 2132 next(); 2133 2134 final ParserContextLoopNode whileNode = new ParserContextLoopNode(); 2135 lc.push(whileNode); 2136 2137 JoinPredecessorExpression test = null; 2138 Block body = null; 2139 2140 try { 2141 expect(LPAREN); 2142 test = joinPredecessorExpression(); 2143 expect(RPAREN); 2144 body = getStatement(); 2145 } finally { 2146 lc.pop(whileNode); 2147 } 2148 2149 if (body != null) { 2150 appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body)); 2151 } 2152 } 2153 2154 /** 2155 * ...IterationStatement : 2156 * ... 2157 * do Statement while( Expression ) ; 2158 * ... 2159 * 2160 * See 12.6 2161 * 2162 * Parse DO WHILE statement. 2163 */ 2164 private void doStatement() { 2165 // Capture DO token. 2166 final long doToken = token; 2167 int doLine = 0; 2168 // DO tested in the caller. 2169 next(); 2170 2171 final ParserContextLoopNode doWhileNode = new ParserContextLoopNode(); 2172 lc.push(doWhileNode); 2173 2174 Block body = null; 2175 JoinPredecessorExpression test = null; 2176 2177 try { 2178 // Get DO body. 2179 body = getStatement(); 2180 2181 expect(WHILE); 2182 expect(LPAREN); 2183 doLine = line; 2184 test = joinPredecessorExpression(); 2185 expect(RPAREN); 2186 2187 if (type == SEMICOLON) { 2188 endOfLine(); 2189 } 2190 } finally { 2191 lc.pop(doWhileNode); 2192 } 2193 2194 appendStatement(new WhileNode(doLine, doToken, finish, true, test, body)); 2195 } 2196 2197 /** 2198 * ContinueStatement : 2199 * continue Identifier? ; // [no LineTerminator here] 2200 * 2201 * See 12.7 2202 * 2203 * Parse CONTINUE statement. 2204 */ 2205 private void continueStatement() { 2206 // Capture CONTINUE token. 2207 final int continueLine = line; 2208 final long continueToken = token; 2209 // CONTINUE tested in caller. 2210 nextOrEOL(); 2211 2212 ParserContextLabelNode labelNode = null; 2213 2214 // SEMICOLON or label. 2215 switch (type) { 2216 case RBRACE: 2217 case SEMICOLON: 2218 case EOL: 2219 case EOF: 2220 break; 2221 2222 default: 2223 final IdentNode ident = getIdent(); 2224 labelNode = lc.findLabel(ident.getName()); 2225 2226 if (labelNode == null) { 2227 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken()); 2228 } 2229 2230 break; 2231 } 2232 2233 final String labelName = labelNode == null ? null : labelNode.getLabelName(); 2234 final ParserContextLoopNode targetNode = lc.getContinueTo(labelName); 2235 2236 if (targetNode == null) { 2237 throw error(AbstractParser.message("illegal.continue.stmt"), continueToken); 2238 } 2239 2240 endOfLine(); 2241 2242 // Construct and add CONTINUE node. 2243 appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName)); 2244 } 2245 2246 /** 2247 * BreakStatement : 2248 * break Identifier? ; // [no LineTerminator here] 2249 * 2250 * See 12.8 2251 * 2252 */ 2253 private void breakStatement() { 2254 // Capture BREAK token. 2255 final int breakLine = line; 2256 final long breakToken = token; 2257 // BREAK tested in caller. 2258 nextOrEOL(); 2259 2260 ParserContextLabelNode labelNode = null; 2261 2262 // SEMICOLON or label. 2263 switch (type) { 2264 case RBRACE: 2265 case SEMICOLON: 2266 case EOL: 2267 case EOF: 2268 break; 2269 2270 default: 2271 final IdentNode ident = getIdent(); 2272 labelNode = lc.findLabel(ident.getName()); 2273 2274 if (labelNode == null) { 2275 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken()); 2276 } 2277 2278 break; 2279 } 2280 2281 //either an explicit label - then get its node or just a "break" - get first breakable 2282 //targetNode is what we are breaking out from. 2283 final String labelName = labelNode == null ? null : labelNode.getLabelName(); 2284 final ParserContextBreakableNode targetNode = lc.getBreakable(labelName); 2285 2286 if( targetNode instanceof ParserContextBlockNode) { 2287 targetNode.setFlag(Block.IS_BREAKABLE); 2288 } 2289 2290 if (targetNode == null) { 2291 throw error(AbstractParser.message("illegal.break.stmt"), breakToken); 2292 } 2293 2294 endOfLine(); 2295 2296 // Construct and add BREAK node. 2297 appendStatement(new BreakNode(breakLine, breakToken, finish, labelName)); 2298 } 2299 2300 /** 2301 * ReturnStatement : 2302 * return Expression? ; // [no LineTerminator here] 2303 * 2304 * See 12.9 2305 * 2306 * Parse RETURN statement. 2307 */ 2308 private void returnStatement() { 2309 // check for return outside function 2310 if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) { 2311 throw error(AbstractParser.message("invalid.return")); 2312 } 2313 2314 // Capture RETURN token. 2315 final int returnLine = line; 2316 final long returnToken = token; 2317 // RETURN tested in caller. 2318 nextOrEOL(); 2319 2320 Expression expression = null; 2321 2322 // SEMICOLON or expression. 2323 switch (type) { 2324 case RBRACE: 2325 case SEMICOLON: 2326 case EOL: 2327 case EOF: 2328 break; 2329 2330 default: 2331 expression = expression(); 2332 break; 2333 } 2334 2335 endOfLine(); 2336 2337 // Construct and add RETURN node. 2338 appendStatement(new ReturnNode(returnLine, returnToken, finish, expression)); 2339 } 2340 2341 /** 2342 * Parse YieldExpression. 2343 * 2344 * YieldExpression[In] : 2345 * yield 2346 * yield [no LineTerminator here] AssignmentExpression[?In, Yield] 2347 * yield [no LineTerminator here] * AssignmentExpression[?In, Yield] 2348 */ 2349 @SuppressWarnings("fallthrough") 2350 private Expression yieldExpression(final boolean noIn) { 2351 assert inGeneratorFunction(); 2352 // Capture YIELD token. 2353 long yieldToken = token; 2354 // YIELD tested in caller. 2355 assert type == YIELD; 2356 nextOrEOL(); 2357 2358 Expression expression = null; 2359 2360 boolean yieldAsterisk = false; 2361 if (type == MUL) { 2362 yieldAsterisk = true; 2363 yieldToken = Token.recast(yieldToken, YIELD_STAR); 2364 next(); 2365 } 2366 2367 switch (type) { 2368 case RBRACE: 2369 case SEMICOLON: 2370 case EOL: 2371 case EOF: 2372 case COMMARIGHT: 2373 case RPAREN: 2374 case RBRACKET: 2375 case COLON: 2376 if (!yieldAsterisk) { 2377 // treat (yield) as (yield void 0) 2378 expression = newUndefinedLiteral(yieldToken, finish); 2379 if (type == EOL) { 2380 next(); 2381 } 2382 break; 2383 } else { 2384 // AssignmentExpression required, fall through 2385 } 2386 2387 default: 2388 expression = assignmentExpression(noIn); 2389 break; 2390 } 2391 2392 // Construct and add YIELD node. 2393 return new UnaryNode(yieldToken, expression); 2394 } 2395 2396 private static UnaryNode newUndefinedLiteral(final long token, final int finish) { 2397 return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0)); 2398 } 2399 2400 /** 2401 * WithStatement : 2402 * with ( Expression ) Statement 2403 * 2404 * See 12.10 2405 * 2406 * Parse WITH statement. 2407 */ 2408 private void withStatement() { 2409 // Capture WITH token. 2410 final int withLine = line; 2411 final long withToken = token; 2412 // WITH tested in caller. 2413 next(); 2414 2415 // ECMA 12.10.1 strict mode restrictions 2416 if (isStrictMode) { 2417 throw error(AbstractParser.message("strict.no.with"), withToken); 2418 } 2419 2420 expect(LPAREN); 2421 final Expression expression = expression(); 2422 expect(RPAREN); 2423 final Block body = getStatement(); 2424 2425 appendStatement(new WithNode(withLine, withToken, finish, expression, body)); 2426 } 2427 2428 /** 2429 * SwitchStatement : 2430 * switch ( Expression ) CaseBlock 2431 * 2432 * CaseBlock : 2433 * { CaseClauses? } 2434 * { CaseClauses? DefaultClause CaseClauses } 2435 * 2436 * CaseClauses : 2437 * CaseClause 2438 * CaseClauses CaseClause 2439 * 2440 * CaseClause : 2441 * case Expression : StatementList? 2442 * 2443 * DefaultClause : 2444 * default : StatementList? 2445 * 2446 * See 12.11 2447 * 2448 * Parse SWITCH statement. 2449 */ 2450 private void switchStatement() { 2451 final int switchLine = line; 2452 final long switchToken = token; 2453 2454 // Block to capture variables declared inside the switch statement. 2455 final ParserContextBlockNode switchBlock = newBlock(); 2456 2457 // SWITCH tested in caller. 2458 next(); 2459 2460 // Create and add switch statement. 2461 final ParserContextSwitchNode switchNode = new ParserContextSwitchNode(); 2462 lc.push(switchNode); 2463 2464 CaseNode defaultCase = null; 2465 // Prepare to accumulate cases. 2466 final List<CaseNode> cases = new ArrayList<>(); 2467 2468 Expression expression = null; 2469 2470 try { 2471 expect(LPAREN); 2472 expression = expression(); 2473 expect(RPAREN); 2474 2475 expect(LBRACE); 2476 2477 2478 while (type != RBRACE) { 2479 // Prepare for next case. 2480 Expression caseExpression = null; 2481 final long caseToken = token; 2482 2483 switch (type) { 2484 case CASE: 2485 next(); 2486 caseExpression = expression(); 2487 break; 2488 2489 case DEFAULT: 2490 if (defaultCase != null) { 2491 throw error(AbstractParser.message("duplicate.default.in.switch")); 2492 } 2493 next(); 2494 break; 2495 2496 default: 2497 // Force an error. 2498 expect(CASE); 2499 break; 2500 } 2501 2502 expect(COLON); 2503 2504 // Get CASE body. 2505 final Block statements = getBlock(false); // TODO: List<Statement> statements = caseStatementList(); 2506 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements); 2507 2508 if (caseExpression == null) { 2509 defaultCase = caseNode; 2510 } 2511 2512 cases.add(caseNode); 2513 } 2514 2515 next(); 2516 } finally { 2517 lc.pop(switchNode); 2518 restoreBlock(switchBlock); 2519 } 2520 2521 final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase); 2522 appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement))); 2523 } 2524 2525 /** 2526 * LabelledStatement : 2527 * Identifier : Statement 2528 * 2529 * See 12.12 2530 * 2531 * Parse label statement. 2532 */ 2533 private void labelStatement() { 2534 // Capture label token. 2535 final long labelToken = token; 2536 // Get label ident. 2537 final IdentNode ident = getIdent(); 2538 2539 expect(COLON); 2540 2541 if (lc.findLabel(ident.getName()) != null) { 2542 throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken); 2543 } 2544 2545 final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName()); 2546 Block body = null; 2547 try { 2548 lc.push(labelNode); 2549 body = getStatement(true); 2550 } finally { 2551 assert lc.peek() instanceof ParserContextLabelNode; 2552 lc.pop(labelNode); 2553 } 2554 2555 appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body)); 2556 } 2557 2558 /** 2559 * ThrowStatement : 2560 * throw Expression ; // [no LineTerminator here] 2561 * 2562 * See 12.13 2563 * 2564 * Parse throw statement. 2565 */ 2566 private void throwStatement() { 2567 // Capture THROW token. 2568 final int throwLine = line; 2569 final long throwToken = token; 2570 // THROW tested in caller. 2571 nextOrEOL(); 2572 2573 Expression expression = null; 2574 2575 // SEMICOLON or expression. 2576 switch (type) { 2577 case RBRACE: 2578 case SEMICOLON: 2579 case EOL: 2580 break; 2581 2582 default: 2583 expression = expression(); 2584 break; 2585 } 2586 2587 if (expression == null) { 2588 throw error(AbstractParser.message("expected.operand", type.getNameOrType())); 2589 } 2590 2591 endOfLine(); 2592 2593 appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false)); 2594 } 2595 2596 /** 2597 * TryStatement : 2598 * try Block Catch 2599 * try Block Finally 2600 * try Block Catch Finally 2601 * 2602 * Catch : 2603 * catch( Identifier if Expression ) Block 2604 * catch( Identifier ) Block 2605 * 2606 * Finally : 2607 * finally Block 2608 * 2609 * See 12.14 2610 * 2611 * Parse TRY statement. 2612 */ 2613 private void tryStatement() { 2614 // Capture TRY token. 2615 final int tryLine = line; 2616 final long tryToken = token; 2617 // TRY tested in caller. 2618 next(); 2619 2620 // Container block needed to act as target for labeled break statements 2621 final int startLine = line; 2622 final ParserContextBlockNode outer = newBlock(); 2623 // Create try. 2624 2625 try { 2626 final Block tryBody = getBlock(true); 2627 final List<Block> catchBlocks = new ArrayList<>(); 2628 2629 while (type == CATCH) { 2630 final int catchLine = line; 2631 final long catchToken = token; 2632 next(); 2633 expect(LPAREN); 2634 2635 // ES6 catch parameter can be a BindingIdentifier or a BindingPattern 2636 // http://www.ecma-international.org/ecma-262/6.0/ 2637 final String contextString = "catch argument"; 2638 final Expression exception = bindingIdentifierOrPattern(contextString); 2639 final boolean isDestructuring = !(exception instanceof IdentNode); 2640 if (isDestructuring) { 2641 verifyDestructuringBindingPattern(exception, new Consumer<IdentNode>() { 2642 @Override 2643 public void accept(final IdentNode identNode) { 2644 verifyIdent(identNode, contextString); 2645 } 2646 }); 2647 } else { 2648 // ECMA 12.4.1 strict mode restrictions 2649 verifyStrictIdent((IdentNode) exception, "catch argument"); 2650 } 2651 2652 2653 // Nashorn extension: catch clause can have optional 2654 // condition. So, a single try can have more than one 2655 // catch clause each with it's own condition. 2656 final Expression ifExpression; 2657 if (!env._no_syntax_extensions && type == IF) { 2658 next(); 2659 // Get the exception condition. 2660 ifExpression = expression(); 2661 } else { 2662 ifExpression = null; 2663 } 2664 2665 expect(RPAREN); 2666 2667 final ParserContextBlockNode catchBlock = newBlock(); 2668 try { 2669 // Get CATCH body. 2670 final Block catchBody = getBlock(true); 2671 final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false); 2672 appendStatement(catchNode); 2673 } finally { 2674 restoreBlock(catchBlock); 2675 catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements())); 2676 } 2677 2678 // If unconditional catch then should to be the end. 2679 if (ifExpression == null) { 2680 break; 2681 } 2682 } 2683 2684 // Prepare to capture finally statement. 2685 Block finallyStatements = null; 2686 2687 if (type == FINALLY) { 2688 next(); 2689 finallyStatements = getBlock(true); 2690 } 2691 2692 // Need at least one catch or a finally. 2693 if (catchBlocks.isEmpty() && finallyStatements == null) { 2694 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken); 2695 } 2696 2697 final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements); 2698 // Add try. 2699 assert lc.peek() == outer; 2700 appendStatement(tryNode); 2701 } finally { 2702 restoreBlock(outer); 2703 } 2704 2705 appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements()))); 2706 } 2707 2708 /** 2709 * DebuggerStatement : 2710 * debugger ; 2711 * 2712 * See 12.15 2713 * 2714 * Parse debugger statement. 2715 */ 2716 private void debuggerStatement() { 2717 // Capture DEBUGGER token. 2718 final int debuggerLine = line; 2719 final long debuggerToken = token; 2720 // DEBUGGER tested in caller. 2721 next(); 2722 endOfLine(); 2723 appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish)); 2724 } 2725 2726 /** 2727 * PrimaryExpression : 2728 * this 2729 * IdentifierReference 2730 * Literal 2731 * ArrayLiteral 2732 * ObjectLiteral 2733 * RegularExpressionLiteral 2734 * TemplateLiteral 2735 * CoverParenthesizedExpressionAndArrowParameterList 2736 * 2737 * CoverParenthesizedExpressionAndArrowParameterList : 2738 * ( Expression ) 2739 * ( ) 2740 * ( ... BindingIdentifier ) 2741 * ( Expression , ... BindingIdentifier ) 2742 * 2743 * Parse primary expression. 2744 * @return Expression node. 2745 */ 2746 @SuppressWarnings("fallthrough") 2747 private Expression primaryExpression() { 2748 // Capture first token. 2749 final int primaryLine = line; 2750 final long primaryToken = token; 2751 2752 switch (type) { 2753 case THIS: 2754 final String name = type.getName(); 2755 next(); 2756 markThis(lc); 2757 return new IdentNode(primaryToken, finish, name); 2758 case IDENT: 2759 final IdentNode ident = getIdent(); 2760 if (ident == null) { 2761 break; 2762 } 2763 detectSpecialProperty(ident); 2764 return ident; 2765 case OCTAL_LEGACY: 2766 if (isStrictMode) { 2767 throw error(AbstractParser.message("strict.no.octal"), token); 2768 } 2769 case STRING: 2770 case ESCSTRING: 2771 case DECIMAL: 2772 case HEXADECIMAL: 2773 case OCTAL: 2774 case BINARY_NUMBER: 2775 case FLOATING: 2776 case REGEX: 2777 case XML: 2778 return getLiteral(); 2779 case EXECSTRING: 2780 return execString(primaryLine, primaryToken); 2781 case FALSE: 2782 next(); 2783 return LiteralNode.newInstance(primaryToken, finish, false); 2784 case TRUE: 2785 next(); 2786 return LiteralNode.newInstance(primaryToken, finish, true); 2787 case NULL: 2788 next(); 2789 return LiteralNode.newInstance(primaryToken, finish); 2790 case LBRACKET: 2791 return arrayLiteral(); 2792 case LBRACE: 2793 return objectLiteral(); 2794 case LPAREN: 2795 next(); 2796 2797 if (isES6()) { 2798 if (type == RPAREN) { 2799 // () 2800 nextOrEOL(); 2801 expectDontAdvance(ARROW); 2802 return new ExpressionList(primaryToken, finish, Collections.emptyList()); 2803 } else if (type == ELLIPSIS) { 2804 // (...rest) 2805 final IdentNode restParam = formalParameterList(false).get(0); 2806 expectDontAdvance(RPAREN); 2807 nextOrEOL(); 2808 expectDontAdvance(ARROW); 2809 return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam)); 2810 } 2811 } 2812 2813 final Expression expression = expression(); 2814 2815 expect(RPAREN); 2816 2817 return expression; 2818 case TEMPLATE: 2819 case TEMPLATE_HEAD: 2820 return templateLiteral(); 2821 2822 default: 2823 // In this context some operator tokens mark the start of a literal. 2824 if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) { 2825 next(); 2826 return getLiteral(); 2827 } 2828 if (isNonStrictModeIdent()) { 2829 return getIdent(); 2830 } 2831 break; 2832 } 2833 2834 return null; 2835 } 2836 2837 /** 2838 * Convert execString to a call to $EXEC. 2839 * 2840 * @param primaryToken Original string token. 2841 * @return callNode to $EXEC. 2842 */ 2843 CallNode execString(final int primaryLine, final long primaryToken) { 2844 // Synthesize an ident to call $EXEC. 2845 final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME); 2846 // Skip over EXECSTRING. 2847 next(); 2848 // Set up argument list for call. 2849 // Skip beginning of edit string expression. 2850 expect(LBRACE); 2851 // Add the following expression to arguments. 2852 final List<Expression> arguments = Collections.singletonList(expression()); 2853 // Skip ending of edit string expression. 2854 expect(RBRACE); 2855 2856 return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false); 2857 } 2858 2859 /** 2860 * ArrayLiteral : 2861 * [ Elision? ] 2862 * [ ElementList ] 2863 * [ ElementList , Elision? ] 2864 * [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ] 2865 * 2866 * ElementList : Elision? AssignmentExpression 2867 * ElementList , Elision? AssignmentExpression 2868 * 2869 * Elision : 2870 * , 2871 * Elision , 2872 * 2873 * See 12.1.4 2874 * JavaScript 1.8 2875 * 2876 * Parse array literal. 2877 * @return Expression node. 2878 */ 2879 @SuppressWarnings("fallthrough") 2880 private LiteralNode<Expression[]> arrayLiteral() { 2881 // Capture LBRACKET token. 2882 final long arrayToken = token; 2883 // LBRACKET tested in caller. 2884 next(); 2885 2886 // Prepare to accumulate elements. 2887 final List<Expression> elements = new ArrayList<>(); 2888 // Track elisions. 2889 boolean elision = true; 2890 boolean hasSpread = false; 2891 loop: 2892 while (true) { 2893 long spreadToken = 0; 2894 switch (type) { 2895 case RBRACKET: 2896 next(); 2897 2898 break loop; 2899 2900 case COMMARIGHT: 2901 next(); 2902 2903 // If no prior expression 2904 if (elision) { 2905 elements.add(null); 2906 } 2907 2908 elision = true; 2909 2910 break; 2911 2912 case ELLIPSIS: 2913 if (isES6()) { 2914 hasSpread = true; 2915 spreadToken = token; 2916 next(); 2917 } 2918 // fall through 2919 2920 default: 2921 if (!elision) { 2922 throw error(AbstractParser.message("expected.comma", type.getNameOrType())); 2923 } 2924 2925 // Add expression element. 2926 Expression expression = assignmentExpression(false); 2927 if (expression != null) { 2928 if (spreadToken != 0) { 2929 expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression); 2930 } 2931 elements.add(expression); 2932 } else { 2933 expect(RBRACKET); 2934 } 2935 2936 elision = false; 2937 break; 2938 } 2939 } 2940 2941 return LiteralNode.newInstance(arrayToken, finish, elements, hasSpread, elision); 2942 } 2943 2944 /** 2945 * ObjectLiteral : 2946 * { } 2947 * { PropertyNameAndValueList } { PropertyNameAndValueList , } 2948 * 2949 * PropertyNameAndValueList : 2950 * PropertyAssignment 2951 * PropertyNameAndValueList , PropertyAssignment 2952 * 2953 * See 11.1.5 2954 * 2955 * Parse an object literal. 2956 * @return Expression node. 2957 */ 2958 private ObjectNode objectLiteral() { 2959 // Capture LBRACE token. 2960 final long objectToken = token; 2961 // LBRACE tested in caller. 2962 next(); 2963 2964 // Object context. 2965 // Prepare to accumulate elements. 2966 final List<PropertyNode> elements = new ArrayList<>(); 2967 final Map<String, Integer> map = new HashMap<>(); 2968 2969 // Create a block for the object literal. 2970 boolean commaSeen = true; 2971 loop: 2972 while (true) { 2973 switch (type) { 2974 case RBRACE: 2975 next(); 2976 break loop; 2977 2978 case COMMARIGHT: 2979 if (commaSeen) { 2980 throw error(AbstractParser.message("expected.property.id", type.getNameOrType())); 2981 } 2982 next(); 2983 commaSeen = true; 2984 break; 2985 2986 default: 2987 if (!commaSeen) { 2988 throw error(AbstractParser.message("expected.comma", type.getNameOrType())); 2989 } 2990 2991 commaSeen = false; 2992 // Get and add the next property. 2993 final PropertyNode property = propertyAssignment(); 2994 2995 if (property.isComputed()) { 2996 elements.add(property); 2997 break; 2998 } 2999 3000 final String key = property.getKeyName(); 3001 final Integer existing = map.get(key); 3002 3003 if (existing == null) { 3004 map.put(key, elements.size()); 3005 elements.add(property); 3006 break; 3007 } 3008 3009 final PropertyNode existingProperty = elements.get(existing); 3010 3011 // ECMA section 11.1.5 Object Initialiser 3012 // point # 4 on property assignment production 3013 final Expression value = property.getValue(); 3014 final FunctionNode getter = property.getGetter(); 3015 final FunctionNode setter = property.getSetter(); 3016 3017 final Expression prevValue = existingProperty.getValue(); 3018 final FunctionNode prevGetter = existingProperty.getGetter(); 3019 final FunctionNode prevSetter = existingProperty.getSetter(); 3020 3021 if (!isES6()) { 3022 checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter); 3023 } else { 3024 if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() && 3025 existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) { 3026 throw error(AbstractParser.message("multiple.proto.key"), property.getToken()); 3027 } 3028 } 3029 3030 if (value != null || prevValue != null) { 3031 map.put(key, elements.size()); 3032 elements.add(property); 3033 } else if (getter != null) { 3034 assert prevGetter != null || prevSetter != null; 3035 elements.set(existing, existingProperty.setGetter(getter)); 3036 } else if (setter != null) { 3037 assert prevGetter != null || prevSetter != null; 3038 elements.set(existing, existingProperty.setSetter(setter)); 3039 } 3040 break; 3041 } 3042 } 3043 3044 return new ObjectNode(objectToken, finish, elements); 3045 } 3046 3047 private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) { 3048 // ECMA 11.1.5 strict mode restrictions 3049 if (isStrictMode && value != null && prevValue != null) { 3050 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); 3051 } 3052 3053 final boolean isPrevAccessor = prevGetter != null || prevSetter != null; 3054 final boolean isAccessor = getter != null || setter != null; 3055 3056 // data property redefined as accessor property 3057 if (prevValue != null && isAccessor) { 3058 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); 3059 } 3060 3061 // accessor property redefined as data 3062 if (isPrevAccessor && value != null) { 3063 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); 3064 } 3065 3066 if (isAccessor && isPrevAccessor) { 3067 if (getter != null && prevGetter != null || 3068 setter != null && prevSetter != null) { 3069 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); 3070 } 3071 } 3072 } 3073 3074 /** 3075 * LiteralPropertyName : 3076 * IdentifierName 3077 * StringLiteral 3078 * NumericLiteral 3079 * 3080 * @return PropertyName node 3081 */ 3082 @SuppressWarnings("fallthrough") 3083 private PropertyKey literalPropertyName() { 3084 switch (type) { 3085 case IDENT: 3086 return getIdent().setIsPropertyName(); 3087 case OCTAL_LEGACY: 3088 if (isStrictMode) { 3089 throw error(AbstractParser.message("strict.no.octal"), token); 3090 } 3091 case STRING: 3092 case ESCSTRING: 3093 case DECIMAL: 3094 case HEXADECIMAL: 3095 case OCTAL: 3096 case BINARY_NUMBER: 3097 case FLOATING: 3098 return getLiteral(); 3099 default: 3100 return getIdentifierName().setIsPropertyName(); 3101 } 3102 } 3103 3104 /** 3105 * ComputedPropertyName : 3106 * AssignmentExpression 3107 * 3108 * @return PropertyName node 3109 */ 3110 private Expression computedPropertyName() { 3111 expect(LBRACKET); 3112 final Expression expression = assignmentExpression(false); 3113 expect(RBRACKET); 3114 return expression; 3115 } 3116 3117 /** 3118 * PropertyName : 3119 * LiteralPropertyName 3120 * ComputedPropertyName 3121 * 3122 * @return PropertyName node 3123 */ 3124 private Expression propertyName() { 3125 if (type == LBRACKET && isES6()) { 3126 return computedPropertyName(); 3127 } else { 3128 return (Expression)literalPropertyName(); 3129 } 3130 } 3131 3132 /** 3133 * PropertyAssignment : 3134 * PropertyName : AssignmentExpression 3135 * get PropertyName ( ) { FunctionBody } 3136 * set PropertyName ( PropertySetParameterList ) { FunctionBody } 3137 * 3138 * PropertySetParameterList : 3139 * Identifier 3140 * 3141 * PropertyName : 3142 * IdentifierName 3143 * StringLiteral 3144 * NumericLiteral 3145 * 3146 * See 11.1.5 3147 * 3148 * Parse an object literal property. 3149 * @return Property or reference node. 3150 */ 3151 private PropertyNode propertyAssignment() { 3152 // Capture firstToken. 3153 final long propertyToken = token; 3154 final int functionLine = line; 3155 3156 final Expression propertyName; 3157 final boolean isIdentifier; 3158 3159 boolean generator = false; 3160 if (type == MUL && isES6()) { 3161 generator = true; 3162 next(); 3163 } 3164 3165 final boolean computed = type == LBRACKET; 3166 if (type == IDENT) { 3167 // Get IDENT. 3168 final String ident = (String)expectValue(IDENT); 3169 3170 if (type != COLON && (type != LPAREN || !isES6())) { 3171 final long getSetToken = propertyToken; 3172 3173 switch (ident) { 3174 case GET_NAME: 3175 final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine); 3176 return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed); 3177 3178 case SET_NAME: 3179 final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine); 3180 return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed); 3181 default: 3182 break; 3183 } 3184 } 3185 3186 isIdentifier = true; 3187 IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName(); 3188 if (type == COLON && ident.equals("__proto__")) { 3189 identNode = identNode.setIsProtoPropertyName(); 3190 } 3191 propertyName = identNode; 3192 } else { 3193 isIdentifier = isNonStrictModeIdent(); 3194 propertyName = propertyName(); 3195 } 3196 3197 Expression propertyValue; 3198 3199 if (generator) { 3200 expectDontAdvance(LPAREN); 3201 } 3202 3203 if (type == LPAREN && isES6()) { 3204 propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode; 3205 } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) { 3206 propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName()); 3207 if (type == ASSIGN && isES6()) { 3208 // TODO if not destructuring, this is a SyntaxError 3209 final long assignToken = token; 3210 next(); 3211 final Expression rhs = assignmentExpression(false); 3212 propertyValue = verifyAssignment(assignToken, propertyValue, rhs); 3213 } 3214 } else { 3215 expect(COLON); 3216 3217 defaultNames.push(propertyName); 3218 try { 3219 propertyValue = assignmentExpression(false); 3220 } finally { 3221 defaultNames.pop(); 3222 } 3223 } 3224 3225 return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed); 3226 } 3227 3228 private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) { 3229 return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD); 3230 } 3231 3232 private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) { 3233 final boolean computed = type == LBRACKET; 3234 final Expression propertyName = propertyName(); 3235 final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false); 3236 final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName)); 3237 expect(LPAREN); 3238 expect(RPAREN); 3239 3240 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList()); 3241 functionNode.setFlag(flags); 3242 if (computed) { 3243 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 3244 } 3245 lc.push(functionNode); 3246 3247 Block functionBody; 3248 3249 3250 try { 3251 functionBody = functionBody(functionNode); 3252 } finally { 3253 lc.pop(functionNode); 3254 } 3255 3256 final FunctionNode function = createFunctionNode( 3257 functionNode, 3258 getSetToken, 3259 getNameNode, 3260 Collections.<IdentNode>emptyList(), 3261 FunctionNode.Kind.GETTER, 3262 functionLine, 3263 functionBody); 3264 3265 return new PropertyFunction(propertyName, function, computed); 3266 } 3267 3268 private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) { 3269 return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD); 3270 } 3271 3272 private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) { 3273 final boolean computed = type == LBRACKET; 3274 final Expression propertyName = propertyName(); 3275 final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false); 3276 final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName)); 3277 expect(LPAREN); 3278 // be sloppy and allow missing setter parameter even though 3279 // spec does not permit it! 3280 final IdentNode argIdent; 3281 if (isBindingIdentifier()) { 3282 argIdent = getIdent(); 3283 verifyIdent(argIdent, "setter argument"); 3284 } else { 3285 argIdent = null; 3286 } 3287 expect(RPAREN); 3288 final List<IdentNode> parameters = new ArrayList<>(); 3289 if (argIdent != null) { 3290 parameters.add(argIdent); 3291 } 3292 3293 3294 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters); 3295 functionNode.setFlag(flags); 3296 if (computed) { 3297 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 3298 } 3299 lc.push(functionNode); 3300 3301 Block functionBody; 3302 try { 3303 functionBody = functionBody(functionNode); 3304 } finally { 3305 lc.pop(functionNode); 3306 } 3307 3308 3309 final FunctionNode function = createFunctionNode( 3310 functionNode, 3311 getSetToken, 3312 setNameNode, 3313 parameters, 3314 FunctionNode.Kind.SETTER, 3315 functionLine, 3316 functionBody); 3317 3318 return new PropertyFunction(propertyName, function, computed); 3319 } 3320 3321 private PropertyFunction propertyMethodFunction(final Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, final boolean computed) { 3322 final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false); 3323 final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName); 3324 3325 final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL; 3326 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null); 3327 functionNode.setFlag(flags); 3328 if (computed) { 3329 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 3330 } 3331 lc.push(functionNode); 3332 3333 try { 3334 final ParserContextBlockNode parameterBlock = newBlock(); 3335 final List<IdentNode> parameters; 3336 try { 3337 expect(LPAREN); 3338 parameters = formalParameterList(generator); 3339 functionNode.setParameters(parameters); 3340 expect(RPAREN); 3341 } finally { 3342 restoreBlock(parameterBlock); 3343 } 3344 3345 Block functionBody = functionBody(functionNode); 3346 3347 functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock); 3348 3349 final FunctionNode function = createFunctionNode( 3350 functionNode, 3351 methodToken, 3352 methodNameNode, 3353 parameters, 3354 functionKind, 3355 methodLine, 3356 functionBody); 3357 return new PropertyFunction(key, function, computed); 3358 } finally { 3359 lc.pop(functionNode); 3360 } 3361 } 3362 3363 private static class PropertyFunction { 3364 final Expression key; 3365 final FunctionNode functionNode; 3366 final boolean computed; 3367 3368 PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) { 3369 this.key = key; 3370 this.functionNode = function; 3371 this.computed = computed; 3372 } 3373 } 3374 3375 /** 3376 * LeftHandSideExpression : 3377 * NewExpression 3378 * CallExpression 3379 * 3380 * CallExpression : 3381 * MemberExpression Arguments 3382 * SuperCall 3383 * CallExpression Arguments 3384 * CallExpression [ Expression ] 3385 * CallExpression . IdentifierName 3386 * 3387 * SuperCall : 3388 * super Arguments 3389 * 3390 * See 11.2 3391 * 3392 * Parse left hand side expression. 3393 * @return Expression node. 3394 */ 3395 private Expression leftHandSideExpression() { 3396 int callLine = line; 3397 long callToken = token; 3398 3399 Expression lhs = memberExpression(); 3400 3401 if (type == LPAREN) { 3402 final List<Expression> arguments = optimizeList(argumentList()); 3403 3404 // Catch special functions. 3405 if (lhs instanceof IdentNode) { 3406 detectSpecialFunction((IdentNode)lhs); 3407 } 3408 3409 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); 3410 } 3411 3412 loop: 3413 while (true) { 3414 // Capture token. 3415 callLine = line; 3416 callToken = token; 3417 3418 switch (type) { 3419 case LPAREN: { 3420 // Get NEW or FUNCTION arguments. 3421 final List<Expression> arguments = optimizeList(argumentList()); 3422 3423 // Create call node. 3424 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); 3425 3426 break; 3427 } 3428 case LBRACKET: { 3429 next(); 3430 3431 // Get array index. 3432 final Expression rhs = expression(); 3433 3434 expect(RBRACKET); 3435 3436 // Create indexing node. 3437 lhs = new IndexNode(callToken, finish, lhs, rhs); 3438 3439 break; 3440 } 3441 case PERIOD: { 3442 next(); 3443 3444 final IdentNode property = getIdentifierName(); 3445 3446 // Create property access node. 3447 lhs = new AccessNode(callToken, finish, lhs, property.getName()); 3448 3449 break; 3450 } 3451 case TEMPLATE: 3452 case TEMPLATE_HEAD: { 3453 // tagged template literal 3454 final List<Expression> arguments = templateLiteralArgumentList(); 3455 3456 // Create call node. 3457 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); 3458 3459 break; 3460 } 3461 default: 3462 break loop; 3463 } 3464 } 3465 3466 return lhs; 3467 } 3468 3469 /** 3470 * NewExpression : 3471 * MemberExpression 3472 * new NewExpression 3473 * 3474 * See 11.2 3475 * 3476 * Parse new expression. 3477 * @return Expression node. 3478 */ 3479 private Expression newExpression() { 3480 final long newToken = token; 3481 // NEW is tested in caller. 3482 next(); 3483 3484 if (type == PERIOD && isES6()) { 3485 next(); 3486 if (type == IDENT && "target".equals(getValue())) { 3487 if (lc.getCurrentFunction().isProgram()) { 3488 throw error(AbstractParser.message("new.target.in.function"), token); 3489 } 3490 next(); 3491 markNewTarget(lc); 3492 return new IdentNode(newToken, finish, "new.target"); 3493 } else { 3494 throw error(AbstractParser.message("expected.target"), token); 3495 } 3496 } 3497 3498 // Get function base. 3499 final int callLine = line; 3500 final Expression constructor = memberExpression(); 3501 if (constructor == null) { 3502 return null; 3503 } 3504 // Get arguments. 3505 ArrayList<Expression> arguments; 3506 3507 // Allow for missing arguments. 3508 if (type == LPAREN) { 3509 arguments = argumentList(); 3510 } else { 3511 arguments = new ArrayList<>(); 3512 } 3513 3514 // Nashorn extension: This is to support the following interface implementation 3515 // syntax: 3516 // 3517 // var r = new java.lang.Runnable() { 3518 // run: function() { println("run"); } 3519 // }; 3520 // 3521 // The object literal following the "new Constructor()" expression 3522 // is passed as an additional (last) argument to the constructor. 3523 if (!env._no_syntax_extensions && type == LBRACE) { 3524 arguments.add(objectLiteral()); 3525 } 3526 3527 final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true); 3528 3529 return new UnaryNode(newToken, callNode); 3530 } 3531 3532 /** 3533 * MemberExpression : 3534 * PrimaryExpression 3535 * FunctionExpression 3536 * ClassExpression 3537 * GeneratorExpression 3538 * MemberExpression [ Expression ] 3539 * MemberExpression . IdentifierName 3540 * MemberExpression TemplateLiteral 3541 * SuperProperty 3542 * MetaProperty 3543 * new MemberExpression Arguments 3544 * 3545 * SuperProperty : 3546 * super [ Expression ] 3547 * super . IdentifierName 3548 * 3549 * MetaProperty : 3550 * NewTarget 3551 * 3552 * Parse member expression. 3553 * @return Expression node. 3554 */ 3555 @SuppressWarnings("fallthrough") 3556 private Expression memberExpression() { 3557 // Prepare to build operation. 3558 Expression lhs; 3559 boolean isSuper = false; 3560 3561 switch (type) { 3562 case NEW: 3563 // Get new expression. 3564 lhs = newExpression(); 3565 break; 3566 3567 case FUNCTION: 3568 // Get function expression. 3569 lhs = functionExpression(false, false); 3570 break; 3571 3572 case CLASS: 3573 if (isES6()) { 3574 lhs = classExpression(false); 3575 break; 3576 } else { 3577 // fall through 3578 } 3579 3580 case SUPER: 3581 if (isES6()) { 3582 final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction(); 3583 if (currentFunction.isMethod()) { 3584 final long identToken = Token.recast(token, IDENT); 3585 next(); 3586 lhs = createIdentNode(identToken, finish, SUPER.getName()); 3587 3588 switch (type) { 3589 case LBRACKET: 3590 case PERIOD: 3591 getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER); 3592 isSuper = true; 3593 break; 3594 case LPAREN: 3595 if (currentFunction.isSubclassConstructor()) { 3596 lhs = ((IdentNode)lhs).setIsDirectSuper(); 3597 break; 3598 } else { 3599 // fall through to throw error 3600 } 3601 default: 3602 throw error(AbstractParser.message("invalid.super"), identToken); 3603 } 3604 break; 3605 } else { 3606 // fall through 3607 } 3608 } else { 3609 // fall through 3610 } 3611 3612 default: 3613 // Get primary expression. 3614 lhs = primaryExpression(); 3615 break; 3616 } 3617 3618 loop: 3619 while (true) { 3620 // Capture token. 3621 final long callToken = token; 3622 3623 switch (type) { 3624 case LBRACKET: { 3625 next(); 3626 3627 // Get array index. 3628 final Expression index = expression(); 3629 3630 expect(RBRACKET); 3631 3632 // Create indexing node. 3633 lhs = new IndexNode(callToken, finish, lhs, index); 3634 3635 if (isSuper) { 3636 isSuper = false; 3637 lhs = ((BaseNode) lhs).setIsSuper(); 3638 } 3639 3640 break; 3641 } 3642 case PERIOD: { 3643 if (lhs == null) { 3644 throw error(AbstractParser.message("expected.operand", type.getNameOrType())); 3645 } 3646 3647 next(); 3648 3649 final IdentNode property = getIdentifierName(); 3650 3651 // Create property access node. 3652 lhs = new AccessNode(callToken, finish, lhs, property.getName()); 3653 3654 if (isSuper) { 3655 isSuper = false; 3656 lhs = ((BaseNode) lhs).setIsSuper(); 3657 } 3658 3659 break; 3660 } 3661 case TEMPLATE: 3662 case TEMPLATE_HEAD: { 3663 // tagged template literal 3664 final int callLine = line; 3665 final List<Expression> arguments = templateLiteralArgumentList(); 3666 3667 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); 3668 3669 break; 3670 } 3671 default: 3672 break loop; 3673 } 3674 } 3675 3676 return lhs; 3677 } 3678 3679 /** 3680 * Arguments : 3681 * ( ) 3682 * ( ArgumentList ) 3683 * 3684 * ArgumentList : 3685 * AssignmentExpression 3686 * ... AssignmentExpression 3687 * ArgumentList , AssignmentExpression 3688 * ArgumentList , ... AssignmentExpression 3689 * 3690 * See 11.2 3691 * 3692 * Parse function call arguments. 3693 * @return Argument list. 3694 */ 3695 private ArrayList<Expression> argumentList() { 3696 // Prepare to accumulate list of arguments. 3697 final ArrayList<Expression> nodeList = new ArrayList<>(); 3698 // LPAREN tested in caller. 3699 next(); 3700 3701 // Track commas. 3702 boolean first = true; 3703 3704 while (type != RPAREN) { 3705 // Comma prior to every argument except the first. 3706 if (!first) { 3707 expect(COMMARIGHT); 3708 } else { 3709 first = false; 3710 } 3711 3712 long spreadToken = 0; 3713 if (type == ELLIPSIS && isES6()) { 3714 spreadToken = token; 3715 next(); 3716 } 3717 3718 // Get argument expression. 3719 Expression expression = assignmentExpression(false); 3720 if (spreadToken != 0) { 3721 expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression); 3722 } 3723 nodeList.add(expression); 3724 } 3725 3726 expect(RPAREN); 3727 return nodeList; 3728 } 3729 3730 private static <T> List<T> optimizeList(final ArrayList<T> list) { 3731 switch(list.size()) { 3732 case 0: { 3733 return Collections.emptyList(); 3734 } 3735 case 1: { 3736 return Collections.singletonList(list.get(0)); 3737 } 3738 default: { 3739 list.trimToSize(); 3740 return list; 3741 } 3742 } 3743 } 3744 3745 /** 3746 * FunctionDeclaration : 3747 * function Identifier ( FormalParameterList? ) { FunctionBody } 3748 * 3749 * FunctionExpression : 3750 * function Identifier? ( FormalParameterList? ) { FunctionBody } 3751 * 3752 * See 13 3753 * 3754 * Parse function declaration. 3755 * @param isStatement True if for is a statement. 3756 * 3757 * @return Expression node. 3758 */ 3759 private Expression functionExpression(final boolean isStatement, final boolean topLevel) { 3760 final long functionToken = token; 3761 final int functionLine = line; 3762 // FUNCTION is tested in caller. 3763 assert type == FUNCTION; 3764 next(); 3765 3766 boolean generator = false; 3767 if (type == MUL && isES6()) { 3768 generator = true; 3769 next(); 3770 } 3771 3772 IdentNode name = null; 3773 3774 if (isBindingIdentifier()) { 3775 if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) { 3776 // 12.1.1 Early SyntaxError if: 3777 // GeneratorExpression with BindingIdentifier yield 3778 // HoistableDeclaration with BindingIdentifier yield in generator function body 3779 expect(IDENT); 3780 } 3781 name = getIdent(); 3782 verifyStrictIdent(name, "function name"); 3783 } else if (isStatement) { 3784 // Nashorn extension: anonymous function statements. 3785 // Do not allow anonymous function statement if extensions 3786 // are now allowed. But if we are reparsing then anon function 3787 // statement is possible - because it was used as function 3788 // expression in surrounding code. 3789 if (env._no_syntax_extensions && reparsedFunction == null) { 3790 expect(IDENT); 3791 } 3792 } 3793 3794 // name is null, generate anonymous name 3795 boolean isAnonymous = false; 3796 if (name == null) { 3797 final String tmpName = getDefaultValidFunctionName(functionLine, isStatement); 3798 name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName); 3799 isAnonymous = true; 3800 } 3801 3802 final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL; 3803 List<IdentNode> parameters = Collections.emptyList(); 3804 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters); 3805 lc.push(functionNode); 3806 3807 Block functionBody = null; 3808 // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}" 3809 // If we didn't hide the current default name, then the innermost anonymous function would receive "x3". 3810 hideDefaultName(); 3811 try { 3812 final ParserContextBlockNode parameterBlock = newBlock(); 3813 try { 3814 expect(LPAREN); 3815 parameters = formalParameterList(generator); 3816 functionNode.setParameters(parameters); 3817 expect(RPAREN); 3818 } finally { 3819 restoreBlock(parameterBlock); 3820 } 3821 3822 functionBody = functionBody(functionNode); 3823 3824 functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock); 3825 } finally { 3826 defaultNames.pop(); 3827 lc.pop(functionNode); 3828 } 3829 3830 if (isStatement) { 3831 if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) { 3832 functionNode.setFlag(FunctionNode.IS_DECLARED); 3833 } else if (isStrictMode) { 3834 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken); 3835 } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) { 3836 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken); 3837 } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) { 3838 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken); 3839 } 3840 if (isArguments(name)) { 3841 lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS); 3842 } 3843 } 3844 3845 if (isAnonymous) { 3846 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 3847 } 3848 3849 verifyParameterList(parameters, functionNode); 3850 3851 final FunctionNode function = createFunctionNode( 3852 functionNode, 3853 functionToken, 3854 name, 3855 parameters, 3856 functionKind, 3857 functionLine, 3858 functionBody); 3859 3860 if (isStatement) { 3861 if (isAnonymous) { 3862 appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function)); 3863 return function; 3864 } 3865 3866 // mark ES6 block functions as lexically scoped 3867 final int varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET; 3868 final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, function, varFlags); 3869 if (topLevel) { 3870 functionDeclarations.add(varNode); 3871 } else if (useBlockScope()) { 3872 prependStatement(varNode); // Hoist to beginning of current block 3873 } else { 3874 appendStatement(varNode); 3875 } 3876 } 3877 3878 return function; 3879 } 3880 3881 private void verifyParameterList(final List<IdentNode> parameters, final ParserContextFunctionNode functionNode) { 3882 final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding(); 3883 if (duplicateParameter != null) { 3884 if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) { 3885 throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken()); 3886 } 3887 3888 final int arity = parameters.size(); 3889 final HashSet<String> parametersSet = new HashSet<>(arity); 3890 3891 for (int i = arity - 1; i >= 0; i--) { 3892 final IdentNode parameter = parameters.get(i); 3893 String parameterName = parameter.getName(); 3894 3895 if (parametersSet.contains(parameterName)) { 3896 // redefinition of parameter name, rename in non-strict mode 3897 parameterName = functionNode.uniqueName(parameterName); 3898 final long parameterToken = parameter.getToken(); 3899 parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName))); 3900 } 3901 parametersSet.add(parameterName); 3902 } 3903 } 3904 } 3905 3906 private static Block maybeWrapBodyInParameterBlock(final Block functionBody, final ParserContextBlockNode parameterBlock) { 3907 assert functionBody.isFunctionBody(); 3908 if (!parameterBlock.getStatements().isEmpty()) { 3909 parameterBlock.appendStatement(new BlockStatement(functionBody)); 3910 return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements()); 3911 } 3912 return functionBody; 3913 } 3914 3915 private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) { 3916 final String defaultFunctionName = getDefaultFunctionName(); 3917 if (isValidIdentifier(defaultFunctionName)) { 3918 if (isStatement) { 3919 // The name will be used as the LHS of a symbol assignment. We add the anonymous function 3920 // prefix to ensure that it can't clash with another variable. 3921 return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName; 3922 } 3923 return defaultFunctionName; 3924 } 3925 return ANON_FUNCTION_PREFIX.symbolName() + functionLine; 3926 } 3927 3928 private static boolean isValidIdentifier(final String name) { 3929 if (name == null || name.isEmpty()) { 3930 return false; 3931 } 3932 if (!Character.isJavaIdentifierStart(name.charAt(0))) { 3933 return false; 3934 } 3935 for (int i = 1; i < name.length(); ++i) { 3936 if (!Character.isJavaIdentifierPart(name.charAt(i))) { 3937 return false; 3938 } 3939 } 3940 return true; 3941 } 3942 3943 private String getDefaultFunctionName() { 3944 if (!defaultNames.isEmpty()) { 3945 final Object nameExpr = defaultNames.peek(); 3946 if (nameExpr instanceof PropertyKey) { 3947 markDefaultNameUsed(); 3948 return ((PropertyKey)nameExpr).getPropertyName(); 3949 } else if (nameExpr instanceof AccessNode) { 3950 markDefaultNameUsed(); 3951 return ((AccessNode)nameExpr).getProperty(); 3952 } 3953 } 3954 return null; 3955 } 3956 3957 private void markDefaultNameUsed() { 3958 defaultNames.pop(); 3959 hideDefaultName(); 3960 } 3961 3962 private void hideDefaultName() { 3963 // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value 3964 // from. Can't be null 3965 defaultNames.push(""); 3966 } 3967 3968 /** 3969 * FormalParameterList : 3970 * Identifier 3971 * FormalParameterList , Identifier 3972 * 3973 * See 13 3974 * 3975 * Parse function parameter list. 3976 * @return List of parameter nodes. 3977 */ 3978 private List<IdentNode> formalParameterList(final boolean yield) { 3979 return formalParameterList(RPAREN, yield); 3980 } 3981 3982 /** 3983 * Same as the other method of the same name - except that the end 3984 * token type expected is passed as argument to this method. 3985 * 3986 * FormalParameterList : 3987 * Identifier 3988 * FormalParameterList , Identifier 3989 * 3990 * See 13 3991 * 3992 * Parse function parameter list. 3993 * @return List of parameter nodes. 3994 */ 3995 private List<IdentNode> formalParameterList(final TokenType endType, final boolean yield) { 3996 // Prepare to gather parameters. 3997 final ArrayList<IdentNode> parameters = new ArrayList<>(); 3998 // Track commas. 3999 boolean first = true; 4000 4001 while (type != endType) { 4002 // Comma prior to every argument except the first. 4003 if (!first) { 4004 expect(COMMARIGHT); 4005 } else { 4006 first = false; 4007 } 4008 4009 boolean restParameter = false; 4010 if (type == ELLIPSIS && isES6()) { 4011 next(); 4012 restParameter = true; 4013 } 4014 4015 if (type == YIELD && yield) { 4016 expect(IDENT); 4017 } 4018 4019 final long paramToken = token; 4020 final int paramLine = line; 4021 final String contextString = "function parameter"; 4022 IdentNode ident; 4023 if (isBindingIdentifier() || restParameter || !isES6()) { 4024 ident = bindingIdentifier(contextString); 4025 4026 if (restParameter) { 4027 ident = ident.setIsRestParameter(); 4028 // rest parameter must be last 4029 expectDontAdvance(endType); 4030 parameters.add(ident); 4031 break; 4032 } else if (type == ASSIGN && isES6()) { 4033 next(); 4034 ident = ident.setIsDefaultParameter(); 4035 4036 if (type == YIELD && yield) { 4037 // error: yield in default expression 4038 expect(IDENT); 4039 } 4040 4041 // default parameter 4042 final Expression initializer = assignmentExpression(false); 4043 4044 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4045 if (currentFunction != null) { 4046 if (env._parse_only) { 4047 // keep what is seen in source "as is" and save it as parameter expression 4048 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, initializer); 4049 currentFunction.addParameterExpression(ident, assignment); 4050 } else { 4051 // desugar to: param = (param === undefined) ? initializer : param; 4052 // possible alternative: if (param === undefined) param = initializer; 4053 final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); 4054 final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); 4055 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value); 4056 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4057 } 4058 } 4059 } 4060 4061 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4062 if (currentFunction != null) { 4063 currentFunction.addParameterBinding(ident); 4064 if (ident.isRestParameter() || ident.isDefaultParameter()) { 4065 currentFunction.setSimpleParameterList(false); 4066 } 4067 } 4068 } else { 4069 final Expression pattern = bindingPattern(); 4070 // Introduce synthetic temporary parameter to capture the object to be destructured. 4071 ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter(); 4072 verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString); 4073 4074 Expression value = ident; 4075 if (type == ASSIGN) { 4076 next(); 4077 ident = ident.setIsDefaultParameter(); 4078 4079 // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param 4080 final Expression initializer = assignmentExpression(false); 4081 4082 if (env._parse_only) { 4083 // we don't want the synthetic identifier in parse only mode 4084 value = initializer; 4085 } else { 4086 // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list) 4087 final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); 4088 value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); 4089 } 4090 } 4091 4092 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4093 if (currentFunction != null) { 4094 // destructuring assignment 4095 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value); 4096 if (env._parse_only) { 4097 // in parse-only mode, represent source tree "as is" 4098 if (ident.isDefaultParameter()) { 4099 currentFunction.addParameterExpression(ident, assignment); 4100 } else { 4101 currentFunction.addParameterExpression(ident, pattern); 4102 } 4103 } else { 4104 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4105 } 4106 } 4107 } 4108 parameters.add(ident); 4109 } 4110 4111 parameters.trimToSize(); 4112 return parameters; 4113 } 4114 4115 private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) { 4116 verifyDestructuringBindingPattern(pattern, new Consumer<IdentNode>() { 4117 public void accept(final IdentNode identNode) { 4118 verifyIdent(identNode, contextString); 4119 4120 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4121 if (currentFunction != null) { 4122 // declare function-scope variables for destructuring bindings 4123 if (!env._parse_only) { 4124 lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null)); 4125 } 4126 // detect duplicate bounds names in parameter list 4127 currentFunction.addParameterBinding(identNode); 4128 currentFunction.setSimpleParameterList(false); 4129 } 4130 } 4131 }); 4132 } 4133 4134 /** 4135 * FunctionBody : 4136 * SourceElements? 4137 * 4138 * See 13 4139 * 4140 * Parse function body. 4141 * @return function node (body.) 4142 */ 4143 private Block functionBody(final ParserContextFunctionNode functionNode) { 4144 long lastToken = 0L; 4145 ParserContextBlockNode body = null; 4146 final long bodyToken = token; 4147 Block functionBody; 4148 int bodyFinish = 0; 4149 4150 final boolean parseBody; 4151 Object endParserState = null; 4152 try { 4153 // Create a new function block. 4154 body = newBlock(); 4155 if (env._debug_scopes) { 4156 // debug scope options forces everything to be in scope 4157 markEval(lc); 4158 } 4159 assert functionNode != null; 4160 final int functionId = functionNode.getId(); 4161 parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId(); 4162 // Nashorn extension: expression closures 4163 if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) { 4164 /* 4165 * Example: 4166 * 4167 * function square(x) x * x; 4168 * print(square(3)); 4169 */ 4170 4171 // just expression as function body 4172 final Expression expr = assignmentExpression(false); 4173 lastToken = previousToken; 4174 functionNode.setLastToken(previousToken); 4175 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode); 4176 // EOL uses length field to store the line number 4177 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken)); 4178 // Only create the return node if we aren't skipping nested functions. Note that we aren't 4179 // skipping parsing of these extended functions; they're considered to be small anyway. Also, 4180 // they don't end with a single well known token, so it'd be very hard to get correctly (see 4181 // the note below for reasoning on skipping happening before instead of after RBRACE for 4182 // details). 4183 if (parseBody) { 4184 functionNode.setFlag(FunctionNode.HAS_EXPRESSION_BODY); 4185 final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr); 4186 appendStatement(returnNode); 4187 } 4188 // bodyFinish = finish; 4189 } else { 4190 expectDontAdvance(LBRACE); 4191 if (parseBody || !skipFunctionBody(functionNode)) { 4192 next(); 4193 // Gather the function elements. 4194 final List<Statement> prevFunctionDecls = functionDeclarations; 4195 functionDeclarations = new ArrayList<>(); 4196 try { 4197 sourceElements(0); 4198 addFunctionDeclarations(functionNode); 4199 } finally { 4200 functionDeclarations = prevFunctionDecls; 4201 } 4202 4203 lastToken = token; 4204 if (parseBody) { 4205 // Since the lexer can read ahead and lexify some number of tokens in advance and have 4206 // them buffered in the TokenStream, we need to produce a lexer state as it was just 4207 // before it lexified RBRACE, and not whatever is its current (quite possibly well read 4208 // ahead) state. 4209 endParserState = new ParserState(Token.descPosition(token), line, linePosition); 4210 4211 // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of 4212 // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the 4213 // state after it. The reason is that RBRACE is a well-known token that we can expect and 4214 // will never involve us getting into a weird lexer state, and as such is a great reparse 4215 // point. Typical example of a weird lexer state after RBRACE would be: 4216 // function this_is_skipped() { ... } "use strict"; 4217 // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead 4218 // of compensating for the possibility of a string literal (or similar) after RBRACE, 4219 // we'll rather just restart parsing from this well-known, friendly token instead. 4220 } 4221 } 4222 bodyFinish = finish; 4223 functionNode.setLastToken(token); 4224 expect(RBRACE); 4225 } 4226 } finally { 4227 restoreBlock(body); 4228 } 4229 4230 // NOTE: we can only do alterations to the function node after restoreFunctionNode. 4231 4232 if (parseBody) { 4233 functionNode.setEndParserState(endParserState); 4234 } else if (!body.getStatements().isEmpty()){ 4235 // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see 4236 // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to 4237 // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as 4238 // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away 4239 // nested bodies early if we were supposed to skip 'em. 4240 body.setStatements(Collections.<Statement>emptyList()); 4241 } 4242 4243 if (reparsedFunction != null) { 4244 // We restore the flags stored in the function's ScriptFunctionData that we got when we first 4245 // eagerly parsed the code. We're doing it because some flags would be set based on the 4246 // content of the function, or even content of its nested functions, most of which are normally 4247 // skipped during an on-demand compilation. 4248 final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId()); 4249 if (data != null) { 4250 // Data can be null if when we originally parsed the file, we removed the function declaration 4251 // as it was dead code. 4252 functionNode.setFlag(data.getFunctionFlags()); 4253 // This compensates for missing markEval() in case the function contains an inner function 4254 // that contains eval(), that now we didn't discover since we skipped the inner function. 4255 if (functionNode.hasNestedEval()) { 4256 assert functionNode.hasScopeBlock(); 4257 body.setFlag(Block.NEEDS_SCOPE); 4258 } 4259 } 4260 } 4261 functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements()); 4262 return functionBody; 4263 } 4264 4265 private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) { 4266 if (reparsedFunction == null) { 4267 // Not reparsing, so don't skip any function body. 4268 return false; 4269 } 4270 // Skip to the RBRACE of this function, and continue parsing from there. 4271 final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId()); 4272 if (data == null) { 4273 // Nested function is not known to the reparsed function. This can happen if the FunctionNode was 4274 // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the 4275 // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it. 4276 return false; 4277 } 4278 final ParserState parserState = (ParserState)data.getEndParserState(); 4279 assert parserState != null; 4280 4281 if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) { 4282 // RBRACE is already in the token stream, so fast forward to it 4283 for (; k < stream.last(); k++) { 4284 final long nextToken = stream.get(k + 1); 4285 if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) { 4286 token = stream.get(k); 4287 type = Token.descType(token); 4288 next(); 4289 assert type == RBRACE && start == parserState.position; 4290 return true; 4291 } 4292 } 4293 } 4294 4295 stream.reset(); 4296 lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6); 4297 line = parserState.line; 4298 linePosition = parserState.linePosition; 4299 // Doesn't really matter, but it's safe to treat it as if there were a semicolon before 4300 // the RBRACE. 4301 type = SEMICOLON; 4302 scanFirstToken(); 4303 4304 return true; 4305 } 4306 4307 /** 4308 * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer 4309 * for resuming parsing after skipping a function body. 4310 */ 4311 private static class ParserState implements Serializable { 4312 private final int position; 4313 private final int line; 4314 private final int linePosition; 4315 4316 private static final long serialVersionUID = -2382565130754093694L; 4317 4318 ParserState(final int position, final int line, final int linePosition) { 4319 this.position = position; 4320 this.line = line; 4321 this.linePosition = linePosition; 4322 } 4323 4324 Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) { 4325 final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true); 4326 newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON)); 4327 return newLexer; 4328 } 4329 } 4330 4331 private void printAST(final FunctionNode functionNode) { 4332 if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) { 4333 env.getErr().println(new ASTWriter(functionNode)); 4334 } 4335 4336 if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) { 4337 env.getErr().println(new PrintVisitor(functionNode, true, false)); 4338 } 4339 } 4340 4341 private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) { 4342 VarNode lastDecl = null; 4343 for (int i = functionDeclarations.size() - 1; i >= 0; i--) { 4344 Statement decl = functionDeclarations.get(i); 4345 if (lastDecl == null && decl instanceof VarNode) { 4346 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION); 4347 functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS); 4348 } 4349 prependStatement(decl); 4350 } 4351 } 4352 4353 private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) { 4354 if (env._parse_only || earlyError) { 4355 throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken()); 4356 } 4357 final ArrayList<Expression> args = new ArrayList<>(); 4358 args.add(lhs); 4359 if (rhs == null) { 4360 args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish())); 4361 } else { 4362 args.add(rhs); 4363 } 4364 args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString())); 4365 return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args); 4366 } 4367 4368 /** 4369 * PostfixExpression : 4370 * LeftHandSideExpression 4371 * LeftHandSideExpression ++ // [no LineTerminator here] 4372 * LeftHandSideExpression -- // [no LineTerminator here] 4373 * 4374 * See 11.3 4375 * 4376 * UnaryExpression : 4377 * PostfixExpression 4378 * delete UnaryExpression 4379 * void UnaryExpression 4380 * typeof UnaryExpression 4381 * ++ UnaryExpression 4382 * -- UnaryExpression 4383 * + UnaryExpression 4384 * - UnaryExpression 4385 * ~ UnaryExpression 4386 * ! UnaryExpression 4387 * 4388 * See 11.4 4389 * 4390 * Parse unary expression. 4391 * @return Expression node. 4392 */ 4393 private Expression unaryExpression() { 4394 final int unaryLine = line; 4395 final long unaryToken = token; 4396 4397 switch (type) { 4398 case DELETE: { 4399 next(); 4400 final Expression expr = unaryExpression(); 4401 if (expr instanceof BaseNode || expr instanceof IdentNode) { 4402 return new UnaryNode(unaryToken, expr); 4403 } 4404 appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr)); 4405 return LiteralNode.newInstance(unaryToken, finish, true); 4406 } 4407 case ADD: 4408 case SUB: { 4409 final TokenType opType = type; 4410 next(); 4411 final Expression expr = unaryExpression(); 4412 return new UnaryNode(Token.recast(unaryToken, (opType == TokenType.ADD) ? TokenType.POS : TokenType.NEG), expr); 4413 } 4414 case VOID: 4415 case TYPEOF: 4416 case BIT_NOT: 4417 case NOT: 4418 next(); 4419 final Expression expr = unaryExpression(); 4420 return new UnaryNode(unaryToken, expr); 4421 4422 case INCPREFIX: 4423 case DECPREFIX: 4424 final TokenType opType = type; 4425 next(); 4426 4427 final Expression lhs = leftHandSideExpression(); 4428 // ++, -- without operand.. 4429 if (lhs == null) { 4430 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType())); 4431 } 4432 4433 return verifyIncDecExpression(unaryToken, opType, lhs, false); 4434 4435 default: 4436 break; 4437 } 4438 4439 final Expression expression = leftHandSideExpression(); 4440 4441 if (last != EOL) { 4442 switch (type) { 4443 case INCPREFIX: 4444 case DECPREFIX: 4445 final long opToken = token; 4446 final TokenType opType = type; 4447 final Expression lhs = expression; 4448 // ++, -- without operand.. 4449 if (lhs == null) { 4450 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType())); 4451 } 4452 next(); 4453 4454 return verifyIncDecExpression(opToken, opType, lhs, true); 4455 default: 4456 break; 4457 } 4458 } 4459 4460 if (expression == null) { 4461 throw error(AbstractParser.message("expected.operand", type.getNameOrType())); 4462 } 4463 4464 return expression; 4465 } 4466 4467 private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) { 4468 assert lhs != null; 4469 4470 if (!(lhs instanceof AccessNode || 4471 lhs instanceof IndexNode || 4472 lhs instanceof IdentNode)) { 4473 return referenceError(lhs, null, env._early_lvalue_error); 4474 } 4475 4476 if (lhs instanceof IdentNode) { 4477 if (!checkIdentLValue((IdentNode)lhs)) { 4478 return referenceError(lhs, null, false); 4479 } 4480 verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator"); 4481 } 4482 4483 return incDecExpression(unaryToken, opType, lhs, isPostfix); 4484 } 4485 4486 /** 4487 * {@code 4488 * MultiplicativeExpression : 4489 * UnaryExpression 4490 * MultiplicativeExpression * UnaryExpression 4491 * MultiplicativeExpression / UnaryExpression 4492 * MultiplicativeExpression % UnaryExpression 4493 * 4494 * See 11.5 4495 * 4496 * AdditiveExpression : 4497 * MultiplicativeExpression 4498 * AdditiveExpression + MultiplicativeExpression 4499 * AdditiveExpression - MultiplicativeExpression 4500 * 4501 * See 11.6 4502 * 4503 * ShiftExpression : 4504 * AdditiveExpression 4505 * ShiftExpression << AdditiveExpression 4506 * ShiftExpression >> AdditiveExpression 4507 * ShiftExpression >>> AdditiveExpression 4508 * 4509 * See 11.7 4510 * 4511 * RelationalExpression : 4512 * ShiftExpression 4513 * RelationalExpression < ShiftExpression 4514 * RelationalExpression > ShiftExpression 4515 * RelationalExpression <= ShiftExpression 4516 * RelationalExpression >= ShiftExpression 4517 * RelationalExpression instanceof ShiftExpression 4518 * RelationalExpression in ShiftExpression // if !noIf 4519 * 4520 * See 11.8 4521 * 4522 * RelationalExpression 4523 * EqualityExpression == RelationalExpression 4524 * EqualityExpression != RelationalExpression 4525 * EqualityExpression === RelationalExpression 4526 * EqualityExpression !== RelationalExpression 4527 * 4528 * See 11.9 4529 * 4530 * BitwiseANDExpression : 4531 * EqualityExpression 4532 * BitwiseANDExpression & EqualityExpression 4533 * 4534 * BitwiseXORExpression : 4535 * BitwiseANDExpression 4536 * BitwiseXORExpression ^ BitwiseANDExpression 4537 * 4538 * BitwiseORExpression : 4539 * BitwiseXORExpression 4540 * BitwiseORExpression | BitwiseXORExpression 4541 * 4542 * See 11.10 4543 * 4544 * LogicalANDExpression : 4545 * BitwiseORExpression 4546 * LogicalANDExpression && BitwiseORExpression 4547 * 4548 * LogicalORExpression : 4549 * LogicalANDExpression 4550 * LogicalORExpression || LogicalANDExpression 4551 * 4552 * See 11.11 4553 * 4554 * ConditionalExpression : 4555 * LogicalORExpression 4556 * LogicalORExpression ? AssignmentExpression : AssignmentExpression 4557 * 4558 * See 11.12 4559 * 4560 * AssignmentExpression : 4561 * ConditionalExpression 4562 * LeftHandSideExpression AssignmentOperator AssignmentExpression 4563 * 4564 * AssignmentOperator : 4565 * = *= /= %= += -= <<= >>= >>>= &= ^= |= 4566 * 4567 * See 11.13 4568 * 4569 * Expression : 4570 * AssignmentExpression 4571 * Expression , AssignmentExpression 4572 * 4573 * See 11.14 4574 * } 4575 * 4576 * Parse expression. 4577 * @return Expression node. 4578 */ 4579 protected Expression expression() { 4580 // This method is protected so that subclass can get details 4581 // at expression start point! 4582 4583 // Include commas in expression parsing. 4584 return expression(false); 4585 } 4586 4587 private Expression expression(final boolean noIn) { 4588 Expression assignmentExpression = assignmentExpression(noIn); 4589 while (type == COMMARIGHT) { 4590 final long commaToken = token; 4591 next(); 4592 4593 boolean rhsRestParameter = false; 4594 if (type == ELLIPSIS && isES6()) { 4595 // (a, b, ...rest) is not a valid expression, unless we're parsing the parameter list of an arrow function (we need to throw the right error). 4596 // But since the rest parameter is always last, at least we know that the expression has to end here and be followed by RPAREN and ARROW, so peek ahead. 4597 if (isRestParameterEndOfArrowFunctionParameterList()) { 4598 next(); 4599 rhsRestParameter = true; 4600 } 4601 } 4602 4603 Expression rhs = assignmentExpression(noIn); 4604 4605 if (rhsRestParameter) { 4606 rhs = ((IdentNode)rhs).setIsRestParameter(); 4607 // Our only valid move is to end Expression here and continue with ArrowFunction. 4608 // We've already checked that this is the parameter list of an arrow function (see above). 4609 // RPAREN is next, so we'll finish the binary expression and drop out of the loop. 4610 assert type == RPAREN; 4611 } 4612 4613 assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs); 4614 } 4615 return assignmentExpression; 4616 } 4617 4618 private Expression expression(final int minPrecedence, final boolean noIn) { 4619 return expression(unaryExpression(), minPrecedence, noIn); 4620 } 4621 4622 private JoinPredecessorExpression joinPredecessorExpression() { 4623 return new JoinPredecessorExpression(expression()); 4624 } 4625 4626 private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) { 4627 // Get the precedence of the next operator. 4628 int precedence = type.getPrecedence(); 4629 Expression lhs = exprLhs; 4630 4631 // While greater precedence. 4632 while (type.isOperator(noIn) && precedence >= minPrecedence) { 4633 // Capture the operator token. 4634 final long op = token; 4635 4636 if (type == TERNARY) { 4637 // Skip operator. 4638 next(); 4639 4640 // Pass expression. Middle expression of a conditional expression can be a "in" 4641 // expression - even in the contexts where "in" is not permitted. 4642 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false); 4643 4644 expect(COLON); 4645 4646 // Fail expression. 4647 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn); 4648 4649 // Build up node. 4650 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr)); 4651 } else { 4652 // Skip operator. 4653 next(); 4654 4655 // Get the next primary expression. 4656 Expression rhs; 4657 final boolean isAssign = Token.descType(op) == ASSIGN; 4658 if(isAssign) { 4659 defaultNames.push(lhs); 4660 } 4661 try { 4662 rhs = unaryExpression(); 4663 // Get precedence of next operator. 4664 int nextPrecedence = type.getPrecedence(); 4665 4666 // Subtask greater precedence. 4667 while (type.isOperator(noIn) && 4668 (nextPrecedence > precedence || 4669 nextPrecedence == precedence && !type.isLeftAssociative())) { 4670 rhs = expression(rhs, nextPrecedence, noIn); 4671 nextPrecedence = type.getPrecedence(); 4672 } 4673 } finally { 4674 if(isAssign) { 4675 defaultNames.pop(); 4676 } 4677 } 4678 lhs = verifyAssignment(op, lhs, rhs); 4679 } 4680 4681 precedence = type.getPrecedence(); 4682 } 4683 4684 return lhs; 4685 } 4686 4687 /** 4688 * AssignmentExpression. 4689 * 4690 * AssignmentExpression[In, Yield] : 4691 * ConditionalExpression[?In, ?Yield] 4692 * [+Yield] YieldExpression[?In] 4693 * ArrowFunction[?In, ?Yield] 4694 * LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield] 4695 * LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield] 4696 * 4697 * @param noIn {@code true} if IN operator should be ignored. 4698 * @return the assignment expression 4699 */ 4700 protected Expression assignmentExpression(final boolean noIn) { 4701 // This method is protected so that subclass can get details 4702 // at assignment expression start point! 4703 4704 if (type == YIELD && inGeneratorFunction() && isES6()) { 4705 return yieldExpression(noIn); 4706 } 4707 4708 final long startToken = token; 4709 final int startLine = line; 4710 final Expression exprLhs = conditionalExpression(noIn); 4711 4712 if (type == ARROW && isES6()) { 4713 if (checkNoLineTerminator()) { 4714 final Expression paramListExpr; 4715 if (exprLhs instanceof ExpressionList) { 4716 paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0)); 4717 } else { 4718 paramListExpr = exprLhs; 4719 } 4720 return arrowFunction(startToken, startLine, paramListExpr); 4721 } 4722 } 4723 assert !(exprLhs instanceof ExpressionList); 4724 4725 if (isAssignmentOperator(type)) { 4726 final boolean isAssign = type == ASSIGN; 4727 if (isAssign) { 4728 defaultNames.push(exprLhs); 4729 } 4730 try { 4731 final long assignToken = token; 4732 next(); 4733 final Expression exprRhs = assignmentExpression(noIn); 4734 return verifyAssignment(assignToken, exprLhs, exprRhs); 4735 } finally { 4736 if (isAssign) { 4737 defaultNames.pop(); 4738 } 4739 } 4740 } else { 4741 return exprLhs; 4742 } 4743 } 4744 4745 /** 4746 * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}? 4747 */ 4748 private static boolean isAssignmentOperator(final TokenType type) { 4749 switch (type) { 4750 case ASSIGN: 4751 case ASSIGN_ADD: 4752 case ASSIGN_BIT_AND: 4753 case ASSIGN_BIT_OR: 4754 case ASSIGN_BIT_XOR: 4755 case ASSIGN_DIV: 4756 case ASSIGN_MOD: 4757 case ASSIGN_MUL: 4758 case ASSIGN_SAR: 4759 case ASSIGN_SHL: 4760 case ASSIGN_SHR: 4761 case ASSIGN_SUB: 4762 return true; 4763 } 4764 return false; 4765 } 4766 4767 /** 4768 * ConditionalExpression. 4769 */ 4770 private Expression conditionalExpression(final boolean noIn) { 4771 return expression(TERNARY.getPrecedence(), noIn); 4772 } 4773 4774 /** 4775 * ArrowFunction. 4776 * 4777 * @param startToken start token of the ArrowParameters expression 4778 * @param functionLine start line of the arrow function 4779 * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list) 4780 */ 4781 private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) { 4782 // caller needs to check that there's no LineTerminator between parameter list and arrow 4783 assert type != ARROW || checkNoLineTerminator(); 4784 expect(ARROW); 4785 4786 final long functionToken = Token.recast(startToken, ARROW); 4787 final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), NameCodec.encode("=>:") + functionLine); 4788 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null); 4789 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 4790 4791 lc.push(functionNode); 4792 try { 4793 final ParserContextBlockNode parameterBlock = newBlock(); 4794 final List<IdentNode> parameters; 4795 try { 4796 parameters = convertArrowFunctionParameterList(paramListExpr, functionLine); 4797 functionNode.setParameters(parameters); 4798 4799 if (!functionNode.isSimpleParameterList()) { 4800 markEvalInArrowParameterList(parameterBlock); 4801 } 4802 } finally { 4803 restoreBlock(parameterBlock); 4804 } 4805 Block functionBody = functionBody(functionNode); 4806 4807 functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock); 4808 4809 verifyParameterList(parameters, functionNode); 4810 4811 final FunctionNode function = createFunctionNode( 4812 functionNode, 4813 functionToken, 4814 name, 4815 parameters, 4816 FunctionNode.Kind.ARROW, 4817 functionLine, 4818 functionBody); 4819 return function; 4820 } finally { 4821 lc.pop(functionNode); 4822 } 4823 } 4824 4825 private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) { 4826 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 4827 final ParserContextFunctionNode current = iter.next(); 4828 final ParserContextFunctionNode parent = iter.next(); 4829 4830 if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) { 4831 // we might have flagged has-eval in the parent function during parsing the parameter list, 4832 // if the parameter list contains eval; must tag arrow function as has-eval. 4833 for (final Statement st : parameterBlock.getStatements()) { 4834 st.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 4835 @Override 4836 public boolean enterCallNode(final CallNode callNode) { 4837 if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) { 4838 current.setFlag(FunctionNode.HAS_EVAL); 4839 } 4840 return true; 4841 } 4842 }); 4843 } 4844 // TODO: function containing the arrow function should not be flagged has-eval 4845 } 4846 } 4847 4848 private List<IdentNode> convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) { 4849 final List<IdentNode> parameters; 4850 if (paramListExpr == null) { 4851 // empty parameter list, i.e. () => 4852 parameters = Collections.emptyList(); 4853 } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) { 4854 parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine)); 4855 } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) { 4856 parameters = new ArrayList<>(); 4857 Expression car = paramListExpr; 4858 do { 4859 final Expression cdr = ((BinaryNode) car).rhs(); 4860 parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine)); 4861 car = ((BinaryNode) car).lhs(); 4862 } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT); 4863 parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine)); 4864 } else { 4865 throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken()); 4866 } 4867 return parameters; 4868 } 4869 4870 private IdentNode verifyArrowParameter(final Expression param, final int index, final int paramLine) { 4871 final String contextString = "function parameter"; 4872 if (param instanceof IdentNode) { 4873 final IdentNode ident = (IdentNode)param; 4874 verifyStrictIdent(ident, contextString); 4875 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4876 if (currentFunction != null) { 4877 currentFunction.addParameterBinding(ident); 4878 } 4879 return ident; 4880 } 4881 4882 if (param.isTokenType(ASSIGN)) { 4883 final Expression lhs = ((BinaryNode) param).lhs(); 4884 final long paramToken = lhs.getToken(); 4885 final Expression initializer = ((BinaryNode) param).rhs(); 4886 if (lhs instanceof IdentNode) { 4887 // default parameter 4888 final IdentNode ident = (IdentNode) lhs; 4889 4890 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4891 if (currentFunction != null) { 4892 if (env._parse_only) { 4893 currentFunction.addParameterExpression(ident, param); 4894 } else { 4895 final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); 4896 final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); 4897 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value); 4898 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4899 } 4900 4901 currentFunction.addParameterBinding(ident); 4902 currentFunction.setSimpleParameterList(false); 4903 } 4904 return ident; 4905 } else if (isDestructuringLhs(lhs)) { 4906 // binding pattern with initializer 4907 // Introduce synthetic temporary parameter to capture the object to be destructured. 4908 final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter(); 4909 verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString); 4910 4911 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4912 if (currentFunction != null) { 4913 if (env._parse_only) { 4914 currentFunction.addParameterExpression(ident, param); 4915 } else { 4916 final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); 4917 final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); 4918 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value); 4919 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4920 } 4921 } 4922 return ident; 4923 } 4924 } else if (isDestructuringLhs(param)) { 4925 // binding pattern 4926 final long paramToken = param.getToken(); 4927 4928 // Introduce synthetic temporary parameter to capture the object to be destructured. 4929 final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter(); 4930 verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString); 4931 4932 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4933 if (currentFunction != null) { 4934 if (env._parse_only) { 4935 currentFunction.addParameterExpression(ident, param); 4936 } else { 4937 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident); 4938 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4939 } 4940 } 4941 return ident; 4942 } 4943 throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken()); 4944 } 4945 4946 private boolean checkNoLineTerminator() { 4947 assert type == ARROW; 4948 if (last == RPAREN) { 4949 return true; 4950 } else if (last == IDENT) { 4951 return true; 4952 } 4953 for (int i = k - 1; i >= 0; i--) { 4954 final TokenType t = T(i); 4955 switch (t) { 4956 case RPAREN: 4957 case IDENT: 4958 return true; 4959 case EOL: 4960 return false; 4961 case COMMENT: 4962 continue; 4963 default: 4964 if (t.getKind() == TokenKind.FUTURESTRICT) { 4965 return true; 4966 } 4967 return false; 4968 } 4969 } 4970 return false; 4971 } 4972 4973 /** 4974 * Peek ahead to see if what follows after the ellipsis is a rest parameter 4975 * at the end of an arrow function parameter list. 4976 */ 4977 private boolean isRestParameterEndOfArrowFunctionParameterList() { 4978 assert type == ELLIPSIS; 4979 // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT 4980 int i = 1; 4981 for (;;) { 4982 final TokenType t = T(k + i++); 4983 if (t == IDENT) { 4984 break; 4985 } else if (t == EOL || t == COMMENT) { 4986 continue; 4987 } else { 4988 return false; 4989 } 4990 } 4991 for (;;) { 4992 final TokenType t = T(k + i++); 4993 if (t == RPAREN) { 4994 break; 4995 } else if (t == EOL || t == COMMENT) { 4996 continue; 4997 } else { 4998 return false; 4999 } 5000 } 5001 for (;;) { 5002 final TokenType t = T(k + i++); 5003 if (t == ARROW) { 5004 break; 5005 } else if (t == COMMENT) { 5006 continue; 5007 } else { 5008 return false; 5009 } 5010 } 5011 return true; 5012 } 5013 5014 /** 5015 * Parse an end of line. 5016 */ 5017 private void endOfLine() { 5018 switch (type) { 5019 case SEMICOLON: 5020 case EOL: 5021 next(); 5022 break; 5023 case RPAREN: 5024 case RBRACKET: 5025 case RBRACE: 5026 case EOF: 5027 break; 5028 default: 5029 if (last != EOL) { 5030 expect(SEMICOLON); 5031 } 5032 break; 5033 } 5034 } 5035 5036 /** 5037 * Parse untagged template literal as string concatenation. 5038 */ 5039 private Expression templateLiteral() { 5040 assert type == TEMPLATE || type == TEMPLATE_HEAD; 5041 final boolean noSubstitutionTemplate = type == TEMPLATE; 5042 long lastLiteralToken = token; 5043 LiteralNode<?> literal = getLiteral(); 5044 if (noSubstitutionTemplate) { 5045 return literal; 5046 } 5047 5048 if (env._parse_only) { 5049 final List<Expression> exprs = new ArrayList<>(); 5050 exprs.add(literal); 5051 TokenType lastLiteralType; 5052 do { 5053 final Expression expression = expression(); 5054 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) { 5055 throw error(AbstractParser.message("unterminated.template.expression"), token); 5056 } 5057 exprs.add(expression); 5058 lastLiteralType = type; 5059 literal = getLiteral(); 5060 exprs.add(literal); 5061 } while (lastLiteralType == TEMPLATE_MIDDLE); 5062 return new TemplateLiteral(exprs); 5063 } else { 5064 Expression concat = literal; 5065 TokenType lastLiteralType; 5066 do { 5067 final Expression expression = expression(); 5068 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) { 5069 throw error(AbstractParser.message("unterminated.template.expression"), token); 5070 } 5071 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression); 5072 lastLiteralType = type; 5073 lastLiteralToken = token; 5074 literal = getLiteral(); 5075 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal); 5076 } while (lastLiteralType == TEMPLATE_MIDDLE); 5077 return concat; 5078 } 5079 } 5080 5081 /** 5082 * Parse tagged template literal as argument list. 5083 * @return argument list for a tag function call (template object, ...substitutions) 5084 */ 5085 private List<Expression> templateLiteralArgumentList() { 5086 assert type == TEMPLATE || type == TEMPLATE_HEAD; 5087 final ArrayList<Expression> argumentList = new ArrayList<>(); 5088 final ArrayList<Expression> rawStrings = new ArrayList<>(); 5089 final ArrayList<Expression> cookedStrings = new ArrayList<>(); 5090 argumentList.add(null); // filled at the end 5091 5092 final long templateToken = token; 5093 final boolean hasSubstitutions = type == TEMPLATE_HEAD; 5094 addTemplateLiteralString(rawStrings, cookedStrings); 5095 5096 if (hasSubstitutions) { 5097 TokenType lastLiteralType; 5098 do { 5099 final Expression expression = expression(); 5100 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) { 5101 throw error(AbstractParser.message("unterminated.template.expression"), token); 5102 } 5103 argumentList.add(expression); 5104 5105 lastLiteralType = type; 5106 addTemplateLiteralString(rawStrings, cookedStrings); 5107 } while (lastLiteralType == TEMPLATE_MIDDLE); 5108 } 5109 5110 final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings); 5111 final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings); 5112 final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray); 5113 argumentList.set(0, templateObject); 5114 return optimizeList(argumentList); 5115 } 5116 5117 private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) { 5118 final long stringToken = token; 5119 final String rawString = lexer.valueOfRawString(stringToken); 5120 final String cookedString = (String) getValue(); 5121 next(); 5122 rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString)); 5123 cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString)); 5124 } 5125 5126 5127 /** 5128 * Parse a module. 5129 * 5130 * Module : 5131 * ModuleBody? 5132 * 5133 * ModuleBody : 5134 * ModuleItemList 5135 */ 5136 private FunctionNode module(final String moduleName) { 5137 final boolean oldStrictMode = isStrictMode; 5138 try { 5139 isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1) 5140 5141 // Make a pseudo-token for the script holding its start and length. 5142 final int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish); 5143 final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart); 5144 final int functionLine = line; 5145 5146 final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName); 5147 final ParserContextFunctionNode script = createParserContextFunctionNode( 5148 ident, 5149 functionToken, 5150 FunctionNode.Kind.MODULE, 5151 functionLine, 5152 Collections.<IdentNode>emptyList()); 5153 lc.push(script); 5154 5155 final ParserContextModuleNode module = new ParserContextModuleNode(moduleName); 5156 lc.push(module); 5157 5158 final ParserContextBlockNode body = newBlock(); 5159 5160 functionDeclarations = new ArrayList<>(); 5161 moduleBody(); 5162 addFunctionDeclarations(script); 5163 functionDeclarations = null; 5164 5165 restoreBlock(body); 5166 body.setFlag(Block.NEEDS_SCOPE); 5167 final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements()); 5168 lc.pop(module); 5169 lc.pop(script); 5170 script.setLastToken(token); 5171 5172 expect(EOF); 5173 5174 script.setModule(module.createModule()); 5175 return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody); 5176 } finally { 5177 isStrictMode = oldStrictMode; 5178 } 5179 } 5180 5181 /** 5182 * Parse module body. 5183 * 5184 * ModuleBody : 5185 * ModuleItemList 5186 * 5187 * ModuleItemList : 5188 * ModuleItem 5189 * ModuleItemList ModuleItem 5190 * 5191 * ModuleItem : 5192 * ImportDeclaration 5193 * ExportDeclaration 5194 * StatementListItem 5195 */ 5196 private void moduleBody() { 5197 loop: 5198 while (type != EOF) { 5199 switch (type) { 5200 case EOF: 5201 break loop; 5202 case IMPORT: 5203 importDeclaration(); 5204 break; 5205 case EXPORT: 5206 exportDeclaration(); 5207 break; 5208 default: 5209 // StatementListItem 5210 statement(true, 0, false, false); 5211 break; 5212 } 5213 } 5214 } 5215 5216 5217 /** 5218 * Parse import declaration. 5219 * 5220 * ImportDeclaration : 5221 * import ImportClause FromClause ; 5222 * import ModuleSpecifier ; 5223 * ImportClause : 5224 * ImportedDefaultBinding 5225 * NameSpaceImport 5226 * NamedImports 5227 * ImportedDefaultBinding , NameSpaceImport 5228 * ImportedDefaultBinding , NamedImports 5229 * ImportedDefaultBinding : 5230 * ImportedBinding 5231 * ModuleSpecifier : 5232 * StringLiteral 5233 * ImportedBinding : 5234 * BindingIdentifier 5235 */ 5236 private void importDeclaration() { 5237 final int startPosition = start; 5238 expect(IMPORT); 5239 final ParserContextModuleNode module = lc.getCurrentModule(); 5240 if (type == STRING || type == ESCSTRING) { 5241 // import ModuleSpecifier ; 5242 final IdentNode moduleSpecifier = createIdentNode(token, finish, (String) getValue()); 5243 next(); 5244 module.addModuleRequest(moduleSpecifier); 5245 } else { 5246 // import ImportClause FromClause ; 5247 List<Module.ImportEntry> importEntries; 5248 if (type == MUL) { 5249 importEntries = Collections.singletonList(nameSpaceImport(startPosition)); 5250 } else if (type == LBRACE) { 5251 importEntries = namedImports(startPosition); 5252 } else if (isBindingIdentifier()) { 5253 // ImportedDefaultBinding 5254 final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding"); 5255 final Module.ImportEntry defaultImport = Module.ImportEntry.importSpecifier(importedDefaultBinding, startPosition, finish); 5256 5257 if (type == COMMARIGHT) { 5258 next(); 5259 importEntries = new ArrayList<>(); 5260 if (type == MUL) { 5261 importEntries.add(nameSpaceImport(startPosition)); 5262 } else if (type == LBRACE) { 5263 importEntries.addAll(namedImports(startPosition)); 5264 } else { 5265 throw error(AbstractParser.message("expected.named.import")); 5266 } 5267 } else { 5268 importEntries = Collections.singletonList(defaultImport); 5269 } 5270 } else { 5271 throw error(AbstractParser.message("expected.import")); 5272 } 5273 5274 final IdentNode moduleSpecifier = fromClause(); 5275 module.addModuleRequest(moduleSpecifier); 5276 for (int i = 0; i < importEntries.size(); i++) { 5277 module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier, finish)); 5278 } 5279 } 5280 expect(SEMICOLON); 5281 } 5282 5283 /** 5284 * NameSpaceImport : 5285 * * as ImportedBinding 5286 * 5287 * @param startPosition the start of the import declaration 5288 * @return imported binding identifier 5289 */ 5290 private Module.ImportEntry nameSpaceImport(final int startPosition) { 5291 assert type == MUL; 5292 final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME); 5293 next(); 5294 final long asToken = token; 5295 final String as = (String) expectValue(IDENT); 5296 if (!"as".equals(as)) { 5297 throw error(AbstractParser.message("expected.as"), asToken); 5298 } 5299 final IdentNode localNameSpace = bindingIdentifier("ImportedBinding"); 5300 return Module.ImportEntry.importSpecifier(starName, localNameSpace, startPosition, finish); 5301 } 5302 5303 /** 5304 * NamedImports : 5305 * { } 5306 * { ImportsList } 5307 * { ImportsList , } 5308 * ImportsList : 5309 * ImportSpecifier 5310 * ImportsList , ImportSpecifier 5311 * ImportSpecifier : 5312 * ImportedBinding 5313 * IdentifierName as ImportedBinding 5314 * ImportedBinding : 5315 * BindingIdentifier 5316 */ 5317 private List<Module.ImportEntry> namedImports(final int startPosition) { 5318 assert type == LBRACE; 5319 next(); 5320 final List<Module.ImportEntry> importEntries = new ArrayList<>(); 5321 while (type != RBRACE) { 5322 final boolean bindingIdentifier = isBindingIdentifier(); 5323 final long nameToken = token; 5324 final IdentNode importName = getIdentifierName(); 5325 if (type == IDENT && "as".equals(getValue())) { 5326 next(); 5327 final IdentNode localName = bindingIdentifier("ImportedBinding"); 5328 importEntries.add(Module.ImportEntry.importSpecifier(importName, localName, startPosition, finish)); 5329 } else if (!bindingIdentifier) { 5330 throw error(AbstractParser.message("expected.binding.identifier"), nameToken); 5331 } else { 5332 importEntries.add(Module.ImportEntry.importSpecifier(importName, startPosition, finish)); 5333 } 5334 if (type == COMMARIGHT) { 5335 next(); 5336 } else { 5337 break; 5338 } 5339 } 5340 expect(RBRACE); 5341 return importEntries; 5342 } 5343 5344 /** 5345 * FromClause : 5346 * from ModuleSpecifier 5347 */ 5348 private IdentNode fromClause() { 5349 final long fromToken = token; 5350 final String name = (String) expectValue(IDENT); 5351 if (!"from".equals(name)) { 5352 throw error(AbstractParser.message("expected.from"), fromToken); 5353 } 5354 if (type == STRING || type == ESCSTRING) { 5355 final IdentNode moduleSpecifier = createIdentNode(Token.recast(token, IDENT), finish, (String) getValue()); 5356 next(); 5357 return moduleSpecifier; 5358 } else { 5359 throw error(expectMessage(STRING)); 5360 } 5361 } 5362 5363 /** 5364 * Parse export declaration. 5365 * 5366 * ExportDeclaration : 5367 * export * FromClause ; 5368 * export ExportClause FromClause ; 5369 * export ExportClause ; 5370 * export VariableStatement 5371 * export Declaration 5372 * export default HoistableDeclaration[Default] 5373 * export default ClassDeclaration[Default] 5374 * export default [lookahead !in {function, class}] AssignmentExpression[In] ; 5375 */ 5376 private void exportDeclaration() { 5377 expect(EXPORT); 5378 final int startPosition = start; 5379 final ParserContextModuleNode module = lc.getCurrentModule(); 5380 switch (type) { 5381 case MUL: { 5382 final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME); 5383 next(); 5384 final IdentNode moduleRequest = fromClause(); 5385 expect(SEMICOLON); 5386 module.addModuleRequest(moduleRequest); 5387 module.addStarExportEntry(Module.ExportEntry.exportStarFrom(starName, moduleRequest, startPosition, finish)); 5388 break; 5389 } 5390 case LBRACE: { 5391 final List<Module.ExportEntry> exportEntries = exportClause(startPosition); 5392 if (type == IDENT && "from".equals(getValue())) { 5393 final IdentNode moduleRequest = fromClause(); 5394 module.addModuleRequest(moduleRequest); 5395 for (final Module.ExportEntry exportEntry : exportEntries) { 5396 module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest, finish)); 5397 } 5398 } else { 5399 for (final Module.ExportEntry exportEntry : exportEntries) { 5400 module.addLocalExportEntry(exportEntry); 5401 } 5402 } 5403 expect(SEMICOLON); 5404 break; 5405 } 5406 case DEFAULT: 5407 final IdentNode defaultName = createIdentNode(Token.recast(token, IDENT), finish, Module.DEFAULT_NAME); 5408 next(); 5409 final Expression assignmentExpression; 5410 IdentNode ident; 5411 final int lineNumber = line; 5412 final long rhsToken = token; 5413 final boolean declaration; 5414 switch (type) { 5415 case FUNCTION: 5416 assignmentExpression = functionExpression(false, true); 5417 ident = ((FunctionNode) assignmentExpression).getIdent(); 5418 declaration = true; 5419 break; 5420 case CLASS: 5421 assignmentExpression = classDeclaration(true); 5422 ident = ((ClassNode) assignmentExpression).getIdent(); 5423 declaration = true; 5424 break; 5425 default: 5426 assignmentExpression = assignmentExpression(false); 5427 ident = null; 5428 declaration = false; 5429 break; 5430 } 5431 if (ident != null) { 5432 module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish)); 5433 } else { 5434 ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME); 5435 lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression)); 5436 if (!declaration) { 5437 expect(SEMICOLON); 5438 } 5439 module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish)); 5440 } 5441 break; 5442 case VAR: 5443 case LET: 5444 case CONST: 5445 final List<Statement> statements = lc.getCurrentBlock().getStatements(); 5446 final int previousEnd = statements.size(); 5447 variableStatement(type); 5448 for (final Statement statement : statements.subList(previousEnd, statements.size())) { 5449 if (statement instanceof VarNode) { 5450 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName(), startPosition, finish)); 5451 } 5452 } 5453 break; 5454 case CLASS: { 5455 final ClassNode classDeclaration = classDeclaration(false); 5456 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent(), startPosition, finish)); 5457 break; 5458 } 5459 case FUNCTION: { 5460 final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true); 5461 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent(), startPosition, finish)); 5462 break; 5463 } 5464 default: 5465 throw error(AbstractParser.message("invalid.export"), token); 5466 } 5467 } 5468 5469 /** 5470 * ExportClause : 5471 * { } 5472 * { ExportsList } 5473 * { ExportsList , } 5474 * ExportsList : 5475 * ExportSpecifier 5476 * ExportsList , ExportSpecifier 5477 * ExportSpecifier : 5478 * IdentifierName 5479 * IdentifierName as IdentifierName 5480 * 5481 * @return a list of ExportSpecifiers 5482 */ 5483 private List<Module.ExportEntry> exportClause(final int startPosition) { 5484 assert type == LBRACE; 5485 next(); 5486 final List<Module.ExportEntry> exports = new ArrayList<>(); 5487 while (type != RBRACE) { 5488 final IdentNode localName = getIdentifierName(); 5489 if (type == IDENT && "as".equals(getValue())) { 5490 next(); 5491 final IdentNode exportName = getIdentifierName(); 5492 exports.add(Module.ExportEntry.exportSpecifier(exportName, localName, startPosition, finish)); 5493 } else { 5494 exports.add(Module.ExportEntry.exportSpecifier(localName, startPosition, finish)); 5495 } 5496 if (type == COMMARIGHT) { 5497 next(); 5498 } else { 5499 break; 5500 } 5501 } 5502 expect(RBRACE); 5503 return exports; 5504 } 5505 5506 @Override 5507 public String toString() { 5508 return "'JavaScript Parsing'"; 5509 } 5510 5511 private static void markEval(final ParserContext lc) { 5512 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5513 boolean flaggedCurrentFn = false; 5514 while (iter.hasNext()) { 5515 final ParserContextFunctionNode fn = iter.next(); 5516 if (!flaggedCurrentFn) { 5517 fn.setFlag(FunctionNode.HAS_EVAL); 5518 flaggedCurrentFn = true; 5519 if (fn.getKind() == FunctionNode.Kind.ARROW) { 5520 // possible use of this in an eval that's nested in an arrow function, e.g.: 5521 // function fun(){ return (() => eval("this"))(); }; 5522 markThis(lc); 5523 markNewTarget(lc); 5524 } 5525 } else { 5526 fn.setFlag(FunctionNode.HAS_NESTED_EVAL); 5527 } 5528 final ParserContextBlockNode body = lc.getFunctionBody(fn); 5529 // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip 5530 // parsing a nested function. functionBody() contains code to compensate for the lack of invoking 5531 // this method when the parser skips a nested function. 5532 body.setFlag(Block.NEEDS_SCOPE); 5533 fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK); 5534 } 5535 } 5536 5537 private void prependStatement(final Statement statement) { 5538 lc.prependStatementToCurrentNode(statement); 5539 } 5540 5541 private void appendStatement(final Statement statement) { 5542 lc.appendStatementToCurrentNode(statement); 5543 } 5544 5545 private static void markSuperCall(final ParserContext lc) { 5546 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5547 while (iter.hasNext()) { 5548 final ParserContextFunctionNode fn = iter.next(); 5549 if (fn.getKind() != FunctionNode.Kind.ARROW) { 5550 assert fn.isSubclassConstructor(); 5551 fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER); 5552 break; 5553 } 5554 } 5555 } 5556 5557 private ParserContextFunctionNode getCurrentNonArrowFunction() { 5558 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5559 while (iter.hasNext()) { 5560 final ParserContextFunctionNode fn = iter.next(); 5561 if (fn.getKind() != FunctionNode.Kind.ARROW) { 5562 return fn; 5563 } 5564 } 5565 return null; 5566 } 5567 5568 private static void markThis(final ParserContext lc) { 5569 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5570 while (iter.hasNext()) { 5571 final ParserContextFunctionNode fn = iter.next(); 5572 fn.setFlag(FunctionNode.USES_THIS); 5573 if (fn.getKind() != FunctionNode.Kind.ARROW) { 5574 break; 5575 } 5576 } 5577 } 5578 5579 private static void markNewTarget(final ParserContext lc) { 5580 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5581 while (iter.hasNext()) { 5582 final ParserContextFunctionNode fn = iter.next(); 5583 if (fn.getKind() != FunctionNode.Kind.ARROW) { 5584 if (!fn.isProgram()) { 5585 fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET); 5586 } 5587 break; 5588 } 5589 } 5590 } 5591 5592 private boolean inGeneratorFunction() { 5593 return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR; 5594 } 5595 }