diff --git a/es2panda/compiler/core/labelTarget.h b/es2panda/compiler/core/labelTarget.h index 6c9ee9792b458ad55d9721d3b82c47d7786d2e14..702adbb036a82ceaa2b3f577a54770a1d9be70c5 100644 --- a/es2panda/compiler/core/labelTarget.h +++ b/es2panda/compiler/core/labelTarget.h @@ -77,6 +77,7 @@ public: static constexpr std::string_view BREAK_LABEL = "#b"; static constexpr std::string_view CONTINUE_LABEL = "#c"; + static constexpr std::string_view RETURN_LABEL = "#r"; private: util::StringView breakLabel_ {}; diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index ef06720971367aeeac918908ace76e484125d4d4..fae67651e47f1d9dd9964921b93a7e0acca4941c 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -709,6 +709,15 @@ Label *PandaGen::ControlFlowChangeContinue(const ir::Identifier *label) return continueTarget; } +void PandaGen::ControlFlowChangeReturn() +{ + auto *iter = dynamicContext_; + while (iter) { + iter->AbortContext(ControlFlowChange::BREAK, LabelTarget::RETURN_LABEL); + iter = iter->Prev(); + } +} + void PandaGen::Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, Label *ifFalse) { switch (op) { diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index afeed11653f20f8af451597fb618d0d71bcca6a0..445d4abb0d11c42b2c9a16ded51ee42cca415b2f 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -267,6 +267,7 @@ public: bool CheckControlFlowChange(); Label *ControlFlowChangeBreak(const ir::Identifier *label = nullptr); Label *ControlFlowChangeContinue(const ir::Identifier *label); + void ControlFlowChangeReturn(); void Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, class Label *ifFalse); void Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand); diff --git a/es2panda/compiler/function/functionBuilder.cpp b/es2panda/compiler/function/functionBuilder.cpp index e6ba14286f873ae08a073e3f46234dc6f16d21c7..2532df116ceab7009c7d7e123f84a9693ca7a279 100644 --- a/es2panda/compiler/function/functionBuilder.cpp +++ b/es2panda/compiler/function/functionBuilder.cpp @@ -129,7 +129,7 @@ void FunctionBuilder::HandleCompletion(const ir::AstNode *node, VReg completionT pg_->Condition(node, lexer::TokenType::PUNCTUATOR_EQUAL, completionType, notRetLabel); if (!handleReturn_) { handleReturn_ = true; - pg_->ControlFlowChangeBreak(); + pg_->ControlFlowChangeReturn(); handleReturn_ = false; } @@ -223,7 +223,7 @@ void FunctionBuilder::YieldStar(const ir::AstNode *node) pg_->BranchIfNotUndefined(node, callMethod); // 1. If generatorKind is async, set received.[[Value]] to ? Await(received.[[Value]]). - pg_->ControlFlowChangeBreak(); + pg_->ControlFlowChangeReturn(); pg_->LoadAccumulator(node, receivedValue); if (GeneratorKind() == IteratorType::ASYNC) { @@ -307,7 +307,7 @@ void FunctionBuilder::YieldStar(const ir::AstNode *node) if (pg_->CheckControlFlowChange()) { pg_->StoreAccumulator(node, receivedValue); - pg_->ControlFlowChangeBreak(); + pg_->ControlFlowChangeReturn(); pg_->LoadAccumulator(node, receivedValue); } diff --git a/es2panda/ir/statements/returnStatement.cpp b/es2panda/ir/statements/returnStatement.cpp index 5d65a90860f58332ddc04961b2ff286f272ed61d..897db1d0e5e2806d3783e15482649ba365247a3b 100644 --- a/es2panda/ir/statements/returnStatement.cpp +++ b/es2panda/ir/statements/returnStatement.cpp @@ -51,7 +51,7 @@ void ReturnStatement::Compile(compiler::PandaGen *pg) const compiler::VReg res = pg->AllocReg(); pg->StoreAccumulator(this, res); - pg->ControlFlowChangeBreak(); + pg->ControlFlowChangeReturn(); pg->LoadAccumulator(this, res); } diff --git a/es2panda/test/compiler/js/language/statements/try/try-finally-with-return-in-switch-expected.txt b/es2panda/test/compiler/js/language/statements/try/try-finally-with-return-in-switch-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..b62420bf91004dec1c04b30d3b40647b87106ff7 --- /dev/null +++ b/es2panda/test/compiler/js/language/statements/try/try-finally-with-return-in-switch-expected.txt @@ -0,0 +1 @@ +Run finally before return diff --git a/es2panda/test/compiler/js/language/statements/try/try-finally-with-return-in-switch.js b/es2panda/test/compiler/js/language/statements/try/try-finally-with-return-in-switch.js new file mode 100644 index 0000000000000000000000000000000000000000..53dd21db3f46ba71e84a894b3278370762e5f9c0 --- /dev/null +++ b/es2panda/test/compiler/js/language/statements/try/try-finally-with-return-in-switch.js @@ -0,0 +1,12 @@ +function test() { + let a = 0; + try { + switch (a) { + case 0: { + return 123; + } + } + } catch {} finally {print("Run finally before return");} +} + +test();