• 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- 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.
12- 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.
13- 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.
14
15## Available APIs
16
17| API                      | Description                           |
18|----------------------------|-------------------------------------|
19| OH_JSVM_SetHandlerForOOMError         | Sets an OOM error handler for a JSVM.|
20| OH_JSVM_SetHandlerForFatalError   | Sets a fatal error handler for a JSVM.|
21| OH_JSVM_SetHandlerForPromiseReject | Sets a promise rejection handler for a JSVM.|
22
23## Example
24
25If 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.
26
27### OH_JSVM_SetHandlerForOOMError
28Call **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.
29
30#### CPP Code
31
32```cpp
33#include <csetjmp>
34#include <vector>
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#include <vector>
101
102static jmp_buf buf;
103static bool fatalHandlerFinished = false;
104void OnFatalError(const char *location, const char *message)
105{
106    fatalHandlerFinished = true;
107    OH_LOG_INFO(LOG_APP, "Run in 106");
108    longjmp(buf, 1);
109}
110
111static JSVM_Value TriggerFatalError(JSVM_Env env, JSVM_CallbackInfo info)
112{
113    fatalHandlerFinished = false;
114    JSVM_VM vm;
115    JSVM_CALL(OH_JSVM_GetVM(env, &vm));
116    // Set a fatal error handler.
117    JSVM_CALL(OH_JSVM_SetHandlerForFatalError(vm, OnFatalError));
118    bool fataled = false;
119    setjmp(buf);
120    if (!fataled) {
121        fataled = true;
122        std::vector<JSVM_Value> arrayVec;
123        int loopCount = 1000;
124        for (int i = 0; i < loopCount; i++) {
125            JSVM_Value array;
126            JSVM_CALL(OH_JSVM_CreateArrayWithLength(env, 0xffffff, &array));
127            arrayVec.push_back(array);
128        }
129    }
130    if (fatalHandlerFinished) {
131      OH_LOG_INFO(LOG_APP, "JSVM Trigger Fatal-Error: success");
132    } else {
133      OH_LOG_ERROR(LOG_APP, "JSVM Trigger Fatal-Error: failed");
134    }
135    // Cancel the fatal error handler.
136    JSVM_CALL(OH_JSVM_SetHandlerForFatalError(vm, NULL));
137    JSVM_Value checked;
138    OH_JSVM_GetBoolean(env, true, &checked);
139    return checked;
140}
141
142static JSVM_CallbackStruct param[] = {
143    {.data = nullptr, .callback = TriggerFatalError},
144};
145static JSVM_CallbackStruct *method = param;
146
147static JSVM_PropertyDescriptor descriptor[] = {
148    {"triggerFatalError", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
149};
150```
151#### JS Example
152
153const char* srcCallNative = R"JS(triggerFatalError())JS";
154
155#### Execution Result
156
157The following information is displayed in the log:<br>JSVM Trigger Fatal-Error: success
158
159### OH_JSVM_SetHandlerForPromiseReject
160Call **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.
161#### CPP Code
162
163```cpp
164static bool promiseRejectHandlerFinished = false;
165
166void OnPromiseReject(JSVM_Env env, JSVM_PromiseRejectEvent rejectEvent, JSVM_Value rejectInfo)
167{
168    bool result;
169    OH_JSVM_IsObject(env, rejectInfo, &result);
170    JSVM_Value promise;
171    JSVM_Value key1;
172    OH_JSVM_CreateStringUtf8(env, "promise", JSVM_AUTO_LENGTH, &key1);
173    OH_JSVM_GetProperty(env, rejectInfo, key1, &promise);
174    bool isPromise = false;
175    OH_JSVM_IsPromise(env, promise, &isPromise);
176    JSVM_Value value;
177    JSVM_Value key2;
178    OH_JSVM_CreateStringUtf8(env, "value", JSVM_AUTO_LENGTH, &key2);
179    OH_JSVM_GetProperty(env, rejectInfo, key2, &value);
180    JSVM_Value js_number;
181    OH_JSVM_CoerceToNumber(env, value, &js_number);
182    double res;
183    OH_JSVM_GetValueDouble(env, js_number, &res);
184    if (res == 42 && isPromise) {
185        promiseRejectHandlerFinished = true;
186    }
187}
188
189static JSVM_Value TriggerPromiseReject(JSVM_Env env, JSVM_CallbackInfo info)
190{
191    promiseRejectHandlerFinished = false;
192    JSVM_VM vm;
193    JSVM_CALL(OH_JSVM_GetVM(env, &vm));
194    // Set a Promise-Reject handler.
195    JSVM_CALL(OH_JSVM_SetHandlerForPromiseReject(vm, OnPromiseReject));
196    JSVM_Value strVal;
197    char *str = "new Promise((resolve, reject) => { reject(42); })";
198    OH_JSVM_CreateStringUtf8(env, str, JSVM_AUTO_LENGTH, &strVal);
199    JSVM_Script script;
200    OH_JSVM_CompileScript(env, strVal, nullptr, 0, false, nullptr, &script);
201    JSVM_Value result;
202    JSVM_Status status = OH_JSVM_RunScript(env, script, &result);
203
204    if (promiseRejectHandlerFinished) {
205      OH_LOG_INFO(LOG_APP, "JSVM Trigger PromiseReject: success");
206    } else {
207      OH_LOG_ERROR(LOG_APP, "JSVM Trigger PromiseReject: failed");
208    }
209    // Cancel the Promise-Reject handler.
210    JSVM_CALL(OH_JSVM_SetHandlerForPromiseReject(vm, NULL));
211    JSVM_Value checked;
212    OH_JSVM_GetBoolean(env, true, &checked);
213    return checked;
214}
215
216static JSVM_CallbackStruct param[] = {
217    {.data = nullptr, .callback = TriggerPromiseReject},
218};
219static JSVM_CallbackStruct *method = param;
220
221static JSVM_PropertyDescriptor descriptor[] = {
222    {"triggerPromiseReject", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
223};
224```
225#### JS Example
226
227const char* srcCallNative = R"JS(triggerPromiseReject())JS";
228
229#### Execution Result
230
231The following information is displayed in the log: <br>JSVM Trigger PromiseReject: success
232