1 /* 2 * Copyright (c) 2010, 2015, 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 appendStatement(new BlockStatement(forLine, new Block( 2057 outer.getToken(), 2058 body.getFinish(), 2059 outer.getStatements()))); 2060 } 2061 } 2062 } 2063 } 2064 2065 private boolean checkValidLValue(final Expression init, final String contextString) { 2066 if (init instanceof IdentNode) { 2067 if (!checkIdentLValue((IdentNode)init)) { 2068 return false; 2069 } 2070 verifyIdent((IdentNode)init, contextString); 2071 return true; 2072 } else if (init instanceof AccessNode || init instanceof IndexNode) { 2073 return true; 2074 } else if (isDestructuringLhs(init)) { 2075 verifyDestructuringAssignmentPattern(init, contextString); 2076 return true; 2077 } else { 2078 return false; 2079 } 2080 } 2081 2082 @SuppressWarnings("fallthrough") 2083 private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) { 2084 assert type == LET; 2085 for (int i = 1;; i++) { 2086 final TokenType t = T(k + i); 2087 switch (t) { 2088 case EOL: 2089 case COMMENT: 2090 continue; 2091 case IDENT: 2092 if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) { 2093 return false; 2094 } 2095 // fall through 2096 case LBRACKET: 2097 case LBRACE: 2098 return true; 2099 default: 2100 // accept future strict tokens in non-strict mode (including LET) 2101 if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) { 2102 return true; 2103 } 2104 return false; 2105 } 2106 } 2107 } 2108 2109 /** 2110 * ...IterationStatement : 2111 * ... 2112 * while ( Expression ) Statement 2113 * ... 2114 * 2115 * See 12.6 2116 * 2117 * Parse while statement. 2118 */ 2119 private void whileStatement() { 2120 // Capture WHILE token. 2121 final long whileToken = token; 2122 final int whileLine = line; 2123 // WHILE tested in caller. 2124 next(); 2125 2126 final ParserContextLoopNode whileNode = new ParserContextLoopNode(); 2127 lc.push(whileNode); 2128 2129 JoinPredecessorExpression test = null; 2130 Block body = null; 2131 2132 try { 2133 expect(LPAREN); 2134 test = joinPredecessorExpression(); 2135 expect(RPAREN); 2136 body = getStatement(); 2137 } finally { 2138 lc.pop(whileNode); 2139 } 2140 2141 if (body != null) { 2142 appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body)); 2143 } 2144 } 2145 2146 /** 2147 * ...IterationStatement : 2148 * ... 2149 * do Statement while( Expression ) ; 2150 * ... 2151 * 2152 * See 12.6 2153 * 2154 * Parse DO WHILE statement. 2155 */ 2156 private void doStatement() { 2157 // Capture DO token. 2158 final long doToken = token; 2159 int doLine = 0; 2160 // DO tested in the caller. 2161 next(); 2162 2163 final ParserContextLoopNode doWhileNode = new ParserContextLoopNode(); 2164 lc.push(doWhileNode); 2165 2166 Block body = null; 2167 JoinPredecessorExpression test = null; 2168 2169 try { 2170 // Get DO body. 2171 body = getStatement(); 2172 2173 expect(WHILE); 2174 expect(LPAREN); 2175 doLine = line; 2176 test = joinPredecessorExpression(); 2177 expect(RPAREN); 2178 2179 if (type == SEMICOLON) { 2180 endOfLine(); 2181 } 2182 } finally { 2183 lc.pop(doWhileNode); 2184 } 2185 2186 appendStatement(new WhileNode(doLine, doToken, finish, true, test, body)); 2187 } 2188 2189 /** 2190 * ContinueStatement : 2191 * continue Identifier? ; // [no LineTerminator here] 2192 * 2193 * See 12.7 2194 * 2195 * Parse CONTINUE statement. 2196 */ 2197 private void continueStatement() { 2198 // Capture CONTINUE token. 2199 final int continueLine = line; 2200 final long continueToken = token; 2201 // CONTINUE tested in caller. 2202 nextOrEOL(); 2203 2204 ParserContextLabelNode labelNode = null; 2205 2206 // SEMICOLON or label. 2207 switch (type) { 2208 case RBRACE: 2209 case SEMICOLON: 2210 case EOL: 2211 case EOF: 2212 break; 2213 2214 default: 2215 final IdentNode ident = getIdent(); 2216 labelNode = lc.findLabel(ident.getName()); 2217 2218 if (labelNode == null) { 2219 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken()); 2220 } 2221 2222 break; 2223 } 2224 2225 final String labelName = labelNode == null ? null : labelNode.getLabelName(); 2226 final ParserContextLoopNode targetNode = lc.getContinueTo(labelName); 2227 2228 if (targetNode == null) { 2229 throw error(AbstractParser.message("illegal.continue.stmt"), continueToken); 2230 } 2231 2232 endOfLine(); 2233 2234 // Construct and add CONTINUE node. 2235 appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName)); 2236 } 2237 2238 /** 2239 * BreakStatement : 2240 * break Identifier? ; // [no LineTerminator here] 2241 * 2242 * See 12.8 2243 * 2244 */ 2245 private void breakStatement() { 2246 // Capture BREAK token. 2247 final int breakLine = line; 2248 final long breakToken = token; 2249 // BREAK tested in caller. 2250 nextOrEOL(); 2251 2252 ParserContextLabelNode labelNode = null; 2253 2254 // SEMICOLON or label. 2255 switch (type) { 2256 case RBRACE: 2257 case SEMICOLON: 2258 case EOL: 2259 case EOF: 2260 break; 2261 2262 default: 2263 final IdentNode ident = getIdent(); 2264 labelNode = lc.findLabel(ident.getName()); 2265 2266 if (labelNode == null) { 2267 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken()); 2268 } 2269 2270 break; 2271 } 2272 2273 //either an explicit label - then get its node or just a "break" - get first breakable 2274 //targetNode is what we are breaking out from. 2275 final String labelName = labelNode == null ? null : labelNode.getLabelName(); 2276 final ParserContextBreakableNode targetNode = lc.getBreakable(labelName); 2277 if (targetNode == null) { 2278 throw error(AbstractParser.message("illegal.break.stmt"), breakToken); 2279 } 2280 2281 endOfLine(); 2282 2283 // Construct and add BREAK node. 2284 appendStatement(new BreakNode(breakLine, breakToken, finish, labelName)); 2285 } 2286 2287 /** 2288 * ReturnStatement : 2289 * return Expression? ; // [no LineTerminator here] 2290 * 2291 * See 12.9 2292 * 2293 * Parse RETURN statement. 2294 */ 2295 private void returnStatement() { 2296 // check for return outside function 2297 if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) { 2298 throw error(AbstractParser.message("invalid.return")); 2299 } 2300 2301 // Capture RETURN token. 2302 final int returnLine = line; 2303 final long returnToken = token; 2304 // RETURN tested in caller. 2305 nextOrEOL(); 2306 2307 Expression expression = null; 2308 2309 // SEMICOLON or expression. 2310 switch (type) { 2311 case RBRACE: 2312 case SEMICOLON: 2313 case EOL: 2314 case EOF: 2315 break; 2316 2317 default: 2318 expression = expression(); 2319 break; 2320 } 2321 2322 endOfLine(); 2323 2324 // Construct and add RETURN node. 2325 appendStatement(new ReturnNode(returnLine, returnToken, finish, expression)); 2326 } 2327 2328 /** 2329 * Parse YieldExpression. 2330 * 2331 * YieldExpression[In] : 2332 * yield 2333 * yield [no LineTerminator here] AssignmentExpression[?In, Yield] 2334 * yield [no LineTerminator here] * AssignmentExpression[?In, Yield] 2335 */ 2336 @SuppressWarnings("fallthrough") 2337 private Expression yieldExpression(final boolean noIn) { 2338 assert inGeneratorFunction(); 2339 // Capture YIELD token. 2340 long yieldToken = token; 2341 // YIELD tested in caller. 2342 assert type == YIELD; 2343 nextOrEOL(); 2344 2345 Expression expression = null; 2346 2347 boolean yieldAsterisk = false; 2348 if (type == MUL) { 2349 yieldAsterisk = true; 2350 yieldToken = Token.recast(yieldToken, YIELD_STAR); 2351 next(); 2352 } 2353 2354 switch (type) { 2355 case RBRACE: 2356 case SEMICOLON: 2357 case EOL: 2358 case EOF: 2359 case COMMARIGHT: 2360 case RPAREN: 2361 case RBRACKET: 2362 case COLON: 2363 if (!yieldAsterisk) { 2364 // treat (yield) as (yield void 0) 2365 expression = newUndefinedLiteral(yieldToken, finish); 2366 if (type == EOL) { 2367 next(); 2368 } 2369 break; 2370 } else { 2371 // AssignmentExpression required, fall through 2372 } 2373 2374 default: 2375 expression = assignmentExpression(noIn); 2376 break; 2377 } 2378 2379 // Construct and add YIELD node. 2380 return new UnaryNode(yieldToken, expression); 2381 } 2382 2383 private static UnaryNode newUndefinedLiteral(final long token, final int finish) { 2384 return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0)); 2385 } 2386 2387 /** 2388 * WithStatement : 2389 * with ( Expression ) Statement 2390 * 2391 * See 12.10 2392 * 2393 * Parse WITH statement. 2394 */ 2395 private void withStatement() { 2396 // Capture WITH token. 2397 final int withLine = line; 2398 final long withToken = token; 2399 // WITH tested in caller. 2400 next(); 2401 2402 // ECMA 12.10.1 strict mode restrictions 2403 if (isStrictMode) { 2404 throw error(AbstractParser.message("strict.no.with"), withToken); 2405 } 2406 2407 expect(LPAREN); 2408 final Expression expression = expression(); 2409 expect(RPAREN); 2410 final Block body = getStatement(); 2411 2412 appendStatement(new WithNode(withLine, withToken, finish, expression, body)); 2413 } 2414 2415 /** 2416 * SwitchStatement : 2417 * switch ( Expression ) CaseBlock 2418 * 2419 * CaseBlock : 2420 * { CaseClauses? } 2421 * { CaseClauses? DefaultClause CaseClauses } 2422 * 2423 * CaseClauses : 2424 * CaseClause 2425 * CaseClauses CaseClause 2426 * 2427 * CaseClause : 2428 * case Expression : StatementList? 2429 * 2430 * DefaultClause : 2431 * default : StatementList? 2432 * 2433 * See 12.11 2434 * 2435 * Parse SWITCH statement. 2436 */ 2437 private void switchStatement() { 2438 final int switchLine = line; 2439 final long switchToken = token; 2440 2441 // Block to capture variables declared inside the switch statement. 2442 final ParserContextBlockNode switchBlock = newBlock(); 2443 2444 // SWITCH tested in caller. 2445 next(); 2446 2447 // Create and add switch statement. 2448 final ParserContextSwitchNode switchNode = new ParserContextSwitchNode(); 2449 lc.push(switchNode); 2450 2451 CaseNode defaultCase = null; 2452 // Prepare to accumulate cases. 2453 final List<CaseNode> cases = new ArrayList<>(); 2454 2455 Expression expression = null; 2456 2457 try { 2458 expect(LPAREN); 2459 expression = expression(); 2460 expect(RPAREN); 2461 2462 expect(LBRACE); 2463 2464 2465 while (type != RBRACE) { 2466 // Prepare for next case. 2467 Expression caseExpression = null; 2468 final long caseToken = token; 2469 2470 switch (type) { 2471 case CASE: 2472 next(); 2473 caseExpression = expression(); 2474 break; 2475 2476 case DEFAULT: 2477 if (defaultCase != null) { 2478 throw error(AbstractParser.message("duplicate.default.in.switch")); 2479 } 2480 next(); 2481 break; 2482 2483 default: 2484 // Force an error. 2485 expect(CASE); 2486 break; 2487 } 2488 2489 expect(COLON); 2490 2491 // Get CASE body. 2492 final Block statements = getBlock(false); // TODO: List<Statement> statements = caseStatementList(); 2493 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements); 2494 2495 if (caseExpression == null) { 2496 defaultCase = caseNode; 2497 } 2498 2499 cases.add(caseNode); 2500 } 2501 2502 next(); 2503 } finally { 2504 lc.pop(switchNode); 2505 restoreBlock(switchBlock); 2506 } 2507 2508 final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase); 2509 appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement))); 2510 } 2511 2512 /** 2513 * LabelledStatement : 2514 * Identifier : Statement 2515 * 2516 * See 12.12 2517 * 2518 * Parse label statement. 2519 */ 2520 private void labelStatement() { 2521 // Capture label token. 2522 final long labelToken = token; 2523 // Get label ident. 2524 final IdentNode ident = getIdent(); 2525 2526 expect(COLON); 2527 2528 if (lc.findLabel(ident.getName()) != null) { 2529 throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken); 2530 } 2531 2532 final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName()); 2533 Block body = null; 2534 try { 2535 lc.push(labelNode); 2536 body = getStatement(true); 2537 } finally { 2538 assert lc.peek() instanceof ParserContextLabelNode; 2539 lc.pop(labelNode); 2540 } 2541 2542 appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body)); 2543 } 2544 2545 /** 2546 * ThrowStatement : 2547 * throw Expression ; // [no LineTerminator here] 2548 * 2549 * See 12.13 2550 * 2551 * Parse throw statement. 2552 */ 2553 private void throwStatement() { 2554 // Capture THROW token. 2555 final int throwLine = line; 2556 final long throwToken = token; 2557 // THROW tested in caller. 2558 nextOrEOL(); 2559 2560 Expression expression = null; 2561 2562 // SEMICOLON or expression. 2563 switch (type) { 2564 case RBRACE: 2565 case SEMICOLON: 2566 case EOL: 2567 break; 2568 2569 default: 2570 expression = expression(); 2571 break; 2572 } 2573 2574 if (expression == null) { 2575 throw error(AbstractParser.message("expected.operand", type.getNameOrType())); 2576 } 2577 2578 endOfLine(); 2579 2580 appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false)); 2581 } 2582 2583 /** 2584 * TryStatement : 2585 * try Block Catch 2586 * try Block Finally 2587 * try Block Catch Finally 2588 * 2589 * Catch : 2590 * catch( Identifier if Expression ) Block 2591 * catch( Identifier ) Block 2592 * 2593 * Finally : 2594 * finally Block 2595 * 2596 * See 12.14 2597 * 2598 * Parse TRY statement. 2599 */ 2600 private void tryStatement() { 2601 // Capture TRY token. 2602 final int tryLine = line; 2603 final long tryToken = token; 2604 // TRY tested in caller. 2605 next(); 2606 2607 // Container block needed to act as target for labeled break statements 2608 final int startLine = line; 2609 final ParserContextBlockNode outer = newBlock(); 2610 // Create try. 2611 2612 try { 2613 final Block tryBody = getBlock(true); 2614 final List<Block> catchBlocks = new ArrayList<>(); 2615 2616 while (type == CATCH) { 2617 final int catchLine = line; 2618 final long catchToken = token; 2619 next(); 2620 expect(LPAREN); 2621 2622 // ES6 catch parameter can be a BindingIdentifier or a BindingPattern 2623 // http://www.ecma-international.org/ecma-262/6.0/ 2624 final String contextString = "catch argument"; 2625 final Expression exception = bindingIdentifierOrPattern(contextString); 2626 final boolean isDestructuring = !(exception instanceof IdentNode); 2627 if (isDestructuring) { 2628 verifyDestructuringBindingPattern(exception, new Consumer<IdentNode>() { 2629 @Override 2630 public void accept(final IdentNode identNode) { 2631 verifyIdent(identNode, contextString); 2632 } 2633 }); 2634 } else { 2635 // ECMA 12.4.1 strict mode restrictions 2636 verifyStrictIdent((IdentNode) exception, "catch argument"); 2637 } 2638 2639 2640 // Nashorn extension: catch clause can have optional 2641 // condition. So, a single try can have more than one 2642 // catch clause each with it's own condition. 2643 final Expression ifExpression; 2644 if (!env._no_syntax_extensions && type == IF) { 2645 next(); 2646 // Get the exception condition. 2647 ifExpression = expression(); 2648 } else { 2649 ifExpression = null; 2650 } 2651 2652 expect(RPAREN); 2653 2654 final ParserContextBlockNode catchBlock = newBlock(); 2655 try { 2656 // Get CATCH body. 2657 final Block catchBody = getBlock(true); 2658 final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false); 2659 appendStatement(catchNode); 2660 } finally { 2661 restoreBlock(catchBlock); 2662 catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements())); 2663 } 2664 2665 // If unconditional catch then should to be the end. 2666 if (ifExpression == null) { 2667 break; 2668 } 2669 } 2670 2671 // Prepare to capture finally statement. 2672 Block finallyStatements = null; 2673 2674 if (type == FINALLY) { 2675 next(); 2676 finallyStatements = getBlock(true); 2677 } 2678 2679 // Need at least one catch or a finally. 2680 if (catchBlocks.isEmpty() && finallyStatements == null) { 2681 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken); 2682 } 2683 2684 final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements); 2685 // Add try. 2686 assert lc.peek() == outer; 2687 appendStatement(tryNode); 2688 } finally { 2689 restoreBlock(outer); 2690 } 2691 2692 appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements()))); 2693 } 2694 2695 /** 2696 * DebuggerStatement : 2697 * debugger ; 2698 * 2699 * See 12.15 2700 * 2701 * Parse debugger statement. 2702 */ 2703 private void debuggerStatement() { 2704 // Capture DEBUGGER token. 2705 final int debuggerLine = line; 2706 final long debuggerToken = token; 2707 // DEBUGGER tested in caller. 2708 next(); 2709 endOfLine(); 2710 appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish)); 2711 } 2712 2713 /** 2714 * PrimaryExpression : 2715 * this 2716 * IdentifierReference 2717 * Literal 2718 * ArrayLiteral 2719 * ObjectLiteral 2720 * RegularExpressionLiteral 2721 * TemplateLiteral 2722 * CoverParenthesizedExpressionAndArrowParameterList 2723 * 2724 * CoverParenthesizedExpressionAndArrowParameterList : 2725 * ( Expression ) 2726 * ( ) 2727 * ( ... BindingIdentifier ) 2728 * ( Expression , ... BindingIdentifier ) 2729 * 2730 * Parse primary expression. 2731 * @return Expression node. 2732 */ 2733 @SuppressWarnings("fallthrough") 2734 private Expression primaryExpression() { 2735 // Capture first token. 2736 final int primaryLine = line; 2737 final long primaryToken = token; 2738 2739 switch (type) { 2740 case THIS: 2741 final String name = type.getName(); 2742 next(); 2743 markThis(lc); 2744 return new IdentNode(primaryToken, finish, name); 2745 case IDENT: 2746 final IdentNode ident = getIdent(); 2747 if (ident == null) { 2748 break; 2749 } 2750 detectSpecialProperty(ident); 2751 return ident; 2752 case OCTAL_LEGACY: 2753 if (isStrictMode) { 2754 throw error(AbstractParser.message("strict.no.octal"), token); 2755 } 2756 case STRING: 2757 case ESCSTRING: 2758 case DECIMAL: 2759 case HEXADECIMAL: 2760 case OCTAL: 2761 case BINARY_NUMBER: 2762 case FLOATING: 2763 case REGEX: 2764 case XML: 2765 return getLiteral(); 2766 case EXECSTRING: 2767 return execString(primaryLine, primaryToken); 2768 case FALSE: 2769 next(); 2770 return LiteralNode.newInstance(primaryToken, finish, false); 2771 case TRUE: 2772 next(); 2773 return LiteralNode.newInstance(primaryToken, finish, true); 2774 case NULL: 2775 next(); 2776 return LiteralNode.newInstance(primaryToken, finish); 2777 case LBRACKET: 2778 return arrayLiteral(); 2779 case LBRACE: 2780 return objectLiteral(); 2781 case LPAREN: 2782 next(); 2783 2784 if (isES6()) { 2785 if (type == RPAREN) { 2786 // () 2787 nextOrEOL(); 2788 expectDontAdvance(ARROW); 2789 return new ExpressionList(primaryToken, finish, Collections.emptyList()); 2790 } else if (type == ELLIPSIS) { 2791 // (...rest) 2792 final IdentNode restParam = formalParameterList(false).get(0); 2793 expectDontAdvance(RPAREN); 2794 nextOrEOL(); 2795 expectDontAdvance(ARROW); 2796 return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam)); 2797 } 2798 } 2799 2800 final Expression expression = expression(); 2801 2802 expect(RPAREN); 2803 2804 return expression; 2805 case TEMPLATE: 2806 case TEMPLATE_HEAD: 2807 return templateLiteral(); 2808 2809 default: 2810 // In this context some operator tokens mark the start of a literal. 2811 if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) { 2812 next(); 2813 return getLiteral(); 2814 } 2815 if (isNonStrictModeIdent()) { 2816 return getIdent(); 2817 } 2818 break; 2819 } 2820 2821 return null; 2822 } 2823 2824 /** 2825 * Convert execString to a call to $EXEC. 2826 * 2827 * @param primaryToken Original string token. 2828 * @return callNode to $EXEC. 2829 */ 2830 CallNode execString(final int primaryLine, final long primaryToken) { 2831 // Synthesize an ident to call $EXEC. 2832 final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME); 2833 // Skip over EXECSTRING. 2834 next(); 2835 // Set up argument list for call. 2836 // Skip beginning of edit string expression. 2837 expect(LBRACE); 2838 // Add the following expression to arguments. 2839 final List<Expression> arguments = Collections.singletonList(expression()); 2840 // Skip ending of edit string expression. 2841 expect(RBRACE); 2842 2843 return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false); 2844 } 2845 2846 /** 2847 * ArrayLiteral : 2848 * [ Elision? ] 2849 * [ ElementList ] 2850 * [ ElementList , Elision? ] 2851 * [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ] 2852 * 2853 * ElementList : Elision? AssignmentExpression 2854 * ElementList , Elision? AssignmentExpression 2855 * 2856 * Elision : 2857 * , 2858 * Elision , 2859 * 2860 * See 12.1.4 2861 * JavaScript 1.8 2862 * 2863 * Parse array literal. 2864 * @return Expression node. 2865 */ 2866 @SuppressWarnings("fallthrough") 2867 private LiteralNode<Expression[]> arrayLiteral() { 2868 // Capture LBRACKET token. 2869 final long arrayToken = token; 2870 // LBRACKET tested in caller. 2871 next(); 2872 2873 // Prepare to accumulate elements. 2874 final List<Expression> elements = new ArrayList<>(); 2875 // Track elisions. 2876 boolean elision = true; 2877 boolean hasSpread = false; 2878 loop: 2879 while (true) { 2880 long spreadToken = 0; 2881 switch (type) { 2882 case RBRACKET: 2883 next(); 2884 2885 break loop; 2886 2887 case COMMARIGHT: 2888 next(); 2889 2890 // If no prior expression 2891 if (elision) { 2892 elements.add(null); 2893 } 2894 2895 elision = true; 2896 2897 break; 2898 2899 case ELLIPSIS: 2900 if (isES6()) { 2901 hasSpread = true; 2902 spreadToken = token; 2903 next(); 2904 } 2905 // fall through 2906 2907 default: 2908 if (!elision) { 2909 throw error(AbstractParser.message("expected.comma", type.getNameOrType())); 2910 } 2911 2912 // Add expression element. 2913 Expression expression = assignmentExpression(false); 2914 if (expression != null) { 2915 if (spreadToken != 0) { 2916 expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression); 2917 } 2918 elements.add(expression); 2919 } else { 2920 expect(RBRACKET); 2921 } 2922 2923 elision = false; 2924 break; 2925 } 2926 } 2927 2928 return LiteralNode.newInstance(arrayToken, finish, elements, hasSpread, elision); 2929 } 2930 2931 /** 2932 * ObjectLiteral : 2933 * { } 2934 * { PropertyNameAndValueList } { PropertyNameAndValueList , } 2935 * 2936 * PropertyNameAndValueList : 2937 * PropertyAssignment 2938 * PropertyNameAndValueList , PropertyAssignment 2939 * 2940 * See 11.1.5 2941 * 2942 * Parse an object literal. 2943 * @return Expression node. 2944 */ 2945 private ObjectNode objectLiteral() { 2946 // Capture LBRACE token. 2947 final long objectToken = token; 2948 // LBRACE tested in caller. 2949 next(); 2950 2951 // Object context. 2952 // Prepare to accumulate elements. 2953 final List<PropertyNode> elements = new ArrayList<>(); 2954 final Map<String, Integer> map = new HashMap<>(); 2955 2956 // Create a block for the object literal. 2957 boolean commaSeen = true; 2958 loop: 2959 while (true) { 2960 switch (type) { 2961 case RBRACE: 2962 next(); 2963 break loop; 2964 2965 case COMMARIGHT: 2966 if (commaSeen) { 2967 throw error(AbstractParser.message("expected.property.id", type.getNameOrType())); 2968 } 2969 next(); 2970 commaSeen = true; 2971 break; 2972 2973 default: 2974 if (!commaSeen) { 2975 throw error(AbstractParser.message("expected.comma", type.getNameOrType())); 2976 } 2977 2978 commaSeen = false; 2979 // Get and add the next property. 2980 final PropertyNode property = propertyAssignment(); 2981 2982 if (property.isComputed()) { 2983 elements.add(property); 2984 break; 2985 } 2986 2987 final String key = property.getKeyName(); 2988 final Integer existing = map.get(key); 2989 2990 if (existing == null) { 2991 map.put(key, elements.size()); 2992 elements.add(property); 2993 break; 2994 } 2995 2996 final PropertyNode existingProperty = elements.get(existing); 2997 2998 // ECMA section 11.1.5 Object Initialiser 2999 // point # 4 on property assignment production 3000 final Expression value = property.getValue(); 3001 final FunctionNode getter = property.getGetter(); 3002 final FunctionNode setter = property.getSetter(); 3003 3004 final Expression prevValue = existingProperty.getValue(); 3005 final FunctionNode prevGetter = existingProperty.getGetter(); 3006 final FunctionNode prevSetter = existingProperty.getSetter(); 3007 3008 if (!isES6()) { 3009 checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter); 3010 } else { 3011 if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() && 3012 existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) { 3013 throw error(AbstractParser.message("multiple.proto.key"), property.getToken()); 3014 } 3015 } 3016 3017 if (value != null || prevValue != null) { 3018 map.put(key, elements.size()); 3019 elements.add(property); 3020 } else if (getter != null) { 3021 assert prevGetter != null || prevSetter != null; 3022 elements.set(existing, existingProperty.setGetter(getter)); 3023 } else if (setter != null) { 3024 assert prevGetter != null || prevSetter != null; 3025 elements.set(existing, existingProperty.setSetter(setter)); 3026 } 3027 break; 3028 } 3029 } 3030 3031 return new ObjectNode(objectToken, finish, elements); 3032 } 3033 3034 private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) { 3035 // ECMA 11.1.5 strict mode restrictions 3036 if (isStrictMode && value != null && prevValue != null) { 3037 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); 3038 } 3039 3040 final boolean isPrevAccessor = prevGetter != null || prevSetter != null; 3041 final boolean isAccessor = getter != null || setter != null; 3042 3043 // data property redefined as accessor property 3044 if (prevValue != null && isAccessor) { 3045 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); 3046 } 3047 3048 // accessor property redefined as data 3049 if (isPrevAccessor && value != null) { 3050 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); 3051 } 3052 3053 if (isAccessor && isPrevAccessor) { 3054 if (getter != null && prevGetter != null || 3055 setter != null && prevSetter != null) { 3056 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); 3057 } 3058 } 3059 } 3060 3061 /** 3062 * LiteralPropertyName : 3063 * IdentifierName 3064 * StringLiteral 3065 * NumericLiteral 3066 * 3067 * @return PropertyName node 3068 */ 3069 @SuppressWarnings("fallthrough") 3070 private PropertyKey literalPropertyName() { 3071 switch (type) { 3072 case IDENT: 3073 return getIdent().setIsPropertyName(); 3074 case OCTAL_LEGACY: 3075 if (isStrictMode) { 3076 throw error(AbstractParser.message("strict.no.octal"), token); 3077 } 3078 case STRING: 3079 case ESCSTRING: 3080 case DECIMAL: 3081 case HEXADECIMAL: 3082 case OCTAL: 3083 case BINARY_NUMBER: 3084 case FLOATING: 3085 return getLiteral(); 3086 default: 3087 return getIdentifierName().setIsPropertyName(); 3088 } 3089 } 3090 3091 /** 3092 * ComputedPropertyName : 3093 * AssignmentExpression 3094 * 3095 * @return PropertyName node 3096 */ 3097 private Expression computedPropertyName() { 3098 expect(LBRACKET); 3099 final Expression expression = assignmentExpression(false); 3100 expect(RBRACKET); 3101 return expression; 3102 } 3103 3104 /** 3105 * PropertyName : 3106 * LiteralPropertyName 3107 * ComputedPropertyName 3108 * 3109 * @return PropertyName node 3110 */ 3111 private Expression propertyName() { 3112 if (type == LBRACKET && isES6()) { 3113 return computedPropertyName(); 3114 } else { 3115 return (Expression)literalPropertyName(); 3116 } 3117 } 3118 3119 /** 3120 * PropertyAssignment : 3121 * PropertyName : AssignmentExpression 3122 * get PropertyName ( ) { FunctionBody } 3123 * set PropertyName ( PropertySetParameterList ) { FunctionBody } 3124 * 3125 * PropertySetParameterList : 3126 * Identifier 3127 * 3128 * PropertyName : 3129 * IdentifierName 3130 * StringLiteral 3131 * NumericLiteral 3132 * 3133 * See 11.1.5 3134 * 3135 * Parse an object literal property. 3136 * @return Property or reference node. 3137 */ 3138 private PropertyNode propertyAssignment() { 3139 // Capture firstToken. 3140 final long propertyToken = token; 3141 final int functionLine = line; 3142 3143 final Expression propertyName; 3144 final boolean isIdentifier; 3145 3146 boolean generator = false; 3147 if (type == MUL && isES6()) { 3148 generator = true; 3149 next(); 3150 } 3151 3152 final boolean computed = type == LBRACKET; 3153 if (type == IDENT) { 3154 // Get IDENT. 3155 final String ident = (String)expectValue(IDENT); 3156 3157 if (type != COLON && (type != LPAREN || !isES6())) { 3158 final long getSetToken = propertyToken; 3159 3160 switch (ident) { 3161 case GET_NAME: 3162 final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine); 3163 return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed); 3164 3165 case SET_NAME: 3166 final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine); 3167 return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed); 3168 default: 3169 break; 3170 } 3171 } 3172 3173 isIdentifier = true; 3174 IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName(); 3175 if (type == COLON && ident.equals("__proto__")) { 3176 identNode = identNode.setIsProtoPropertyName(); 3177 } 3178 propertyName = identNode; 3179 } else { 3180 isIdentifier = isNonStrictModeIdent(); 3181 propertyName = propertyName(); 3182 } 3183 3184 Expression propertyValue; 3185 3186 if (generator) { 3187 expectDontAdvance(LPAREN); 3188 } 3189 3190 if (type == LPAREN && isES6()) { 3191 propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode; 3192 } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) { 3193 propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName()); 3194 if (type == ASSIGN && isES6()) { 3195 // TODO if not destructuring, this is a SyntaxError 3196 final long assignToken = token; 3197 next(); 3198 final Expression rhs = assignmentExpression(false); 3199 propertyValue = verifyAssignment(assignToken, propertyValue, rhs); 3200 } 3201 } else { 3202 expect(COLON); 3203 3204 defaultNames.push(propertyName); 3205 try { 3206 propertyValue = assignmentExpression(false); 3207 } finally { 3208 defaultNames.pop(); 3209 } 3210 } 3211 3212 return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed); 3213 } 3214 3215 private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) { 3216 return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD); 3217 } 3218 3219 private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) { 3220 final boolean computed = type == LBRACKET; 3221 final Expression propertyName = propertyName(); 3222 final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false); 3223 final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName)); 3224 expect(LPAREN); 3225 expect(RPAREN); 3226 3227 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList()); 3228 functionNode.setFlag(flags); 3229 if (computed) { 3230 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 3231 } 3232 lc.push(functionNode); 3233 3234 Block functionBody; 3235 3236 3237 try { 3238 functionBody = functionBody(functionNode); 3239 } finally { 3240 lc.pop(functionNode); 3241 } 3242 3243 final FunctionNode function = createFunctionNode( 3244 functionNode, 3245 getSetToken, 3246 getNameNode, 3247 Collections.<IdentNode>emptyList(), 3248 FunctionNode.Kind.GETTER, 3249 functionLine, 3250 functionBody); 3251 3252 return new PropertyFunction(propertyName, function, computed); 3253 } 3254 3255 private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) { 3256 return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD); 3257 } 3258 3259 private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) { 3260 final boolean computed = type == LBRACKET; 3261 final Expression propertyName = propertyName(); 3262 final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false); 3263 final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName)); 3264 expect(LPAREN); 3265 // be sloppy and allow missing setter parameter even though 3266 // spec does not permit it! 3267 final IdentNode argIdent; 3268 if (isBindingIdentifier()) { 3269 argIdent = getIdent(); 3270 verifyIdent(argIdent, "setter argument"); 3271 } else { 3272 argIdent = null; 3273 } 3274 expect(RPAREN); 3275 final List<IdentNode> parameters = new ArrayList<>(); 3276 if (argIdent != null) { 3277 parameters.add(argIdent); 3278 } 3279 3280 3281 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters); 3282 functionNode.setFlag(flags); 3283 if (computed) { 3284 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 3285 } 3286 lc.push(functionNode); 3287 3288 Block functionBody; 3289 try { 3290 functionBody = functionBody(functionNode); 3291 } finally { 3292 lc.pop(functionNode); 3293 } 3294 3295 3296 final FunctionNode function = createFunctionNode( 3297 functionNode, 3298 getSetToken, 3299 setNameNode, 3300 parameters, 3301 FunctionNode.Kind.SETTER, 3302 functionLine, 3303 functionBody); 3304 3305 return new PropertyFunction(propertyName, function, computed); 3306 } 3307 3308 private PropertyFunction propertyMethodFunction(final Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, final boolean computed) { 3309 final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false); 3310 final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName); 3311 3312 final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL; 3313 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null); 3314 functionNode.setFlag(flags); 3315 if (computed) { 3316 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 3317 } 3318 lc.push(functionNode); 3319 3320 try { 3321 final ParserContextBlockNode parameterBlock = newBlock(); 3322 final List<IdentNode> parameters; 3323 try { 3324 expect(LPAREN); 3325 parameters = formalParameterList(generator); 3326 functionNode.setParameters(parameters); 3327 expect(RPAREN); 3328 } finally { 3329 restoreBlock(parameterBlock); 3330 } 3331 3332 Block functionBody = functionBody(functionNode); 3333 3334 functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock); 3335 3336 final FunctionNode function = createFunctionNode( 3337 functionNode, 3338 methodToken, 3339 methodNameNode, 3340 parameters, 3341 functionKind, 3342 methodLine, 3343 functionBody); 3344 return new PropertyFunction(key, function, computed); 3345 } finally { 3346 lc.pop(functionNode); 3347 } 3348 } 3349 3350 private static class PropertyFunction { 3351 final Expression key; 3352 final FunctionNode functionNode; 3353 final boolean computed; 3354 3355 PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) { 3356 this.key = key; 3357 this.functionNode = function; 3358 this.computed = computed; 3359 } 3360 } 3361 3362 /** 3363 * LeftHandSideExpression : 3364 * NewExpression 3365 * CallExpression 3366 * 3367 * CallExpression : 3368 * MemberExpression Arguments 3369 * SuperCall 3370 * CallExpression Arguments 3371 * CallExpression [ Expression ] 3372 * CallExpression . IdentifierName 3373 * 3374 * SuperCall : 3375 * super Arguments 3376 * 3377 * See 11.2 3378 * 3379 * Parse left hand side expression. 3380 * @return Expression node. 3381 */ 3382 private Expression leftHandSideExpression() { 3383 int callLine = line; 3384 long callToken = token; 3385 3386 Expression lhs = memberExpression(); 3387 3388 if (type == LPAREN) { 3389 final List<Expression> arguments = optimizeList(argumentList()); 3390 3391 // Catch special functions. 3392 if (lhs instanceof IdentNode) { 3393 detectSpecialFunction((IdentNode)lhs); 3394 } 3395 3396 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); 3397 } 3398 3399 loop: 3400 while (true) { 3401 // Capture token. 3402 callLine = line; 3403 callToken = token; 3404 3405 switch (type) { 3406 case LPAREN: { 3407 // Get NEW or FUNCTION arguments. 3408 final List<Expression> arguments = optimizeList(argumentList()); 3409 3410 // Create call node. 3411 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); 3412 3413 break; 3414 } 3415 case LBRACKET: { 3416 next(); 3417 3418 // Get array index. 3419 final Expression rhs = expression(); 3420 3421 expect(RBRACKET); 3422 3423 // Create indexing node. 3424 lhs = new IndexNode(callToken, finish, lhs, rhs); 3425 3426 break; 3427 } 3428 case PERIOD: { 3429 next(); 3430 3431 final IdentNode property = getIdentifierName(); 3432 3433 // Create property access node. 3434 lhs = new AccessNode(callToken, finish, lhs, property.getName()); 3435 3436 break; 3437 } 3438 case TEMPLATE: 3439 case TEMPLATE_HEAD: { 3440 // tagged template literal 3441 final List<Expression> arguments = templateLiteralArgumentList(); 3442 3443 // Create call node. 3444 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); 3445 3446 break; 3447 } 3448 default: 3449 break loop; 3450 } 3451 } 3452 3453 return lhs; 3454 } 3455 3456 /** 3457 * NewExpression : 3458 * MemberExpression 3459 * new NewExpression 3460 * 3461 * See 11.2 3462 * 3463 * Parse new expression. 3464 * @return Expression node. 3465 */ 3466 private Expression newExpression() { 3467 final long newToken = token; 3468 // NEW is tested in caller. 3469 next(); 3470 3471 if (type == PERIOD && isES6()) { 3472 next(); 3473 if (type == IDENT && "target".equals(getValue())) { 3474 if (lc.getCurrentFunction().isProgram()) { 3475 throw error(AbstractParser.message("new.target.in.function"), token); 3476 } 3477 next(); 3478 markNewTarget(lc); 3479 return new IdentNode(newToken, finish, "new.target"); 3480 } else { 3481 throw error(AbstractParser.message("expected.target"), token); 3482 } 3483 } 3484 3485 // Get function base. 3486 final int callLine = line; 3487 final Expression constructor = memberExpression(); 3488 if (constructor == null) { 3489 return null; 3490 } 3491 // Get arguments. 3492 ArrayList<Expression> arguments; 3493 3494 // Allow for missing arguments. 3495 if (type == LPAREN) { 3496 arguments = argumentList(); 3497 } else { 3498 arguments = new ArrayList<>(); 3499 } 3500 3501 // Nashorn extension: This is to support the following interface implementation 3502 // syntax: 3503 // 3504 // var r = new java.lang.Runnable() { 3505 // run: function() { println("run"); } 3506 // }; 3507 // 3508 // The object literal following the "new Constructor()" expression 3509 // is passed as an additional (last) argument to the constructor. 3510 if (!env._no_syntax_extensions && type == LBRACE) { 3511 arguments.add(objectLiteral()); 3512 } 3513 3514 final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true); 3515 3516 return new UnaryNode(newToken, callNode); 3517 } 3518 3519 /** 3520 * MemberExpression : 3521 * PrimaryExpression 3522 * FunctionExpression 3523 * ClassExpression 3524 * GeneratorExpression 3525 * MemberExpression [ Expression ] 3526 * MemberExpression . IdentifierName 3527 * MemberExpression TemplateLiteral 3528 * SuperProperty 3529 * MetaProperty 3530 * new MemberExpression Arguments 3531 * 3532 * SuperProperty : 3533 * super [ Expression ] 3534 * super . IdentifierName 3535 * 3536 * MetaProperty : 3537 * NewTarget 3538 * 3539 * Parse member expression. 3540 * @return Expression node. 3541 */ 3542 @SuppressWarnings("fallthrough") 3543 private Expression memberExpression() { 3544 // Prepare to build operation. 3545 Expression lhs; 3546 boolean isSuper = false; 3547 3548 switch (type) { 3549 case NEW: 3550 // Get new expression. 3551 lhs = newExpression(); 3552 break; 3553 3554 case FUNCTION: 3555 // Get function expression. 3556 lhs = functionExpression(false, false); 3557 break; 3558 3559 case CLASS: 3560 if (isES6()) { 3561 lhs = classExpression(false); 3562 break; 3563 } else { 3564 // fall through 3565 } 3566 3567 case SUPER: 3568 if (isES6()) { 3569 final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction(); 3570 if (currentFunction.isMethod()) { 3571 final long identToken = Token.recast(token, IDENT); 3572 next(); 3573 lhs = createIdentNode(identToken, finish, SUPER.getName()); 3574 3575 switch (type) { 3576 case LBRACKET: 3577 case PERIOD: 3578 getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER); 3579 isSuper = true; 3580 break; 3581 case LPAREN: 3582 if (currentFunction.isSubclassConstructor()) { 3583 lhs = ((IdentNode)lhs).setIsDirectSuper(); 3584 break; 3585 } else { 3586 // fall through to throw error 3587 } 3588 default: 3589 throw error(AbstractParser.message("invalid.super"), identToken); 3590 } 3591 break; 3592 } else { 3593 // fall through 3594 } 3595 } else { 3596 // fall through 3597 } 3598 3599 default: 3600 // Get primary expression. 3601 lhs = primaryExpression(); 3602 break; 3603 } 3604 3605 loop: 3606 while (true) { 3607 // Capture token. 3608 final long callToken = token; 3609 3610 switch (type) { 3611 case LBRACKET: { 3612 next(); 3613 3614 // Get array index. 3615 final Expression index = expression(); 3616 3617 expect(RBRACKET); 3618 3619 // Create indexing node. 3620 lhs = new IndexNode(callToken, finish, lhs, index); 3621 3622 if (isSuper) { 3623 isSuper = false; 3624 lhs = ((BaseNode) lhs).setIsSuper(); 3625 } 3626 3627 break; 3628 } 3629 case PERIOD: { 3630 if (lhs == null) { 3631 throw error(AbstractParser.message("expected.operand", type.getNameOrType())); 3632 } 3633 3634 next(); 3635 3636 final IdentNode property = getIdentifierName(); 3637 3638 // Create property access node. 3639 lhs = new AccessNode(callToken, finish, lhs, property.getName()); 3640 3641 if (isSuper) { 3642 isSuper = false; 3643 lhs = ((BaseNode) lhs).setIsSuper(); 3644 } 3645 3646 break; 3647 } 3648 case TEMPLATE: 3649 case TEMPLATE_HEAD: { 3650 // tagged template literal 3651 final int callLine = line; 3652 final List<Expression> arguments = templateLiteralArgumentList(); 3653 3654 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); 3655 3656 break; 3657 } 3658 default: 3659 break loop; 3660 } 3661 } 3662 3663 return lhs; 3664 } 3665 3666 /** 3667 * Arguments : 3668 * ( ) 3669 * ( ArgumentList ) 3670 * 3671 * ArgumentList : 3672 * AssignmentExpression 3673 * ... AssignmentExpression 3674 * ArgumentList , AssignmentExpression 3675 * ArgumentList , ... AssignmentExpression 3676 * 3677 * See 11.2 3678 * 3679 * Parse function call arguments. 3680 * @return Argument list. 3681 */ 3682 private ArrayList<Expression> argumentList() { 3683 // Prepare to accumulate list of arguments. 3684 final ArrayList<Expression> nodeList = new ArrayList<>(); 3685 // LPAREN tested in caller. 3686 next(); 3687 3688 // Track commas. 3689 boolean first = true; 3690 3691 while (type != RPAREN) { 3692 // Comma prior to every argument except the first. 3693 if (!first) { 3694 expect(COMMARIGHT); 3695 } else { 3696 first = false; 3697 } 3698 3699 long spreadToken = 0; 3700 if (type == ELLIPSIS && isES6()) { 3701 spreadToken = token; 3702 next(); 3703 } 3704 3705 // Get argument expression. 3706 Expression expression = assignmentExpression(false); 3707 if (spreadToken != 0) { 3708 expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression); 3709 } 3710 nodeList.add(expression); 3711 } 3712 3713 expect(RPAREN); 3714 return nodeList; 3715 } 3716 3717 private static <T> List<T> optimizeList(final ArrayList<T> list) { 3718 switch(list.size()) { 3719 case 0: { 3720 return Collections.emptyList(); 3721 } 3722 case 1: { 3723 return Collections.singletonList(list.get(0)); 3724 } 3725 default: { 3726 list.trimToSize(); 3727 return list; 3728 } 3729 } 3730 } 3731 3732 /** 3733 * FunctionDeclaration : 3734 * function Identifier ( FormalParameterList? ) { FunctionBody } 3735 * 3736 * FunctionExpression : 3737 * function Identifier? ( FormalParameterList? ) { FunctionBody } 3738 * 3739 * See 13 3740 * 3741 * Parse function declaration. 3742 * @param isStatement True if for is a statement. 3743 * 3744 * @return Expression node. 3745 */ 3746 private Expression functionExpression(final boolean isStatement, final boolean topLevel) { 3747 final long functionToken = token; 3748 final int functionLine = line; 3749 // FUNCTION is tested in caller. 3750 assert type == FUNCTION; 3751 next(); 3752 3753 boolean generator = false; 3754 if (type == MUL && isES6()) { 3755 generator = true; 3756 next(); 3757 } 3758 3759 IdentNode name = null; 3760 3761 if (isBindingIdentifier()) { 3762 if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) { 3763 // 12.1.1 Early SyntaxError if: 3764 // GeneratorExpression with BindingIdentifier yield 3765 // HoistableDeclaration with BindingIdentifier yield in generator function body 3766 expect(IDENT); 3767 } 3768 name = getIdent(); 3769 verifyStrictIdent(name, "function name"); 3770 } else if (isStatement) { 3771 // Nashorn extension: anonymous function statements. 3772 // Do not allow anonymous function statement if extensions 3773 // are now allowed. But if we are reparsing then anon function 3774 // statement is possible - because it was used as function 3775 // expression in surrounding code. 3776 if (env._no_syntax_extensions && reparsedFunction == null) { 3777 expect(IDENT); 3778 } 3779 } 3780 3781 // name is null, generate anonymous name 3782 boolean isAnonymous = false; 3783 if (name == null) { 3784 final String tmpName = getDefaultValidFunctionName(functionLine, isStatement); 3785 name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName); 3786 isAnonymous = true; 3787 } 3788 3789 final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL; 3790 List<IdentNode> parameters = Collections.emptyList(); 3791 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters); 3792 lc.push(functionNode); 3793 3794 Block functionBody = null; 3795 // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}" 3796 // If we didn't hide the current default name, then the innermost anonymous function would receive "x3". 3797 hideDefaultName(); 3798 try { 3799 final ParserContextBlockNode parameterBlock = newBlock(); 3800 try { 3801 expect(LPAREN); 3802 parameters = formalParameterList(generator); 3803 functionNode.setParameters(parameters); 3804 expect(RPAREN); 3805 } finally { 3806 restoreBlock(parameterBlock); 3807 } 3808 3809 functionBody = functionBody(functionNode); 3810 3811 functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock); 3812 } finally { 3813 defaultNames.pop(); 3814 lc.pop(functionNode); 3815 } 3816 3817 if (isStatement) { 3818 if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) { 3819 functionNode.setFlag(FunctionNode.IS_DECLARED); 3820 } else if (isStrictMode) { 3821 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken); 3822 } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) { 3823 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken); 3824 } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) { 3825 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken); 3826 } 3827 if (isArguments(name)) { 3828 lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS); 3829 } 3830 } 3831 3832 if (isAnonymous) { 3833 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 3834 } 3835 3836 verifyParameterList(parameters, functionNode); 3837 3838 final FunctionNode function = createFunctionNode( 3839 functionNode, 3840 functionToken, 3841 name, 3842 parameters, 3843 functionKind, 3844 functionLine, 3845 functionBody); 3846 3847 if (isStatement) { 3848 if (isAnonymous) { 3849 appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function)); 3850 return function; 3851 } 3852 3853 // mark ES6 block functions as lexically scoped 3854 final int varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET; 3855 final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, function, varFlags); 3856 if (topLevel) { 3857 functionDeclarations.add(varNode); 3858 } else if (useBlockScope()) { 3859 prependStatement(varNode); // Hoist to beginning of current block 3860 } else { 3861 appendStatement(varNode); 3862 } 3863 } 3864 3865 return function; 3866 } 3867 3868 private void verifyParameterList(final List<IdentNode> parameters, final ParserContextFunctionNode functionNode) { 3869 final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding(); 3870 if (duplicateParameter != null) { 3871 if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) { 3872 throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken()); 3873 } 3874 3875 final int arity = parameters.size(); 3876 final HashSet<String> parametersSet = new HashSet<>(arity); 3877 3878 for (int i = arity - 1; i >= 0; i--) { 3879 final IdentNode parameter = parameters.get(i); 3880 String parameterName = parameter.getName(); 3881 3882 if (parametersSet.contains(parameterName)) { 3883 // redefinition of parameter name, rename in non-strict mode 3884 parameterName = functionNode.uniqueName(parameterName); 3885 final long parameterToken = parameter.getToken(); 3886 parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName))); 3887 } 3888 parametersSet.add(parameterName); 3889 } 3890 } 3891 } 3892 3893 private static Block maybeWrapBodyInParameterBlock(final Block functionBody, final ParserContextBlockNode parameterBlock) { 3894 assert functionBody.isFunctionBody(); 3895 if (!parameterBlock.getStatements().isEmpty()) { 3896 parameterBlock.appendStatement(new BlockStatement(functionBody)); 3897 return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements()); 3898 } 3899 return functionBody; 3900 } 3901 3902 private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) { 3903 final String defaultFunctionName = getDefaultFunctionName(); 3904 if (isValidIdentifier(defaultFunctionName)) { 3905 if (isStatement) { 3906 // The name will be used as the LHS of a symbol assignment. We add the anonymous function 3907 // prefix to ensure that it can't clash with another variable. 3908 return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName; 3909 } 3910 return defaultFunctionName; 3911 } 3912 return ANON_FUNCTION_PREFIX.symbolName() + functionLine; 3913 } 3914 3915 private static boolean isValidIdentifier(final String name) { 3916 if (name == null || name.isEmpty()) { 3917 return false; 3918 } 3919 if (!Character.isJavaIdentifierStart(name.charAt(0))) { 3920 return false; 3921 } 3922 for (int i = 1; i < name.length(); ++i) { 3923 if (!Character.isJavaIdentifierPart(name.charAt(i))) { 3924 return false; 3925 } 3926 } 3927 return true; 3928 } 3929 3930 private String getDefaultFunctionName() { 3931 if (!defaultNames.isEmpty()) { 3932 final Object nameExpr = defaultNames.peek(); 3933 if (nameExpr instanceof PropertyKey) { 3934 markDefaultNameUsed(); 3935 return ((PropertyKey)nameExpr).getPropertyName(); 3936 } else if (nameExpr instanceof AccessNode) { 3937 markDefaultNameUsed(); 3938 return ((AccessNode)nameExpr).getProperty(); 3939 } 3940 } 3941 return null; 3942 } 3943 3944 private void markDefaultNameUsed() { 3945 defaultNames.pop(); 3946 hideDefaultName(); 3947 } 3948 3949 private void hideDefaultName() { 3950 // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value 3951 // from. Can't be null 3952 defaultNames.push(""); 3953 } 3954 3955 /** 3956 * FormalParameterList : 3957 * Identifier 3958 * FormalParameterList , Identifier 3959 * 3960 * See 13 3961 * 3962 * Parse function parameter list. 3963 * @return List of parameter nodes. 3964 */ 3965 private List<IdentNode> formalParameterList(final boolean yield) { 3966 return formalParameterList(RPAREN, yield); 3967 } 3968 3969 /** 3970 * Same as the other method of the same name - except that the end 3971 * token type expected is passed as argument to this method. 3972 * 3973 * FormalParameterList : 3974 * Identifier 3975 * FormalParameterList , Identifier 3976 * 3977 * See 13 3978 * 3979 * Parse function parameter list. 3980 * @return List of parameter nodes. 3981 */ 3982 private List<IdentNode> formalParameterList(final TokenType endType, final boolean yield) { 3983 // Prepare to gather parameters. 3984 final ArrayList<IdentNode> parameters = new ArrayList<>(); 3985 // Track commas. 3986 boolean first = true; 3987 3988 while (type != endType) { 3989 // Comma prior to every argument except the first. 3990 if (!first) { 3991 expect(COMMARIGHT); 3992 } else { 3993 first = false; 3994 } 3995 3996 boolean restParameter = false; 3997 if (type == ELLIPSIS && isES6()) { 3998 next(); 3999 restParameter = true; 4000 } 4001 4002 if (type == YIELD && yield) { 4003 expect(IDENT); 4004 } 4005 4006 final long paramToken = token; 4007 final int paramLine = line; 4008 final String contextString = "function parameter"; 4009 IdentNode ident; 4010 if (isBindingIdentifier() || restParameter || !isES6()) { 4011 ident = bindingIdentifier(contextString); 4012 4013 if (restParameter) { 4014 ident = ident.setIsRestParameter(); 4015 // rest parameter must be last 4016 expectDontAdvance(endType); 4017 parameters.add(ident); 4018 break; 4019 } else if (type == ASSIGN && isES6()) { 4020 next(); 4021 ident = ident.setIsDefaultParameter(); 4022 4023 if (type == YIELD && yield) { 4024 // error: yield in default expression 4025 expect(IDENT); 4026 } 4027 4028 // default parameter 4029 final Expression initializer = assignmentExpression(false); 4030 4031 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4032 if (currentFunction != null) { 4033 if (env._parse_only) { 4034 // keep what is seen in source "as is" and save it as parameter expression 4035 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, initializer); 4036 currentFunction.addParameterExpression(ident, assignment); 4037 } else { 4038 // desugar to: param = (param === undefined) ? initializer : param; 4039 // possible alternative: if (param === undefined) param = initializer; 4040 final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); 4041 final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); 4042 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value); 4043 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4044 } 4045 } 4046 } 4047 4048 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4049 if (currentFunction != null) { 4050 currentFunction.addParameterBinding(ident); 4051 if (ident.isRestParameter() || ident.isDefaultParameter()) { 4052 currentFunction.setSimpleParameterList(false); 4053 } 4054 } 4055 } else { 4056 final Expression pattern = bindingPattern(); 4057 // Introduce synthetic temporary parameter to capture the object to be destructured. 4058 ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter(); 4059 verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString); 4060 4061 Expression value = ident; 4062 if (type == ASSIGN) { 4063 next(); 4064 ident = ident.setIsDefaultParameter(); 4065 4066 // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param 4067 final Expression initializer = assignmentExpression(false); 4068 4069 if (env._parse_only) { 4070 // we don't want the synthetic identifier in parse only mode 4071 value = initializer; 4072 } else { 4073 // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list) 4074 final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); 4075 value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); 4076 } 4077 } 4078 4079 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4080 if (currentFunction != null) { 4081 // destructuring assignment 4082 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value); 4083 if (env._parse_only) { 4084 // in parse-only mode, represent source tree "as is" 4085 if (ident.isDefaultParameter()) { 4086 currentFunction.addParameterExpression(ident, assignment); 4087 } else { 4088 currentFunction.addParameterExpression(ident, pattern); 4089 } 4090 } else { 4091 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4092 } 4093 } 4094 } 4095 parameters.add(ident); 4096 } 4097 4098 parameters.trimToSize(); 4099 return parameters; 4100 } 4101 4102 private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) { 4103 verifyDestructuringBindingPattern(pattern, new Consumer<IdentNode>() { 4104 public void accept(final IdentNode identNode) { 4105 verifyIdent(identNode, contextString); 4106 4107 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4108 if (currentFunction != null) { 4109 // declare function-scope variables for destructuring bindings 4110 if (!env._parse_only) { 4111 lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null)); 4112 } 4113 // detect duplicate bounds names in parameter list 4114 currentFunction.addParameterBinding(identNode); 4115 currentFunction.setSimpleParameterList(false); 4116 } 4117 } 4118 }); 4119 } 4120 4121 /** 4122 * FunctionBody : 4123 * SourceElements? 4124 * 4125 * See 13 4126 * 4127 * Parse function body. 4128 * @return function node (body.) 4129 */ 4130 private Block functionBody(final ParserContextFunctionNode functionNode) { 4131 long lastToken = 0L; 4132 ParserContextBlockNode body = null; 4133 final long bodyToken = token; 4134 Block functionBody; 4135 int bodyFinish = 0; 4136 4137 final boolean parseBody; 4138 Object endParserState = null; 4139 try { 4140 // Create a new function block. 4141 body = newBlock(); 4142 if (env._debug_scopes) { 4143 // debug scope options forces everything to be in scope 4144 markEval(lc); 4145 } 4146 assert functionNode != null; 4147 final int functionId = functionNode.getId(); 4148 parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId(); 4149 // Nashorn extension: expression closures 4150 if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) { 4151 /* 4152 * Example: 4153 * 4154 * function square(x) x * x; 4155 * print(square(3)); 4156 */ 4157 4158 // just expression as function body 4159 final Expression expr = assignmentExpression(false); 4160 lastToken = previousToken; 4161 functionNode.setLastToken(previousToken); 4162 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode); 4163 // EOL uses length field to store the line number 4164 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken)); 4165 // Only create the return node if we aren't skipping nested functions. Note that we aren't 4166 // skipping parsing of these extended functions; they're considered to be small anyway. Also, 4167 // they don't end with a single well known token, so it'd be very hard to get correctly (see 4168 // the note below for reasoning on skipping happening before instead of after RBRACE for 4169 // details). 4170 if (parseBody) { 4171 functionNode.setFlag(FunctionNode.HAS_EXPRESSION_BODY); 4172 final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr); 4173 appendStatement(returnNode); 4174 } 4175 // bodyFinish = finish; 4176 } else { 4177 expectDontAdvance(LBRACE); 4178 if (parseBody || !skipFunctionBody(functionNode)) { 4179 next(); 4180 // Gather the function elements. 4181 final List<Statement> prevFunctionDecls = functionDeclarations; 4182 functionDeclarations = new ArrayList<>(); 4183 try { 4184 sourceElements(0); 4185 addFunctionDeclarations(functionNode); 4186 } finally { 4187 functionDeclarations = prevFunctionDecls; 4188 } 4189 4190 lastToken = token; 4191 if (parseBody) { 4192 // Since the lexer can read ahead and lexify some number of tokens in advance and have 4193 // them buffered in the TokenStream, we need to produce a lexer state as it was just 4194 // before it lexified RBRACE, and not whatever is its current (quite possibly well read 4195 // ahead) state. 4196 endParserState = new ParserState(Token.descPosition(token), line, linePosition); 4197 4198 // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of 4199 // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the 4200 // state after it. The reason is that RBRACE is a well-known token that we can expect and 4201 // will never involve us getting into a weird lexer state, and as such is a great reparse 4202 // point. Typical example of a weird lexer state after RBRACE would be: 4203 // function this_is_skipped() { ... } "use strict"; 4204 // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead 4205 // of compensating for the possibility of a string literal (or similar) after RBRACE, 4206 // we'll rather just restart parsing from this well-known, friendly token instead. 4207 } 4208 } 4209 bodyFinish = finish; 4210 functionNode.setLastToken(token); 4211 expect(RBRACE); 4212 } 4213 } finally { 4214 restoreBlock(body); 4215 } 4216 4217 // NOTE: we can only do alterations to the function node after restoreFunctionNode. 4218 4219 if (parseBody) { 4220 functionNode.setEndParserState(endParserState); 4221 } else if (!body.getStatements().isEmpty()){ 4222 // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see 4223 // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to 4224 // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as 4225 // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away 4226 // nested bodies early if we were supposed to skip 'em. 4227 body.setStatements(Collections.<Statement>emptyList()); 4228 } 4229 4230 if (reparsedFunction != null) { 4231 // We restore the flags stored in the function's ScriptFunctionData that we got when we first 4232 // eagerly parsed the code. We're doing it because some flags would be set based on the 4233 // content of the function, or even content of its nested functions, most of which are normally 4234 // skipped during an on-demand compilation. 4235 final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId()); 4236 if (data != null) { 4237 // Data can be null if when we originally parsed the file, we removed the function declaration 4238 // as it was dead code. 4239 functionNode.setFlag(data.getFunctionFlags()); 4240 // This compensates for missing markEval() in case the function contains an inner function 4241 // that contains eval(), that now we didn't discover since we skipped the inner function. 4242 if (functionNode.hasNestedEval()) { 4243 assert functionNode.hasScopeBlock(); 4244 body.setFlag(Block.NEEDS_SCOPE); 4245 } 4246 } 4247 } 4248 functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements()); 4249 return functionBody; 4250 } 4251 4252 private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) { 4253 if (reparsedFunction == null) { 4254 // Not reparsing, so don't skip any function body. 4255 return false; 4256 } 4257 // Skip to the RBRACE of this function, and continue parsing from there. 4258 final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId()); 4259 if (data == null) { 4260 // Nested function is not known to the reparsed function. This can happen if the FunctionNode was 4261 // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the 4262 // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it. 4263 return false; 4264 } 4265 final ParserState parserState = (ParserState)data.getEndParserState(); 4266 assert parserState != null; 4267 4268 if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) { 4269 // RBRACE is already in the token stream, so fast forward to it 4270 for (; k < stream.last(); k++) { 4271 final long nextToken = stream.get(k + 1); 4272 if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) { 4273 token = stream.get(k); 4274 type = Token.descType(token); 4275 next(); 4276 assert type == RBRACE && start == parserState.position; 4277 return true; 4278 } 4279 } 4280 } 4281 4282 stream.reset(); 4283 lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6); 4284 line = parserState.line; 4285 linePosition = parserState.linePosition; 4286 // Doesn't really matter, but it's safe to treat it as if there were a semicolon before 4287 // the RBRACE. 4288 type = SEMICOLON; 4289 scanFirstToken(); 4290 4291 return true; 4292 } 4293 4294 /** 4295 * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer 4296 * for resuming parsing after skipping a function body. 4297 */ 4298 private static class ParserState implements Serializable { 4299 private final int position; 4300 private final int line; 4301 private final int linePosition; 4302 4303 private static final long serialVersionUID = -2382565130754093694L; 4304 4305 ParserState(final int position, final int line, final int linePosition) { 4306 this.position = position; 4307 this.line = line; 4308 this.linePosition = linePosition; 4309 } 4310 4311 Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) { 4312 final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true); 4313 newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON)); 4314 return newLexer; 4315 } 4316 } 4317 4318 private void printAST(final FunctionNode functionNode) { 4319 if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) { 4320 env.getErr().println(new ASTWriter(functionNode)); 4321 } 4322 4323 if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) { 4324 env.getErr().println(new PrintVisitor(functionNode, true, false)); 4325 } 4326 } 4327 4328 private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) { 4329 VarNode lastDecl = null; 4330 for (int i = functionDeclarations.size() - 1; i >= 0; i--) { 4331 Statement decl = functionDeclarations.get(i); 4332 if (lastDecl == null && decl instanceof VarNode) { 4333 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION); 4334 functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS); 4335 } 4336 prependStatement(decl); 4337 } 4338 } 4339 4340 private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) { 4341 if (env._parse_only || earlyError) { 4342 throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken()); 4343 } 4344 final ArrayList<Expression> args = new ArrayList<>(); 4345 args.add(lhs); 4346 if (rhs == null) { 4347 args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish())); 4348 } else { 4349 args.add(rhs); 4350 } 4351 args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString())); 4352 return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args); 4353 } 4354 4355 /** 4356 * PostfixExpression : 4357 * LeftHandSideExpression 4358 * LeftHandSideExpression ++ // [no LineTerminator here] 4359 * LeftHandSideExpression -- // [no LineTerminator here] 4360 * 4361 * See 11.3 4362 * 4363 * UnaryExpression : 4364 * PostfixExpression 4365 * delete UnaryExpression 4366 * void UnaryExpression 4367 * typeof UnaryExpression 4368 * ++ UnaryExpression 4369 * -- UnaryExpression 4370 * + UnaryExpression 4371 * - UnaryExpression 4372 * ~ UnaryExpression 4373 * ! UnaryExpression 4374 * 4375 * See 11.4 4376 * 4377 * Parse unary expression. 4378 * @return Expression node. 4379 */ 4380 private Expression unaryExpression() { 4381 final int unaryLine = line; 4382 final long unaryToken = token; 4383 4384 switch (type) { 4385 case DELETE: { 4386 next(); 4387 final Expression expr = unaryExpression(); 4388 if (expr instanceof BaseNode || expr instanceof IdentNode) { 4389 return new UnaryNode(unaryToken, expr); 4390 } 4391 appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr)); 4392 return LiteralNode.newInstance(unaryToken, finish, true); 4393 } 4394 case VOID: 4395 case TYPEOF: 4396 case ADD: 4397 case SUB: 4398 case BIT_NOT: 4399 case NOT: 4400 next(); 4401 final Expression expr = unaryExpression(); 4402 return new UnaryNode(unaryToken, expr); 4403 4404 case INCPREFIX: 4405 case DECPREFIX: 4406 final TokenType opType = type; 4407 next(); 4408 4409 final Expression lhs = leftHandSideExpression(); 4410 // ++, -- without operand.. 4411 if (lhs == null) { 4412 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType())); 4413 } 4414 4415 return verifyIncDecExpression(unaryToken, opType, lhs, false); 4416 4417 default: 4418 break; 4419 } 4420 4421 final Expression expression = leftHandSideExpression(); 4422 4423 if (last != EOL) { 4424 switch (type) { 4425 case INCPREFIX: 4426 case DECPREFIX: 4427 final long opToken = token; 4428 final TokenType opType = type; 4429 final Expression lhs = expression; 4430 // ++, -- without operand.. 4431 if (lhs == null) { 4432 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType())); 4433 } 4434 next(); 4435 4436 return verifyIncDecExpression(opToken, opType, lhs, true); 4437 default: 4438 break; 4439 } 4440 } 4441 4442 if (expression == null) { 4443 throw error(AbstractParser.message("expected.operand", type.getNameOrType())); 4444 } 4445 4446 return expression; 4447 } 4448 4449 private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) { 4450 assert lhs != null; 4451 4452 if (!(lhs instanceof AccessNode || 4453 lhs instanceof IndexNode || 4454 lhs instanceof IdentNode)) { 4455 return referenceError(lhs, null, env._early_lvalue_error); 4456 } 4457 4458 if (lhs instanceof IdentNode) { 4459 if (!checkIdentLValue((IdentNode)lhs)) { 4460 return referenceError(lhs, null, false); 4461 } 4462 verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator"); 4463 } 4464 4465 return incDecExpression(unaryToken, opType, lhs, isPostfix); 4466 } 4467 4468 /** 4469 * {@code 4470 * MultiplicativeExpression : 4471 * UnaryExpression 4472 * MultiplicativeExpression * UnaryExpression 4473 * MultiplicativeExpression / UnaryExpression 4474 * MultiplicativeExpression % UnaryExpression 4475 * 4476 * See 11.5 4477 * 4478 * AdditiveExpression : 4479 * MultiplicativeExpression 4480 * AdditiveExpression + MultiplicativeExpression 4481 * AdditiveExpression - MultiplicativeExpression 4482 * 4483 * See 11.6 4484 * 4485 * ShiftExpression : 4486 * AdditiveExpression 4487 * ShiftExpression << AdditiveExpression 4488 * ShiftExpression >> AdditiveExpression 4489 * ShiftExpression >>> AdditiveExpression 4490 * 4491 * See 11.7 4492 * 4493 * RelationalExpression : 4494 * ShiftExpression 4495 * RelationalExpression < ShiftExpression 4496 * RelationalExpression > ShiftExpression 4497 * RelationalExpression <= ShiftExpression 4498 * RelationalExpression >= ShiftExpression 4499 * RelationalExpression instanceof ShiftExpression 4500 * RelationalExpression in ShiftExpression // if !noIf 4501 * 4502 * See 11.8 4503 * 4504 * RelationalExpression 4505 * EqualityExpression == RelationalExpression 4506 * EqualityExpression != RelationalExpression 4507 * EqualityExpression === RelationalExpression 4508 * EqualityExpression !== RelationalExpression 4509 * 4510 * See 11.9 4511 * 4512 * BitwiseANDExpression : 4513 * EqualityExpression 4514 * BitwiseANDExpression & EqualityExpression 4515 * 4516 * BitwiseXORExpression : 4517 * BitwiseANDExpression 4518 * BitwiseXORExpression ^ BitwiseANDExpression 4519 * 4520 * BitwiseORExpression : 4521 * BitwiseXORExpression 4522 * BitwiseORExpression | BitwiseXORExpression 4523 * 4524 * See 11.10 4525 * 4526 * LogicalANDExpression : 4527 * BitwiseORExpression 4528 * LogicalANDExpression && BitwiseORExpression 4529 * 4530 * LogicalORExpression : 4531 * LogicalANDExpression 4532 * LogicalORExpression || LogicalANDExpression 4533 * 4534 * See 11.11 4535 * 4536 * ConditionalExpression : 4537 * LogicalORExpression 4538 * LogicalORExpression ? AssignmentExpression : AssignmentExpression 4539 * 4540 * See 11.12 4541 * 4542 * AssignmentExpression : 4543 * ConditionalExpression 4544 * LeftHandSideExpression AssignmentOperator AssignmentExpression 4545 * 4546 * AssignmentOperator : 4547 * = *= /= %= += -= <<= >>= >>>= &= ^= |= 4548 * 4549 * See 11.13 4550 * 4551 * Expression : 4552 * AssignmentExpression 4553 * Expression , AssignmentExpression 4554 * 4555 * See 11.14 4556 * } 4557 * 4558 * Parse expression. 4559 * @return Expression node. 4560 */ 4561 protected Expression expression() { 4562 // This method is protected so that subclass can get details 4563 // at expression start point! 4564 4565 // Include commas in expression parsing. 4566 return expression(false); 4567 } 4568 4569 private Expression expression(final boolean noIn) { 4570 Expression assignmentExpression = assignmentExpression(noIn); 4571 while (type == COMMARIGHT) { 4572 final long commaToken = token; 4573 next(); 4574 4575 boolean rhsRestParameter = false; 4576 if (type == ELLIPSIS && isES6()) { 4577 // (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). 4578 // 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. 4579 if (isRestParameterEndOfArrowFunctionParameterList()) { 4580 next(); 4581 rhsRestParameter = true; 4582 } 4583 } 4584 4585 Expression rhs = assignmentExpression(noIn); 4586 4587 if (rhsRestParameter) { 4588 rhs = ((IdentNode)rhs).setIsRestParameter(); 4589 // Our only valid move is to end Expression here and continue with ArrowFunction. 4590 // We've already checked that this is the parameter list of an arrow function (see above). 4591 // RPAREN is next, so we'll finish the binary expression and drop out of the loop. 4592 assert type == RPAREN; 4593 } 4594 4595 assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs); 4596 } 4597 return assignmentExpression; 4598 } 4599 4600 private Expression expression(final int minPrecedence, final boolean noIn) { 4601 return expression(unaryExpression(), minPrecedence, noIn); 4602 } 4603 4604 private JoinPredecessorExpression joinPredecessorExpression() { 4605 return new JoinPredecessorExpression(expression()); 4606 } 4607 4608 private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) { 4609 // Get the precedence of the next operator. 4610 int precedence = type.getPrecedence(); 4611 Expression lhs = exprLhs; 4612 4613 // While greater precedence. 4614 while (type.isOperator(noIn) && precedence >= minPrecedence) { 4615 // Capture the operator token. 4616 final long op = token; 4617 4618 if (type == TERNARY) { 4619 // Skip operator. 4620 next(); 4621 4622 // Pass expression. Middle expression of a conditional expression can be a "in" 4623 // expression - even in the contexts where "in" is not permitted. 4624 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false); 4625 4626 expect(COLON); 4627 4628 // Fail expression. 4629 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn); 4630 4631 // Build up node. 4632 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr)); 4633 } else { 4634 // Skip operator. 4635 next(); 4636 4637 // Get the next primary expression. 4638 Expression rhs; 4639 final boolean isAssign = Token.descType(op) == ASSIGN; 4640 if(isAssign) { 4641 defaultNames.push(lhs); 4642 } 4643 try { 4644 rhs = unaryExpression(); 4645 // Get precedence of next operator. 4646 int nextPrecedence = type.getPrecedence(); 4647 4648 // Subtask greater precedence. 4649 while (type.isOperator(noIn) && 4650 (nextPrecedence > precedence || 4651 nextPrecedence == precedence && !type.isLeftAssociative())) { 4652 rhs = expression(rhs, nextPrecedence, noIn); 4653 nextPrecedence = type.getPrecedence(); 4654 } 4655 } finally { 4656 if(isAssign) { 4657 defaultNames.pop(); 4658 } 4659 } 4660 lhs = verifyAssignment(op, lhs, rhs); 4661 } 4662 4663 precedence = type.getPrecedence(); 4664 } 4665 4666 return lhs; 4667 } 4668 4669 /** 4670 * AssignmentExpression. 4671 * 4672 * AssignmentExpression[In, Yield] : 4673 * ConditionalExpression[?In, ?Yield] 4674 * [+Yield] YieldExpression[?In] 4675 * ArrowFunction[?In, ?Yield] 4676 * LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield] 4677 * LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield] 4678 * 4679 * @param noIn {@code true} if IN operator should be ignored. 4680 * @return the assignment expression 4681 */ 4682 protected Expression assignmentExpression(final boolean noIn) { 4683 // This method is protected so that subclass can get details 4684 // at assignment expression start point! 4685 4686 if (type == YIELD && inGeneratorFunction() && isES6()) { 4687 return yieldExpression(noIn); 4688 } 4689 4690 final long startToken = token; 4691 final int startLine = line; 4692 final Expression exprLhs = conditionalExpression(noIn); 4693 4694 if (type == ARROW && isES6()) { 4695 if (checkNoLineTerminator()) { 4696 final Expression paramListExpr; 4697 if (exprLhs instanceof ExpressionList) { 4698 paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0)); 4699 } else { 4700 paramListExpr = exprLhs; 4701 } 4702 return arrowFunction(startToken, startLine, paramListExpr); 4703 } 4704 } 4705 assert !(exprLhs instanceof ExpressionList); 4706 4707 if (isAssignmentOperator(type)) { 4708 final boolean isAssign = type == ASSIGN; 4709 if (isAssign) { 4710 defaultNames.push(exprLhs); 4711 } 4712 try { 4713 final long assignToken = token; 4714 next(); 4715 final Expression exprRhs = assignmentExpression(noIn); 4716 return verifyAssignment(assignToken, exprLhs, exprRhs); 4717 } finally { 4718 if (isAssign) { 4719 defaultNames.pop(); 4720 } 4721 } 4722 } else { 4723 return exprLhs; 4724 } 4725 } 4726 4727 /** 4728 * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}? 4729 */ 4730 private static boolean isAssignmentOperator(final TokenType type) { 4731 switch (type) { 4732 case ASSIGN: 4733 case ASSIGN_ADD: 4734 case ASSIGN_BIT_AND: 4735 case ASSIGN_BIT_OR: 4736 case ASSIGN_BIT_XOR: 4737 case ASSIGN_DIV: 4738 case ASSIGN_MOD: 4739 case ASSIGN_MUL: 4740 case ASSIGN_SAR: 4741 case ASSIGN_SHL: 4742 case ASSIGN_SHR: 4743 case ASSIGN_SUB: 4744 return true; 4745 } 4746 return false; 4747 } 4748 4749 /** 4750 * ConditionalExpression. 4751 */ 4752 private Expression conditionalExpression(final boolean noIn) { 4753 return expression(TERNARY.getPrecedence(), noIn); 4754 } 4755 4756 /** 4757 * ArrowFunction. 4758 * 4759 * @param startToken start token of the ArrowParameters expression 4760 * @param functionLine start line of the arrow function 4761 * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list) 4762 */ 4763 private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) { 4764 // caller needs to check that there's no LineTerminator between parameter list and arrow 4765 assert type != ARROW || checkNoLineTerminator(); 4766 expect(ARROW); 4767 4768 final long functionToken = Token.recast(startToken, ARROW); 4769 final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), NameCodec.encode("=>:") + functionLine); 4770 final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null); 4771 functionNode.setFlag(FunctionNode.IS_ANONYMOUS); 4772 4773 lc.push(functionNode); 4774 try { 4775 final ParserContextBlockNode parameterBlock = newBlock(); 4776 final List<IdentNode> parameters; 4777 try { 4778 parameters = convertArrowFunctionParameterList(paramListExpr, functionLine); 4779 functionNode.setParameters(parameters); 4780 4781 if (!functionNode.isSimpleParameterList()) { 4782 markEvalInArrowParameterList(parameterBlock); 4783 } 4784 } finally { 4785 restoreBlock(parameterBlock); 4786 } 4787 Block functionBody = functionBody(functionNode); 4788 4789 functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock); 4790 4791 verifyParameterList(parameters, functionNode); 4792 4793 final FunctionNode function = createFunctionNode( 4794 functionNode, 4795 functionToken, 4796 name, 4797 parameters, 4798 FunctionNode.Kind.ARROW, 4799 functionLine, 4800 functionBody); 4801 return function; 4802 } finally { 4803 lc.pop(functionNode); 4804 } 4805 } 4806 4807 private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) { 4808 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 4809 final ParserContextFunctionNode current = iter.next(); 4810 final ParserContextFunctionNode parent = iter.next(); 4811 4812 if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) { 4813 // we might have flagged has-eval in the parent function during parsing the parameter list, 4814 // if the parameter list contains eval; must tag arrow function as has-eval. 4815 for (final Statement st : parameterBlock.getStatements()) { 4816 st.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 4817 @Override 4818 public boolean enterCallNode(final CallNode callNode) { 4819 if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) { 4820 current.setFlag(FunctionNode.HAS_EVAL); 4821 } 4822 return true; 4823 } 4824 }); 4825 } 4826 // TODO: function containing the arrow function should not be flagged has-eval 4827 } 4828 } 4829 4830 private List<IdentNode> convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) { 4831 final List<IdentNode> parameters; 4832 if (paramListExpr == null) { 4833 // empty parameter list, i.e. () => 4834 parameters = Collections.emptyList(); 4835 } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) { 4836 parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine)); 4837 } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) { 4838 parameters = new ArrayList<>(); 4839 Expression car = paramListExpr; 4840 do { 4841 final Expression cdr = ((BinaryNode) car).rhs(); 4842 parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine)); 4843 car = ((BinaryNode) car).lhs(); 4844 } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT); 4845 parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine)); 4846 } else { 4847 throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken()); 4848 } 4849 return parameters; 4850 } 4851 4852 private IdentNode verifyArrowParameter(final Expression param, final int index, final int paramLine) { 4853 final String contextString = "function parameter"; 4854 if (param instanceof IdentNode) { 4855 final IdentNode ident = (IdentNode)param; 4856 verifyStrictIdent(ident, contextString); 4857 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4858 if (currentFunction != null) { 4859 currentFunction.addParameterBinding(ident); 4860 } 4861 return ident; 4862 } 4863 4864 if (param.isTokenType(ASSIGN)) { 4865 final Expression lhs = ((BinaryNode) param).lhs(); 4866 final long paramToken = lhs.getToken(); 4867 final Expression initializer = ((BinaryNode) param).rhs(); 4868 if (lhs instanceof IdentNode) { 4869 // default parameter 4870 final IdentNode ident = (IdentNode) lhs; 4871 4872 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4873 if (currentFunction != null) { 4874 if (env._parse_only) { 4875 currentFunction.addParameterExpression(ident, param); 4876 } else { 4877 final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); 4878 final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); 4879 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value); 4880 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4881 } 4882 4883 currentFunction.addParameterBinding(ident); 4884 currentFunction.setSimpleParameterList(false); 4885 } 4886 return ident; 4887 } else if (isDestructuringLhs(lhs)) { 4888 // binding pattern with initializer 4889 // Introduce synthetic temporary parameter to capture the object to be destructured. 4890 final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter(); 4891 verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString); 4892 4893 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4894 if (currentFunction != null) { 4895 if (env._parse_only) { 4896 currentFunction.addParameterExpression(ident, param); 4897 } else { 4898 final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); 4899 final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); 4900 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value); 4901 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4902 } 4903 } 4904 return ident; 4905 } 4906 } else if (isDestructuringLhs(param)) { 4907 // binding pattern 4908 final long paramToken = param.getToken(); 4909 4910 // Introduce synthetic temporary parameter to capture the object to be destructured. 4911 final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter(); 4912 verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString); 4913 4914 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); 4915 if (currentFunction != null) { 4916 if (env._parse_only) { 4917 currentFunction.addParameterExpression(ident, param); 4918 } else { 4919 final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident); 4920 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); 4921 } 4922 } 4923 return ident; 4924 } 4925 throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken()); 4926 } 4927 4928 private boolean checkNoLineTerminator() { 4929 assert type == ARROW; 4930 if (last == RPAREN) { 4931 return true; 4932 } else if (last == IDENT) { 4933 return true; 4934 } 4935 for (int i = k - 1; i >= 0; i--) { 4936 final TokenType t = T(i); 4937 switch (t) { 4938 case RPAREN: 4939 case IDENT: 4940 return true; 4941 case EOL: 4942 return false; 4943 case COMMENT: 4944 continue; 4945 default: 4946 if (t.getKind() == TokenKind.FUTURESTRICT) { 4947 return true; 4948 } 4949 return false; 4950 } 4951 } 4952 return false; 4953 } 4954 4955 /** 4956 * Peek ahead to see if what follows after the ellipsis is a rest parameter 4957 * at the end of an arrow function parameter list. 4958 */ 4959 private boolean isRestParameterEndOfArrowFunctionParameterList() { 4960 assert type == ELLIPSIS; 4961 // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT 4962 int i = 1; 4963 for (;;) { 4964 final TokenType t = T(k + i++); 4965 if (t == IDENT) { 4966 break; 4967 } else if (t == EOL || t == COMMENT) { 4968 continue; 4969 } else { 4970 return false; 4971 } 4972 } 4973 for (;;) { 4974 final TokenType t = T(k + i++); 4975 if (t == RPAREN) { 4976 break; 4977 } else if (t == EOL || t == COMMENT) { 4978 continue; 4979 } else { 4980 return false; 4981 } 4982 } 4983 for (;;) { 4984 final TokenType t = T(k + i++); 4985 if (t == ARROW) { 4986 break; 4987 } else if (t == COMMENT) { 4988 continue; 4989 } else { 4990 return false; 4991 } 4992 } 4993 return true; 4994 } 4995 4996 /** 4997 * Parse an end of line. 4998 */ 4999 private void endOfLine() { 5000 switch (type) { 5001 case SEMICOLON: 5002 case EOL: 5003 next(); 5004 break; 5005 case RPAREN: 5006 case RBRACKET: 5007 case RBRACE: 5008 case EOF: 5009 break; 5010 default: 5011 if (last != EOL) { 5012 expect(SEMICOLON); 5013 } 5014 break; 5015 } 5016 } 5017 5018 /** 5019 * Parse untagged template literal as string concatenation. 5020 */ 5021 private Expression templateLiteral() { 5022 assert type == TEMPLATE || type == TEMPLATE_HEAD; 5023 final boolean noSubstitutionTemplate = type == TEMPLATE; 5024 long lastLiteralToken = token; 5025 LiteralNode<?> literal = getLiteral(); 5026 if (noSubstitutionTemplate) { 5027 return literal; 5028 } 5029 5030 if (env._parse_only) { 5031 final List<Expression> exprs = new ArrayList<>(); 5032 exprs.add(literal); 5033 TokenType lastLiteralType; 5034 do { 5035 final Expression expression = expression(); 5036 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) { 5037 throw error(AbstractParser.message("unterminated.template.expression"), token); 5038 } 5039 exprs.add(expression); 5040 lastLiteralType = type; 5041 literal = getLiteral(); 5042 exprs.add(literal); 5043 } while (lastLiteralType == TEMPLATE_MIDDLE); 5044 return new TemplateLiteral(exprs); 5045 } else { 5046 Expression concat = literal; 5047 TokenType lastLiteralType; 5048 do { 5049 final Expression expression = expression(); 5050 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) { 5051 throw error(AbstractParser.message("unterminated.template.expression"), token); 5052 } 5053 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression); 5054 lastLiteralType = type; 5055 lastLiteralToken = token; 5056 literal = getLiteral(); 5057 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal); 5058 } while (lastLiteralType == TEMPLATE_MIDDLE); 5059 return concat; 5060 } 5061 } 5062 5063 /** 5064 * Parse tagged template literal as argument list. 5065 * @return argument list for a tag function call (template object, ...substitutions) 5066 */ 5067 private List<Expression> templateLiteralArgumentList() { 5068 assert type == TEMPLATE || type == TEMPLATE_HEAD; 5069 final ArrayList<Expression> argumentList = new ArrayList<>(); 5070 final ArrayList<Expression> rawStrings = new ArrayList<>(); 5071 final ArrayList<Expression> cookedStrings = new ArrayList<>(); 5072 argumentList.add(null); // filled at the end 5073 5074 final long templateToken = token; 5075 final boolean hasSubstitutions = type == TEMPLATE_HEAD; 5076 addTemplateLiteralString(rawStrings, cookedStrings); 5077 5078 if (hasSubstitutions) { 5079 TokenType lastLiteralType; 5080 do { 5081 final Expression expression = expression(); 5082 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) { 5083 throw error(AbstractParser.message("unterminated.template.expression"), token); 5084 } 5085 argumentList.add(expression); 5086 5087 lastLiteralType = type; 5088 addTemplateLiteralString(rawStrings, cookedStrings); 5089 } while (lastLiteralType == TEMPLATE_MIDDLE); 5090 } 5091 5092 final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings); 5093 final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings); 5094 final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray); 5095 argumentList.set(0, templateObject); 5096 return optimizeList(argumentList); 5097 } 5098 5099 private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) { 5100 final long stringToken = token; 5101 final String rawString = lexer.valueOfRawString(stringToken); 5102 final String cookedString = (String) getValue(); 5103 next(); 5104 rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString)); 5105 cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString)); 5106 } 5107 5108 5109 /** 5110 * Parse a module. 5111 * 5112 * Module : 5113 * ModuleBody? 5114 * 5115 * ModuleBody : 5116 * ModuleItemList 5117 */ 5118 private FunctionNode module(final String moduleName) { 5119 final boolean oldStrictMode = isStrictMode; 5120 try { 5121 isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1) 5122 5123 // Make a pseudo-token for the script holding its start and length. 5124 final int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish); 5125 final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart); 5126 final int functionLine = line; 5127 5128 final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName); 5129 final ParserContextFunctionNode script = createParserContextFunctionNode( 5130 ident, 5131 functionToken, 5132 FunctionNode.Kind.MODULE, 5133 functionLine, 5134 Collections.<IdentNode>emptyList()); 5135 lc.push(script); 5136 5137 final ParserContextModuleNode module = new ParserContextModuleNode(moduleName); 5138 lc.push(module); 5139 5140 final ParserContextBlockNode body = newBlock(); 5141 5142 functionDeclarations = new ArrayList<>(); 5143 moduleBody(); 5144 addFunctionDeclarations(script); 5145 functionDeclarations = null; 5146 5147 restoreBlock(body); 5148 body.setFlag(Block.NEEDS_SCOPE); 5149 final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements()); 5150 lc.pop(module); 5151 lc.pop(script); 5152 script.setLastToken(token); 5153 5154 expect(EOF); 5155 5156 script.setModule(module.createModule()); 5157 return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody); 5158 } finally { 5159 isStrictMode = oldStrictMode; 5160 } 5161 } 5162 5163 /** 5164 * Parse module body. 5165 * 5166 * ModuleBody : 5167 * ModuleItemList 5168 * 5169 * ModuleItemList : 5170 * ModuleItem 5171 * ModuleItemList ModuleItem 5172 * 5173 * ModuleItem : 5174 * ImportDeclaration 5175 * ExportDeclaration 5176 * StatementListItem 5177 */ 5178 private void moduleBody() { 5179 loop: 5180 while (type != EOF) { 5181 switch (type) { 5182 case EOF: 5183 break loop; 5184 case IMPORT: 5185 importDeclaration(); 5186 break; 5187 case EXPORT: 5188 exportDeclaration(); 5189 break; 5190 default: 5191 // StatementListItem 5192 statement(true, 0, false, false); 5193 break; 5194 } 5195 } 5196 } 5197 5198 5199 /** 5200 * Parse import declaration. 5201 * 5202 * ImportDeclaration : 5203 * import ImportClause FromClause ; 5204 * import ModuleSpecifier ; 5205 * ImportClause : 5206 * ImportedDefaultBinding 5207 * NameSpaceImport 5208 * NamedImports 5209 * ImportedDefaultBinding , NameSpaceImport 5210 * ImportedDefaultBinding , NamedImports 5211 * ImportedDefaultBinding : 5212 * ImportedBinding 5213 * ModuleSpecifier : 5214 * StringLiteral 5215 * ImportedBinding : 5216 * BindingIdentifier 5217 */ 5218 private void importDeclaration() { 5219 final int startPosition = start; 5220 expect(IMPORT); 5221 final ParserContextModuleNode module = lc.getCurrentModule(); 5222 if (type == STRING || type == ESCSTRING) { 5223 // import ModuleSpecifier ; 5224 final IdentNode moduleSpecifier = createIdentNode(token, finish, (String) getValue()); 5225 next(); 5226 module.addModuleRequest(moduleSpecifier); 5227 } else { 5228 // import ImportClause FromClause ; 5229 List<Module.ImportEntry> importEntries; 5230 if (type == MUL) { 5231 importEntries = Collections.singletonList(nameSpaceImport(startPosition)); 5232 } else if (type == LBRACE) { 5233 importEntries = namedImports(startPosition); 5234 } else if (isBindingIdentifier()) { 5235 // ImportedDefaultBinding 5236 final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding"); 5237 final Module.ImportEntry defaultImport = Module.ImportEntry.importSpecifier(importedDefaultBinding, startPosition, finish); 5238 5239 if (type == COMMARIGHT) { 5240 next(); 5241 importEntries = new ArrayList<>(); 5242 if (type == MUL) { 5243 importEntries.add(nameSpaceImport(startPosition)); 5244 } else if (type == LBRACE) { 5245 importEntries.addAll(namedImports(startPosition)); 5246 } else { 5247 throw error(AbstractParser.message("expected.named.import")); 5248 } 5249 } else { 5250 importEntries = Collections.singletonList(defaultImport); 5251 } 5252 } else { 5253 throw error(AbstractParser.message("expected.import")); 5254 } 5255 5256 final IdentNode moduleSpecifier = fromClause(); 5257 module.addModuleRequest(moduleSpecifier); 5258 for (int i = 0; i < importEntries.size(); i++) { 5259 module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier, finish)); 5260 } 5261 } 5262 expect(SEMICOLON); 5263 } 5264 5265 /** 5266 * NameSpaceImport : 5267 * * as ImportedBinding 5268 * 5269 * @param startPosition the start of the import declaration 5270 * @return imported binding identifier 5271 */ 5272 private Module.ImportEntry nameSpaceImport(final int startPosition) { 5273 assert type == MUL; 5274 final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME); 5275 next(); 5276 final long asToken = token; 5277 final String as = (String) expectValue(IDENT); 5278 if (!"as".equals(as)) { 5279 throw error(AbstractParser.message("expected.as"), asToken); 5280 } 5281 final IdentNode localNameSpace = bindingIdentifier("ImportedBinding"); 5282 return Module.ImportEntry.importSpecifier(starName, localNameSpace, startPosition, finish); 5283 } 5284 5285 /** 5286 * NamedImports : 5287 * { } 5288 * { ImportsList } 5289 * { ImportsList , } 5290 * ImportsList : 5291 * ImportSpecifier 5292 * ImportsList , ImportSpecifier 5293 * ImportSpecifier : 5294 * ImportedBinding 5295 * IdentifierName as ImportedBinding 5296 * ImportedBinding : 5297 * BindingIdentifier 5298 */ 5299 private List<Module.ImportEntry> namedImports(final int startPosition) { 5300 assert type == LBRACE; 5301 next(); 5302 final List<Module.ImportEntry> importEntries = new ArrayList<>(); 5303 while (type != RBRACE) { 5304 final boolean bindingIdentifier = isBindingIdentifier(); 5305 final long nameToken = token; 5306 final IdentNode importName = getIdentifierName(); 5307 if (type == IDENT && "as".equals(getValue())) { 5308 next(); 5309 final IdentNode localName = bindingIdentifier("ImportedBinding"); 5310 importEntries.add(Module.ImportEntry.importSpecifier(importName, localName, startPosition, finish)); 5311 } else if (!bindingIdentifier) { 5312 throw error(AbstractParser.message("expected.binding.identifier"), nameToken); 5313 } else { 5314 importEntries.add(Module.ImportEntry.importSpecifier(importName, startPosition, finish)); 5315 } 5316 if (type == COMMARIGHT) { 5317 next(); 5318 } else { 5319 break; 5320 } 5321 } 5322 expect(RBRACE); 5323 return importEntries; 5324 } 5325 5326 /** 5327 * FromClause : 5328 * from ModuleSpecifier 5329 */ 5330 private IdentNode fromClause() { 5331 final long fromToken = token; 5332 final String name = (String) expectValue(IDENT); 5333 if (!"from".equals(name)) { 5334 throw error(AbstractParser.message("expected.from"), fromToken); 5335 } 5336 if (type == STRING || type == ESCSTRING) { 5337 final IdentNode moduleSpecifier = createIdentNode(Token.recast(token, IDENT), finish, (String) getValue()); 5338 next(); 5339 return moduleSpecifier; 5340 } else { 5341 throw error(expectMessage(STRING)); 5342 } 5343 } 5344 5345 /** 5346 * Parse export declaration. 5347 * 5348 * ExportDeclaration : 5349 * export * FromClause ; 5350 * export ExportClause FromClause ; 5351 * export ExportClause ; 5352 * export VariableStatement 5353 * export Declaration 5354 * export default HoistableDeclaration[Default] 5355 * export default ClassDeclaration[Default] 5356 * export default [lookahead !in {function, class}] AssignmentExpression[In] ; 5357 */ 5358 private void exportDeclaration() { 5359 expect(EXPORT); 5360 final int startPosition = start; 5361 final ParserContextModuleNode module = lc.getCurrentModule(); 5362 switch (type) { 5363 case MUL: { 5364 final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME); 5365 next(); 5366 final IdentNode moduleRequest = fromClause(); 5367 expect(SEMICOLON); 5368 module.addModuleRequest(moduleRequest); 5369 module.addStarExportEntry(Module.ExportEntry.exportStarFrom(starName, moduleRequest, startPosition, finish)); 5370 break; 5371 } 5372 case LBRACE: { 5373 final List<Module.ExportEntry> exportEntries = exportClause(startPosition); 5374 if (type == IDENT && "from".equals(getValue())) { 5375 final IdentNode moduleRequest = fromClause(); 5376 module.addModuleRequest(moduleRequest); 5377 for (final Module.ExportEntry exportEntry : exportEntries) { 5378 module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest, finish)); 5379 } 5380 } else { 5381 for (final Module.ExportEntry exportEntry : exportEntries) { 5382 module.addLocalExportEntry(exportEntry); 5383 } 5384 } 5385 expect(SEMICOLON); 5386 break; 5387 } 5388 case DEFAULT: 5389 final IdentNode defaultName = createIdentNode(Token.recast(token, IDENT), finish, Module.DEFAULT_NAME); 5390 next(); 5391 final Expression assignmentExpression; 5392 IdentNode ident; 5393 final int lineNumber = line; 5394 final long rhsToken = token; 5395 final boolean declaration; 5396 switch (type) { 5397 case FUNCTION: 5398 assignmentExpression = functionExpression(false, true); 5399 ident = ((FunctionNode) assignmentExpression).getIdent(); 5400 declaration = true; 5401 break; 5402 case CLASS: 5403 assignmentExpression = classDeclaration(true); 5404 ident = ((ClassNode) assignmentExpression).getIdent(); 5405 declaration = true; 5406 break; 5407 default: 5408 assignmentExpression = assignmentExpression(false); 5409 ident = null; 5410 declaration = false; 5411 break; 5412 } 5413 if (ident != null) { 5414 module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish)); 5415 } else { 5416 ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME); 5417 lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression)); 5418 if (!declaration) { 5419 expect(SEMICOLON); 5420 } 5421 module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish)); 5422 } 5423 break; 5424 case VAR: 5425 case LET: 5426 case CONST: 5427 final List<Statement> statements = lc.getCurrentBlock().getStatements(); 5428 final int previousEnd = statements.size(); 5429 variableStatement(type); 5430 for (final Statement statement : statements.subList(previousEnd, statements.size())) { 5431 if (statement instanceof VarNode) { 5432 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName(), startPosition, finish)); 5433 } 5434 } 5435 break; 5436 case CLASS: { 5437 final ClassNode classDeclaration = classDeclaration(false); 5438 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent(), startPosition, finish)); 5439 break; 5440 } 5441 case FUNCTION: { 5442 final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true); 5443 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent(), startPosition, finish)); 5444 break; 5445 } 5446 default: 5447 throw error(AbstractParser.message("invalid.export"), token); 5448 } 5449 } 5450 5451 /** 5452 * ExportClause : 5453 * { } 5454 * { ExportsList } 5455 * { ExportsList , } 5456 * ExportsList : 5457 * ExportSpecifier 5458 * ExportsList , ExportSpecifier 5459 * ExportSpecifier : 5460 * IdentifierName 5461 * IdentifierName as IdentifierName 5462 * 5463 * @return a list of ExportSpecifiers 5464 */ 5465 private List<Module.ExportEntry> exportClause(final int startPosition) { 5466 assert type == LBRACE; 5467 next(); 5468 final List<Module.ExportEntry> exports = new ArrayList<>(); 5469 while (type != RBRACE) { 5470 final IdentNode localName = getIdentifierName(); 5471 if (type == IDENT && "as".equals(getValue())) { 5472 next(); 5473 final IdentNode exportName = getIdentifierName(); 5474 exports.add(Module.ExportEntry.exportSpecifier(exportName, localName, startPosition, finish)); 5475 } else { 5476 exports.add(Module.ExportEntry.exportSpecifier(localName, startPosition, finish)); 5477 } 5478 if (type == COMMARIGHT) { 5479 next(); 5480 } else { 5481 break; 5482 } 5483 } 5484 expect(RBRACE); 5485 return exports; 5486 } 5487 5488 @Override 5489 public String toString() { 5490 return "'JavaScript Parsing'"; 5491 } 5492 5493 private static void markEval(final ParserContext lc) { 5494 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5495 boolean flaggedCurrentFn = false; 5496 while (iter.hasNext()) { 5497 final ParserContextFunctionNode fn = iter.next(); 5498 if (!flaggedCurrentFn) { 5499 fn.setFlag(FunctionNode.HAS_EVAL); 5500 flaggedCurrentFn = true; 5501 if (fn.getKind() == FunctionNode.Kind.ARROW) { 5502 // possible use of this in an eval that's nested in an arrow function, e.g.: 5503 // function fun(){ return (() => eval("this"))(); }; 5504 markThis(lc); 5505 markNewTarget(lc); 5506 } 5507 } else { 5508 fn.setFlag(FunctionNode.HAS_NESTED_EVAL); 5509 } 5510 final ParserContextBlockNode body = lc.getFunctionBody(fn); 5511 // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip 5512 // parsing a nested function. functionBody() contains code to compensate for the lack of invoking 5513 // this method when the parser skips a nested function. 5514 body.setFlag(Block.NEEDS_SCOPE); 5515 fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK); 5516 } 5517 } 5518 5519 private void prependStatement(final Statement statement) { 5520 lc.prependStatementToCurrentNode(statement); 5521 } 5522 5523 private void appendStatement(final Statement statement) { 5524 lc.appendStatementToCurrentNode(statement); 5525 } 5526 5527 private static void markSuperCall(final ParserContext lc) { 5528 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5529 while (iter.hasNext()) { 5530 final ParserContextFunctionNode fn = iter.next(); 5531 if (fn.getKind() != FunctionNode.Kind.ARROW) { 5532 assert fn.isSubclassConstructor(); 5533 fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER); 5534 break; 5535 } 5536 } 5537 } 5538 5539 private ParserContextFunctionNode getCurrentNonArrowFunction() { 5540 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5541 while (iter.hasNext()) { 5542 final ParserContextFunctionNode fn = iter.next(); 5543 if (fn.getKind() != FunctionNode.Kind.ARROW) { 5544 return fn; 5545 } 5546 } 5547 return null; 5548 } 5549 5550 private static void markThis(final ParserContext lc) { 5551 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5552 while (iter.hasNext()) { 5553 final ParserContextFunctionNode fn = iter.next(); 5554 fn.setFlag(FunctionNode.USES_THIS); 5555 if (fn.getKind() != FunctionNode.Kind.ARROW) { 5556 break; 5557 } 5558 } 5559 } 5560 5561 private static void markNewTarget(final ParserContext lc) { 5562 final Iterator<ParserContextFunctionNode> iter = lc.getFunctions(); 5563 while (iter.hasNext()) { 5564 final ParserContextFunctionNode fn = iter.next(); 5565 if (fn.getKind() != FunctionNode.Kind.ARROW) { 5566 if (!fn.isProgram()) { 5567 fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET); 5568 } 5569 break; 5570 } 5571 } 5572 } 5573 5574 private boolean inGeneratorFunction() { 5575 return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR; 5576 } 5577 }