diff options
Diffstat (limited to 'src')
-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 | ||||
-rw-r--r-- | src/qml/parser/qqmljs.g | 18 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast.cpp | 1 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast_p.h | 8 |
8 files changed, 42 insertions, 18 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) { diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 8e71b8a42b..f162d123f5 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -3396,7 +3396,7 @@ TryStatement: T_TRY Block Catch Finally; Catch: T_CATCH T_LPAREN CatchParameter T_RPAREN Block; /. case $rule_number: { - AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); + AST::Catch *node = new (pool) AST::Catch(sym(3).PatternElement, sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); node->identifierToken = loc(3); @@ -3415,9 +3415,23 @@ Finally: T_FINALLY Block; ./ CatchParameter: BindingIdentifier; +/. + case $rule_number: { + AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(1)); + node->identifierToken = loc(1); + node->scope = AST::VariableScope::Let; + sym(1).Node = node; + } break; +./ CatchParameter: BindingPattern; -/. case $rule_number: { UNIMPLEMENTED; } ./ +/. + case $rule_number: { + AST::PatternElement *node = new (pool) AST::PatternElement(sym(1).Pattern); + node->scope = AST::VariableScope::Let; + sym(1).Node = node; + } break; +./ DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON; -- automatic semicolon DebuggerStatement: T_DEBUGGER T_SEMICOLON; diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp index 6c0e394a34..cc8b290bc9 100644 --- a/src/qml/parser/qqmljsast.cpp +++ b/src/qml/parser/qqmljsast.cpp @@ -938,6 +938,7 @@ void TryStatement::accept0(Visitor *visitor) void Catch::accept0(Visitor *visitor) { if (visitor->visit(this)) { + accept(patternElement, visitor); accept(statement, visitor); } diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index e54d1aea31..36060f7358 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -2063,9 +2063,9 @@ class QML_PARSER_EXPORT Catch: public Node public: QQMLJS_DECLARE_AST_NODE(Catch) - Catch(const QStringRef &n, Block *stmt): - name (n), statement (stmt) - { kind = K; } + Catch(PatternElement *p, Block *stmt) + : patternElement(p), statement(stmt) + { kind = K; } void accept0(Visitor *visitor) override; @@ -2076,7 +2076,7 @@ public: { return statement->lastSourceLocation(); } // attributes - QStringRef name; + PatternElement *patternElement; Block *statement; SourceLocation catchToken; SourceLocation lparenToken; |