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