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