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