From 4cf7e80c5740912804383e4d866ba12b2520d0e6 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 4 May 2018 15:16:08 +0200 Subject: Ensure we have a lexical scope for global code This requires a bit more work than simply pushing a new BlockContext for the lexically declared variables, as eval() and the Function constructor operate on the global scope (including the lexically declared names). To fix this introduce Push/PopScriptContext instructions, that create a BlockContext for the lexically declared vars and pushes that one as a global script context that eval and friends use. Change-Id: I0fd0b0f682f82e250545e874fe93978449fe5e46 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4compilerscanfunctions.cpp | 30 ++++++++++++++------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'src/qml/compiler/qv4compilerscanfunctions.cpp') diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp index 47329e978b..f7100a1d1a 100644 --- a/src/qml/compiler/qv4compilerscanfunctions.cpp +++ b/src/qml/compiler/qv4compilerscanfunctions.cpp @@ -522,20 +522,19 @@ void ScanFunctions::calcEscapingVariables() if (current->isWithBlock || current->contextType != ContextType::Block) break; } + Q_ASSERT(c != inner); while (c) { Context::MemberMap::const_iterator it = c->members.find(var); if (it != c->members.end()) { - if (c != inner) { + if (c->parent || it->isLexicallyScoped()) { it->canEscape = true; c->requiresExecutionContext = true; } break; } if (c->findArgument(var) != -1) { - if (c != inner) { - c->argumentsCanEscape = true; - c->requiresExecutionContext = true; - } + c->argumentsCanEscape = true; + c->requiresExecutionContext = true; break; } c = c->parent; @@ -551,18 +550,21 @@ void ScanFunctions::calcEscapingVariables() bool allVarsEscape = c->hasDirectEval; if (allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty()) allVarsEscape = false; - if (m->debugMode) + if (!c->parent || m->debugMode) allVarsEscape = true; if (allVarsEscape) { - c->requiresExecutionContext = true; - c->argumentsCanEscape = true; + if (c->parent) { + c->requiresExecutionContext = true; + c->argumentsCanEscape = true; + } else { + for (const auto &m : qAsConst(c->members)) { + if (m.isLexicallyScoped()) { + c->requiresExecutionContext = true; + break; + } + } + } } - // ### for now until we have lexically scoped vars that'll require it - 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->contextType == ContextType::Eval && c->isStrict) - c->requiresExecutionContext = true; if (c->contextType == ContextType::Block && c->isCatchBlock) { c->requiresExecutionContext = true; auto m = c->members.find(c->catchedVariable); -- cgit v1.2.3