• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 
28 #include "JSParser.h"
29 
30 using namespace JSC;
31 
32 #include "CodeBlock.h"
33 #include "JSGlobalData.h"
34 #include "NodeInfo.h"
35 #include "ASTBuilder.h"
36 #include "SourceProvider.h"
37 #include "SourceProviderCacheItem.h"
38 #include <wtf/HashFunctions.h>
39 #include <wtf/OwnPtr.h>
40 #include <wtf/WTFThreadData.h>
41 #include <utility>
42 
43 using namespace std;
44 
45 namespace JSC {
46 #define fail() do { m_error = true; return 0; } while (0)
47 #define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
48 #define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
49 #define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0)
50 #define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0)
51 #define consumeOrFail(tokenType) do { if (!consume(tokenType)) fail(); } while (0)
52 #define matchOrFail(tokenType) do { if (!match(tokenType)) fail(); } while (0)
53 #define failIfStackOverflow() do { failIfFalse(canRecurse()); } while (0)
54 
55 // Macros to make the more common TreeBuilder types a little less verbose
56 #define TreeStatement typename TreeBuilder::Statement
57 #define TreeExpression typename TreeBuilder::Expression
58 #define TreeFormalParameterList typename TreeBuilder::FormalParameterList
59 #define TreeSourceElements typename TreeBuilder::SourceElements
60 #define TreeClause typename TreeBuilder::Clause
61 #define TreeClauseList typename TreeBuilder::ClauseList
62 #define TreeConstDeclList typename TreeBuilder::ConstDeclList
63 #define TreeArguments typename TreeBuilder::Arguments
64 #define TreeArgumentsList typename TreeBuilder::ArgumentsList
65 #define TreeFunctionBody typename TreeBuilder::FunctionBody
66 #define TreeProperty typename TreeBuilder::Property
67 #define TreePropertyList typename TreeBuilder::PropertyList
68 
69 COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
70 
71 class JSParser {
72 public:
73     JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, SourceProvider*);
74     const char* parseProgram();
75 private:
76     struct AllowInOverride {
AllowInOverrideJSC::JSParser::AllowInOverride77         AllowInOverride(JSParser* parser)
78             : m_parser(parser)
79             , m_oldAllowsIn(parser->m_allowsIn)
80         {
81             parser->m_allowsIn = true;
82         }
~AllowInOverrideJSC::JSParser::AllowInOverride83         ~AllowInOverride()
84         {
85             m_parser->m_allowsIn = m_oldAllowsIn;
86         }
87         JSParser* m_parser;
88         bool m_oldAllowsIn;
89     };
90 
91     struct ScopeLabelInfo {
ScopeLabelInfoJSC::JSParser::ScopeLabelInfo92         ScopeLabelInfo(StringImpl* ident, bool isLoop)
93         : m_ident(ident)
94         , m_isLoop(isLoop)
95         {
96         }
97         StringImpl* m_ident;
98         bool m_isLoop;
99     };
100 
next(Lexer::LexType lexType=Lexer::IdentifyReservedWords)101     void next(Lexer::LexType lexType = Lexer::IdentifyReservedWords)
102     {
103         m_lastLine = m_token.m_info.line;
104         m_lastTokenEnd = m_token.m_info.endOffset;
105         m_lexer->setLastLineNumber(m_lastLine);
106         m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexType, strictMode());
107     }
108 
nextTokenIsColon()109     bool nextTokenIsColon()
110     {
111         return m_lexer->nextTokenIsColon();
112     }
113 
consume(JSTokenType expected)114     bool consume(JSTokenType expected)
115     {
116         bool result = m_token.m_type == expected;
117         failIfFalse(result);
118         next();
119         return result;
120     }
121 
match(JSTokenType expected)122     bool match(JSTokenType expected)
123     {
124         return m_token.m_type == expected;
125     }
126 
tokenStart()127     int tokenStart()
128     {
129         return m_token.m_info.startOffset;
130     }
131 
tokenLine()132     int tokenLine()
133     {
134         return m_token.m_info.line;
135     }
136 
tokenEnd()137     int tokenEnd()
138     {
139         return m_token.m_info.endOffset;
140     }
141 
startLoop()142     void startLoop() { currentScope()->startLoop(); }
endLoop()143     void endLoop() { currentScope()->endLoop(); }
startSwitch()144     void startSwitch() { currentScope()->startSwitch(); }
endSwitch()145     void endSwitch() { currentScope()->endSwitch(); }
setStrictMode()146     void setStrictMode() { currentScope()->setStrictMode(); }
strictMode()147     bool strictMode() { return currentScope()->strictMode(); }
isValidStrictMode()148     bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
declareParameter(const Identifier * ident)149     bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
breakIsValid()150     bool breakIsValid()
151     {
152         ScopeRef current = currentScope();
153         while (!current->breakIsValid()) {
154             if (!current.hasContainingScope())
155                 return false;
156             current = current.containingScope();
157         }
158         return true;
159     }
continueIsValid()160     bool continueIsValid()
161     {
162         ScopeRef current = currentScope();
163         while (!current->continueIsValid()) {
164             if (!current.hasContainingScope())
165                 return false;
166             current = current.containingScope();
167         }
168         return true;
169     }
pushLabel(const Identifier * label,bool isLoop)170     void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); }
popLabel()171     void popLabel() { currentScope()->popLabel(); }
getLabel(const Identifier * label)172     ScopeLabelInfo* getLabel(const Identifier* label)
173     {
174         ScopeRef current = currentScope();
175         ScopeLabelInfo* result = 0;
176         while (!(result = current->getLabel(label))) {
177             if (!current.hasContainingScope())
178                 return 0;
179             current = current.containingScope();
180         }
181         return result;
182     }
183 
184     enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
185     template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
186     template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive);
187     template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&);
188     template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&);
189     template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&);
190     template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
191     template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&);
192     template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&);
193     template <class TreeBuilder> TreeStatement parseBreakStatement(TreeBuilder&);
194     template <class TreeBuilder> TreeStatement parseContinueStatement(TreeBuilder&);
195     template <class TreeBuilder> TreeStatement parseReturnStatement(TreeBuilder&);
196     template <class TreeBuilder> TreeStatement parseThrowStatement(TreeBuilder&);
197     template <class TreeBuilder> TreeStatement parseWithStatement(TreeBuilder&);
198     template <class TreeBuilder> TreeStatement parseSwitchStatement(TreeBuilder&);
199     template <class TreeBuilder> TreeClauseList parseSwitchClauses(TreeBuilder&);
200     template <class TreeBuilder> TreeClause parseSwitchDefaultClause(TreeBuilder&);
201     template <class TreeBuilder> TreeStatement parseTryStatement(TreeBuilder&);
202     template <class TreeBuilder> TreeStatement parseDebuggerStatement(TreeBuilder&);
203     template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&);
204     template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&);
205     template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&);
206     template <class TreeBuilder> ALWAYS_INLINE TreeStatement parseBlockStatement(TreeBuilder&);
207     template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&);
208     template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&);
209     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&);
210     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseBinaryExpression(TreeBuilder&);
211     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseUnaryExpression(TreeBuilder&);
212     template <class TreeBuilder> TreeExpression parseMemberExpression(TreeBuilder&);
213     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&);
214     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
215     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
216     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
217     template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
218     template <bool strict, class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&);
219     template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
220     template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
221     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd);
222     template <class TreeBuilder> ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context);
223     enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
224     template <FunctionRequirements, bool nameIsInContainingScope, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine);
225     ALWAYS_INLINE int isBinaryOperator(JSTokenType token);
226     bool allowAutomaticSemicolon();
227 
autoSemiColon()228     bool autoSemiColon()
229     {
230         if (m_token.m_type == SEMICOLON) {
231             next();
232             return true;
233         }
234         return allowAutomaticSemicolon();
235     }
236 
canRecurse()237     bool canRecurse()
238     {
239         return m_stack.recursionCheck();
240     }
241 
lastTokenEnd() const242     int lastTokenEnd() const
243     {
244         return m_lastTokenEnd;
245     }
246 
247     ParserArena m_arena;
248     Lexer* m_lexer;
249     StackBounds m_stack;
250     bool m_error;
251     const char* m_errorMessage;
252     JSGlobalData* m_globalData;
253     JSToken m_token;
254     bool m_allowsIn;
255     int m_lastLine;
256     int m_lastTokenEnd;
257     int m_assignmentCount;
258     int m_nonLHSCount;
259     bool m_syntaxAlreadyValidated;
260     int m_statementDepth;
261     int m_nonTrivialExpressionCount;
262     const Identifier* m_lastIdentifier;
263 
264     struct DepthManager {
DepthManagerJSC::JSParser::DepthManager265         DepthManager(int* depth)
266             : m_originalDepth(*depth)
267             , m_depth(depth)
268         {
269         }
270 
~DepthManagerJSC::JSParser::DepthManager271         ~DepthManager()
272         {
273             *m_depth = m_originalDepth;
274         }
275 
276     private:
277         int m_originalDepth;
278         int* m_depth;
279     };
280 
281     struct Scope {
ScopeJSC::JSParser::Scope282         Scope(JSGlobalData* globalData, bool isFunction, bool strictMode)
283             : m_globalData(globalData)
284             , m_shadowsArguments(false)
285             , m_usesEval(false)
286             , m_needsFullActivation(false)
287             , m_allowsNewDecls(true)
288             , m_strictMode(strictMode)
289             , m_isFunction(isFunction)
290             , m_isFunctionBoundary(false)
291             , m_isValidStrictMode(true)
292             , m_loopDepth(0)
293             , m_switchDepth(0)
294             , m_labels(0)
295         {
296         }
297 
ScopeJSC::JSParser::Scope298         Scope(const Scope& rhs)
299             : m_globalData(rhs.m_globalData)
300             , m_shadowsArguments(rhs.m_shadowsArguments)
301             , m_usesEval(rhs.m_usesEval)
302             , m_needsFullActivation(rhs.m_needsFullActivation)
303             , m_allowsNewDecls(rhs.m_allowsNewDecls)
304             , m_strictMode(rhs.m_strictMode)
305             , m_isFunction(rhs.m_isFunction)
306             , m_isFunctionBoundary(rhs.m_isFunctionBoundary)
307             , m_isValidStrictMode(rhs.m_isValidStrictMode)
308             , m_loopDepth(rhs.m_loopDepth)
309             , m_switchDepth(rhs.m_switchDepth)
310             , m_labels(0)
311         {
312             if (rhs.m_labels) {
313                 m_labels = adoptPtr(new LabelStack);
314 
315                 typedef LabelStack::const_iterator iterator;
316                 iterator end = rhs.m_labels->end();
317                 for (iterator it = rhs.m_labels->begin(); it != end; ++it)
318                     m_labels->append(ScopeLabelInfo(it->m_ident, it->m_isLoop));
319             }
320         }
321 
startSwitchJSC::JSParser::Scope322         void startSwitch() { m_switchDepth++; }
endSwitchJSC::JSParser::Scope323         void endSwitch() { m_switchDepth--; }
startLoopJSC::JSParser::Scope324         void startLoop() { m_loopDepth++; }
endLoopJSC::JSParser::Scope325         void endLoop() { ASSERT(m_loopDepth); m_loopDepth--; }
inLoopJSC::JSParser::Scope326         bool inLoop() { return !!m_loopDepth; }
breakIsValidJSC::JSParser::Scope327         bool breakIsValid() { return m_loopDepth || m_switchDepth; }
continueIsValidJSC::JSParser::Scope328         bool continueIsValid() { return m_loopDepth; }
329 
pushLabelJSC::JSParser::Scope330         void pushLabel(const Identifier* label, bool isLoop)
331         {
332             if (!m_labels)
333                 m_labels = adoptPtr(new LabelStack);
334             m_labels->append(ScopeLabelInfo(label->impl(), isLoop));
335         }
336 
popLabelJSC::JSParser::Scope337         void popLabel()
338         {
339             ASSERT(m_labels);
340             ASSERT(m_labels->size());
341             m_labels->removeLast();
342         }
343 
getLabelJSC::JSParser::Scope344         ScopeLabelInfo* getLabel(const Identifier* label)
345         {
346             if (!m_labels)
347                 return 0;
348             for (int i = m_labels->size(); i > 0; i--) {
349                 if (m_labels->at(i - 1).m_ident == label->impl())
350                     return &m_labels->at(i - 1);
351             }
352             return 0;
353         }
354 
setIsFunctionJSC::JSParser::Scope355         void setIsFunction()
356         {
357             m_isFunction = true;
358             m_isFunctionBoundary = true;
359         }
isFunctionJSC::JSParser::Scope360         bool isFunction() { return m_isFunction; }
isFunctionBoundaryJSC::JSParser::Scope361         bool isFunctionBoundary() { return m_isFunctionBoundary; }
362 
declareVariableJSC::JSParser::Scope363         bool declareVariable(const Identifier* ident)
364         {
365             bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident;
366             m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
367             m_declaredVariables.add(ident->ustring().impl());
368             return isValidStrictMode;
369         }
370 
declareWriteJSC::JSParser::Scope371         void declareWrite(const Identifier* ident)
372         {
373             ASSERT(m_strictMode);
374             m_writtenVariables.add(ident->impl());
375         }
376 
preventNewDeclsJSC::JSParser::Scope377         void preventNewDecls() { m_allowsNewDecls = false; }
allowsNewDeclsJSC::JSParser::Scope378         bool allowsNewDecls() const { return m_allowsNewDecls; }
379 
declareParameterJSC::JSParser::Scope380         bool declareParameter(const Identifier* ident)
381         {
382             bool isArguments = m_globalData->propertyNames->arguments == *ident;
383             bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).second && m_globalData->propertyNames->eval != *ident && !isArguments;
384             m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
385             if (isArguments)
386                 m_shadowsArguments = true;
387             return isValidStrictMode;
388         }
389 
useVariableJSC::JSParser::Scope390         void useVariable(const Identifier* ident, bool isEval)
391         {
392             m_usesEval |= isEval;
393             m_usedVariables.add(ident->ustring().impl());
394         }
395 
setNeedsFullActivationJSC::JSParser::Scope396         void setNeedsFullActivation() { m_needsFullActivation = true; }
397 
collectFreeVariablesJSC::JSParser::Scope398         bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
399         {
400             if (nestedScope->m_usesEval)
401                 m_usesEval = true;
402             IdentifierSet::iterator end = nestedScope->m_usedVariables.end();
403             for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) {
404                 if (nestedScope->m_declaredVariables.contains(*ptr))
405                     continue;
406                 m_usedVariables.add(*ptr);
407                 if (shouldTrackClosedVariables)
408                     m_closedVariables.add(*ptr);
409             }
410             if (nestedScope->m_writtenVariables.size()) {
411                 IdentifierSet::iterator end = nestedScope->m_writtenVariables.end();
412                 for (IdentifierSet::iterator ptr = nestedScope->m_writtenVariables.begin(); ptr != end; ++ptr) {
413                     if (nestedScope->m_declaredVariables.contains(*ptr))
414                         continue;
415                     m_writtenVariables.add(*ptr);
416                 }
417             }
418 
419             return true;
420         }
421 
getUncapturedWrittenVariablesJSC::JSParser::Scope422         void getUncapturedWrittenVariables(IdentifierSet& writtenVariables)
423         {
424             IdentifierSet::iterator end = m_writtenVariables.end();
425             for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) {
426                 if (!m_declaredVariables.contains(*ptr))
427                     writtenVariables.add(*ptr);
428             }
429         }
430 
getCapturedVariablesJSC::JSParser::Scope431         void getCapturedVariables(IdentifierSet& capturedVariables)
432         {
433             if (m_needsFullActivation || m_usesEval) {
434                 capturedVariables.swap(m_declaredVariables);
435                 return;
436             }
437             for (IdentifierSet::iterator ptr = m_closedVariables.begin(); ptr != m_closedVariables.end(); ++ptr) {
438                 if (!m_declaredVariables.contains(*ptr))
439                     continue;
440                 capturedVariables.add(*ptr);
441             }
442         }
setStrictModeJSC::JSParser::Scope443         void setStrictMode() { m_strictMode = true; }
strictModeJSC::JSParser::Scope444         bool strictMode() const { return m_strictMode; }
isValidStrictModeJSC::JSParser::Scope445         bool isValidStrictMode() const { return m_isValidStrictMode; }
shadowsArgumentsJSC::JSParser::Scope446         bool shadowsArguments() const { return m_shadowsArguments; }
447 
copyCapturedVariablesToVectorJSC::JSParser::Scope448         void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl> >& vector)
449         {
450             IdentifierSet::iterator end = capturedVariables.end();
451             for (IdentifierSet::iterator it = capturedVariables.begin(); it != end; ++it) {
452                 if (m_declaredVariables.contains(*it))
453                     continue;
454                 vector.append(*it);
455             }
456             vector.shrinkToFit();
457         }
458 
saveFunctionInfoJSC::JSParser::Scope459         void saveFunctionInfo(SourceProviderCacheItem* info)
460         {
461             ASSERT(m_isFunction);
462             info->usesEval = m_usesEval;
463             copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables);
464             copyCapturedVariablesToVector(m_usedVariables, info->usedVariables);
465         }
466 
restoreFunctionInfoJSC::JSParser::Scope467         void restoreFunctionInfo(const SourceProviderCacheItem* info)
468         {
469             ASSERT(m_isFunction);
470             m_usesEval = info->usesEval;
471             unsigned size = info->usedVariables.size();
472             for (unsigned i = 0; i < size; ++i)
473                 m_usedVariables.add(info->usedVariables[i]);
474             size = info->writtenVariables.size();
475             for (unsigned i = 0; i < size; ++i)
476                 m_writtenVariables.add(info->writtenVariables[i]);
477         }
478 
479     private:
480         JSGlobalData* m_globalData;
481         bool m_shadowsArguments : 1;
482         bool m_usesEval : 1;
483         bool m_needsFullActivation : 1;
484         bool m_allowsNewDecls : 1;
485         bool m_strictMode : 1;
486         bool m_isFunction : 1;
487         bool m_isFunctionBoundary : 1;
488         bool m_isValidStrictMode : 1;
489         int m_loopDepth;
490         int m_switchDepth;
491 
492         typedef Vector<ScopeLabelInfo, 2> LabelStack;
493         OwnPtr<LabelStack> m_labels;
494         IdentifierSet m_declaredVariables;
495         IdentifierSet m_usedVariables;
496         IdentifierSet m_closedVariables;
497         IdentifierSet m_writtenVariables;
498     };
499 
500     typedef Vector<Scope, 10> ScopeStack;
501 
502     struct ScopeRef {
ScopeRefJSC::JSParser::ScopeRef503         ScopeRef(ScopeStack* scopeStack, unsigned index)
504             : m_scopeStack(scopeStack)
505             , m_index(index)
506         {
507         }
operator ->JSC::JSParser::ScopeRef508         Scope* operator->() { return &m_scopeStack->at(m_index); }
indexJSC::JSParser::ScopeRef509         unsigned index() const { return m_index; }
510 
hasContainingScopeJSC::JSParser::ScopeRef511         bool hasContainingScope()
512         {
513             return m_index && !m_scopeStack->at(m_index).isFunctionBoundary();
514         }
515 
containingScopeJSC::JSParser::ScopeRef516         ScopeRef containingScope()
517         {
518             ASSERT(hasContainingScope());
519             return ScopeRef(m_scopeStack, m_index - 1);
520         }
521 
522     private:
523         ScopeStack* m_scopeStack;
524         unsigned m_index;
525     };
526 
527     struct AutoPopScopeRef : public ScopeRef {
AutoPopScopeRefJSC::JSParser::AutoPopScopeRef528         AutoPopScopeRef(JSParser* parser, ScopeRef scope)
529             : ScopeRef(scope)
530             , m_parser(parser)
531         {
532         }
533 
~AutoPopScopeRefJSC::JSParser::AutoPopScopeRef534         ~AutoPopScopeRef()
535         {
536             if (m_parser)
537                 m_parser->popScope(*this, false);
538         }
539 
setPoppedJSC::JSParser::AutoPopScopeRef540         void setPopped()
541         {
542             m_parser = 0;
543         }
544 
545     private:
546         JSParser* m_parser;
547     };
548 
currentScope()549     ScopeRef currentScope()
550     {
551         return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1);
552     }
553 
pushScope()554     ScopeRef pushScope()
555     {
556         bool isFunction = false;
557         bool isStrict = false;
558         if (!m_scopeStack.isEmpty()) {
559             isStrict = m_scopeStack.last().strictMode();
560             isFunction = m_scopeStack.last().isFunction();
561         }
562         m_scopeStack.append(Scope(m_globalData, isFunction, isStrict));
563         return currentScope();
564     }
565 
popScopeInternal(ScopeRef & scope,bool shouldTrackClosedVariables)566     bool popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables)
567     {
568         ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
569         ASSERT(m_scopeStack.size() > 1);
570         bool result = m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables);
571         m_scopeStack.removeLast();
572         return result;
573     }
574 
popScope(ScopeRef & scope,bool shouldTrackClosedVariables)575     bool popScope(ScopeRef& scope, bool shouldTrackClosedVariables)
576     {
577         return popScopeInternal(scope, shouldTrackClosedVariables);
578     }
579 
popScope(AutoPopScopeRef & scope,bool shouldTrackClosedVariables)580     bool popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables)
581     {
582         scope.setPopped();
583         return popScopeInternal(scope, shouldTrackClosedVariables);
584     }
585 
declareVariable(const Identifier * ident)586     bool declareVariable(const Identifier* ident)
587     {
588         unsigned i = m_scopeStack.size() - 1;
589         ASSERT(i < m_scopeStack.size());
590         while (!m_scopeStack[i].allowsNewDecls()) {
591             i--;
592             ASSERT(i < m_scopeStack.size());
593         }
594         return m_scopeStack[i].declareVariable(ident);
595     }
596 
declareWrite(const Identifier * ident)597     void declareWrite(const Identifier* ident)
598     {
599         if (!m_syntaxAlreadyValidated)
600             m_scopeStack.last().declareWrite(ident);
601     }
602 
603     ScopeStack m_scopeStack;
604 
findCachedFunctionInfo(int openBracePos)605     const SourceProviderCacheItem* findCachedFunctionInfo(int openBracePos)
606     {
607         return m_functionCache ? m_functionCache->get(openBracePos) : 0;
608     }
609 
610     SourceProviderCache* m_functionCache;
611 };
612 
jsParse(JSGlobalData * globalData,FunctionParameters * parameters,JSParserStrictness strictness,JSParserMode parserMode,const SourceCode * source)613 const char* jsParse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source)
614 {
615     JSParser parser(globalData->lexer, globalData, parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider());
616     return parser.parseProgram();
617 }
618 
JSParser(Lexer * lexer,JSGlobalData * globalData,FunctionParameters * parameters,bool inStrictContext,bool isFunction,SourceProvider * provider)619 JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, bool inStrictContext, bool isFunction, SourceProvider* provider)
620     : m_lexer(lexer)
621     , m_stack(globalData->stack())
622     , m_error(false)
623     , m_errorMessage("Parse error")
624     , m_globalData(globalData)
625     , m_allowsIn(true)
626     , m_lastLine(0)
627     , m_lastTokenEnd(0)
628     , m_assignmentCount(0)
629     , m_nonLHSCount(0)
630     , m_syntaxAlreadyValidated(provider->isValid())
631     , m_statementDepth(0)
632     , m_nonTrivialExpressionCount(0)
633     , m_lastIdentifier(0)
634     , m_functionCache(m_lexer->sourceProvider()->cache())
635 {
636     ScopeRef scope = pushScope();
637     if (isFunction)
638         scope->setIsFunction();
639     if (inStrictContext)
640         scope->setStrictMode();
641     if (parameters) {
642         for (unsigned i = 0; i < parameters->size(); i++)
643             scope->declareParameter(&parameters->at(i));
644     }
645     next();
646     m_lexer->setLastLineNumber(tokenLine());
647 }
648 
parseProgram()649 const char* JSParser::parseProgram()
650 {
651     unsigned oldFunctionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
652     ASTBuilder context(m_globalData, m_lexer);
653     if (m_lexer->isReparsing())
654         m_statementDepth--;
655     ScopeRef scope = currentScope();
656     SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
657     if (!sourceElements || !consume(EOFTOK))
658         return m_errorMessage;
659     IdentifierSet capturedVariables;
660     scope->getCapturedVariables(capturedVariables);
661     CodeFeatures features = context.features();
662     if (scope->strictMode())
663         features |= StrictModeFeature;
664     if (scope->shadowsArguments())
665         features |= ShadowsArgumentsFeature;
666 
667     unsigned functionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
668     if (functionCacheSize != oldFunctionCacheSize)
669         m_lexer->sourceProvider()->notifyCacheSizeChanged(functionCacheSize - oldFunctionCacheSize);
670 
671     m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
672                                            m_lastLine, context.numConstants(), capturedVariables);
673     return 0;
674 }
675 
allowAutomaticSemicolon()676 bool JSParser::allowAutomaticSemicolon()
677 {
678     return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
679 }
680 
parseSourceElements(TreeBuilder & context)681 template <JSParser::SourceElementsMode mode, class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context)
682 {
683     TreeSourceElements sourceElements = context.createSourceElements();
684     bool seenNonDirective = false;
685     const Identifier* directive = 0;
686     unsigned startOffset = m_token.m_info.startOffset;
687     bool hasSetStrict = false;
688     while (TreeStatement statement = parseStatement(context, directive)) {
689         if (mode == CheckForStrictMode && !seenNonDirective) {
690             if (directive) {
691                 if (!hasSetStrict && m_globalData->propertyNames->useStrictIdentifier == *directive) {
692                     setStrictMode();
693                     hasSetStrict = true;
694                     failIfFalse(isValidStrictMode());
695                     m_lexer->setOffset(startOffset);
696                     next();
697                     failIfTrue(m_error);
698                     continue;
699                 }
700             } else
701                 seenNonDirective = true;
702         }
703         context.appendStatement(sourceElements, statement);
704     }
705 
706     if (m_error)
707         fail();
708     return sourceElements;
709 }
710 
parseVarDeclaration(TreeBuilder & context)711 template <class TreeBuilder> TreeStatement JSParser::parseVarDeclaration(TreeBuilder& context)
712 {
713     ASSERT(match(VAR));
714     int start = tokenLine();
715     int end = 0;
716     int scratch;
717     const Identifier* scratch1 = 0;
718     TreeExpression scratch2 = 0;
719     int scratch3 = 0;
720     TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3);
721     failIfTrue(m_error);
722     failIfFalse(autoSemiColon());
723 
724     return context.createVarStatement(varDecls, start, end);
725 }
726 
parseConstDeclaration(TreeBuilder & context)727 template <class TreeBuilder> TreeStatement JSParser::parseConstDeclaration(TreeBuilder& context)
728 {
729     ASSERT(match(CONSTTOKEN));
730     int start = tokenLine();
731     int end = 0;
732     TreeConstDeclList constDecls = parseConstDeclarationList(context);
733     failIfTrue(m_error);
734     failIfFalse(autoSemiColon());
735 
736     return context.createConstStatement(constDecls, start, end);
737 }
738 
parseDoWhileStatement(TreeBuilder & context)739 template <class TreeBuilder> TreeStatement JSParser::parseDoWhileStatement(TreeBuilder& context)
740 {
741     ASSERT(match(DO));
742     int startLine = tokenLine();
743     next();
744     const Identifier* unused = 0;
745     startLoop();
746     TreeStatement statement = parseStatement(context, unused);
747     endLoop();
748     failIfFalse(statement);
749     int endLine = tokenLine();
750     consumeOrFail(WHILE);
751     consumeOrFail(OPENPAREN);
752     TreeExpression expr = parseExpression(context);
753     failIfFalse(expr);
754     consumeOrFail(CLOSEPAREN);
755     if (match(SEMICOLON))
756         next(); // Always performs automatic semicolon insertion.
757     return context.createDoWhileStatement(statement, expr, startLine, endLine);
758 }
759 
parseWhileStatement(TreeBuilder & context)760 template <class TreeBuilder> TreeStatement JSParser::parseWhileStatement(TreeBuilder& context)
761 {
762     ASSERT(match(WHILE));
763     int startLine = tokenLine();
764     next();
765     consumeOrFail(OPENPAREN);
766     TreeExpression expr = parseExpression(context);
767     failIfFalse(expr);
768     int endLine = tokenLine();
769     consumeOrFail(CLOSEPAREN);
770     const Identifier* unused = 0;
771     startLoop();
772     TreeStatement statement = parseStatement(context, unused);
773     endLoop();
774     failIfFalse(statement);
775     return context.createWhileStatement(expr, statement, startLine, endLine);
776 }
777 
parseVarDeclarationList(TreeBuilder & context,int & declarations,const Identifier * & lastIdent,TreeExpression & lastInitializer,int & identStart,int & initStart,int & initEnd)778 template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(TreeBuilder& context, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd)
779 {
780     TreeExpression varDecls = 0;
781     do {
782         declarations++;
783         next();
784         matchOrFail(IDENT);
785 
786         int varStart = tokenStart();
787         identStart = varStart;
788         const Identifier* name = m_token.m_data.ident;
789         lastIdent = name;
790         next();
791         bool hasInitializer = match(EQUAL);
792         failIfFalseIfStrict(declareVariable(name));
793         context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
794         if (hasInitializer) {
795             int varDivot = tokenStart() + 1;
796             initStart = tokenStart();
797             next(); // consume '='
798             int initialAssignments = m_assignmentCount;
799             TreeExpression initializer = parseAssignmentExpression(context);
800             initEnd = lastTokenEnd();
801             lastInitializer = initializer;
802             failIfFalse(initializer);
803 
804             TreeExpression node = context.createAssignResolve(*name, initializer, initialAssignments != m_assignmentCount, varStart, varDivot, lastTokenEnd());
805             if (!varDecls)
806                 varDecls = node;
807             else
808                 varDecls = context.combineCommaNodes(varDecls, node);
809         }
810     } while (match(COMMA));
811     return varDecls;
812 }
813 
parseConstDeclarationList(TreeBuilder & context)814 template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationList(TreeBuilder& context)
815 {
816     failIfTrue(strictMode());
817     TreeConstDeclList constDecls = 0;
818     TreeConstDeclList tail = 0;
819     do {
820         next();
821         matchOrFail(IDENT);
822         const Identifier* name = m_token.m_data.ident;
823         next();
824         bool hasInitializer = match(EQUAL);
825         declareVariable(name);
826         context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
827         TreeExpression initializer = 0;
828         if (hasInitializer) {
829             next(); // consume '='
830             initializer = parseAssignmentExpression(context);
831         }
832         tail = context.appendConstDecl(tail, name, initializer);
833         if (!constDecls)
834             constDecls = tail;
835     } while (match(COMMA));
836     return constDecls;
837 }
838 
parseForStatement(TreeBuilder & context)839 template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuilder& context)
840 {
841     ASSERT(match(FOR));
842     int startLine = tokenLine();
843     next();
844     consumeOrFail(OPENPAREN);
845     int nonLHSCount = m_nonLHSCount;
846     int declarations = 0;
847     int declsStart = 0;
848     int declsEnd = 0;
849     TreeExpression decls = 0;
850     bool hasDeclaration = false;
851     if (match(VAR)) {
852         /*
853          for (var IDENT in expression) statement
854          for (var IDENT = expression in expression) statement
855          for (var varDeclarationList; expressionOpt; expressionOpt)
856          */
857         hasDeclaration = true;
858         const Identifier* forInTarget = 0;
859         TreeExpression forInInitializer = 0;
860         m_allowsIn = false;
861         int initStart = 0;
862         int initEnd = 0;
863         decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd);
864         m_allowsIn = true;
865         if (m_error)
866             fail();
867 
868         // Remainder of a standard for loop is handled identically
869         if (match(SEMICOLON))
870             goto standardForLoop;
871 
872         failIfFalse(declarations == 1);
873 
874         // Handle for-in with var declaration
875         int inLocation = tokenStart();
876         if (!consume(INTOKEN))
877             fail();
878 
879         TreeExpression expr = parseExpression(context);
880         failIfFalse(expr);
881         int exprEnd = lastTokenEnd();
882 
883         int endLine = tokenLine();
884         consumeOrFail(CLOSEPAREN);
885 
886         const Identifier* unused = 0;
887         startLoop();
888         TreeStatement statement = parseStatement(context, unused);
889         endLoop();
890         failIfFalse(statement);
891 
892         return context.createForInLoop(forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine);
893     }
894 
895     if (!match(SEMICOLON)) {
896         m_allowsIn = false;
897         declsStart = tokenStart();
898         decls = parseExpression(context);
899         declsEnd = lastTokenEnd();
900         m_allowsIn = true;
901         failIfFalse(decls);
902     }
903 
904     if (match(SEMICOLON)) {
905     standardForLoop:
906         // Standard for loop
907         next();
908         TreeExpression condition = 0;
909 
910         if (!match(SEMICOLON)) {
911             condition = parseExpression(context);
912             failIfFalse(condition);
913         }
914         consumeOrFail(SEMICOLON);
915 
916         TreeExpression increment = 0;
917         if (!match(CLOSEPAREN)) {
918             increment = parseExpression(context);
919             failIfFalse(increment);
920         }
921         int endLine = tokenLine();
922         consumeOrFail(CLOSEPAREN);
923         const Identifier* unused = 0;
924         startLoop();
925         TreeStatement statement = parseStatement(context, unused);
926         endLoop();
927         failIfFalse(statement);
928         return context.createForLoop(decls, condition, increment, statement, hasDeclaration, startLine, endLine);
929     }
930 
931     // For-in loop
932     failIfFalse(nonLHSCount == m_nonLHSCount);
933     consumeOrFail(INTOKEN);
934     TreeExpression expr = parseExpression(context);
935     failIfFalse(expr);
936     int exprEnd = lastTokenEnd();
937     int endLine = tokenLine();
938     consumeOrFail(CLOSEPAREN);
939     const Identifier* unused = 0;
940     startLoop();
941     TreeStatement statement = parseStatement(context, unused);
942     endLoop();
943     failIfFalse(statement);
944 
945     return context.createForInLoop(decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
946 }
947 
parseBreakStatement(TreeBuilder & context)948 template <class TreeBuilder> TreeStatement JSParser::parseBreakStatement(TreeBuilder& context)
949 {
950     ASSERT(match(BREAK));
951     int startCol = tokenStart();
952     int endCol = tokenEnd();
953     int startLine = tokenLine();
954     int endLine = tokenLine();
955     next();
956 
957     if (autoSemiColon()) {
958         failIfFalse(breakIsValid());
959         return context.createBreakStatement(startCol, endCol, startLine, endLine);
960     }
961     matchOrFail(IDENT);
962     const Identifier* ident = m_token.m_data.ident;
963     failIfFalse(getLabel(ident));
964     endCol = tokenEnd();
965     endLine = tokenLine();
966     next();
967     failIfFalse(autoSemiColon());
968     return context.createBreakStatement(ident, startCol, endCol, startLine, endLine);
969 }
970 
parseContinueStatement(TreeBuilder & context)971 template <class TreeBuilder> TreeStatement JSParser::parseContinueStatement(TreeBuilder& context)
972 {
973     ASSERT(match(CONTINUE));
974     int startCol = tokenStart();
975     int endCol = tokenEnd();
976     int startLine = tokenLine();
977     int endLine = tokenLine();
978     next();
979 
980     if (autoSemiColon()) {
981         failIfFalse(continueIsValid());
982         return context.createContinueStatement(startCol, endCol, startLine, endLine);
983     }
984     matchOrFail(IDENT);
985     const Identifier* ident = m_token.m_data.ident;
986     ScopeLabelInfo* label = getLabel(ident);
987     failIfFalse(label);
988     failIfFalse(label->m_isLoop);
989     endCol = tokenEnd();
990     endLine = tokenLine();
991     next();
992     failIfFalse(autoSemiColon());
993     return context.createContinueStatement(ident, startCol, endCol, startLine, endLine);
994 }
995 
parseReturnStatement(TreeBuilder & context)996 template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBuilder& context)
997 {
998     ASSERT(match(RETURN));
999     failIfFalse(currentScope()->isFunction());
1000     int startLine = tokenLine();
1001     int endLine = startLine;
1002     int start = tokenStart();
1003     int end = tokenEnd();
1004     next();
1005     // We do the auto semicolon check before attempting to parse an expression
1006     // as we need to ensure the a line break after the return correctly terminates
1007     // the statement
1008     if (match(SEMICOLON))
1009         endLine  = tokenLine();
1010     if (autoSemiColon())
1011         return context.createReturnStatement(0, start, end, startLine, endLine);
1012     TreeExpression expr = parseExpression(context);
1013     failIfFalse(expr);
1014     end = lastTokenEnd();
1015     if (match(SEMICOLON))
1016         endLine  = tokenLine();
1017     failIfFalse(autoSemiColon());
1018     return context.createReturnStatement(expr, start, end, startLine, endLine);
1019 }
1020 
parseThrowStatement(TreeBuilder & context)1021 template <class TreeBuilder> TreeStatement JSParser::parseThrowStatement(TreeBuilder& context)
1022 {
1023     ASSERT(match(THROW));
1024     int eStart = tokenStart();
1025     int startLine = tokenLine();
1026     next();
1027 
1028     failIfTrue(autoSemiColon());
1029 
1030     TreeExpression expr = parseExpression(context);
1031     failIfFalse(expr);
1032     int eEnd = lastTokenEnd();
1033     int endLine = tokenLine();
1034     failIfFalse(autoSemiColon());
1035 
1036     return context.createThrowStatement(expr, eStart, eEnd, startLine, endLine);
1037 }
1038 
parseWithStatement(TreeBuilder & context)1039 template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuilder& context)
1040 {
1041     ASSERT(match(WITH));
1042     failIfTrue(strictMode());
1043     currentScope()->setNeedsFullActivation();
1044     int startLine = tokenLine();
1045     next();
1046     consumeOrFail(OPENPAREN);
1047     int start = tokenStart();
1048     TreeExpression expr = parseExpression(context);
1049     failIfFalse(expr);
1050     int end = lastTokenEnd();
1051 
1052     int endLine = tokenLine();
1053     consumeOrFail(CLOSEPAREN);
1054     const Identifier* unused = 0;
1055     TreeStatement statement = parseStatement(context, unused);
1056     failIfFalse(statement);
1057 
1058     return context.createWithStatement(expr, statement, start, end, startLine, endLine);
1059 }
1060 
parseSwitchStatement(TreeBuilder & context)1061 template <class TreeBuilder> TreeStatement JSParser::parseSwitchStatement(TreeBuilder& context)
1062 {
1063     ASSERT(match(SWITCH));
1064     int startLine = tokenLine();
1065     next();
1066     consumeOrFail(OPENPAREN);
1067     TreeExpression expr = parseExpression(context);
1068     failIfFalse(expr);
1069     int endLine = tokenLine();
1070     consumeOrFail(CLOSEPAREN);
1071     consumeOrFail(OPENBRACE);
1072     startSwitch();
1073     TreeClauseList firstClauses = parseSwitchClauses(context);
1074     failIfTrue(m_error);
1075 
1076     TreeClause defaultClause = parseSwitchDefaultClause(context);
1077     failIfTrue(m_error);
1078 
1079     TreeClauseList secondClauses = parseSwitchClauses(context);
1080     failIfTrue(m_error);
1081     endSwitch();
1082     consumeOrFail(CLOSEBRACE);
1083 
1084     return context.createSwitchStatement(expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
1085 
1086 }
1087 
parseSwitchClauses(TreeBuilder & context)1088 template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBuilder& context)
1089 {
1090     if (!match(CASE))
1091         return 0;
1092     next();
1093     TreeExpression condition = parseExpression(context);
1094     failIfFalse(condition);
1095     consumeOrFail(COLON);
1096     TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
1097     failIfFalse(statements);
1098     TreeClause clause = context.createClause(condition, statements);
1099     TreeClauseList clauseList = context.createClauseList(clause);
1100     TreeClauseList tail = clauseList;
1101 
1102     while (match(CASE)) {
1103         next();
1104         TreeExpression condition = parseExpression(context);
1105         failIfFalse(condition);
1106         consumeOrFail(COLON);
1107         TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
1108         failIfFalse(statements);
1109         clause = context.createClause(condition, statements);
1110         tail = context.createClauseList(tail, clause);
1111     }
1112     return clauseList;
1113 }
1114 
parseSwitchDefaultClause(TreeBuilder & context)1115 template <class TreeBuilder> TreeClause JSParser::parseSwitchDefaultClause(TreeBuilder& context)
1116 {
1117     if (!match(DEFAULT))
1118         return 0;
1119     next();
1120     consumeOrFail(COLON);
1121     TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
1122     failIfFalse(statements);
1123     return context.createClause(0, statements);
1124 }
1125 
parseTryStatement(TreeBuilder & context)1126 template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuilder& context)
1127 {
1128     ASSERT(match(TRY));
1129     TreeStatement tryBlock = 0;
1130     const Identifier* ident = &m_globalData->propertyNames->nullIdentifier;
1131     bool catchHasEval = false;
1132     TreeStatement catchBlock = 0;
1133     TreeStatement finallyBlock = 0;
1134     int firstLine = tokenLine();
1135     next();
1136     matchOrFail(OPENBRACE);
1137 
1138     tryBlock = parseBlockStatement(context);
1139     failIfFalse(tryBlock);
1140     int lastLine = m_lastLine;
1141 
1142     if (match(CATCH)) {
1143         currentScope()->setNeedsFullActivation();
1144         next();
1145         consumeOrFail(OPENPAREN);
1146         matchOrFail(IDENT);
1147         ident = m_token.m_data.ident;
1148         next();
1149         AutoPopScopeRef catchScope(this, pushScope());
1150         failIfFalseIfStrict(catchScope->declareVariable(ident));
1151         catchScope->preventNewDecls();
1152         consumeOrFail(CLOSEPAREN);
1153         matchOrFail(OPENBRACE);
1154         int initialEvalCount = context.evalCount();
1155         catchBlock = parseBlockStatement(context);
1156         failIfFalse(catchBlock);
1157         catchHasEval = initialEvalCount != context.evalCount();
1158         failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo));
1159     }
1160 
1161     if (match(FINALLY)) {
1162         next();
1163         matchOrFail(OPENBRACE);
1164         finallyBlock = parseBlockStatement(context);
1165         failIfFalse(finallyBlock);
1166     }
1167     failIfFalse(catchBlock || finallyBlock);
1168     return context.createTryStatement(tryBlock, ident, catchHasEval, catchBlock, finallyBlock, firstLine, lastLine);
1169 }
1170 
parseDebuggerStatement(TreeBuilder & context)1171 template <class TreeBuilder> TreeStatement JSParser::parseDebuggerStatement(TreeBuilder& context)
1172 {
1173     ASSERT(match(DEBUGGER));
1174     int startLine = tokenLine();
1175     int endLine = startLine;
1176     next();
1177     if (match(SEMICOLON))
1178         startLine = tokenLine();
1179     failIfFalse(autoSemiColon());
1180     return context.createDebugger(startLine, endLine);
1181 }
1182 
parseBlockStatement(TreeBuilder & context)1183 template <class TreeBuilder> TreeStatement JSParser::parseBlockStatement(TreeBuilder& context)
1184 {
1185     ASSERT(match(OPENBRACE));
1186     int start = tokenLine();
1187     next();
1188     if (match(CLOSEBRACE)) {
1189         next();
1190         return context.createBlockStatement(0, start, m_lastLine);
1191     }
1192     TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context);
1193     failIfFalse(subtree);
1194     matchOrFail(CLOSEBRACE);
1195     next();
1196     return context.createBlockStatement(subtree, start, m_lastLine);
1197 }
1198 
parseStatement(TreeBuilder & context,const Identifier * & directive)1199 template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& context, const Identifier*& directive)
1200 {
1201     DepthManager statementDepth(&m_statementDepth);
1202     m_statementDepth++;
1203     directive = 0;
1204     int nonTrivialExpressionCount = 0;
1205     failIfStackOverflow();
1206     switch (m_token.m_type) {
1207     case OPENBRACE:
1208         return parseBlockStatement(context);
1209     case VAR:
1210         return parseVarDeclaration(context);
1211     case CONSTTOKEN:
1212         return parseConstDeclaration(context);
1213     case FUNCTION:
1214         failIfFalseIfStrict(m_statementDepth == 1);
1215         return parseFunctionDeclaration(context);
1216     case SEMICOLON:
1217         next();
1218         return context.createEmptyStatement();
1219     case IF:
1220         return parseIfStatement(context);
1221     case DO:
1222         return parseDoWhileStatement(context);
1223     case WHILE:
1224         return parseWhileStatement(context);
1225     case FOR:
1226         return parseForStatement(context);
1227     case CONTINUE:
1228         return parseContinueStatement(context);
1229     case BREAK:
1230         return parseBreakStatement(context);
1231     case RETURN:
1232         return parseReturnStatement(context);
1233     case WITH:
1234         return parseWithStatement(context);
1235     case SWITCH:
1236         return parseSwitchStatement(context);
1237     case THROW:
1238         return parseThrowStatement(context);
1239     case TRY:
1240         return parseTryStatement(context);
1241     case DEBUGGER:
1242         return parseDebuggerStatement(context);
1243     case EOFTOK:
1244     case CASE:
1245     case CLOSEBRACE:
1246     case DEFAULT:
1247         // These tokens imply the end of a set of source elements
1248         return 0;
1249     case IDENT:
1250         return parseExpressionOrLabelStatement(context);
1251     case STRING:
1252         directive = m_token.m_data.ident;
1253         nonTrivialExpressionCount = m_nonTrivialExpressionCount;
1254     default:
1255         TreeStatement exprStatement = parseExpressionStatement(context);
1256         if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
1257             directive = 0;
1258         return exprStatement;
1259     }
1260 }
1261 
parseFormalParameters(TreeBuilder & context)1262 template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParameters(TreeBuilder& context)
1263 {
1264     matchOrFail(IDENT);
1265     failIfFalseIfStrict(declareParameter(m_token.m_data.ident));
1266     TreeFormalParameterList list = context.createFormalParameterList(*m_token.m_data.ident);
1267     TreeFormalParameterList tail = list;
1268     next();
1269     while (match(COMMA)) {
1270         next();
1271         matchOrFail(IDENT);
1272         const Identifier* ident = m_token.m_data.ident;
1273         failIfFalseIfStrict(declareParameter(ident));
1274         next();
1275         tail = context.createFormalParameterList(tail, *ident);
1276     }
1277     return list;
1278 }
1279 
parseFunctionBody(TreeBuilder & context)1280 template <class TreeBuilder> TreeFunctionBody JSParser::parseFunctionBody(TreeBuilder& context)
1281 {
1282     if (match(CLOSEBRACE))
1283         return context.createFunctionBody(strictMode());
1284     DepthManager statementDepth(&m_statementDepth);
1285     m_statementDepth = 0;
1286     typename TreeBuilder::FunctionBodyBuilder bodyBuilder(m_globalData, m_lexer);
1287     failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder));
1288     return context.createFunctionBody(strictMode());
1289 }
1290 
parseFunctionInfo(TreeBuilder & context,const Identifier * & name,TreeFormalParameterList & parameters,TreeFunctionBody & body,int & openBracePos,int & closeBracePos,int & bodyStartLine)1291 template <JSParser::FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine)
1292 {
1293     AutoPopScopeRef functionScope(this, pushScope());
1294     functionScope->setIsFunction();
1295     if (match(IDENT)) {
1296         name = m_token.m_data.ident;
1297         failIfTrue(*name == m_globalData->propertyNames->underscoreProto);
1298         next();
1299         if (!nameIsInContainingScope)
1300             failIfFalseIfStrict(functionScope->declareVariable(name));
1301     } else if (requirements == FunctionNeedsName)
1302         return false;
1303     consumeOrFail(OPENPAREN);
1304     if (!match(CLOSEPAREN)) {
1305         parameters = parseFormalParameters(context);
1306         failIfFalse(parameters);
1307     }
1308     consumeOrFail(CLOSEPAREN);
1309     matchOrFail(OPENBRACE);
1310 
1311     openBracePos = m_token.m_data.intValue;
1312     bodyStartLine = tokenLine();
1313 
1314     if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) {
1315         // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
1316         body = context.createFunctionBody(strictMode());
1317 
1318         functionScope->restoreFunctionInfo(cachedInfo);
1319         failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
1320 
1321         closeBracePos = cachedInfo->closeBracePos;
1322         m_token = cachedInfo->closeBraceToken();
1323         m_lexer->setOffset(m_token.m_info.endOffset);
1324         m_lexer->setLineNumber(m_token.m_info.line);
1325 
1326         next();
1327         return true;
1328     }
1329 
1330     next();
1331 
1332     body = parseFunctionBody(context);
1333     failIfFalse(body);
1334     if (functionScope->strictMode() && name) {
1335         failIfTrue(m_globalData->propertyNames->arguments == *name);
1336         failIfTrue(m_globalData->propertyNames->eval == *name);
1337     }
1338     closeBracePos = m_token.m_data.intValue;
1339 
1340     // Cache the tokenizer state and the function scope the first time the function is parsed.
1341     // Any future reparsing can then skip the function.
1342     static const int minimumFunctionLengthToCache = 64;
1343     OwnPtr<SourceProviderCacheItem> newInfo;
1344     int functionLength = closeBracePos - openBracePos;
1345     if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
1346         newInfo = adoptPtr(new SourceProviderCacheItem(m_token.m_info.line, closeBracePos));
1347         functionScope->saveFunctionInfo(newInfo.get());
1348     }
1349 
1350     failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
1351     matchOrFail(CLOSEBRACE);
1352 
1353     if (newInfo) {
1354         unsigned approximateByteSize = newInfo->approximateByteSize();
1355         m_functionCache->add(openBracePos, newInfo.release(), approximateByteSize);
1356     }
1357 
1358     next();
1359     return true;
1360 }
1361 
parseFunctionDeclaration(TreeBuilder & context)1362 template <class TreeBuilder> TreeStatement JSParser::parseFunctionDeclaration(TreeBuilder& context)
1363 {
1364     ASSERT(match(FUNCTION));
1365     next();
1366     const Identifier* name = 0;
1367     TreeFormalParameterList parameters = 0;
1368     TreeFunctionBody body = 0;
1369     int openBracePos = 0;
1370     int closeBracePos = 0;
1371     int bodyStartLine = 0;
1372     failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
1373     failIfFalse(name);
1374     failIfFalseIfStrict(declareVariable(name));
1375     return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
1376 }
1377 
1378 struct LabelInfo {
LabelInfoJSC::LabelInfo1379     LabelInfo(const Identifier* ident, int start, int end)
1380         : m_ident(ident)
1381         , m_start(start)
1382         , m_end(end)
1383     {
1384     }
1385 
1386     const Identifier* m_ident;
1387     int m_start;
1388     int m_end;
1389 };
1390 
parseExpressionOrLabelStatement(TreeBuilder & context)1391 template <class TreeBuilder> TreeStatement JSParser::parseExpressionOrLabelStatement(TreeBuilder& context)
1392 {
1393 
1394     /* Expression and Label statements are ambiguous at LL(1), so we have a
1395      * special case that looks for a colon as the next character in the input.
1396      */
1397     Vector<LabelInfo> labels;
1398 
1399     do {
1400         int start = tokenStart();
1401         int startLine = tokenLine();
1402         if (!nextTokenIsColon()) {
1403             // If we hit this path we're making a expression statement, which
1404             // by definition can't make use of continue/break so we can just
1405             // ignore any labels we might have accumulated.
1406             TreeExpression expression = parseExpression(context);
1407             failIfFalse(expression);
1408             failIfFalse(autoSemiColon());
1409             return context.createExprStatement(expression, startLine, m_lastLine);
1410         }
1411         const Identifier* ident = m_token.m_data.ident;
1412         int end = tokenEnd();
1413         next();
1414         consumeOrFail(COLON);
1415         if (!m_syntaxAlreadyValidated) {
1416             // This is O(N^2) over the current list of consecutive labels, but I
1417             // have never seen more than one label in a row in the real world.
1418             for (size_t i = 0; i < labels.size(); i++)
1419                 failIfTrue(ident->impl() == labels[i].m_ident->impl());
1420             failIfTrue(getLabel(ident));
1421             labels.append(LabelInfo(ident, start, end));
1422         }
1423     } while (match(IDENT));
1424     bool isLoop = false;
1425     switch (m_token.m_type) {
1426     case FOR:
1427     case WHILE:
1428     case DO:
1429         isLoop = true;
1430         break;
1431 
1432     default:
1433         break;
1434     }
1435     const Identifier* unused = 0;
1436     if (!m_syntaxAlreadyValidated) {
1437         for (size_t i = 0; i < labels.size(); i++)
1438             pushLabel(labels[i].m_ident, isLoop);
1439     }
1440     TreeStatement statement = parseStatement(context, unused);
1441     if (!m_syntaxAlreadyValidated) {
1442         for (size_t i = 0; i < labels.size(); i++)
1443             popLabel();
1444     }
1445     failIfFalse(statement);
1446     for (size_t i = 0; i < labels.size(); i++) {
1447         const LabelInfo& info = labels[labels.size() - i - 1];
1448         statement = context.createLabelStatement(info.m_ident, statement, info.m_start, info.m_end);
1449     }
1450     return statement;
1451 }
1452 
parseExpressionStatement(TreeBuilder & context)1453 template <class TreeBuilder> TreeStatement JSParser::parseExpressionStatement(TreeBuilder& context)
1454 {
1455     int startLine = tokenLine();
1456     TreeExpression expression = parseExpression(context);
1457     failIfFalse(expression);
1458     failIfFalse(autoSemiColon());
1459     return context.createExprStatement(expression, startLine, m_lastLine);
1460 }
1461 
parseIfStatement(TreeBuilder & context)1462 template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilder& context)
1463 {
1464     ASSERT(match(IF));
1465 
1466     int start = tokenLine();
1467     next();
1468 
1469     consumeOrFail(OPENPAREN);
1470 
1471     TreeExpression condition = parseExpression(context);
1472     failIfFalse(condition);
1473     int end = tokenLine();
1474     consumeOrFail(CLOSEPAREN);
1475 
1476     const Identifier* unused = 0;
1477     TreeStatement trueBlock = parseStatement(context, unused);
1478     failIfFalse(trueBlock);
1479 
1480     if (!match(ELSE))
1481         return context.createIfStatement(condition, trueBlock, start, end);
1482 
1483     Vector<TreeExpression> exprStack;
1484     Vector<pair<int, int> > posStack;
1485     Vector<TreeStatement> statementStack;
1486     bool trailingElse = false;
1487     do {
1488         next();
1489         if (!match(IF)) {
1490             const Identifier* unused = 0;
1491             TreeStatement block = parseStatement(context, unused);
1492             failIfFalse(block);
1493             statementStack.append(block);
1494             trailingElse = true;
1495             break;
1496         }
1497         int innerStart = tokenLine();
1498         next();
1499 
1500         consumeOrFail(OPENPAREN);
1501 
1502         TreeExpression innerCondition = parseExpression(context);
1503         failIfFalse(innerCondition);
1504         int innerEnd = tokenLine();
1505         consumeOrFail(CLOSEPAREN);
1506         const Identifier* unused = 0;
1507         TreeStatement innerTrueBlock = parseStatement(context, unused);
1508         failIfFalse(innerTrueBlock);
1509         exprStack.append(innerCondition);
1510         posStack.append(make_pair(innerStart, innerEnd));
1511         statementStack.append(innerTrueBlock);
1512     } while (match(ELSE));
1513 
1514     if (!trailingElse) {
1515         TreeExpression condition = exprStack.last();
1516         exprStack.removeLast();
1517         TreeStatement trueBlock = statementStack.last();
1518         statementStack.removeLast();
1519         pair<int, int> pos = posStack.last();
1520         posStack.removeLast();
1521         statementStack.append(context.createIfStatement(condition, trueBlock, pos.first, pos.second));
1522     }
1523 
1524     while (!exprStack.isEmpty()) {
1525         TreeExpression condition = exprStack.last();
1526         exprStack.removeLast();
1527         TreeStatement falseBlock = statementStack.last();
1528         statementStack.removeLast();
1529         TreeStatement trueBlock = statementStack.last();
1530         statementStack.removeLast();
1531         pair<int, int> pos = posStack.last();
1532         posStack.removeLast();
1533         statementStack.append(context.createIfStatement(condition, trueBlock, falseBlock, pos.first, pos.second));
1534     }
1535 
1536     return context.createIfStatement(condition, trueBlock, statementStack.last(), start, end);
1537 }
1538 
parseExpression(TreeBuilder & context)1539 template <class TreeBuilder> TreeExpression JSParser::parseExpression(TreeBuilder& context)
1540 {
1541     failIfStackOverflow();
1542     TreeExpression node = parseAssignmentExpression(context);
1543     failIfFalse(node);
1544     if (!match(COMMA))
1545         return node;
1546     next();
1547     m_nonTrivialExpressionCount++;
1548     m_nonLHSCount++;
1549     TreeExpression right = parseAssignmentExpression(context);
1550     failIfFalse(right);
1551     typename TreeBuilder::Comma commaNode = context.createCommaExpr(node, right);
1552     while (match(COMMA)) {
1553         next();
1554         right = parseAssignmentExpression(context);
1555         failIfFalse(right);
1556         context.appendToComma(commaNode, right);
1557     }
1558     return commaNode;
1559 }
1560 
1561 
parseAssignmentExpression(TreeBuilder & context)1562 template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpression(TreeBuilder& context)
1563 {
1564     failIfStackOverflow();
1565     int start = tokenStart();
1566     int initialAssignmentCount = m_assignmentCount;
1567     int initialNonLHSCount = m_nonLHSCount;
1568     TreeExpression lhs = parseConditionalExpression(context);
1569     failIfFalse(lhs);
1570     if (initialNonLHSCount != m_nonLHSCount)
1571         return lhs;
1572 
1573     int assignmentStack = 0;
1574     Operator op;
1575     bool hadAssignment = false;
1576     while (true) {
1577         switch (m_token.m_type) {
1578         case EQUAL: op = OpEqual; break;
1579         case PLUSEQUAL: op = OpPlusEq; break;
1580         case MINUSEQUAL: op = OpMinusEq; break;
1581         case MULTEQUAL: op = OpMultEq; break;
1582         case DIVEQUAL: op = OpDivEq; break;
1583         case LSHIFTEQUAL: op = OpLShift; break;
1584         case RSHIFTEQUAL: op = OpRShift; break;
1585         case URSHIFTEQUAL: op = OpURShift; break;
1586         case ANDEQUAL: op = OpAndEq; break;
1587         case XOREQUAL: op = OpXOrEq; break;
1588         case OREQUAL: op = OpOrEq; break;
1589         case MODEQUAL: op = OpModEq; break;
1590         default:
1591             goto end;
1592         }
1593         m_nonTrivialExpressionCount++;
1594         hadAssignment = true;
1595         context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), m_assignmentCount, op);
1596         start = tokenStart();
1597         m_assignmentCount++;
1598         next();
1599         if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
1600             failIfTrueIfStrict(m_globalData->propertyNames->eval == *m_lastIdentifier);
1601             failIfTrueIfStrict(m_globalData->propertyNames->arguments == *m_lastIdentifier);
1602             declareWrite(m_lastIdentifier);
1603             m_lastIdentifier = 0;
1604         }
1605         lhs = parseConditionalExpression(context);
1606         failIfFalse(lhs);
1607         if (initialNonLHSCount != m_nonLHSCount)
1608             break;
1609     }
1610 end:
1611     if (hadAssignment)
1612         m_nonLHSCount++;
1613 
1614     if (!TreeBuilder::CreatesAST)
1615         return lhs;
1616 
1617     while (assignmentStack)
1618         lhs = context.createAssignment(assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd());
1619 
1620     return lhs;
1621 }
1622 
parseConditionalExpression(TreeBuilder & context)1623 template <class TreeBuilder> TreeExpression JSParser::parseConditionalExpression(TreeBuilder& context)
1624 {
1625     TreeExpression cond = parseBinaryExpression(context);
1626     failIfFalse(cond);
1627     if (!match(QUESTION))
1628         return cond;
1629     m_nonTrivialExpressionCount++;
1630     m_nonLHSCount++;
1631     next();
1632     TreeExpression lhs = parseAssignmentExpression(context);
1633     consumeOrFail(COLON);
1634 
1635     TreeExpression rhs = parseAssignmentExpression(context);
1636     failIfFalse(rhs);
1637     return context.createConditionalExpr(cond, lhs, rhs);
1638 }
1639 
isUnaryOp(JSTokenType token)1640 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
1641 {
1642     return token & UnaryOpTokenFlag;
1643 }
1644 
isBinaryOperator(JSTokenType token)1645 int JSParser::isBinaryOperator(JSTokenType token)
1646 {
1647     if (m_allowsIn)
1648         return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
1649     return token & BinaryOpTokenPrecedenceMask;
1650 }
1651 
parseBinaryExpression(TreeBuilder & context)1652 template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(TreeBuilder& context)
1653 {
1654 
1655     int operandStackDepth = 0;
1656     int operatorStackDepth = 0;
1657     typename TreeBuilder::BinaryExprContext binaryExprContext(context);
1658     while (true) {
1659         int exprStart = tokenStart();
1660         int initialAssignments = m_assignmentCount;
1661         TreeExpression current = parseUnaryExpression(context);
1662         failIfFalse(current);
1663 
1664         context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), initialAssignments != m_assignmentCount);
1665         int precedence = isBinaryOperator(m_token.m_type);
1666         if (!precedence)
1667             break;
1668         m_nonTrivialExpressionCount++;
1669         m_nonLHSCount++;
1670         int operatorToken = m_token.m_type;
1671         next();
1672 
1673         while (operatorStackDepth &&  context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
1674             ASSERT(operandStackDepth > 1);
1675 
1676             typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1677             typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1678             context.shrinkOperandStackBy(operandStackDepth, 2);
1679             context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
1680             context.operatorStackPop(operatorStackDepth);
1681         }
1682         context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
1683     }
1684     while (operatorStackDepth) {
1685         ASSERT(operandStackDepth > 1);
1686 
1687         typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1688         typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1689         context.shrinkOperandStackBy(operandStackDepth, 2);
1690         context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
1691         context.operatorStackPop(operatorStackDepth);
1692     }
1693     return context.popOperandStack(operandStackDepth);
1694 }
1695 
1696 
parseProperty(TreeBuilder & context)1697 template <bool complete, class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& context)
1698 {
1699     bool wasIdent = false;
1700     switch (m_token.m_type) {
1701     namedProperty:
1702     case IDENT:
1703         wasIdent = true;
1704     case STRING: {
1705         const Identifier* ident = m_token.m_data.ident;
1706         next(Lexer::IgnoreReservedWords);
1707         if (match(COLON)) {
1708             next();
1709             TreeExpression node = parseAssignmentExpression(context);
1710             failIfFalse(node);
1711             return context.template createProperty<complete>(ident, node, PropertyNode::Constant);
1712         }
1713         failIfFalse(wasIdent);
1714         matchOrFail(IDENT);
1715         const Identifier* accessorName = 0;
1716         TreeFormalParameterList parameters = 0;
1717         TreeFunctionBody body = 0;
1718         int openBracePos = 0;
1719         int closeBracePos = 0;
1720         int bodyStartLine = 0;
1721         PropertyNode::Type type;
1722         if (*ident == m_globalData->propertyNames->get)
1723             type = PropertyNode::Getter;
1724         else if (*ident == m_globalData->propertyNames->set)
1725             type = PropertyNode::Setter;
1726         else
1727             fail();
1728         failIfFalse((parseFunctionInfo<FunctionNeedsName, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
1729         return context.template createGetterOrSetterProperty<complete>(type, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
1730     }
1731     case NUMBER: {
1732         double propertyName = m_token.m_data.doubleValue;
1733         next();
1734         consumeOrFail(COLON);
1735         TreeExpression node = parseAssignmentExpression(context);
1736         failIfFalse(node);
1737         return context.template createProperty<complete>(m_globalData, propertyName, node, PropertyNode::Constant);
1738     }
1739     default:
1740         failIfFalse(m_token.m_type & KeywordTokenFlag);
1741         goto namedProperty;
1742     }
1743 }
1744 
parseObjectLiteral(TreeBuilder & context)1745 template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBuilder& context)
1746 {
1747     int startOffset = m_token.m_data.intValue;
1748     consumeOrFail(OPENBRACE);
1749 
1750     if (match(CLOSEBRACE)) {
1751         next();
1752         return context.createObjectLiteral();
1753     }
1754 
1755     TreeProperty property = parseProperty<false>(context);
1756     failIfFalse(property);
1757     if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
1758         m_lexer->setOffset(startOffset);
1759         next();
1760         return parseStrictObjectLiteral(context);
1761     }
1762     TreePropertyList propertyList = context.createPropertyList(property);
1763     TreePropertyList tail = propertyList;
1764     while (match(COMMA)) {
1765         next();
1766         // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1767         if (match(CLOSEBRACE))
1768             break;
1769         property = parseProperty<false>(context);
1770         failIfFalse(property);
1771         if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
1772             m_lexer->setOffset(startOffset);
1773             next();
1774             return parseStrictObjectLiteral(context);
1775         }
1776         tail = context.createPropertyList(property, tail);
1777     }
1778 
1779     consumeOrFail(CLOSEBRACE);
1780 
1781     return context.createObjectLiteral(propertyList);
1782 }
1783 
parseStrictObjectLiteral(TreeBuilder & context)1784 template <class TreeBuilder> TreeExpression JSParser::parseStrictObjectLiteral(TreeBuilder& context)
1785 {
1786     consumeOrFail(OPENBRACE);
1787 
1788     if (match(CLOSEBRACE)) {
1789         next();
1790         return context.createObjectLiteral();
1791     }
1792 
1793     TreeProperty property = parseProperty<true>(context);
1794     failIfFalse(property);
1795 
1796     typedef HashMap<RefPtr<StringImpl>, unsigned, IdentifierRepHash> ObjectValidationMap;
1797     ObjectValidationMap objectValidator;
1798     // Add the first property
1799     if (!m_syntaxAlreadyValidated)
1800         objectValidator.add(context.getName(property).impl(), context.getType(property));
1801 
1802     TreePropertyList propertyList = context.createPropertyList(property);
1803     TreePropertyList tail = propertyList;
1804     while (match(COMMA)) {
1805         next();
1806         // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1807         if (match(CLOSEBRACE))
1808             break;
1809         property = parseProperty<true>(context);
1810         failIfFalse(property);
1811         if (!m_syntaxAlreadyValidated) {
1812             std::pair<ObjectValidationMap::iterator, bool> propertyEntryIter = objectValidator.add(context.getName(property).impl(), context.getType(property));
1813             if (!propertyEntryIter.second) {
1814                 failIfTrue(strictMode());
1815                 if ((context.getType(property) & propertyEntryIter.first->second) != PropertyNode::Constant) {
1816                     // Can't have multiple getters or setters with the same name, nor can we define
1817                     // a property as both an accessor and a constant value
1818                     failIfTrue(context.getType(property) & propertyEntryIter.first->second);
1819                     failIfTrue((context.getType(property) | propertyEntryIter.first->second) & PropertyNode::Constant);
1820                 }
1821             }
1822         }
1823         tail = context.createPropertyList(property, tail);
1824     }
1825 
1826     consumeOrFail(CLOSEBRACE);
1827 
1828     return context.createObjectLiteral(propertyList);
1829 }
1830 
parseArrayLiteral(TreeBuilder & context)1831 template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuilder& context)
1832 {
1833     consumeOrFail(OPENBRACKET);
1834 
1835     int elisions = 0;
1836     while (match(COMMA)) {
1837         next();
1838         elisions++;
1839     }
1840     if (match(CLOSEBRACKET)) {
1841         next();
1842         return context.createArray(elisions);
1843     }
1844 
1845     TreeExpression elem = parseAssignmentExpression(context);
1846     failIfFalse(elem);
1847     typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
1848     typename TreeBuilder::ElementList tail = elementList;
1849     elisions = 0;
1850     while (match(COMMA)) {
1851         next();
1852         elisions = 0;
1853 
1854         while (match(COMMA)) {
1855             next();
1856             elisions++;
1857         }
1858 
1859         if (match(CLOSEBRACKET)) {
1860             next();
1861             return context.createArray(elisions, elementList);
1862         }
1863         TreeExpression elem = parseAssignmentExpression(context);
1864         failIfFalse(elem);
1865         tail = context.createElementList(tail, elisions, elem);
1866     }
1867 
1868     consumeOrFail(CLOSEBRACKET);
1869 
1870     return context.createArray(elementList);
1871 }
1872 
parsePrimaryExpression(TreeBuilder & context)1873 template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(TreeBuilder& context)
1874 {
1875     switch (m_token.m_type) {
1876     case OPENBRACE:
1877         if (strictMode())
1878             return parseStrictObjectLiteral(context);
1879         return parseObjectLiteral(context);
1880     case OPENBRACKET:
1881         return parseArrayLiteral(context);
1882     case OPENPAREN: {
1883         next();
1884         int oldNonLHSCount = m_nonLHSCount;
1885         TreeExpression result = parseExpression(context);
1886         m_nonLHSCount = oldNonLHSCount;
1887         consumeOrFail(CLOSEPAREN);
1888 
1889         return result;
1890     }
1891     case THISTOKEN: {
1892         next();
1893         return context.thisExpr();
1894     }
1895     case IDENT: {
1896         int start = tokenStart();
1897         const Identifier* ident = m_token.m_data.ident;
1898         next();
1899         currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident);
1900         m_lastIdentifier = ident;
1901         return context.createResolve(ident, start);
1902     }
1903     case STRING: {
1904         const Identifier* ident = m_token.m_data.ident;
1905         next();
1906         return context.createString(ident);
1907     }
1908     case NUMBER: {
1909         double d = m_token.m_data.doubleValue;
1910         next();
1911         return context.createNumberExpr(d);
1912     }
1913     case NULLTOKEN: {
1914         next();
1915         return context.createNull();
1916     }
1917     case TRUETOKEN: {
1918         next();
1919         return context.createBoolean(true);
1920     }
1921     case FALSETOKEN: {
1922         next();
1923         return context.createBoolean(false);
1924     }
1925     case DIVEQUAL:
1926     case DIVIDE: {
1927         /* regexp */
1928         const Identifier* pattern;
1929         const Identifier* flags;
1930         if (match(DIVEQUAL))
1931             failIfFalse(m_lexer->scanRegExp(pattern, flags, '='));
1932         else
1933             failIfFalse(m_lexer->scanRegExp(pattern, flags));
1934 
1935         int start = tokenStart();
1936         next();
1937         TreeExpression re = context.createRegExp(*pattern, *flags, start);
1938         if (!re) {
1939             m_errorMessage = Yarr::checkSyntax(pattern->ustring());
1940             ASSERT(m_errorMessage);
1941             fail();
1942         }
1943         return re;
1944     }
1945     default:
1946         fail();
1947     }
1948 }
1949 
parseArguments(TreeBuilder & context)1950 template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder& context)
1951 {
1952     consumeOrFail(OPENPAREN);
1953     if (match(CLOSEPAREN)) {
1954         next();
1955         return context.createArguments();
1956     }
1957     TreeExpression firstArg = parseAssignmentExpression(context);
1958     failIfFalse(firstArg);
1959 
1960     TreeArgumentsList argList = context.createArgumentsList(firstArg);
1961     TreeArgumentsList tail = argList;
1962     while (match(COMMA)) {
1963         next();
1964         TreeExpression arg = parseAssignmentExpression(context);
1965         failIfFalse(arg);
1966         tail = context.createArgumentsList(tail, arg);
1967     }
1968     consumeOrFail(CLOSEPAREN);
1969     return context.createArguments(argList);
1970 }
1971 
parseMemberExpression(TreeBuilder & context)1972 template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(TreeBuilder& context)
1973 {
1974     TreeExpression base = 0;
1975     int start = tokenStart();
1976     int expressionStart = start;
1977     int newCount = 0;
1978     while (match(NEW)) {
1979         next();
1980         newCount++;
1981     }
1982 
1983     if (match(FUNCTION)) {
1984         const Identifier* name = &m_globalData->propertyNames->nullIdentifier;
1985         TreeFormalParameterList parameters = 0;
1986         TreeFunctionBody body = 0;
1987         int openBracePos = 0;
1988         int closeBracePos = 0;
1989         int bodyStartLine = 0;
1990         next();
1991         failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
1992         base = context.createFunctionExpr(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
1993     } else
1994         base = parsePrimaryExpression(context);
1995 
1996     failIfFalse(base);
1997     while (true) {
1998         switch (m_token.m_type) {
1999         case OPENBRACKET: {
2000             m_nonTrivialExpressionCount++;
2001             int expressionEnd = lastTokenEnd();
2002             next();
2003             int nonLHSCount = m_nonLHSCount;
2004             int initialAssignments = m_assignmentCount;
2005             TreeExpression property = parseExpression(context);
2006             failIfFalse(property);
2007             base = context.createBracketAccess(base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd());
2008             if (!consume(CLOSEBRACKET))
2009                 fail();
2010             m_nonLHSCount = nonLHSCount;
2011             break;
2012         }
2013         case OPENPAREN: {
2014             m_nonTrivialExpressionCount++;
2015             if (newCount) {
2016                 newCount--;
2017                 if (match(OPENPAREN)) {
2018                     int exprEnd = lastTokenEnd();
2019                     TreeArguments arguments = parseArguments(context);
2020                     failIfFalse(arguments);
2021                     base = context.createNewExpr(base, arguments, start, exprEnd, lastTokenEnd());
2022                 } else
2023                     base = context.createNewExpr(base, start, lastTokenEnd());
2024             } else {
2025                 int nonLHSCount = m_nonLHSCount;
2026                 int expressionEnd = lastTokenEnd();
2027                 TreeArguments arguments = parseArguments(context);
2028                 failIfFalse(arguments);
2029                 base = context.makeFunctionCallNode(base, arguments, expressionStart, expressionEnd, lastTokenEnd());
2030                 m_nonLHSCount = nonLHSCount;
2031             }
2032             break;
2033         }
2034         case DOT: {
2035             m_nonTrivialExpressionCount++;
2036             int expressionEnd = lastTokenEnd();
2037             next(Lexer::IgnoreReservedWords);
2038             matchOrFail(IDENT);
2039             base = context.createDotAccess(base, *m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd());
2040             next();
2041             break;
2042         }
2043         default:
2044             goto endMemberExpression;
2045         }
2046     }
2047 endMemberExpression:
2048     while (newCount--)
2049         base = context.createNewExpr(base, start, lastTokenEnd());
2050     return base;
2051 }
2052 
parseUnaryExpression(TreeBuilder & context)2053 template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeBuilder& context)
2054 {
2055     typename TreeBuilder::UnaryExprContext unaryExprContext(context);
2056     AllowInOverride allowInOverride(this);
2057     int tokenStackDepth = 0;
2058     bool modifiesExpr = false;
2059     bool requiresLExpr = false;
2060     while (isUnaryOp(m_token.m_type)) {
2061         if (strictMode()) {
2062             switch (m_token.m_type) {
2063             case PLUSPLUS:
2064             case MINUSMINUS:
2065             case AUTOPLUSPLUS:
2066             case AUTOMINUSMINUS:
2067                 failIfTrue(requiresLExpr);
2068                 modifiesExpr = true;
2069                 requiresLExpr = true;
2070                 break;
2071             case DELETETOKEN:
2072                 failIfTrue(requiresLExpr);
2073                 requiresLExpr = true;
2074                 break;
2075             default:
2076                 failIfTrue(requiresLExpr);
2077                 break;
2078             }
2079         }
2080         m_nonLHSCount++;
2081         context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart());
2082         next();
2083         m_nonTrivialExpressionCount++;
2084     }
2085     int subExprStart = tokenStart();
2086     TreeExpression expr = parseMemberExpression(context);
2087     failIfFalse(expr);
2088     bool isEvalOrArguments = false;
2089     if (strictMode() && !m_syntaxAlreadyValidated) {
2090         if (context.isResolve(expr)) {
2091             isEvalOrArguments = *m_lastIdentifier == m_globalData->propertyNames->eval || *m_lastIdentifier == m_globalData->propertyNames->arguments;
2092         }
2093     }
2094     failIfTrueIfStrict(isEvalOrArguments && modifiesExpr);
2095     switch (m_token.m_type) {
2096     case PLUSPLUS:
2097         m_nonTrivialExpressionCount++;
2098         m_nonLHSCount++;
2099         expr = context.makePostfixNode(expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd());
2100         m_assignmentCount++;
2101         failIfTrueIfStrict(isEvalOrArguments);
2102         failIfTrueIfStrict(requiresLExpr);
2103         next();
2104         break;
2105     case MINUSMINUS:
2106         m_nonTrivialExpressionCount++;
2107         m_nonLHSCount++;
2108         expr = context.makePostfixNode(expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd());
2109         m_assignmentCount++;
2110         failIfTrueIfStrict(isEvalOrArguments);
2111         failIfTrueIfStrict(requiresLExpr);
2112         next();
2113         break;
2114     default:
2115         break;
2116     }
2117 
2118     int end = lastTokenEnd();
2119 
2120     if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
2121         return expr;
2122 
2123     while (tokenStackDepth) {
2124         switch (context.unaryTokenStackLastType(tokenStackDepth)) {
2125         case EXCLAMATION:
2126             expr = context.createLogicalNot(expr);
2127             break;
2128         case TILDE:
2129             expr = context.makeBitwiseNotNode(expr);
2130             break;
2131         case MINUS:
2132             expr = context.makeNegateNode(expr);
2133             break;
2134         case PLUS:
2135             expr = context.createUnaryPlus(expr);
2136             break;
2137         case PLUSPLUS:
2138         case AUTOPLUSPLUS:
2139             expr = context.makePrefixNode(expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
2140             m_assignmentCount++;
2141             break;
2142         case MINUSMINUS:
2143         case AUTOMINUSMINUS:
2144             expr = context.makePrefixNode(expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
2145             m_assignmentCount++;
2146             break;
2147         case TYPEOF:
2148             expr = context.makeTypeOfNode(expr);
2149             break;
2150         case VOIDTOKEN:
2151             expr = context.createVoid(expr);
2152             break;
2153         case DELETETOKEN:
2154             failIfTrueIfStrict(context.isResolve(expr));
2155             expr = context.makeDeleteNode(expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
2156             break;
2157         default:
2158             // If we get here something has gone horribly horribly wrong
2159             CRASH();
2160         }
2161         subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
2162         context.unaryTokenStackRemoveLast(tokenStackDepth);
2163     }
2164     return expr;
2165 }
2166 
2167 }
2168 
2169 namespace WTF
2170 {
2171     template <> struct VectorTraits<JSC::JSParser::Scope> : SimpleClassVectorTraits {
2172         static const bool canInitializeWithMemset = false; // Not all Scope data members initialize to 0.
2173     };
2174 }
2175