1/* 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 * 21 */ 22 23#ifndef Parser_h 24#define Parser_h 25 26#include "Debugger.h" 27#include "ExceptionHelpers.h" 28#include "Executable.h" 29#include "JSGlobalObject.h" 30#include "Lexer.h" 31#include "Nodes.h" 32#include "ParserArena.h" 33#include "ParserError.h" 34#include "ParserTokens.h" 35#include "SourceProvider.h" 36#include "SourceProviderCache.h" 37#include "SourceProviderCacheItem.h" 38#include <wtf/Forward.h> 39#include <wtf/Noncopyable.h> 40#include <wtf/OwnPtr.h> 41#include <wtf/RefPtr.h> 42namespace JSC { 43struct Scope; 44} 45 46namespace WTF { 47template <> struct VectorTraits<JSC::Scope> : SimpleClassVectorTraits { 48 static const bool canInitializeWithMemset = false; // Not all Scope data members initialize to 0. 49}; 50} 51 52namespace JSC { 53 54class ExecState; 55class FunctionBodyNode; 56class FunctionParameters; 57class Identifier; 58class VM; 59class ProgramNode; 60class SourceCode; 61 62// Macros to make the more common TreeBuilder types a little less verbose 63#define TreeStatement typename TreeBuilder::Statement 64#define TreeExpression typename TreeBuilder::Expression 65#define TreeFormalParameterList typename TreeBuilder::FormalParameterList 66#define TreeSourceElements typename TreeBuilder::SourceElements 67#define TreeClause typename TreeBuilder::Clause 68#define TreeClauseList typename TreeBuilder::ClauseList 69#define TreeConstDeclList typename TreeBuilder::ConstDeclList 70#define TreeArguments typename TreeBuilder::Arguments 71#define TreeArgumentsList typename TreeBuilder::ArgumentsList 72#define TreeFunctionBody typename TreeBuilder::FunctionBody 73#define TreeProperty typename TreeBuilder::Property 74#define TreePropertyList typename TreeBuilder::PropertyList 75#define TreeDeconstructionPattern typename TreeBuilder::DeconstructionPattern 76 77COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens); 78 79enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode }; 80enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName }; 81enum FunctionParseMode { FunctionMode, GetterMode, SetterMode }; 82enum DeconstructionKind { 83 DeconstructToVariables, 84 DeconstructToParameters, 85 DeconstructToExpressions 86}; 87 88template <typename T> inline bool isEvalNode() { return false; } 89template <> inline bool isEvalNode<EvalNode>() { return true; } 90 91struct ScopeLabelInfo { 92 ScopeLabelInfo(StringImpl* ident, bool isLoop) 93 : m_ident(ident) 94 , m_isLoop(isLoop) 95 { 96 } 97 98 StringImpl* m_ident; 99 bool m_isLoop; 100}; 101 102struct Scope { 103 Scope(const VM* vm, bool isFunction, bool strictMode) 104 : m_vm(vm) 105 , m_shadowsArguments(false) 106 , m_usesEval(false) 107 , m_needsFullActivation(false) 108 , m_allowsNewDecls(true) 109 , m_strictMode(strictMode) 110 , m_isFunction(isFunction) 111 , m_isFunctionBoundary(false) 112 , m_isValidStrictMode(true) 113 , m_loopDepth(0) 114 , m_switchDepth(0) 115 { 116 } 117 118 Scope(const Scope& rhs) 119 : m_vm(rhs.m_vm) 120 , m_shadowsArguments(rhs.m_shadowsArguments) 121 , m_usesEval(rhs.m_usesEval) 122 , m_needsFullActivation(rhs.m_needsFullActivation) 123 , m_allowsNewDecls(rhs.m_allowsNewDecls) 124 , m_strictMode(rhs.m_strictMode) 125 , m_isFunction(rhs.m_isFunction) 126 , m_isFunctionBoundary(rhs.m_isFunctionBoundary) 127 , m_isValidStrictMode(rhs.m_isValidStrictMode) 128 , m_loopDepth(rhs.m_loopDepth) 129 , m_switchDepth(rhs.m_switchDepth) 130 { 131 if (rhs.m_labels) { 132 m_labels = adoptPtr(new LabelStack); 133 134 typedef LabelStack::const_iterator iterator; 135 iterator end = rhs.m_labels->end(); 136 for (iterator it = rhs.m_labels->begin(); it != end; ++it) 137 m_labels->append(ScopeLabelInfo(it->m_ident, it->m_isLoop)); 138 } 139 } 140 141 void startSwitch() { m_switchDepth++; } 142 void endSwitch() { m_switchDepth--; } 143 void startLoop() { m_loopDepth++; } 144 void endLoop() { ASSERT(m_loopDepth); m_loopDepth--; } 145 bool inLoop() { return !!m_loopDepth; } 146 bool breakIsValid() { return m_loopDepth || m_switchDepth; } 147 bool continueIsValid() { return m_loopDepth; } 148 149 void pushLabel(const Identifier* label, bool isLoop) 150 { 151 if (!m_labels) 152 m_labels = adoptPtr(new LabelStack); 153 m_labels->append(ScopeLabelInfo(label->impl(), isLoop)); 154 } 155 156 void popLabel() 157 { 158 ASSERT(m_labels); 159 ASSERT(m_labels->size()); 160 m_labels->removeLast(); 161 } 162 163 ScopeLabelInfo* getLabel(const Identifier* label) 164 { 165 if (!m_labels) 166 return 0; 167 for (int i = m_labels->size(); i > 0; i--) { 168 if (m_labels->at(i - 1).m_ident == label->impl()) 169 return &m_labels->at(i - 1); 170 } 171 return 0; 172 } 173 174 void setIsFunction() 175 { 176 m_isFunction = true; 177 m_isFunctionBoundary = true; 178 } 179 bool isFunction() { return m_isFunction; } 180 bool isFunctionBoundary() { return m_isFunctionBoundary; } 181 182 void declareCallee(const Identifier* ident) 183 { 184 m_declaredVariables.add(ident->string().impl()); 185 } 186 187 bool declareVariable(const Identifier* ident) 188 { 189 bool isValidStrictMode = m_vm->propertyNames->eval != *ident && m_vm->propertyNames->arguments != *ident; 190 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; 191 m_declaredVariables.add(ident->string().impl()); 192 return isValidStrictMode; 193 } 194 195 bool hasDeclaredVariable(const Identifier& ident) 196 { 197 return m_declaredVariables.contains(ident.impl()); 198 } 199 200 bool hasDeclaredParameter(const Identifier& ident) 201 { 202 return m_declaredParameters.contains(ident.impl()) || m_declaredVariables.contains(ident.impl()); 203 } 204 205 void declareWrite(const Identifier* ident) 206 { 207 ASSERT(m_strictMode); 208 m_writtenVariables.add(ident->impl()); 209 } 210 211 void preventNewDecls() { m_allowsNewDecls = false; } 212 bool allowsNewDecls() const { return m_allowsNewDecls; } 213 214 bool declareParameter(const Identifier* ident) 215 { 216 bool isArguments = m_vm->propertyNames->arguments == *ident; 217 bool isValidStrictMode = m_declaredVariables.add(ident->string().impl()).isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments; 218 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; 219 m_declaredParameters.add(ident->string().impl()); 220 221 if (isArguments) 222 m_shadowsArguments = true; 223 return isValidStrictMode; 224 } 225 226 enum BindingResult { 227 BindingFailed, 228 StrictBindingFailed, 229 BindingSucceeded 230 }; 231 BindingResult declareBoundParameter(const Identifier* ident) 232 { 233 bool isArguments = m_vm->propertyNames->arguments == *ident; 234 bool newEntry = m_declaredVariables.add(ident->string().impl()).isNewEntry; 235 bool isValidStrictMode = newEntry && m_vm->propertyNames->eval != *ident && !isArguments; 236 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; 237 238 if (isArguments) 239 m_shadowsArguments = true; 240 if (!newEntry) 241 return BindingFailed; 242 return isValidStrictMode ? BindingSucceeded : StrictBindingFailed; 243 } 244 245 void getUsedVariables(IdentifierSet& usedVariables) 246 { 247 usedVariables.swap(m_usedVariables); 248 } 249 250 void useVariable(const Identifier* ident, bool isEval) 251 { 252 m_usesEval |= isEval; 253 m_usedVariables.add(ident->string().impl()); 254 } 255 256 void setNeedsFullActivation() { m_needsFullActivation = true; } 257 258 bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) 259 { 260 if (nestedScope->m_usesEval) 261 m_usesEval = true; 262 IdentifierSet::iterator end = nestedScope->m_usedVariables.end(); 263 for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) { 264 if (nestedScope->m_declaredVariables.contains(*ptr)) 265 continue; 266 m_usedVariables.add(*ptr); 267 if (shouldTrackClosedVariables) 268 m_closedVariables.add(*ptr); 269 } 270 if (nestedScope->m_writtenVariables.size()) { 271 IdentifierSet::iterator end = nestedScope->m_writtenVariables.end(); 272 for (IdentifierSet::iterator ptr = nestedScope->m_writtenVariables.begin(); ptr != end; ++ptr) { 273 if (nestedScope->m_declaredVariables.contains(*ptr)) 274 continue; 275 m_writtenVariables.add(*ptr); 276 } 277 } 278 279 return true; 280 } 281 282 void getCapturedVariables(IdentifierSet& capturedVariables, bool& modifiedParameter) 283 { 284 if (m_needsFullActivation || m_usesEval) { 285 modifiedParameter = true; 286 capturedVariables.swap(m_declaredVariables); 287 return; 288 } 289 for (IdentifierSet::iterator ptr = m_closedVariables.begin(); ptr != m_closedVariables.end(); ++ptr) { 290 if (!m_declaredVariables.contains(*ptr)) 291 continue; 292 capturedVariables.add(*ptr); 293 } 294 modifiedParameter = false; 295 if (m_declaredParameters.size()) { 296 IdentifierSet::iterator end = m_writtenVariables.end(); 297 for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) { 298 if (!m_declaredParameters.contains(*ptr)) 299 continue; 300 modifiedParameter = true; 301 break; 302 } 303 } 304 } 305 void setStrictMode() { m_strictMode = true; } 306 bool strictMode() const { return m_strictMode; } 307 bool isValidStrictMode() const { return m_isValidStrictMode; } 308 bool shadowsArguments() const { return m_shadowsArguments; } 309 310 void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl>>& vector) 311 { 312 IdentifierSet::iterator end = capturedVariables.end(); 313 for (IdentifierSet::iterator it = capturedVariables.begin(); it != end; ++it) { 314 if (m_declaredVariables.contains(*it)) 315 continue; 316 vector.append(*it); 317 } 318 } 319 320 void fillParametersForSourceProviderCache(SourceProviderCacheItemCreationParameters& parameters) 321 { 322 ASSERT(m_isFunction); 323 parameters.usesEval = m_usesEval; 324 parameters.strictMode = m_strictMode; 325 parameters.needsFullActivation = m_needsFullActivation; 326 copyCapturedVariablesToVector(m_writtenVariables, parameters.writtenVariables); 327 copyCapturedVariablesToVector(m_usedVariables, parameters.usedVariables); 328 } 329 330 void restoreFromSourceProviderCache(const SourceProviderCacheItem* info) 331 { 332 ASSERT(m_isFunction); 333 m_usesEval = info->usesEval; 334 m_strictMode = info->strictMode; 335 m_needsFullActivation = info->needsFullActivation; 336 for (unsigned i = 0; i < info->usedVariablesCount; ++i) 337 m_usedVariables.add(info->usedVariables()[i]); 338 for (unsigned i = 0; i < info->writtenVariablesCount; ++i) 339 m_writtenVariables.add(info->writtenVariables()[i]); 340 } 341 342private: 343 const VM* m_vm; 344 bool m_shadowsArguments : 1; 345 bool m_usesEval : 1; 346 bool m_needsFullActivation : 1; 347 bool m_allowsNewDecls : 1; 348 bool m_strictMode : 1; 349 bool m_isFunction : 1; 350 bool m_isFunctionBoundary : 1; 351 bool m_isValidStrictMode : 1; 352 int m_loopDepth; 353 int m_switchDepth; 354 355 typedef Vector<ScopeLabelInfo, 2> LabelStack; 356 OwnPtr<LabelStack> m_labels; 357 IdentifierSet m_declaredParameters; 358 IdentifierSet m_declaredVariables; 359 IdentifierSet m_usedVariables; 360 IdentifierSet m_closedVariables; 361 IdentifierSet m_writtenVariables; 362}; 363 364typedef Vector<Scope, 10> ScopeStack; 365 366struct ScopeRef { 367 ScopeRef(ScopeStack* scopeStack, unsigned index) 368 : m_scopeStack(scopeStack) 369 , m_index(index) 370 { 371 } 372 Scope* operator->() { return &m_scopeStack->at(m_index); } 373 unsigned index() const { return m_index; } 374 375 bool hasContainingScope() 376 { 377 return m_index && !m_scopeStack->at(m_index).isFunctionBoundary(); 378 } 379 380 ScopeRef containingScope() 381 { 382 ASSERT(hasContainingScope()); 383 return ScopeRef(m_scopeStack, m_index - 1); 384 } 385 386private: 387 ScopeStack* m_scopeStack; 388 unsigned m_index; 389}; 390 391template <typename LexerType> 392class Parser { 393 WTF_MAKE_NONCOPYABLE(Parser); 394 WTF_MAKE_FAST_ALLOCATED; 395 396public: 397 Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode); 398 ~Parser(); 399 400 template <class ParsedNode> 401 PassRefPtr<ParsedNode> parse(ParserError&, bool needReparsingAdjustment); 402 403 JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); } 404 Vector<RefPtr<StringImpl>>&& closedVariables() { return WTF::move(m_closedVariables); } 405 406private: 407 struct AllowInOverride { 408 AllowInOverride(Parser* parser) 409 : m_parser(parser) 410 , m_oldAllowsIn(parser->m_allowsIn) 411 { 412 parser->m_allowsIn = true; 413 } 414 ~AllowInOverride() 415 { 416 m_parser->m_allowsIn = m_oldAllowsIn; 417 } 418 Parser* m_parser; 419 bool m_oldAllowsIn; 420 }; 421 422 struct AutoPopScopeRef : public ScopeRef { 423 AutoPopScopeRef(Parser* parser, ScopeRef scope) 424 : ScopeRef(scope) 425 , m_parser(parser) 426 { 427 } 428 429 ~AutoPopScopeRef() 430 { 431 if (m_parser) 432 m_parser->popScope(*this, false); 433 } 434 435 void setPopped() 436 { 437 m_parser = 0; 438 } 439 440 private: 441 Parser* m_parser; 442 }; 443 444 ScopeRef currentScope() 445 { 446 return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); 447 } 448 449 ScopeRef pushScope() 450 { 451 bool isFunction = false; 452 bool isStrict = false; 453 if (!m_scopeStack.isEmpty()) { 454 isStrict = m_scopeStack.last().strictMode(); 455 isFunction = m_scopeStack.last().isFunction(); 456 } 457 m_scopeStack.append(Scope(m_vm, isFunction, isStrict)); 458 return currentScope(); 459 } 460 461 bool popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables) 462 { 463 ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1); 464 ASSERT(m_scopeStack.size() > 1); 465 bool result = m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); 466 m_scopeStack.removeLast(); 467 return result; 468 } 469 470 bool popScope(ScopeRef& scope, bool shouldTrackClosedVariables) 471 { 472 return popScopeInternal(scope, shouldTrackClosedVariables); 473 } 474 475 bool popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables) 476 { 477 scope.setPopped(); 478 return popScopeInternal(scope, shouldTrackClosedVariables); 479 } 480 481 bool declareVariable(const Identifier* ident) 482 { 483 unsigned i = m_scopeStack.size() - 1; 484 ASSERT(i < m_scopeStack.size()); 485 while (!m_scopeStack[i].allowsNewDecls()) { 486 i--; 487 ASSERT(i < m_scopeStack.size()); 488 } 489 return m_scopeStack[i].declareVariable(ident); 490 } 491 492 NEVER_INLINE bool hasDeclaredVariable(const Identifier& ident) 493 { 494 unsigned i = m_scopeStack.size() - 1; 495 ASSERT(i < m_scopeStack.size()); 496 while (!m_scopeStack[i].allowsNewDecls()) { 497 i--; 498 ASSERT(i < m_scopeStack.size()); 499 } 500 return m_scopeStack[i].hasDeclaredVariable(ident); 501 } 502 503 NEVER_INLINE bool hasDeclaredParameter(const Identifier& ident) 504 { 505 unsigned i = m_scopeStack.size() - 1; 506 ASSERT(i < m_scopeStack.size()); 507 while (!m_scopeStack[i].allowsNewDecls()) { 508 i--; 509 ASSERT(i < m_scopeStack.size()); 510 } 511 return m_scopeStack[i].hasDeclaredParameter(ident); 512 } 513 514 void declareWrite(const Identifier* ident) 515 { 516 if (!m_syntaxAlreadyValidated || strictMode()) 517 m_scopeStack.last().declareWrite(ident); 518 } 519 520 ScopeStack m_scopeStack; 521 522 const SourceProviderCacheItem* findCachedFunctionInfo(int openBracePos) 523 { 524 return m_functionCache ? m_functionCache->get(openBracePos) : 0; 525 } 526 527 Parser(); 528 String parseInner(); 529 530 void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, 531 ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, int, IdentifierSet&, const Vector<RefPtr<StringImpl>>&&); 532 533 // Used to determine type of error to report. 534 bool isFunctionBodyNode(ScopeNode*) { return false; } 535 bool isFunctionBodyNode(FunctionBodyNode*) { return true; } 536 537 ALWAYS_INLINE void next(unsigned lexerFlags = 0) 538 { 539 int lastLine = m_token.m_location.line; 540 int lastTokenEnd = m_token.m_location.endOffset; 541 int lastTokenLineStart = m_token.m_location.lineStartOffset; 542 m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart); 543 m_lexer->setLastLineNumber(lastLine); 544 m_token.m_type = m_lexer->lex(&m_token, lexerFlags, strictMode()); 545 } 546 547 ALWAYS_INLINE void nextExpectIdentifier(unsigned lexerFlags = 0) 548 { 549 int lastLine = m_token.m_location.line; 550 int lastTokenEnd = m_token.m_location.endOffset; 551 int lastTokenLineStart = m_token.m_location.lineStartOffset; 552 m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart); 553 m_lexer->setLastLineNumber(lastLine); 554 m_token.m_type = m_lexer->lexExpectIdentifier(&m_token, lexerFlags, strictMode()); 555 } 556 557 ALWAYS_INLINE bool nextTokenIsColon() 558 { 559 return m_lexer->nextTokenIsColon(); 560 } 561 562 ALWAYS_INLINE bool consume(JSTokenType expected, unsigned flags = 0) 563 { 564 bool result = m_token.m_type == expected; 565 if (result) 566 next(flags); 567 return result; 568 } 569 570 void printUnexpectedTokenText(WTF::PrintStream&); 571 ALWAYS_INLINE String getToken() { 572 SourceProvider* sourceProvider = m_source->provider(); 573 return sourceProvider->getRange(tokenStart(), tokenEndPosition().offset); 574 } 575 576 ALWAYS_INLINE bool match(JSTokenType expected) 577 { 578 return m_token.m_type == expected; 579 } 580 581 ALWAYS_INLINE bool isofToken() 582 { 583 return m_token.m_type == IDENT && *m_token.m_data.ident == m_vm->propertyNames->of; 584 } 585 586 ALWAYS_INLINE unsigned tokenStart() 587 { 588 return m_token.m_location.startOffset; 589 } 590 591 ALWAYS_INLINE const JSTextPosition& tokenStartPosition() 592 { 593 return m_token.m_startPosition; 594 } 595 596 ALWAYS_INLINE int tokenLine() 597 { 598 return m_token.m_location.line; 599 } 600 601 ALWAYS_INLINE int tokenColumn() 602 { 603 return tokenStart() - tokenLineStart(); 604 } 605 606 ALWAYS_INLINE const JSTextPosition& tokenEndPosition() 607 { 608 return m_token.m_endPosition; 609 } 610 611 ALWAYS_INLINE unsigned tokenLineStart() 612 { 613 return m_token.m_location.lineStartOffset; 614 } 615 616 ALWAYS_INLINE const JSTokenLocation& tokenLocation() 617 { 618 return m_token.m_location; 619 } 620 621 void setErrorMessage(String msg) 622 { 623 m_errorMessage = msg; 624 } 625 626 NEVER_INLINE void logError(bool); 627 template <typename A> NEVER_INLINE void logError(bool, const A&); 628 template <typename A, typename B> NEVER_INLINE void logError(bool, const A&, const B&); 629 template <typename A, typename B, typename C> NEVER_INLINE void logError(bool, const A&, const B&, const C&); 630 template <typename A, typename B, typename C, typename D> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&); 631 template <typename A, typename B, typename C, typename D, typename E> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&); 632 template <typename A, typename B, typename C, typename D, typename E, typename F> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&, const F&); 633 template <typename A, typename B, typename C, typename D, typename E, typename F, typename G> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&, const F&, const G&); 634 635 NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMsg, String name, const char* afterMsg) 636 { 637 m_errorMessage = makeString(beforeMsg, " '", name, "' ", afterMsg); 638 } 639 640 NEVER_INLINE void updateErrorMessage(const char* msg) 641 { 642 ASSERT(msg); 643 m_errorMessage = String(msg); 644 ASSERT(!m_errorMessage.isNull()); 645 } 646 647 void startLoop() { currentScope()->startLoop(); } 648 void endLoop() { currentScope()->endLoop(); } 649 void startSwitch() { currentScope()->startSwitch(); } 650 void endSwitch() { currentScope()->endSwitch(); } 651 void setStrictMode() { currentScope()->setStrictMode(); } 652 bool strictMode() { return currentScope()->strictMode(); } 653 bool isValidStrictMode() { return currentScope()->isValidStrictMode(); } 654 bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } 655 Scope::BindingResult declareBoundParameter(const Identifier* ident) { return currentScope()->declareBoundParameter(ident); } 656 bool breakIsValid() 657 { 658 ScopeRef current = currentScope(); 659 while (!current->breakIsValid()) { 660 if (!current.hasContainingScope()) 661 return false; 662 current = current.containingScope(); 663 } 664 return true; 665 } 666 bool continueIsValid() 667 { 668 ScopeRef current = currentScope(); 669 while (!current->continueIsValid()) { 670 if (!current.hasContainingScope()) 671 return false; 672 current = current.containingScope(); 673 } 674 return true; 675 } 676 void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); } 677 void popLabel() { currentScope()->popLabel(); } 678 ScopeLabelInfo* getLabel(const Identifier* label) 679 { 680 ScopeRef current = currentScope(); 681 ScopeLabelInfo* result = 0; 682 while (!(result = current->getLabel(label))) { 683 if (!current.hasContainingScope()) 684 return 0; 685 current = current.containingScope(); 686 } 687 return result; 688 } 689 690 template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode); 691 template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0); 692 template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&); 693 template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&); 694 template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&); 695 template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&); 696 template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&); 697 template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&); 698 template <class TreeBuilder> TreeStatement parseBreakStatement(TreeBuilder&); 699 template <class TreeBuilder> TreeStatement parseContinueStatement(TreeBuilder&); 700 template <class TreeBuilder> TreeStatement parseReturnStatement(TreeBuilder&); 701 template <class TreeBuilder> TreeStatement parseThrowStatement(TreeBuilder&); 702 template <class TreeBuilder> TreeStatement parseWithStatement(TreeBuilder&); 703 template <class TreeBuilder> TreeStatement parseSwitchStatement(TreeBuilder&); 704 template <class TreeBuilder> TreeClauseList parseSwitchClauses(TreeBuilder&); 705 template <class TreeBuilder> TreeClause parseSwitchDefaultClause(TreeBuilder&); 706 template <class TreeBuilder> TreeStatement parseTryStatement(TreeBuilder&); 707 template <class TreeBuilder> TreeStatement parseDebuggerStatement(TreeBuilder&); 708 template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&); 709 template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&); 710 template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&); 711 template <class TreeBuilder> TreeStatement parseBlockStatement(TreeBuilder&); 712 template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&); 713 template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&); 714 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&); 715 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseBinaryExpression(TreeBuilder&); 716 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseUnaryExpression(TreeBuilder&); 717 template <class TreeBuilder> TreeExpression parseMemberExpression(TreeBuilder&); 718 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&); 719 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&); 720 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&); 721 template <class TreeBuilder> NEVER_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&); 722 enum SpreadMode { AllowSpread, DontAllowSpread }; 723 template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&, SpreadMode); 724 template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict); 725 template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&); 726 template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&); 727 template <class TreeBuilder> TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd); 728 template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&); 729 730 template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern createBindingPattern(TreeBuilder&, DeconstructionKind, const Identifier&, int depth); 731 template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&, DeconstructionKind, int depth = 0); 732 template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&); 733 template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn); 734 ALWAYS_INLINE int isBinaryOperator(JSTokenType); 735 bool allowAutomaticSemicolon(); 736 737 bool autoSemiColon() 738 { 739 if (m_token.m_type == SEMICOLON) { 740 next(); 741 return true; 742 } 743 return allowAutomaticSemicolon(); 744 } 745 746 bool canRecurse() 747 { 748 return m_vm->isSafeToRecurse(); 749 } 750 751 const JSTextPosition& lastTokenEndPosition() const 752 { 753 return m_lastTokenEndPosition; 754 } 755 756 bool hasError() const 757 { 758 return !m_errorMessage.isNull(); 759 } 760 761 struct SavePoint { 762 int startOffset; 763 unsigned oldLineStartOffset; 764 unsigned oldLastLineNumber; 765 unsigned oldLineNumber; 766 }; 767 768 ALWAYS_INLINE SavePoint createSavePoint() 769 { 770 ASSERT(!hasError()); 771 SavePoint result; 772 result.startOffset = m_token.m_location.startOffset; 773 result.oldLineStartOffset = m_token.m_location.lineStartOffset; 774 result.oldLastLineNumber = m_lexer->lastLineNumber(); 775 result.oldLineNumber = m_lexer->lineNumber(); 776 return result; 777 } 778 779 ALWAYS_INLINE void restoreSavePoint(const SavePoint& savePoint) 780 { 781 m_errorMessage = String(); 782 m_lexer->setOffset(savePoint.startOffset, savePoint.oldLineStartOffset); 783 next(); 784 m_lexer->setLastLineNumber(savePoint.oldLastLineNumber); 785 m_lexer->setLineNumber(savePoint.oldLineNumber); 786 } 787 788 struct ParserState { 789 int assignmentCount; 790 int nonLHSCount; 791 int nonTrivialExpressionCount; 792 }; 793 794 ALWAYS_INLINE ParserState saveState() 795 { 796 ParserState result; 797 result.assignmentCount = m_assignmentCount; 798 result.nonLHSCount = m_nonLHSCount; 799 result.nonTrivialExpressionCount = m_nonTrivialExpressionCount; 800 return result; 801 } 802 803 ALWAYS_INLINE void restoreState(const ParserState& state) 804 { 805 m_assignmentCount = state.assignmentCount; 806 m_nonLHSCount = state.nonLHSCount; 807 m_nonTrivialExpressionCount = state.nonTrivialExpressionCount; 808 809 } 810 811 812 VM* m_vm; 813 const SourceCode* m_source; 814 ParserArena* m_arena; 815 OwnPtr<LexerType> m_lexer; 816 817 bool m_hasStackOverflow; 818 String m_errorMessage; 819 JSToken m_token; 820 bool m_allowsIn; 821 JSTextPosition m_lastTokenEndPosition; 822 int m_assignmentCount; 823 int m_nonLHSCount; 824 bool m_syntaxAlreadyValidated; 825 int m_statementDepth; 826 int m_nonTrivialExpressionCount; 827 const Identifier* m_lastIdentifier; 828 const Identifier* m_lastFunctionName; 829 RefPtr<SourceProviderCache> m_functionCache; 830 SourceElements* m_sourceElements; 831 bool m_parsingBuiltin; 832 ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; 833 ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; 834 IdentifierSet m_capturedVariables; 835 Vector<RefPtr<StringImpl>> m_closedVariables; 836 CodeFeatures m_features; 837 int m_numConstants; 838 839 struct DepthManager { 840 DepthManager(int* depth) 841 : m_originalDepth(*depth) 842 , m_depth(depth) 843 { 844 } 845 846 ~DepthManager() 847 { 848 *m_depth = m_originalDepth; 849 } 850 851 private: 852 int m_originalDepth; 853 int* m_depth; 854 }; 855}; 856 857 858template <typename LexerType> 859template <class ParsedNode> 860PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error, bool needReparsingAdjustment) 861{ 862 int errLine; 863 String errMsg; 864 865 if (ParsedNode::scopeIsFunction && needReparsingAdjustment) 866 m_lexer->setIsReparsing(); 867 868 m_sourceElements = 0; 869 870 errLine = -1; 871 errMsg = String(); 872 873 JSTokenLocation startLocation(tokenLocation()); 874 ASSERT(m_source->startColumn() > 0); 875 unsigned startColumn = m_source->startColumn() - 1; 876 877 String parseError = parseInner(); 878 879 int lineNumber = m_lexer->lineNumber(); 880 bool lexError = m_lexer->sawError(); 881 String lexErrorMessage = lexError ? m_lexer->getErrorMessage() : String(); 882 ASSERT(lexErrorMessage.isNull() != lexError); 883 m_lexer->clear(); 884 885 if (!parseError.isNull() || lexError) { 886 errLine = lineNumber; 887 errMsg = !lexErrorMessage.isNull() ? lexErrorMessage : parseError; 888 m_sourceElements = 0; 889 } 890 891 RefPtr<ParsedNode> result; 892 if (m_sourceElements) { 893 JSTokenLocation endLocation; 894 endLocation.line = m_lexer->lineNumber(); 895 endLocation.lineStartOffset = m_lexer->currentLineStartOffset(); 896 endLocation.startOffset = m_lexer->currentOffset(); 897 unsigned endColumn = endLocation.startOffset - endLocation.lineStartOffset; 898 result = ParsedNode::create(m_vm, 899 startLocation, 900 endLocation, 901 startColumn, 902 endColumn, 903 m_sourceElements, 904 m_varDeclarations ? &m_varDeclarations->data : 0, 905 m_funcDeclarations ? &m_funcDeclarations->data : 0, 906 m_capturedVariables, 907 *m_source, 908 m_features, 909 m_numConstants); 910 result->setLoc(m_source->firstLine(), m_lexer->lineNumber(), m_lexer->currentOffset(), m_lexer->currentLineStartOffset()); 911 } else { 912 // We can never see a syntax error when reparsing a function, since we should have 913 // reported the error when parsing the containing program or eval code. So if we're 914 // parsing a function body node, we assume that what actually happened here is that 915 // we ran out of stack while parsing. If we see an error while parsing eval or program 916 // code we assume that it was a syntax error since running out of stack is much less 917 // likely, and we are currently unable to distinguish between the two cases. 918 if (isFunctionBodyNode(static_cast<ParsedNode*>(0)) || m_hasStackOverflow) 919 error = ParserError(ParserError::StackOverflow, ParserError::SyntaxErrorNone, m_token); 920 else { 921 ParserError::SyntaxErrorType errorType = ParserError::SyntaxErrorIrrecoverable; 922 if (m_token.m_type == EOFTOK) 923 errorType = ParserError::SyntaxErrorRecoverable; 924 else if (m_token.m_type & UnterminatedErrorTokenFlag) 925 errorType = ParserError::SyntaxErrorUnterminatedLiteral; 926 927 if (isEvalNode<ParsedNode>()) 928 error = ParserError(ParserError::EvalError, errorType, m_token, errMsg, errLine); 929 else 930 error = ParserError(ParserError::SyntaxError, errorType, m_token, errMsg, errLine); 931 } 932 } 933 934 m_arena->reset(); 935 936 return result.release(); 937} 938 939template <class ParsedNode> 940PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0, bool needReparsingAdjustment = false) 941{ 942 SamplingRegion samplingRegion("Parsing"); 943 944 ASSERT(!source.provider()->source().isNull()); 945 if (source.provider()->source().is8Bit()) { 946 Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode); 947 RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error, needReparsingAdjustment); 948 if (positionBeforeLastNewline) 949 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); 950 if (strictness == JSParseBuiltin) { 951 if (!result) 952 WTF::dataLog("Error compiling builtin: ", error.m_message, "\n"); 953 RELEASE_ASSERT(result); 954 result->setClosedVariables(parser.closedVariables()); 955 } 956 return result.release(); 957 } 958 Parser<Lexer<UChar>> parser(vm, source, parameters, name, strictness, parserMode); 959 RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error, needReparsingAdjustment); 960 if (positionBeforeLastNewline) 961 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); 962 return result.release(); 963} 964 965} // namespace 966#endif 967