1# 使用JSVM-API进行异常的定制化处理 2 3## 简介 4 5JSVM-API提供了一组用于处理JSVM异常的接口。用户可以通过这些接口,向JSVM中注册回调函数。当JSVM触发异常时,会触发对所注册的回调函数的回调。 6这些接口提供了对JS引擎中某些关键错误的定制化处理能力,可以帮助开发者在运行时更好地管理错误和异常情况。 7 8## 基本概念 9 10当JS引擎遇到内存不足的问题时,系统会抛出一个OOM Error,如果开发者提前向JS引擎中注册了OOM-Error的处理函数,系统就会调用这个设置的处理函数,开发者可以在处理函数中执行一些清理或者日志记录操作。 11当JS引擎发生致命错误时,例如执行JavaScript代码时出现无法恢复的错误,系统会抛出一个Fatal Error,同时系统会调用用户提前设置的处理Fatal Error的函数。在这个处理函数中,用户可以输出额外的日志或者报告错误,而不是让程序直接崩溃。 12当JavaScript中的Promise被拒绝,而这个拒绝又没有被catch处理时,系统就会抛出一个Promise Reject,同时系统会调用用户提前设置的处理Promise Reject的函数。在这个处理函数中,用户可以处理未捕获的Promise拒绝。 13 14## 接口说明 15 16| 接口 | 功能说明 | 17|----------------------------|-------------------------------------| 18| OH_JSVM_SetHandlerForOOMError | 用于在VM中设置处理OOM-Error的函数| 19| OH_JSVM_SetHandlerForFatalError | 用于在VM中设置处理Fatal-Error的函数| 20| OH_JSVM_SetHandlerForPromiseReject | 用于在VM中设置处理Promise-Reject的函数 | 21 22## 使用示例 23 24JSVM-API接口开发流程参考[使用JSVM-API实现JS与C/C++语言交互开发流程](use-jsvm-process.md),本文仅对接口对应C++相关代码进行展示。 25 26### OH_JSVM_SetHandlerForOOMError 27通过OH_JSVM_SetHandlerForOOMError,用户可以设置处理OOM Error的函数。当多次调用这个API进行函数设置时,仅最后一次设置会生效。当用户传入的设置函数为NULL时,则表示取消之前设置的处理函数。 28 29#### cpp部分代码 30 31```cpp 32#include <csetjmp> 33 34static jmp_buf buf; 35static bool oomHandlerFinished = false; 36 37void OnOOMError(const char *location, const char *detail, bool isHeapOOM) 38{ 39 oomHandlerFinished = true; 40 longjmp(buf, 1); 41} 42 43static JSVM_Value TriggerOOMError(JSVM_Env env, JSVM_CallbackInfo info) 44{ 45 oomHandlerFinished = false; 46 JSVM_VM vm; 47 JSVM_CALL(OH_JSVM_GetVM(env, &vm)); 48 // 设置OOM Error处理函数 49 JSVM_CALL(OH_JSVM_SetHandlerForOOMError(vm, OnOOMError)); 50 bool oomed = false; 51 setjmp(buf); 52 if (!oomed) { 53 oomed = true; 54 // 触发OOM 55 std::vector<JSVM_Value> arrayVec; 56 int loopCount = 1000; 57 for (int i = 0; i < loopCount; i++) { 58 JSVM_Value array; 59 JSVM_CALL(OH_JSVM_CreateArrayWithLength(env, 0xffffff, &array)); 60 arrayVec.push_back(array); 61 } 62 } 63 if (oomHandlerFinished) { 64 OH_LOG_INFO(LOG_APP, "JSVM Trigger OOM-Error: success"); 65 } else { 66 OH_LOG_ERROR(LOG_APP, "JSVM Trigger OOM-Error: failed"); 67 } 68 // 取消对OOM Error处理函数的设置 69 JSVM_CALL(OH_JSVM_SetHandlerForOOMError(vm, NULL)); 70 JSVM_Value checked; 71 OH_JSVM_GetBoolean(env, true, &checked); 72 return checked; 73} 74 75static JSVM_CallbackStruct param[] = { 76 {.data = nullptr, .callback = TriggerOOMError}, 77}; 78static JSVM_CallbackStruct *method = param; 79 80static JSVM_PropertyDescriptor descriptor[] = { 81 {"triggerOOMError", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, 82}; 83``` 84#### 样例测试JS 85 86const char *srcCallNative = R"JS(triggerOOMError();)JS"; 87 88#### 执行结果 89 90在LOG中输出: JSVM Trigger OOM-Error: success 91 92### OH_JSVM_SetHandlerForFatalError 93通过OH_JSVM_SetHandlerForFatalError,用户可以设置处理Fatal Error的函数。当多次调用这个API进行函数设置时,仅最后一次设置会生效。当用户传入的设置函数为NULL时,则表示取消之前设置的处理函数。 94#### cpp部分代码 95 96```cpp 97#include <csetjmp> 98 99static jmp_buf buf; 100static bool fatalHandlerFinished = false; 101void OnFatalError(const char *location, const char *message) 102{ 103 fatalHandlerFinished = true; 104 OH_LOG_INFO(LOG_APP, "Run in 106"); 105 longjmp(buf, 1); 106} 107 108static JSVM_Value TriggerFatalError(JSVM_Env env, JSVM_CallbackInfo info) 109{ 110 fatalHandlerFinished = false; 111 JSVM_VM vm; 112 JSVM_CALL(OH_JSVM_GetVM(env, &vm)); 113 // 设置Fatal Error处理函数 114 JSVM_CALL(OH_JSVM_SetHandlerForFatalError(vm, OnFatalError)); 115 bool fataled = false; 116 setjmp(buf); 117 if (!fataled) { 118 fataled = true; 119 std::vector<JSVM_Value> arrayVec; 120 int loopCount = 1000; 121 for (int i = 0; i < loopCount; i++) { 122 JSVM_Value array; 123 JSVM_CALL(OH_JSVM_CreateArrayWithLength(env, 0xffffff, &array)); 124 arrayVec.push_back(array); 125 } 126 } 127 if (fatalHandlerFinished) { 128 OH_LOG_INFO(LOG_APP, "JSVM Trigger Fatal-Error: success"); 129 } else { 130 OH_LOG_ERROR(LOG_APP, "JSVM Trigger Fatal-Error: failed"); 131 } 132 // 取消对Fatal Error处理函数的设置 133 JSVM_CALL(OH_JSVM_SetHandlerForFatalError(vm, NULL)); 134 JSVM_Value checked; 135 OH_JSVM_GetBoolean(env, true, &checked); 136 return checked; 137} 138 139static JSVM_CallbackStruct param[] = { 140 {.data = nullptr, .callback = TriggerFatalError}, 141}; 142static JSVM_CallbackStruct *method = param; 143 144static JSVM_PropertyDescriptor descriptor[] = { 145 {"triggerFatalError", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, 146}; 147``` 148#### 样例测试JS 149 150const char* srcCallNative = R"JS(triggerFatalError())JS"; 151 152#### 执行结果 153 154在LOG中输出: JSVM Trigger Fatal-Error: success 155 156### OH_JSVM_SetHandlerForPromiseReject 157通过OH_JSVM_SetHandlerForPromiseReject,用户可以设置处理Promise Reject的函数。当多次调用这个API进行函数设置时,仅最后一次设置会生效。当用户传入的设置函数为NULL时,则表示取消之前设置的处理函数。 158#### cpp部分代码 159 160```cpp 161static bool promiseRejectHandlerFinished = false; 162 163void OnPromiseReject(JSVM_Env env, JSVM_PromiseRejectEvent rejectEvent, JSVM_Value rejectInfo) 164{ 165 bool result; 166 OH_JSVM_IsObject(env, rejectInfo, &result); 167 JSVM_Value promise; 168 JSVM_Value key1; 169 OH_JSVM_CreateStringUtf8(env, "promise", JSVM_AUTO_LENGTH, &key1); 170 OH_JSVM_GetProperty(env, rejectInfo, key1, &promise); 171 bool isPromise = false; 172 OH_JSVM_IsPromise(env, promise, &isPromise); 173 JSVM_Value value; 174 JSVM_Value key2; 175 OH_JSVM_CreateStringUtf8(env, "value", JSVM_AUTO_LENGTH, &key2); 176 OH_JSVM_GetProperty(env, rejectInfo, key2, &value); 177 JSVM_Value js_number; 178 OH_JSVM_CoerceToNumber(env, value, &js_number); 179 double res; 180 OH_JSVM_GetValueDouble(env, js_number, &res); 181 if (res == 42 && isPromise) { 182 promiseRejectHandlerFinished = true; 183 } 184} 185 186static JSVM_Value TriggerPromiseReject(JSVM_Env env, JSVM_CallbackInfo info) 187{ 188 promiseRejectHandlerFinished = false; 189 JSVM_VM vm; 190 JSVM_CALL(OH_JSVM_GetVM(env, &vm)); 191 // 设置Promise Reject处理函数 192 JSVM_CALL(OH_JSVM_SetHandlerForPromiseReject(vm, OnPromiseReject)); 193 JSVM_Value strVal; 194 char *str = "new Promise((resolve, reject) => { reject(42); })"; 195 OH_JSVM_CreateStringUtf8(env, str, JSVM_AUTO_LENGTH, &strVal); 196 JSVM_Script script; 197 OH_JSVM_CompileScript(env, strVal, nullptr, 0, false, nullptr, &script); 198 JSVM_Value result; 199 JSVM_Status status = OH_JSVM_RunScript(env, script, &result); 200 201 if (promiseRejectHandlerFinished) { 202 OH_LOG_INFO(LOG_APP, "JSVM Trigger PromiseReject: success"); 203 } else { 204 OH_LOG_ERROR(LOG_APP, "JSVM Trigger PromiseReject: failed"); 205 } 206 // 取消对Promise Reject处理函数的设置 207 JSVM_CALL(OH_JSVM_SetHandlerForPromiseReject(vm, NULL)); 208 JSVM_Value checked; 209 OH_JSVM_GetBoolean(env, true, &checked); 210 return checked; 211} 212 213static JSVM_CallbackStruct param[] = { 214 {.data = nullptr, .callback = TriggerPromiseReject}, 215}; 216static JSVM_CallbackStruct *method = param; 217 218static JSVM_PropertyDescriptor descriptor[] = { 219 {"triggerPromiseReject", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, 220}; 221``` 222#### 样例测试JS 223 224const char* srcCallNative = R"JS(triggerPromiseReject())JS"; 225 226#### 执行结果 227 228在LOG中输出: JSVM Trigger PromiseReject: success