/* * 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 * * 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 "ExecutableInfo.h" #include "ModuleScopeData.h" #include 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, LexicalScopeFeatures lexicalScopeFeatures) : StatementNode(endLocation) , ParserArenaRoot(parserArena) , m_startLineNumber(startLocation.line) , m_startStartOffset(startLocation.startOffset) , m_startLineStartOffset(startLocation.lineStartOffset) , m_features(NoFeatures) , m_lexicalScopeFeatures(lexicalScopeFeatures) , m_innerArrowFunctionCodeFeatures(NoInnerArrowFunctionFeatures) , m_numConstants(0) , m_statements(nullptr) { } 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants) : StatementNode(endLocation) , ParserArenaRoot(parserArena) , VariableEnvironmentNode(WTFMove(lexicalVariables), WTFMove(funcStack)) , m_startLineNumber(startLocation.line) , m_startStartOffset(startLocation.startOffset) , m_startLineStartOffset(startLocation.lineStartOffset) , m_features(features) , m_lexicalScopeFeatures(lexicalScopeFeatures) , m_innerArrowFunctionCodeFeatures(innerArrowFunctionCodeFeatures) , m_source(source) , m_varDeclarations(WTFMove(varEnvironment)) , m_sloppyModeHoistedFunctions(WTFMove(sloppyModeHoistedFunctions)) , m_numConstants(numConstants) , m_statements(children) { } 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr&&) : ScopeNode(parserArena, startLocation, endLocation, source, children, WTFMove(varEnvironment), WTFMove(funcStack), WTFMove(lexicalVariables), WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr&& moduleScopeData) : ScopeNode(parserArena, startLocation, endLocation, source, children, WTFMove(varEnvironment), WTFMove(funcStack), WTFMove(lexicalVariables), WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, numConstants) , m_startColumn(startColumn) , m_endColumn(endColumn) , m_usesAwait(features & AwaitFeature) , 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr&&) : ScopeNode(parserArena, startLocation, endLocation, source, children, WTFMove(varEnvironment), WTFMove(funcStack), WTFMove(lexicalVariables), WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, 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, ImplementationVisibility implementationVisibility, LexicalScopeFeatures lexicalScopeFeatures, ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression) : Node(endLocation) , m_implementationVisibility(static_cast(implementationVisibility)) , m_lexicalScopeFeatures(lexicalScopeFeatures) , m_superBinding(static_cast(superBinding)) , m_constructorKind(static_cast(constructorKind)) , m_needsClassFieldInitializer(static_cast(NeedsClassFieldInitializer::No)) , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression) , m_privateBrandRequirement(static_cast(PrivateBrandRequirement::None)) , 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_implementationVisibility == static_cast(implementationVisibility)); ASSERT(m_superBinding == static_cast(superBinding)); ASSERT(m_constructorKind == static_cast(constructorKind)); } FunctionMetadataNode::FunctionMetadataNode( const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, int functionKeywordStart, int functionNameStart, int parametersStart, ImplementationVisibility implementationVisibility, LexicalScopeFeatures lexicalScopeFeatures, ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression) : Node(endLocation) , m_implementationVisibility(static_cast(implementationVisibility)) , m_lexicalScopeFeatures(lexicalScopeFeatures) , m_superBinding(static_cast(superBinding)) , m_constructorKind(static_cast(constructorKind)) , m_needsClassFieldInitializer(static_cast(NeedsClassFieldInitializer::No)) , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression) , m_privateBrandRequirement(static_cast(PrivateBrandRequirement::None)) , 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_implementationVisibility == static_cast(implementationVisibility)); ASSERT(m_superBinding == static_cast(superBinding)); ASSERT(m_constructorKind == static_cast(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_implementationVisibility == other.m_implementationVisibility && m_lexicalScopeFeatures == other.m_lexicalScopeFeatures && 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(m_parseMode)); stream.println("m_implementationVisibility ", m_implementationVisibility); stream.println("m_lexicalScopeFeatures ", m_lexicalScopeFeatures); 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(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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr&&) : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, WTFMove(varEnvironment), WTFMove(funcStack), WTFMove(lexicalVariables), WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, 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() || list->m_node->isPrivate()) 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(WTFMove(lexicalVariables)) { } VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment&& lexicalVariables, FunctionStack&& functionStack) : m_lexicalVariables(WTFMove(lexicalVariables)) , m_functionStack(WTFMove(functionStack)) { } } // namespace JSC