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.
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.
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.
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.
27 #include "ExceptionHelpers.h"
28 #include "Executable.h"
29 #include "JSGlobalObject.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>
47 template <> struct VectorTraits
<JSC::Scope
> : SimpleClassVectorTraits
{
48 static const bool canInitializeWithMemset
= false; // Not all Scope data members initialize to 0.
55 class FunctionBodyNode
;
56 class FunctionParameters
;
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
77 COMPILE_ASSERT(LastUntaggedToken
< 64, LessThan64UntaggedTokens
);
79 enum SourceElementsMode
{ CheckForStrictMode
, DontCheckForStrictMode
};
80 enum FunctionRequirements
{ FunctionNoRequirements
, FunctionNeedsName
};
81 enum FunctionParseMode
{ FunctionMode
, GetterMode
, SetterMode
};
82 enum DeconstructionKind
{
83 DeconstructToVariables
,
84 DeconstructToParameters
,
85 DeconstructToExpressions
88 template <typename T
> inline bool isEvalNode() { return false; }
89 template <> inline bool isEvalNode
<EvalNode
>() { return true; }
91 struct ScopeLabelInfo
{
92 ScopeLabelInfo(StringImpl
* ident
, bool isLoop
)
103 Scope(const VM
* vm
, bool isFunction
, bool strictMode
)
105 , m_shadowsArguments(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)
118 Scope(const Scope
& rhs
)
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
)
132 m_labels
= adoptPtr(new LabelStack
);
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
));
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
; }
149 void pushLabel(const Identifier
* label
, bool isLoop
)
152 m_labels
= adoptPtr(new LabelStack
);
153 m_labels
->append(ScopeLabelInfo(label
->impl(), isLoop
));
159 ASSERT(m_labels
->size());
160 m_labels
->removeLast();
163 ScopeLabelInfo
* getLabel(const Identifier
* label
)
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);
177 m_isFunctionBoundary
= true;
179 bool isFunction() { return m_isFunction
; }
180 bool isFunctionBoundary() { return m_isFunctionBoundary
; }
182 void declareCallee(const Identifier
* ident
)
184 m_declaredVariables
.add(ident
->string().impl());
187 bool declareVariable(const Identifier
* ident
)
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
;
195 bool hasDeclaredVariable(const Identifier
& ident
)
197 return m_declaredVariables
.contains(ident
.impl());
200 bool hasDeclaredParameter(const Identifier
& ident
)
202 return m_declaredParameters
.contains(ident
.impl()) || m_declaredVariables
.contains(ident
.impl());
205 void declareWrite(const Identifier
* ident
)
207 ASSERT(m_strictMode
);
208 m_writtenVariables
.add(ident
->impl());
211 void preventNewDecls() { m_allowsNewDecls
= false; }
212 bool allowsNewDecls() const { return m_allowsNewDecls
; }
214 bool declareParameter(const Identifier
* ident
)
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());
222 m_shadowsArguments
= true;
223 return isValidStrictMode
;
231 BindingResult
declareBoundParameter(const Identifier
* ident
)
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
;
239 m_shadowsArguments
= true;
241 return BindingFailed
;
242 return isValidStrictMode
? BindingSucceeded
: StrictBindingFailed
;
245 void getUsedVariables(IdentifierSet
& usedVariables
)
247 usedVariables
.swap(m_usedVariables
);
250 void useVariable(const Identifier
* ident
, bool isEval
)
252 m_usesEval
|= isEval
;
253 m_usedVariables
.add(ident
->string().impl());
256 void setNeedsFullActivation() { m_needsFullActivation
= true; }
258 bool collectFreeVariables(Scope
* nestedScope
, bool shouldTrackClosedVariables
)
260 if (nestedScope
->m_usesEval
)
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
))
266 m_usedVariables
.add(*ptr
);
267 if (shouldTrackClosedVariables
)
268 m_closedVariables
.add(*ptr
);
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
))
275 m_writtenVariables
.add(*ptr
);
282 void getCapturedVariables(IdentifierSet
& capturedVariables
, bool& modifiedParameter
)
284 if (m_needsFullActivation
|| m_usesEval
) {
285 modifiedParameter
= true;
286 capturedVariables
.swap(m_declaredVariables
);
289 for (IdentifierSet::iterator ptr
= m_closedVariables
.begin(); ptr
!= m_closedVariables
.end(); ++ptr
) {
290 if (!m_declaredVariables
.contains(*ptr
))
292 capturedVariables
.add(*ptr
);
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
))
300 modifiedParameter
= true;
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
; }
310 void copyCapturedVariablesToVector(const IdentifierSet
& capturedVariables
, Vector
<RefPtr
<StringImpl
>>& vector
)
312 IdentifierSet::iterator end
= capturedVariables
.end();
313 for (IdentifierSet::iterator it
= capturedVariables
.begin(); it
!= end
; ++it
) {
314 if (m_declaredVariables
.contains(*it
))
320 void fillParametersForSourceProviderCache(SourceProviderCacheItemCreationParameters
& parameters
)
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
);
330 void restoreFromSourceProviderCache(const SourceProviderCacheItem
* info
)
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
]);
344 bool m_shadowsArguments
: 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;
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
;
364 typedef Vector
<Scope
, 10> ScopeStack
;
367 ScopeRef(ScopeStack
* scopeStack
, unsigned index
)
368 : m_scopeStack(scopeStack
)
372 Scope
* operator->() { return &m_scopeStack
->at(m_index
); }
373 unsigned index() const { return m_index
; }
375 bool hasContainingScope()
377 return m_index
&& !m_scopeStack
->at(m_index
).isFunctionBoundary();
380 ScopeRef
containingScope()
382 ASSERT(hasContainingScope());
383 return ScopeRef(m_scopeStack
, m_index
- 1);
387 ScopeStack
* m_scopeStack
;
391 template <typename LexerType
>
393 WTF_MAKE_NONCOPYABLE(Parser
);
394 WTF_MAKE_FAST_ALLOCATED
;
397 Parser(VM
*, const SourceCode
&, FunctionParameters
*, const Identifier
&, JSParserStrictness
, JSParserMode
);
400 template <class ParsedNode
>
401 PassRefPtr
<ParsedNode
> parse(ParserError
&, bool needReparsingAdjustment
);
403 JSTextPosition
positionBeforeLastNewline() const { return m_lexer
->positionBeforeLastNewline(); }
404 Vector
<RefPtr
<StringImpl
>>&& closedVariables() { return WTF::move(m_closedVariables
); }
407 struct AllowInOverride
{
408 AllowInOverride(Parser
* parser
)
410 , m_oldAllowsIn(parser
->m_allowsIn
)
412 parser
->m_allowsIn
= true;
416 m_parser
->m_allowsIn
= m_oldAllowsIn
;
422 struct AutoPopScopeRef
: public ScopeRef
{
423 AutoPopScopeRef(Parser
* parser
, ScopeRef scope
)
432 m_parser
->popScope(*this, false);
444 ScopeRef
currentScope()
446 return ScopeRef(&m_scopeStack
, m_scopeStack
.size() - 1);
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();
457 m_scopeStack
.append(Scope(m_vm
, isFunction
, isStrict
));
458 return currentScope();
461 bool popScopeInternal(ScopeRef
& scope
, bool shouldTrackClosedVariables
)
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();
470 bool popScope(ScopeRef
& scope
, bool shouldTrackClosedVariables
)
472 return popScopeInternal(scope
, shouldTrackClosedVariables
);
475 bool popScope(AutoPopScopeRef
& scope
, bool shouldTrackClosedVariables
)
478 return popScopeInternal(scope
, shouldTrackClosedVariables
);
481 bool declareVariable(const Identifier
* ident
)
483 unsigned i
= m_scopeStack
.size() - 1;
484 ASSERT(i
< m_scopeStack
.size());
485 while (!m_scopeStack
[i
].allowsNewDecls()) {
487 ASSERT(i
< m_scopeStack
.size());
489 return m_scopeStack
[i
].declareVariable(ident
);
492 NEVER_INLINE
bool hasDeclaredVariable(const Identifier
& ident
)
494 unsigned i
= m_scopeStack
.size() - 1;
495 ASSERT(i
< m_scopeStack
.size());
496 while (!m_scopeStack
[i
].allowsNewDecls()) {
498 ASSERT(i
< m_scopeStack
.size());
500 return m_scopeStack
[i
].hasDeclaredVariable(ident
);
503 NEVER_INLINE
bool hasDeclaredParameter(const Identifier
& ident
)
505 unsigned i
= m_scopeStack
.size() - 1;
506 ASSERT(i
< m_scopeStack
.size());
507 while (!m_scopeStack
[i
].allowsNewDecls()) {
509 ASSERT(i
< m_scopeStack
.size());
511 return m_scopeStack
[i
].hasDeclaredParameter(ident
);
514 void declareWrite(const Identifier
* ident
)
516 if (!m_syntaxAlreadyValidated
|| strictMode())
517 m_scopeStack
.last().declareWrite(ident
);
520 ScopeStack m_scopeStack
;
522 const SourceProviderCacheItem
* findCachedFunctionInfo(int openBracePos
)
524 return m_functionCache
? m_functionCache
->get(openBracePos
) : 0;
530 void didFinishParsing(SourceElements
*, ParserArenaData
<DeclarationStacks::VarStack
>*,
531 ParserArenaData
<DeclarationStacks::FunctionStack
>*, CodeFeatures
, int, IdentifierSet
&, const Vector
<RefPtr
<StringImpl
>>&&);
533 // Used to determine type of error to report.
534 bool isFunctionBodyNode(ScopeNode
*) { return false; }
535 bool isFunctionBodyNode(FunctionBodyNode
*) { return true; }
537 ALWAYS_INLINE
void next(unsigned lexerFlags
= 0)
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());
547 ALWAYS_INLINE
void nextExpectIdentifier(unsigned lexerFlags
= 0)
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());
557 ALWAYS_INLINE
bool nextTokenIsColon()
559 return m_lexer
->nextTokenIsColon();
562 ALWAYS_INLINE
bool consume(JSTokenType expected
, unsigned flags
= 0)
564 bool result
= m_token
.m_type
== expected
;
570 void printUnexpectedTokenText(WTF::PrintStream
&);
571 ALWAYS_INLINE String
getToken() {
572 SourceProvider
* sourceProvider
= m_source
->provider();
573 return sourceProvider
->getRange(tokenStart(), tokenEndPosition().offset
);
576 ALWAYS_INLINE
bool match(JSTokenType expected
)
578 return m_token
.m_type
== expected
;
581 ALWAYS_INLINE
bool isofToken()
583 return m_token
.m_type
== IDENT
&& *m_token
.m_data
.ident
== m_vm
->propertyNames
->of
;
586 ALWAYS_INLINE
unsigned tokenStart()
588 return m_token
.m_location
.startOffset
;
591 ALWAYS_INLINE
const JSTextPosition
& tokenStartPosition()
593 return m_token
.m_startPosition
;
596 ALWAYS_INLINE
int tokenLine()
598 return m_token
.m_location
.line
;
601 ALWAYS_INLINE
int tokenColumn()
603 return tokenStart() - tokenLineStart();
606 ALWAYS_INLINE
const JSTextPosition
& tokenEndPosition()
608 return m_token
.m_endPosition
;
611 ALWAYS_INLINE
unsigned tokenLineStart()
613 return m_token
.m_location
.lineStartOffset
;
616 ALWAYS_INLINE
const JSTokenLocation
& tokenLocation()
618 return m_token
.m_location
;
621 void setErrorMessage(String msg
)
623 m_errorMessage
= msg
;
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
&);
635 NEVER_INLINE
void updateErrorWithNameAndMessage(const char* beforeMsg
, String name
, const char* afterMsg
)
637 m_errorMessage
= makeString(beforeMsg
, " '", name
, "' ", afterMsg
);
640 NEVER_INLINE
void updateErrorMessage(const char* msg
)
643 m_errorMessage
= String(msg
);
644 ASSERT(!m_errorMessage
.isNull());
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
); }
658 ScopeRef current
= currentScope();
659 while (!current
->breakIsValid()) {
660 if (!current
.hasContainingScope())
662 current
= current
.containingScope();
666 bool continueIsValid()
668 ScopeRef current
= currentScope();
669 while (!current
->continueIsValid()) {
670 if (!current
.hasContainingScope())
672 current
= current
.containingScope();
676 void pushLabel(const Identifier
* label
, bool isLoop
) { currentScope()->pushLabel(label
, isLoop
); }
677 void popLabel() { currentScope()->popLabel(); }
678 ScopeLabelInfo
* getLabel(const Identifier
* label
)
680 ScopeRef current
= currentScope();
681 ScopeLabelInfo
* result
= 0;
682 while (!(result
= current
->getLabel(label
))) {
683 if (!current
.hasContainingScope())
685 current
= current
.containingScope();
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
&);
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();
739 if (m_token
.m_type
== SEMICOLON
) {
743 return allowAutomaticSemicolon();
748 return m_vm
->isSafeToRecurse();
751 const JSTextPosition
& lastTokenEndPosition() const
753 return m_lastTokenEndPosition
;
756 bool hasError() const
758 return !m_errorMessage
.isNull();
763 unsigned oldLineStartOffset
;
764 unsigned oldLastLineNumber
;
765 unsigned oldLineNumber
;
768 ALWAYS_INLINE SavePoint
createSavePoint()
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();
779 ALWAYS_INLINE
void restoreSavePoint(const SavePoint
& savePoint
)
781 m_errorMessage
= String();
782 m_lexer
->setOffset(savePoint
.startOffset
, savePoint
.oldLineStartOffset
);
784 m_lexer
->setLastLineNumber(savePoint
.oldLastLineNumber
);
785 m_lexer
->setLineNumber(savePoint
.oldLineNumber
);
791 int nonTrivialExpressionCount
;
794 ALWAYS_INLINE ParserState
saveState()
797 result
.assignmentCount
= m_assignmentCount
;
798 result
.nonLHSCount
= m_nonLHSCount
;
799 result
.nonTrivialExpressionCount
= m_nonTrivialExpressionCount
;
803 ALWAYS_INLINE
void restoreState(const ParserState
& state
)
805 m_assignmentCount
= state
.assignmentCount
;
806 m_nonLHSCount
= state
.nonLHSCount
;
807 m_nonTrivialExpressionCount
= state
.nonTrivialExpressionCount
;
813 const SourceCode
* m_source
;
814 ParserArena
* m_arena
;
815 OwnPtr
<LexerType
> m_lexer
;
817 bool m_hasStackOverflow
;
818 String m_errorMessage
;
821 JSTextPosition m_lastTokenEndPosition
;
822 int m_assignmentCount
;
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
;
839 struct DepthManager
{
840 DepthManager(int* depth
)
841 : m_originalDepth(*depth
)
848 *m_depth
= m_originalDepth
;
858 template <typename LexerType
>
859 template <class ParsedNode
>
860 PassRefPtr
<ParsedNode
> Parser
<LexerType
>::parse(ParserError
& error
, bool needReparsingAdjustment
)
865 if (ParsedNode::scopeIsFunction
&& needReparsingAdjustment
)
866 m_lexer
->setIsReparsing();
868 m_sourceElements
= 0;
873 JSTokenLocation
startLocation(tokenLocation());
874 ASSERT(m_source
->startColumn() > 0);
875 unsigned startColumn
= m_source
->startColumn() - 1;
877 String parseError
= parseInner();
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
);
885 if (!parseError
.isNull() || lexError
) {
886 errLine
= lineNumber
;
887 errMsg
= !lexErrorMessage
.isNull() ? lexErrorMessage
: parseError
;
888 m_sourceElements
= 0;
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
,
904 m_varDeclarations
? &m_varDeclarations
->data
: 0,
905 m_funcDeclarations
? &m_funcDeclarations
->data
: 0,
910 result
->setLoc(m_source
->firstLine(), m_lexer
->lineNumber(), m_lexer
->currentOffset(), m_lexer
->currentLineStartOffset());
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
);
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
;
927 if (isEvalNode
<ParsedNode
>())
928 error
= ParserError(ParserError::EvalError
, errorType
, m_token
, errMsg
, errLine
);
930 error
= ParserError(ParserError::SyntaxError
, errorType
, m_token
, errMsg
, errLine
);
936 return result
.release();
939 template <class ParsedNode
>
940 PassRefPtr
<ParsedNode
> parse(VM
* vm
, const SourceCode
& source
, FunctionParameters
* parameters
, const Identifier
& name
, JSParserStrictness strictness
, JSParserMode parserMode
, ParserError
& error
, JSTextPosition
* positionBeforeLastNewline
= 0, bool needReparsingAdjustment
= false)
942 SamplingRegion
samplingRegion("Parsing");
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
) {
952 WTF::dataLog("Error compiling builtin: ", error
.m_message
, "\n");
953 RELEASE_ASSERT(result
);
954 result
->setClosedVariables(parser
.closedVariables());
956 return result
.release();
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();