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.cpp30
1 files changed, 25 insertions, 5 deletions
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 4fa35f3adb..312f07e254 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -395,10 +395,17 @@ bool ScanFunctions::visit(ThisExpression *)
bool ScanFunctions::visit(Block *ast)
{
TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
+ enterEnvironment(ast, ContextType::Block);
+ _context->name = QLatin1String("Block");
Node::accept(ast->statements, this);
return false;
}
+void ScanFunctions::endVisit(Block *)
+{
+ leaveEnvironment();
+}
+
bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, StatementList *body, bool enterName)
{
Context *outerContext = _context;
@@ -421,6 +428,7 @@ bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete
outerContext->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
}
+ _context->name = name;
if (formals && formals->containsName(QStringLiteral("arguments")))
_context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
if (expr) {
@@ -496,18 +504,29 @@ void ScanFunctions::calcEscapingVariables()
c->hasWith |= inner->hasWith;
c = c->parent;
}
+ if (inner->contextType == ContextType::Block && inner->usesArgumentsObject == Context::ArgumentsObjectUsed) {
+ Context *f = inner->parent;
+ while (f->contextType == ContextType::Block)
+ f = f->parent;
+ f->usesArgumentsObject = Context::ArgumentsObjectUsed;
+ inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
+ }
}
for (Context *c : qAsConst(m->contextMap)) {
- bool allVarsEscape = c->hasWith || c->hasTry || c->hasDirectEval || m->debugMode;
+ bool allVarsEscape = c->hasWith || c->hasTry || c->hasDirectEval;
+ if (allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty())
+ allVarsEscape = false;
+ if (m->debugMode)
+ allVarsEscape = true;
if (allVarsEscape) {
c->requiresExecutionContext = true;
c->argumentsCanEscape = true;
}
// ### for now until we have lexically scoped vars that'll require it
- if (c->type == ContextType::Global)
+ if (c->contextType == ContextType::Global)
c->requiresExecutionContext = false;
// ### Shouldn't be required, we could probably rather change the ContextType to FunctionCode for strict eval
- if (c->type == ContextType::Eval && c->isStrict)
+ if (c->contextType == ContextType::Eval && c->isStrict)
c->requiresExecutionContext = true;
if (!c->parent || c->usesArgumentsObject == Context::ArgumentsObjectUnknown)
c->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
@@ -529,11 +548,12 @@ void ScanFunctions::calcEscapingVariables()
if (showEscapingVars) {
qDebug() << "==== escaping variables ====";
for (Context *c : qAsConst(m->contextMap)) {
- qDebug() << "Context" << c << c->name << ":";
+ qDebug() << "Context" << c << c->name << "requiresExecutionContext" << c->requiresExecutionContext;
+ qDebug() << " parent:" << c->parent;
if (c->argumentsCanEscape)
qDebug() << " Arguments escape";
for (auto it = c->members.constBegin(); it != c->members.constEnd(); ++it) {
- qDebug() << " " << it.key() << it.value().canEscape;
+ qDebug() << " " << it.key() << it.value().canEscape << "isLexicallyScoped:" << it.value().isLexicallyScoped();
}
}
}