mirror of
https://github.com/darlinghq/darling-JavaScriptCore.git
synced 2024-11-26 21:50:53 +00:00
370 lines
16 KiB
C++
370 lines
16 KiB
C++
/*
|
|
* 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 "ExecutableInfo.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(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, 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() || 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.swap(lexicalVariables);
|
|
}
|
|
|
|
VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables, FunctionStack&& functionStack)
|
|
{
|
|
m_lexicalVariables.swap(lexicalVariables);
|
|
m_functionStack = WTFMove(functionStack);
|
|
}
|
|
|
|
} // namespace JSC
|