1 | /* |
2 | * Copyright (C) 2010-2019 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #pragma once |
27 | |
28 | #include "BuiltinNames.h" |
29 | #include "BytecodeIntrinsicRegistry.h" |
30 | #include "MathCommon.h" |
31 | #include "NodeConstructors.h" |
32 | #include "SyntaxChecker.h" |
33 | #include "VariableEnvironment.h" |
34 | #include <utility> |
35 | |
36 | namespace JSC { |
37 | |
38 | class ASTBuilder { |
39 | struct BinaryOpInfo { |
40 | BinaryOpInfo() {} |
41 | BinaryOpInfo(const JSTextPosition& otherStart, const JSTextPosition& otherDivot, const JSTextPosition& otherEnd, bool rhsHasAssignment) |
42 | : start(otherStart) |
43 | , divot(otherDivot) |
44 | , end(otherEnd) |
45 | , hasAssignment(rhsHasAssignment) |
46 | { |
47 | } |
48 | BinaryOpInfo(const BinaryOpInfo& lhs, const BinaryOpInfo& rhs) |
49 | : start(lhs.start) |
50 | , divot(rhs.start) |
51 | , end(rhs.end) |
52 | , hasAssignment(lhs.hasAssignment || rhs.hasAssignment) |
53 | { |
54 | } |
55 | JSTextPosition start; |
56 | JSTextPosition divot; |
57 | JSTextPosition end; |
58 | bool hasAssignment; |
59 | }; |
60 | |
61 | |
62 | struct AssignmentInfo { |
63 | AssignmentInfo() {} |
64 | AssignmentInfo(ExpressionNode* node, const JSTextPosition& start, const JSTextPosition& divot, int initAssignments, Operator op) |
65 | : m_node(node) |
66 | , m_start(start) |
67 | , m_divot(divot) |
68 | , m_initAssignments(initAssignments) |
69 | , m_op(op) |
70 | { |
71 | ASSERT(m_divot.offset >= m_divot.lineStartOffset); |
72 | ASSERT(m_start.offset >= m_start.lineStartOffset); |
73 | } |
74 | ExpressionNode* m_node; |
75 | JSTextPosition m_start; |
76 | JSTextPosition m_divot; |
77 | int m_initAssignments; |
78 | Operator m_op; |
79 | }; |
80 | public: |
81 | ASTBuilder(VM& vm, ParserArena& parserArena, SourceCode* sourceCode) |
82 | : m_vm(vm) |
83 | , m_parserArena(parserArena) |
84 | , m_sourceCode(sourceCode) |
85 | , m_evalCount(0) |
86 | { |
87 | } |
88 | |
89 | struct BinaryExprContext { |
90 | BinaryExprContext(ASTBuilder&) {} |
91 | }; |
92 | struct UnaryExprContext { |
93 | UnaryExprContext(ASTBuilder&) {} |
94 | }; |
95 | |
96 | typedef ExpressionNode* Expression; |
97 | typedef JSC::SourceElements* SourceElements; |
98 | typedef ArgumentsNode* Arguments; |
99 | typedef CommaNode* Comma; |
100 | typedef PropertyNode* Property; |
101 | typedef PropertyListNode* PropertyList; |
102 | typedef ElementNode* ElementList; |
103 | typedef ArgumentListNode* ArgumentsList; |
104 | typedef TemplateExpressionListNode* TemplateExpressionList; |
105 | typedef TemplateStringNode* TemplateString; |
106 | typedef TemplateStringListNode* TemplateStringList; |
107 | typedef TemplateLiteralNode* TemplateLiteral; |
108 | typedef FunctionParameters* FormalParameterList; |
109 | typedef FunctionMetadataNode* FunctionBody; |
110 | typedef ClassExprNode* ClassExpression; |
111 | typedef ModuleNameNode* ModuleName; |
112 | typedef ImportSpecifierNode* ImportSpecifier; |
113 | typedef ImportSpecifierListNode* ImportSpecifierList; |
114 | typedef ExportSpecifierNode* ExportSpecifier; |
115 | typedef ExportSpecifierListNode* ExportSpecifierList; |
116 | typedef StatementNode* Statement; |
117 | typedef ClauseListNode* ClauseList; |
118 | typedef CaseClauseNode* Clause; |
119 | typedef std::pair<ExpressionNode*, BinaryOpInfo> BinaryOperand; |
120 | typedef DestructuringPatternNode* DestructuringPattern; |
121 | typedef ArrayPatternNode* ArrayPattern; |
122 | typedef ObjectPatternNode* ObjectPattern; |
123 | typedef BindingNode* BindingPattern; |
124 | typedef AssignmentElementNode* AssignmentElement; |
125 | static constexpr bool CreatesAST = true; |
126 | static constexpr bool NeedsFreeVariableInfo = true; |
127 | static constexpr bool CanUseFunctionCache = true; |
128 | static constexpr OptionSet<LexerFlags> DontBuildKeywords = { }; |
129 | static constexpr OptionSet<LexerFlags> DontBuildStrings = { }; |
130 | |
131 | ExpressionNode* makeBinaryNode(const JSTokenLocation&, int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>); |
132 | ExpressionNode* makeFunctionCallNode(const JSTokenLocation&, ExpressionNode* func, bool previousBaseWasSuper, ArgumentsNode* args, const JSTextPosition& divotStart, const JSTextPosition& divot, const JSTextPosition& divotEnd, size_t callOrApplyChildDepth, bool isOptionalCall); |
133 | |
134 | JSC::SourceElements* createSourceElements() { return new (m_parserArena) JSC::SourceElements(); } |
135 | |
136 | int features() const { return m_scope.m_features; } |
137 | int numConstants() const { return m_scope.m_numConstants; } |
138 | |
139 | ExpressionNode* makeAssignNode(const JSTokenLocation&, ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end); |
140 | ExpressionNode* makePrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end); |
141 | ExpressionNode* makePostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end); |
142 | ExpressionNode* makeTypeOfNode(const JSTokenLocation&, ExpressionNode*); |
143 | ExpressionNode* makeDeleteNode(const JSTokenLocation&, ExpressionNode*, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end); |
144 | ExpressionNode* makeNegateNode(const JSTokenLocation&, ExpressionNode*); |
145 | ExpressionNode* makeBitwiseNotNode(const JSTokenLocation&, ExpressionNode*); |
146 | ExpressionNode* makePowNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
147 | ExpressionNode* makeMultNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
148 | ExpressionNode* makeDivNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
149 | ExpressionNode* makeModNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
150 | ExpressionNode* makeAddNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
151 | ExpressionNode* makeSubNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
152 | ExpressionNode* makeBitXOrNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
153 | ExpressionNode* makeBitAndNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
154 | ExpressionNode* makeBitOrNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
155 | ExpressionNode* makeCoalesceNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right); |
156 | ExpressionNode* makeLeftShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
157 | ExpressionNode* makeRightShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
158 | ExpressionNode* makeURightShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); |
159 | |
160 | ExpressionNode* createLogicalNot(const JSTokenLocation& location, ExpressionNode* expr) |
161 | { |
162 | if (expr->isNumber()) |
163 | return createBoolean(location, isZeroOrUnordered(static_cast<NumberNode*>(expr)->value())); |
164 | |
165 | return new (m_parserArena) LogicalNotNode(location, expr); |
166 | } |
167 | ExpressionNode* createUnaryPlus(const JSTokenLocation& location, ExpressionNode* expr) { return new (m_parserArena) UnaryPlusNode(location, expr); } |
168 | ExpressionNode* createVoid(const JSTokenLocation& location, ExpressionNode* expr) |
169 | { |
170 | incConstants(); |
171 | return new (m_parserArena) VoidNode(location, expr); |
172 | } |
173 | ExpressionNode* createThisExpr(const JSTokenLocation& location) |
174 | { |
175 | usesThis(); |
176 | return new (m_parserArena) ThisNode(location); |
177 | } |
178 | ExpressionNode* createSuperExpr(const JSTokenLocation& location) |
179 | { |
180 | return new (m_parserArena) SuperNode(location); |
181 | } |
182 | ExpressionNode* createImportExpr(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
183 | { |
184 | auto* node = new (m_parserArena) ImportNode(location, expr); |
185 | setExceptionLocation(node, start, divot, end); |
186 | return node; |
187 | } |
188 | ExpressionNode* createNewTargetExpr(const JSTokenLocation location) |
189 | { |
190 | usesNewTarget(); |
191 | return new (m_parserArena) NewTargetNode(location); |
192 | } |
193 | ExpressionNode* createImportMetaExpr(const JSTokenLocation& location, ExpressionNode* expr) { return new (m_parserArena) ImportMetaNode(location, expr); } |
194 | bool isMetaProperty(ExpressionNode* node) { return node->isMetaProperty(); } |
195 | bool isNewTarget(ExpressionNode* node) { return node->isNewTarget(); } |
196 | bool isImportMeta(ExpressionNode* node) { return node->isImportMeta(); } |
197 | ExpressionNode* createResolve(const JSTokenLocation& location, const Identifier& ident, const JSTextPosition& start, const JSTextPosition& end) |
198 | { |
199 | if (m_vm.propertyNames->arguments == ident) |
200 | usesArguments(); |
201 | |
202 | if (ident.isSymbol()) { |
203 | auto entry = m_vm.bytecodeIntrinsicRegistry().lookup(ident); |
204 | if (entry) |
205 | return new (m_parserArena) BytecodeIntrinsicNode(BytecodeIntrinsicNode::Type::Constant, location, entry.value(), ident, nullptr, start, start, end); |
206 | } |
207 | |
208 | return new (m_parserArena) ResolveNode(location, ident, start); |
209 | } |
210 | ExpressionNode* createObjectLiteral(const JSTokenLocation& location) { return new (m_parserArena) ObjectLiteralNode(location); } |
211 | ExpressionNode* createObjectLiteral(const JSTokenLocation& location, PropertyListNode* properties) { return new (m_parserArena) ObjectLiteralNode(location, properties); } |
212 | |
213 | ExpressionNode* createArray(const JSTokenLocation& location, int elisions) |
214 | { |
215 | if (elisions) |
216 | incConstants(); |
217 | return new (m_parserArena) ArrayNode(location, elisions); |
218 | } |
219 | |
220 | ExpressionNode* createArray(const JSTokenLocation& location, ElementNode* elems) { return new (m_parserArena) ArrayNode(location, elems); } |
221 | ExpressionNode* createArray(const JSTokenLocation& location, int elisions, ElementNode* elems) |
222 | { |
223 | if (elisions) |
224 | incConstants(); |
225 | return new (m_parserArena) ArrayNode(location, elisions, elems); |
226 | } |
227 | ExpressionNode* createDoubleExpr(const JSTokenLocation& location, double d) |
228 | { |
229 | incConstants(); |
230 | return new (m_parserArena) DoubleNode(location, d); |
231 | } |
232 | ExpressionNode* createIntegerExpr(const JSTokenLocation& location, double d) |
233 | { |
234 | incConstants(); |
235 | return new (m_parserArena) IntegerNode(location, d); |
236 | } |
237 | |
238 | ExpressionNode* createBigInt(const JSTokenLocation& location, const Identifier* bigInt, uint8_t radix) |
239 | { |
240 | incConstants(); |
241 | return new (m_parserArena) BigIntNode(location, *bigInt, radix); |
242 | } |
243 | |
244 | ExpressionNode* createString(const JSTokenLocation& location, const Identifier* string) |
245 | { |
246 | ASSERT(string); |
247 | incConstants(); |
248 | return new (m_parserArena) StringNode(location, *string); |
249 | } |
250 | |
251 | ExpressionNode* createBoolean(const JSTokenLocation& location, bool b) |
252 | { |
253 | incConstants(); |
254 | return new (m_parserArena) BooleanNode(location, b); |
255 | } |
256 | |
257 | ExpressionNode* createNull(const JSTokenLocation& location) |
258 | { |
259 | incConstants(); |
260 | return new (m_parserArena) NullNode(location); |
261 | } |
262 | |
263 | ExpressionNode* createBracketAccess(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
264 | { |
265 | if (base->isSuperNode()) |
266 | usesSuperProperty(); |
267 | |
268 | BracketAccessorNode* node = new (m_parserArena) BracketAccessorNode(location, base, property, propertyHasAssignments); |
269 | setExceptionLocation(node, start, divot, end); |
270 | return node; |
271 | } |
272 | |
273 | ExpressionNode* createDotAccess(const JSTokenLocation& location, ExpressionNode* base, const Identifier* property, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
274 | { |
275 | if (base->isSuperNode()) |
276 | usesSuperProperty(); |
277 | |
278 | DotAccessorNode* node = new (m_parserArena) DotAccessorNode(location, base, *property); |
279 | setExceptionLocation(node, start, divot, end); |
280 | return node; |
281 | } |
282 | |
283 | ExpressionNode* createSpreadExpression(const JSTokenLocation& location, ExpressionNode* expression, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
284 | { |
285 | auto node = new (m_parserArena) SpreadExpressionNode(location, expression); |
286 | setExceptionLocation(node, start, divot, end); |
287 | return node; |
288 | } |
289 | |
290 | ExpressionNode* createObjectSpreadExpression(const JSTokenLocation& location, ExpressionNode* expression, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
291 | { |
292 | auto node = new (m_parserArena) ObjectSpreadExpressionNode(location, expression); |
293 | setExceptionLocation(node, start, divot, end); |
294 | return node; |
295 | } |
296 | |
297 | TemplateStringNode* createTemplateString(const JSTokenLocation& location, const Identifier* cooked, const Identifier* raw) |
298 | { |
299 | return new (m_parserArena) TemplateStringNode(location, cooked, raw); |
300 | } |
301 | |
302 | TemplateStringListNode* createTemplateStringList(TemplateStringNode* templateString) |
303 | { |
304 | return new (m_parserArena) TemplateStringListNode(templateString); |
305 | } |
306 | |
307 | TemplateStringListNode* createTemplateStringList(TemplateStringListNode* templateStringList, TemplateStringNode* templateString) |
308 | { |
309 | return new (m_parserArena) TemplateStringListNode(templateStringList, templateString); |
310 | } |
311 | |
312 | TemplateExpressionListNode* createTemplateExpressionList(ExpressionNode* expression) |
313 | { |
314 | return new (m_parserArena) TemplateExpressionListNode(expression); |
315 | } |
316 | |
317 | TemplateExpressionListNode* createTemplateExpressionList(TemplateExpressionListNode* templateExpressionListNode, ExpressionNode* expression) |
318 | { |
319 | return new (m_parserArena) TemplateExpressionListNode(templateExpressionListNode, expression); |
320 | } |
321 | |
322 | TemplateLiteralNode* createTemplateLiteral(const JSTokenLocation& location, TemplateStringListNode* templateStringList) |
323 | { |
324 | return new (m_parserArena) TemplateLiteralNode(location, templateStringList); |
325 | } |
326 | |
327 | TemplateLiteralNode* createTemplateLiteral(const JSTokenLocation& location, TemplateStringListNode* templateStringList, TemplateExpressionListNode* templateExpressionList) |
328 | { |
329 | return new (m_parserArena) TemplateLiteralNode(location, templateStringList, templateExpressionList); |
330 | } |
331 | |
332 | ExpressionNode* createTaggedTemplate(const JSTokenLocation& location, ExpressionNode* base, TemplateLiteralNode* templateLiteral, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
333 | { |
334 | auto node = new (m_parserArena) TaggedTemplateNode(location, base, templateLiteral); |
335 | setExceptionLocation(node, start, divot, end); |
336 | setEndOffset(node, end.offset); |
337 | return node; |
338 | } |
339 | |
340 | ExpressionNode* createRegExp(const JSTokenLocation& location, const Identifier& pattern, const Identifier& flags, const JSTextPosition& start) |
341 | { |
342 | if (Yarr::hasError(Yarr::checkSyntax(pattern.string(), flags.string()))) |
343 | return 0; |
344 | RegExpNode* node = new (m_parserArena) RegExpNode(location, pattern, flags); |
345 | int size = pattern.length() + 2; // + 2 for the two /'s |
346 | JSTextPosition end = start + size; |
347 | setExceptionLocation(node, start, end, end); |
348 | return node; |
349 | } |
350 | |
351 | ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, ArgumentsNode* arguments, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
352 | { |
353 | NewExprNode* node = new (m_parserArena) NewExprNode(location, expr, arguments); |
354 | setExceptionLocation(node, start, divot, end); |
355 | return node; |
356 | } |
357 | |
358 | ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, const JSTextPosition& end) |
359 | { |
360 | NewExprNode* node = new (m_parserArena) NewExprNode(location, expr); |
361 | setExceptionLocation(node, start, end, end); |
362 | return node; |
363 | } |
364 | |
365 | ExpressionNode* createOptionalChain(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* expr, bool isOutermost) |
366 | { |
367 | base->setIsOptionalChainBase(); |
368 | return new (m_parserArena) OptionalChainNode(location, expr, isOutermost); |
369 | } |
370 | |
371 | ExpressionNode* createConditionalExpr(const JSTokenLocation& location, ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs) |
372 | { |
373 | return new (m_parserArena) ConditionalNode(location, condition, lhs, rhs); |
374 | } |
375 | |
376 | ExpressionNode* createAssignResolve(const JSTokenLocation& location, const Identifier& ident, ExpressionNode* rhs, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end, AssignmentContext assignmentContext) |
377 | { |
378 | if (rhs->isBaseFuncExprNode()) { |
379 | auto metadata = static_cast<BaseFuncExprNode*>(rhs)->metadata(); |
380 | metadata->setEcmaName(ident); |
381 | } else if (rhs->isClassExprNode()) |
382 | static_cast<ClassExprNode*>(rhs)->setEcmaName(ident); |
383 | AssignResolveNode* node = new (m_parserArena) AssignResolveNode(location, ident, rhs, assignmentContext); |
384 | setExceptionLocation(node, start, divot, end); |
385 | return node; |
386 | } |
387 | |
388 | YieldExprNode* createYield(const JSTokenLocation& location) |
389 | { |
390 | return new (m_parserArena) YieldExprNode(location, nullptr, /* delegate */ false); |
391 | } |
392 | |
393 | YieldExprNode* createYield(const JSTokenLocation& location, ExpressionNode* argument, bool delegate, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
394 | { |
395 | YieldExprNode* node = new (m_parserArena) YieldExprNode(location, argument, delegate); |
396 | setExceptionLocation(node, start, divot, end); |
397 | return node; |
398 | } |
399 | |
400 | AwaitExprNode* createAwait(const JSTokenLocation& location, ExpressionNode* argument, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
401 | { |
402 | ASSERT(argument); |
403 | AwaitExprNode* node = new (m_parserArena) AwaitExprNode(location, argument); |
404 | setExceptionLocation(node, start, divot, end); |
405 | return node; |
406 | } |
407 | |
408 | ClassExprNode* createClassExpr(const JSTokenLocation& location, const ParserClassInfo<ASTBuilder>& classInfo, VariableEnvironment& classEnvironment, ExpressionNode* constructor, |
409 | ExpressionNode* parentClass, PropertyListNode* classElements) |
410 | { |
411 | SourceCode source = m_sourceCode->subExpression(classInfo.startOffset, classInfo.endOffset, classInfo.startLine, classInfo.startColumn); |
412 | return new (m_parserArena) ClassExprNode(location, *classInfo.className, source, classEnvironment, constructor, parentClass, classElements); |
413 | } |
414 | |
415 | ExpressionNode* createFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo) |
416 | { |
417 | FuncExprNode* result = new (m_parserArena) FuncExprNode(location, *functionInfo.name, functionInfo.body, |
418 | m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn)); |
419 | functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset); |
420 | return result; |
421 | } |
422 | |
423 | ExpressionNode* createGeneratorFunctionBody(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo, const Identifier& name) |
424 | { |
425 | FuncExprNode* result = static_cast<FuncExprNode*>(createFunctionExpr(location, functionInfo)); |
426 | if (!name.isNull()) |
427 | result->metadata()->setEcmaName(name); |
428 | return result; |
429 | } |
430 | |
431 | ExpressionNode* createAsyncFunctionBody(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo, SourceParseMode parseMode) |
432 | { |
433 | if (parseMode == SourceParseMode::AsyncArrowFunctionBodyMode) { |
434 | SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.body->isArrowFunctionBodyExpression() ? functionInfo.endOffset - 1 : functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn); |
435 | FuncExprNode* result = new (m_parserArena) FuncExprNode(location, *functionInfo.name, functionInfo.body, source); |
436 | functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset); |
437 | return result; |
438 | } |
439 | return createFunctionExpr(location, functionInfo); |
440 | } |
441 | |
442 | ExpressionNode* createMethodDefinition(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo) |
443 | { |
444 | MethodDefinitionNode* result = new (m_parserArena) MethodDefinitionNode(location, *functionInfo.name, functionInfo.body, |
445 | m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn)); |
446 | functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset); |
447 | return result; |
448 | } |
449 | |
450 | FunctionMetadataNode* createFunctionMetadata( |
451 | const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, |
452 | unsigned startColumn, unsigned endColumn, int functionKeywordStart, |
453 | int functionNameStart, int , bool inStrictContext, |
454 | ConstructorKind constructorKind, SuperBinding superBinding, |
455 | unsigned parameterCount, |
456 | SourceParseMode mode, bool isArrowFunctionBodyExpression) |
457 | { |
458 | return new (m_parserArena) FunctionMetadataNode( |
459 | m_parserArena, startLocation, endLocation, startColumn, endColumn, |
460 | functionKeywordStart, functionNameStart, parametersStart, |
461 | inStrictContext, constructorKind, superBinding, |
462 | parameterCount, mode, isArrowFunctionBodyExpression); |
463 | } |
464 | |
465 | ExpressionNode* createArrowFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo) |
466 | { |
467 | usesArrowFunction(); |
468 | SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.body->isArrowFunctionBodyExpression() ? functionInfo.endOffset - 1 : functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn); |
469 | ArrowFuncExprNode* result = new (m_parserArena) ArrowFuncExprNode(location, *functionInfo.name, functionInfo.body, source); |
470 | functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset); |
471 | return result; |
472 | } |
473 | |
474 | ArgumentsNode* createArguments() { return new (m_parserArena) ArgumentsNode(); } |
475 | ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_parserArena) ArgumentsNode(args); } |
476 | ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ExpressionNode* arg) { return new (m_parserArena) ArgumentListNode(location, arg); } |
477 | ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ArgumentListNode* args, ExpressionNode* arg) { return new (m_parserArena) ArgumentListNode(location, args, arg); } |
478 | |
479 | NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool, |
480 | const Identifier* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag) |
481 | { |
482 | ASSERT(name); |
483 | functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset); |
484 | functionInfo.body->setEcmaName(*name); |
485 | SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn); |
486 | MethodDefinitionNode* methodDef = new (m_parserArena) MethodDefinitionNode(location, m_vm.propertyNames->nullIdentifier, functionInfo.body, source); |
487 | return new (m_parserArena) PropertyNode(*name, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, tag); |
488 | } |
489 | |
490 | NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool, |
491 | ExpressionNode* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag) |
492 | { |
493 | ASSERT(name); |
494 | functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset); |
495 | SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn); |
496 | MethodDefinitionNode* methodDef = new (m_parserArena) MethodDefinitionNode(location, m_vm.propertyNames->nullIdentifier, functionInfo.body, source); |
497 | return new (m_parserArena) PropertyNode(name, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, tag); |
498 | } |
499 | |
500 | NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM& vm, ParserArena& parserArena, const JSTokenLocation& location, PropertyNode::Type type, bool, |
501 | double name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag) |
502 | { |
503 | functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset); |
504 | const Identifier& ident = parserArena.identifierArena().makeNumericIdentifier(vm, name); |
505 | SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn); |
506 | MethodDefinitionNode* methodDef = new (m_parserArena) MethodDefinitionNode(location, vm.propertyNames->nullIdentifier, functionInfo.body, source); |
507 | return new (m_parserArena) PropertyNode(ident, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, tag); |
508 | } |
509 | |
510 | PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, InferName inferName, ClassElementTag tag) |
511 | { |
512 | if (inferName == InferName::Allowed) { |
513 | if (node->isBaseFuncExprNode()) { |
514 | auto metadata = static_cast<BaseFuncExprNode*>(node)->metadata(); |
515 | metadata->setEcmaName(*propertyName); |
516 | } else if (node->isClassExprNode()) |
517 | static_cast<ClassExprNode*>(node)->setEcmaName(*propertyName); |
518 | } |
519 | return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding, tag); |
520 | } |
521 | PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag) |
522 | { |
523 | return new (m_parserArena) PropertyNode(node, type, putType, superBinding, tag); |
524 | } |
525 | PropertyNode* createProperty(VM& vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag) |
526 | { |
527 | return new (m_parserArena) PropertyNode(parserArena.identifierArena().makeNumericIdentifier(vm, propertyName), node, type, putType, superBinding, tag); |
528 | } |
529 | PropertyNode* createProperty(ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag) { return new (m_parserArena) PropertyNode(propertyName, node, type, putType, superBinding, tag); } |
530 | PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property) { return new (m_parserArena) PropertyListNode(location, property); } |
531 | PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property, PropertyListNode* tail) { return new (m_parserArena) PropertyListNode(location, property, tail); } |
532 | |
533 | ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_parserArena) ElementNode(elisions, expr); } |
534 | ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_parserArena) ElementNode(elems, elisions, expr); } |
535 | ElementNode* createElementList(ArgumentListNode* elems) |
536 | { |
537 | ElementNode* head = new (m_parserArena) ElementNode(0, elems->m_expr); |
538 | ElementNode* tail = head; |
539 | elems = elems->m_next; |
540 | while (elems) { |
541 | tail = new (m_parserArena) ElementNode(tail, 0, elems->m_expr); |
542 | elems = elems->m_next; |
543 | } |
544 | return head; |
545 | } |
546 | |
547 | FormalParameterList createFormalParameterList() { return new (m_parserArena) FunctionParameters(); } |
548 | void appendParameter(FormalParameterList list, DestructuringPattern pattern, ExpressionNode* defaultValue) |
549 | { |
550 | list->append(pattern, defaultValue); |
551 | tryInferNameInPattern(pattern, defaultValue); |
552 | } |
553 | |
554 | CaseClauseNode* createClause(ExpressionNode* expr, JSC::SourceElements* statements) { return new (m_parserArena) CaseClauseNode(expr, statements); } |
555 | ClauseListNode* createClauseList(CaseClauseNode* clause) { return new (m_parserArena) ClauseListNode(clause); } |
556 | ClauseListNode* createClauseList(ClauseListNode* tail, CaseClauseNode* clause) { return new (m_parserArena) ClauseListNode(tail, clause); } |
557 | |
558 | StatementNode* createFuncDeclStatement(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo) |
559 | { |
560 | FuncDeclNode* decl = new (m_parserArena) FuncDeclNode(location, *functionInfo.name, functionInfo.body, |
561 | m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn)); |
562 | if (*functionInfo.name == m_vm.propertyNames->arguments) |
563 | usesArguments(); |
564 | functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset); |
565 | return decl; |
566 | } |
567 | |
568 | StatementNode* createClassDeclStatement(const JSTokenLocation& location, ClassExprNode* classExpression, |
569 | const JSTextPosition& classStart, const JSTextPosition& classEnd, unsigned startLine, unsigned endLine) |
570 | { |
571 | ExpressionNode* assign = createAssignResolve(location, classExpression->name(), classExpression, classStart, classStart + 1, classEnd, AssignmentContext::DeclarationStatement); |
572 | ClassDeclNode* decl = new (m_parserArena) ClassDeclNode(location, assign); |
573 | decl->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); |
574 | return decl; |
575 | } |
576 | |
577 | StatementNode* createBlockStatement(const JSTokenLocation& location, JSC::SourceElements* elements, int startLine, int endLine, VariableEnvironment& lexicalVariables, DeclarationStacks::FunctionStack&& functionStack) |
578 | { |
579 | BlockNode* block = new (m_parserArena) BlockNode(location, elements, lexicalVariables, WTFMove(functionStack)); |
580 | block->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); |
581 | return block; |
582 | } |
583 | |
584 | StatementNode* createExprStatement(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, int end) |
585 | { |
586 | ExprStatementNode* result = new (m_parserArena) ExprStatementNode(location, expr); |
587 | result->setLoc(start.line, end, start.offset, start.lineStartOffset); |
588 | return result; |
589 | } |
590 | |
591 | StatementNode* createIfStatement(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end) |
592 | { |
593 | IfElseNode* result = new (m_parserArena) IfElseNode(location, condition, trueBlock, falseBlock); |
594 | result->setLoc(start, end, location.startOffset, location.lineStartOffset); |
595 | return result; |
596 | } |
597 | |
598 | StatementNode* createForLoop(const JSTokenLocation& location, ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, int start, int end, VariableEnvironment& lexicalVariables) |
599 | { |
600 | ForNode* result = new (m_parserArena) ForNode(location, initializer, condition, iter, statements, lexicalVariables); |
601 | result->setLoc(start, end, location.startOffset, location.lineStartOffset); |
602 | return result; |
603 | } |
604 | |
605 | StatementNode* createForInLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables) |
606 | { |
607 | ForInNode* result = new (m_parserArena) ForInNode(location, lhs, iter, statements, lexicalVariables); |
608 | result->setLoc(start, end, location.startOffset, location.lineStartOffset); |
609 | setExceptionLocation(result, eStart, eDivot, eEnd); |
610 | return result; |
611 | } |
612 | |
613 | StatementNode* createForInLoop(const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation& declLocation, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables) |
614 | { |
615 | auto lexpr = new (m_parserArena) DestructuringAssignmentNode(declLocation, pattern, nullptr); |
616 | return createForInLoop(location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, lexicalVariables); |
617 | } |
618 | |
619 | StatementNode* createForOfLoop(bool isForAwait, const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables) |
620 | { |
621 | ForOfNode* result = new (m_parserArena) ForOfNode(isForAwait, location, lhs, iter, statements, lexicalVariables); |
622 | result->setLoc(start, end, location.startOffset, location.lineStartOffset); |
623 | setExceptionLocation(result, eStart, eDivot, eEnd); |
624 | return result; |
625 | } |
626 | |
627 | StatementNode* createForOfLoop(bool isForAwait, const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation& declLocation, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables) |
628 | { |
629 | auto lexpr = new (m_parserArena) DestructuringAssignmentNode(declLocation, pattern, nullptr); |
630 | return createForOfLoop(isForAwait, location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, lexicalVariables); |
631 | } |
632 | |
633 | bool isBindingNode(const DestructuringPattern& pattern) |
634 | { |
635 | return pattern->isBindingNode(); |
636 | } |
637 | |
638 | bool isLocation(const Expression& node) |
639 | { |
640 | return node->isLocation(); |
641 | } |
642 | |
643 | bool isAssignmentLocation(const Expression& node) |
644 | { |
645 | return node->isAssignmentLocation(); |
646 | } |
647 | |
648 | bool isObjectLiteral(const Expression& node) |
649 | { |
650 | return node->isObjectLiteral(); |
651 | } |
652 | |
653 | bool isArrayLiteral(const Expression& node) |
654 | { |
655 | return node->isArrayLiteral(); |
656 | } |
657 | |
658 | bool isObjectOrArrayLiteral(const Expression& node) |
659 | { |
660 | return isObjectLiteral(node) || isArrayLiteral(node); |
661 | } |
662 | |
663 | bool isFunctionCall(const Expression& node) |
664 | { |
665 | return node->isFunctionCall(); |
666 | } |
667 | |
668 | bool shouldSkipPauseLocation(StatementNode* statement) const |
669 | { |
670 | return !statement || statement->isLabel(); |
671 | } |
672 | |
673 | StatementNode* createEmptyStatement(const JSTokenLocation& location) { return new (m_parserArena) EmptyStatementNode(location); } |
674 | |
675 | StatementNode* createDeclarationStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) |
676 | { |
677 | StatementNode* result; |
678 | result = new (m_parserArena) DeclarationStatement(location, expr); |
679 | result->setLoc(start, end, location.startOffset, location.lineStartOffset); |
680 | return result; |
681 | } |
682 | |
683 | ExpressionNode* createEmptyVarExpression(const JSTokenLocation& location, const Identifier& identifier) |
684 | { |
685 | return new (m_parserArena) EmptyVarExpression(location, identifier); |
686 | } |
687 | |
688 | ExpressionNode* createEmptyLetExpression(const JSTokenLocation& location, const Identifier& identifier) |
689 | { |
690 | return new (m_parserArena) EmptyLetExpression(location, identifier); |
691 | } |
692 | |
693 | StatementNode* createReturnStatement(const JSTokenLocation& location, ExpressionNode* expression, const JSTextPosition& start, const JSTextPosition& end) |
694 | { |
695 | ReturnNode* result = new (m_parserArena) ReturnNode(location, expression); |
696 | setExceptionLocation(result, start, end, end); |
697 | result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); |
698 | return result; |
699 | } |
700 | |
701 | StatementNode* createBreakStatement(const JSTokenLocation& location, const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end) |
702 | { |
703 | BreakNode* result = new (m_parserArena) BreakNode(location, *ident); |
704 | setExceptionLocation(result, start, end, end); |
705 | result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); |
706 | return result; |
707 | } |
708 | |
709 | StatementNode* createContinueStatement(const JSTokenLocation& location, const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end) |
710 | { |
711 | ContinueNode* result = new (m_parserArena) ContinueNode(location, *ident); |
712 | setExceptionLocation(result, start, end, end); |
713 | result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); |
714 | return result; |
715 | } |
716 | |
717 | StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, DestructuringPatternNode* catchPattern, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine, VariableEnvironment& catchEnvironment) |
718 | { |
719 | TryNode* result = new (m_parserArena) TryNode(location, tryBlock, catchPattern, catchBlock, catchEnvironment, finallyBlock); |
720 | result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); |
721 | return result; |
722 | } |
723 | |
724 | StatementNode* createSwitchStatement(const JSTokenLocation& location, ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine, VariableEnvironment& lexicalVariables, DeclarationStacks::FunctionStack&& functionStack) |
725 | { |
726 | CaseBlockNode* cases = new (m_parserArena) CaseBlockNode(firstClauses, defaultClause, secondClauses); |
727 | SwitchNode* result = new (m_parserArena) SwitchNode(location, expr, cases, lexicalVariables, WTFMove(functionStack)); |
728 | result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); |
729 | return result; |
730 | } |
731 | |
732 | StatementNode* createWhileStatement(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, int startLine, int endLine) |
733 | { |
734 | WhileNode* result = new (m_parserArena) WhileNode(location, expr, statement); |
735 | result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); |
736 | return result; |
737 | } |
738 | |
739 | StatementNode* createDoWhileStatement(const JSTokenLocation& location, StatementNode* statement, ExpressionNode* expr, int startLine, int endLine) |
740 | { |
741 | DoWhileNode* result = new (m_parserArena) DoWhileNode(location, statement, expr); |
742 | result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); |
743 | return result; |
744 | } |
745 | |
746 | StatementNode* createLabelStatement(const JSTokenLocation& location, const Identifier* ident, StatementNode* statement, const JSTextPosition& start, const JSTextPosition& end) |
747 | { |
748 | LabelNode* result = new (m_parserArena) LabelNode(location, *ident, statement); |
749 | setExceptionLocation(result, start, end, end); |
750 | return result; |
751 | } |
752 | |
753 | StatementNode* createWithStatement(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, unsigned start, const JSTextPosition& end, unsigned startLine, unsigned endLine) |
754 | { |
755 | usesWith(); |
756 | WithNode* result = new (m_parserArena) WithNode(location, expr, statement, end, end - start); |
757 | result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); |
758 | return result; |
759 | } |
760 | |
761 | StatementNode* createThrowStatement(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, const JSTextPosition& end) |
762 | { |
763 | ThrowNode* result = new (m_parserArena) ThrowNode(location, expr); |
764 | result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); |
765 | setExceptionLocation(result, start, end, end); |
766 | return result; |
767 | } |
768 | |
769 | StatementNode* createDebugger(const JSTokenLocation& location, int startLine, int endLine) |
770 | { |
771 | DebuggerStatementNode* result = new (m_parserArena) DebuggerStatementNode(location); |
772 | result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); |
773 | return result; |
774 | } |
775 | |
776 | ModuleNameNode* createModuleName(const JSTokenLocation& location, const Identifier& moduleName) |
777 | { |
778 | return new (m_parserArena) ModuleNameNode(location, moduleName); |
779 | } |
780 | |
781 | ImportSpecifierNode* createImportSpecifier(const JSTokenLocation& location, const Identifier& importedName, const Identifier& localName) |
782 | { |
783 | return new (m_parserArena) ImportSpecifierNode(location, importedName, localName); |
784 | } |
785 | |
786 | ImportSpecifierListNode* createImportSpecifierList() |
787 | { |
788 | return new (m_parserArena) ImportSpecifierListNode(); |
789 | } |
790 | |
791 | void appendImportSpecifier(ImportSpecifierListNode* specifierList, ImportSpecifierNode* specifier) |
792 | { |
793 | specifierList->append(specifier); |
794 | } |
795 | |
796 | StatementNode* createImportDeclaration(const JSTokenLocation& location, ImportSpecifierListNode* importSpecifierList, ModuleNameNode* moduleName) |
797 | { |
798 | return new (m_parserArena) ImportDeclarationNode(location, importSpecifierList, moduleName); |
799 | } |
800 | |
801 | StatementNode* createExportAllDeclaration(const JSTokenLocation& location, ModuleNameNode* moduleName) |
802 | { |
803 | return new (m_parserArena) ExportAllDeclarationNode(location, moduleName); |
804 | } |
805 | |
806 | StatementNode* createExportDefaultDeclaration(const JSTokenLocation& location, StatementNode* declaration, const Identifier& localName) |
807 | { |
808 | return new (m_parserArena) ExportDefaultDeclarationNode(location, declaration, localName); |
809 | } |
810 | |
811 | StatementNode* createExportLocalDeclaration(const JSTokenLocation& location, StatementNode* declaration) |
812 | { |
813 | return new (m_parserArena) ExportLocalDeclarationNode(location, declaration); |
814 | } |
815 | |
816 | StatementNode* createExportNamedDeclaration(const JSTokenLocation& location, ExportSpecifierListNode* exportSpecifierList, ModuleNameNode* moduleName) |
817 | { |
818 | return new (m_parserArena) ExportNamedDeclarationNode(location, exportSpecifierList, moduleName); |
819 | } |
820 | |
821 | ExportSpecifierNode* createExportSpecifier(const JSTokenLocation& location, const Identifier& localName, const Identifier& exportedName) |
822 | { |
823 | return new (m_parserArena) ExportSpecifierNode(location, localName, exportedName); |
824 | } |
825 | |
826 | ExportSpecifierListNode* createExportSpecifierList() |
827 | { |
828 | return new (m_parserArena) ExportSpecifierListNode(); |
829 | } |
830 | |
831 | void appendExportSpecifier(ExportSpecifierListNode* specifierList, ExportSpecifierNode* specifier) |
832 | { |
833 | specifierList->append(specifier); |
834 | } |
835 | |
836 | void appendStatement(JSC::SourceElements* elements, JSC::StatementNode* statement) |
837 | { |
838 | elements->append(statement); |
839 | } |
840 | |
841 | CommaNode* createCommaExpr(const JSTokenLocation& location, ExpressionNode* node) |
842 | { |
843 | return new (m_parserArena) CommaNode(location, node); |
844 | } |
845 | |
846 | CommaNode* appendToCommaExpr(const JSTokenLocation& location, ExpressionNode*, ExpressionNode* tail, ExpressionNode* next) |
847 | { |
848 | ASSERT(tail->isCommaNode()); |
849 | ASSERT(next); |
850 | CommaNode* newTail = new (m_parserArena) CommaNode(location, next); |
851 | static_cast<CommaNode*>(tail)->setNext(newTail); |
852 | return newTail; |
853 | } |
854 | |
855 | int evalCount() const { return m_evalCount; } |
856 | |
857 | void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, const JSTextPosition& exprStart, const JSTextPosition& lhs, const JSTextPosition& rhs, bool hasAssignments) |
858 | { |
859 | operandStackDepth++; |
860 | m_binaryOperandStack.append(std::make_pair(current, BinaryOpInfo(exprStart, lhs, rhs, hasAssignments))); |
861 | } |
862 | |
863 | // Logic to handle datastructures used during parsing of binary expressions |
864 | void operatorStackPop(int& operatorStackDepth) |
865 | { |
866 | operatorStackDepth--; |
867 | m_binaryOperatorStack.removeLast(); |
868 | } |
869 | bool operatorStackShouldReduce(int precedence) |
870 | { |
871 | // If the current precedence of the operator stack is the same to the one of the given operator, |
872 | // it depends on the associative whether we reduce the stack. |
873 | // If the operator is right associative, we should not reduce the stack right now. |
874 | if (precedence == m_binaryOperatorStack.last().second) |
875 | return !(m_binaryOperatorStack.last().first & RightAssociativeBinaryOpTokenFlag); |
876 | return precedence < m_binaryOperatorStack.last().second; |
877 | } |
878 | const BinaryOperand& getFromOperandStack(int i) { return m_binaryOperandStack[m_binaryOperandStack.size() + i]; } |
879 | void shrinkOperandStackBy(int& operandStackDepth, int amount) |
880 | { |
881 | operandStackDepth -= amount; |
882 | ASSERT(operandStackDepth >= 0); |
883 | m_binaryOperandStack.shrink(m_binaryOperandStack.size() - amount); |
884 | } |
885 | void appendBinaryOperation(const JSTokenLocation& location, int& operandStackDepth, int&, const BinaryOperand& lhs, const BinaryOperand& rhs) |
886 | { |
887 | operandStackDepth++; |
888 | m_binaryOperandStack.append(std::make_pair(makeBinaryNode(location, m_binaryOperatorStack.last().first, lhs, rhs), BinaryOpInfo(lhs.second, rhs.second))); |
889 | } |
890 | void operatorStackAppend(int& operatorStackDepth, int op, int precedence) |
891 | { |
892 | operatorStackDepth++; |
893 | m_binaryOperatorStack.append(std::make_pair(op, precedence)); |
894 | } |
895 | ExpressionNode* popOperandStack(int&) |
896 | { |
897 | ExpressionNode* result = m_binaryOperandStack.last().first; |
898 | m_binaryOperandStack.removeLast(); |
899 | return result; |
900 | } |
901 | |
902 | void appendUnaryToken(int& tokenStackDepth, int type, const JSTextPosition& start) |
903 | { |
904 | tokenStackDepth++; |
905 | m_unaryTokenStack.append(std::make_pair(type, start)); |
906 | } |
907 | |
908 | int unaryTokenStackLastType(int&) |
909 | { |
910 | return m_unaryTokenStack.last().first; |
911 | } |
912 | |
913 | const JSTextPosition& unaryTokenStackLastStart(int&) |
914 | { |
915 | return m_unaryTokenStack.last().second; |
916 | } |
917 | |
918 | void unaryTokenStackRemoveLast(int& tokenStackDepth) |
919 | { |
920 | tokenStackDepth--; |
921 | m_unaryTokenStack.removeLast(); |
922 | } |
923 | |
924 | void assignmentStackAppend(int& assignmentStackDepth, ExpressionNode* node, const JSTextPosition& start, const JSTextPosition& divot, int assignmentCount, Operator op) |
925 | { |
926 | assignmentStackDepth++; |
927 | ASSERT(start.offset >= start.lineStartOffset); |
928 | ASSERT(divot.offset >= divot.lineStartOffset); |
929 | m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, assignmentCount, op)); |
930 | } |
931 | |
932 | ExpressionNode* createAssignment(const JSTokenLocation& location, int& assignmentStackDepth, ExpressionNode* rhs, int initialAssignmentCount, int currentAssignmentCount, const JSTextPosition& lastTokenEnd) |
933 | { |
934 | AssignmentInfo& info = m_assignmentInfoStack.last(); |
935 | ExpressionNode* result = makeAssignNode(location, info.m_node, info.m_op, rhs, info.m_initAssignments != initialAssignmentCount, info.m_initAssignments != currentAssignmentCount, info.m_start, info.m_divot + 1, lastTokenEnd); |
936 | m_assignmentInfoStack.removeLast(); |
937 | assignmentStackDepth--; |
938 | return result; |
939 | } |
940 | |
941 | const Identifier* getName(const Property& property) const { return property->name(); } |
942 | PropertyNode::Type getType(const Property& property) const { return property->type(); } |
943 | |
944 | bool isResolve(ExpressionNode* expr) const { return expr->isResolveNode(); } |
945 | |
946 | ExpressionNode* createDestructuringAssignment(const JSTokenLocation& location, DestructuringPattern pattern, ExpressionNode* initializer) |
947 | { |
948 | return new (m_parserArena) DestructuringAssignmentNode(location, pattern, initializer); |
949 | } |
950 | |
951 | ArrayPattern createArrayPattern(const JSTokenLocation&) |
952 | { |
953 | return new (m_parserArena) ArrayPatternNode(); |
954 | } |
955 | |
956 | void appendArrayPatternSkipEntry(ArrayPattern node, const JSTokenLocation& location) |
957 | { |
958 | node->appendIndex(ArrayPatternNode::BindingType::Elision, location, 0, nullptr); |
959 | } |
960 | |
961 | void appendArrayPatternEntry(ArrayPattern node, const JSTokenLocation& location, DestructuringPattern pattern, ExpressionNode* defaultValue) |
962 | { |
963 | node->appendIndex(ArrayPatternNode::BindingType::Element, location, pattern, defaultValue); |
964 | tryInferNameInPattern(pattern, defaultValue); |
965 | } |
966 | |
967 | void appendArrayPatternRestEntry(ArrayPattern node, const JSTokenLocation& location, DestructuringPattern pattern) |
968 | { |
969 | node->appendIndex(ArrayPatternNode::BindingType::RestElement, location, pattern, nullptr); |
970 | } |
971 | |
972 | void finishArrayPattern(ArrayPattern node, const JSTextPosition& divotStart, const JSTextPosition& divot, const JSTextPosition& divotEnd) |
973 | { |
974 | setExceptionLocation(node, divotStart, divot, divotEnd); |
975 | } |
976 | |
977 | ObjectPattern createObjectPattern(const JSTokenLocation&) |
978 | { |
979 | return new (m_parserArena) ObjectPatternNode(); |
980 | } |
981 | |
982 | void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, bool wasString, const Identifier& identifier, DestructuringPattern pattern, ExpressionNode* defaultValue) |
983 | { |
984 | node->appendEntry(location, identifier, wasString, pattern, defaultValue, ObjectPatternNode::BindingType::Element); |
985 | tryInferNameInPattern(pattern, defaultValue); |
986 | } |
987 | |
988 | void appendObjectPatternEntry(VM& vm, ObjectPattern node, const JSTokenLocation& location, ExpressionNode* propertyExpression, DestructuringPattern pattern, ExpressionNode* defaultValue) |
989 | { |
990 | node->appendEntry(vm, location, propertyExpression, pattern, defaultValue, ObjectPatternNode::BindingType::Element); |
991 | tryInferNameInPattern(pattern, defaultValue); |
992 | } |
993 | |
994 | void appendObjectPatternRestEntry(VM& vm, ObjectPattern node, const JSTokenLocation& location, DestructuringPattern pattern) |
995 | { |
996 | node->appendEntry(vm, location, nullptr, pattern, nullptr, ObjectPatternNode::BindingType::RestElement); |
997 | } |
998 | |
999 | void setContainsObjectRestElement(ObjectPattern node, bool containsRestElement) |
1000 | { |
1001 | node->setContainsRestElement(containsRestElement); |
1002 | } |
1003 | |
1004 | void setContainsComputedProperty(ObjectPattern node, bool containsComputedProperty) |
1005 | { |
1006 | node->setContainsComputedProperty(containsComputedProperty); |
1007 | } |
1008 | |
1009 | BindingPattern createBindingLocation(const JSTokenLocation&, const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end, AssignmentContext context) |
1010 | { |
1011 | return new (m_parserArena) BindingNode(boundProperty, start, end, context); |
1012 | } |
1013 | |
1014 | RestParameterNode* createRestParameter(DestructuringPatternNode* pattern, size_t numParametersToSkip) |
1015 | { |
1016 | return new (m_parserArena) RestParameterNode(pattern, numParametersToSkip); |
1017 | } |
1018 | |
1019 | AssignmentElement createAssignmentElement(const Expression& assignmentTarget, const JSTextPosition& start, const JSTextPosition& end) |
1020 | { |
1021 | return new (m_parserArena) AssignmentElementNode(assignmentTarget, start, end); |
1022 | } |
1023 | |
1024 | void setEndOffset(Node* node, int offset) |
1025 | { |
1026 | node->setEndOffset(offset); |
1027 | } |
1028 | |
1029 | int endOffset(Node* node) |
1030 | { |
1031 | return node->endOffset(); |
1032 | } |
1033 | |
1034 | void setStartOffset(CaseClauseNode* node, int offset) |
1035 | { |
1036 | node->setStartOffset(offset); |
1037 | } |
1038 | |
1039 | void setStartOffset(Node* node, int offset) |
1040 | { |
1041 | node->setStartOffset(offset); |
1042 | } |
1043 | |
1044 | JSTextPosition breakpointLocation(Node* node) |
1045 | { |
1046 | node->setNeedsDebugHook(); |
1047 | return node->position(); |
1048 | } |
1049 | |
1050 | void propagateArgumentsUse() { usesArguments(); } |
1051 | |
1052 | private: |
1053 | struct Scope { |
1054 | Scope() |
1055 | : m_features(0) |
1056 | , m_numConstants(0) |
1057 | { |
1058 | } |
1059 | int m_features; |
1060 | int m_numConstants; |
1061 | }; |
1062 | |
1063 | static void setExceptionLocation(ThrowableExpressionData* node, const JSTextPosition& divotStart, const JSTextPosition& divot, const JSTextPosition& divotEnd) |
1064 | { |
1065 | ASSERT(divot.offset >= divot.lineStartOffset); |
1066 | node->setExceptionSourceCode(divot, divotStart, divotEnd); |
1067 | } |
1068 | |
1069 | void incConstants() { m_scope.m_numConstants++; } |
1070 | void usesThis() { m_scope.m_features |= ThisFeature; } |
1071 | void usesArrowFunction() { m_scope.m_features |= ArrowFunctionFeature; } |
1072 | void usesArguments() { m_scope.m_features |= ArgumentsFeature; } |
1073 | void usesWith() { m_scope.m_features |= WithFeature; } |
1074 | void usesSuperCall() { m_scope.m_features |= SuperCallFeature; } |
1075 | void usesSuperProperty() { m_scope.m_features |= SuperPropertyFeature; } |
1076 | void usesEval() |
1077 | { |
1078 | m_evalCount++; |
1079 | m_scope.m_features |= EvalFeature; |
1080 | } |
1081 | void usesNewTarget() { m_scope.m_features |= NewTargetFeature; } |
1082 | ExpressionNode* createIntegerLikeNumber(const JSTokenLocation& location, double d) |
1083 | { |
1084 | return new (m_parserArena) IntegerNode(location, d); |
1085 | } |
1086 | ExpressionNode* createDoubleLikeNumber(const JSTokenLocation& location, double d) |
1087 | { |
1088 | return new (m_parserArena) DoubleNode(location, d); |
1089 | } |
1090 | ExpressionNode* createBigIntWithSign(const JSTokenLocation& location, const Identifier& bigInt, uint8_t radix, bool sign) |
1091 | { |
1092 | return new (m_parserArena) BigIntNode(location, bigInt, radix, sign); |
1093 | } |
1094 | ExpressionNode* createNumberFromBinaryOperation(const JSTokenLocation& location, double value, const NumberNode& originalNodeA, const NumberNode& originalNodeB) |
1095 | { |
1096 | if (originalNodeA.isIntegerNode() && originalNodeB.isIntegerNode()) |
1097 | return createIntegerLikeNumber(location, value); |
1098 | return createDoubleLikeNumber(location, value); |
1099 | } |
1100 | ExpressionNode* createNumberFromUnaryOperation(const JSTokenLocation& location, double value, const NumberNode& originalNode) |
1101 | { |
1102 | if (originalNode.isIntegerNode()) |
1103 | return createIntegerLikeNumber(location, value); |
1104 | return createDoubleLikeNumber(location, value); |
1105 | } |
1106 | ExpressionNode* createBigIntFromUnaryOperation(const JSTokenLocation& location, bool sign, const BigIntNode& originalNode) |
1107 | { |
1108 | return createBigIntWithSign(location, originalNode.identifier(), originalNode.radix(), sign); |
1109 | } |
1110 | |
1111 | void tryInferNameInPattern(DestructuringPattern pattern, ExpressionNode* defaultValue) |
1112 | { |
1113 | if (!defaultValue) |
1114 | return; |
1115 | |
1116 | if (pattern->isBindingNode()) { |
1117 | const Identifier& ident = static_cast<BindingNode*>(pattern)->boundProperty(); |
1118 | tryInferNameInPatternWithIdentifier(ident, defaultValue); |
1119 | } else if (pattern->isAssignmentElementNode()) { |
1120 | const ExpressionNode* assignmentTarget = static_cast<AssignmentElementNode*>(pattern)->assignmentTarget(); |
1121 | if (assignmentTarget->isResolveNode()) { |
1122 | const Identifier& ident = static_cast<const ResolveNode*>(assignmentTarget)->identifier(); |
1123 | tryInferNameInPatternWithIdentifier(ident, defaultValue); |
1124 | } |
1125 | } |
1126 | } |
1127 | |
1128 | void tryInferNameInPatternWithIdentifier(const Identifier& ident, ExpressionNode* defaultValue) |
1129 | { |
1130 | if (defaultValue->isBaseFuncExprNode()) { |
1131 | auto metadata = static_cast<BaseFuncExprNode*>(defaultValue)->metadata(); |
1132 | metadata->setEcmaName(ident); |
1133 | } else if (defaultValue->isClassExprNode()) |
1134 | static_cast<ClassExprNode*>(defaultValue)->setEcmaName(ident); |
1135 | } |
1136 | |
1137 | VM& m_vm; |
1138 | ParserArena& m_parserArena; |
1139 | SourceCode* m_sourceCode; |
1140 | Scope m_scope; |
1141 | Vector<BinaryOperand, 10, UnsafeVectorOverflow> m_binaryOperandStack; |
1142 | Vector<AssignmentInfo, 10, UnsafeVectorOverflow> m_assignmentInfoStack; |
1143 | Vector<std::pair<int, int>, 10, UnsafeVectorOverflow> m_binaryOperatorStack; |
1144 | Vector<std::pair<int, JSTextPosition>, 10, UnsafeVectorOverflow> m_unaryTokenStack; |
1145 | int m_evalCount; |
1146 | }; |
1147 | |
1148 | ExpressionNode* ASTBuilder::makeTypeOfNode(const JSTokenLocation& location, ExpressionNode* expr) |
1149 | { |
1150 | if (expr->isResolveNode()) { |
1151 | ResolveNode* resolve = static_cast<ResolveNode*>(expr); |
1152 | return new (m_parserArena) TypeOfResolveNode(location, resolve->identifier()); |
1153 | } |
1154 | return new (m_parserArena) TypeOfValueNode(location, expr); |
1155 | } |
1156 | |
1157 | ExpressionNode* ASTBuilder::makeDeleteNode(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
1158 | { |
1159 | if (expr->isOptionalChain()) { |
1160 | OptionalChainNode* optionalChain = static_cast<OptionalChainNode*>(expr); |
1161 | if (optionalChain->expr()->isLocation()) { |
1162 | ASSERT(!optionalChain->expr()->isResolveNode()); |
1163 | optionalChain->setExpr(makeDeleteNode(location, optionalChain->expr(), start, divot, end)); |
1164 | return optionalChain; |
1165 | } |
1166 | } |
1167 | |
1168 | if (!expr->isLocation()) |
1169 | return new (m_parserArena) DeleteValueNode(location, expr); |
1170 | if (expr->isResolveNode()) { |
1171 | ResolveNode* resolve = static_cast<ResolveNode*>(expr); |
1172 | return new (m_parserArena) DeleteResolveNode(location, resolve->identifier(), divot, start, end); |
1173 | } |
1174 | if (expr->isBracketAccessorNode()) { |
1175 | BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); |
1176 | return new (m_parserArena) DeleteBracketNode(location, bracket->base(), bracket->subscript(), divot, start, end); |
1177 | } |
1178 | ASSERT(expr->isDotAccessorNode()); |
1179 | DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); |
1180 | return new (m_parserArena) DeleteDotNode(location, dot->base(), dot->identifier(), divot, start, end); |
1181 | } |
1182 | |
1183 | ExpressionNode* ASTBuilder::makeNegateNode(const JSTokenLocation& location, ExpressionNode* n) |
1184 | { |
1185 | if (n->isNumber()) { |
1186 | const NumberNode& numberNode = static_cast<const NumberNode&>(*n); |
1187 | return createNumberFromUnaryOperation(location, -numberNode.value(), numberNode); |
1188 | } |
1189 | |
1190 | if (n->isBigInt()) { |
1191 | const BigIntNode& bigIntNode = static_cast<const BigIntNode&>(*n); |
1192 | return createBigIntFromUnaryOperation(location, !bigIntNode.sign(), bigIntNode); |
1193 | } |
1194 | |
1195 | return new (m_parserArena) NegateNode(location, n); |
1196 | } |
1197 | |
1198 | ExpressionNode* ASTBuilder::makeBitwiseNotNode(const JSTokenLocation& location, ExpressionNode* expr) |
1199 | { |
1200 | if (expr->isNumber()) |
1201 | return createIntegerLikeNumber(location, ~toInt32(static_cast<NumberNode*>(expr)->value())); |
1202 | return new (m_parserArena) BitwiseNotNode(location, expr); |
1203 | } |
1204 | |
1205 | ExpressionNode* ASTBuilder::makePowNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1206 | { |
1207 | auto* strippedExpr1 = expr1->stripUnaryPlus(); |
1208 | auto* strippedExpr2 = expr2->stripUnaryPlus(); |
1209 | |
1210 | if (strippedExpr1->isNumber() && strippedExpr2->isNumber()) { |
1211 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*strippedExpr1); |
1212 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*strippedExpr2); |
1213 | return createNumberFromBinaryOperation(location, operationMathPow(numberExpr1.value(), numberExpr2.value()), numberExpr1, numberExpr2); |
1214 | } |
1215 | |
1216 | if (strippedExpr1->isNumber()) |
1217 | expr1 = strippedExpr1; |
1218 | if (strippedExpr2->isNumber()) |
1219 | expr2 = strippedExpr2; |
1220 | |
1221 | return new (m_parserArena) PowNode(location, expr1, expr2, rightHasAssignments); |
1222 | } |
1223 | |
1224 | ExpressionNode* ASTBuilder::makeMultNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1225 | { |
1226 | // FIXME: Unary + change the evaluation order. |
1227 | // https://bugs.webkit.org/show_bug.cgi?id=159968 |
1228 | expr1 = expr1->stripUnaryPlus(); |
1229 | expr2 = expr2->stripUnaryPlus(); |
1230 | |
1231 | if (expr1->isNumber() && expr2->isNumber()) { |
1232 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1233 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1234 | return createNumberFromBinaryOperation(location, numberExpr1.value() * numberExpr2.value(), numberExpr1, numberExpr2); |
1235 | } |
1236 | |
1237 | if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1) |
1238 | return new (m_parserArena) UnaryPlusNode(location, expr2); |
1239 | |
1240 | if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1) |
1241 | return new (m_parserArena) UnaryPlusNode(location, expr1); |
1242 | |
1243 | return new (m_parserArena) MultNode(location, expr1, expr2, rightHasAssignments); |
1244 | } |
1245 | |
1246 | ExpressionNode* ASTBuilder::makeDivNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1247 | { |
1248 | // FIXME: Unary + change the evaluation order. |
1249 | // https://bugs.webkit.org/show_bug.cgi?id=159968 |
1250 | expr1 = expr1->stripUnaryPlus(); |
1251 | expr2 = expr2->stripUnaryPlus(); |
1252 | |
1253 | if (expr1->isNumber() && expr2->isNumber()) { |
1254 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1255 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1256 | double result = numberExpr1.value() / numberExpr2.value(); |
1257 | if (static_cast<int64_t>(result) == result) |
1258 | return createNumberFromBinaryOperation(location, result, numberExpr1, numberExpr2); |
1259 | return createDoubleLikeNumber(location, result); |
1260 | } |
1261 | return new (m_parserArena) DivNode(location, expr1, expr2, rightHasAssignments); |
1262 | } |
1263 | |
1264 | ExpressionNode* ASTBuilder::makeModNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1265 | { |
1266 | // FIXME: Unary + change the evaluation order. |
1267 | // https://bugs.webkit.org/show_bug.cgi?id=159968 |
1268 | expr1 = expr1->stripUnaryPlus(); |
1269 | expr2 = expr2->stripUnaryPlus(); |
1270 | |
1271 | if (expr1->isNumber() && expr2->isNumber()) { |
1272 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1273 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1274 | return createIntegerLikeNumber(location, fmod(numberExpr1.value(), numberExpr2.value())); |
1275 | } |
1276 | return new (m_parserArena) ModNode(location, expr1, expr2, rightHasAssignments); |
1277 | } |
1278 | |
1279 | ExpressionNode* ASTBuilder::makeAddNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1280 | { |
1281 | |
1282 | if (expr1->isNumber() && expr2->isNumber()) { |
1283 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1284 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1285 | return createNumberFromBinaryOperation(location, numberExpr1.value() + numberExpr2.value(), numberExpr1, numberExpr2); |
1286 | } |
1287 | return new (m_parserArena) AddNode(location, expr1, expr2, rightHasAssignments); |
1288 | } |
1289 | |
1290 | ExpressionNode* ASTBuilder::makeSubNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1291 | { |
1292 | // FIXME: Unary + change the evaluation order. |
1293 | // https://bugs.webkit.org/show_bug.cgi?id=159968 |
1294 | expr1 = expr1->stripUnaryPlus(); |
1295 | expr2 = expr2->stripUnaryPlus(); |
1296 | |
1297 | if (expr1->isNumber() && expr2->isNumber()) { |
1298 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1299 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1300 | return createNumberFromBinaryOperation(location, numberExpr1.value() - numberExpr2.value(), numberExpr1, numberExpr2); |
1301 | } |
1302 | return new (m_parserArena) SubNode(location, expr1, expr2, rightHasAssignments); |
1303 | } |
1304 | |
1305 | ExpressionNode* ASTBuilder::makeLeftShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1306 | { |
1307 | if (expr1->isNumber() && expr2->isNumber()) { |
1308 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1309 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1310 | return createIntegerLikeNumber(location, toInt32(numberExpr1.value()) << (toUInt32(numberExpr2.value()) & 0x1f)); |
1311 | } |
1312 | return new (m_parserArena) LeftShiftNode(location, expr1, expr2, rightHasAssignments); |
1313 | } |
1314 | |
1315 | ExpressionNode* ASTBuilder::makeRightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1316 | { |
1317 | if (expr1->isNumber() && expr2->isNumber()) { |
1318 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1319 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1320 | return createIntegerLikeNumber(location, toInt32(numberExpr1.value()) >> (toUInt32(numberExpr2.value()) & 0x1f)); |
1321 | } |
1322 | return new (m_parserArena) RightShiftNode(location, expr1, expr2, rightHasAssignments); |
1323 | } |
1324 | |
1325 | ExpressionNode* ASTBuilder::makeURightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1326 | { |
1327 | if (expr1->isNumber() && expr2->isNumber()) { |
1328 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1329 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1330 | return createIntegerLikeNumber(location, toUInt32(numberExpr1.value()) >> (toUInt32(numberExpr2.value()) & 0x1f)); |
1331 | } |
1332 | return new (m_parserArena) UnsignedRightShiftNode(location, expr1, expr2, rightHasAssignments); |
1333 | } |
1334 | |
1335 | ExpressionNode* ASTBuilder::makeBitOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1336 | { |
1337 | if (expr1->isNumber() && expr2->isNumber()) { |
1338 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1339 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1340 | return createIntegerLikeNumber(location, toInt32(numberExpr1.value()) | toInt32(numberExpr2.value())); |
1341 | } |
1342 | return new (m_parserArena) BitOrNode(location, expr1, expr2, rightHasAssignments); |
1343 | } |
1344 | |
1345 | ExpressionNode* ASTBuilder::makeBitAndNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1346 | { |
1347 | if (expr1->isNumber() && expr2->isNumber()) { |
1348 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1349 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1350 | return createIntegerLikeNumber(location, toInt32(numberExpr1.value()) & toInt32(numberExpr2.value())); |
1351 | } |
1352 | return new (m_parserArena) BitAndNode(location, expr1, expr2, rightHasAssignments); |
1353 | } |
1354 | |
1355 | ExpressionNode* ASTBuilder::makeBitXOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
1356 | { |
1357 | if (expr1->isNumber() && expr2->isNumber()) { |
1358 | const NumberNode& numberExpr1 = static_cast<NumberNode&>(*expr1); |
1359 | const NumberNode& numberExpr2 = static_cast<NumberNode&>(*expr2); |
1360 | return createIntegerLikeNumber(location, toInt32(numberExpr1.value()) ^ toInt32(numberExpr2.value())); |
1361 | } |
1362 | return new (m_parserArena) BitXOrNode(location, expr1, expr2, rightHasAssignments); |
1363 | } |
1364 | |
1365 | ExpressionNode* ASTBuilder::makeCoalesceNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2) |
1366 | { |
1367 | // Optimization for `x?.y ?? z`. |
1368 | if (expr1->isOptionalChain()) { |
1369 | OptionalChainNode* optionalChain = static_cast<OptionalChainNode*>(expr1); |
1370 | if (!optionalChain->expr()->isDeleteNode()) { |
1371 | constexpr bool hasAbsorbedOptionalChain = true; |
1372 | return new (m_parserArena) CoalesceNode(location, optionalChain->expr(), expr2, hasAbsorbedOptionalChain); |
1373 | } |
1374 | } |
1375 | constexpr bool hasAbsorbedOptionalChain = false; |
1376 | return new (m_parserArena) CoalesceNode(location, expr1, expr2, hasAbsorbedOptionalChain); |
1377 | } |
1378 | |
1379 | ExpressionNode* ASTBuilder::makeFunctionCallNode(const JSTokenLocation& location, ExpressionNode* func, bool previousBaseWasSuper, ArgumentsNode* args, const JSTextPosition& divotStart, const JSTextPosition& divot, const JSTextPosition& divotEnd, size_t callOrApplyChildDepth, bool isOptionalCall) |
1380 | { |
1381 | ASSERT(divot.offset >= divot.lineStartOffset); |
1382 | if (func->isSuperNode()) |
1383 | usesSuperCall(); |
1384 | |
1385 | if (func->isBytecodeIntrinsicNode()) { |
1386 | ASSERT(!isOptionalCall); |
1387 | BytecodeIntrinsicNode* intrinsic = static_cast<BytecodeIntrinsicNode*>(func); |
1388 | if (intrinsic->type() == BytecodeIntrinsicNode::Type::Constant && intrinsic->entry().type() == BytecodeIntrinsicRegistry::Type::Emitter) |
1389 | return new (m_parserArena) BytecodeIntrinsicNode(BytecodeIntrinsicNode::Type::Function, location, intrinsic->entry(), intrinsic->identifier(), args, divot, divotStart, divotEnd); |
1390 | } |
1391 | |
1392 | if (func->isOptionalChain()) { |
1393 | OptionalChainNode* optionalChain = static_cast<OptionalChainNode*>(func); |
1394 | if (optionalChain->expr()->isLocation()) { |
1395 | ASSERT(!optionalChain->expr()->isResolveNode()); |
1396 | // We must take care to preserve our `this` value in cases like `a?.b?.()` and `(a?.b)()`, respectively. |
1397 | if (isOptionalCall) |
1398 | return makeFunctionCallNode(location, optionalChain->expr(), previousBaseWasSuper, args, divotStart, divot, divotEnd, callOrApplyChildDepth, isOptionalCall); |
1399 | optionalChain->setExpr(makeFunctionCallNode(location, optionalChain->expr(), previousBaseWasSuper, args, divotStart, divot, divotEnd, callOrApplyChildDepth, isOptionalCall)); |
1400 | return optionalChain; |
1401 | } |
1402 | } |
1403 | |
1404 | if (!func->isLocation()) |
1405 | return new (m_parserArena) FunctionCallValueNode(location, func, args, divot, divotStart, divotEnd); |
1406 | if (func->isResolveNode()) { |
1407 | ResolveNode* resolve = static_cast<ResolveNode*>(func); |
1408 | const Identifier& identifier = resolve->identifier(); |
1409 | if (identifier == m_vm.propertyNames->eval) { |
1410 | usesEval(); |
1411 | return new (m_parserArena) EvalFunctionCallNode(location, args, divot, divotStart, divotEnd); |
1412 | } |
1413 | return new (m_parserArena) FunctionCallResolveNode(location, identifier, args, divot, divotStart, divotEnd); |
1414 | } |
1415 | if (func->isBracketAccessorNode()) { |
1416 | BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func); |
1417 | FunctionCallBracketNode* node = new (m_parserArena) FunctionCallBracketNode(location, bracket->base(), bracket->subscript(), bracket->subscriptHasAssignments(), args, divot, divotStart, divotEnd); |
1418 | node->setSubexpressionInfo(bracket->divot(), bracket->divotEnd().offset); |
1419 | return node; |
1420 | } |
1421 | ASSERT(func->isDotAccessorNode()); |
1422 | DotAccessorNode* dot = static_cast<DotAccessorNode*>(func); |
1423 | FunctionCallDotNode* node = nullptr; |
1424 | if (!previousBaseWasSuper && (dot->identifier() == m_vm.propertyNames->builtinNames().callPublicName() || dot->identifier() == m_vm.propertyNames->builtinNames().callPrivateName())) |
1425 | node = new (m_parserArena) CallFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd, callOrApplyChildDepth); |
1426 | else if (!previousBaseWasSuper && (dot->identifier() == m_vm.propertyNames->builtinNames().applyPublicName() || dot->identifier() == m_vm.propertyNames->builtinNames().applyPrivateName())) { |
1427 | // FIXME: This check is only needed because we haven't taught the bytecode generator to inline |
1428 | // Reflect.apply yet. See https://bugs.webkit.org/show_bug.cgi?id=190668. |
1429 | if (!dot->base()->isResolveNode() || static_cast<ResolveNode*>(dot->base())->identifier() != "Reflect" ) |
1430 | node = new (m_parserArena) ApplyFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd, callOrApplyChildDepth); |
1431 | } |
1432 | if (!node) |
1433 | node = new (m_parserArena) FunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd); |
1434 | node->setSubexpressionInfo(dot->divot(), dot->divotEnd().offset); |
1435 | return node; |
1436 | } |
1437 | |
1438 | ExpressionNode* ASTBuilder::makeBinaryNode(const JSTokenLocation& location, int token, std::pair<ExpressionNode*, BinaryOpInfo> lhs, std::pair<ExpressionNode*, BinaryOpInfo> rhs) |
1439 | { |
1440 | switch (token) { |
1441 | case COALESCE: |
1442 | return makeCoalesceNode(location, lhs.first, rhs.first); |
1443 | |
1444 | case OR: |
1445 | return new (m_parserArena) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalOr); |
1446 | |
1447 | case AND: |
1448 | return new (m_parserArena) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalAnd); |
1449 | |
1450 | case BITOR: |
1451 | return makeBitOrNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1452 | |
1453 | case BITXOR: |
1454 | return makeBitXOrNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1455 | |
1456 | case BITAND: |
1457 | return makeBitAndNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1458 | |
1459 | case EQEQ: |
1460 | return new (m_parserArena) EqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1461 | |
1462 | case NE: |
1463 | return new (m_parserArena) NotEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1464 | |
1465 | case STREQ: |
1466 | return new (m_parserArena) StrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1467 | |
1468 | case STRNEQ: |
1469 | return new (m_parserArena) NotStrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1470 | |
1471 | case LT: |
1472 | return new (m_parserArena) LessNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1473 | |
1474 | case GT: |
1475 | return new (m_parserArena) GreaterNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1476 | |
1477 | case LE: |
1478 | return new (m_parserArena) LessEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1479 | |
1480 | case GE: |
1481 | return new (m_parserArena) GreaterEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1482 | |
1483 | case INSTANCEOF: { |
1484 | InstanceOfNode* node = new (m_parserArena) InstanceOfNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1485 | setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); |
1486 | return node; |
1487 | } |
1488 | |
1489 | case INTOKEN: { |
1490 | InNode* node = new (m_parserArena) InNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1491 | setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); |
1492 | return node; |
1493 | } |
1494 | |
1495 | case LSHIFT: |
1496 | return makeLeftShiftNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1497 | |
1498 | case RSHIFT: |
1499 | return makeRightShiftNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1500 | |
1501 | case URSHIFT: |
1502 | return makeURightShiftNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1503 | |
1504 | case PLUS: |
1505 | return makeAddNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1506 | |
1507 | case MINUS: |
1508 | return makeSubNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1509 | |
1510 | case TIMES: |
1511 | return makeMultNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1512 | |
1513 | case DIVIDE: |
1514 | return makeDivNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1515 | |
1516 | case MOD: |
1517 | return makeModNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1518 | |
1519 | case POW: |
1520 | return makePowNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); |
1521 | } |
1522 | CRASH(); |
1523 | return 0; |
1524 | } |
1525 | |
1526 | ExpressionNode* ASTBuilder::makeAssignNode(const JSTokenLocation& location, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
1527 | { |
1528 | if (!loc->isLocation()) { |
1529 | ASSERT(loc->isFunctionCall()); |
1530 | return new (m_parserArena) AssignErrorNode(location, divot, start, end); |
1531 | } |
1532 | |
1533 | if (loc->isResolveNode()) { |
1534 | ResolveNode* resolve = static_cast<ResolveNode*>(loc); |
1535 | if (op == OpEqual) { |
1536 | if (expr->isBaseFuncExprNode()) { |
1537 | auto metadata = static_cast<BaseFuncExprNode*>(expr)->metadata(); |
1538 | metadata->setEcmaName(resolve->identifier()); |
1539 | } else if (expr->isClassExprNode()) |
1540 | static_cast<ClassExprNode*>(expr)->setEcmaName(resolve->identifier()); |
1541 | AssignResolveNode* node = new (m_parserArena) AssignResolveNode(location, resolve->identifier(), expr, AssignmentContext::AssignmentExpression); |
1542 | setExceptionLocation(node, start, divot, end); |
1543 | return node; |
1544 | } |
1545 | return new (m_parserArena) ReadModifyResolveNode(location, resolve->identifier(), op, expr, exprHasAssignments, divot, start, end); |
1546 | } |
1547 | if (loc->isBracketAccessorNode()) { |
1548 | BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc); |
1549 | if (op == OpEqual) |
1550 | return new (m_parserArena) AssignBracketNode(location, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), start, end); |
1551 | ReadModifyBracketNode* node = new (m_parserArena) ReadModifyBracketNode(location, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, start, end); |
1552 | node->setSubexpressionInfo(bracket->divot(), bracket->divotEnd().offset); |
1553 | return node; |
1554 | } |
1555 | ASSERT(loc->isDotAccessorNode()); |
1556 | DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc); |
1557 | if (op == OpEqual) |
1558 | return new (m_parserArena) AssignDotNode(location, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), start, end); |
1559 | |
1560 | ReadModifyDotNode* node = new (m_parserArena) ReadModifyDotNode(location, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, start, end); |
1561 | node->setSubexpressionInfo(dot->divot(), dot->divotEnd().offset); |
1562 | return node; |
1563 | } |
1564 | |
1565 | ExpressionNode* ASTBuilder::makePrefixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
1566 | { |
1567 | return new (m_parserArena) PrefixNode(location, expr, op, divot, start, end); |
1568 | } |
1569 | |
1570 | ExpressionNode* ASTBuilder::makePostfixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) |
1571 | { |
1572 | return new (m_parserArena) PostfixNode(location, expr, op, divot, start, end); |
1573 | } |
1574 | |
1575 | } |
1576 | |