1/*
2* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3* Copyright (C) 2001 Peter Kelly (pmk@post.com)
4* Copyright (C) 2003-2009, 2013, 2016 Apple Inc. All rights reserved.
5* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
8*
9* This library is free software; you can redistribute it and/or
10* modify it under the terms of the GNU Library General Public
11* License as published by the Free Software Foundation; either
12* version 2 of the License, or (at your option) any later version.
13*
14* This library is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17* Library General Public License for more details.
18*
19* You should have received a copy of the GNU Library General Public License
20* along with this library; see the file COPYING.LIB. If not, write to
21* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22* Boston, MA 02110-1301, USA.
23*
24*/
25
26#include "config.h"
27#include "Nodes.h"
28#include "NodeConstructors.h"
29
30#include "JSCInlines.h"
31#include "ModuleScopeData.h"
32#include <wtf/Assertions.h>
33
34namespace JSC {
35
36// ------------------------------ StatementNode --------------------------------
37
38void StatementNode::setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset)
39{
40 m_lastLine = lastLine;
41 m_position = JSTextPosition(firstLine, startOffset, lineStartOffset);
42 ASSERT(m_position.offset >= m_position.lineStartOffset);
43}
44
45// ------------------------------ SourceElements --------------------------------
46
47void SourceElements::append(StatementNode* statement)
48{
49 if (statement->isEmptyStatement())
50 return;
51
52 if (!m_head) {
53 m_head = statement;
54 m_tail = statement;
55 return;
56 }
57
58 m_tail->setNext(statement);
59 m_tail = statement;
60}
61
62StatementNode* SourceElements::singleStatement() const
63{
64 return m_head == m_tail ? m_head : nullptr;
65}
66
67StatementNode* SourceElements::lastStatement() const
68{
69 return m_tail;
70}
71
72bool SourceElements::hasCompletionValue() const
73{
74 for (StatementNode* statement = m_head; statement; statement = statement->next()) {
75 if (statement->hasCompletionValue())
76 return true;
77 }
78
79 return false;
80}
81
82bool SourceElements::hasEarlyBreakOrContinue() const
83{
84 for (StatementNode* statement = m_head; statement; statement = statement->next()) {
85 if (statement->isBreak() || statement->isContinue())
86 return true;
87 if (statement->hasCompletionValue())
88 return false;
89 }
90
91 return false;
92}
93
94// ------------------------------ BlockNode ------------------------------------
95
96StatementNode* BlockNode::lastStatement() const
97{
98 return m_statements ? m_statements->lastStatement() : nullptr;
99}
100
101StatementNode* BlockNode::singleStatement() const
102{
103 return m_statements ? m_statements->singleStatement() : nullptr;
104}
105
106bool BlockNode::hasCompletionValue() const
107{
108 return m_statements ? m_statements->hasCompletionValue() : false;
109}
110
111bool BlockNode::hasEarlyBreakOrContinue() const
112{
113 return m_statements ? m_statements->hasEarlyBreakOrContinue() : false;
114}
115
116// ------------------------------ ScopeNode -----------------------------
117
118ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, bool inStrictContext)
119 : StatementNode(endLocation)
120 , ParserArenaRoot(parserArena)
121 , m_startLineNumber(startLocation.line)
122 , m_startStartOffset(startLocation.startOffset)
123 , m_startLineStartOffset(startLocation.lineStartOffset)
124 , m_features(inStrictContext ? StrictModeFeature : NoFeatures)
125 , m_innerArrowFunctionCodeFeatures(NoInnerArrowFunctionFeatures)
126 , m_numConstants(0)
127 , m_statements(0)
128{
129}
130
131ScopeNode::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)
132 : StatementNode(endLocation)
133 , ParserArenaRoot(parserArena)
134 , VariableEnvironmentNode(lexicalVariables, WTFMove(funcStack))
135 , m_startLineNumber(startLocation.line)
136 , m_startStartOffset(startLocation.startOffset)
137 , m_startLineStartOffset(startLocation.lineStartOffset)
138 , m_features(features)
139 , m_innerArrowFunctionCodeFeatures(innerArrowFunctionCodeFeatures)
140 , m_source(source)
141 , m_sloppyModeHoistedFunctions(WTFMove(sloppyModeHoistedFunctions))
142 , m_numConstants(numConstants)
143 , m_statements(children)
144{
145 m_varDeclarations.swap(varEnvironment);
146}
147
148StatementNode* ScopeNode::singleStatement() const
149{
150 return m_statements ? m_statements->singleStatement() : nullptr;
151}
152
153bool ScopeNode::hasCompletionValue() const
154{
155 return m_statements ? m_statements->hasCompletionValue() : false;
156}
157
158bool ScopeNode::hasEarlyBreakOrContinue() const
159{
160 return m_statements ? m_statements->hasEarlyBreakOrContinue() : false;
161}
162
163// ------------------------------ ProgramNode -----------------------------
164
165ProgramNode::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>&&)
166 : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
167 , m_startColumn(startColumn)
168 , m_endColumn(endColumn)
169{
170}
171
172// ------------------------------ ModuleProgramNode -----------------------------
173
174ModuleProgramNode::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)
175 : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
176 , m_startColumn(startColumn)
177 , m_endColumn(endColumn)
178 , m_moduleScopeData(*WTFMove(moduleScopeData))
179{
180}
181
182// ------------------------------ EvalNode -----------------------------
183
184EvalNode::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>&&)
185 : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
186 , m_endColumn(endColumn)
187{
188}
189
190// ------------------------------ FunctionMetadataNode -----------------------------
191
192FunctionMetadataNode::FunctionMetadataNode(
193 ParserArena&, const JSTokenLocation& startLocation,
194 const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn,
195 int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext,
196 ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
197 : Node(endLocation)
198 , m_isInStrictContext(isInStrictContext)
199 , m_superBinding(static_cast<unsigned>(superBinding))
200 , m_constructorKind(static_cast<unsigned>(constructorKind))
201 , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression)
202 , m_parseMode(mode)
203 , m_startColumn(startColumn)
204 , m_endColumn(endColumn)
205 , m_functionKeywordStart(functionKeywordStart)
206 , m_functionNameStart(functionNameStart)
207 , m_parametersStart(parametersStart)
208 , m_startStartOffset(startLocation.startOffset)
209 , m_parameterCount(parameterCount)
210{
211 ASSERT(m_superBinding == static_cast<unsigned>(superBinding));
212 ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
213}
214
215FunctionMetadataNode::FunctionMetadataNode(
216 const JSTokenLocation& startLocation,
217 const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn,
218 int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext,
219 ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
220 : Node(endLocation)
221 , m_isInStrictContext(isInStrictContext)
222 , m_superBinding(static_cast<unsigned>(superBinding))
223 , m_constructorKind(static_cast<unsigned>(constructorKind))
224 , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression)
225 , m_parseMode(mode)
226 , m_startColumn(startColumn)
227 , m_endColumn(endColumn)
228 , m_functionKeywordStart(functionKeywordStart)
229 , m_functionNameStart(functionNameStart)
230 , m_parametersStart(parametersStart)
231 , m_startStartOffset(startLocation.startOffset)
232 , m_parameterCount(parameterCount)
233{
234 ASSERT(m_superBinding == static_cast<unsigned>(superBinding));
235 ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
236}
237
238void FunctionMetadataNode::finishParsing(const SourceCode& source, const Identifier& ident, FunctionMode functionMode)
239{
240 m_source = source;
241 m_ident = ident;
242 m_functionMode = functionMode;
243}
244
245void FunctionMetadataNode::setEndPosition(JSTextPosition position)
246{
247 m_lastLine = position.line;
248 m_endColumn = position.offset - position.lineStartOffset;
249}
250
251bool FunctionMetadataNode::operator==(const FunctionMetadataNode& other) const
252{
253 return m_parseMode== other.m_parseMode
254 && m_isInStrictContext == other.m_isInStrictContext
255 && m_superBinding == other.m_superBinding
256 && m_constructorKind == other.m_constructorKind
257 && m_isArrowFunctionBodyExpression == other.m_isArrowFunctionBodyExpression
258 && m_ident == other.m_ident
259 && m_ecmaName == other.m_ecmaName
260 && m_functionMode== other.m_functionMode
261 && m_startColumn== other.m_startColumn
262 && m_endColumn== other.m_endColumn
263 && m_functionKeywordStart== other.m_functionKeywordStart
264 && m_functionNameStart== other.m_functionNameStart
265 && m_parametersStart== other.m_parametersStart
266 && m_source== other.m_source
267 && m_classSource== other.m_classSource
268 && m_startStartOffset== other.m_startStartOffset
269 && m_parameterCount== other.m_parameterCount
270 && m_lastLine== other.m_lastLine
271 && m_position == other.m_position;
272}
273
274void FunctionMetadataNode::dump(PrintStream& stream) const
275{
276 stream.println("m_parseMode ", static_cast<uint32_t>(m_parseMode));
277 stream.println("m_isInStrictContext ", m_isInStrictContext);
278 stream.println("m_superBinding ", m_superBinding);
279 stream.println("m_constructorKind ", m_constructorKind);
280 stream.println("m_isArrowFunctionBodyExpression ", m_isArrowFunctionBodyExpression);
281 stream.println("m_ident ", m_ident);
282 stream.println("m_ecmaName ", m_ecmaName);
283 stream.println("m_functionMode ", static_cast<uint32_t>(m_functionMode));
284 stream.println("m_startColumn ", m_startColumn);
285 stream.println("m_endColumn ", m_endColumn);
286 stream.println("m_functionKeywordStart ", m_functionKeywordStart);
287 stream.println("m_functionNameStart ", m_functionNameStart);
288 stream.println("m_parametersStart ", m_parametersStart);
289 stream.println("m_classSource.isNull() ", m_classSource.isNull());
290 stream.println("m_startStartOffset ", m_startStartOffset);
291 stream.println("m_parameterCount ", m_parameterCount);
292 stream.println("m_lastLine ", m_lastLine);
293 stream.println("position().line ", position().line);
294 stream.println("position().offset ", position().offset);
295 stream.println("position().lineStartOffset ", position().lineStartOffset);
296}
297
298// ------------------------------ FunctionNode -----------------------------
299
300FunctionNode::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>&&)
301 : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
302 , m_parameters(parameters)
303 , m_startColumn(startColumn)
304 , m_endColumn(endColumn)
305{
306}
307
308void FunctionNode::finishParsing(const Identifier& ident, FunctionMode functionMode)
309{
310 ASSERT(!source().isNull());
311 m_ident = ident;
312 m_functionMode = functionMode;
313}
314
315bool PropertyListNode::hasStaticallyNamedProperty(const Identifier& propName)
316{
317 PropertyListNode* list = this;
318 while (list) {
319 if (list->m_node->isStaticClassProperty()) {
320 const Identifier* currentNodeName = list->m_node->name();
321 if (currentNodeName && *currentNodeName == propName)
322 return true;
323 }
324 list = list->m_next;
325 }
326 return false;
327}
328
329VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables)
330{
331 m_lexicalVariables.swap(lexicalVariables);
332}
333
334VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables, FunctionStack&& functionStack)
335{
336 m_lexicalVariables.swap(lexicalVariables);
337 m_functionStack = WTFMove(functionStack);
338}
339
340} // namespace JSC
341