diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-03-26 22:59:28 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-05-02 14:17:46 +0000 |
commit | 20d30b6b3a253eebedc927dbb91685bbec52cfee (patch) | |
tree | 0e91a6c519829bd279258f3fe807519e6c8a1e3d /src/qml/compiler/qv4compilerscanfunctions.cpp | |
parent | d499a995292629d3522f5e77b7c958bacdf5d0ae (diff) | |
download | qtdeclarative-20d30b6b3a253eebedc927dbb91685bbec52cfee.tar.gz |
Add support for proper lexical scoping
This is still to some extend work in progress as
lexically scoped for loops won't yet do the right
thing.
let and const variables are still accessible before
they are declared, and the global scope doesn't yet
have a proper context for lexically declared variables.
Change-Id: Ie39f74a8fccdaead437fbf07f9fc228a444c26ed
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4compilerscanfunctions.cpp')
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions.cpp | 30 |
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(); } } } |