1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "qmljsevaluate.h"
27 #include "qmljscontext.h"
28 #include "qmljsscopechain.h"
29 #include "qmljsvalueowner.h"
30 #include "parser/qmljsast_p.h"
31
32 #include <QDebug>
33
34 using namespace QmlJS;
35
36 /*!
37 \class QmlJS::Evaluate
38 \brief The Evaluate class evaluates \l{AST::Node}s to \l{Value}s.
39 \sa Value ScopeChain
40
41 The Evaluate visitor is constructed with a ScopeChain and accepts JavaScript
42 expressions as well as some other AST::Nodes. It evaluates the expression in
43 the given ScopeChain and returns a Value representing the result.
44
45 Example: Pass in the AST for "1 + 2" and NumberValue will be returned.
46
47 In normal cases only the call operator (or the equivalent value() function)
48 will be used.
49
50 The reference() function has the special behavior of not resolving \l{Reference}s
51 which can be useful when interested in the identity of a variable instead
52 of its value.
53
54 Example: In a scope where "var a = 1"
55 \list
56 \li value(Identifier-a) will return NumberValue
57 \li reference(Identifier-a) will return the ASTVariableReference for the declaration of "a"
58 \endlist
59 */
60
Evaluate(const ScopeChain * scopeChain,ReferenceContext * referenceContext)61 Evaluate::Evaluate(const ScopeChain *scopeChain, ReferenceContext *referenceContext)
62 : _valueOwner(scopeChain->context()->valueOwner()),
63 _context(scopeChain->context()),
64 _referenceContext(referenceContext),
65 _scopeChain(scopeChain),
66 _result(nullptr)
67 {
68 }
69
~Evaluate()70 Evaluate::~Evaluate()
71 {
72 }
73
operator ()(AST::Node * ast)74 const Value *Evaluate::operator()(AST::Node *ast)
75 {
76 return value(ast);
77 }
78
value(AST::Node * ast)79 const Value *Evaluate::value(AST::Node *ast)
80 {
81 const Value *result = reference(ast);
82
83 if (const Reference *ref = value_cast<Reference>(result)) {
84 if (_referenceContext)
85 result = _referenceContext->lookupReference(ref);
86 else
87 result = _context->lookupReference(ref);
88 }
89
90 // if evaluation fails, return an unknown value
91 if (! result)
92 result = _valueOwner->unknownValue();
93
94 return result;
95 }
96
reference(AST::Node * ast)97 const Value *Evaluate::reference(AST::Node *ast)
98 {
99 // save the result
100 const Value *previousResult = switchResult(nullptr);
101
102 // process the expression
103 accept(ast);
104
105 // restore the previous result
106 return switchResult(previousResult);
107 }
108
switchResult(const Value * result)109 const Value *Evaluate::switchResult(const Value *result)
110 {
111 const Value *previousResult = _result;
112 _result = result;
113 return previousResult;
114 }
115
accept(AST::Node * node)116 void Evaluate::accept(AST::Node *node)
117 {
118 AST::Node::accept(node, this);
119 }
120
visit(AST::UiProgram *)121 bool Evaluate::visit(AST::UiProgram *)
122 {
123 return false;
124 }
125
visit(AST::UiHeaderItemList *)126 bool Evaluate::visit(AST::UiHeaderItemList *)
127 {
128 return false;
129 }
130
visit(AST::UiPragma *)131 bool Evaluate::visit(AST::UiPragma *)
132 {
133 return false;
134 }
135
visit(AST::UiImport *)136 bool Evaluate::visit(AST::UiImport *)
137 {
138 return false;
139 }
140
visit(AST::UiPublicMember *)141 bool Evaluate::visit(AST::UiPublicMember *)
142 {
143 return false;
144 }
145
visit(AST::UiSourceElement *)146 bool Evaluate::visit(AST::UiSourceElement *)
147 {
148 return false;
149 }
150
visit(AST::UiObjectDefinition *)151 bool Evaluate::visit(AST::UiObjectDefinition *)
152 {
153 return false;
154 }
155
visit(AST::UiObjectInitializer *)156 bool Evaluate::visit(AST::UiObjectInitializer *)
157 {
158 return false;
159 }
160
visit(AST::UiObjectBinding *)161 bool Evaluate::visit(AST::UiObjectBinding *)
162 {
163 return false;
164 }
165
visit(AST::UiScriptBinding *)166 bool Evaluate::visit(AST::UiScriptBinding *)
167 {
168 return false;
169 }
170
visit(AST::UiArrayBinding *)171 bool Evaluate::visit(AST::UiArrayBinding *)
172 {
173 return false;
174 }
175
visit(AST::UiObjectMemberList *)176 bool Evaluate::visit(AST::UiObjectMemberList *)
177 {
178 return false;
179 }
180
visit(AST::UiArrayMemberList *)181 bool Evaluate::visit(AST::UiArrayMemberList *)
182 {
183 return false;
184 }
185
visit(AST::UiQualifiedId * ast)186 bool Evaluate::visit(AST::UiQualifiedId *ast)
187 {
188 if (ast->name.isEmpty())
189 return false;
190
191 const Value *value = _scopeChain->lookup(ast->name.toString());
192 if (! ast->next) {
193 _result = value;
194
195 } else {
196 const ObjectValue *base = value_cast<ObjectValue>(value);
197
198 for (AST::UiQualifiedId *it = ast->next; base && it; it = it->next) {
199 const QString &name = it->name.toString();
200 if (name.isEmpty())
201 break;
202
203 const Value *value = base->lookupMember(name, _context);
204 if (! it->next)
205 _result = value;
206 else
207 base = value_cast<ObjectValue>(value);
208 }
209 }
210
211 return false;
212 }
213
visit(AST::ThisExpression *)214 bool Evaluate::visit(AST::ThisExpression *)
215 {
216 return false;
217 }
218
visit(AST::IdentifierExpression * ast)219 bool Evaluate::visit(AST::IdentifierExpression *ast)
220 {
221 if (ast->name.isEmpty())
222 return false;
223
224 _result = _scopeChain->lookup(ast->name.toString());
225 return false;
226 }
227
visit(AST::NullExpression *)228 bool Evaluate::visit(AST::NullExpression *)
229 {
230 _result = _valueOwner->nullValue();
231 return false;
232 }
233
visit(AST::TrueLiteral *)234 bool Evaluate::visit(AST::TrueLiteral *)
235 {
236 _result = _valueOwner->booleanValue();
237 return false;
238 }
239
visit(AST::FalseLiteral *)240 bool Evaluate::visit(AST::FalseLiteral *)
241 {
242 _result = _valueOwner->booleanValue();
243 return false;
244 }
245
visit(AST::StringLiteral *)246 bool Evaluate::visit(AST::StringLiteral *)
247 {
248 _result = _valueOwner->stringValue();
249 return false;
250 }
251
visit(AST::NumericLiteral *)252 bool Evaluate::visit(AST::NumericLiteral *)
253 {
254 _result = _valueOwner->numberValue();
255 return false;
256 }
257
visit(AST::RegExpLiteral *)258 bool Evaluate::visit(AST::RegExpLiteral *)
259 {
260 _result = _valueOwner->regexpCtor()->returnValue();
261 return false;
262 }
263
visit(AST::ArrayPattern *)264 bool Evaluate::visit(AST::ArrayPattern *)
265 {
266 _result = _valueOwner->arrayCtor()->returnValue();
267 return false;
268 }
269
visit(AST::ObjectPattern *)270 bool Evaluate::visit(AST::ObjectPattern *)
271 {
272 // ### properties
273 _result = _valueOwner->newObject();
274 return false;
275 }
276
visit(AST::PatternElementList *)277 bool Evaluate::visit(AST::PatternElementList *)
278 {
279 return false;
280 }
281
visit(AST::Elision *)282 bool Evaluate::visit(AST::Elision *)
283 {
284 return false;
285 }
286
visit(AST::PatternPropertyList *)287 bool Evaluate::visit(AST::PatternPropertyList *)
288 {
289 return false;
290 }
291
visit(AST::PatternProperty *)292 bool Evaluate::visit(AST::PatternProperty *)
293 {
294 return false;
295 }
296
visit(AST::NestedExpression *)297 bool Evaluate::visit(AST::NestedExpression *)
298 {
299 return true; // visit the child expression
300 }
301
visit(AST::IdentifierPropertyName *)302 bool Evaluate::visit(AST::IdentifierPropertyName *)
303 {
304 return false;
305 }
306
visit(AST::StringLiteralPropertyName *)307 bool Evaluate::visit(AST::StringLiteralPropertyName *)
308 {
309 return false;
310 }
311
visit(AST::NumericLiteralPropertyName *)312 bool Evaluate::visit(AST::NumericLiteralPropertyName *)
313 {
314 return false;
315 }
316
visit(AST::ArrayMemberExpression *)317 bool Evaluate::visit(AST::ArrayMemberExpression *)
318 {
319 return false;
320 }
321
visit(AST::FieldMemberExpression * ast)322 bool Evaluate::visit(AST::FieldMemberExpression *ast)
323 {
324 if (ast->name.isEmpty())
325 return false;
326
327 if (const Value *base = _valueOwner->convertToObject(value(ast->base))) {
328 if (const ObjectValue *obj = base->asObjectValue())
329 _result = obj->lookupMember(ast->name.toString(), _context);
330 }
331
332 return false;
333 }
334
visit(AST::NewMemberExpression * ast)335 bool Evaluate::visit(AST::NewMemberExpression *ast)
336 {
337 if (const FunctionValue *ctor = value_cast<FunctionValue>(value(ast->base)))
338 _result = ctor->returnValue();
339 return false;
340 }
341
visit(AST::NewExpression * ast)342 bool Evaluate::visit(AST::NewExpression *ast)
343 {
344 if (const FunctionValue *ctor = value_cast<FunctionValue>(value(ast->expression)))
345 _result = ctor->returnValue();
346 return false;
347 }
348
visit(AST::CallExpression * ast)349 bool Evaluate::visit(AST::CallExpression *ast)
350 {
351 if (const Value *base = value(ast->base)) {
352 if (const FunctionValue *obj = base->asFunctionValue())
353 _result = obj->returnValue();
354 }
355 return false;
356 }
357
visit(AST::ArgumentList *)358 bool Evaluate::visit(AST::ArgumentList *)
359 {
360 return false;
361 }
362
visit(AST::PostIncrementExpression *)363 bool Evaluate::visit(AST::PostIncrementExpression *)
364 {
365 _result = _valueOwner->numberValue();
366 return false;
367 }
368
visit(AST::PostDecrementExpression *)369 bool Evaluate::visit(AST::PostDecrementExpression *)
370 {
371 _result = _valueOwner->numberValue();
372 return false;
373 }
374
visit(AST::DeleteExpression *)375 bool Evaluate::visit(AST::DeleteExpression *)
376 {
377 _result = _valueOwner->booleanValue();
378 return false;
379 }
380
visit(AST::VoidExpression *)381 bool Evaluate::visit(AST::VoidExpression *)
382 {
383 _result = _valueOwner->undefinedValue();
384 return false;
385 }
386
visit(AST::TypeOfExpression *)387 bool Evaluate::visit(AST::TypeOfExpression *)
388 {
389 _result = _valueOwner->stringValue();
390 return false;
391 }
392
visit(AST::PreIncrementExpression *)393 bool Evaluate::visit(AST::PreIncrementExpression *)
394 {
395 _result = _valueOwner->numberValue();
396 return false;
397 }
398
visit(AST::PreDecrementExpression *)399 bool Evaluate::visit(AST::PreDecrementExpression *)
400 {
401 _result = _valueOwner->numberValue();
402 return false;
403 }
404
visit(AST::UnaryPlusExpression *)405 bool Evaluate::visit(AST::UnaryPlusExpression *)
406 {
407 _result = _valueOwner->numberValue();
408 return false;
409 }
410
visit(AST::UnaryMinusExpression *)411 bool Evaluate::visit(AST::UnaryMinusExpression *)
412 {
413 _result = _valueOwner->numberValue();
414 return false;
415 }
416
visit(AST::TildeExpression *)417 bool Evaluate::visit(AST::TildeExpression *)
418 {
419 _result = _valueOwner->numberValue();
420 return false;
421 }
422
visit(AST::NotExpression *)423 bool Evaluate::visit(AST::NotExpression *)
424 {
425 _result = _valueOwner->booleanValue();
426 return false;
427 }
428
visit(AST::BinaryExpression * ast)429 bool Evaluate::visit(AST::BinaryExpression *ast)
430 {
431 const Value *lhs = nullptr;
432 const Value *rhs = nullptr;
433 switch (ast->op) {
434 case QSOperator::Add:
435 case QSOperator::InplaceAdd:
436 //case QSOperator::And: // ### enable once implemented below
437 //case QSOperator::Or:
438 lhs = value(ast->left);
439 Q_FALLTHROUGH();
440 case QSOperator::Assign:
441 rhs = value(ast->right);
442 break;
443 default:
444 break;
445 }
446
447 switch (ast->op) {
448 case QSOperator::Add:
449 case QSOperator::InplaceAdd:
450 if (lhs->asStringValue() || rhs->asStringValue())
451 _result = _valueOwner->stringValue();
452 else
453 _result = _valueOwner->numberValue();
454 break;
455
456 case QSOperator::Sub:
457 case QSOperator::InplaceSub:
458 case QSOperator::Mul:
459 case QSOperator::InplaceMul:
460 case QSOperator::Div:
461 case QSOperator::InplaceDiv:
462 case QSOperator::Mod:
463 case QSOperator::InplaceMod:
464 case QSOperator::BitAnd:
465 case QSOperator::InplaceAnd:
466 case QSOperator::BitXor:
467 case QSOperator::InplaceXor:
468 case QSOperator::BitOr:
469 case QSOperator::InplaceOr:
470 case QSOperator::LShift:
471 case QSOperator::InplaceLeftShift:
472 case QSOperator::RShift:
473 case QSOperator::InplaceRightShift:
474 case QSOperator::URShift:
475 case QSOperator::InplaceURightShift:
476 _result = _valueOwner->numberValue();
477 break;
478
479 case QSOperator::Le:
480 case QSOperator::Ge:
481 case QSOperator::Lt:
482 case QSOperator::Gt:
483 case QSOperator::Equal:
484 case QSOperator::NotEqual:
485 case QSOperator::StrictEqual:
486 case QSOperator::StrictNotEqual:
487 case QSOperator::InstanceOf:
488 case QSOperator::In:
489 _result = _valueOwner->booleanValue();
490 break;
491
492 case QSOperator::And:
493 case QSOperator::Or:
494 // ### either lhs or rhs
495 _result = _valueOwner->unknownValue();
496 break;
497
498 case QSOperator::Assign:
499 _result = rhs;
500 break;
501
502 default:
503 break;
504 }
505
506 return false;
507 }
508
visit(AST::ConditionalExpression *)509 bool Evaluate::visit(AST::ConditionalExpression *)
510 {
511 return false;
512 }
513
visit(AST::Expression *)514 bool Evaluate::visit(AST::Expression *)
515 {
516 return false;
517 }
518
visit(AST::Block *)519 bool Evaluate::visit(AST::Block *)
520 {
521 return false;
522 }
523
visit(AST::VariableStatement *)524 bool Evaluate::visit(AST::VariableStatement *)
525 {
526 return false;
527 }
528
visit(AST::VariableDeclarationList *)529 bool Evaluate::visit(AST::VariableDeclarationList *)
530 {
531 return false;
532 }
533
visit(AST::PatternElement *)534 bool Evaluate::visit(AST::PatternElement *)
535 {
536 return false;
537 }
538
visit(AST::EmptyStatement *)539 bool Evaluate::visit(AST::EmptyStatement *)
540 {
541 return false;
542 }
543
visit(AST::ExpressionStatement *)544 bool Evaluate::visit(AST::ExpressionStatement *)
545 {
546 return true;
547 }
548
visit(AST::IfStatement *)549 bool Evaluate::visit(AST::IfStatement *)
550 {
551 return false;
552 }
553
visit(AST::DoWhileStatement *)554 bool Evaluate::visit(AST::DoWhileStatement *)
555 {
556 return false;
557 }
558
visit(AST::WhileStatement *)559 bool Evaluate::visit(AST::WhileStatement *)
560 {
561 return false;
562 }
563
visit(AST::ForStatement *)564 bool Evaluate::visit(AST::ForStatement *)
565 {
566 return false;
567 }
568
visit(AST::ForEachStatement *)569 bool Evaluate::visit(AST::ForEachStatement *)
570 {
571 return false;
572 }
573
visit(AST::ContinueStatement *)574 bool Evaluate::visit(AST::ContinueStatement *)
575 {
576 return false;
577 }
578
visit(AST::BreakStatement *)579 bool Evaluate::visit(AST::BreakStatement *)
580 {
581 return false;
582 }
583
visit(AST::ReturnStatement *)584 bool Evaluate::visit(AST::ReturnStatement *)
585 {
586 return true;
587 }
588
visit(AST::WithStatement *)589 bool Evaluate::visit(AST::WithStatement *)
590 {
591 return false;
592 }
593
visit(AST::SwitchStatement *)594 bool Evaluate::visit(AST::SwitchStatement *)
595 {
596 return false;
597 }
598
visit(AST::CaseBlock *)599 bool Evaluate::visit(AST::CaseBlock *)
600 {
601 return false;
602 }
603
visit(AST::CaseClauses *)604 bool Evaluate::visit(AST::CaseClauses *)
605 {
606 return false;
607 }
608
visit(AST::CaseClause *)609 bool Evaluate::visit(AST::CaseClause *)
610 {
611 return false;
612 }
613
visit(AST::DefaultClause *)614 bool Evaluate::visit(AST::DefaultClause *)
615 {
616 return false;
617 }
618
visit(AST::LabelledStatement *)619 bool Evaluate::visit(AST::LabelledStatement *)
620 {
621 return false;
622 }
623
visit(AST::ThrowStatement *)624 bool Evaluate::visit(AST::ThrowStatement *)
625 {
626 return false;
627 }
628
visit(AST::TryStatement *)629 bool Evaluate::visit(AST::TryStatement *)
630 {
631 return false;
632 }
633
visit(AST::Catch *)634 bool Evaluate::visit(AST::Catch *)
635 {
636 return false;
637 }
638
visit(AST::Finally *)639 bool Evaluate::visit(AST::Finally *)
640 {
641 return false;
642 }
643
visit(AST::FunctionDeclaration *)644 bool Evaluate::visit(AST::FunctionDeclaration *)
645 {
646 return false;
647 }
648
visit(AST::FunctionExpression *)649 bool Evaluate::visit(AST::FunctionExpression *)
650 {
651 return false;
652 }
653
visit(AST::FormalParameterList *)654 bool Evaluate::visit(AST::FormalParameterList *)
655 {
656 return false;
657 }
658
visit(AST::Program *)659 bool Evaluate::visit(AST::Program *)
660 {
661 return false;
662 }
663
visit(AST::StatementList *)664 bool Evaluate::visit(AST::StatementList *)
665 {
666 return false;
667 }
668
visit(AST::DebuggerStatement *)669 bool Evaluate::visit(AST::DebuggerStatement *)
670 {
671 return false;
672 }
673
throwRecursionDepthError()674 void Evaluate::throwRecursionDepthError()
675 {
676 qWarning("Evaluate hit maximum recursion error when visiting AST");
677 }
678