| /* |
| * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) |
| * Copyright (C) 2001 Peter Kelly (pmk@post.com) |
| * Copyright (C) 2003-2009, 2013, 2016 Apple Inc. All rights reserved. |
| * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) |
| * Copyright (C) 2007 Maks Orlovich |
| * Copyright (C) 2007 Eric Seidel <eric@webkit.org> |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| * |
| */ |
| |
| #include "config.h" |
| #include "Nodes.h" |
| #include "NodeConstructors.h" |
| |
| #include "JSCInlines.h" |
| #include "ModuleScopeData.h" |
| #include <wtf/Assertions.h> |
| |
| namespace JSC { |
| |
| DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(ParserArenaRoot); |
| |
| // ------------------------------ StatementNode -------------------------------- |
| |
| void StatementNode::setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset) |
| { |
| m_lastLine = lastLine; |
| m_position = JSTextPosition(firstLine, startOffset, lineStartOffset); |
| ASSERT(m_position.offset >= m_position.lineStartOffset); |
| } |
| |
| // ------------------------------ SourceElements -------------------------------- |
| |
| void SourceElements::append(StatementNode* statement) |
| { |
| if (statement->isEmptyStatement()) |
| return; |
| |
| if (!m_head) { |
| m_head = statement; |
| m_tail = statement; |
| return; |
| } |
| |
| m_tail->setNext(statement); |
| m_tail = statement; |
| } |
| |
| StatementNode* SourceElements::singleStatement() const |
| { |
| return m_head == m_tail ? m_head : nullptr; |
| } |
| |
| StatementNode* SourceElements::lastStatement() const |
| { |
| return m_tail; |
| } |
| |
| bool SourceElements::hasCompletionValue() const |
| { |
| for (StatementNode* statement = m_head; statement; statement = statement->next()) { |
| if (statement->hasCompletionValue()) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| bool SourceElements::hasEarlyBreakOrContinue() const |
| { |
| for (StatementNode* statement = m_head; statement; statement = statement->next()) { |
| if (statement->isBreak() || statement->isContinue()) |
| return true; |
| if (statement->hasCompletionValue()) |
| return false; |
| } |
| |
| return false; |
| } |
| |
| // ------------------------------ BlockNode ------------------------------------ |
| |
| StatementNode* BlockNode::lastStatement() const |
| { |
| return m_statements ? m_statements->lastStatement() : nullptr; |
| } |
| |
| StatementNode* BlockNode::singleStatement() const |
| { |
| return m_statements ? m_statements->singleStatement() : nullptr; |
| } |
| |
| bool BlockNode::hasCompletionValue() const |
| { |
| return m_statements ? m_statements->hasCompletionValue() : false; |
| } |
| |
| bool BlockNode::hasEarlyBreakOrContinue() const |
| { |
| return m_statements ? m_statements->hasEarlyBreakOrContinue() : false; |
| } |
| |
| // ------------------------------ ScopeNode ----------------------------- |
| |
| ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, bool inStrictContext) |
| : StatementNode(endLocation) |
| , ParserArenaRoot(parserArena) |
| , m_startLineNumber(startLocation.line) |
| , m_startStartOffset(startLocation.startOffset) |
| , m_startLineStartOffset(startLocation.lineStartOffset) |
| , m_features(inStrictContext ? StrictModeFeature : NoFeatures) |
| , m_innerArrowFunctionCodeFeatures(NoInnerArrowFunctionFeatures) |
| , m_numConstants(0) |
| , m_statements(0) |
| { |
| } |
| |
| ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants) |
| : StatementNode(endLocation) |
| , ParserArenaRoot(parserArena) |
| , VariableEnvironmentNode(lexicalVariables, WTFMove(funcStack)) |
| , m_startLineNumber(startLocation.line) |
| , m_startStartOffset(startLocation.startOffset) |
| , m_startLineStartOffset(startLocation.lineStartOffset) |
| , m_features(features) |
| , m_innerArrowFunctionCodeFeatures(innerArrowFunctionCodeFeatures) |
| , m_source(source) |
| , m_sloppyModeHoistedFunctions(WTFMove(sloppyModeHoistedFunctions)) |
| , m_numConstants(numConstants) |
| , m_statements(children) |
| { |
| m_varDeclarations.swap(varEnvironment); |
| } |
| |
| StatementNode* ScopeNode::singleStatement() const |
| { |
| return m_statements ? m_statements->singleStatement() : nullptr; |
| } |
| |
| bool ScopeNode::hasCompletionValue() const |
| { |
| return m_statements ? m_statements->hasCompletionValue() : false; |
| } |
| |
| bool ScopeNode::hasEarlyBreakOrContinue() const |
| { |
| return m_statements ? m_statements->hasEarlyBreakOrContinue() : false; |
| } |
| |
| // ------------------------------ ProgramNode ----------------------------- |
| |
| ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&) |
| : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants) |
| , m_startColumn(startColumn) |
| , m_endColumn(endColumn) |
| { |
| } |
| |
| // ------------------------------ ModuleProgramNode ----------------------------- |
| |
| ModuleProgramNode::ModuleProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&& moduleScopeData) |
| : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants) |
| , m_startColumn(startColumn) |
| , m_endColumn(endColumn) |
| , m_moduleScopeData(*WTFMove(moduleScopeData)) |
| { |
| } |
| |
| // ------------------------------ EvalNode ----------------------------- |
| |
| EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&) |
| : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants) |
| , m_endColumn(endColumn) |
| { |
| } |
| |
| // ------------------------------ FunctionMetadataNode ----------------------------- |
| |
| FunctionMetadataNode::FunctionMetadataNode( |
| ParserArena&, const JSTokenLocation& startLocation, |
| const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, |
| int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext, |
| ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression) |
| : Node(endLocation) |
| , m_isInStrictContext(isInStrictContext) |
| , m_superBinding(static_cast<unsigned>(superBinding)) |
| , m_constructorKind(static_cast<unsigned>(constructorKind)) |
| , m_needsClassFieldInitializer(static_cast<unsigned>(NeedsClassFieldInitializer::No)) |
| , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression) |
| , m_parseMode(mode) |
| , m_startColumn(startColumn) |
| , m_endColumn(endColumn) |
| , m_functionKeywordStart(functionKeywordStart) |
| , m_functionNameStart(functionNameStart) |
| , m_parametersStart(parametersStart) |
| , m_startStartOffset(startLocation.startOffset) |
| , m_parameterCount(parameterCount) |
| { |
| ASSERT(m_superBinding == static_cast<unsigned>(superBinding)); |
| ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind)); |
| } |
| |
| FunctionMetadataNode::FunctionMetadataNode( |
| const JSTokenLocation& startLocation, |
| const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, |
| int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext, |
| ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression) |
| : Node(endLocation) |
| , m_isInStrictContext(isInStrictContext) |
| , m_superBinding(static_cast<unsigned>(superBinding)) |
| , m_constructorKind(static_cast<unsigned>(constructorKind)) |
| , m_needsClassFieldInitializer(static_cast<unsigned>(NeedsClassFieldInitializer::No)) |
| , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression) |
| , m_parseMode(mode) |
| , m_startColumn(startColumn) |
| , m_endColumn(endColumn) |
| , m_functionKeywordStart(functionKeywordStart) |
| , m_functionNameStart(functionNameStart) |
| , m_parametersStart(parametersStart) |
| , m_startStartOffset(startLocation.startOffset) |
| , m_parameterCount(parameterCount) |
| { |
| ASSERT(m_superBinding == static_cast<unsigned>(superBinding)); |
| ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind)); |
| } |
| |
| void FunctionMetadataNode::finishParsing(const SourceCode& source, const Identifier& ident, FunctionMode functionMode) |
| { |
| m_source = source; |
| m_ident = ident; |
| m_functionMode = functionMode; |
| } |
| |
| void FunctionMetadataNode::setEndPosition(JSTextPosition position) |
| { |
| m_lastLine = position.line; |
| m_endColumn = position.offset - position.lineStartOffset; |
| } |
| |
| bool FunctionMetadataNode::operator==(const FunctionMetadataNode& other) const |
| { |
| return m_parseMode== other.m_parseMode |
| && m_isInStrictContext == other.m_isInStrictContext |
| && m_superBinding == other.m_superBinding |
| && m_constructorKind == other.m_constructorKind |
| && m_isArrowFunctionBodyExpression == other.m_isArrowFunctionBodyExpression |
| && m_ident == other.m_ident |
| && m_ecmaName == other.m_ecmaName |
| && m_functionMode== other.m_functionMode |
| && m_startColumn== other.m_startColumn |
| && m_endColumn== other.m_endColumn |
| && m_functionKeywordStart== other.m_functionKeywordStart |
| && m_functionNameStart== other.m_functionNameStart |
| && m_parametersStart== other.m_parametersStart |
| && m_source== other.m_source |
| && m_classSource== other.m_classSource |
| && m_startStartOffset== other.m_startStartOffset |
| && m_parameterCount== other.m_parameterCount |
| && m_lastLine== other.m_lastLine |
| && m_position == other.m_position; |
| } |
| |
| void FunctionMetadataNode::dump(PrintStream& stream) const |
| { |
| stream.println("m_parseMode ", static_cast<uint32_t>(m_parseMode)); |
| stream.println("m_isInStrictContext ", m_isInStrictContext); |
| stream.println("m_superBinding ", m_superBinding); |
| stream.println("m_constructorKind ", m_constructorKind); |
| stream.println("m_isArrowFunctionBodyExpression ", m_isArrowFunctionBodyExpression); |
| stream.println("m_ident ", m_ident); |
| stream.println("m_ecmaName ", m_ecmaName); |
| stream.println("m_functionMode ", static_cast<uint32_t>(m_functionMode)); |
| stream.println("m_startColumn ", m_startColumn); |
| stream.println("m_endColumn ", m_endColumn); |
| stream.println("m_functionKeywordStart ", m_functionKeywordStart); |
| stream.println("m_functionNameStart ", m_functionNameStart); |
| stream.println("m_parametersStart ", m_parametersStart); |
| stream.println("m_classSource.isNull() ", m_classSource.isNull()); |
| stream.println("m_startStartOffset ", m_startStartOffset); |
| stream.println("m_parameterCount ", m_parameterCount); |
| stream.println("m_lastLine ", m_lastLine); |
| stream.println("position().line ", position().line); |
| stream.println("position().offset ", position().offset); |
| stream.println("position().lineStartOffset ", position().lineStartOffset); |
| } |
| |
| // ------------------------------ FunctionNode ----------------------------- |
| |
| FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&) |
| : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants) |
| , m_parameters(parameters) |
| , m_startColumn(startColumn) |
| , m_endColumn(endColumn) |
| { |
| } |
| |
| void FunctionNode::finishParsing(const Identifier& ident, FunctionMode functionMode) |
| { |
| ASSERT(!source().isNull()); |
| m_ident = ident; |
| m_functionMode = functionMode; |
| } |
| |
| bool PropertyListNode::hasStaticallyNamedProperty(const Identifier& propName) |
| { |
| PropertyListNode* list = this; |
| while (list) { |
| if (list->m_node->isStaticClassProperty()) { |
| const Identifier* currentNodeName = list->m_node->name(); |
| if (currentNodeName && *currentNodeName == propName) |
| return true; |
| } |
| list = list->m_next; |
| } |
| return false; |
| } |
| |
| // FIXME: calculate this feature once when parsing the property list. |
| // https://bugs.webkit.org/show_bug.cgi?id=206174 |
| bool PropertyListNode::shouldCreateLexicalScopeForClass(PropertyListNode* list) |
| { |
| while (list) { |
| if (list->m_node->isComputedClassField()) |
| return true; |
| list = list->m_next; |
| } |
| return false; |
| } |
| |
| // ------------------------------ ClassExprNode ----------------------------- |
| |
| // FIXME: calculate this feature once when parsing the property list. |
| // https://bugs.webkit.org/show_bug.cgi?id=206174 |
| bool PropertyListNode::hasInstanceFields() const |
| { |
| for (auto list = this; list; list = list->m_next) { |
| if (list->m_node->isInstanceClassField()) |
| return true; |
| } |
| return false; |
| } |
| |
| VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables) |
| { |
| m_lexicalVariables.swap(lexicalVariables); |
| } |
| |
| VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables, FunctionStack&& functionStack) |
| { |
| m_lexicalVariables.swap(lexicalVariables); |
| m_functionStack = WTFMove(functionStack); |
| } |
| |
| } // namespace JSC |