Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qv4compilerscanfunctions.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtCore/QCoreApplication>
7#include <QtCore/QStringList>
8#include <QtCore/QSet>
9#include <QtCore/QBuffer>
10#include <QtCore/QBitArray>
11#include <QtCore/QStack>
12#include <private/qqmljsast_p.h>
13#include <private/qv4compilercontext_p.h>
14#include <private/qv4codegen_p.h>
15
17using namespace QV4;
18using namespace QV4::Compiler;
19using namespace QQmlJS;
20using namespace QQmlJS::AST;
21
23{
24 return CompiledData::Location(astLocation.startLine, astLocation.startColumn);
25}
26
27
28ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, ContextType defaultProgramType)
29 : QQmlJS::AST::Visitor(cg->recursionDepth())
30 , _cg(cg)
31 , _sourceCode(sourceCode)
32 , _context(nullptr)
33 , _allowFuncDecls(true)
34 , defaultProgramType(defaultProgramType)
35{
36}
37
39{
40 if (node)
41 node->accept(this);
42
44}
45
47{
48 enterEnvironment(astNodeForGlobalEnvironment, compilationMode, QStringLiteral("%GlobalCode"));
49}
50
51void ScanFunctions::enterEnvironment(Node *node, ContextType compilationMode, const QString &name)
52{
53 Context *c = _cg->_module->contextMap.value(node);
54 if (!c)
55 c = _cg->_module->newContext(node, _context, compilationMode);
56 if (!c->isStrict)
58 c->name = name;
59 _contextStack.append(c);
60 _context = c;
61}
62
68
70{
72 for (StatementList *it = ast; it; it = it->next) {
73 if (ExpressionStatement *expr = cast<ExpressionStatement *>(it->statement)) {
74 if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) {
75 // Use the source code, because the StringLiteral's
76 // value might have escape sequences in it, which is not
77 // allowed.
78 if (strLit->literalToken.length < 2)
79 continue;
80 QStringView str = QStringView{_sourceCode}.mid(strLit->literalToken.offset + 1, strLit->literalToken.length - 2);
81 if (str == QLatin1String("use strict")) {
82 _context->isStrict = true;
83 } else {
84 // TODO: give a warning.
85 }
86 continue;
87 }
88 }
89
90 break;
91 }
92}
93
95{
97 if (_context->isStrict) {
98 if (name == QLatin1String("implements")
99 || name == QLatin1String("interface")
100 || name == QLatin1String("let")
101 || name == QLatin1String("package")
102 || name == QLatin1String("private")
103 || name == QLatin1String("protected")
104 || name == QLatin1String("public")
105 || name == QLatin1String("static")
106 || name == QLatin1String("yield")) {
107 _cg->throwSyntaxError(loc, QStringLiteral("Unexpected strict mode reserved word"));
108 }
109 }
110}
111
113{
116 return true;
117}
118
123
125{
128 _context->isStrict = true;
129 return true;
130}
131
136
138{
140 QString module;
141 if (declaration->fromClause) {
142 module = declaration->fromClause->moduleSpecifier.toString();
143 if (!module.isEmpty())
144 _context->moduleRequests << module;
145 }
146
147 QString localNameForDefaultExport = QStringLiteral("*default*");
148
149 if (declaration->exportsAll()) {
150 Q_ASSERT_X(declaration->fromClause, "ScanFunctions",
151 "ExportDeclaration with exportAll always have a fromClause");
154 entry.importName = QStringLiteral("*");
155 entry.location = location(declaration->firstSourceLocation());
157 } else if (declaration->exportClause) {
158 for (ExportsList *it = declaration->exportClause->exportsList; it; it = it->next) {
159 ExportSpecifier *spec = it->exportSpecifier;
161 if (module.isEmpty())
163 else
164 entry.importName = spec->identifier.toString();
165
166 entry.moduleRequest = module;
167 entry.exportName = spec->exportedIdentifier.toString();
168 entry.location = location(it->firstSourceLocation());
169
171 }
172 } else if (auto *vstmt = AST::cast<AST::VariableStatement*>(declaration->variableStatementOrDeclaration)) {
173 BoundNames boundNames;
174 for (VariableDeclarationList *it = vstmt->declarations; it; it = it->next) {
175 if (!it->declaration)
176 continue;
177 it->declaration->boundNames(&boundNames);
178 }
179 for (const auto &name: boundNames) {
181 entry.localName = name.id;
182 entry.exportName = name.id;
183 entry.location = location(vstmt->firstSourceLocation());
185 }
186 } else if (auto *classDecl = AST::cast<AST::ClassDeclaration*>(declaration->variableStatementOrDeclaration)) {
187 QString name = classDecl->name.toString();
188 if (!name.isEmpty()) {
191 entry.exportName = name;
192 entry.location = location(classDecl->firstSourceLocation());
194 if (declaration->exportDefault)
195 localNameForDefaultExport = entry.localName;
196 }
197 } else if (auto *fdef = declaration->variableStatementOrDeclaration->asFunctionDefinition()) {
198 QString functionName;
199
200 // Only function definitions for which we enter their name into the local environment
201 // can result in exports. Nested expressions such as (function foo() {}) are not accessible
202 // as locals and can only be exported as default exports (further down).
203 auto ast = declaration->variableStatementOrDeclaration;
204 if (AST::cast<AST::ExpressionStatement*>(ast) || AST::cast<AST::FunctionDeclaration*>(ast))
205 functionName = fdef->name.toString();
206
207 if (!functionName.isEmpty()) {
209 entry.localName = functionName;
210 entry.exportName = functionName;
211 entry.location = location(fdef->firstSourceLocation());
213 if (declaration->exportDefault)
214 localNameForDefaultExport = entry.localName;
215 }
216 }
217
218 if (declaration->exportDefault) {
220 entry.localName = localNameForDefaultExport;
221 _context->localNameForDefaultExport = localNameForDefaultExport;
222 entry.exportName = QStringLiteral("default");
223 entry.location = location(declaration->firstSourceLocation());
225 }
226
227 return true; // scan through potential assignment expression code, etc.
228}
229
231{
233 QString module;
234 if (declaration->fromClause) {
235 module = declaration->fromClause->moduleSpecifier.toString();
236 if (!module.isEmpty())
237 _context->moduleRequests << module;
238 }
239
240 if (!declaration->moduleSpecifier.isEmpty())
242
243 if (ImportClause *import = declaration->importClause) {
244 if (!import->importedDefaultBinding.isEmpty()) {
246 entry.moduleRequest = module;
247 entry.importName = QStringLiteral("default");
248 entry.localName = import->importedDefaultBinding.toString();
249 entry.location = location(declaration->firstSourceLocation());
251 }
252
253 if (import->nameSpaceImport) {
255 entry.moduleRequest = module;
256 entry.importName = QStringLiteral("*");
257 entry.localName = import->nameSpaceImport->importedBinding.toString();
258 entry.location = location(declaration->firstSourceLocation());
260 }
261
262 if (import->namedImports) {
263 for (ImportsList *it = import->namedImports->importsList; it; it = it->next) {
265 entry.moduleRequest = module;
266 entry.localName = it->importSpecifier->importedBinding.toString();
267 if (!it->importSpecifier->identifier.isEmpty())
268 entry.importName = it->importSpecifier->identifier.toString();
269 else
270 entry.importName = entry.localName;
271 entry.location = location(declaration->firstSourceLocation());
273 }
274 }
275 }
276 return false;
277}
278
280{
282 if (!_context->hasDirectEval) {
283 if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
284 if (id->name == QLatin1String("eval")) {
287 _context->hasDirectEval = true;
288 }
289 }
290 }
291 return true;
292}
293
295{
297 if (!ast->isVariableDeclaration())
298 return true;
299
301 ast->boundNames(&names);
302
303 QQmlJS::SourceLocation declarationLocation = ast->firstSourceLocation();
305 declarationLocation.length = _context->lastBlockInitializerLocation.end()
306 - declarationLocation.offset;
307 } else {
308 declarationLocation.length = ast->lastSourceLocation().end() - declarationLocation.offset;
309 }
310
311 for (const auto &name : std::as_const(names)) {
312 if (_context->isStrict && (name.id == QLatin1String("eval") || name.id == QLatin1String("arguments")))
313 _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Variable name may not be eval or arguments in strict mode"));
315 if (name.id == QLatin1String("arguments"))
317 if (ast->scope == VariableScope::Const && !ast->initializer && !ast->isForDeclaration && !ast->destructuringPattern()) {
318 _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Missing initializer in const declaration"));
319 return false;
320 }
322 /*function*/nullptr, declarationLocation)) {
323 _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Identifier %1 has already been declared").arg(name.id));
324 return false;
325 }
326 }
327 return true;
328}
329
339
341{
342 if (FunctionExpression* expr = AST::cast<AST::FunctionExpression*>(ast->expression)) {
343 if (!_allowFuncDecls)
344 _cg->throwSyntaxError(expr->functionToken, QStringLiteral("conditional function or closure declaration"));
345
346 if (!enterFunction(expr, expr->identifierToken.length > 0
349 return false;
350 }
351 Node::accept(expr->formals, this);
352 Node::accept(expr->body, this);
354 return false;
355 } else {
356 SourceLocation firstToken = ast->firstSourceLocation();
357 if (QStringView{_sourceCode}.mid(firstToken.offset, firstToken.length) == QLatin1String("function")) {
358 _cg->throwSyntaxError(firstToken, QStringLiteral("unexpected token"));
359 }
360 }
361 return true;
362}
363
370
372{
375 _context->isStrict = true;
377 if (!ast->name.isEmpty())
378 _context->addLocalVar(ast->name.toString(), Context::VariableDefinition, AST::VariableScope::Const);
379 return true;
380}
381
386
388{
390 if (!ast->name.isEmpty())
391 _context->addLocalVar(ast->name.toString(), Context::VariableDeclaration, AST::VariableScope::Let);
392
394 _context->isStrict = true;
396 if (!ast->name.isEmpty())
397 _context->addLocalVar(ast->name.toString(), Context::VariableDefinition, AST::VariableScope::Const);
398 return true;
399}
400
405
407{
408 while (ast) {
409 if (ast->expression)
410 Node::accept(ast->expression, this);
411 ast = ast->next;
412 }
413 return true;
414
415}
416
418{
420 Context *c = _context;
421 bool needContext = false;
422 while (c->contextType == ContextType::Block || c->isArrowFunction) {
423 needContext |= c->isArrowFunction;
424 c = c->parent;
425 }
426
427 c->requiresExecutionContext |= needContext;
428
429 return false;
430}
431
433{
434 if (AST::IdentifierExpression *id = AST::cast<AST::IdentifierExpression *>(ast->base)) {
435 if (id->name == QLatin1String("new")) {
436 // new.target
437 if (ast->name != QLatin1String("target")) {
438 _cg->throwSyntaxError(ast->identifierToken, QLatin1String("Expected 'target' after 'new.'."));
439 return false;
440 }
442 Context *c = _context;
443 bool needContext = false;
444 while (c->contextType == ContextType::Block || c->isArrowFunction) {
445 needContext |= c->isArrowFunction;
446 c = c->parent;
447 }
448 c->requiresExecutionContext |= needContext;
449 c->innerFunctionAccessesNewTarget |= needContext;
450
451 return false;
452 }
453 }
454
455 return true;
456}
457
459{
460 for (PatternElementList *it = ast->elements; it; it = it->next)
461 Node::accept(it->element, this);
462
463 return false;
464}
465
467{
469 if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
470 _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Function name may not be eval or arguments in strict mode"));
471 return enterFunction(ast, ast->name.toString(), ast->formals, ast->body, nameContext);
472}
473
478
480{
481 TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
482 Node::accept(ast->properties, this);
483 return false;
484}
485
487{
488 Q_UNUSED(ast);
489 // ### Shouldn't be required anymore
490// if (ast->type == PatternProperty::Getter || ast->type == PatternProperty::Setter) {
491// TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
492// return enterFunction(ast, QString(), ast->formals, ast->functionBody, /*enterName */ false);
493// }
494 return true;
495}
496
498{
499 // ###
500// if (ast->type == PatternProperty::Getter || ast->type == PatternProperty::Setter)
501// leaveEnvironment();
502}
503
508
513
515 {
516 TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_context->isStrict);
517 Node::accept(ast->statement, this);
518 }
519 Node::accept(ast->expression, this);
520 return false;
521}
522
525 Node::accept(ast->initialiser, this);
526 Node::accept(ast->declarations, this);
527 Node::accept(ast->condition, this);
528 Node::accept(ast->expression, this);
529
530 TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_context->isStrict);
531 Node::accept(ast->statement, this);
532
533 return false;
534}
535
540
542{
544 if (ast->expression) {
547 }
548 Node::accept(ast->lhs, this);
549 Node::accept(ast->expression, this);
550
551 TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_context->isStrict);
552 Node::accept(ast->statement, this);
553
554 return false;
555}
556
561
563{
565 _context->usesThis = true;
566 return false;
567}
568
570{
571 TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
573 Node::accept(ast->statements, this);
574 return false;
575}
576
581
583{
585 return true;
586}
587
592
594{
596 TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
598 _context->isCatchBlock = true;
600 if (caughtVar.isEmpty())
601 caughtVar = QStringLiteral("@caught");
602 _context->addLocalVar(caughtVar, Context::MemberType::VariableDefinition, VariableScope::Let);
603
604 _context->caughtVariable = caughtVar;
605 if (_context->isStrict &&
606 (caughtVar == QLatin1String("eval") || caughtVar == QLatin1String("arguments"))) {
607 _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Catch variable name may not be eval or arguments in strict mode"));
608 return false;
609 }
610 Node::accept(ast->patternElement, this);
611 // skip the block statement
612 Node::accept(ast->statement->statements, this);
613 return false;
614}
615
620
622{
624 Node::accept(ast->expression, this);
625
626 TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
628 _context->isWithBlock = true;
629
630 if (_context->isStrict) {
631 _cg->throwSyntaxError(ast->withToken, QStringLiteral("'with' statement is not allowed in strict mode"));
632 return false;
633 }
634 Node::accept(ast->statement, this);
635
636 return false;
637}
638
643
645 Node *ast, const QString &name, FormalParameterList *formals, StatementList *body,
646 FunctionNameContext nameContext)
647{
648 Context *outerContext = _context;
650
651 FunctionExpression *expr = AST::cast<FunctionExpression *>(ast);
652 if (!expr)
653 expr = AST::cast<FunctionDeclaration *>(ast);
654 if (outerContext) {
655 outerContext->hasNestedFunctions = true;
656 // The identifier of a function expression cannot be referenced from the enclosing environment.
657 if (nameContext == FunctionNameContext::Outer) {
658 if (!outerContext->addLocalVar(name, Context::FunctionDefinition, VariableScope::Var, expr)) {
659 _cg->throwSyntaxError(ast->firstSourceLocation(), QStringLiteral("Identifier %1 has already been declared").arg(name));
660 return false;
661 }
662 outerContext->addLocalVar(name, Context::FunctionDefinition, VariableScope::Var, expr);
663 }
664 if (name == QLatin1String("arguments"))
666 }
667
669 _context->name = name;
670 if (formals && formals->containsName(QStringLiteral("arguments")))
672 if (expr) {
673 if (expr->isArrowFunction)
675 else if (expr->isGenerator)
676 _context->isGenerator = true;
677
678 if (expr->typeAnnotation)
680 }
681
682
683 if (nameContext == FunctionNameContext::Inner
684 && (!name.isEmpty() && (!formals || !formals->containsName(name)))) {
685 _context->addLocalVar(name, Context::ThisFunctionName, VariableScope::Var);
686 }
687 _context->formals = formals;
688
689 if (body && !_context->isStrict)
691
692 bool isSimpleParameterList = formals && formals->isSimpleParameterList();
693
694 _context->arguments = formals ? formals->formals() : BoundNames();
695
696 const BoundNames boundNames = formals ? formals->boundNames() : BoundNames();
697 for (int i = 0; i < boundNames.size(); ++i) {
698 const auto &arg = boundNames.at(i);
699 if (_context->isStrict || !isSimpleParameterList) {
700 bool duplicate = (boundNames.indexOf(arg.id, i + 1) != -1);
701 if (duplicate) {
702 _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("Duplicate parameter name '%1' is not allowed.").arg(arg.id));
703 return false;
704 }
705 }
706 if (_context->isStrict) {
707 if (arg.id == QLatin1String("eval") || arg.id == QLatin1String("arguments")) {
708 _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("'%1' cannot be used as parameter name in strict mode").arg(arg.id));
709 return false;
710 }
711 }
712 if (!_context->arguments.contains(arg.id)) {
713 _context->addLocalVar(arg.id, Context::VariableDefinition, VariableScope::Var, nullptr,
714 QQmlJS::SourceLocation(), arg.isInjected());
715 }
716 }
717
718 return true;
719}
720
722{
723 Module *m = _cg->_module;
724
725 for (Context *inner : std::as_const(m->contextMap)) {
726 if (inner->usesArgumentsObject != Context::ArgumentsObjectUsed)
727 continue;
728 if (inner->contextType != ContextType::Block && !inner->isArrowFunction)
729 continue;
730 Context *c = inner->parent;
731 while (c && (c->contextType == ContextType::Block || c->isArrowFunction))
732 c = c->parent;
733 if (c)
734 c->usesArgumentsObject = Context::ArgumentsObjectUsed;
735 inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
736 }
737 for (Context *inner : std::as_const(m->contextMap)) {
738 if (!inner->parent || inner->usesArgumentsObject == Context::ArgumentsObjectUnknown)
739 inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
740 if (inner->usesArgumentsObject == Context::ArgumentsObjectUsed) {
741 QString arguments = QStringLiteral("arguments");
742 inner->addLocalVar(arguments, Context::VariableDeclaration, AST::VariableScope::Var);
743 if (!inner->isStrict) {
744 inner->argumentsCanEscape = true;
745 inner->requiresExecutionContext = true;
746 }
747 }
748 }
749
750 for (Context *c : std::as_const(m->contextMap)) {
751 if (c->contextType != ContextType::ESModule)
752 continue;
753 for (const auto &entry: c->exportEntries) {
754 auto mIt = c->members.constFind(entry.localName);
755 if (mIt != c->members.constEnd())
756 mIt->canEscape = true;
757 }
758 break;
759 }
760
761 for (Context *inner : std::as_const(m->contextMap)) {
762 for (const QString &var : std::as_const(inner->usedVariables)) {
763 Context *c = inner;
764 while (c) {
765 Context *current = c;
766 c = c->parent;
767 if (current->isWithBlock || current->contextType != ContextType::Block)
768 break;
769 }
770 Q_ASSERT(c != inner);
771 while (c) {
772 Context::MemberMap::const_iterator it = c->members.constFind(var);
773 if (it != c->members.constEnd()) {
774 if (c->parent || it->isLexicallyScoped()) {
775 it->canEscape = true;
776 c->requiresExecutionContext = true;
777 } else if (c->contextType == ContextType::ESModule) {
778 // Module instantiation provides a context, but vars used from inner
779 // scopes need to be stored in its locals[].
780 it->canEscape = true;
781 }
782 break;
783 }
784 if (c->hasArgument(var)) {
785 c->argumentsCanEscape = true;
786 c->requiresExecutionContext = true;
787 break;
788 }
789 c = c->parent;
790 }
791 }
792 if (inner->hasDirectEval) {
793 inner->hasDirectEval = false;
794 inner->innerFunctionAccessesNewTarget = true;
795 if (!inner->isStrict) {
796 Context *c = inner;
797 while (c->contextType == ContextType::Block) {
798 c = c->parent;
799 }
800 Q_ASSERT(c);
801 c->hasDirectEval = true;
802 c->innerFunctionAccessesThis = true;
803 }
804 Context *c = inner;
805 while (c) {
806 c->allVarsEscape = true;
807 c = c->parent;
808 }
809 }
810 if (inner->usesThis) {
811 inner->usesThis = false;
812 bool innerFunctionAccessesThis = false;
813 Context *c = inner;
814 while (c->contextType == ContextType::Block || c->isArrowFunction) {
815 innerFunctionAccessesThis |= c->isArrowFunction;
816 c = c->parent;
817 }
818 Q_ASSERT(c);
819 if (!inner->isStrict)
820 c->usesThis = true;
821 c->innerFunctionAccessesThis |= innerFunctionAccessesThis;
822 }
823 }
824 for (Context *c : std::as_const(m->contextMap)) {
825 if (c->innerFunctionAccessesThis) {
826 // add an escaping 'this' variable
827 c->addLocalVar(QStringLiteral("this"), Context::VariableDefinition, VariableScope::Let);
828 c->requiresExecutionContext = true;
829 auto mIt = c->members.constFind(QStringLiteral("this"));
830 Q_ASSERT(mIt != c->members.constEnd());
831 mIt->canEscape = true;
832 }
833 if (c->innerFunctionAccessesNewTarget) {
834 // add an escaping 'new.target' variable
835 c->addLocalVar(QStringLiteral("new.target"), Context::VariableDefinition, VariableScope::Let);
836 c->requiresExecutionContext = true;
837 auto mIt = c->members.constFind(QStringLiteral("new.target"));
838 Q_ASSERT(mIt != c->members.constEnd());
839 mIt->canEscape = true;
840 }
841 if (c->allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty())
842 c->allVarsEscape = false;
843 if (c->contextType == ContextType::Global || c->contextType == ContextType::ScriptImportedByQML || (!c->isStrict && c->contextType == ContextType::Eval) || m->debugMode)
844 c->allVarsEscape = true;
845 if (c->allVarsEscape) {
846 if (c->parent) {
847 c->requiresExecutionContext = true;
848 c->argumentsCanEscape = true;
849 } else {
850 for (const auto &m : std::as_const(c->members)) {
851 if (m.isLexicallyScoped()) {
852 c->requiresExecutionContext = true;
853 break;
854 }
855 }
856 }
857 }
858 if (c->contextType == ContextType::Block && c->isCatchBlock) {
859 c->requiresExecutionContext = true;
860 auto mIt = c->members.constFind(c->caughtVariable);
861 Q_ASSERT(mIt != c->members.constEnd());
862 mIt->canEscape = true;
863 }
864 const QLatin1String exprForOn("expression for on");
865 if (c->contextType == ContextType::Binding && c->name.size() > exprForOn.size() &&
866 c->name.startsWith(exprForOn) && c->name.at(exprForOn.size()).isUpper())
867 // we don't really need this for bindings, but we do for signal handlers, and in this case,
868 // we don't know if the code is a signal handler or not.
869 c->requiresExecutionContext = true;
870 if (c->allVarsEscape) {
871 for (const auto &m : std::as_const(c->members))
872 m.canEscape = true;
873 }
874 }
875
876 static const bool showEscapingVars = qEnvironmentVariableIsSet("QV4_SHOW_ESCAPING_VARS");
877 if (showEscapingVars) {
878 qDebug() << "==== escaping variables ====";
879 for (Context *c : std::as_const(m->contextMap)) {
880 qDebug() << "Context" << c << c->name << "requiresExecutionContext" << c->requiresExecutionContext << "isStrict" << c->isStrict;
881 qDebug() << " isArrowFunction" << c->isArrowFunction << "innerFunctionAccessesThis" << c->innerFunctionAccessesThis;
882 qDebug() << " parent:" << c->parent;
883 if (c->argumentsCanEscape)
884 qDebug() << " Arguments escape";
885 for (auto it = c->members.constBegin(); it != c->members.constEnd(); ++it) {
886 qDebug() << " " << it.key() << it.value().index << it.value().canEscape << "isLexicallyScoped:" << it.value().isLexicallyScoped();
887 }
888 }
889 }
890}
891
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
PatternElementList * elements
StatementList * statements
SourceLocation identifierToken
PatternElement * patternElement
SourceLocation firstSourceLocation() const override
SourceLocation firstSourceLocation() const override
ExpressionNode * expression
VariableDeclarationList * declarations
ExpressionNode * initialiser
ExpressionNode * condition
SourceLocation firstSourceLocation() const override
bool containsName(const QString &name) const
FormalParameterList * formals
SourceLocation firstSourceLocation() const override
virtual SourceLocation lastSourceLocation() const =0
virtual FunctionExpression * asFunctionDefinition()
Definition qqmljsast.cpp:69
PatternPropertyList * properties
SourceLocation identifierToken
SourceLocation firstSourceLocation() const override
ExpressionNode * initializer
SourceLocation lastSourceLocation() const override
Pattern * destructuringPattern() const
virtual void boundNames(BoundNames *names)
bool isVariableDeclaration() const
StatementList * statements
ExpressionNode * expression
ExpressionNode * expression
bool isEmpty() const
Definition qset.h:52
const_iterator constBegin() const noexcept
Definition qset.h:139
const_iterator constEnd() const noexcept
Definition qset.h:143
const_iterator constFind(const T &value) const
Definition qset.h:161
\inmodule QtCore
Definition qstringview.h:78
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
QString toString() const
Returns a deep copy of this string view's data as a QString.
Definition qstring.h:1121
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
virtual void throwSyntaxError(const QQmlJS::SourceLocation &loc, const QString &detail)
void throwRecursionDepthError() override
bool visit(QQmlJS::AST::Program *ast) override
bool enterFunction(QQmlJS::AST::FunctionExpression *ast, FunctionNameContext nameContext)
ScanFunctions(Codegen *cg, const QString &sourceCode, ContextType defaultProgramType)
void checkName(QStringView name, const QQmlJS::SourceLocation &loc)
void checkDirectivePrologue(QQmlJS::AST::StatementList *ast)
void endVisit(QQmlJS::AST::Program *) override
void enterEnvironment(QQmlJS::AST::Node *node, ContextType compilationMode, const QString &name)
void enterGlobalEnvironment(ContextType compilationMode)
void operator()(QQmlJS::AST::Node *node)
QString str
[2]
QSet< QString >::iterator it
QList< QVariant > arguments
#define qDebug
[1]
Definition qlogging.h:164
GLint location
const GLfloat * m
GLenum GLuint id
[7]
GLuint name
const GLubyte * c
GLuint GLuint * names
GLuint entry
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
SSL_CTX int void * arg
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
#define Q_UNUSED(x)
QObject::connect nullptr
bool contains(const QString &name) const
int indexOf(const QString &name, int from=0) const
QQmlJS::AST::FormalParameterList * formals
QQmlJS::AST::BoundNames arguments
QVector< ImportEntry > importEntries
UsesArgumentsObject usesArgumentsObject
QVector< ExportEntry > exportEntries
QQmlJS::AST::Type * returnType
QQmlJS::SourceLocation lastBlockInitializerLocation
void addUsedVariable(const QString &name)
bool addLocalVar(const QString &name, MemberType contextType, QQmlJS::AST::VariableScope scope, QQmlJS::AST::FunctionExpression *function=nullptr, const QQmlJS::SourceLocation &declarationLocation=QQmlJS::SourceLocation(), bool isInjected=false)
Context * newContext(QQmlJS::AST::Node *node, Context *parent, ContextType compilationMode)
QHash< QQmlJS::AST::Node *, Context * > contextMap