6#include <QtCore/QCoreApplication>
7#include <QtCore/QStringList>
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>
31 , _sourceCode(sourceCode)
33 , _allowFuncDecls(true)
34 , defaultProgramType(defaultProgramType)
74 if (
StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) {
78 if (strLit->literalToken.length < 2)
151 "ExportDeclaration with exportAll always have a fromClause");
166 entry.moduleRequest = module;
175 if (!
it->declaration)
177 it->declaration->boundNames(&boundNames);
179 for (
const auto &
name: boundNames) {
188 if (!
name.isEmpty()) {
195 localNameForDefaultExport =
entry.localName;
204 if (AST::cast<AST::ExpressionStatement*>(ast) || AST::cast<AST::FunctionDeclaration*>(ast))
205 functionName = fdef->name.toString();
209 entry.localName = functionName;
210 entry.exportName = functionName;
214 localNameForDefaultExport =
entry.localName;
220 entry.localName = localNameForDefaultExport;
244 if (!import->importedDefaultBinding.isEmpty()) {
246 entry.moduleRequest = module;
248 entry.localName =
import->importedDefaultBinding.toString();
253 if (import->nameSpaceImport) {
255 entry.moduleRequest = module;
257 entry.localName =
import->nameSpaceImport->importedBinding.toString();
262 if (import->namedImports) {
265 entry.moduleRequest = module;
266 entry.localName =
it->importSpecifier->importedBinding.toString();
267 if (!
it->importSpecifier->identifier.
isEmpty())
268 entry.importName =
it->importSpecifier->identifier.toString();
306 - declarationLocation.
offset;
311 for (
const auto &
name : std::as_const(
names)) {
322 nullptr, declarationLocation)) {
351 Node::accept(expr->formals,
this);
352 Node::accept(expr->body,
this);
421 bool needContext =
false;
427 c->requiresExecutionContext |= needContext;
443 bool needContext =
false;
448 c->requiresExecutionContext |= needContext;
449 c->innerFunctionAccessesNewTarget |= needContext;
461 Node::accept(
it->element,
this);
548 Node::accept(ast->
lhs,
this);
646 FunctionNameContext nameContext)
653 expr = AST::cast<FunctionDeclaration *>(ast);
697 for (
int i = 0;
i < boundNames.
size(); ++
i) {
698 const auto &
arg = boundNames.
at(
i);
700 bool duplicate = (boundNames.
indexOf(
arg.id,
i + 1) != -1);
725 for (
Context *inner : std::as_const(
m->contextMap)) {
737 for (
Context *inner : std::as_const(
m->contextMap)) {
743 if (!inner->isStrict) {
744 inner->argumentsCanEscape =
true;
745 inner->requiresExecutionContext =
true;
750 for (
Context *
c : std::as_const(
m->contextMap)) {
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;
761 for (
Context *inner : std::as_const(
m->contextMap)) {
762 for (
const QString &
var : std::as_const(inner->usedVariables)) {
774 if (
c->parent ||
it->isLexicallyScoped()) {
775 it->canEscape =
true;
776 c->requiresExecutionContext =
true;
780 it->canEscape =
true;
784 if (
c->hasArgument(
var)) {
785 c->argumentsCanEscape =
true;
786 c->requiresExecutionContext =
true;
792 if (inner->hasDirectEval) {
793 inner->hasDirectEval =
false;
794 inner->innerFunctionAccessesNewTarget =
true;
795 if (!inner->isStrict) {
801 c->hasDirectEval =
true;
802 c->innerFunctionAccessesThis =
true;
810 if (inner->usesThis) {
811 inner->usesThis =
false;
812 bool innerFunctionAccessesThis =
false;
819 if (!inner->isStrict)
821 c->innerFunctionAccessesThis |= innerFunctionAccessesThis;
824 for (
Context *
c : std::as_const(
m->contextMap)) {
825 if (
c->innerFunctionAccessesThis) {
828 c->requiresExecutionContext =
true;
831 mIt->canEscape =
true;
833 if (
c->innerFunctionAccessesNewTarget) {
836 c->requiresExecutionContext =
true;
839 mIt->canEscape =
true;
842 c->allVarsEscape =
false;
844 c->allVarsEscape =
true;
845 if (
c->allVarsEscape) {
847 c->requiresExecutionContext =
true;
848 c->argumentsCanEscape =
true;
850 for (
const auto &
m : std::as_const(
c->members)) {
851 if (
m.isLexicallyScoped()) {
852 c->requiresExecutionContext =
true;
859 c->requiresExecutionContext =
true;
860 auto mIt =
c->members.constFind(
c->caughtVariable);
862 mIt->canEscape =
true;
866 c->name.startsWith(exprForOn) &&
c->name.at(exprForOn.
size()).isUpper())
869 c->requiresExecutionContext =
true;
870 if (
c->allVarsEscape) {
871 for (
const auto &
m : std::as_const(
c->members))
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";
886 qDebug() <<
" " <<
it.key() <<
it.value().index <<
it.value().canEscape <<
"isLexicallyScoped:" <<
it.value().isLexicallyScoped();
constexpr qsizetype size() const noexcept
qsizetype size() const noexcept
const_reference at(qsizetype i) const noexcept
PatternElementList * elements
StatementList * statements
SourceLocation identifierToken
PatternElement * patternElement
ExpressionNode * expression
ExportsList * exportsList
SourceLocation firstSourceLocation() const override
Node * variableStatementOrDeclaration
ExportClause * exportClause
QStringView exportedIdentifier
SourceLocation firstSourceLocation() const override
ExpressionNode * expression
SourceLocation identifierToken
ExpressionNode * expression
ExpressionNode * expression
VariableDeclarationList * declarations
ExpressionNode * initialiser
ExpressionNode * condition
QStringView moduleSpecifier
FormalParameterList * formals
SourceLocation identifierToken
TypeAnnotation * typeAnnotation
SourceLocation identifierToken
ImportClause * importClause
SourceLocation firstSourceLocation() const override
QStringView moduleSpecifier
virtual SourceLocation lastSourceLocation() const =0
virtual FunctionExpression * asFunctionDefinition()
PatternPropertyList * properties
SourceLocation identifierToken
SourceLocation firstSourceLocation() const override
QStringView bindingIdentifier
ExpressionNode * initializer
SourceLocation lastSourceLocation() const override
Pattern * destructuringPattern() const
virtual void boundNames(BoundNames *names)
bool isVariableDeclaration() const
StatementList * statements
ExpressionNode * expression
ExpressionNode * expression
const_iterator constBegin() const noexcept
const_iterator constEnd() const noexcept
const_iterator constFind(const T &value) const
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.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
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)
QStack< Context * > _contextStack
void throwRecursionDepthError() override
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)
ContextType defaultProgramType
void operator()(QQmlJS::AST::Node *node)
void calcEscapingVariables()
const QString _sourceCode
QSet< QString >::iterator it
QList< QVariant > arguments
\qmltype Particle \inqmlmodule QtQuick.Particles
#define Q_ASSERT_X(cond, x, msg)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
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
QString localNameForDefaultExport
QQmlJS::SourceLocation lastBlockInitializerLocation
void addUsedVariable(const QString &name)
QStringList moduleRequests
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