aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4compilerscanfunctions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4compilerscanfunctions.cpp')
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp52
1 files changed, 39 insertions, 13 deletions
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 5d3a7a6d8c..dafb1c360d 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -414,6 +414,17 @@ bool ScanFunctions::visit(TemplateLiteral *ast)
}
+bool ScanFunctions::visit(SuperLiteral *)
+{
+ Context *c = _context;
+ while (c && (c->contextType != ContextType::Function || c->isArrowFunction))
+ c = c->parent;
+
+ if (c)
+ c->requiresExecutionContext = true;
+
+ return false;
+}
bool ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName)
{
if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
@@ -656,13 +667,16 @@ void ScanFunctions::calcEscapingVariables()
Module *m = _cg->_module;
for (Context *inner : qAsConst(m->contextMap)) {
- if (inner->contextType == ContextType::Block && inner->usesArgumentsObject == Context::ArgumentsObjectUsed) {
- Context *c = inner->parent;
- while (c->contextType == ContextType::Block)
- c = c->parent;
+ if (inner->usesArgumentsObject != Context::ArgumentsObjectUsed)
+ continue;
+ if (inner->contextType != ContextType::Block && !inner->isArrowFunction)
+ continue;
+ Context *c = inner->parent;
+ while (c && (c->contextType == ContextType::Block || c->isArrowFunction))
+ c = c->parent;
+ if (c)
c->usesArgumentsObject = Context::ArgumentsObjectUsed;
- inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
- }
+ inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
}
for (Context *inner : qAsConst(m->contextMap)) {
if (!inner->parent || inner->usesArgumentsObject == Context::ArgumentsObjectUnknown)
@@ -728,6 +742,8 @@ void ScanFunctions::calcEscapingVariables()
}
Q_ASSERT(c);
c->hasDirectEval = true;
+ if (!c->isStrict)
+ c->innerFunctionAccessesThis = true;
}
Context *c = inner;
while (c) {
@@ -737,17 +753,26 @@ void ScanFunctions::calcEscapingVariables()
}
if (inner->usesThis) {
inner->usesThis = false;
- if (!inner->isStrict) {
- Context *c = inner;
- while (c->contextType == ContextType::Block) {
- c = c->parent;
- }
- Q_ASSERT(c);
- c->usesThis = true;
+ bool innerFunctionAccessesThis = false;
+ Context *c = inner;
+ while (c->contextType == ContextType::Block || c->isArrowFunction) {
+ innerFunctionAccessesThis |= c->isArrowFunction;
+ c = c->parent;
}
+ Q_ASSERT(c);
+ if (!inner->isStrict)
+ c->usesThis = true;
+ c->innerFunctionAccessesThis |= innerFunctionAccessesThis;
}
}
for (Context *c : qAsConst(m->contextMap)) {
+ if (c->innerFunctionAccessesThis) {
+ // add an escaping 'this' variable
+ c->addLocalVar(QStringLiteral("this"), Context::VariableDefinition, VariableScope::Let);
+ c->requiresExecutionContext = true;
+ auto m = c->members.find(QStringLiteral("this"));
+ m->canEscape = true;
+ }
if (c->allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty())
c->allVarsEscape = false;
if (c->contextType == ContextType::Global || (!c->isStrict && c->contextType == ContextType::Eval) || m->debugMode)
@@ -787,6 +812,7 @@ void ScanFunctions::calcEscapingVariables()
qDebug() << "==== escaping variables ====";
for (Context *c : qAsConst(m->contextMap)) {
qDebug() << "Context" << c << c->name << "requiresExecutionContext" << c->requiresExecutionContext << "isStrict" << c->isStrict;
+ qDebug() << " isArrowFunction" << c->isArrowFunction << "innerFunctionAccessesThis" << c->innerFunctionAccessesThis;
qDebug() << " parent:" << c->parent;
if (c->argumentsCanEscape)
qDebug() << " Arguments escape";