diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-05-08 14:34:58 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-05-11 07:17:12 +0000 |
commit | 01a1ad296c2b8325476abd6d28c8cc2463c42eb6 (patch) | |
tree | 4acaaf72782e634615e74c2da52227206cd16a42 /src/qml/compiler | |
parent | 4cf7e80c5740912804383e4d866ba12b2520d0e6 (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.cpp | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext.cpp | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontrolflow_p.h | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions.cpp | 17 |
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) { |