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
24namespace panda::ecmascript {
25JSHandle<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
44JSHandle<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
61JSHandle<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