diff options
Diffstat (limited to 'Source/JavaScriptCore/parser/Parser.h')
-rw-r--r-- | Source/JavaScriptCore/parser/Parser.h | 709 |
1 files changed, 147 insertions, 562 deletions
diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h index c2e6a6504..b698ef936 100644 --- a/Source/JavaScriptCore/parser/Parser.h +++ b/Source/JavaScriptCore/parser/Parser.h @@ -31,14 +31,13 @@ #include "Nodes.h" #include "ParserArena.h" #include "ParserError.h" -#include "ParserFunctionInfo.h" #include "ParserTokens.h" #include "SourceProvider.h" #include "SourceProviderCache.h" #include "SourceProviderCacheItem.h" -#include "VariableEnvironment.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> namespace JSC { struct Scope; @@ -53,7 +52,7 @@ template <> struct VectorTraits<JSC::Scope> : SimpleClassVectorTraits { namespace JSC { class ExecState; -class FunctionMetadataNode; +class FunctionBodyNode; class FunctionParameters; class Identifier; class VM; @@ -67,95 +66,54 @@ class SourceCode; #define TreeSourceElements typename TreeBuilder::SourceElements #define TreeClause typename TreeBuilder::Clause #define TreeClauseList typename TreeBuilder::ClauseList +#define TreeConstDeclList typename TreeBuilder::ConstDeclList #define TreeArguments typename TreeBuilder::Arguments #define TreeArgumentsList typename TreeBuilder::ArgumentsList #define TreeFunctionBody typename TreeBuilder::FunctionBody -#if ENABLE(ES6_CLASS_SYNTAX) -#define TreeClassExpression typename TreeBuilder::ClassExpression -#endif #define TreeProperty typename TreeBuilder::Property #define TreePropertyList typename TreeBuilder::PropertyList -#define TreeDestructuringPattern typename TreeBuilder::DestructuringPattern +#define TreeDeconstructionPattern typename TreeBuilder::DeconstructionPattern COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens); enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode }; -enum FunctionParseType { StandardFunctionParseType, ArrowFunctionParseType }; -enum FunctionBodyType { ArrowFunctionBodyExpression, ArrowFunctionBodyBlock, StandardFunctionBodyBlock }; enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName }; - -enum DestructuringKind { - DestructureToVariables, - DestructureToLet, - DestructureToConst, - DestructureToParameters, - DestructureToExpressions -}; - -enum class DeclarationType { - VarDeclaration, - LetDeclaration, - ConstDeclaration -}; - -enum class DeclarationImportType { - Imported, - NotImported +enum FunctionParseMode { FunctionMode, GetterMode, SetterMode }; +enum DeconstructionKind { + DeconstructToVariables, + DeconstructToParameters, + DeconstructToExpressions }; -enum DeclarationResult { - Valid = 0, - InvalidStrictMode = 1 << 0, - InvalidDuplicateDeclaration = 1 << 1 -}; - -typedef uint8_t DeclarationResultMask; - - template <typename T> inline bool isEvalNode() { return false; } template <> inline bool isEvalNode<EvalNode>() { return true; } -struct ScopeLabelInfo { - UniquedStringImpl* uid; - bool isLoop; -}; - -ALWAYS_INLINE static bool isArguments(const VM* vm, const Identifier* ident) -{ - return vm->propertyNames->arguments == *ident; -} -ALWAYS_INLINE static bool isEval(const VM* vm, const Identifier* ident) -{ - return vm->propertyNames->eval == *ident; -} -ALWAYS_INLINE static bool isEvalOrArgumentsIdentifier(const VM* vm, const Identifier* ident) -{ - return isEval(vm, ident) || isArguments(vm, ident); -} -ALWAYS_INLINE static bool isIdentifierOrKeyword(const JSToken& token) -{ - return token.m_type == IDENT || token.m_type & KeywordTokenFlag; -} - -class ModuleScopeData : public RefCounted<ModuleScopeData> { -public: - static Ref<ModuleScopeData> create() { return adoptRef(*new ModuleScopeData); } - - const IdentifierSet& exportedBindings() const { return m_exportedBindings; } - - bool exportName(const Identifier& exportedName) +struct DepthManager { + DepthManager(int* depth) + : m_originalDepth(*depth) + , m_depth(depth) { - return m_exportedNames.add(exportedName.impl()).isNewEntry; } - void exportBinding(const Identifier& localName) + ~DepthManager() { - m_exportedBindings.add(localName.impl()); + *m_depth = m_originalDepth; } private: - IdentifierSet m_exportedNames { }; - IdentifierSet m_exportedBindings { }; + int m_originalDepth; + int* m_depth; +}; + +struct ScopeLabelInfo { + ScopeLabelInfo(StringImpl* ident, bool isLoop) + : m_ident(ident) + , m_isLoop(isLoop) + { + } + + StringImpl* m_ident; + bool m_isLoop; }; struct Scope { @@ -164,13 +122,9 @@ struct Scope { , m_shadowsArguments(false) , m_usesEval(false) , m_needsFullActivation(false) - , m_hasDirectSuper(false) - , m_needsSuperBinding(false) - , m_allowsVarDeclarations(true) - , m_allowsLexicalDeclarations(true) + , m_allowsNewDecls(true) , m_strictMode(strictMode) , m_isFunction(isFunction) - , m_isLexicalScope(false) , m_isFunctionBoundary(false) , m_isValidStrictMode(true) , m_loopDepth(0) @@ -183,26 +137,21 @@ struct Scope { , m_shadowsArguments(rhs.m_shadowsArguments) , m_usesEval(rhs.m_usesEval) , m_needsFullActivation(rhs.m_needsFullActivation) - , m_hasDirectSuper(rhs.m_hasDirectSuper) - , m_needsSuperBinding(rhs.m_needsSuperBinding) - , m_allowsVarDeclarations(rhs.m_allowsVarDeclarations) - , m_allowsLexicalDeclarations(rhs.m_allowsLexicalDeclarations) + , m_allowsNewDecls(rhs.m_allowsNewDecls) , m_strictMode(rhs.m_strictMode) , m_isFunction(rhs.m_isFunction) - , m_isLexicalScope(rhs.m_isLexicalScope) , m_isFunctionBoundary(rhs.m_isFunctionBoundary) , m_isValidStrictMode(rhs.m_isValidStrictMode) , m_loopDepth(rhs.m_loopDepth) , m_switchDepth(rhs.m_switchDepth) - , m_moduleScopeData(rhs.m_moduleScopeData) { if (rhs.m_labels) { - m_labels = std::make_unique<LabelStack>(); + m_labels = adoptPtr(new LabelStack); typedef LabelStack::const_iterator iterator; iterator end = rhs.m_labels->end(); for (iterator it = rhs.m_labels->begin(); it != end; ++it) - m_labels->append(ScopeLabelInfo { it->uid, it->isLoop }); + m_labels->append(ScopeLabelInfo(it->m_ident, it->m_isLoop)); } } @@ -217,8 +166,8 @@ struct Scope { void pushLabel(const Identifier* label, bool isLoop) { if (!m_labels) - m_labels = std::make_unique<LabelStack>(); - m_labels->append(ScopeLabelInfo { label->impl(), isLoop }); + m_labels = adoptPtr(new LabelStack); + m_labels->append(ScopeLabelInfo(label->impl(), isLoop)); } void popLabel() @@ -233,7 +182,7 @@ struct Scope { if (!m_labels) return 0; for (int i = m_labels->size(); i > 0; i--) { - if (m_labels->at(i - 1).uid == label->impl()) + if (m_labels->at(i - 1).m_ident == label->impl()) return &m_labels->at(i - 1); } return 0; @@ -243,130 +192,31 @@ struct Scope { { m_isFunction = true; m_isFunctionBoundary = true; - setIsLexicalScope(); - } - - void setIsModule() - { - m_moduleScopeData = ModuleScopeData::create(); - } - - bool isFunction() const { return m_isFunction; } - bool isFunctionBoundary() const { return m_isFunctionBoundary; } - - void setIsLexicalScope() - { - m_isLexicalScope = true; - m_allowsLexicalDeclarations = true; - } - bool isLexicalScope() { return m_isLexicalScope; } - - VariableEnvironment& declaredVariables() { return m_declaredVariables; } - VariableEnvironment& lexicalVariables() { return m_lexicalVariables; } - VariableEnvironment& finalizeLexicalEnvironment() - { - if (m_usesEval || m_needsFullActivation) - m_lexicalVariables.markAllVariablesAsCaptured(); - else - computeLexicallyCapturedVariablesAndPurgeCandidates(); - - return m_lexicalVariables; - } - - ModuleScopeData& moduleScopeData() const - { - ASSERT(m_moduleScopeData); - return *m_moduleScopeData; - } - - void computeLexicallyCapturedVariablesAndPurgeCandidates() - { - // Because variables may be defined at any time in the range of a lexical scope, we must - // track lexical variables that might be captured. Then, when we're preparing to pop the top - // lexical scope off the stack, we should find which variables are truly captured, and which - // variable still may be captured in a parent scope. - if (m_lexicalVariables.size() && m_closedVariableCandidates.size()) { - auto end = m_closedVariableCandidates.end(); - for (auto iter = m_closedVariableCandidates.begin(); iter != end; ++iter) - m_lexicalVariables.markVariableAsCapturedIfDefined(iter->get()); - } - - // We can now purge values from the captured candidates because they're captured in this scope. - { - for (auto entry : m_lexicalVariables) { - if (entry.value.isCaptured()) - m_closedVariableCandidates.remove(entry.key); - } - } } + bool isFunction() { return m_isFunction; } + bool isFunctionBoundary() { return m_isFunctionBoundary; } void declareCallee(const Identifier* ident) { - auto addResult = m_declaredVariables.add(ident->impl()); - // We want to track if callee is captured, but we don't want to act like it's a 'var' - // because that would cause the BytecodeGenerator to emit bad code. - addResult.iterator->value.clearIsVar(); + m_declaredVariables.add(ident->string().impl()); } - DeclarationResultMask declareVariable(const Identifier* ident) + bool declareVariable(const Identifier* ident) { - ASSERT(m_allowsVarDeclarations); - DeclarationResultMask result = DeclarationResult::Valid; - bool isValidStrictMode = !isEvalOrArgumentsIdentifier(m_vm, ident); + bool isValidStrictMode = m_vm->propertyNames->eval != *ident && m_vm->propertyNames->arguments != *ident; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; - auto addResult = m_declaredVariables.add(ident->impl()); - addResult.iterator->value.setIsVar(); - if (!isValidStrictMode) - result |= DeclarationResult::InvalidStrictMode; - return result; - } - - DeclarationResultMask declareLexicalVariable(const Identifier* ident, bool isConstant, DeclarationImportType importType = DeclarationImportType::NotImported) - { - ASSERT(m_allowsLexicalDeclarations); - DeclarationResultMask result = DeclarationResult::Valid; - bool isValidStrictMode = !isEvalOrArgumentsIdentifier(m_vm, ident); - m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; - auto addResult = m_lexicalVariables.add(ident->impl()); - if (isConstant) - addResult.iterator->value.setIsConst(); - else - addResult.iterator->value.setIsLet(); - - if (importType == DeclarationImportType::Imported) - addResult.iterator->value.setIsImported(); - - if (!addResult.isNewEntry) - result |= DeclarationResult::InvalidDuplicateDeclaration; - if (!isValidStrictMode) - result |= DeclarationResult::InvalidStrictMode; - - return result; + m_declaredVariables.add(ident->string().impl()); + return isValidStrictMode; } bool hasDeclaredVariable(const Identifier& ident) { - return hasDeclaredVariable(ident.impl()); - } - - bool hasDeclaredVariable(const RefPtr<UniquedStringImpl>& ident) - { - return m_declaredVariables.contains(ident.get()); - } - - bool hasLexicallyDeclaredVariable(const RefPtr<UniquedStringImpl>& ident) const - { - return m_lexicalVariables.contains(ident.get()); + return m_declaredVariables.contains(ident.impl()); } - ALWAYS_INLINE bool hasDeclaredParameter(const Identifier& ident) + bool hasDeclaredParameter(const Identifier& ident) { - return hasDeclaredParameter(ident.impl()); - } - - bool hasDeclaredParameter(const RefPtr<UniquedStringImpl>& ident) - { - return m_declaredParameters.contains(ident) || m_declaredVariables.contains(ident.get()); + return m_declaredParameters.contains(ident.impl()) || m_declaredVariables.contains(ident.impl()); } void declareWrite(const Identifier* ident) @@ -375,33 +225,19 @@ struct Scope { m_writtenVariables.add(ident->impl()); } - void preventAllVariableDeclarations() - { - m_allowsVarDeclarations = false; - m_allowsLexicalDeclarations = false; - } - void preventVarDeclarations() { m_allowsVarDeclarations = false; } - bool allowsVarDeclarations() const { return m_allowsVarDeclarations; } - bool allowsLexicalDeclarations() const { return m_allowsLexicalDeclarations; } + void preventNewDecls() { m_allowsNewDecls = false; } + bool allowsNewDecls() const { return m_allowsNewDecls; } - DeclarationResultMask declareParameter(const Identifier* ident) + bool declareParameter(const Identifier* ident) { - ASSERT(m_allowsVarDeclarations); - DeclarationResultMask result = DeclarationResult::Valid; - bool isArgumentsIdent = isArguments(m_vm, ident); - auto addResult = m_declaredVariables.add(ident->impl()); - addResult.iterator->value.clearIsVar(); - bool isValidStrictMode = addResult.isNewEntry && m_vm->propertyNames->eval != *ident && !isArgumentsIdent; + bool isArguments = m_vm->propertyNames->arguments == *ident; + bool isValidStrictMode = m_declaredVariables.add(ident->string().impl()).isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; - m_declaredParameters.add(ident->impl()); - if (!isValidStrictMode) - result |= DeclarationResult::InvalidStrictMode; - if (isArgumentsIdent) - m_shadowsArguments = true; - if (!addResult.isNewEntry) - result |= DeclarationResult::InvalidDuplicateDeclaration; + m_declaredParameters.add(ident->string().impl()); - return result; + if (isArguments) + m_shadowsArguments = true; + return isValidStrictMode; } enum BindingResult { @@ -411,104 +247,67 @@ struct Scope { }; BindingResult declareBoundParameter(const Identifier* ident) { - bool isArgumentsIdent = isArguments(m_vm, ident); - auto addResult = m_declaredVariables.add(ident->impl()); - addResult.iterator->value.setIsVar(); // Treat destructuring parameters as "var"s. - bool isValidStrictMode = addResult.isNewEntry && !isEval(m_vm, ident) && !isArgumentsIdent; + bool isArguments = m_vm->propertyNames->arguments == *ident; + bool newEntry = m_declaredVariables.add(ident->string().impl()).isNewEntry; + bool isValidStrictMode = newEntry && m_vm->propertyNames->eval != *ident && !isArguments; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; - if (isArgumentsIdent) + if (isArguments) m_shadowsArguments = true; - if (!addResult.isNewEntry) + if (!newEntry) return BindingFailed; return isValidStrictMode ? BindingSucceeded : StrictBindingFailed; } - void getUsedVariables(IdentifierSet& usedVariables) - { - usedVariables.swap(m_usedVariables); - } void useVariable(const Identifier* ident, bool isEval) { m_usesEval |= isEval; - m_usedVariables.add(ident->impl()); + m_usedVariables.add(ident->string().impl()); } void setNeedsFullActivation() { m_needsFullActivation = true; } - bool needsFullActivation() const { return m_needsFullActivation; } - -#if ENABLE(ES6_CLASS_SYNTAX) - bool hasDirectSuper() { return m_hasDirectSuper; } -#else - bool hasDirectSuper() { return false; } -#endif - void setHasDirectSuper() { m_hasDirectSuper = true; } - -#if ENABLE(ES6_CLASS_SYNTAX) - bool needsSuperBinding() { return m_needsSuperBinding; } -#else - bool needsSuperBinding() { return false; } -#endif - void setNeedsSuperBinding() { m_needsSuperBinding = true; } - void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) + bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) { if (nestedScope->m_usesEval) m_usesEval = true; - - { - IdentifierSet::iterator end = nestedScope->m_usedVariables.end(); - for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) { - if (nestedScope->m_declaredVariables.contains(*ptr) || nestedScope->m_lexicalVariables.contains(*ptr)) - continue; - m_usedVariables.add(*ptr); - // We don't want a declared variable that is used in an inner scope to be thought of as captured if - // that inner scope is both a lexical scope and not a function. Only inner functions and "catch" - // statements can cause variables to be captured. - if (shouldTrackClosedVariables && (nestedScope->m_isFunctionBoundary || !nestedScope->m_isLexicalScope)) - m_closedVariableCandidates.add(*ptr); - } - } - // Propagate closed variable candidates downwards within the same function. - // Cross function captures will be realized via m_usedVariables propagation. - if (shouldTrackClosedVariables && !nestedScope->m_isFunctionBoundary && nestedScope->m_closedVariableCandidates.size()) { - IdentifierSet::iterator end = nestedScope->m_closedVariableCandidates.end(); - IdentifierSet::iterator begin = nestedScope->m_closedVariableCandidates.begin(); - m_closedVariableCandidates.add(begin, end); + IdentifierSet::iterator end = nestedScope->m_usedVariables.end(); + for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) { + if (nestedScope->m_declaredVariables.contains(*ptr)) + continue; + m_usedVariables.add(*ptr); + if (shouldTrackClosedVariables) + m_closedVariables.add(*ptr); } - if (nestedScope->m_writtenVariables.size()) { IdentifierSet::iterator end = nestedScope->m_writtenVariables.end(); for (IdentifierSet::iterator ptr = nestedScope->m_writtenVariables.begin(); ptr != end; ++ptr) { - if (nestedScope->m_declaredVariables.contains(*ptr) || nestedScope->m_lexicalVariables.contains(*ptr)) + if (nestedScope->m_declaredVariables.contains(*ptr)) continue; m_writtenVariables.add(*ptr); } } + + return true; } - - void getCapturedVars(IdentifierSet& capturedVariables, bool& modifiedParameter, bool& modifiedArguments) + + void getCapturedVariables(IdentifierSet& capturedVariables, bool& modifiedParameter) { if (m_needsFullActivation || m_usesEval) { modifiedParameter = true; - for (auto& entry : m_declaredVariables) - capturedVariables.add(entry.key); + capturedVariables.swap(m_declaredVariables); return; } - for (IdentifierSet::iterator ptr = m_closedVariableCandidates.begin(); ptr != m_closedVariableCandidates.end(); ++ptr) { + for (IdentifierSet::iterator ptr = m_closedVariables.begin(); ptr != m_closedVariables.end(); ++ptr) { if (!m_declaredVariables.contains(*ptr)) continue; capturedVariables.add(*ptr); } modifiedParameter = false; - if (shadowsArguments()) - modifiedArguments = true; if (m_declaredParameters.size()) { IdentifierSet::iterator end = m_writtenVariables.end(); for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) { - if (*ptr == m_vm->propertyNames->arguments.impl()) - modifiedArguments = true; if (!m_declaredParameters.contains(*ptr)) continue; modifiedParameter = true; @@ -521,11 +320,11 @@ struct Scope { bool isValidStrictMode() const { return m_isValidStrictMode; } bool shadowsArguments() const { return m_shadowsArguments; } - void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<UniquedStringImpl>>& vector) + void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl>>& vector) { IdentifierSet::iterator end = capturedVariables.end(); for (IdentifierSet::iterator it = capturedVariables.begin(); it != end; ++it) { - if (m_declaredVariables.contains(*it) || m_lexicalVariables.contains(*it)) + if (m_declaredVariables.contains(*it)) continue; vector.append(*it); } @@ -558,27 +357,21 @@ private: bool m_shadowsArguments : 1; bool m_usesEval : 1; bool m_needsFullActivation : 1; - bool m_hasDirectSuper : 1; - bool m_needsSuperBinding : 1; - bool m_allowsVarDeclarations : 1; - bool m_allowsLexicalDeclarations : 1; + bool m_allowsNewDecls : 1; bool m_strictMode : 1; bool m_isFunction : 1; - bool m_isLexicalScope : 1; bool m_isFunctionBoundary : 1; bool m_isValidStrictMode : 1; int m_loopDepth; int m_switchDepth; typedef Vector<ScopeLabelInfo, 2> LabelStack; - std::unique_ptr<LabelStack> m_labels; + OwnPtr<LabelStack> m_labels; IdentifierSet m_declaredParameters; - VariableEnvironment m_declaredVariables; - VariableEnvironment m_lexicalVariables; + IdentifierSet m_declaredVariables; IdentifierSet m_usedVariables; - IdentifierSet m_closedVariableCandidates; + IdentifierSet m_closedVariables; IdentifierSet m_writtenVariables; - RefPtr<ModuleScopeData> m_moduleScopeData { }; }; typedef Vector<Scope, 10> ScopeStack; @@ -614,17 +407,13 @@ class Parser { WTF_MAKE_FAST_ALLOCATED; public: - Parser( - VM*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, SourceParseMode, - ConstructorKind defaultConstructorKind = ConstructorKind::None, ThisTDZMode = ThisTDZMode::CheckIfNeeded); + Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode); ~Parser(); template <class ParsedNode> - std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode); + PassRefPtr<ParsedNode> parse(ParserError&); JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); } - JSTokenLocation locationBeforeLastToken() const { return m_lexer->lastTokenLocation(); } - Vector<RefPtr<UniquedStringImpl>>&& closedVariables() { return WTF::move(m_closedVariables); } private: struct AllowInOverride { @@ -664,74 +453,6 @@ private: Parser* m_parser; }; - struct AutoCleanupLexicalScope { - // We can allocate this object on the stack without actually knowing beforehand if we're - // going to create a new lexical scope. If we decide to create a new lexical scope, we - // can pass the scope into this obejct and it will take care of the cleanup for us if the parse fails. - // This is helpful if we may fail from syntax errors after creating a lexical scope conditionally. - AutoCleanupLexicalScope() - : m_scope(nullptr, UINT_MAX) - , m_parser(nullptr) - { - } - - ~AutoCleanupLexicalScope() - { - // This should only ever be called if we fail from a syntax error. Otherwise - // it's the intention that a user of this class pops this scope manually on a - // successful parse. - if (isValid()) - m_parser->popScope(*this, false); - } - - void setIsValid(ScopeRef& scope, Parser* parser) - { - RELEASE_ASSERT(scope->isLexicalScope()); - m_scope = scope; - m_parser = parser; - } - - bool isValid() const { return !!m_parser; } - - void setPopped() - { - m_parser = nullptr; - } - - ScopeRef& scope() { return m_scope; } - - private: - ScopeRef m_scope; - Parser* m_parser; - }; - - ALWAYS_INLINE DestructuringKind destructuringKindFromDeclarationType(DeclarationType type) - { - switch (type) { - case DeclarationType::VarDeclaration: - return DestructureToVariables; - case DeclarationType::LetDeclaration: - return DestructureToLet; - case DeclarationType::ConstDeclaration: - return DestructureToConst; - } - - RELEASE_ASSERT_NOT_REACHED(); - return DestructureToVariables; - } - - ALWAYS_INLINE AssignmentContext assignmentContextFromDeclarationType(DeclarationType type) - { - switch (type) { - case DeclarationType::ConstDeclaration: - return AssignmentContext::ConstDeclarationStatement; - default: - return AssignmentContext::DeclarationStatement; - } - } - - ALWAYS_INLINE bool isEvalOrArguments(const Identifier* ident) { return isEvalOrArgumentsIdentifier(m_vm, ident); } - ScopeRef currentScope() { return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); @@ -749,79 +470,53 @@ private: return currentScope(); } - void popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables) + bool popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables) { ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1); ASSERT(m_scopeStack.size() > 1); - m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); - if (!m_scopeStack.last().isFunctionBoundary() && m_scopeStack.last().needsFullActivation()) - m_scopeStack[m_scopeStack.size() - 2].setNeedsFullActivation(); + bool result = m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); m_scopeStack.removeLast(); + return result; } - ALWAYS_INLINE void popScope(ScopeRef& scope, bool shouldTrackClosedVariables) + bool popScope(ScopeRef& scope, bool shouldTrackClosedVariables) { - popScopeInternal(scope, shouldTrackClosedVariables); + return popScopeInternal(scope, shouldTrackClosedVariables); } - ALWAYS_INLINE void popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables) + bool popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables) { scope.setPopped(); - popScopeInternal(scope, shouldTrackClosedVariables); - } - - ALWAYS_INLINE void popScope(AutoCleanupLexicalScope& cleanupScope, bool shouldTrackClosedVariables) - { - RELEASE_ASSERT(cleanupScope.isValid()); - ScopeRef& scope = cleanupScope.scope(); - cleanupScope.setPopped(); - popScopeInternal(scope, shouldTrackClosedVariables); + return popScopeInternal(scope, shouldTrackClosedVariables); } - DeclarationResultMask declareVariable(const Identifier* ident, DeclarationType type = DeclarationType::VarDeclaration, DeclarationImportType importType = DeclarationImportType::NotImported) + bool declareVariable(const Identifier* ident) { unsigned i = m_scopeStack.size() - 1; ASSERT(i < m_scopeStack.size()); - - if (type == DeclarationType::VarDeclaration) { - while (!m_scopeStack[i].allowsVarDeclarations()) { - i--; - ASSERT(i < m_scopeStack.size()); - } - - return m_scopeStack[i].declareVariable(ident); - } - - ASSERT(type == DeclarationType::LetDeclaration || type == DeclarationType::ConstDeclaration); - - // Lexical variables declared at a top level scope that shadow arguments or vars are not allowed. - if (m_statementDepth == 1 && (hasDeclaredParameter(*ident) || hasDeclaredVariable(*ident))) - return DeclarationResult::InvalidDuplicateDeclaration; - - while (!m_scopeStack[i].allowsLexicalDeclarations()) { + while (!m_scopeStack[i].allowsNewDecls()) { i--; ASSERT(i < m_scopeStack.size()); } - - return m_scopeStack[i].declareLexicalVariable(ident, type == DeclarationType::ConstDeclaration, importType); + return m_scopeStack[i].declareVariable(ident); } NEVER_INLINE bool hasDeclaredVariable(const Identifier& ident) { unsigned i = m_scopeStack.size() - 1; ASSERT(i < m_scopeStack.size()); - while (!m_scopeStack[i].allowsVarDeclarations()) { + while (!m_scopeStack[i].allowsNewDecls()) { i--; ASSERT(i < m_scopeStack.size()); } return m_scopeStack[i].hasDeclaredVariable(ident); } - + NEVER_INLINE bool hasDeclaredParameter(const Identifier& ident) { unsigned i = m_scopeStack.size() - 1; ASSERT(i < m_scopeStack.size()); - while (!m_scopeStack[i].allowsVarDeclarations()) { + while (!m_scopeStack[i].allowsNewDecls()) { i--; ASSERT(i < m_scopeStack.size()); } @@ -833,13 +528,7 @@ private: if (!m_syntaxAlreadyValidated || strictMode()) m_scopeStack.last().declareWrite(ident); } - - bool exportName(const Identifier& ident) - { - ASSERT(currentScope().index() == 0); - return currentScope()->moduleScopeData().exportName(ident); - } - + ScopeStack m_scopeStack; const SourceProviderCacheItem* findCachedFunctionInfo(int openBracePos) @@ -848,13 +537,14 @@ private: } Parser(); - String parseInner(const Identifier&, SourceParseMode); + String parseInner(); - void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&, VariableEnvironment&, CodeFeatures, int, const Vector<RefPtr<UniquedStringImpl>>&&); + void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, + ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, int, IdentifierSet&); // Used to determine type of error to report. - bool isFunctionMetadataNode(ScopeNode*) { return false; } - bool isFunctionMetadataNode(FunctionMetadataNode*) { return true; } + bool isFunctionBodyNode(ScopeNode*) { return false; } + bool isFunctionBodyNode(FunctionBodyNode*) { return true; } ALWAYS_INLINE void next(unsigned lexerFlags = 0) { @@ -900,57 +590,9 @@ private: return m_token.m_type == expected; } - ALWAYS_INLINE bool matchContextualKeyword(const Identifier& identifier) - { - return m_token.m_type == IDENT && *m_token.m_data.ident == identifier; - } - - ALWAYS_INLINE bool matchIdentifierOrKeyword() + ALWAYS_INLINE bool isofToken() { - return isIdentifierOrKeyword(m_token); - } - - ALWAYS_INLINE bool isEndOfArrowFunction() - { - return match(SEMICOLON) || match(COMMA) || match(CLOSEPAREN) || match(CLOSEBRACE) || match(CLOSEBRACKET) || match(EOFTOK) || m_lexer->prevTerminator(); - } - - ALWAYS_INLINE bool isArrowFunctionParamters() - { -#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) - bool isArrowFunction = false; - - if (match(EOFTOK)) - return isArrowFunction; - - SavePoint saveArrowFunctionPoint = createSavePoint(); - - if (consume(OPENPAREN)) { - bool isArrowFunctionParamters = true; - - while (consume(IDENT)) { - if (consume(COMMA)) { - if (!match(IDENT)) { - isArrowFunctionParamters = false; - break; - } - } else - break; - } - - if (isArrowFunctionParamters) { - if (consume(CLOSEPAREN) && match(ARROWFUNCTION)) - isArrowFunction = true; - } - } else if (consume(IDENT) && match(ARROWFUNCTION)) - isArrowFunction = true; - - restoreSavePoint(saveArrowFunctionPoint); - - return isArrowFunction; -#else - return false; -#endif + return m_token.m_type == IDENT && *m_token.m_data.ident == m_vm->propertyNames->of; } ALWAYS_INLINE unsigned tokenStart() @@ -988,9 +630,9 @@ private: return m_token.m_location; } - void setErrorMessage(const String& message) + void setErrorMessage(String msg) { - m_errorMessage = message; + m_errorMessage = msg; } NEVER_INLINE void logError(bool); @@ -1002,9 +644,9 @@ private: 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&); 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&); - NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMessage, const String& name, const char* afterMessage) + NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMsg, String name, const char* afterMsg) { - m_errorMessage = makeString(beforeMessage, " '", name, "' ", afterMessage); + m_errorMessage = makeString(beforeMsg, " '", name, "' ", afterMsg); } NEVER_INLINE void updateErrorMessage(const char* msg) @@ -1021,7 +663,7 @@ private: void setStrictMode() { currentScope()->setStrictMode(); } bool strictMode() { return currentScope()->strictMode(); } bool isValidStrictMode() { return currentScope()->isValidStrictMode(); } - DeclarationResultMask declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } + bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } Scope::BindingResult declareBoundParameter(const Identifier* ident) { return currentScope()->declareBoundParameter(ident); } bool breakIsValid() { @@ -1044,7 +686,7 @@ private: return true; } void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); } - void popLabel(ScopeRef scope) { scope->popLabel(); } + void popLabel() { currentScope()->popLabel(); } ScopeLabelInfo* getLabel(const Identifier* label) { ScopeRef current = currentScope(); @@ -1056,21 +698,12 @@ private: } return result; } - - ALWAYS_INLINE bool isLETMaskedAsIDENT() - { - return match(LET) && !strictMode(); - } - + template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode); - template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength); template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0); - enum class ExportType { Exported, NotExported }; -#if ENABLE(ES6_CLASS_SYNTAX) - template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported); -#endif - template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported); - template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType, ExportType = ExportType::NotExported); + template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&); + template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&); + template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&); template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&); template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&); template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&); @@ -1101,41 +734,15 @@ private: enum SpreadMode { AllowSpread, DontAllowSpread }; template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&, SpreadMode); template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict); - template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName); - template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind = ConstructorKind::None, SuperBinding = SuperBinding::NotNeeded); - template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, FunctionBodyType, unsigned, SourceParseMode); - template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, unsigned&); - enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext }; - template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType, ExportType, bool& forLoopConstDoesNotHaveInitializer); - template <class TreeBuilder> TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&); - template <class TreeBuilder> TreeExpression parseArrowFunctionExpression(TreeBuilder&); - template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier&, int depth, JSToken, AssignmentContext, const Identifier** duplicateIdentifier); - template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0); - template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&, AssignmentContext); - template <class TreeBuilder> NEVER_INLINE TreeExpression parseDefaultValueForDestructuringPattern(TreeBuilder&); - template <class TreeBuilder> TreeSourceElements parseModuleSourceElements(TreeBuilder&, SourceParseMode); - enum class ImportSpecifierType { NamespaceImport, NamedImport, DefaultImport }; - template <class TreeBuilder> typename TreeBuilder::ImportSpecifier parseImportClauseItem(TreeBuilder&, ImportSpecifierType); - template <class TreeBuilder> typename TreeBuilder::ModuleName parseModuleName(TreeBuilder&); - template <class TreeBuilder> TreeStatement parseImportDeclaration(TreeBuilder&); - template <class TreeBuilder> typename TreeBuilder::ExportSpecifier parseExportSpecifier(TreeBuilder& context, Vector<const Identifier*>& maybeLocalNames, bool& hasKeywordForLocalBindings); - template <class TreeBuilder> TreeStatement parseExportDeclaration(TreeBuilder&); - - template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionParseType); - - template <class TreeBuilder> NEVER_INLINE int parseFunctionParameters(TreeBuilder&, SourceParseMode, ParserFunctionInfo<TreeBuilder>&); - -#if ENABLE(ES6_CLASS_SYNTAX) - template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionRequirements, ParserClassInfo<TreeBuilder>&); -#endif - -#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX) - template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateString parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode, bool& elementIsTail); - template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateLiteral parseTemplateLiteral(TreeBuilder&, typename LexerType::RawStringsBuildMode); -#endif - - template <class TreeBuilder> ALWAYS_INLINE bool shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder&, const TreeProperty&); - + template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&); + template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&); + template <class TreeBuilder> TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd); + template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&); + + template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern createBindingPattern(TreeBuilder&, DeconstructionKind, const Identifier&, int depth); + template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&, DeconstructionKind, int depth = 0); + template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&); + template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn); ALWAYS_INLINE int isBinaryOperator(JSTokenType); bool allowAutomaticSemicolon(); @@ -1148,11 +755,6 @@ private: return allowAutomaticSemicolon(); } - void setEndOfStatement() - { - m_lexer->setTokenPosition(&m_token); - } - bool canRecurse() { return m_vm->isSafeToRecurse(); @@ -1221,9 +823,8 @@ private: VM* m_vm; const SourceCode* m_source; - ParserArena m_parserArena; - std::unique_ptr<LexerType> m_lexer; - FunctionParameters* m_parameters { nullptr }; + ParserArena* m_arena; + OwnPtr<LexerType> m_lexer; bool m_hasStackOverflow; String m_errorMessage; @@ -1239,12 +840,9 @@ private: const Identifier* m_lastFunctionName; RefPtr<SourceProviderCache> m_functionCache; SourceElements* m_sourceElements; - bool m_parsingBuiltin; - ConstructorKind m_defaultConstructorKind; - ThisTDZMode m_thisTDZMode; - VariableEnvironment m_varDeclarations; - DeclarationStacks::FunctionStack m_funcDeclarations; - Vector<RefPtr<UniquedStringImpl>> m_closedVariables; + ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; + ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; + IdentifierSet m_capturedVariables; CodeFeatures m_features; int m_numConstants; @@ -1269,13 +867,13 @@ private: template <typename LexerType> template <class ParsedNode> -std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode) +PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error) { int errLine; String errMsg; if (ParsedNode::scopeIsFunction) - m_lexer->setIsReparsingFunction(); + m_lexer->setIsReparsing(); m_sourceElements = 0; @@ -1286,7 +884,7 @@ std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const I ASSERT(m_source->startColumn() > 0); unsigned startColumn = m_source->startColumn() - 1; - String parseError = parseInner(calleeName, parseMode); + String parseError = parseInner(); int lineNumber = m_lexer->lineNumber(); bool lexError = m_lexer->sawError(); @@ -1300,28 +898,26 @@ std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const I m_sourceElements = 0; } - std::unique_ptr<ParsedNode> result; + RefPtr<ParsedNode> result; if (m_sourceElements) { JSTokenLocation endLocation; endLocation.line = m_lexer->lineNumber(); endLocation.lineStartOffset = m_lexer->currentLineStartOffset(); endLocation.startOffset = m_lexer->currentOffset(); unsigned endColumn = endLocation.startOffset - endLocation.lineStartOffset; - result = std::make_unique<ParsedNode>(m_parserArena, + result = ParsedNode::create(m_vm, startLocation, endLocation, startColumn, endColumn, m_sourceElements, - m_varDeclarations, - m_funcDeclarations, - currentScope()->finalizeLexicalEnvironment(), - m_parameters, + m_varDeclarations ? &m_varDeclarations->data : 0, + m_funcDeclarations ? &m_funcDeclarations->data : 0, + m_capturedVariables, *m_source, m_features, m_numConstants); result->setLoc(m_source->firstLine(), m_lexer->lineNumber(), m_lexer->currentOffset(), m_lexer->currentLineStartOffset()); - result->setEndOffset(m_lexer->currentOffset()); } else { // We can never see a syntax error when reparsing a function, since we should have // reported the error when parsing the containing program or eval code. So if we're @@ -1329,7 +925,7 @@ std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const I // we ran out of stack while parsing. If we see an error while parsing eval or program // code we assume that it was a syntax error since running out of stack is much less // likely, and we are currently unable to distinguish between the two cases. - if (isFunctionMetadataNode(static_cast<ParsedNode*>(0)) || m_hasStackOverflow) + if (isFunctionBodyNode(static_cast<ParsedNode*>(0)) || m_hasStackOverflow) error = ParserError(ParserError::StackOverflow, ParserError::SyntaxErrorNone, m_token); else { ParserError::SyntaxErrorType errorType = ParserError::SyntaxErrorIrrecoverable; @@ -1345,40 +941,29 @@ std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const I } } - return result; + m_arena->reset(); + + return result.release(); } template <class ParsedNode> -std::unique_ptr<ParsedNode> parse( - VM* vm, const SourceCode& source, - const Identifier& name, JSParserBuiltinMode builtinMode, - JSParserStrictMode strictMode, SourceParseMode parseMode, - ParserError& error, JSTextPosition* positionBeforeLastNewline = nullptr, - ConstructorKind defaultConstructorKind = ConstructorKind::None, - ThisTDZMode thisTDZMode = ThisTDZMode::CheckIfNeeded) +PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0) { SamplingRegion samplingRegion("Parsing"); ASSERT(!source.provider()->source().isNull()); if (source.provider()->source().is8Bit()) { - Parser<Lexer<LChar>> parser(vm, source, builtinMode, strictMode, parseMode, defaultConstructorKind, thisTDZMode); - std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error, name, parseMode); + Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode); + RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error); if (positionBeforeLastNewline) *positionBeforeLastNewline = parser.positionBeforeLastNewline(); - if (builtinMode == JSParserBuiltinMode::Builtin) { - if (!result) - WTF::dataLog("Error compiling builtin: ", error.message(), "\n"); - RELEASE_ASSERT(result); - result->setClosedVariables(parser.closedVariables()); - } - return result; + return result.release(); } - ASSERT_WITH_MESSAGE(defaultConstructorKind == ConstructorKind::None, "BuiltinExecutables::createDefaultConstructor should always use a 8-bit string"); - Parser<Lexer<UChar>> parser(vm, source, builtinMode, strictMode, parseMode, defaultConstructorKind, thisTDZMode); - std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error, name, parseMode); + Parser<Lexer<UChar>> parser(vm, source, parameters, name, strictness, parserMode); + RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error); if (positionBeforeLastNewline) *positionBeforeLastNewline = parser.positionBeforeLastNewline(); - return result; + return result.release(); } } // namespace |