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