• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2025 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 #ifndef PANDA_PLUGINS_ETS_ERROR_H
17 #define PANDA_PLUGINS_ETS_ERROR_H
18 
19 #include "plugins/ets/runtime/ets_platform_types.h"
20 #include "plugins/ets/runtime/types/ets_object.h"
21 #include "plugins/ets/runtime/types/ets_string.h"
22 #include "plugins/ets/runtime/types/ets_array.h"
23 #include "plugins/ets/runtime/types/ets_stacktrace_element.h"
24 
25 namespace ark::ets {
26 
27 namespace test {
28 class EtsErrorTest;
29 }  // namespace test
30 
31 // class Error is mirror class for escompat.Error
32 // Currently, there is no necessity to declare this class as mirror in yaml files,
33 // this this class is auxiliary for describing std.core error classes as mirror classes.
34 class Error : public EtsObject {
35 public:
36     NO_COPY_SEMANTIC(Error);
37     NO_MOVE_SEMANTIC(Error);
38 
39     Error() = delete;
40     ~Error() = delete;
41 
Create(EtsCoroutine * coro,EtsClass * klass)42     static Error *Create(EtsCoroutine *coro, EtsClass *klass)
43     {
44         return FromEtsObject(EtsObject::Create(coro, klass));
45     }
46 
FromEtsObject(EtsObject * object)47     static Error *FromEtsObject(EtsObject *object)
48     {
49         return static_cast<Error *>(object);
50     }
51 
AsObject()52     EtsObject *AsObject()
53     {
54         return this;
55     }
56 
AsObject()57     const EtsObject *AsObject() const
58     {
59         return this;
60     }
61 
SetName(EtsCoroutine * coro,EtsString * name)62     void SetName(EtsCoroutine *coro, EtsString *name)
63     {
64         ASSERT(name != nullptr);
65         ObjectAccessor::SetObject(coro, this, MEMBER_OFFSET(Error, name_), name->GetCoreType());
66     }
67 
SetMessage(EtsCoroutine * coro,EtsString * msg)68     void SetMessage(EtsCoroutine *coro, EtsString *msg)
69     {
70         ASSERT(msg != nullptr);
71         ObjectAccessor::SetObject(coro, this, MEMBER_OFFSET(Error, message_), msg->GetCoreType());
72     }
73 
SetStack(EtsCoroutine * coro,EtsString * stack)74     void SetStack(EtsCoroutine *coro, EtsString *stack)
75     {
76         ASSERT(stack != nullptr);
77         ObjectAccessor::SetObject(coro, this, MEMBER_OFFSET(Error, stack_), stack->GetCoreType());
78     }
79 
SetStackLines(EtsCoroutine * coro,EtsTypedObjectArray<EtsStackTraceElement> * stackLines)80     void SetStackLines(EtsCoroutine *coro, EtsTypedObjectArray<EtsStackTraceElement> *stackLines)
81     {
82         ASSERT(stackLines != nullptr);
83         ObjectAccessor::SetObject(coro, this, MEMBER_OFFSET(Error, stackLines_), stackLines->GetCoreType());
84     }
85 
86 private:
87     ObjectPointer<EtsString> name_;
88     ObjectPointer<EtsString> message_;
89     ObjectPointer<EtsTypedObjectArray<EtsStackTraceElement>> stackLines_;
90     ObjectPointer<EtsString> stack_;  // non-mandatory field in `class Error`
91     ObjectPointer<EtsObject> cause_;  // non-mandatory field in `class Error`
92 
93     friend class test::EtsErrorTest;
94 };
95 
96 // Purpose of this class is to have preallocated OOM object in runtime, that can be useful in situation
97 // when all heap is filled and we don't have space to allocate stdlib OOM error.
98 class EtsOutOfMemoryError final : public Error {
99 public:
100     static constexpr std::string_view OOM_ERROR_NAME = "OutOfMemoryError";
101     // Default message should be empty string to avoid allocations in .toString()
102     // NOLINTNEXTLINE(readability-redundant-string-init)
103     static constexpr std::string_view DEFAULT_OOM_MSG = "";
104     static constexpr std::string_view DEFAULT_OOM_STACK = "Heap is full, no space to collect stack";
105 
106 public:
107     NO_COPY_SEMANTIC(EtsOutOfMemoryError);
108     NO_MOVE_SEMANTIC(EtsOutOfMemoryError);
109 
110     EtsOutOfMemoryError() = delete;
111     ~EtsOutOfMemoryError() = delete;
112 
Create(EtsCoroutine * coro)113     static EtsOutOfMemoryError *Create(EtsCoroutine *coro)
114     {
115         [[maybe_unused]] EtsHandleScope scope(coro);
116 
117         auto oomH = EtsHandle<EtsOutOfMemoryError>(
118             coro, FromError(Error::Create(coro, PlatformTypes(coro)->coreOutOfMemoryError)));
119 
120         ASSERT(oomH.GetPtr() != nullptr);
121         auto *name = EtsString::CreateFromMUtf8(OOM_ERROR_NAME.data());
122         oomH->SetName(coro, name);
123 
124         auto *message = EtsString::CreateFromMUtf8(DEFAULT_OOM_MSG.data());
125         oomH->SetMessage(coro, message);
126 
127         auto *stack = EtsString::CreateFromMUtf8(DEFAULT_OOM_STACK.data());
128         oomH->SetStack(coro, stack);
129 
130         auto *stackLines =
131             EtsTypedObjectArray<EtsStackTraceElement>::Create(PlatformTypes(coro)->coreStackTraceElement, 0U);
132         oomH->SetStackLines(coro, stackLines);
133 
134         return oomH.GetPtr();
135     }
136 
FromError(Error * error)137     static EtsOutOfMemoryError *FromError(Error *error)
138     {
139         ASSERT(error->GetClass()->GetDescriptor() == panda_file_items::class_descriptors::OUT_OF_MEMORY_ERROR);
140         return static_cast<EtsOutOfMemoryError *>(error);
141     }
142 };
143 
144 }  // namespace ark::ets
145 
146 #endif  // PANDA_PLUGINS_ETS_ERROR_H
147