aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-05-08 14:34:58 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-11 07:17:12 +0000
commit01a1ad296c2b8325476abd6d28c8cc2463c42eb6 (patch)
tree4acaaf72782e634615e74c2da52227206cd16a42 /src/qml/compiler
parent4cf7e80c5740912804383e4d866ba12b2520d0e6 (diff)
Support destructuring inside catch()
Change-Id: Ib60b56ac6a7111446e01235564a4cf92ad8ad025 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qv4codegen.cpp6
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp4
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h2
-rw-r--r--src/qml/compiler/qv4compilercontrolflow_p.h4
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp17
5 files changed, 21 insertions, 12 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index f55e6205dc..8c6964930d 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2954,12 +2954,6 @@ bool Codegen::visit(ThrowStatement *ast)
void Codegen::handleTryCatch(TryStatement *ast)
{
Q_ASSERT(ast);
- if (_context->isStrict &&
- (ast->catchExpression->name == QLatin1String("eval") || ast->catchExpression->name == QLatin1String("arguments"))) {
- throwSyntaxError(ast->catchExpression->identifierToken, QStringLiteral("Catch variable name may not be eval or arguments in strict mode"));
- return;
- }
-
RegisterScope scope(this);
BytecodeGenerator::Label noException = bytecodeGenerator->newLabel();
{
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp
index 67afea28ab..07e19811a8 100644
--- a/src/qml/compiler/qv4compilercontext.cpp
+++ b/src/qml/compiler/qv4compilercontext.cpp
@@ -81,7 +81,7 @@ bool Context::addLocalVar(const QString &name, Context::MemberType type, Variabl
if (formals && formals->containsName(name))
return (scope == VariableScope::Var);
}
- if (!isCatchBlock || name != catchedVariable) {
+ if (!isCatchBlock || name != caughtVariable) {
MemberMap::iterator it = members.find(name);
if (it != members.end()) {
if (scope != VariableScope::Var || (*it).scope != VariableScope::Var)
@@ -178,7 +178,7 @@ int Context::emitBlockHeader(Codegen *codegen)
Instruction::PushCatchContext catchContext;
catchContext.index = blockIndex;
catchContext.reg = contextReg = bytecodeGenerator->newRegister();
- catchContext.name = codegen->registerString(catchedVariable);
+ catchContext.name = codegen->registerString(caughtVariable);
bytecodeGenerator->addInstruction(catchContext);
} else {
Instruction::PushBlockContext blockContext;
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 20bee6583a..6838610d1c 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -155,7 +155,7 @@ struct Context {
bool requiresExecutionContext = false;
bool isWithBlock = false;
bool isCatchBlock = false;
- QString catchedVariable;
+ QString caughtVariable;
enum UsesArgumentsObject {
ArgumentsObjectUnknown,
diff --git a/src/qml/compiler/qv4compilercontrolflow_p.h b/src/qml/compiler/qv4compilercontrolflow_p.h
index b89226c411..db83af0022 100644
--- a/src/qml/compiler/qv4compilercontrolflow_p.h
+++ b/src/qml/compiler/qv4compilercontrolflow_p.h
@@ -422,6 +422,10 @@ struct ControlFlowCatch : public ControlFlowUnwind
Reference::storeConstOnStack(cg, QV4::Encode::undefined(), controlFlowTemp);
generator()->setExceptionHandler(&catchUnwindLabel);
+ if (catchExpression->patternElement->bindingIdentifier.isEmpty())
+ // destructuring pattern
+ cg->initializeAndDestructureBindingElement(catchExpression->patternElement, Reference::fromName(cg, QStringLiteral("@caught")));
+ // skip the additional block
cg->statementList(catchExpression->statement->statements);
insideCatch = false;
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index f7100a1d1a..4dbd11ef1c 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -387,8 +387,19 @@ bool ScanFunctions::visit(Catch *ast)
enterEnvironment(ast, ContextType::Block);
_context->name = QLatin1String("CatchBlock");
_context->isCatchBlock = true;
- _context->catchedVariable = ast->name.toString();
- _context->addLocalVar(ast->name.toString(), Context::MemberType::VariableDefinition, VariableScope::Let);
+ QString caughtVar = ast->patternElement->bindingIdentifier;
+ if (caughtVar.isEmpty())
+ caughtVar = QStringLiteral("@caught");
+ _context->addLocalVar(caughtVar, Context::MemberType::VariableDefinition, VariableScope::Let);
+
+ _context->caughtVariable = caughtVar;
+ if (_context->isStrict &&
+ (caughtVar == QLatin1String("eval") || caughtVar == QLatin1String("arguments"))) {
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Catch variable name may not be eval or arguments in strict mode"));
+ return false;
+ }
+ Node::accept(ast->patternElement, this);
+ // skip the block statement
Node::accept(ast->statement->statements, this);
return false;
}
@@ -567,7 +578,7 @@ void ScanFunctions::calcEscapingVariables()
}
if (c->contextType == ContextType::Block && c->isCatchBlock) {
c->requiresExecutionContext = true;
- auto m = c->members.find(c->catchedVariable);
+ auto m = c->members.find(c->caughtVariable);
m->canEscape = true;
}
if (allVarsEscape) {