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