aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4compilerscanfunctions.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-04-06 11:33:20 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-02 14:17:55 +0000
commit2c23299ecd94dbcce0a90b3b374a674cad6a3683 (patch)
treea5ade5f3b39685ada7d069b89b86e8b983ee159a /src/qml/compiler/qv4compilerscanfunctions.cpp
parent922e6f42b4fa9b9fa87246c577c13bb945bd4bc4 (diff)
Cleanup handling of with() statements
Add a CompilerContext for with, whose only purpose it is to trigger variable lookup by name. This avoids looking up variables declared inside the with() {} block by name and we do not lookup variables outside the with block by name neither anymore. Change-Id: I52e9fb2daa9601f9e5102714c002dc506ad5ed23 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4compilerscanfunctions.cpp')
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp78
1 files changed, 47 insertions, 31 deletions
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 120c606f91..f5bfd14c93 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -150,7 +150,7 @@ void ScanFunctions::endVisit(Program *)
bool ScanFunctions::visit(CallExpression *ast)
{
- if (! _context->hasDirectEval) {
+ if (!_context->hasDirectEval) {
if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
if (id->name == QLatin1String("eval")) {
if (_context->usesArgumentsObject == Context::ArgumentsObjectUnknown)
@@ -317,17 +317,6 @@ void ScanFunctions::endVisit(FunctionDeclaration *)
leaveEnvironment();
}
-bool ScanFunctions::visit(WithStatement *ast)
-{
- if (_context->isStrict) {
- _cg->throwSyntaxError(ast->withToken, QStringLiteral("'with' statement is not allowed in strict mode"));
- return false;
- }
-
- _context->hasWith = true;
- return true;
-}
-
bool ScanFunctions::visit(DoWhileStatement *ast) {
{
TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_context->isStrict);
@@ -416,6 +405,29 @@ void ScanFunctions::endVisit(Catch *)
leaveEnvironment();
}
+bool ScanFunctions::visit(WithStatement *ast)
+{
+ Node::accept(ast->expression, this);
+
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
+ enterEnvironment(ast, ContextType::Block);
+ _context->name = QLatin1String("WithBlock");
+ _context->isWithBlock = true;
+
+ if (_context->isStrict) {
+ _cg->throwSyntaxError(ast->withToken, QStringLiteral("'with' statement is not allowed in strict mode"));
+ return false;
+ }
+ Node::accept(ast->statement, this);
+
+ return false;
+}
+
+void ScanFunctions::endVisit(WithStatement *)
+{
+ leaveEnvironment();
+}
+
bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, StatementList *body, bool enterName)
{
Context *outerContext = _context;
@@ -487,6 +499,28 @@ 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;
+ c->usesArgumentsObject = Context::ArgumentsObjectUsed;
+ inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
+ }
+ }
+ for (Context *inner : qAsConst(m->contextMap)) {
+ if (!inner->parent || inner->usesArgumentsObject == Context::ArgumentsObjectUnknown)
+ inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
+ if (inner->usesArgumentsObject == Context::ArgumentsObjectUsed) {
+ QString arguments = QStringLiteral("arguments");
+ inner->addLocalVar(arguments, Context::VariableDeclaration, AST::VariableScope::Var);
+ if (!inner->isStrict) {
+ inner->argumentsCanEscape = true;
+ inner->requiresExecutionContext = true;
+ }
+ }
+ }
+
+ for (Context *inner : qAsConst(m->contextMap)) {
for (const QString &var : qAsConst(inner->usedVariables)) {
Context *c = inner;
while (c) {
@@ -511,19 +545,11 @@ void ScanFunctions::calcEscapingVariables()
Context *c = inner->parent;
while (c) {
c->hasDirectEval |= inner->hasDirectEval;
- 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->hasDirectEval;
+ bool allVarsEscape = c->hasDirectEval;
if (allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty())
allVarsEscape = false;
if (m->debugMode)
@@ -543,16 +569,6 @@ void ScanFunctions::calcEscapingVariables()
auto m = c->members.find(c->catchedVariable);
m->canEscape = true;
}
- if (!c->parent || c->usesArgumentsObject == Context::ArgumentsObjectUnknown)
- c->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
- if (c->usesArgumentsObject == Context::ArgumentsObjectUsed) {
- QString arguments = QStringLiteral("arguments");
- c->addLocalVar(arguments, Context::VariableDeclaration, AST::VariableScope::Var);
- if (!c->isStrict) {
- c->argumentsCanEscape = true;
- c->requiresExecutionContext = true;
- }
- }
if (allVarsEscape) {
for (auto &m : c->members)
m.canEscape = true;