1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/generator_helper.h"
17
18 #include "ecmascript/interpreter/interpreter-inl.h"
19 #include "ecmascript/js_iterator.h"
20
21 namespace panda::ecmascript {
Next(JSThread * thread,const JSHandle<GeneratorContext> & genContext,JSTaggedValue value)22 JSHandle<JSObject> GeneratorHelper::Next(JSThread *thread, const JSHandle<GeneratorContext> &genContext,
23 JSTaggedValue value)
24 {
25 JSHandle<JSGeneratorObject> genObject(thread, genContext->GetGeneratorObject());
26 genObject->SetResumeResult(thread, value);
27 genObject->SetGeneratorState(JSGeneratorState::EXECUTING);
28 genObject->SetResumeMode(GeneratorResumeMode::NEXT);
29
30 JSTaggedValue next = EcmaInterpreter::GeneratorReEnterInterpreter(thread, genContext);
31 JSHandle<JSTaggedValue> nextValue(thread, next);
32
33 if (genObject->IsSuspendYield()) {
34 return JSHandle<JSObject>::Cast(nextValue);
35 }
36 genObject->SetGeneratorState(JSGeneratorState::COMPLETED);
37 RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread);
38 return JSIterator::CreateIterResultObject(thread, nextValue, true);
39 }
40
Return(JSThread * thread,const JSHandle<GeneratorContext> & genContext,JSTaggedValue value)41 JSHandle<JSObject> GeneratorHelper::Return(JSThread *thread, const JSHandle<GeneratorContext> &genContext,
42 JSTaggedValue value)
43 {
44 JSHandle<JSGeneratorObject> genObject(thread, genContext->GetGeneratorObject());
45 genObject->SetResumeMode(GeneratorResumeMode::RETURN);
46 genObject->SetResumeResult(thread, value);
47
48 JSTaggedValue res = EcmaInterpreter::GeneratorReEnterInterpreter(thread, genContext);
49 JSHandle<JSTaggedValue> returnValue(thread, res);
50 // change state to completed
51 if (genObject->IsExecuting()) {
52 genObject->SetGeneratorState(JSGeneratorState::COMPLETED);
53 }
54 RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread);
55 return JSIterator::CreateIterResultObject(thread, returnValue, true);
56 }
57
Throw(JSThread * thread,const JSHandle<GeneratorContext> & genContext,JSTaggedValue value)58 JSHandle<JSObject> GeneratorHelper::Throw(JSThread *thread, const JSHandle<GeneratorContext> &genContext,
59 JSTaggedValue value)
60 {
61 JSHandle<JSGeneratorObject> genObject(thread, genContext->GetGeneratorObject());
62 genObject->SetResumeMode(GeneratorResumeMode::THROW);
63 genObject->SetResumeResult(thread, value);
64
65 JSTaggedValue res = EcmaInterpreter::GeneratorReEnterInterpreter(thread, genContext);
66 JSHandle<JSTaggedValue> throwValue(thread, res);
67
68 if (genObject->IsSuspendYield()) {
69 return JSHandle<JSObject>::Cast(throwValue);
70 }
71
72 // change state to completed
73 genObject->SetGeneratorState(JSGeneratorState::COMPLETED);
74 RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread);
75 return JSIterator::CreateIterResultObject(thread, throwValue, true);
76 }
77 } // namespace panda::ecmascript
78