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