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