From 05fda11360cb068c0b08689e16fed745e6d1a607 Mon Sep 17 00:00:00 2001 From: ctw-ian Date: Sat, 7 Jan 2023 22:06:55 +0800 Subject: [PATCH] Fix sync IteratorClose Issue:I69CVD Signed-off-by: ctw-ian Change-Id: I78ff429c9c831465ac2f810cfeea50fed0ed5c5a --- es2panda/compiler/base/iterators.cpp | 82 +++++++++++++------ es2panda/compiler/base/iterators.h | 2 + ...lose-uncallable-return-test-1-expected.txt | 2 + .../iteratorclose-uncallable-return-test-1.js | 16 ++++ ...close-undefined-return-test-1-expected.txt | 2 + .../iteratorclose-undefined-return-test-1.js | 16 ++++ 6 files changed, 97 insertions(+), 23 deletions(-) create mode 100644 es2panda/test/compiler/js/iteratorclose-uncallable-return-test-1-expected.txt create mode 100644 es2panda/test/compiler/js/iteratorclose-uncallable-return-test-1.js create mode 100644 es2panda/test/compiler/js/iteratorclose-undefined-return-test-1-expected.txt create mode 100644 es2panda/test/compiler/js/iteratorclose-undefined-return-test-1.js diff --git a/es2panda/compiler/base/iterators.cpp b/es2panda/compiler/base/iterators.cpp index f88e502870..57d8c1ffa7 100644 --- a/es2panda/compiler/base/iterators.cpp +++ b/es2panda/compiler/base/iterators.cpp @@ -78,29 +78,7 @@ void Iterator::Value() const void Iterator::Close(bool abruptCompletion) const { if (type_ == IteratorType::SYNC) { - RegScope rs(pg_); - VReg exception = pg_->AllocReg(); - VReg innerResult = pg_->AllocReg(); - Label *noReturn = pg_->AllocLabel(); - - if (abruptCompletion) { - pg_->StoreAccumulator(node_, exception); - } - - // close iterator - pg_->LoadObjByName(node_, iterator_, "return"); - pg_->StoreAccumulator(node_, method_); - pg_->LoadConst(node_, Constant::JS_UNDEFINED); - pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, method_, noReturn); - CallMethod(); - pg_->StoreAccumulator(node_, innerResult); - pg_->ThrowIfNotObject(node_, innerResult); - - pg_->SetLabel(node_, noReturn); - if (abruptCompletion) { - pg_->LoadAccumulator(node_, exception); - pg_->EmitThrow(node_); - } + SyncClose(abruptCompletion); return; } @@ -179,6 +157,64 @@ void Iterator::Close(bool abruptCompletion) const pg_->ThrowIfNotObject(node_, innerResult); } +void Iterator::SyncClose(bool abruptCompletion) const +{ + RegScope rs(pg_); + VReg completion = pg_->AllocReg(); + VReg innerResult = pg_->AllocReg(); + VReg innnerException = pg_->AllocReg(); + Label *noReturn = pg_->AllocLabel(); + Label *finishClose = pg_->AllocLabel(); + + pg_->StoreAccumulator(node_, completion); + + pg_->StoreConst(node_, innnerException, Constant::JS_HOLE); + + TryContext tryCtx(pg_); + const auto &labelSet = tryCtx.LabelSet(); + + pg_->SetLabel(node_, labelSet.TryBegin()); + // 4. Let innerResult be GetMethod(iterator, "return"). + GetMethod("return"); + + // 5. If innerResult.[[Type]] is normal, then + pg_->BranchIfUndefined(node_, noReturn); + + // c. Set innerResult to Call(return, iterator). + CallMethod(); + pg_->StoreAccumulator(node_, innerResult); + pg_->SetLabel(node_, labelSet.TryEnd()); + pg_->Branch(node_, labelSet.CatchEnd()); + + pg_->SetLabel(node_, labelSet.CatchBegin()); + pg_->StoreAccumulator(node_, innnerException); + pg_->SetLabel(node_, labelSet.CatchEnd()); + + // 6. If completion.[[Type]] is throw, return Completion(completion). + if (abruptCompletion) { + pg_->LoadAccumulator(node_, completion); + pg_->EmitThrow(node_); + } else { + // 7. If innerResult.[[Type]] is throw, return Completion(innerResult). + pg_->LoadAccumulator(node_, innnerException); + pg_->EmitRethrow(node_); + } + + // 8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. + pg_->LoadAccumulator(node_, innerResult); + pg_->ThrowIfNotObject(node_, innerResult); + pg_->Branch(node_, finishClose); + + pg_->SetLabel(node_, noReturn); + // b. If return is undefined, return Completion(completion). + pg_->LoadAccumulator(node_, completion); + if (abruptCompletion) { + pg_->EmitThrow(node_); + } + + pg_->SetLabel(node_, finishClose); +} + DestructuringIterator::DestructuringIterator(PandaGen *pg, const ir::AstNode *node) : Iterator(pg, node, IteratorType::SYNC), done_(pg->AllocReg()), result_(pg->AllocReg()) { diff --git a/es2panda/compiler/base/iterators.h b/es2panda/compiler/base/iterators.h index d43bc95687..2ae8fa6606 100644 --- a/es2panda/compiler/base/iterators.h +++ b/es2panda/compiler/base/iterators.h @@ -63,6 +63,8 @@ public: void Complete() const; void Value() const; void Close(bool abruptCompletion) const; + void SyncClose(bool abruptCompletion) const; + void AsyncClose(bool abruptCompletion) const; protected: PandaGen *pg_; diff --git a/es2panda/test/compiler/js/iteratorclose-uncallable-return-test-1-expected.txt b/es2panda/test/compiler/js/iteratorclose-uncallable-return-test-1-expected.txt new file mode 100644 index 0000000000..a247b96d92 --- /dev/null +++ b/es2panda/test/compiler/js/iteratorclose-uncallable-return-test-1-expected.txt @@ -0,0 +1,2 @@ +1 +123 diff --git a/es2panda/test/compiler/js/iteratorclose-uncallable-return-test-1.js b/es2panda/test/compiler/js/iteratorclose-uncallable-return-test-1.js new file mode 100644 index 0000000000..5bb33fa2a0 --- /dev/null +++ b/es2panda/test/compiler/js/iteratorclose-uncallable-return-test-1.js @@ -0,0 +1,16 @@ +"use strict"; +var iterable = {}; + +iterable[Symbol.iterator] = function() { + return { + next: function() { + return { done: false, value: 1 }; + }, + return: 1 + }; +}; + +for (let i of iterable) { + print(i); + throw "123"; +} diff --git a/es2panda/test/compiler/js/iteratorclose-undefined-return-test-1-expected.txt b/es2panda/test/compiler/js/iteratorclose-undefined-return-test-1-expected.txt new file mode 100644 index 0000000000..a247b96d92 --- /dev/null +++ b/es2panda/test/compiler/js/iteratorclose-undefined-return-test-1-expected.txt @@ -0,0 +1,2 @@ +1 +123 diff --git a/es2panda/test/compiler/js/iteratorclose-undefined-return-test-1.js b/es2panda/test/compiler/js/iteratorclose-undefined-return-test-1.js new file mode 100644 index 0000000000..c39bf3e058 --- /dev/null +++ b/es2panda/test/compiler/js/iteratorclose-undefined-return-test-1.js @@ -0,0 +1,16 @@ +"use strict"; +var iterable = {}; + +iterable[Symbol.iterator] = function() { + return { + next: function() { + return { done: false, value: 1 }; + }, + return: undefined + }; +}; + +for (let i of iterable) { + print(i); + throw "123"; +} -- Gitee