1 /*
2  * Copyright (c) 2021-2024 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.h"
19 #include "ecmascript/js_iterator.h"
20 #if ECMASCRIPT_ENABLE_CAST_CHECK
21 #include "ecmascript/js_tagged_value-inl.h"
22 #endif
23 
24 namespace panda::ecmascript {
Next(JSThread *thread, const JSHandle<GeneratorContext> &genContext, JSTaggedValue value)25 JSHandle<JSObject> GeneratorHelper::Next(JSThread *thread, const JSHandle<GeneratorContext> &genContext,
26                                          JSTaggedValue value)
27 {
28     JSHandle<JSGeneratorObject> genObject(thread, genContext->GetGeneratorObject());
29     genObject->SetResumeResult(thread, value);
30     genObject->SetGeneratorState(JSGeneratorState::EXECUTING);
31     genObject->SetResumeMode(GeneratorResumeMode::NEXT);
32 
33     JSTaggedValue next = EcmaInterpreter::GeneratorReEnterInterpreter(thread, genContext);
34     JSHandle<JSTaggedValue> nextValue(thread, next);
35 
36     if (genObject->IsSuspendYield()) {
37         return JSHandle<JSObject>::Cast(nextValue);
38     }
39     genObject->SetGeneratorState(JSGeneratorState::COMPLETED);
40     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread);
41     return JSIterator::CreateIterResultObject(thread, nextValue, true);
42 }
43 
Return(JSThread *thread, const JSHandle<GeneratorContext> &genContext, JSTaggedValue value)44 JSHandle<JSObject> GeneratorHelper::Return(JSThread *thread, const JSHandle<GeneratorContext> &genContext,
45                                            JSTaggedValue value)
46 {
47     JSHandle<JSGeneratorObject> genObject(thread, genContext->GetGeneratorObject());
48     genObject->SetResumeMode(GeneratorResumeMode::RETURN);
49     genObject->SetResumeResult(thread, value);
50 
51     JSTaggedValue res = EcmaInterpreter::GeneratorReEnterInterpreter(thread, genContext);
52     JSHandle<JSTaggedValue> returnValue(thread, res);
53     // change state to completed
54     if (genObject->IsExecuting()) {
55         genObject->SetGeneratorState(JSGeneratorState::COMPLETED);
56     }
57     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread);
58     return JSIterator::CreateIterResultObject(thread, returnValue, true);
59 }
60 
Throw(JSThread *thread, const JSHandle<GeneratorContext> &genContext, JSTaggedValue value)61 JSHandle<JSObject> GeneratorHelper::Throw(JSThread *thread, const JSHandle<GeneratorContext> &genContext,
62                                           JSTaggedValue value)
63 {
64     JSHandle<JSGeneratorObject> genObject(thread, genContext->GetGeneratorObject());
65     genObject->SetResumeMode(GeneratorResumeMode::THROW);
66     genObject->SetResumeResult(thread, value);
67 
68     JSTaggedValue res = EcmaInterpreter::GeneratorReEnterInterpreter(thread, genContext);
69     JSHandle<JSTaggedValue> throwValue(thread, res);
70 
71     if (genObject->IsSuspendYield()) {
72         return JSHandle<JSObject>::Cast(throwValue);
73     }
74 
75     // change state to completed
76     genObject->SetGeneratorState(JSGeneratorState::COMPLETED);
77     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread);
78     return JSIterator::CreateIterResultObject(thread, throwValue, true);
79 }
80 }  // namespace panda::ecmascript
81