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(¶meters->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