• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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