• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# JSVM-API支持的数据类型和接口
2
3## JSVM-API的数据类型
4
5### JSVM_Status
6
7是一个枚举数据类型,表示JSVM-API接口返回的状态信息。
8
9每当调用一个JSVM-API函数,都会返回该值,表示操作成功与否的相关信息。
10
11```c++
12typedef enum {
13    JSVM_OK,
14    JSVM_INVALID_ARG,
15    JSVM_OBJECT_EXPECTED,
16    JSVM_STRING_EXPECTED,
17    JSVM_NAME_EXPECTED,
18    JSVM_FUNCTION_EXPECTED,
19    JSVM_NUMBER_EXPECTED,
20    JSVM_BOOL_EXPECTED,
21    JSVM_ARRAY_EXPECTED,
22    JSVM_GENERIC_FAILURE,
23    JSVM_PENDING_EXCEPTION,
24    JSVM_CENCELLED,
25    JSVM_ESCAPE_CALLED_TWICE,
26    JSVM_HANDLE_SCOPE_MISMATCH,
27    JSVM_CALLBACK_SCOPE_MISMATCH,
28    JSVM_QUEUE_FULL,
29    JSVM_CLOSING,
30    JSVM_BIGINT_EXPECTED,
31    JSVM_DATA_EXPECTED,
32    JSVM_CALLBACK_SCOPE_MISMATCH,
33    JSVM_DETACHABLE_ARRAYBUFFER_EXPECTED,
34    JSVM_WOULD_DEADLOCK,  /* unused */
35    JSVM_NO_EXTERNAL_BUFFERS_ALLOWED,
36    JSVM_CANNOT_RUN_JS
37} JSVM_Status;
38```
39
40### JSVM_ExtendedErrorInfo
41
42一个结构体,在调用函数不成功时存储了较为详细的错误信息。
43
44```c++
45typedef struct {
46    const char* errorMessage;
47    void* engineReserved;
48    uint32_t engineErrorCode;
49    JSVM_Status errorCode;
50} JSVM_ExtendedErrorInfo;
51```
52
53### JSVM_Value
54
55在C++代码中,表示一个JavaScript值。
56
57### JSVM_Env
58
59- 用于表示JSVM-API执行时的上下文,Native侧函数入参,并传递给函数中的JSVM-API接口。
60
61- 退出Native侧插件时,JSVM_Env将失效,该事件通过回调传递给OH_JSVM_SetInstanceData。
62
63- 禁止缓存JSVM_Env,禁止在不同Worker中传递JSVM_Env。
64
65- 在不同线程间共享JSVM_Env时,要保证在线程切换时在前一个线程中关闭env scope并在新的线程中打开新的env scope,以保证threadlocal变量的线程隔离。
66
67### JSVM_ValueType
68
69JSVM_Value的类型。包含了ECMAScript语言规范中定义的类型,其中JSVM_EXTERNAL表示外部数据类型。
70
71```c++
72typedef enum {
73    JSVM_UNDEFINED,
74    JSVM_NULL,
75    JSVM_BOOLEAN,
76    JSVM_NUMBER,
77    JSVM_STRING,
78    JSVM_SYMBOL,
79    JSVM_OBJECT,
80    JSVM_FUNCTION,
81    JSVM_EXTERNAL,
82    JSVM_BIGINT,
83} JSVM_ValueType;
84```
85
86### JSVM_TypedarrayType
87
88TypedArray的基本二进制标量数据类型。
89
90```c++
91typedef enum {
92    JSVM_INT8_ARRAY,
93    JSVM_UINT8_ARRAY,
94    JSVM_UINT8_CLAMPED_ARRAY,
95    JSVM_INT16_ARRAY,
96    JAVM_UINT16_ARRAY,
97    JSVM_INT32_ARRAY,
98    JSVM_UINT32_ARRAY,
99    JSVM_FLOAT32_ARRAY,
100    JSVM_FLOAT64_ARRAY,
101    JSVM_BIGINT64_ARRAY,
102    JSVM_BIGUINT64_ARRAY,
103} JSVM_TypedarrayType;
104```
105
106### 内存管理类型
107
108JSVM-API包含以下内存管理类型:
109
110**JSVM_HandleScope**
111
112JSVM_HandleScope数据类型是用来管理JavaScript对象的生命周期的。它允许JavaScript对象在一定范围内保持活动状态,以便在JavaScript代码中使用。在创建JSVM_HandleScope时,所有在该范围内创建的JavaScript对象都会保持活动状态,直到结束。这样可以避免在JavaScript代码中使用已经被释放的对象,从而提高代码的可靠性和性能
113
114**JSVM_EscapableHandleScope**
115
116- 由OH_JSVM_OpenEscapableHandleScope接口创建,由OH_JSVM_CloseEscapableHandleScope接口关闭。
117
118- 表示一种特殊类型的句柄范围,用于将在JSVM_EscapableHandleScope范围内创建的值返回给父scope。
119
120- 用于OH_JSVM_EscapeHandle接口,将JSVM_EscapableHandleScope提升到JavaScript对象,以便在外部作用域使用。
121
122**JSVM_Ref**
123
124指向JSVM_Value,允许用户管理JavaScript值的生命周期。
125
126**JSVM_TypeTag**
127
128该结构体定义了一个包含两个无符号64位整数的类型标签,用于标识一个JSVM-API值的类型信息。
129
130```c++
131typedef struct {
132    uint64_t lower;
133    uint64_t upper;
134} JSVM_TypeTag;
135```
136
137- 存储了两个无符号64位整数的128位值,用它来标记JavaScript对象,确保它们属于某种类型。
138
139- 比OH_JSVM_Instanceof更强的类型检查,如果对象的原型被操纵,OH_JSVM_Instanceof可能会报告误报。
140
141- JSVM_TypeTag 在与 OH_JSVM_Wrap 结合使用时最有用,因为它确保从包装对象检索的指针可以安全地转换为与先前应用于JavaScript对象的类型标记相对应的Native类型。
142
143### 回调类型
144
145JSVM-API包含以下回调类型:
146
147**JSVM_CallbackInfo**
148
149表示用户定义的Native函数,暴露给JavaScript,即JS侧调用的接口;一般不在此Callback中创建Handle或者CallbackScope。
150
151**JSVM_CallbackStruct**
152
153用户提供的Native函数的回调函数指针和数据,JSVM_CallbackStruct将通过JSVM-API暴露给JavaScript。
154
155```c++
156typedef struct {
157  JSVM_Value(*callback)(JSVM_Env env, JSVM_CallbackInfo info);
158  void* data;
159} JSVM_CallbackStruct;
160```
161
162**JSVM_Callback**
163
164表示用户定义的Native函数,暴露给JavaScript,即JS侧调用的接口;除非在对象生命周期管理中有特殊要求,一般不在此callback中创建handle或者callback scope。
165
166基本用法如下:
167
168```c++
169typedef JSVM_CallbackStruct* JSVM_Callback;
170```
171
172**JSVM_Finalize**
173
174函数指针,用于传入OH_JSVM_SetInstanceData、OH_JSVM_CreateExternal、OH_JSVM_Wrap等接口。JSVM_Finalize在对象被回收时会被调用,可用于在JavaScript对象被垃圾回收时释放Native对象。
175
176写法如下:
177
178```c++
179typedef void (JSVM_Finalize)(JSVM_Env env, void finalizeData, void* finalizeHint);
180```
181
182## 支持的JSVM-API接口
183
184标准JS引擎的能力通过JSVM-API提供。JSVM-API支持动态链接到不同版本的JS引擎库,从而为开发者屏蔽掉不同引擎接口的差异。JSVM-API提供引擎生命周期管理、JS context管理、JS代码执行、JS/C++互操作、执行环境快照、codecache等能力,具体可见下文。
185
186### 使用 JSVM-API 接口创建引擎实例及 JS 执行上下文环境
187
188#### 场景介绍
189
190执行JS代码需要先创建JavaScript VM,创建JS执行的上下文环境。
191
192#### 接口说明
193| 接口 | 功能说明 |
194| -------- | -------- |
195| OH_JSVM_Init| 初始化JavaScript引擎实例 |
196| OH_JSVM_CreateVM| 创建JavaScript引擎实例|
197| OH_JSVM_DestroyVM| 销毁JavaScript引擎实例 |
198| OH_JSVM_OpenVMScope| 打开一个新的VM scope,引擎实例只能在scope范围内使用,可以保证引擎实例不被销毁 |
199| OH_JSVM_CloseVMScope| 关闭VM scope |
200| OH_JSVM_CreateEnv| 创建一个新的JS执行上下文环境,并注册指定的Native函数 |
201| OH_JSVM_DestroyEnv| 销毁一个JS执行上下文环境 |
202| OH_JSVM_OpenEnvScope| 打开一个新的Env scope,Env只能在scope范围内使用 |
203| OH_JSVM_CloseEnvScope| 关闭Env scope |
204| OH_JSVM_OpenHandleScope| 打开一个Handle scope,确保scope范围内的JSVM_Value不被GC回收 |
205| OH_JSVM_CloseHandleScope| 关闭Handle scope |
206
207场景示例:
208创建及销毁JavaScript引擎实例,包含创建及销毁JS执行上下文环境
209
210```c++
211bool VM_INIT = false;
212
213static JSVM_Value ConsoleInfo(JSVM_Env env, JSVM_CallbackInfo info) {
214    size_t argc = 1;
215    JSVM_Value args[1];
216    char log[256] = "";
217    size_t logLength;
218    OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL);
219
220    OH_JSVM_GetValueStringUtf8(env, args[0], log, 255, &logLength);
221    log[255] = 0;
222    OH_LOG_INFO(LOG_APP, "JSVM API TEST: %{public}s", log);
223    return nullptr;
224}
225
226static JSVM_Value Add(JSVM_Env env, JSVM_CallbackInfo info) {
227    size_t argc = 2;
228    JSVM_Value args[2];
229    OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL);
230    double num1, num2;
231    env, OH_JSVM_GetValueDouble(env, args[0], &num1);
232    OH_JSVM_GetValueDouble(env, args[1], &num2);
233    JSVM_Value sum = nullptr;
234    OH_JSVM_CreateDouble(env, num1 + num2, &sum);
235    return sum;
236}
237
238static napi_value MyJSVMDemo([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) {
239    std::thread t([]() {
240        if (!VM_INIT) {
241            // JSVM only need init once
242            JSVM_InitOptions initOptions;
243            memset(&initOptions, 0, sizeof(initOptions));
244            OH_JSVM_Init(&initOptions);
245            VM_INIT = true;
246        }
247        // create vm, and open vm scope
248        JSVM_VM vm;
249        JSVM_CreateVMOptions options;
250        memset(&options, 0, sizeof(options));
251        OH_JSVM_CreateVM(&options, &vm);
252
253        JSVM_VMScope vmScope;
254        OH_JSVM_OpenVMScope(vm, &vmScope);
255
256        JSVM_CallbackStruct param[] = {
257            {.data = nullptr, .callback = ConsoleInfo},
258            {.data = nullptr, .callback = Add},
259        };
260        JSVM_PropertyDescriptor descriptor[] = {
261            {"consoleinfo", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
262            {"add", NULL, &param[1], NULL, NULL, NULL, JSVM_DEFAULT},
263        };
264        // create env, register native method, and open env scope
265        JSVM_Env env;
266        OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env);
267
268        JSVM_EnvScope envScope;
269        OH_JSVM_OpenEnvScope(env, &envScope);
270
271        // open handle scope
272        JSVM_HandleScope handleScope;
273        OH_JSVM_OpenHandleScope(env, &handleScope);
274
275        std::string sourceCodeStr = "\
276{\
277let value = add(4.96, 5.28);\
278consoleinfo('Result is:' + value);\
279}\
280";
281        // compile js script
282        JSVM_Value sourceCodeValue;
283        OH_JSVM_CreateStringUtf8(env, sourceCodeStr.c_str(), sourceCodeStr.size(), &sourceCodeValue);
284        JSVM_Script script;
285        OH_JSVM_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script);
286        JSVM_Value result;
287        // run js script
288        OH_JSVM_RunScript(env, script, &result);
289        JSVM_ValueType type;
290        OH_JSVM_Typeof(env, result, &type);
291        OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type);
292
293        // exit vm and clean memory
294        OH_JSVM_CloseHandleScope(env, handleScope);
295
296        OH_JSVM_CloseEnvScope(env, envScope);
297        OH_JSVM_DestroyEnv(env);
298
299        OH_JSVM_CloseVMScope(vm, vmScope);
300        OH_JSVM_DestroyVM(vm);
301    });
302
303    t.detach();
304
305    return nullptr;
306}
307```
308
309### 使用 JSVM-API 接口编译及执行 JS 代码
310
311#### 场景介绍
312
313编译及执行JS代码。
314
315#### 接口说明
316| 接口 | 功能说明 |
317| -------- | -------- |
318| OH_JSVM_CompileScript| 编译JavaScript代码并返回绑定到当前环境的编译脚本 |
319| OH_JSVM_CreateCodeCache| 为编译脚本创建code cache|
320| OH_JSVM_RunScript| 执行编译脚本 |
321
322场景示例:
323编译及执行JS代码(创建vm,注册function,执行js,销毁vm)。
324
325```c++
326#include <cstring>
327#include <fstream>
328#include <string>
329#include <vector>
330
331// 依赖libjsvm.so
332#include "ark_runtime/jsvm.h"
333
334using namespace std;
335
336static JSVM_Value Hello(JSVM_Env env, JSVM_CallbackInfo info) {
337    JSVM_Value output;
338    void* data = nullptr;
339    OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data);
340    OH_JSVM_CreateStringUtf8(env, (char*)data, strlen((char*)data), &output);
341    return output;
342}
343
344static JSVM_CallbackStruct hello_cb = { Hello, (void*)"Hello" };
345
346static string srcGlobal = R"JS(
347const concat = (...args) => args.reduce((a, b) => a + b);
348)JS";
349
350static void RunScript(JSVM_Env env, string& src,
351                       const uint8_t** dataPtr = nullptr,
352                       size_t* lengthPtr = nullptr) {
353    JSVM_HandleScope handleScope;
354    OH_JSVM_OpenHandleScope(env, &handleScope);
355
356    JSVM_Value jsSrc;
357    OH_JSVM_CreateStringUtf8(env, src.c_str(), src.size(), &jsSrc);
358
359    const uint8_t* data = dataPtr ? *dataPtr : nullptr;
360    size_t length = lengthPtr ? *lengthPtr : 0;
361    bool cacheRejected = true;
362    JSVM_Script script;
363    // 编译js代码
364    OH_JSVM_CompileScript(env, jsSrc, data, length, true, &cacheRejected, &script);
365    printf("Code cache is %s\n", cacheRejected ? "rejected" : "used");
366
367    JSVM_Value result;
368    // 执行js代码
369    OH_JSVM_RunScript(env, script, &result);
370
371    char resultStr[128];
372    size_t size;
373    OH_JSVM_GetValueStringUtf8(env, result, resultStr, 128, &size);
374    printf("%s\n", resultStr);
375    if (dataPtr && lengthPtr && *dataPtr == nullptr) {
376        // 将js源码编译出的脚本保存到cache,可以避免重复编译,带来性能提升
377        OH_JSVM_CreateCodeCache(env, script, dataPtr, lengthPtr);
378        printf("Code cache created with length = %ld\n", *lengthPtr);
379    }
380
381    OH_JSVM_CloseHandleScope(env, handleScope);
382}
383
384static void CreateSnapshot() {
385    JSVM_VM vm;
386    JSVM_CreateVMOptions options;
387    memset(&options, 0, sizeof(options));
388    options.isForSnapshotting = true;
389    OH_JSVM_CreateVM(&options, &vm);
390    JSVM_VMScope vmScope;
391    OH_JSVM_OpenVMScope(vm, &vmScope);
392
393    JSVM_Env env;
394    // 将native函数注册成js可调用的方法,hello_cb中记录该native方法的指针和参数等信息
395    JSVM_PropertyDescriptor descriptors[] = {
396        { "hello", NULL, &hello_cb, NULL, NULL, NULL, JSVM_DEFAULT }
397    };
398    OH_JSVM_CreateEnv(vm, 1, descriptors, &env);
399
400    JSVM_EnvScope envScope;
401    OH_JSVM_OpenEnvScope(env, &envScope);
402    // 执行js源码src,src中可以包含任何js语法。也可以调用已注册的native方法。
403    string src = srcGlobal + "concat(hello(), ', ', 'World from CreateSnapshot!');";
404    RunScript(env, src);
405
406    // 创建snapshot,将当前的env保存到字符串,可以在某个时机通过该字符串还原出env,避免重复定义该env中的属性,带来性能提升。
407    const char* blobData = nullptr;
408    size_t blobSize = 0;
409    JSVM_Env envs[1] = { env };
410    OH_JSVM_CreateSnapshot(vm, 1, envs, &blobData, &blobSize);
411    printf("Snapshot blob size = %ld\n", blobSize);
412
413    // 如果将snapshot保存到文件中,需要考虑应用中的文件读写权限
414    ofstream file("/data/storage/el2/base/files/blob.bin", ios::out | ios::binary | ios::trunc);
415    file.write(blobData, blobSize);
416    file.close();
417
418    OH_JSVM_CloseEnvScope(env, envScope);
419    OH_JSVM_DestroyEnv(env);
420    OH_JSVM_CloseVMScope(vm, vmScope);
421    OH_JSVM_DestroyVM(vm);
422}
423
424void RunWithoutSnapshot(const uint8_t** dataPtr, size_t* lengthPtr) {
425    // 创建虚拟机实例
426    JSVM_VM vm;
427    OH_JSVM_CreateVM(nullptr, &vm);
428    JSVM_VMScope vmScope;
429    OH_JSVM_OpenVMScope(vm, &vmScope);
430
431    JSVM_Env env;
432    // 将native函数注册成js可调用的方法,hello_cb中记录该native方法的指针和参数等信息
433    JSVM_PropertyDescriptor descriptors[] = {
434        { "hello", NULL, &hello_cb, NULL, NULL, NULL, JSVM_DEFAULT }
435    };
436    OH_JSVM_CreateEnv(vm, 1, descriptors, &env);
437    JSVM_EnvScope envScope;
438    OH_JSVM_OpenEnvScope(env, &envScope);
439    // 执行js源码src,src中可以包含任何js语法。也可以调用已注册的native方法。
440    auto src = srcGlobal + "concat(hello(), ', ', 'World', ' from RunWithoutSnapshot!')";
441    RunScript(env, src, dataPtr, lengthPtr);
442
443    OH_JSVM_CloseEnvScope(env, envScope);
444    OH_JSVM_DestroyEnv(env);
445    OH_JSVM_CloseVMScope(vm, vmScope);
446    OH_JSVM_DestroyVM(vm);
447}
448
449void RunWithSnapshot(const uint8_t **dataPtr, size_t *lengthPtr) {
450    // The lifetime of blobData must not be shorter than that of the vm.
451    // 如果从文件中读取snapshot,需要考虑应用中的文件读写权限
452    vector<char> blobData;
453    ifstream file("/data/storage/el2/base/files/blob.bin", ios::in | ios::binary | ios::ate);
454    size_t blobSize = file.tellg();
455    blobData.resize(blobSize);
456    file.seekg(0, ios::beg);
457    file.read(blobData.data(), blobSize);
458    file.close();
459
460    // 创建虚拟机实例
461    JSVM_VM vm;
462    JSVM_CreateVMOptions options;
463    memset(&options, 0, sizeof(options));
464    options.snapshotBlobData = blobData.data();
465    options.snapshotBlobSize = blobSize;
466    OH_JSVM_CreateVM(&options, &vm);
467    JSVM_VMScope vmScope;
468    OH_JSVM_OpenVMScope(vm, &vmScope);
469
470    // 从快照中创建env
471    JSVM_Env env;
472    OH_JSVM_CreateEnvFromSnapshot(vm, 0, &env);
473    JSVM_EnvScope envScope;
474    OH_JSVM_OpenEnvScope(env, &envScope);
475
476    // 执行js脚本,因为快照记录的env中定义了hello(),所以无需重新定义。dataPtr中如果保存了编译后的js脚本,就能直接执行js脚本,避免从源码重复编译。
477    string src = "concat(hello(), ', ', 'World', ' from RunWithSnapshot!')";
478    RunScript(env, src, dataPtr, lengthPtr);
479
480    OH_JSVM_CloseEnvScope(env, envScope);
481    OH_JSVM_DestroyEnv(env);
482    OH_JSVM_CloseVMScope(vm, vmScope);
483    OH_JSVM_DestroyVM(vm);
484}
485
486void PrintVmInfo() {
487    JSVM_VMInfo vmInfo;
488    OH_JSVM_GetVMInfo(&vmInfo);
489    printf("apiVersion: %d\n", vmInfo.apiVersion);
490    printf("engine: %s\n", vmInfo.engine);
491    printf("version: %s\n", vmInfo.version);
492    printf("cachedDataVersionTag: 0x%x\n", vmInfo.cachedDataVersionTag);
493}
494
495static intptr_t externals[] = {
496    (intptr_t)&hello_cb,
497    0,
498};
499
500int main(int argc, char *argv[]) {
501    if (argc <= 1) {
502        printf("Usage: %s gen-snapshot|use-snapshot|no-snapshot\n", argv[0]);
503        return 0;
504    }
505
506    JSVM_InitOptions initOptions;
507    memset(&initOptions, 0, sizeof(initOptions));
508    initOptions.externalReferences = externals;
509    // 初始化引擎,一个进程中只能初始化一次
510    OH_JSVM_Init(&initOptions);
511    PrintVmInfo();
512
513    if (argv[1] == string("gen-snapshot")) {
514        CreateSnapshot();
515        return 0;
516    }
517
518    // snapshot可以记录下某个时间的js执行环境,可以跨进程通过snapshot快速还原出js执行上下文环境,前提是保证snapshot数据的生命周期。
519    const auto useSnapshot = argv[1] == string("use-snapshot");
520    const auto run = useSnapshot ? RunWithSnapshot : RunWithoutSnapshot;
521    const uint8_t* data = nullptr;
522    size_t length = 0;
523    run(&data, &length);
524    run(&data, &length);
525    delete[] data;
526
527    return 0;
528}
529```
530
531### 异常处理
532
533#### 场景介绍
534
535获取、抛出、清理JS异常
536
537#### 接口说明
538| 接口 | 功能说明 |
539| -------- | -------- |
540| OH_JSVM_Throw| 抛出一个JS值 |
541| OH_JSVM_ThrowTypeError| 抛出一个JS TypeError |
542| OH_JSVM_ThrowRangeError| 抛出一个JS RangeError |
543| OH_JSVM_IsError| 判断JS值是否为JS异常 |
544| OH_JSVM_CreateError| 创建一个JS异常 |
545| OH_JSVM_CreateTypeError| 创建一个JS TypeError并返回 |
546| OH_JSVM_CreateRangeError| 创建一个JS RangeError并返回 |
547| OH_JSVM_ThrowError| 抛出一个JS异常 |
548| OH_JSVM_GetAndClearLastException| 清理并返回最后一个JS异常 |
549| OH_JSVM_IsExceptionPending| 判断当前是否有异常 |
550| OH_JSVM_GetLastErrorInfo| 获取最后一个异常的信息 |
551| OH_JSVM_ThrowSyntaxError| 抛出一个JS SyntaxError |
552| OH_JSVM_CreateSyntaxError| 创建一个JS SyntaxError并返回 |
553
554场景示例:
555以TypeError为例。创建,判断,并抛出JS TypeError。
556
557```c++
558JSVM_Value code = nullptr;
559JSVM_Value message = nullptr;
560OH_JSVM_CreateStringUtf8(env, "500", JSVM_AUTO_LENGTH, &code);
561OH_JSVM_CreateStringUtf8(env, "type error 500", JSVM_AUTO_LENGTH, &message);
562JSVM_Value error = nullptr;
563OH_JSVM_CreateTypeError(env, code, message, &error);
564bool isError = false;
565OH_JSVM_IsError(env, error, &isError);
566OH_JSVM_ThrowTypeError(env, nullptr, "type error1");
567```
568
569使用OH_JSVM_GetAndClearLastException后将异常信息以字符串形式打印
570
571```c++
572if (status != JSVM_OK) // 当执行失败出现异常时
573{
574    bool isPending = false;
575    if (JSVM_OK == OH_JSVM_IsExceptionPending((env), &isPending) && isPending)
576    {
577        JSVM_Value error;
578        if (JSVM_OK == OH_JSVM_GetAndClearLastException((env), &error))
579        {
580            // 获取异常堆栈
581            JSVM_Value stack;
582            OH_JSVM_GetNamedProperty((env), error, "stack", &stack);
583
584            JSVM_Value message;
585            OH_JSVM_GetNamedProperty((env), error, "message", &message);
586
587            char stackstr[256];
588            OH_JSVM_GetValueStringUtf8(env, stack, stackstr, 256, nullptr);
589            OH_LOG_INFO(LOG_APP, "JSVM error stack: %{public}s", stackstr);
590
591            char messagestr[256];
592            OH_JSVM_GetValueStringUtf8(env, message, messagestr, 256, nullptr);
593            OH_LOG_INFO(LOG_APP, "JSVM error message: %{public}s", messagestr);
594        }
595    }
596}
597```
598
599### 对象生命周期管理
600
601在调用JSVM-API接口时,底层VM堆中的对象可能会作为JSVM_Values返回句柄。这些句柄必须在Native方法退出或主动释放掉前,使其关联的对象处于“活动”状态,防止被引擎回收掉。
602
603当对象句柄被返回时,它们与一个“scope”相关联。默认作用域的生命周期与本机方法调用的生命周期相关联,这些句柄及关联的对象将在Native方法的生命周期内保持活动状态。
604
605然而,在许多情况下,句柄必须保持有效的时间范围并不与Native方法的生命周期相同。下面将介绍可用于更改句柄的生命周期的JSVM-API方法。
606
607#### 对象生命周期管理接口说明
608| 接口 | 功能说明 |
609| -------- | -------- |
610| OH_JSVM_OpenHandleScope| 打开一个新的scope,在关闭该scope之前创建的对象在scope范围内不会被GC回收 |
611| OH_JSVM_CloseHandleScope| 关闭一个scope,在此scope范围内创建的对象在关闭scope后可以被GC回收|
612| OH_JSVM_OpenEscapableHandleScope| 打开一个新的scope逃逸handle scope,在关闭该scope之前创建的对象与父作用域有相同的生命周期 |
613| OH_JSVM_CloseEscapableHandleScope| 关闭一个scope,在此scope范围外创建的对象不受父作用域保护 |
614| OH_JSVM_EscapeHandle| 将 JavaScript 对象的句柄提升到外部作用域,确保在外部作用域中可以持续地使用该对象 |
615| OH_JSVM_CreateReference| 以指定的引用计数为JavaScript对象创建一个新的引用,该引用将指向传入的对象,引用允许在不同的上下文中使用和共享对象,并且可以有效地跟踪对象的生命周期 |
616| OH_JSVM_DeleteReference| 释放由 OH_JSVM_CreateReference 创建的引用,确保对象在不再被使用时能够被正确地释放和回收,避免内存泄漏 |
617| OH_JSVM_ReferenceRef| 增加由OH_JSVM_CreateReference 创建的引用的引用计数,以确保对象在有引用时不会被提前释放 |
618| OH_JSVM_ReferenceUnref| 减少由OH_JSVM_CreateReference 创建的引用的引用计数,以确保没有任何引用指向该对象时能正确地释放和回收 |
619| OH_JSVM_GetReferenceValue| 返回由 OH_JSVM_CreateReference 创建的引用的对象 |
620
621场景示例:
622通过handlescope保护在scope范围内创建的对象在该范围内不被回收。
623
624```c++
625JSVM_HandleScope scope;
626OH_JSVM_OpenHandleScope(env, &scope);
627JSVM_Value obj = nullptr;
628OH_JSVM_CreateObject(env, &obj);
629OH_JSVM_CloseHandleScope(env, scope);
630```
631
632通过escapable handlescope保护在scope范围内创建的对象在父作用域范围内不被回收
633
634```c++
635JSVM_EscapableHandleScope scope;
636JSVM_CALL(env, OH_JSVM_OpenEscapableHandleScope(env, &scope));
637JSVM_Value output = NULL;
638JSVM_Value escapee = NULL;
639JSVM_CALL(env, OH_JSVM_CreateObject(env, &output));
640JSVM_CALL(env, OH_JSVM_EscapeHandle(env, scope, output, &escapee));
641JSVM_CALL(env, OH_JSVM_CloseEscapableHandleScope(env, scope));
642return escapee;
643```
644
645通过CreateReference创建对象引用和释放
646
647```c++
648JSVM_Value obj = nullptr;
649OH_JSVM_CreateObject(env, &obj);
650// 创建引用
651JSVM_Ref reference;
652OH_JSVM_CreateReference(env, obj, 1, &reference);
653
654// 使用引用
655JSVM_Value result;
656OH_JSVM_GetReferenceValue(env, reference, &result);
657
658// 释放引用
659OH_JSVM_DeleteReference(env, reference);
660```
661
662### 创建JS对象类型和基本类型
663
664#### 场景介绍
665
666创建JS对象类型和基本类型
667
668#### 接口说明
669| 接口 | 功能说明 |
670| -------- | -------- |
671|OH_JSVM_CreateArray | 创建一个新的 JavaScript 数组对象 |
672|OH_JSVM_CreateArrayWithLength | 创建一个指定长度的 JavaScript 数组对象 |
673|OH_JSVM_CreateArraybuffer | 创建一个指定大小的 ArrayBuffer 对象 |
674|OH_JSVM_CreateDate | 创建了一个表示给定毫秒数的 Date 对象 |
675|OH_JSVM_CreateExternal | 创建一个包装了外部指针的 JavaScript 对象 |
676|OH_JSVM_CreateExternalArraybuffer | 创建一个包装了外部 Arraybuffer 的 JavaScript 对象 |
677|OH_JSVM_CreateObject | 创建一个默认的JavaScript Object对象 |
678|OH_JSVM_CreateSymbol | 根据给定的描述符创建一个 Symbol 对象 |
679|OH_JSVM_SymbolFor | 在全局注册表中搜索具有给定描述的现有Symbol,如果该Symbol已经存在,它将被返回,否则将在注册表中创建一个新Symbol |
680|OH_JSVM_CreateTypedarray | 在现有的 ArrayBuffer 上创建一个 JavaScript TypedArray 对象,TypedArray 对象在底层数据缓冲区上提供类似数组的视图,其中每个元素都具有相同的底层二进制标量数据类型 |
681|OH_JSVM_CreateDataview | 在现有的 ArrayBuffer 上创建一个 JavaScript DataView 对象,DataView 对象在底层数据缓冲区上提供类似数组的视图 |
682|OH_JSVM_CreateInt32 | 根据 Int32_t 类型对象创建 JavaScript number 对象 |
683|OH_JSVM_CreateUint32 | 根据 Uint32_t 类型对象创建 JavaScript number 对象 |
684|OH_JSVM_CreateInt64 | 根据 Int64_t 类型对象创建 JavaScript number 对象 |
685|OH_JSVM_CreateDouble | 根据 Double 类型对象创建 JavaScript number 对象 |
686|OH_JSVM_CreateBigintInt64 | 根据 Int64 类型对象创建 JavaScript Bigint 对象 |
687|OH_JSVM_CreateBigintUint64 | 根据 Uint64 类型对象创建 JavaScript Bigint 对象 |
688|OH_JSVM_CreateBigintWords | 根据给定的 Uint64_t 数组创建一个 JavaScript BigInt 对象 |
689|OH_JSVM_CreateStringLatin1 | 根据 Latin-1 编码的字符串创建一个 JavaScript string 对象 |
690|OH_JSVM_CreateStringUtf16 | 根据 Utf16 编码的字符串创建一个 JavaScript string 对象 |
691|OH_JSVM_CreateStringUtf8 | 根据 Utf8 编码的字符串创建一个 JavaScript string 对象 |
692
693场景示例:
694创建指定长度的数组
695
696```c++
697size_t arrayLength = 2;
698JSVM_Value arr;
699
700OH_JSVM_CreateArrayWithLength(env, arrayLength, &arr);
701for (uint32_t i = 0; i < arrayLength; i++)
702{
703    JSVM_Value element;
704    OH_JSVM_CreateUint32(env, i * 2, &element);
705    OH_JSVM_SetElement(env, arr, i, element);
706}
707```
708
709创建typedarray,以Int32Array为例:
710
711```c++
712JSVM_Value arrayBuffer = nullptr;
713void *arrayBufferPtr = nullptr;
714size_t arrayBufferSize = 16;
715size_t typedArrayLength = 4;
716OH_JSVM_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer);
717
718void *tmpArrayBufferPtr = nullptr;
719size_t arrayBufferLength = 0;
720OH_JSVM_GetArraybufferInfo(env, arrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength);
721
722JSVM_Value result;
723OH_JSVM_CreateTypedarray(env, JSVM_TypedarrayType::JSVM_INT32_ARRAY, typedArrayLength, arrayBuffer, 0, &result);
724return result;
725```
726
727创建number和string:
728
729```c++
730const char *testStringStr = "test";
731JSVM_Value testString = nullptr;
732OH_JSVM_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString);
733
734JSVM_Value testNumber1 = nullptr;
735JSVM_Value testNumber2 = nullptr;
736OH_JSVM_CreateDouble(env, 10.1, &testNumber1);
737OH_JSVM_CreateInt32(env, 10, &testNumber2);
738```
739
740### 从JS类型获取C类型&获取JS类型信息
741
742#### 场景介绍
743
744从JS类型获取C类型&获取JS类型信息。
745
746#### 接口说明
747| 接口 | 功能说明 |
748| -------- | -------- |
749|OH_JSVM_GetArrayLength | 返回 Array 对象的长度 |
750|OH_JSVM_GetArraybufferInfo | 检索 ArrayBuffer 的底层数据缓冲区及其长度 |
751|OH_JSVM_GetPrototype | 获取给定 JavaScript 对象的原型 |
752|OH_JSVM_GetTypedarrayInfo | 获取 TypedArray(类型化数组)对象的信息 |
753|OH_JSVM_GetDataviewInfo | 获取 Dataview 对象的信息 |
754|OH_JSVM_GetDateValue | 获取给定 JavaScript Date 的时间值的 Double 基础类型值 |
755|OH_JSVM_GetValueBool | 获取给定 JavaScript Boolean 的 C 布尔基础类型值 |
756|OH_JSVM_GetValueDouble | 获取给定 JavaScript number 的 Double 基础类型值 |
757|OH_JSVM_GetValueBigintInt64 | 获取给定 JavaScript BigInt 的 Int64_t 基础类型值 |
758|OH_JSVM_GetValueBigintUint64 | 获取给定 JavaScript BigInt 的 Uint64_t 基础类型值 |
759|OH_JSVM_GetValueBigintWords | 获取给定 JavaScript BigInt 对象的底层数据,即 BigInt 数据的字词表示 |
760|OH_JSVM_GetValueExternal | 获取先前传递给 OH_JSVM_CreateExternal 的外部数据指针 |
761|OH_JSVM_GetValueInt32 | 获取给定 JavaScript number 的 Int32 基础类型值 |
762|OH_JSVM_GetValueInt64 | 获取给定 JavaScript number 的 Int64 基础类型值 |
763|OH_JSVM_GetValueStringLatin1 | 获取给定 JavaScript string 对象的 Latin1 编码字符串 |
764|OH_JSVM_GetValueStringUtf8 | 获取给定 JavaScript string 对象的 Utf8 编码字符串 |
765|OH_JSVM_GetValueStringUtf16 | 获取给定 JavaScript string 对象的 Utf16 编码字符串 |
766|OH_JSVM_GetValueUint32 | 获取给定 JavaScript number 的 Uint32 基础类型值 |
767|OH_JSVM_GetBoolean | 返回用于表示给定布尔值的 JavaScript 单例对象 |
768|OH_JSVM_GetGlobal | 返回当前环境中的全局 global 对象 |
769|OH_JSVM_GetNull | 返回 JavaScript null 对象 |
770|OH_JSVM_GetUndefined | 返回 JavaScript Undefined 对象 |
771
772场景示例:
773创建64位的BigInt,并获取64位int值。
774
775```c++
776int64_t testValue = INT64_MAX;
777JSVM_Value result = nullptr;
778OH_JSVM_CreateBigintInt64(env, testValue, &result);
779int64_t resultValue = 0;
780bool flag = false;
781OH_JSVM_GetValueBigintInt64(env, result, &resultValue, &flag);
782```
783
784创建一个Int32Array,并获取其长度,byteoffset等信息。
785
786```c++
787JSVM_Value arrayBuffer = nullptr;
788void *arrayBufferPtr = nullptr;
789size_t arrayBufferSize = 16;
790size_t typedArrayLength = 4;
791OH_JSVM_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer);
792
793bool isArrayBuffer = false;
794OH_JSVM_IsArraybuffer(env, arrayBuffer, &isArrayBuffer);
795
796JSVM_Value result;
797OH_JSVM_CreateTypedarray(env, JSVM_TypedarrayType::JSVM_INT32_ARRAY, typedArrayLength, arrayBuffer, 0, &result);
798
799bool isTypedArray = false;
800OH_JSVM_IsTypedarray(env, result, &isTypedArray);
801
802
803JSVM_TypedarrayType type;
804size_t length = 0;
805void *data = nullptr;
806JSVM_Value retArrayBuffer;
807size_t byteOffset = -1;
808OH_JSVM_GetTypedarrayInfo(env, result, &type, &length, &data, &retArrayBuffer, &byteOffset);
809
810
811bool retIsArrayBuffer = false;
812OH_JSVM_IsArraybuffer(env, retArrayBuffer, &retIsArrayBuffer);
813void *tmpArrayBufferPtr = nullptr;
814size_t arrayBufferLength = 0;
815OH_JSVM_GetArraybufferInfo(env, retArrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength);
816```
817
818创建utf8类型的String,并获取C字符串。
819
820```c++
821const char *testStringStr = "testString";
822JSVM_Value testString = nullptr;
823OH_JSVM_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString);
824
825char buffer[128];
826size_t bufferSize = 128;
827size_t copied;
828
829OH_JSVM_GetValueStringUtf8(env, testString, buffer, bufferSize, &copied);
830```
831
832### JS值操作和抽象操作
833
834#### 场景介绍
835
836JS值操作和抽象操作。
837
838#### 接口说明
839| 接口 | 功能说明 |
840| -------- | -------- |
841|OH_JSVM_CoerceToBool | 将目标值转换为 Boolean 类型对象|
842|OH_JSVM_CoerceToNumber | 将目标值转换为 Number 类型对象 |
843|OH_JSVM_CoerceToObject | 将目标值转换为 Object 类型对象 |
844|OH_JSVM_CoerceToString | 将目标值转换为 String 类型对象 |
845|OH_JSVM_Typeof | 返回 JavaScript 对象的类型 |
846|OH_JSVM_Instanceof | 判断一个对象是否是某个构造函数的实例 |
847|OH_JSVM_IsArray | 判断一个 JavaScript 对象是否为 Array 类型对象|
848|OH_JSVM_IsArraybuffer | 判断一个 JavaScript 对象是否为 Arraybuffer 类型对象 |
849|OH_JSVM_IsDate | 判断一个 JavaScript 对象是否为 Date 类型对象 |
850|OH_JSVM_IsTypedarray | 判断一个 JavaScript 对象是否为 Typedarray 类型对象 |
851|OH_JSVM_IsDataview | 判断一个 JavaScript 对象是否为 Dataview 类型对象 |
852|OH_JSVM_StrictEquals | 判断两个 JSVM_Value 对象是否相等 |
853|OH_JSVM_DetachArraybuffer | 调用 ArrayBuffer 对象的Detach操作 |
854|OH_JSVM_IsDetachedArraybuffer | 检查给定的 ArrayBuffer 是否已被分离(detached) |
855
856场景示例:
857判断JS值是否为数组类型
858
859```c++
860JSVM_Value array = nullptr;
861OH_JSVM_CreateArray(env, &array);
862bool isArray = false;
863OH_JSVM_IsArray(env, array, &isArray);
864```
865
866将int32类型转换为string类型
867
868```c++
869int32_t num = 123;
870JSVM_Value intValue;
871OH_JSVM_CreateInt32(env, num, &intValue);
872JSVM_Value stringValue;
873OH_JSVM_CoerceToString(env, intValue, &stringValue);
874
875char buffer[128];
876size_t bufferSize = 128;
877size_t copied = 0;
878
879OH_JSVM_GetValueStringUtf8(env, stringValue, buffer, bufferSize, &copied);
880// buffer:"123";
881```
882
883判断两个JS值类型是否相同
884
885```c++
886JSVM_Value value = nullptr;
887JSVM_Value value1 = nullptr;
888OH_JSVM_CreateArray(env, &value);
889
890OH_JSVM_CreateInt32(env, 10, &value1);
891bool isArray = true;
892OH_JSVM_StrictEquals(env, value, value, &isArray);
893```
894
895### JS属性操作
896
897#### 场景介绍
898
899JS对象属性的增删获取和判断
900
901#### 接口说明
902| 接口 | 功能说明 |
903| -------- | -------- |
904|OH_JSVM_GetPropertyNames | 获取给定对象的所有可枚举属性名称, 结果变量将存储一个包含所有可枚举属性名称的JavaScript数组 |
905|OH_JSVM_GetAllPropertyNames | 获取给定对象的所有可用属性名称, 结果变量将存储一个包含所有可枚举属性名称的JavaScript数组 |
906|OH_JSVM_SetProperty | 为给定对象设置一个属性 |
907|OH_JSVM_GetProperty | 用给定的属性的名称,检索目标对象的属性 |
908|OH_JSVM_HasProperty | 用给定的属性的名称,查询目标对象是否有此属性 |
909|OH_JSVM_DeleteProperty | 用给定的属性的名称,删除目标对象属性 |
910|OH_JSVM_HasOwnProperty | 检查目标对象是否具有指定的自有属性 |
911|OH_JSVM_SetNamedProperty | 用给定的属性的名称为目标对象设置属性,此方法等效于使用从作为 utf8Name 传入的字符串创建的 JSVM_Value 调用 OH_JSVM_SetNamedProperty |
912|OH_JSVM_GetNamedProperty | 用给定的属性的名称,检索目标对象的属性,此方法等效于使用从作为 utf8Name 传入的字符串创建的 JSVM_Value 调用 OH_JSVM_GetNamedProperty |
913|OH_JSVM_HasNamedProperty | 用给定的属性的名称,查询目标对象是否有此属性,此方法等效于使用从作为 utf8Name 传入的字符串创建的 JSVM_Value 调用 OH_JSVM_HasNamedProperty |
914|OH_JSVM_SetElement | 在给定对象的指定索引处设置元素 |
915|OH_JSVM_GetElement | 获取给定对象指定索引处的元素 |
916|OH_JSVM_HasElement | 若给定对象的指定索引处拥有属性,获取该元素 |
917|OH_JSVM_DeleteElement | 尝试删除给定对象的指定索引处的元素 |
918|OH_JSVM_DefineProperties |  批量的向给定对象中定义属性 |
919|OH_JSVM_ObjectFreeze | 冻结给定的对象,防止向其添加新属性,删除现有属性,防止更改现有属性的可枚举性、可配置性或可写性,并防止更改现有属性的值 |
920|OH_JSVM_ObjectSeal | 密封给定的对象。这可以防止向其添加新属性,以及将所有现有属性标记为不可配置 |
921
922场景示例:
923JS对象属性的增删获取和判断
924
925```c++
926// 创建一个空对象
927JSVM_Value myObject = nullptr;
928OH_JSVM_CreateObject(env, &myObject);
929
930// 设置属性
931const char *testNameStr = "John Doe";
932JSVM_Value propValue = nullptr;
933JSVM_Value key;
934OH_JSVM_CreateStringUtf8(env, "name", JSVM_AUTO_LENGTH, &key);
935OH_JSVM_CreateStringUtf8(env, testNameStr, strlen(testNameStr), &propValue);
936OH_JSVM_SetProperty(env, myObject, key, propValue);
937
938// 获取属性
939JSVM_Value propResult = nullptr;
940OH_JSVM_GetProperty(env, myObject, key, &propResult);
941
942// 检查属性是否存在
943bool hasProperty = false;
944OH_JSVM_HasNamedProperty(env, myObject, "name", &hasProperty);
945    // 属性存在,做相应处理...
946    if (hasProperty)
947    {
948        // 获取对象的所有属性名
949        JSVM_Value propNames = nullptr;
950        OH_JSVM_GetPropertyNames(env, myObject, &propNames);
951
952        bool isArray = false;
953        OH_JSVM_IsArray(env, propNames, &isArray);
954
955        uint32_t arrayLength = 0;
956        OH_JSVM_GetArrayLength(env, propNames, &arrayLength);
957        // 遍历属性元素
958        for (uint32_t i = 0; i < arrayLength; i++)
959        {
960            bool hasElement = false;
961            OH_JSVM_HasElement(env, propNames, i, &hasElement);
962
963            JSVM_Value propName = nullptr;
964            OH_JSVM_GetElement(env, propNames, i, &propName);
965
966            bool hasProp = false;
967            OH_JSVM_HasProperty(env, myObject, propName, &hasProp);
968
969            JSVM_Value propValue = nullptr;
970            OH_JSVM_GetProperty(env, myObject, propName, &propValue);
971        }
972    }
973
974// 删除属性
975OH_JSVM_DeleteProperty(env, myObject, key, &hasProperty);
976```
977
978### JS函数操作
979
980#### 场景介绍
981
982JS函数操作。
983
984#### 接口说明
985| 接口 | 功能说明 |
986| -------- | -------- |
987|OH_JSVM_CallFunction | 在C/C++侧调用JS方法 |
988|OH_JSVM_CreateFunction | 用于创建JavaScript函数,用于从JavaScript环境中调用C/C++代码中的函数 |
989|OH_JSVM_GetCbInfo | 从给定的callback info中获取有关调用的详细信息,如参数和this指针 |
990|OH_JSVM_GetNewTarget | 获取构造函数调用的new.target |
991|OH_JSVM_NewInstance | 通过给定的构造函数,构建一个实例 |
992
993场景示例:
994创建JavaScript函数操作
995
996```c++
997JSVM_Value SayHello(JSVM_Env env, JSVM_CallbackInfo info)
998{
999    printf("Hello\n");
1000    JSVM_Value ret;
1001    OH_JSVM_CreateInt32(env, 2, &ret);
1002    return ret;
1003}
1004
1005static JSVM_Value JsvmCreateFunction(JSVM_Env env, JSVM_CallbackInfo info)
1006{
1007    JSVM_CallbackStruct param;
1008    param.data = nullptr;
1009    param.callback = SayHello;
1010
1011    JSVM_Value funcValue = nullptr;
1012    JSVM_Status status = OH_JSVM_CreateFunction(env, "func", JSVM_AUTO_LENGTH, &param, &funcValue);
1013    return funcValue;
1014}
1015```
1016
1017在C/C++侧获取并调用JS方法
1018
1019```c++
1020static JSVM_Value CallFunction(JSVM_Env env, JSVM_CallbackInfo info)
1021{
1022    size_t argc = 1;
1023    JSVM_Value args[1];
1024    JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL));
1025
1026    JSVM_ASSERT(env, argc >= 1, "Wrong number of arguments");
1027
1028    JSVM_ValueType valuetype;
1029    JSVM_CALL(env, OH_JSVM_Typeof(env, args[0], &valuetype));
1030    JSVM_ASSERT(env, valuetype == JSVM_ValueType::JSVM_FUNCTION, "Wrong type of argment. Expects a string.");
1031
1032    JSVM_Value global;
1033    JSVM_CALL(env, OH_JSVM_GetGlobal(env, &global));
1034
1035    JSVM_Value ret;
1036    JSVM_CALL(env, OH_JSVM_CallFunction(env, global, args[0], 0, nullptr, &ret));
1037    return ret;
1038}
1039```
1040
1041### 对象绑定操作
1042
1043#### 场景介绍
1044
1045对象绑定操作。
1046
1047#### 接口说明
1048| 接口 | 功能说明 |
1049| -------- | -------- |
1050|OH_JSVM_DefineClass| 用于在JavaScript中定义一个类,并与对应的C类进行封装和交互。它提供了创建类的构造函数、定义属性和方法的能力,以及在C和JavaScript之间进行数据交互的支持 |
1051|OH_JSVM_Wrap| 在 JavaScript 对象中封装原生实例。稍后可以使用 OH_JSVM_Unwrap() 检索原生实例 |
1052|OH_JSVM_Unwrap | 使用 OH_JSVM_Wrap() 检索先前封装在 JavaScript 对象中的原生实例 |
1053|OH_JSVM_RemoveWrap | 检索先前封装在 JavaScript 对象中的原生实例并移除封装 |
1054|OH_JSVM_TypeTagObject | 将 type_tag 指针的值与 JavaScript 对象或外部对象相关联 |
1055|OH_JSVM_CheckObjectTypeTag | 检查给定的类型标签是否与对象上的类型标签匹配 |
1056|OH_JSVM_AddFinalizer | 为对象添加 JSVM_Finalize 回调,以便在 JavaScript 对象被垃圾回收时调用来释放原生对象 |
1057|OH_JSVM_PostFinalizer | 安排在事件循环中异步调用 JSVM_Finalize 回调 |
1058
1059场景示例:
1060对象绑定操作。
1061
1062```c++
1063static JSVM_Value AssertEqual(JSVM_Env env, JSVM_CallbackInfo info)
1064{
1065    size_t argc = 2;
1066    JSVM_Value args[2];
1067    JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL));
1068
1069    bool isStrictEquals = false;
1070    OH_JSVM_StrictEquals(env, args[0], args[1], &isStrictEquals);
1071    return nullptr;
1072}
1073
1074static napi_value TestWrap(napi_env env1, napi_callback_info info)
1075{
1076    OH_LOG_ERROR(LOG_APP, "testWrap start");
1077    JSVM_InitOptions init_options;
1078    memset(&init_options, 0, sizeof(init_options));
1079    init_options.externalReferences = externals;
1080    if (aa == 0) {
1081        OH_JSVM_Init(&init_options);
1082        aa++;
1083    }
1084    JSVM_VM vm;
1085    JSVM_CreateVMOptions options;
1086    memset(&options, 0, sizeof(options));
1087    OH_JSVM_CreateVM(&options, &vm);
1088    JSVM_VMScope vm_scope;
1089    OH_JSVM_OpenVMScope(vm, &vm_scope);
1090    JSVM_Env env;
1091    JSVM_CallbackStruct param[1];
1092    param[0].data = nullptr;
1093    param[0].callback = AssertEqual;
1094    JSVM_PropertyDescriptor descriptor[] = {
1095        {"assertEqual", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
1096    };
1097    OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env);
1098    JSVM_EnvScope envScope;
1099    OH_JSVM_OpenEnvScope(env, &envScope);
1100    JSVM_HandleScope handlescope;
1101    OH_JSVM_OpenHandleScope(env, &handlescope);
1102    JSVM_Value testClass = nullptr;
1103    JSVM_CallbackStruct param1;
1104    param1.data = nullptr;
1105    param1.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value {
1106        JSVM_Value thisVar = nullptr;
1107        OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr);
1108
1109        return thisVar;
1110    };
1111    OH_JSVM_DefineClass(env, "TestClass", JSVM_AUTO_LENGTH, &param1, 0, nullptr, &testClass);
1112
1113    JSVM_Value instanceValue = nullptr;
1114    OH_JSVM_NewInstance(env, testClass, 0, nullptr, &instanceValue);
1115
1116    const char *testStr = "test";
1117    OH_JSVM_Wrap(
1118        env, instanceValue, (void *)testStr, [](JSVM_Env env, void *data, void *hint) {}, nullptr, nullptr);
1119    const char *tmpTestStr = nullptr;
1120    OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr);
1121    const char *tmpTestStr1 = nullptr;
1122    OH_JSVM_RemoveWrap(env, instanceValue, (void **)&tmpTestStr1);
1123    OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr1);
1124    OH_JSVM_CloseHandleScope(env, handlescope);
1125    OH_JSVM_CloseEnvScope(env, envScope);
1126    OH_JSVM_DestroyEnv(env);
1127    OH_JSVM_CloseVMScope(vm, vm_scope);
1128    OH_JSVM_DestroyVM(vm);
1129    OH_LOG_ERROR(LOG_APP, "testWrap pass");
1130    return nullptr;
1131}
1132```
1133
1134### 版本管理
1135
1136#### 场景介绍
1137
1138获取当前版本信息。
1139
1140#### 接口说明
1141| 接口 | 功能说明 |
1142| -------- | -------- |
1143|OH_JSVM_GetVersion| 返回JSVM运行时支持的最高JSVM API版本 |
1144|OH_JSVM_GetVMInfo| 返回虚拟机的信息 |
1145
1146场景示例:
1147获取当前版本信息。
1148
1149```c++
1150JSVM_VMInfo result;
1151OH_JSVM_GetVMInfo(&result);
1152uint32_t versionId = 0;
1153OH_JSVM_GetVersion(env, &versionId);
1154```
1155
1156### 内存管理
1157
1158#### 场景介绍
1159
1160内存管理
1161
1162#### 接口说明
1163| 接口 | 功能说明 |
1164| -------- | -------- |
1165|OH_JSVM_AdjustExternalMemory| 通知虚拟机系统内存不足并有选择地触发垃圾回收 |
1166|OH_JSVM_MemoryPressureNotification| 创建一个延迟对象和一个JavaScript promise |
1167
1168场景示例:
1169内存管理。
1170
1171```c++
1172int64_t change = 1024 * 1024; // 分配1MB的内存
1173int64_t result;
1174OH_JSVM_AdjustExternalMemory(env, change, &result);
1175```
1176
1177### Promise操作
1178
1179#### 场景介绍
1180
1181Promise相关操作。
1182
1183#### 接口说明
1184| 接口 | 功能说明 |
1185| -------- | -------- |
1186|OH_JSVM_CreatePromise| 创建一个延迟对象和一个JavaScript promise |
1187|OH_JSVM_ResolveDeferred| 通过与之关联的延迟对象来解析JavaScript promise |
1188|OH_JSVM_RejectDeferred| 通过与之关联的延迟对象来拒绝JavaScript Promise |
1189|OH_JSVM_IsPromise| 查询Promise是否为原生Promise对象 |
1190
1191场景示例:
1192Promise相关操作。
1193
1194```c++
1195JSVM_Deferred deferred;
1196JSVM_Value promise;
1197OH_JSVM_CreatePromise(env, &deferred, &promise);
1198
1199// 模拟异步操作
1200int result = 42;
1201bool success = true;
1202if (success)
1203{
1204    // 解析Promise,并传递结果
1205    JSVM_Value value;
1206    OH_JSVM_CreateInt32(env, result, &value);
1207    OH_JSVM_ResolveDeferred(env, deferred, value);
1208} else {
1209    // 拒绝Promise,并传递错误信息
1210    JSVM_Value code = nullptr;
1211    JSVM_Value message = nullptr;
1212    OH_JSVM_CreateStringUtf8(env, "600", JSVM_AUTO_LENGTH, &code);
1213    OH_JSVM_CreateStringUtf8(env, "Async operation failed", JSVM_AUTO_LENGTH, &message);
1214    JSVM_Value error = nullptr;
1215    OH_JSVM_CreateError(env, code, message, &error);
1216    OH_JSVM_RejectDeferred(env, deferred, error);
1217}
1218```
1219
1220### JSON操作
1221
1222#### 场景介绍
1223
1224JSON操作。
1225
1226#### 接口说明
1227
1228| 接口 | 功能说明 |
1229| -------- | -------- |
1230|OH_JSVM_JsonParse| 解析JSON字符串,并返回成功解析的值 |
1231|OH_JSVM_JsonStringify| 将对象字符串化,并返回成功转换后的字符串 |
1232
1233场景示例:
1234解析JSON操作。
1235
1236```c++
1237std::string sourcecodestr = "{\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}" ;
1238JSVM_Value jsonString;
1239OH_JSVM_CreateStringUtf8(env, sourcecodestr.c_str(), sourcecodestr.size(), &jsonString)
1240JSVM_Value result;
1241OH_JSVM_JsonParse(env, jsonString, &result);
1242```
1243
1244### 创建虚拟机的启动快照
1245
1246#### 场景介绍
1247
1248创建虚拟机的启动快照
1249
1250#### 接口说明
1251| 接口 | 功能说明 |
1252| -------- | -------- |
1253|OH_JSVM_CreateSnapshot| 用于创建虚拟机的启动快照 |
1254
1255场景示例:
1256创建虚拟机的启动快照。
1257
1258```c++
1259JSVM_VM vm;
1260JSVM_CreateVMOptions options;
1261memset(&options, 0, sizeof(options));
1262OH_JSVM_CreateVM(&options, &vm);
1263JSVM_Env env;
1264JSVM_CallbackStruct param[1];
1265param[0].data = nullptr;
1266param[0].callback = AssertEqual;
1267JSVM_PropertyDescriptor descriptor[] = {
1268    {"test", nullptr, &param[0], nullptr, nullptr, nullptr, JSVM_DEFAULT},
1269};
1270OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env);
1271const char *blobData = nullptr;
1272size_t blobSize = 0;
1273JSVM_Env envs[1] = {env};
1274OH_JSVM_CreateSnapshot(vm, 1, envs, &blobData, &blobSize);
1275```