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