• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Customizing Exception Handling Using JSVM-API
2
3## Introduction
4
5JSVM-API provides APIs for handling JSVM exceptions. You can use these APIs to register callbacks with a JSVM. When an exception occurs on the JSVM, the registered callback will be triggered.
6With these APIs, you can customize the handling of critical errors in the JS engine, streamlining error and exception handling during runtime.
7
8## Basic Concepts
9
10JSVM-API provides APIs for handling the following errors:
11
12- Out-of-memory (OOM) error: You can use JSVM-API to register an OOM handler with a JSVM. When the JSVM encounters insufficient memory, the system will throw an OOM error and call the registered OOM error handler to perform cleanup or logging operations.
13- Fatal error: You can use JSVM-API to register a fatal error handler with a JSVM. When the JSVM encounters a fatal error, for example, an unrecoverable error while running JS code, the system will throw a fatal error and call the registered handler to output additional log information or report the error instead of allowing the application to crash.
14- Promise rejection without a catch handler: You can use JSVM-API to register a promise rejection handler with a JSVM. When a promise in JS is rejected without being caught by a catch handler, the system will throw a Promise Reject error and call the registered handler to handle the promise rejection.
15
16## Available APIs
17
18| API                      | Description                           |
19|----------------------------|-------------------------------------|
20| OH_JSVM_SetHandlerForOOMError         | Sets an OOM error handler for a JSVM.|
21| OH_JSVM_SetHandlerForFatalError   | Sets a fatal error handler for a JSVM.|
22| OH_JSVM_SetHandlerForPromiseReject | Sets a promise rejection handler for a JSVM.|
23
24## Example
25
26If you are just starting out with JSVM-API, see [JSVM-API Development Process](use-jsvm-process.md). The following demonstrates only the C++ code involved in exception handling.
27
28### OH_JSVM_SetHandlerForOOMError
29Call **OH_JSVM_SetHandlerForOOMError** to set a function for handling the OOM error. If this API is called multiple times, only the last setting takes effect. If **NULL** is passed in for the function to set in this API, the previously set handler will be canceled.
30
31#### CPP Code
32
33```cpp
34#include <csetjmp>
35
36static jmp_buf buf;
37static bool oomHandlerFinished = false;
38
39void OnOOMError(const char *location, const char *detail, bool isHeapOOM)
40{
41    oomHandlerFinished = true;
42    longjmp(buf, 1);
43}
44
45static JSVM_Value TriggerOOMError(JSVM_Env env, JSVM_CallbackInfo info)
46{
47    oomHandlerFinished = false;
48    JSVM_VM vm;
49    JSVM_CALL(OH_JSVM_GetVM(env, &vm));
50    // Set an OOM error handler.
51    JSVM_CALL(OH_JSVM_SetHandlerForOOMError(vm, OnOOMError));
52    bool oomed = false;
53    setjmp(buf);
54    if (!oomed) {
55        oomed = true;
56        // Trigger an OOM error.
57        std::vector<JSVM_Value> arrayVec;
58        int loopCount = 1000;
59        for (int i = 0; i < loopCount; i++) {
60            JSVM_Value array;
61            JSVM_CALL(OH_JSVM_CreateArrayWithLength(env, 0xffffff, &array));
62            arrayVec.push_back(array);
63        }
64    }
65    if (oomHandlerFinished) {
66      OH_LOG_INFO(LOG_APP, "JSVM Trigger OOM-Error: success");
67    } else {
68      OH_LOG_ERROR(LOG_APP, "JSVM Trigger OOM-Error: failed");
69    }
70    // Cancel the OOM error handler.
71    JSVM_CALL(OH_JSVM_SetHandlerForOOMError(vm, NULL));
72    JSVM_Value checked;
73    OH_JSVM_GetBoolean(env, true, &checked);
74    return checked;
75}
76
77static JSVM_CallbackStruct param[] = {
78    {.data = nullptr, .callback = TriggerOOMError},
79};
80static JSVM_CallbackStruct *method = param;
81
82static JSVM_PropertyDescriptor descriptor[] = {
83    {"triggerOOMError", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
84};
85```
86#### JS Example
87
88const char *srcCallNative = R"JS(triggerOOMError();)JS";
89
90#### Execution Result
91
92The following information is displayed in the log:<br>JSVM Trigger OOM-Error: success
93
94### OH_JSVM_SetHandlerForFatalError
95Call **OH_JSVM_SetHandlerForFatalError** to set a function for handling the fatal error. If this API is called multiple times, only the last setting takes effect. If **NULL** is passed in for the function to set in this API, the previously set handler will be canceled.
96#### CPP Code
97
98```cpp
99#include <csetjmp>
100
101static jmp_buf buf;
102static bool fatalHandlerFinished = false;
103void OnFatalError(const char *location, const char *message)
104{
105    fatalHandlerFinished = true;
106    OH_LOG_INFO(LOG_APP, "Run in 106");
107    longjmp(buf, 1);
108}
109
110static JSVM_Value TriggerFatalError(JSVM_Env env, JSVM_CallbackInfo info)
111{
112    fatalHandlerFinished = false;
113    JSVM_VM vm;
114    JSVM_CALL(OH_JSVM_GetVM(env, &vm));
115    // Set a fatal error handler.
116    JSVM_CALL(OH_JSVM_SetHandlerForFatalError(vm, OnFatalError));
117    bool fataled = false;
118    setjmp(buf);
119    if (!fataled) {
120        fataled = true;
121        std::vector<JSVM_Value> arrayVec;
122        int loopCount = 1000;
123        for (int i = 0; i < loopCount; i++) {
124            JSVM_Value array;
125            JSVM_CALL(OH_JSVM_CreateArrayWithLength(env, 0xffffff, &array));
126            arrayVec.push_back(array);
127        }
128    }
129    if (fatalHandlerFinished) {
130      OH_LOG_INFO(LOG_APP, "JSVM Trigger Fatal-Error: success");
131    } else {
132      OH_LOG_ERROR(LOG_APP, "JSVM Trigger Fatal-Error: failed");
133    }
134    // Cancel the fatal error handler.
135    JSVM_CALL(OH_JSVM_SetHandlerForFatalError(vm, NULL));
136    JSVM_Value checked;
137    OH_JSVM_GetBoolean(env, true, &checked);
138    return checked;
139}
140
141static JSVM_CallbackStruct param[] = {
142    {.data = nullptr, .callback = TriggerFatalError},
143};
144static JSVM_CallbackStruct *method = param;
145
146static JSVM_PropertyDescriptor descriptor[] = {
147    {"triggerFatalError", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
148};
149```
150#### JS Example
151
152const char* srcCallNative = R"JS(triggerFatalError())JS";
153
154#### Execution Result
155
156The following information is displayed in the log:<br>JSVM Trigger Fatal-Error: success
157
158### OH_JSVM_SetHandlerForPromiseReject
159Call **OH_JSVM_SetHandlerForPromiseReject** to set the function for handling promise rejection. If this API is called multiple times, only the last setting takes effect. If **NULL** is passed in for the function to set in this API, the previously set handler will be canceled.
160#### CPP Code
161
162```cpp
163static bool promiseRejectHandlerFinished = false;
164
165void OnPromiseReject(JSVM_Env env, JSVM_PromiseRejectEvent rejectEvent, JSVM_Value rejectInfo)
166{
167    bool result;
168    OH_JSVM_IsObject(env, rejectInfo, &result);
169    JSVM_Value promise;
170    JSVM_Value key1;
171    OH_JSVM_CreateStringUtf8(env, "promise", JSVM_AUTO_LENGTH, &key1);
172    OH_JSVM_GetProperty(env, rejectInfo, key1, &promise);
173    bool isPromise = false;
174    OH_JSVM_IsPromise(env, promise, &isPromise);
175    JSVM_Value value;
176    JSVM_Value key2;
177    OH_JSVM_CreateStringUtf8(env, "value", JSVM_AUTO_LENGTH, &key2);
178    OH_JSVM_GetProperty(env, rejectInfo, key2, &value);
179    JSVM_Value js_number;
180    OH_JSVM_CoerceToNumber(env, value, &js_number);
181    double res;
182    OH_JSVM_GetValueDouble(env, js_number, &res);
183    if (res == 42 && isPromise) {
184        promiseRejectHandlerFinished = true;
185    }
186}
187
188static JSVM_Value TriggerPromiseReject(JSVM_Env env, JSVM_CallbackInfo info)
189{
190    promiseRejectHandlerFinished = false;
191    JSVM_VM vm;
192    JSVM_CALL(OH_JSVM_GetVM(env, &vm));
193    // Set a Promise-Reject handler.
194    JSVM_CALL(OH_JSVM_SetHandlerForPromiseReject(vm, OnPromiseReject));
195    JSVM_Value strVal;
196    char *str = "new Promise((resolve, reject) => { reject(42); })";
197    OH_JSVM_CreateStringUtf8(env, str, JSVM_AUTO_LENGTH, &strVal);
198    JSVM_Script script;
199    OH_JSVM_CompileScript(env, strVal, nullptr, 0, false, nullptr, &script);
200    JSVM_Value result;
201    JSVM_Status status = OH_JSVM_RunScript(env, script, &result);
202
203    if (promiseRejectHandlerFinished) {
204      OH_LOG_INFO(LOG_APP, "JSVM Trigger PromiseReject: success");
205    } else {
206      OH_LOG_ERROR(LOG_APP, "JSVM Trigger PromiseReject: failed");
207    }
208    // Cancel the Promise-Reject handler.
209    JSVM_CALL(OH_JSVM_SetHandlerForPromiseReject(vm, NULL));
210    JSVM_Value checked;
211    OH_JSVM_GetBoolean(env, true, &checked);
212    return checked;
213}
214
215static JSVM_CallbackStruct param[] = {
216    {.data = nullptr, .callback = TriggerPromiseReject},
217};
218static JSVM_CallbackStruct *method = param;
219
220static JSVM_PropertyDescriptor descriptor[] = {
221    {"triggerPromiseReject", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
222};
223```
224#### JS Example
225
226const char* srcCallNative = R"JS(triggerPromiseReject())JS";
227
228#### Execution Result
229
230The following information is displayed in the log: <br>JSVM Trigger PromiseReject: success
231