• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# JSVM-API 支持的数据类型和接口
2<!--Kit: NDK Development-->
3<!--Subsystem: arkcompiler-->
4<!--Owner: @yuanxiaogou; @string_sz-->
5<!--Designer: @knightaoko-->
6<!--Tester: @test_lzz-->
7<!--Adviser: @fang-jinxu-->
8
9## JSVM-API 的数据类型
10
11### `JSVM_Status`
12
13    这是一个枚举数据类型,用来表示 JSVM-API 接口返回的状态信息。
14
15    每调用一次 JSVM-API 函数,都会返回一个值,用来表示操作成功与否的相关信息。
16
17```c++
18    typedef enum {
19        JSVM_OK,                              /* 成功状态 */
20        JSVM_INVALID_ARG,                     /* 无效的状态 */
21        JSVM_OBJECT_EXPECTED,                 /* 期待传入对象类型 */
22        JSVM_STRING_EXPECTED,                 /* 期待传入字符串类型 */
23        JSVM_NAME_EXPECTED,                   /* 期待传入名字 */
24        JSVM_FUNCTION_EXPECTED,               /* 期待传入函数类型 */
25        JSVM_NUMBER_EXPECTED,                 /* 期待传入数字类型 */
26        JSVM_BOOL_EXPECTED,                   /* 期待传入布尔类型 */
27        JSVM_ARRAY_EXPECTED,                  /* 期待传入数组类型 */
28        JSVM_GENERIC_FAILURE,                 /* 泛型失败状态 */
29        JSVM_PENDING_EXCEPTION,               /* 挂起异常状态 */
30        JSVM_CANCELLED,                       /* 取消状态 */
31        JSVM_ESCAPE_CALLED_TWICE,             /* 转义调用了2次 */
32        JSVM_HANDLE_SCOPE_MISMATCH,           /* 句柄作用域不匹配 */
33        JSVM_CALLBACK_SCOPE_MISMATCH,         /* 回调作用域不匹配 */
34        JSVM_QUEUE_FULL,                      /* 队列满 */
35        JSVM_CLOSING,                         /* 关闭中 */
36        JSVM_BIGINT_EXPECTED,                 /* 期望传入Bigint类型 */
37        JSVM_DATE_EXPECTED,                   /* 期望传入日期类型 */
38        JSVM_ARRAYBUFFER_EXPECTED,            /* 期望传入ArrayBuffer类型 */
39        JSVM_DETACHABLE_ARRAYBUFFER_EXPECTED, /* 可分离的数组缓冲区预期状态 */
40        JSVM_WOULD_DEADLOCK,                  /* 将死锁状态 */
41        JSVM_NO_EXTERNAL_BUFFERS_ALLOWED,     /* 不允许外部缓冲区 */
42        JSVM_CANNOT_RUN_JS,                   /* 不能执行JS */
43        JSVM_INVALID_TYPE,                    /* 非法类型 */
44        JSVM_JIT_MODE_EXPECTED,                /* 期望在JIT模式下执行 */
45    } JSVM_Status;
46```
47
48### JSVM_ExtendedErrorInfo
49
50一个结构体,在调用函数不成功时存储了较为详细的错误信息。
51
52```c++
53typedef struct {
54    const char* errorMessage;
55    void* engineReserved;
56    uint32_t engineErrorCode;
57    JSVM_Status errorCode;
58} JSVM_ExtendedErrorInfo;
59```
60
61### JSVM_Value
62
63在C++代码中,用于表示JavaScript值。
64
65### JSVM_Env
66
67- 表示JSVM-API执行时的上下文,作为Native函数的参数传递给JSVM-API接口。
68
69- 退出Native侧插件时,JSVM_Env将失效,该事件通过回调传递给OH_JSVM_SetInstanceData接口。
70
71- 禁止缓存JSVM_Env,并禁止在不同Worker中传递JSVM_Env。
72
73- 在不同线程间共享JSVM_Env时,要保证在线程切换时在前一个线程中关闭env scope并在新的线程中打开新的env scope,以保证threadlocal变量的线程隔离。
74
75### JSVM_ValueType
76
77JSVM_Value的类型。包含了ECMAScript语言规范中定义的类型,其中JSVM_EXTERNAL表示外部数据类型。
78
79```c++
80typedef enum {
81    JSVM_UNDEFINED,
82    JSVM_NULL,
83    JSVM_BOOLEAN,
84    JSVM_NUMBER,
85    JSVM_STRING,
86    JSVM_SYMBOL,
87    JSVM_OBJECT,
88    JSVM_FUNCTION,
89    JSVM_EXTERNAL,
90    JSVM_BIGINT,
91} JSVM_ValueType;
92```
93
94### JSVM_TypedarrayType
95
96TypedArray 的基本二进制标量数据类型。
97
98```c++
99typedef enum {
100    JSVM_INT8_ARRAY,
101    JSVM_UINT8_ARRAY,
102    JSVM_UINT8_CLAMPED_ARRAY,
103    JSVM_INT16_ARRAY,
104    JSVM_UINT16_ARRAY,
105    JSVM_INT32_ARRAY,
106    JSVM_UINT32_ARRAY,
107    JSVM_FLOAT32_ARRAY,
108    JSVM_FLOAT64_ARRAY,
109    JSVM_BIGINT64_ARRAY,
110    JSVM_BIGUINT64_ARRAY,
111} JSVM_TypedarrayType;
112```
113
114### JSVM_RegExpFlags
115
116正则表达式标志位。
117
118```c++
119typedef enum {
120    JSVM_REGEXP_NONE = 0,
121    JSVM_REGEXP_GLOBAL = 1 << 0,
122    JSVM_REGEXP_IGNORE_CASE = 1 << 1,
123    JSVM_REGEXP_MULTILINE = 1 << 2,
124    JSVM_REGEXP_STICKY = 1 << 3,
125    JSVM_REGEXP_UNICODE = 1 << 4,
126    JSVM_REGEXP_DOT_ALL = 1 << 5,
127    JSVM_REGEXP_LINEAR = 1 << 6,
128    JSVM_REGEXP_HAS_INDICES = 1 << 7,
129    JSVM_REGEXP_UNICODE_SETS = 1 << 8,
130} JSVM_RegExpFlags;
131```
132
133### 编译选项相关类型
134**JSVM_CompileOptions**
135
136配合 OH_JSVM_CompileScriptWithOptions 接口使用,是其参数中 options 数组的元素类型。
137
138其中:
139- id 代表这个编译选项的类型。
140- content 代表编译选项的内容。
141
142id 的值和 content 的类型需对应使用,具体对应关系请参见各选项类型的介绍。
143
144```c
145typedef struct {
146    /** compile option id. */
147    JSVM_CompileOptionId id;
148    /** option content. */
149    union {
150      /** ptr type. */
151      void *ptr;
152      /** int type. */
153      int num;
154      /** bool type. */
155      _Bool boolean;
156    } content;
157} JSVM_CompileOptions;
158```
159
160**JSVM_CompileOptionId**
161
162JSVM_CompileOptions 中的 id 对应类型,每个值有对应的 content 类型。JSVM_COMPILE_ENABLE_SOURCE_MAP 的类型为 bool,当 JSVM_ScriptOrigin 中的 sourceMapUrl 不为空时生效。
163
164```c
165typedef enum {
166    /** compile mode. */
167    JSVM_COMPILE_MODE,
168    /** code cache content. */
169    JSVM_COMPILE_CODE_CACHE,
170    /** script origin. */
171    JSVM_COMPILE_SCRIPT_ORIGIN,
172    /** compile profile content. */
173    JSVM_COMPILE_COMPILE_PROFILE,
174    /** switch for source map support. */
175    JSVM_COMPILE_ENABLE_SOURCE_MAP,
176} JSVM_CompileOptionId;
177```
178
179**JSVM_CompileMode**
180
181当 id 为 JSVM_COMPILE_MODE 时,content 类型的每个值代表一种编译模式。
182
183- JSVM_COMPILE_MODE_DEFAULT : 默认的编译选项。
184- JSVM_COMPILE_MODE_CONSUME_CODE_CACHE : 消耗 codecache 进行编译。
185- JSVM_COMPILE_MODE_EAGER_COMPILE : 进行全量编译,不再进行 lazy compile。
186- JSVM_COMPILE_MODE_PRODUCE_COMPILE_PROFILE/JSVM_COMPILE_MODE_CONSUME_COMPILE_PROFILE : 当前暂无效果,请等待后续更新。
187
188```c
189typedef enum {
190    /** default mode. */
191    JSVM_COMPILE_MODE_DEFAULT,
192    /** consume code cache. */
193    JSVM_COMPILE_MODE_CONSUME_CODE_CACHE,
194    /** apply eager compile. */
195    JSVM_COMPILE_MODE_EAGER_COMPILE,
196    /** preset for compile profile. */
197    JSVM_COMPILE_MODE_PRODUCE_COMPILE_PROFILE,
198    /** consume compile profile. */
199    JSVM_COMPILE_MODE_CONSUME_COMPILE_PROFILE,
200} JSVM_CompileMode;
201```
202
203
204**JSVM_CodeCache**
205
206当 id 为 JSVM_COMPILE_CODE_CACHE 时,content 的类型为:
207
208- cache : 指向 code cache 的指针。
209- length : 代表 code cache 的大小。
210
211```c
212typedef struct {
213    /** cache pointer. */
214    uint8_t *cache;
215    /** length. */
216    size_t length;
217} JSVM_CodeCache;
218```
219
220**JSVM_ScriptOrigin**
221
222当 id 为 JSVM_COMPILE_SCRIPT_ORIGIN 时,content 存放待编译脚本的源码信息。
223
224- sourceMapUrl : sourceMap 的路径,当前仅支持运行设备上的本地路径,可以为空。
225- resourceName : 待编译的 js script 的名字。
226
227```c
228typedef struct {
229    /** Sourcemap url. */
230    const char* sourceMapUrl;
231    /** Resource name. */
232    const char* resourceName;
233    /** Resource line offset. */
234    size_t resourceLineOffset;
235    /** Resource column offset. */
236    size_t resourceColumnOffset;
237} JSVM_ScriptOrigin;
238```
239
240### JSVM
241### 内存管理类型
242
243JSVM-API 包含以下内存管理类型:
244
245**JSVM_HandleScope**
246
247JSVM_HandleScope 数据类型用于管理 JavaScript 对象的生命周期。它确保在指定范围内创建的 JavaScript 对象保持活动状态,直到该范围结束。这样可以防止使用已释放的对象,提高代码的可靠性和性能。
248
249**JSVM_EscapableHandleScope**
250
251- 由 OH_JSVM_OpenEscapableHandleScope 接口创建,由 OH_JSVM_CloseEscapableHandleScope 接口关闭。
252
253- 表示一种特殊类型的句柄范围,用于将在JSVM_EscapableHandleScope范围内创建的值返回给父scope。
254
255- 用于 OH_JSVM_EscapeHandle 接口,将 JSVM_EscapableHandleScope 范围内的值提升为 JavaScript 对象,以便在外部作用域使用。
256
257**JSVM_Ref**
258
259指向JSVM_Value,允许开发者管理JavaScript值的生命周期。
260
261**JSVM_TypeTag**
262
263该结构体定义了一个包含两个无符号64位整数的类型标签,用于标识一个JSVM-API值的类型信息。
264
265```c++
266typedef struct {
267    uint64_t lower;
268    uint64_t upper;
269} JSVM_TypeTag;
270```
271
272- 存储了两个无符号64位整数的128位值,用它来标识JavaScript对象,确保它们属于某种类型。
273
274- 比OH_JSVM_Instanceof更强的类型检查,如果对象的原型被操纵,OH_JSVM_Instanceof可能会报告误报。
275
276- JSVM_TypeTag 在与 OH_JSVM_Wrap 结合使用时最有用,因为它确保从包装对象检索的指针可以安全地转换为与先前应用于JavaScript对象的类型标签相对应的Native类型。
277
278### 回调类型
279
280JSVM-API包含以下回调类型:
281
282**JSVM_CallbackStruct**
283
284用户提供的 Native callback 的回调函数指针和数据,JSVM_CallbackStruct 将通过 JSVM-API 暴露给 JavaScript。例如,可以使用 OH_JSVM_CreateFunction 接口创建绑定到 Native callback 的 JS 函数,其中 Native callback 就是通过 JSVM_CallbackStruct 结构定义。除非在对象生命周期管理中有特殊要求,一般不在此 callback 中创建 handle 或者 callback scope。
285
286```c++
287typedef struct {
288  JSVM_Value(*callback)(JSVM_Env env, JSVM_CallbackInfo info);
289  void* data;
290} JSVM_CallbackStruct;
291```
292
293**JSVM_Callback**
294
295JSVM_CallbackStruct 指针类型的别名。
296
297定义如下:
298
299```c++
300typedef JSVM_CallbackStruct* JSVM_Callback;
301```
302
303**JSVM_CallbackInfo**
304
305用户定义的 Native callback,第一个参数类型是 JSVM_Env,第二个参数类型是 JSVM_CallbackInfo。JSVM_CallbackInfo 表示从 JS 侧调用到 Native 侧时携带的调用信息,如参数列表。在实现 Native callback 时,一般使用 OH_JSVM_GetCbInfo 接口从 JSVM_CallbackInfo 中获取调用信息。
306
307**JSVM_Finalize**
308
309函数指针,用于传入OH_JSVM_SetInstanceData、OH_JSVM_CreateExternal、OH_JSVM_Wrap等接口。JSVM_Finalize在对象被回收后会被调用,可用于在JavaScript对象被垃圾回收时释放Native对象。JSVM 不保证是否执行该回调函数,也不保证执行该回调函数的时机,**开发者不应依赖于该回调的执行时机**。
310
311写法如下:
312
313```c++
314typedef void (*JSVM_Finalize)(JSVM_Env env, void* finalizeData, void* finalizeHint);
315```
316
317**JSVM_PropertyHandlerConfigurationStruct**
318
319当执行对象的getter、setter、deleter和enumerator操作时,对应的回调将会触发。
320
321```c++
322typedef struct {
323    JSVM_Value(JSVM_CDECL* genericNamedPropertyGetterCallback)(JSVM_Env env,
324                                                               JSVM_Value name,
325                                                               JSVM_Value thisArg,
326                                                               JSVM_Value namedPropertyData);
327    JSVM_Value(JSVM_CDECL* genericNamedPropertySetterCallback)(JSVM_Env env,
328                                                               JSVM_Value name,
329                                                               JSVM_Value property,
330                                                               JSVM_Value thisArg,
331                                                               JSVM_Value namedPropertyData);
332    JSVM_Value(JSVM_CDECL* genericNamedPropertyDeleterCallback)(JSVM_Env env,
333                                                                JSVM_Value name,
334                                                                JSVM_Value thisArg,
335                                                                JSVM_Value namedPropertyData);
336    JSVM_Value(JSVM_CDECL* genericNamedPropertyEnumeratorCallback)(JSVM_Env env,
337                                                                   JSVM_Value thisArg,
338                                                                   JSVM_Value namedPropertyData);
339    JSVM_Value(JSVM_CDECL* genericIndexedPropertyGetterCallback)(JSVM_Env env,
340                                                                JSVM_Value index,
341                                                                JSVM_Value thisArg,
342                                                                JSVM_Value indexedPropertyData);
343    JSVM_Value(JSVM_CDECL* genericIndexedPropertySetterCallback)(JSVM_Env env,
344                                                                 JSVM_Value index,
345                                                                 JSVM_Value property,
346                                                                 JSVM_Value thisArg,
347                                                                 JSVM_Value indexedPropertyData);
348    JSVM_Value(JSVM_CDECL* genericIndexedPropertyDeleterCallback)(JSVM_Env env,
349                                                                  JSVM_Value index,
350                                                                  JSVM_Value thisArg,
351                                                                  JSVM_Value indexedPropertyData);
352    JSVM_Value(JSVM_CDECL* genericIndexedPropertyEnumeratorCallback)(JSVM_Env env,
353                                                                     JSVM_Value thisArg,
354                                                                     JSVM_Value indexedPropertyData);
355    JSVM_Value namedPropertyData;
356    JSVM_Value indexedPropertyData;
357} JSVM_PropertyHandlerConfigurationStruct;
358```
359
360**JSVM_PropertyHandlerCfg**
361
362包含属性监听回调的结构指针。
363
364基本用法如下:
365
366```c++
367typedef JSVM_PropertyHandlerConfigurationStruct* JSVM_PropertyHandlerCfg;
368```
369
370## 支持的JSVM-API接口
371
372标准JS引擎的能力通过JSVM-API提供。JSVM-API支持动态链接到不同版本的JS引擎库,从而为开发者屏蔽掉不同引擎接口的差异。JSVM-API提供引擎生命周期管理、JS context管理、JS代码执行、JS/C++互操作、执行环境快照、codecache等能力,具体可见下文。
373
374### 使用 JSVM-API 接口创建引擎实例及 JS 执行上下文环境
375
376**场景介绍**
377
378执行JS代码需要先创建JavaScript VM,创建JS执行的上下文环境。
379
380**接口说明**
381| 接口 | 功能说明 |
382| -------- | -------- |
383| OH_JSVM_Init| 初始化JavaScript引擎实例 |
384| OH_JSVM_CreateVM| 创建JavaScript引擎实例|
385| OH_JSVM_DestroyVM| 销毁JavaScript引擎实例 |
386| OH_JSVM_OpenVMScope| 打开一个新的VM scope,引擎实例只能在scope范围内使用,可以保证引擎实例不被销毁 |
387| OH_JSVM_CloseVMScope| 关闭VM scope |
388| OH_JSVM_CreateEnv| 创建一个新的JS执行上下文环境,并注册指定的Native函数 |
389| OH_JSVM_DestroyEnv| 销毁一个JS执行上下文环境 |
390| OH_JSVM_OpenEnvScope| 打开一个新的Env scope,Env只能在scope范围内使用 |
391| OH_JSVM_CloseEnvScope| 关闭Env scope |
392| OH_JSVM_OpenHandleScope| 打开一个Handle scope,确保scope范围内的JSVM_Value不被GC回收 |
393| OH_JSVM_CloseHandleScope| 关闭Handle scope |
394
395**JSVM_InitOptions 的使用描述**
396
397JSVM 提供了多种配置选项,允许开发者在执行 `OH_JSVM_Init` 时灵活配置其行为。可以通过 `OH_JSVM_GetVMInfo` 接口获取当前 JSVM 版本所对应的 V8 引擎版本。JSVM 中可支持的选项范围与对应的 V8 引擎版本可支持的选项范围保持一致。`OH_JSVM_GetVMInfo` 接口的使用参考[使用JSVM-API接口获取JSVM API的版本号](use-jsvm-about-version.md)。
398
399**注意:** 建议开发者在没有特殊需求的情况下,仅使用 JSVM 内部的默认配置选项。
400
401场景示例:
402常规模式下初始化 VM 平台。
403```c++
404static void NormalInit(bool &vmInit) {
405    if (!vmInit) {
406        // JSVM only need init once
407        JSVM_InitOptions initOptions;
408        memset(&initOptions, 0, sizeof(initOptions));
409        JSVM_Status cond = OH_JSVM_Init(&initOptions);
410        if(cond == JSVM_OK) {
411            vmInit = true;
412        } else {
413            vmInit = false;
414        }
415    }
416}
417```
418
419场景示例:
420初始化低内存占用的 VM 平台。
421```c++
422static void LowMemoryInit(bool &vmInit) {
423    if (!vmInit) {
424        // JSVM only need init once
425        JSVM_InitOptions initOptions;
426        int argc = 4;
427        initOptions.argc = &argc;
428        const char* argv[4];
429        argv[1] = "--incremental-marking-hard-trigger=40";
430        argv[2] = "--min-semi-space-size=1";
431        argv[3] = "--max-semi-space-size=4";
432        initOptions.argv = const_cast<char**>(argv);
433        OH_JSVM_Init(&initOptions);
434        vmInit = true;
435    }
436}
437```
438
439场景示例:
440初始化低GC触发频次的 VM 平台。
441```c++
442static void LowGCFrequencyInit(bool &vmInit) {
443    if (!vmInit) {
444        // JSVM only need init once
445        JSVM_InitOptions initOptions;
446        int argc = 4;
447        initOptions.argc = &argc;
448        const char* argv[4];
449        argv[1] = "--incremental-marking-hard-trigger=80";
450        argv[2] = "--min-semi-space-size=16";
451        argv[3] = "--max-semi-space-size=16";
452        initOptions.argv = const_cast<char**>(argv);
453        OH_JSVM_Init(&initOptions);
454        vmInit = true;
455    }
456}
457```
458
459执行结果:
460使用以上三个接口可以分别初始化具备不同特性的 VM 平台。初始化之后,可以创建 VM 实例,并执行 JavaScript 脚本。
461相比 NormalInit 接口,LowGCFrequencyInit 接口初始化的VM平台 GC 触发频次更低。
462相比 NormalInit 接口,LowMemoryInit 接口初始化的VM平台内存占用更少。
463
464**创建 VM 实例**
465
466场景示例:
467创建及销毁 JavaScript 引擎实例,包含创建及销毁 JS 执行上下文环境
468```c++
469bool VM_INIT = false;
470
471static JSVM_Value ConsoleInfo(JSVM_Env env, JSVM_CallbackInfo info) {
472    size_t argc = 1;
473    JSVM_Value args[1];
474    char log[256] = "";
475    size_t logLength = 0;
476    OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL);
477
478    OH_JSVM_GetValueStringUtf8(env, args[0], log, 255, &logLength);
479    log[255] = 0;
480    OH_LOG_INFO(LOG_APP, "JSVM API TEST: %{public}s", log);
481    return nullptr;
482}
483
484static JSVM_Value Add(JSVM_Env env, JSVM_CallbackInfo info) {
485    size_t argc = 2;
486    JSVM_Value args[2];
487    OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL);
488    double num1 = 0;
489	double num2 = 0;
490    OH_JSVM_GetValueDouble(env, args[0], &num1);
491    OH_JSVM_GetValueDouble(env, args[1], &num2);
492    JSVM_Value sum = nullptr;
493    OH_JSVM_CreateDouble(env, num1 + num2, &sum);
494    return sum;
495}
496
497static napi_value MyJSVMDemo([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) {
498    std::thread t([]() {
499        // 可以根据不同的业务需求初始化具备不同能力的 VM 平台:
500        // 1. 初始化默认的 VM 平台:调用'NormalInit'接口。
501        // 2. 初始化低内存占用的 VM 平台:调用'LowMemoryInit'接口。
502        // 3. 初始化低 GC 触发频次的 VM 平台:调用'LowGCFrequencyInit'接口。
503        NormalInit(VM_INIT);
504        // create vm, and open vm scope
505        JSVM_VM vm;
506        JSVM_CreateVMOptions options;
507        memset(&options, 0, sizeof(options));
508        OH_JSVM_CreateVM(&options, &vm);
509
510        JSVM_VMScope vmScope;
511        OH_JSVM_OpenVMScope(vm, &vmScope);
512
513        JSVM_CallbackStruct param[] = {
514            {.data = nullptr, .callback = ConsoleInfo},
515            {.data = nullptr, .callback = Add},
516        };
517        JSVM_PropertyDescriptor descriptor[] = {
518            {"consoleinfo", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
519            {"add", NULL, &param[1], NULL, NULL, NULL, JSVM_DEFAULT},
520        };
521        // create env, register native method, and open env scope
522        JSVM_Env env;
523        OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env);
524
525        JSVM_EnvScope envScope;
526        OH_JSVM_OpenEnvScope(env, &envScope);
527
528        // open handle scope
529        JSVM_HandleScope handleScope;
530        OH_JSVM_OpenHandleScope(env, &handleScope);
531
532        std::string sourceCodeStr = "\
533        {\
534            let value = add(4.96, 5.28);\
535            consoleinfo('Result is:' + value);\
536        }";
537        // compile js script
538        JSVM_Value sourceCodeValue;
539        OH_JSVM_CreateStringUtf8(env, sourceCodeStr.c_str(), sourceCodeStr.size(), &sourceCodeValue);
540        JSVM_Script script;
541        OH_JSVM_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script);
542        JSVM_Value result;
543        // run js script
544        OH_JSVM_RunScript(env, script, &result);
545        JSVM_ValueType type;
546        OH_JSVM_Typeof(env, result, &type);
547        OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type);
548
549        // exit vm and clean memory
550        OH_JSVM_CloseHandleScope(env, handleScope);
551
552        OH_JSVM_CloseEnvScope(env, envScope);
553        OH_JSVM_DestroyEnv(env);
554
555        OH_JSVM_CloseVMScope(vm, vmScope);
556        OH_JSVM_DestroyVM(vm);
557    });
558
559    t.detach();
560
561    return nullptr;
562}
563```
564
565### 使用 JSVM-API 接口编译及执行 JS 代码
566
567**场景介绍**
568
569编译及执行JS代码。
570
571**接口说明**
572| 接口                              | 功能说明                                                                               |
573| ------------------------------- | ---------------------------------------------------------------------------------- |
574| OH_JSVM_CompileScript           | 编译JavaScript代码并返回绑定到当前环境的编译脚本                                                      |
575| OH_JSVM_CompileScriptWithOrigin | 编译JavaScript代码并返回绑定到当前环境的编译脚本,同时传入包括 sourceMapUrl 和源文件名在内的源代码信息,用于处理 source map 信息 |
576| OH_JSVM_CompileScriptWithOptions | 通用的编译接口,通过传入 option 数组完成前面的 compile 接口全部功能,同时支持后续选项扩展 |
577| OH_JSVM_CreateCodeCache         | 为编译脚本创建code cache                                                                  |
578| OH_JSVM_RunScript               | 执行编译脚本,如果没有 JIT 权限支持,执行含wasm的脚本会失败,在特定场景下存在性能差异,并打印一行日志提示开发者                                                                             |
579
580场景示例:
581编译及执行 JS 代码(创建 VM 实例,注册函数,执行 JS,销毁 VM 实例)
582
583cpp 部分代码
584
585```c++
586#include <cstring>
587#include <fstream>
588#include <string>
589#include <vector>
590
591// 依赖libjsvm.so
592#include "ark_runtime/jsvm.h"
593
594using namespace std;
595
596static JSVM_Value Hello(JSVM_Env env, JSVM_CallbackInfo info) {
597    JSVM_Value output;
598    void* data = nullptr;
599    OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data);
600    OH_JSVM_CreateStringUtf8(env, (char*)data, strlen((char*)data), &output);
601    return output;
602}
603
604static JSVM_CallbackStruct hello_cb = { Hello, (void*)"Hello" };
605
606static string srcGlobal = R"JS(
607const concat = (...args) => args.reduce((a, b) => a + b);
608)JS";
609
610static void RunScriptWithOption(JSVM_Env env, string& src,
611								uint8_t** dataPtr = nullptr,
612								size_t* lengthPtr = nullptr) {
613    JSVM_HandleScope handleScope;
614    OH_JSVM_OpenHandleScope(env, &handleScope);
615
616    JSVM_Value jsSrc;
617    OH_JSVM_CreateStringUtf8(env, src.c_str(), src.size(), &jsSrc);
618
619    uint8_t* data = dataPtr ? *dataPtr : nullptr;
620    auto compilMode = data ? JSVM_COMPILE_MODE_CONSUME_CODE_CACHE :  JSVM_COMPILE_MODE_DEFAULT;
621    size_t length = lengthPtr ? *lengthPtr : 0;
622    JSVM_Script script;
623    // 编译js代码
624	JSVM_ScriptOrigin origin {
625	    // 以包名 helloworld 为例, 假如存在对应的 sourcemap, source map 的的路径可以是 /data/app/el2/100/base/com.example.helloworld/files/index.js.map
626	    .sourceMapUrl = "/data/app/el2/100/base/com.example.helloworld/files/index.js.map",
627	    // 源文件名字
628	    .resourceName = "index.js",
629	    // scirpt 在源文件中的起始行列号
630	    .resourceLineOffset = 0,
631	    .resourceColumnOffset = 0,
632	};
633	JSVM_CompileOptions option[3];
634	option[0] = {
635		.id = JSVM_COMPILE_MODE,
636		.content = { .num = compilMode }
637	};
638	JSVM_CodeCache codeCache = {
639		.cache = data,
640		.length = length
641	};
642	option[1] = {
643		.id = JSVM_COMPILE_CODE_CACHE,
644		.content = { .ptr = &codeCache }
645	};
646	// JSVM_COMPILE_ENABLE_SOURCE_MAP 选项默认值为 false,若为 true 那么对应的 sourceMapUrl 必须不为空
647	option[2] = {
648		.id = JSVM_COMPILE_ENABLE_SOURCE_MAP,
649		.content = { .boolean = true }
650	};
651	OH_JSVM_CompileScriptWithOptions(env, jsSrc, 3, option, &script);
652
653    JSVM_Value result;
654    // 执行js代码
655    OH_JSVM_RunScript(env, script, &result);
656
657    char resultStr[128];
658    size_t size = 0;
659    OH_JSVM_GetValueStringUtf8(env, result, resultStr, 128, &size);
660
661    OH_JSVM_CloseHandleScope(env, handleScope);
662}
663
664static void RunScript(JSVM_Env env, string& src,
665                       bool withOrigin = false,
666                       uint8_t** dataPtr = nullptr,
667                       size_t* lengthPtr = nullptr) {
668    JSVM_HandleScope handleScope;
669    OH_JSVM_OpenHandleScope(env, &handleScope);
670
671    JSVM_Value jsSrc;
672    OH_JSVM_CreateStringUtf8(env, src.c_str(), src.size(), &jsSrc);
673
674    uint8_t* data = dataPtr ? *dataPtr : nullptr;
675    size_t length = lengthPtr ? *lengthPtr : 0;
676    bool cacheRejected = true;
677    JSVM_Script script;
678    // 编译js代码
679    if (withOrigin) {
680	    JSVM_ScriptOrigin origin {
681	        // 以包名 helloworld 为例, 假如存在对应的 sourcemap, source map 的的路径可以是 /data/app/el2/100/base/com.example.helloworld/files/index.js.map
682		    .sourceMapUrl = "/data/app/el2/100/base/com.example.helloworld/files/index.js.map",
683		    // 源文件名字
684		    .resourceName = "index.js",
685		    // scirpt 在源文件中的起始行列号
686		    .resourceLineOffset = 0,
687		    .resourceColumnOffset = 0,
688	    };
689		OH_JSVM_CompileScriptWithOrigin(env, jsSrc, data, length, true, &cacheRejected, &origin, &script);
690    } else {
691	    OH_JSVM_CompileScript(env, jsSrc, data, length, true, &cacheRejected, &script);
692    }
693    printf("Code cache is %s\n", cacheRejected ? "rejected" : "used");
694
695    JSVM_Value result;
696    // 执行js代码
697    OH_JSVM_RunScript(env, script, &result);
698
699    char resultStr[128];
700    size_t size = 0;
701    OH_JSVM_GetValueStringUtf8(env, result, resultStr, 128, &size);
702
703    OH_JSVM_CloseHandleScope(env, handleScope);
704}
705
706void RunWithOption(uint8_t** dataPtr, size_t* lengthPtr) {
707    // 创建虚拟机实例
708    JSVM_VM vm;
709    OH_JSVM_CreateVM(nullptr, &vm);
710    JSVM_VMScope vmScope;
711    OH_JSVM_OpenVMScope(vm, &vmScope);
712
713    JSVM_Env env;
714    // 将native函数注册成js可调用的方法,hello_cb中记录该native方法的指针和参数等信息
715    JSVM_PropertyDescriptor descriptors[] = {
716        { "hello", NULL, &hello_cb, NULL, NULL, NULL, JSVM_DEFAULT }
717    };
718    OH_JSVM_CreateEnv(vm, 1, descriptors, &env);
719    JSVM_EnvScope envScope;
720    OH_JSVM_OpenEnvScope(env, &envScope);
721    // 执行js源码src,src中可以包含任何js语法。也可以调用已注册的native方法。
722    auto src = srcGlobal + "concat(hello(), ', ', 'World', ' from RunWithOption!')";
723    // 其中使用新增接口,可以覆盖原有 Compile 系列接口的功能且具有拓展性
724    RunScriptWithOption(env, src, dataPtr, lengthPtr);
725
726    OH_JSVM_CloseEnvScope(env, envScope);
727    OH_JSVM_DestroyEnv(env);
728    OH_JSVM_CloseVMScope(vm, vmScope);
729    OH_JSVM_DestroyVM(vm);
730
731    bool result = true;
732    OH_LOG_INFO(LOG_APP, "RunWithOption: success: %{public}d", result);
733}
734
735void RunWithOrigin(uint8_t **dataPtr, size_t *lengthPtr) {
736    // 创建虚拟机实例
737    JSVM_VM vm;
738    JSVM_CreateVMOptions options;
739    memset(&options, 0, sizeof(options));
740    options.isForSnapshotting = true;
741    OH_JSVM_CreateVM(&options, &vm);
742    JSVM_VMScope vmScope;
743    OH_JSVM_OpenVMScope(vm, &vmScope);
744
745    // 从快照中创建env
746    JSVM_Env env;
747    // 将native函数注册成js可调用的方法,hello_cb中记录该native方法的指针和参数等信息
748    JSVM_PropertyDescriptor descriptors[] = {
749        { "hello", NULL, &hello_cb, NULL, NULL, NULL, JSVM_DEFAULT }
750    };
751    OH_JSVM_CreateEnv(vm, 1, descriptors, &env);
752    JSVM_EnvScope envScope;
753    OH_JSVM_OpenEnvScope(env, &envScope);
754    // 执行js脚本,因为快照记录的env中定义了hello(),所以无需重新定义。dataPtr中如果保存了编译后的js脚本,就能直接执行js脚本,避免从源码重复编译。
755    string src = "concat(hello(), ', ', 'World', ' from RunWithOrigin!')";
756    RunScript(env, src, true, dataPtr, lengthPtr);
757
758    OH_JSVM_CloseEnvScope(env, envScope);
759    OH_JSVM_DestroyEnv(env);
760    OH_JSVM_CloseVMScope(vm, vmScope);
761    OH_JSVM_DestroyVM(vm);
762
763    bool result = true;
764    OH_LOG_INFO(LOG_APP, "RunWithOrigin: success: %{public}d", result);
765}
766
767static JSVM_Value RunDemo(JSVM_Env env, JSVM_CallbackInfo info) {
768    size_t argc = 1;
769    JSVM_Value args[1] = {nullptr};
770    OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
771
772    char* str = "WithOrigin";
773    size_t len = strlen(str);
774    JSVM_Value result = nullptr;
775    OH_JSVM_CreateStringUtf8(env, str, len, &result);
776
777    uint8_t* data = nullptr;
778    size_t length = 0;
779    bool equal = false;
780    OH_JSVM_StrictEquals(env, args[0], result, &equal);
781    const auto run = equal ? RunWithOrigin : RunWithOption;
782    run(&data, &length);
783    delete[] data;
784
785    return nullptr;
786}
787
788// RunDemo注册回调
789static JSVM_CallbackStruct param[] = {
790    {.data = nullptr, .callback = RunDemo},
791};
792static JSVM_CallbackStruct *method = param;
793// RunDemo方法别名,供JS调用
794static JSVM_PropertyDescriptor descriptor[] = {
795    {"RunDemo", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
796};
797
798// 样例测试js
799const char *srcCallNative = R"JS(RunDemo("WithOrigin"); RunDemo("WithOption"))JS";
800```
801
802预期输出结果
803```ts
804RunWithOption: success: 1
805RunWithOrigin: success: 1
806```
807
808OH_JSVM_CreateCodeCache 接口用法可参考[使用 code cache 加速编译](use-jsvm-about-code-cache.md)。
809
810### 使用 JSVM-API WebAssembly 接口编译 wasm module
811
812**场景介绍**
813
814JSVM-API WebAssembly 接口提供了 WebAssembly 字节码编译、WebAssembly 函数优化、WebAssembly cache 序列化和反序列化的能力。
815详见[使用 JSVM-API WebAssembly 接口](use-jsvm-about-wasm.md)。
816
817**接口说明**
818
819| 接口                          | 功能说明                                                                                 |
820| --------------------------- | ------------------------------------------------------------------------------------ |
821| OH_JSVM_CompileWasmModule   | 将 wasm 字节码同步编译为 wasm module。如果提供了 cache 参数,先尝试将 cache 反序列为 wasm module,反序列化失败时再执行编译。如果没有 JIT 权限支持,则打印一行日志提示开发者。 |
822| OH_JSVM_CompileWasmFunction | 将 wasm module 中指定编号的函数编译为优化后的机器码,目前只使能了最高的优化等级,函数编号的合法性由接口调用者保证。如果没有 JIT 权限支持,则打印一行日志提示开发者。                     |
823| OH_JSVM_IsWasmModuleObject  | 判断传入的值是否是一个 wasm module。                                                             |
824| OH_JSVM_CreateWasmCache     | 将 wasm module 中的机器码序列化为 wasm cache,如果 wasm module 不包含机器码,则会序列化失败。如果没有 JIT 权限支持,则打印一行日志提示开发者。                    |
825| OH_JSVM_ReleaseCache        | 释放由 JSVM 接口生成的 cache。传入的 cacheType 和 cacheData 必须匹配,否则会产生未定义行为。                      |
826
827**场景示例**
828
829详见[使用 JSVM-API WebAssembly 接口](use-jsvm-about-wasm.md)。
830
831### 异常处理
832
833**场景介绍**
834
835获取、抛出、清理JS异常。
836
837**接口说明**
838| 接口 | 功能说明 |
839| -------- | -------- |
840| OH_JSVM_Throw| 抛出一个JS值 |
841| OH_JSVM_ThrowTypeError| 抛出一个JS TypeError |
842| OH_JSVM_ThrowRangeError| 抛出一个JS RangeError |
843| OH_JSVM_IsError| 判断JS值是否为JS异常 |
844| OH_JSVM_CreateError| 创建一个JS异常 |
845| OH_JSVM_CreateTypeError| 创建一个JS TypeError并返回 |
846| OH_JSVM_CreateRangeError| 创建一个JS RangeError并返回 |
847| OH_JSVM_ThrowError| 抛出一个JS异常 |
848| OH_JSVM_GetAndClearLastException| 清理并返回最后一个JS异常 |
849| OH_JSVM_IsExceptionPending| 判断当前是否有异常 |
850| OH_JSVM_GetLastErrorInfo| 获取最后一个异常的信息 |
851| OH_JSVM_ThrowSyntaxError| 抛出一个JS SyntaxError |
852| OH_JSVM_CreateSyntaxError| 创建一个JS SyntaxError并返回 |
853
854场景示例:
855以TypeError为例。创建、判断,并抛出JS TypeError。
856
857```c++
858JSVM_Value code = nullptr;
859JSVM_Value message = nullptr;
860OH_JSVM_CreateStringUtf8(env, "500", JSVM_AUTO_LENGTH, &code);
861OH_JSVM_CreateStringUtf8(env, "type error 500", JSVM_AUTO_LENGTH, &message);
862JSVM_Value error = nullptr;
863OH_JSVM_CreateTypeError(env, code, message, &error);
864bool isError = false;
865OH_JSVM_IsError(env, error, &isError);
866OH_JSVM_ThrowTypeError(env, nullptr, "type error1");
867```
868
869使用OH_JSVM_GetAndClearLastException后将异常信息以字符串形式打印
870
871```c++
872if (status != JSVM_OK) // 当执行失败出现异常时
873{
874    bool isPending = false;
875    if (JSVM_OK == OH_JSVM_IsExceptionPending((env), &isPending) && isPending)
876    {
877        JSVM_Value error;
878        if (JSVM_OK == OH_JSVM_GetAndClearLastException((env), &error))
879        {
880            // 获取异常堆栈
881            JSVM_Value stack;
882            OH_JSVM_GetNamedProperty((env), error, "stack", &stack);
883
884            JSVM_Value message;
885            OH_JSVM_GetNamedProperty((env), error, "message", &message);
886
887            char stackstr[256];
888            OH_JSVM_GetValueStringUtf8(env, stack, stackstr, 256, nullptr);
889            OH_LOG_INFO(LOG_APP, "JSVM error stack: %{public}s", stackstr);
890
891            char messagestr[256];
892            OH_JSVM_GetValueStringUtf8(env, message, messagestr, 256, nullptr);
893            OH_LOG_INFO(LOG_APP, "JSVM error message: %{public}s", messagestr);
894        }
895    }
896}
897```
898
899### 对象生命周期管理
900
901在调用JSVM-API接口时,底层VM堆中的对象可能会作为JSVM_Values返回句柄。这些句柄必须在Native方法销毁或主动释放掉前,使其关联的对象处于“活动”状态,防止被引擎回收掉。
902
903当对象句柄被返回时,它们与一个“scope”相关联。默认作用域的生命周期与Native方法调用的生命周期相关联,这些句柄及关联的对象将在Native方法的生命周期内保持活动状态。
904
905然而,在许多情况下,句柄必须保持有效的时间范围并不与Native方法的生命周期相同。下面将介绍可用于更改句柄的生命周期的JSVM-API方法。
906
907**对象生命周期管理接口说明**
908| 接口 | 功能说明 |
909| -------- | -------- |
910| OH_JSVM_OpenHandleScope| 打开一个新的scope,在关闭该scope之前创建的对象在scope范围内不会被GC回收 |
911| OH_JSVM_CloseHandleScope| 关闭一个scope,在此scope范围内创建的对象在关闭scope后可以被GC回收|
912| OH_JSVM_OpenEscapableHandleScope| 打开一个新的scope逃逸handle scope,在关闭该scope之前创建的对象与父作用域有相同的生命周期 |
913| OH_JSVM_CloseEscapableHandleScope| 关闭一个scope,在此scope范围外创建的对象不受父作用域保护 |
914| OH_JSVM_EscapeHandle| 将 JavaScript 对象的句柄提升到外部作用域,确保在外部作用域中可以持续地使用该对象 |
915| OH_JSVM_CreateReference| 以指定的引用计数为JavaScript对象创建一个新的引用,该引用将指向传入的对象,引用允许在不同的上下文中使用和共享对象,并且可以有效地监测对象的生命周期 |
916| OH_JSVM_DeleteReference| 释放由 OH_JSVM_CreateReference 创建的引用,确保对象在不再被使用时能够被正确地释放和回收,避免内存泄漏 |
917| OH_JSVM_ReferenceRef| 增加由OH_JSVM_CreateReference 创建的引用的引用计数,以确保对象在有引用时不会被提前释放 |
918| OH_JSVM_ReferenceUnref| 减少由OH_JSVM_CreateReference 创建的引用的引用计数,以确保没有任何引用指向该对象时能正确地释放和回收 |
919| OH_JSVM_GetReferenceValue| 返回由 OH_JSVM_CreateReference 创建的引用的对象 |
920| OH_JSVM_RetainScript | 持久化保存一个 JSVM_Script, 使其能够跨过当前 scope 使用 |
921| OH_JSVM_ReleaseScript | 释放持久化保存过的 JSVM_Script,释放之后 JSVM_Script 不再可用,应当置为空 |
922
923场景示例:
924通过handle scope保护在scope范围内创建的对象在该范围内不被回收。
925
926```c++
927JSVM_HandleScope scope;
928OH_JSVM_OpenHandleScope(env, &scope);
929JSVM_Value obj = nullptr;
930OH_JSVM_CreateObject(env, &obj);
931OH_JSVM_CloseHandleScope(env, scope);
932```
933
934通过escapable handle scope保护在scope范围内创建的对象在父作用域范围内不被回收
935
936```c++
937JSVM_EscapableHandleScope scope;
938JSVM_CALL(OH_JSVM_OpenEscapableHandleScope(env, &scope));
939JSVM_Value output = NULL;
940JSVM_Value escapee = NULL;
941JSVM_CALL(OH_JSVM_CreateObject(env, &output));
942JSVM_CALL(OH_JSVM_EscapeHandle(env, scope, output, &escapee));
943JSVM_CALL(OH_JSVM_CloseEscapableHandleScope(env, scope));
944return escapee;
945```
946
947通过CreateReference创建对象引用和释放
948
949```c++
950JSVM_Value obj = nullptr;
951OH_JSVM_CreateObject(env, &obj);
952// 创建引用
953JSVM_Ref reference;
954OH_JSVM_CreateReference(env, obj, 1, &reference);
955
956// 使用引用
957JSVM_Value result;
958OH_JSVM_GetReferenceValue(env, reference, &result);
959
960// 释放引用
961OH_JSVM_DeleteReference(env, reference);
962```
963
964通过 RetainScript 持久化保存 JSVM_Script 并使用
965
966```c++
967JSVM_HandleScope scope;
968JSVM_CALL(OH_JSVM_OpenHandleScope(env, &scope));
969JSVM_Script script;
970JSVM_Value jsSrc;
971std::string src(R"JS(
972let a = 37;
973a = a * 9;
974)JS");
975JSVM_CALL(OH_JSVM_CreateStringUtf8(env, src.c_str(), src.size(), &jsSrc));
976JSVM_CALL(OH_JSVM_CompileScriptWithOptions(env, jsSrc, 0, nullptr, &script));
977JSVM_CALL(OH_JSVM_RetainScript(env, script));
978JSVM_CALL(OH_JSVM_CloseHandleScope(env, scope));
979
980// 使用JSVM_Script
981JSVM_CALL(OH_JSVM_OpenHandleScope(env, &scope));
982JSVM_Value result;
983JSVM_CALL(OH_JSVM_RunScript(env, script, &result));
984
985// 释放JSVM_Script,并置空
986JSVM_CALL(OH_JSVM_ReleaseScript(env, script));
987script = nullptr;
988JSVM_CALL(OH_JSVM_CloseHandleScope(env, scope));
989```
990
991### 创建JS对象类型和基本类型
992
993**场景介绍**
994
995创建JS对象类型和基本类型。
996
997**接口说明**
998| 接口 | 功能说明 |
999| -------- | -------- |
1000|OH_JSVM_CreateArray | 创建一个新的 JavaScript 数组对象 |
1001|OH_JSVM_CreateArrayWithLength | 创建一个指定长度的 JavaScript 数组对象 |
1002|OH_JSVM_CreateArraybuffer | 创建一个指定大小的 ArrayBuffer 对象 |
1003|OH_JSVM_CreateDate | 创建了一个表示给定毫秒数的 Date 对象 |
1004|OH_JSVM_CreateExternal | 创建一个包装了外部指针的 JavaScript 对象 |
1005|OH_JSVM_CreateObject | 创建一个默认的JavaScript Object对象 |
1006|OH_JSVM_CreateSymbol | 根据给定的描述符创建一个 Symbol 对象 |
1007|OH_JSVM_SymbolFor | 在全局注册表中搜索具有给定描述的现有Symbol,如果该Symbol已经存在,它将被返回,否则将在注册表中创建一个新Symbol |
1008|OH_JSVM_CreateTypedarray | 在现有的 ArrayBuffer 上创建一个 JavaScript TypedArray 对象,TypedArray 对象在底层数据缓冲区上提供类似数组的视图,其中每个元素都具有相同的底层二进制标量数据类型 |
1009|OH_JSVM_CreateDataview | 在现有的 ArrayBuffer 上创建一个 JavaScript DataView 对象,DataView 对象在底层数据缓冲区上提供类似数组的视图 |
1010|OH_JSVM_CreateInt32 | 根据 Int32_t 类型对象创建 JavaScript number 对象 |
1011|OH_JSVM_CreateUint32 | 根据 Uint32_t 类型对象创建 JavaScript number 对象 |
1012|OH_JSVM_CreateInt64 | 根据 Int64_t 类型对象创建 JavaScript number 对象 |
1013|OH_JSVM_CreateDouble | 根据 Double 类型对象创建 JavaScript number 对象 |
1014|OH_JSVM_CreateBigintInt64 | 根据 Int64 类型对象创建 JavaScript Bigint 对象 |
1015|OH_JSVM_CreateBigintUint64 | 根据 Uint64 类型对象创建 JavaScript Bigint 对象 |
1016|OH_JSVM_CreateBigintWords | 根据给定的 Uint64_t 数组创建一个 JavaScript BigInt 对象 |
1017|OH_JSVM_CreateStringLatin1 | 根据 Latin-1 编码的字符串创建一个 JavaScript string 对象 |
1018|OH_JSVM_CreateStringUtf16 | 根据 Utf16 编码的字符串创建一个 JavaScript string 对象 |
1019|OH_JSVM_CreateStringUtf8 | 根据 Utf8 编码的字符串创建一个 JavaScript string 对象 |
1020|OH_JSVM_CreateMap | 创建一个新的 JavaScript Map对象 |
1021|OH_JSVM_CreateRegExp | 根据输入的字符串创建一个JavaScript 正则对象 |
1022|OH_JSVM_CreateSet | 创建一个新的 JavaScript Set对象 |
1023
1024场景示例:
1025创建指定长度的JavaScript数组。
1026
1027```c++
1028size_t arrayLength = 2;
1029JSVM_Value arr;
1030
1031OH_JSVM_CreateArrayWithLength(env, arrayLength, &arr);
1032for (uint32_t i = 0; i < arrayLength; i++)
1033{
1034    JSVM_Value element;
1035    OH_JSVM_CreateUint32(env, i * 2, &element);
1036    OH_JSVM_SetElement(env, arr, i, element);
1037}
1038```
1039
1040创建TypedArray,以Int32Array为例:
1041
1042```c++
1043JSVM_Value arrayBuffer = nullptr;
1044void *arrayBufferPtr = nullptr;
1045size_t arrayBufferSize = 16;
1046size_t typedArrayLength = 4;
1047OH_JSVM_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer);
1048
1049void *tmpArrayBufferPtr = nullptr;
1050size_t arrayBufferLength = 0;
1051OH_JSVM_GetArraybufferInfo(env, arrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength);
1052
1053JSVM_Value result;
1054OH_JSVM_CreateTypedarray(env, JSVM_TypedarrayType::JSVM_INT32_ARRAY, typedArrayLength, arrayBuffer, 0, &result);
1055return result;
1056```
1057
1058创建number和string:
1059
1060```c++
1061const char *testStringStr = "test";
1062JSVM_Value testString = nullptr;
1063OH_JSVM_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString);
1064
1065JSVM_Value testNumber1 = nullptr;
1066JSVM_Value testNumber2 = nullptr;
1067OH_JSVM_CreateDouble(env, 10.1, &testNumber1);
1068OH_JSVM_CreateInt32(env, 10, &testNumber2);
1069```
1070
1071创建Map:
1072
1073```c++
1074JSVM_Value value = nullptr;
1075OH_JSVM_CreateMap(env, &value);
1076```
1077
1078创建RegExp:
1079
1080```c++
1081JSVM_Value value = nullptr;
1082const char testStr[] = "ab+c";
1083OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &value);
1084JSVM_Value result = nullptr;
1085OH_JSVM_CreateRegExp(env, value, JSVM_RegExpFlags::JSVM_REGEXP_GLOBAL, &result);
1086```
1087
1088创建Set:
1089
1090```c++
1091JSVM_Value value = nullptr;
1092OH_JSVM_CreateSet(env, &value);
1093```
1094
1095### 从JS类型获取C类型&JS类型信息
1096
1097**场景介绍**
1098
1099从JS类型获取C类型&JS类型信息。
1100
1101**接口说明**
1102| 接口 | 功能说明 |
1103| -------- | -------- |
1104|OH_JSVM_GetArrayLength | 返回 Array 对象的长度 |
1105|OH_JSVM_GetArraybufferInfo | 检索 ArrayBuffer 的底层数据缓冲区及其长度 |
1106|OH_JSVM_GetPrototype | 获取给定 JavaScript 对象的原型 |
1107|OH_JSVM_GetTypedarrayInfo | 获取 TypedArray(类型化数组)对象的信息 |
1108|OH_JSVM_GetDataviewInfo | 获取 Dataview 对象的信息 |
1109|OH_JSVM_GetDateValue | 获取给定 JavaScript Date 的时间值的 Double 基础类型值 |
1110|OH_JSVM_GetValueBool | 获取给定 JavaScript Boolean 的 C 布尔基础类型值 |
1111|OH_JSVM_GetValueDouble | 获取给定 JavaScript number 的 Double 基础类型值 |
1112|OH_JSVM_GetValueBigintInt64 | 获取给定 JavaScript BigInt 的 Int64_t 基础类型值 |
1113|OH_JSVM_GetValueBigintUint64 | 获取给定 JavaScript BigInt 的 Uint64_t 基础类型值 |
1114|OH_JSVM_GetValueBigintWords | 获取给定 JavaScript BigInt 对象的底层数据,即 BigInt 数据的字词表示 |
1115|OH_JSVM_GetValueExternal | 获取先前传递给 OH_JSVM_CreateExternal 的外部数据指针 |
1116|OH_JSVM_GetValueInt32 | 获取给定 JavaScript number 的 Int32 基础类型值 |
1117|OH_JSVM_GetValueInt64 | 获取给定 JavaScript number 的 Int64 基础类型值 |
1118|OH_JSVM_GetValueStringLatin1 | 获取给定 JavaScript string 对象的 Latin1 编码字符串 |
1119|OH_JSVM_GetValueStringUtf8 | 获取给定 JavaScript string 对象的 Utf8 编码字符串 |
1120|OH_JSVM_GetValueStringUtf16 | 获取给定 JavaScript string 对象的 Utf16 编码字符串 |
1121|OH_JSVM_GetValueUint32 | 获取给定 JavaScript number 的 Uint32 基础类型值 |
1122|OH_JSVM_GetBoolean | 返回用于表示给定布尔值的 JavaScript 单例对象 |
1123|OH_JSVM_GetGlobal | 返回当前环境中的全局 global 对象 |
1124|OH_JSVM_GetNull | 返回 JavaScript null 对象 |
1125|OH_JSVM_GetUndefined | 返回 JavaScript Undefined 对象 |
1126
1127场景示例:
1128创建64位的 BigInt,并获取64位 Int 值。
1129
1130```c++
1131int64_t testValue = INT64_MAX;
1132JSVM_Value result = nullptr;
1133OH_JSVM_CreateBigintInt64(env, testValue, &result);
1134int64_t resultValue = 0;
1135bool flag = false;
1136OH_JSVM_GetValueBigintInt64(env, result, &resultValue, &flag);
1137```
1138
1139创建一个 Int32Array,并获取其长度、byteOffset 等信息。
1140
1141```c++
1142JSVM_Value arrayBuffer = nullptr;
1143void *arrayBufferPtr = nullptr;
1144size_t arrayBufferSize = 16;
1145size_t typedArrayLength = 4;
1146OH_JSVM_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer);
1147
1148bool isArrayBuffer = false;
1149OH_JSVM_IsArraybuffer(env, arrayBuffer, &isArrayBuffer);
1150
1151JSVM_Value result;
1152OH_JSVM_CreateTypedarray(env, JSVM_TypedarrayType::JSVM_INT32_ARRAY, typedArrayLength, arrayBuffer, 0, &result);
1153
1154bool isTypedArray = false;
1155OH_JSVM_IsTypedarray(env, result, &isTypedArray);
1156
1157
1158JSVM_TypedarrayType type;
1159size_t length = 0;
1160void *data = nullptr;
1161JSVM_Value retArrayBuffer;
1162size_t byteOffset = -1;
1163OH_JSVM_GetTypedarrayInfo(env, result, &type, &length, &data, &retArrayBuffer, &byteOffset);
1164
1165
1166bool retIsArrayBuffer = false;
1167OH_JSVM_IsArraybuffer(env, retArrayBuffer, &retIsArrayBuffer);
1168void *tmpArrayBufferPtr = nullptr;
1169size_t arrayBufferLength = 0;
1170OH_JSVM_GetArraybufferInfo(env, retArrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength);
1171```
1172
1173根据 UTF-8 编码的 C 字符串创建一个 JavaScript 字符串,以及获取给定 JavaScript 字符串的 UTF-8 编码 C 字符串。
1174
1175```c++
1176const char *testStringStr = "testString";
1177JSVM_Value testString = nullptr;
1178JSVM_CALL(OH_JSVM_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString));
1179
1180char buffer[128];
1181size_t bufferSize = 128;
1182size_t copied = 0;
1183
1184JSVM_CALL(OH_JSVM_GetValueStringUtf8(env, testString, buffer, bufferSize, &copied));
1185```
1186
1187### JS值操作和抽象操作
1188
1189**场景介绍**
1190
1191JS值操作和抽象操作。
1192
1193**接口说明**
1194| 接口 | 功能说明 |
1195| -------- | -------- |
1196|OH_JSVM_CoerceToBool | 将目标值转换为 Boolean 类型对象|
1197|OH_JSVM_CoerceToNumber | 将目标值转换为 Number 类型对象 |
1198|OH_JSVM_CoerceToObject | 将目标值转换为 Object 类型对象 |
1199|OH_JSVM_CoerceToString | 将目标值转换为 String 类型对象 |
1200|OH_JSVM_CoerceToBigInt | 将目标值转换为 BigInt 类型对象 |
1201|OH_JSVM_Typeof | 返回 JavaScript 对象的类型 |
1202|OH_JSVM_Instanceof | 判断一个对象是否是某个构造函数的实例 |
1203|OH_JSVM_IsArray | 判断一个 JavaScript 对象是否为 Array 类型对象|
1204|OH_JSVM_IsArraybuffer | 判断一个 JavaScript 对象是否为 ArrayBuffer 类型对象 |
1205|OH_JSVM_IsDate | 判断一个 JavaScript 对象是否为 Date 类型对象 |
1206|OH_JSVM_IsTypedarray | 判断一个 JavaScript 对象是否为 TypedArray 类型对象 |
1207|OH_JSVM_IsDataview | 判断一个 JavaScript 对象是否为 DataView 类型对象 |
1208|OH_JSVM_IsUndefined | 此API检查传入的值是否为Undefined。这相当于JS中的`value === undefined`。 |
1209|OH_JSVM_IsNull | 此API检查传入的值是否为Null对象。这相当于JS中的`value === null`。 |
1210|OH_JSVM_IsNullOrUndefined | 此API检查传入的值是否为Null或Undefined。这相当于JS中的`value == null`。 |
1211|OH_JSVM_IsBoolean | 此API检查传入的值是否为Boolean。这相当于JS中的`typeof value === 'boolean'`。 |
1212|OH_JSVM_IsNumber | 此API检查传入的值是否为Number。这相当于JS中的`typeof value === 'number'`。 |
1213|OH_JSVM_IsString | 此API检查传入的值是否为String。这相当于JS中的`typeof value === 'string'`。 |
1214|OH_JSVM_IsSymbol | 此API检查传入的值是否为Symbol。这相当于JS中的`typeof value === 'symbol'`。 |
1215|OH_JSVM_IsFunction | 此API检查传入的值是否为Function。这相当于JS中的`typeof value === 'function'`。 |
1216|OH_JSVM_IsObject | 此API检查传入的值是否为Object。 |
1217|OH_JSVM_IsBigInt | 此API检查传入的值是否为BigInt。这相当于JS中的`typeof value === 'bigint'`。 |
1218|OH_JSVM_IsConstructor | 此API检查传入的值是否为构造函数。 |
1219|OH_JSVM_IsMap | 此API检查传入的值是否为Map。 |
1220|OH_JSVM_IsSet | 此API检查传入的值是否为Set。 |
1221|OH_JSVM_IsRegExp | 此API检查传入的值是否为RegExp。 |
1222|OH_JSVM_StrictEquals | 判断两个 JSVM_Value 对象是否严格相等 |
1223|OH_JSVM_Equals | 判断两个 JSVM_Value 对象是否宽松相等 |
1224|OH_JSVM_DetachArraybuffer | 调用 ArrayBuffer 对象的Detach操作 |
1225|OH_JSVM_IsDetachedArraybuffer | 检查给定的 ArrayBuffer 是否已被分离(detached) |
1226
1227场景示例:
1228判断JS值是否为Array类型
1229
1230```c++
1231JSVM_Value array = nullptr;
1232OH_JSVM_CreateArray(env, &array);
1233bool isArray = false;
1234OH_JSVM_IsArray(env, array, &isArray);
1235```
1236
1237将int32类型的目标值转换为string类型
1238
1239```c++
1240int32_t num = 123;
1241JSVM_Value intValue;
1242OH_JSVM_CreateInt32(env, num, &intValue);
1243JSVM_Value stringValue;
1244OH_JSVM_CoerceToString(env, intValue, &stringValue);
1245
1246char buffer[128];
1247size_t bufferSize = 128;
1248size_t copied = 0;
1249
1250OH_JSVM_GetValueStringUtf8(env, stringValue, buffer, bufferSize, &copied);
1251// buffer:"123";
1252```
1253
1254将boolean类型的目标值转换为bigint类型
1255
1256```c++
1257JSVM_Value boolValue;
1258OH_JSVM_GetBoolean(env, false, &boolValue);
1259JSVM_Value bigIntValue;
1260OH_JSVM_CoerceToBigInt(env, boolValue, &bigIntValue);
1261```
1262
1263判断两个JSVM_Value对象类型是否严格相同:先比较操作数类型,操作数类型不同就是不相等,操作数类型相同时,比较值是否相等,相等才返回true。
1264
1265```c++
1266JSVM_Value value = nullptr;
1267JSVM_Value value1 = nullptr;
1268OH_JSVM_CreateArray(env, &value);
1269
1270OH_JSVM_CreateInt32(env, 10, &value1);
1271bool isArray = true;
1272OH_JSVM_StrictEquals(env, value, value, &isArray);
1273```
1274
1275判断两个JSVM_Value对象类型是否宽松相同:判断两个操作数的类型是否相同,若不相同,且可以转换为相同的数据类型,转换为相同的数据类型后,值做严格相等比较,其他的都返回false。
1276
1277```c++
1278JSVM_HandleScope handleScope;
1279OH_JSVM_OpenHandleScope(env, &handleScope);
1280const char testStr[] = "1";
1281JSVM_Value lhs = nullptr;
1282OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &lhs);
1283JSVM_Value rhs;
1284OH_JSVM_CreateInt32(env, 1, &rhs);
1285bool isEquals = false;
1286OH_JSVM_Equals(env, lhs, rhs, &isEquals); // 这里isEquals的值是true
1287OH_JSVM_CloseHandleScope(env, handleScope);
1288```
1289
1290判断传入的JS值是否为构造函数
1291
1292```c++
1293JSVM_Value SayHello(JSVM_Env env, JSVM_CallbackInfo info)
1294{
1295    return nullptr;
1296}
1297JSVM_Value value = nullptr;
1298JSVM_CallbackStruct param;
1299param.data = nullptr;
1300param.callback = SayHello;
1301OH_JSVM_CreateFunction(env, "func", JSVM_AUTO_LENGTH, &param, &value);
1302bool isConstructor = false;
1303OH_JSVM_IsConstructor(env, value, &isConstructor); // 这里isConstructor的值是true
1304```
1305
1306判断传入的JS值是否为Map类型
1307
1308```c++
1309JSVM_Value value = nullptr;
1310OH_JSVM_CreateMap(env, &value);
1311bool isMap = false;
1312OH_JSVM_IsMap(env, value, &isMap); // 这里isMap的值是true
1313```
1314
1315判断传入的JS值是否为Set类型
1316
1317```c++
1318JSVM_Value value;
1319OH_JSVM_CreateSet(env, &value);
1320bool isSet = false;
1321OH_JSVM_IsSet(env, value, &isSet); // 这里isSet的值是true
1322```
1323
1324判断JS值是否为RegExp类型
1325
1326```c++
1327JSVM_Value value = nullptr;
1328const char testStr[] = "ab+c";
1329OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &value);
1330JSVM_Value result = nullptr;
1331OH_JSVM_CreateRegExp(env, value, JSVM_RegExpFlags::JSVM_REGEXP_GLOBAL, &result);
1332bool isRegExp = false;
1333OH_JSVM_IsRegExp(env, result, &isRegExp);
1334```
1335
1336### JS属性操作
1337
1338**场景介绍**
1339
1340JS对象属性的增加、删除、获取和判断。
1341
1342**接口说明**
1343| 接口 | 功能说明 |
1344| -------- | -------- |
1345|OH_JSVM_GetPropertyNames | 获取给定对象的所有可枚举属性名称, 结果变量将存储一个包含所有可枚举属性名称的JavaScript数组。 |
1346|OH_JSVM_GetAllPropertyNames | 获取给定对象的所有可用属性名称, 结果变量将存储一个包含所有可枚举属性名称的JavaScript数组。 |
1347|OH_JSVM_SetProperty | 为给定对象设置一个属性。 |
1348|OH_JSVM_GetProperty | 用给定的属性的名称,检索目标对象的属性。 |
1349|OH_JSVM_HasProperty | 用给定的属性的名称,查询目标对象是否有此属性。 |
1350|OH_JSVM_DeleteProperty | 用给定的属性的名称,删除目标对象属性。 |
1351|OH_JSVM_HasOwnProperty | 检查目标对象是否具有指定的自有属性。 |
1352|OH_JSVM_SetNamedProperty | 用给定的属性的名称为目标对象设置属性,此方法等效于使用从作为 utf8Name 传入的字符串创建的 JSVM_Value 调用 OH_JSVM_SetProperty。 |
1353|OH_JSVM_GetNamedProperty | 用给定的属性的名称,检索目标对象的属性,此方法等效于使用从作为 utf8Name 传入的字符串创建的 JSVM_Value 调用 OH_JSVM_GetProperty。 |
1354|OH_JSVM_HasNamedProperty | 用给定的属性的名称,查询目标对象是否有此属性,此方法等效于使用从作为 utf8Name 传入的字符串创建的 JSVM_Value 调用 OH_JSVM_HasProperty。 |
1355|OH_JSVM_SetElement | 在给定对象的指定索引处设置元素。 |
1356|OH_JSVM_GetElement | 获取给定对象指定索引处的元素。 |
1357|OH_JSVM_HasElement | 若给定对象的指定索引处拥有属性,获取该元素。 |
1358|OH_JSVM_DeleteElement | 尝试删除给定对象的指定索引处的元素。 |
1359|OH_JSVM_DefineProperties |  批量的向给定对象中定义属性。 |
1360|OH_JSVM_ObjectFreeze | 冻结给定的对象,防止向其添加新属性,删除现有属性,防止更改现有属性的可枚举性、可配置性或可写性,并防止更改现有属性的值。 |
1361|OH_JSVM_ObjectSeal | 密封给定的对象。这可以防止向其添加新属性,以及将所有现有属性标记为不可配置。 |
1362|OH_JSVM_ObjectSetPrototypeOf | 为给定对象设置一个原型。 |
1363|OH_JSVM_ObjectGetPrototypeOf | 获取给定JavaScript对象的原型。 |
1364
1365场景示例:
1366JS对象属性的增加、删除、获取和判断。
1367
1368```c++
1369// 创建一个空对象
1370JSVM_Value myObject = nullptr;
1371OH_JSVM_CreateObject(env, &myObject);
1372
1373// 设置属性
1374const char *testNameStr = "John Doe";
1375JSVM_Value propValue = nullptr;
1376JSVM_Value key = nullptr;
1377OH_JSVM_CreateStringUtf8(env, "name", JSVM_AUTO_LENGTH, &key);
1378OH_JSVM_CreateStringUtf8(env, testNameStr, strlen(testNameStr), &propValue);
1379OH_JSVM_SetProperty(env, myObject, key, propValue);
1380
1381// 获取属性
1382JSVM_Value propResult = nullptr;
1383OH_JSVM_GetProperty(env, myObject, key, &propResult);
1384
1385// 检查属性是否存在
1386bool hasProperty = false;
1387OH_JSVM_HasNamedProperty(env, myObject, "name", &hasProperty);
1388    // 属性存在,做相应处理...
1389    if (hasProperty)
1390    {
1391        // 获取对象的所有属性名
1392        JSVM_Value propNames = nullptr;
1393        OH_JSVM_GetPropertyNames(env, myObject, &propNames);
1394
1395        bool isArray = false;
1396        OH_JSVM_IsArray(env, propNames, &isArray);
1397
1398        uint32_t arrayLength = 0;
1399        OH_JSVM_GetArrayLength(env, propNames, &arrayLength);
1400        // 遍历属性元素
1401        for (uint32_t i = 0; i < arrayLength; i++)
1402        {
1403            bool hasElement = false;
1404            OH_JSVM_HasElement(env, propNames, i, &hasElement);
1405
1406            JSVM_Value propName = nullptr;
1407            OH_JSVM_GetElement(env, propNames, i, &propName);
1408
1409            bool hasProp = false;
1410            OH_JSVM_HasProperty(env, myObject, propName, &hasProp);
1411
1412            JSVM_Value propValue = nullptr;
1413            OH_JSVM_GetProperty(env, myObject, propName, &propValue);
1414        }
1415    }
1416
1417// 删除属性
1418OH_JSVM_DeleteProperty(env, myObject, key, &hasProperty);
1419
1420// 设置对象原型
1421JSVM_Value value;
1422OH_JSVM_CreateSet(env, &value);
1423OH_JSVM_ObjectSetPrototypeOf(env, myObject, value);
1424
1425// 获取对象原型
1426JSVM_Value proto;
1427OH_JSVM_ObjectGetPrototypeOf(env, myObject, &proto);
1428```
1429
1430### JS函数操作
1431
1432**场景介绍**
1433
1434JS函数操作。
1435
1436**接口说明**
1437| 接口 | 功能说明 |
1438| -------- | -------- |
1439|OH_JSVM_CallFunction | 在C/C++侧调用JS方法 |
1440|OH_JSVM_CreateFunction | 用于创建JavaScript函数,用于从JavaScript环境中调用C/C++代码中的函数 |
1441|OH_JSVM_GetCbInfo | 从给定的callback info中获取有关调用的详细信息,如参数和this指针 |
1442|OH_JSVM_GetNewTarget | 获取构造函数调用的new.target |
1443|OH_JSVM_NewInstance | 通过给定的构造函数,构建一个实例 |
1444|OH_JSVM_CreateFunctionWithScript | 根据传入的函数体和函数参数列表,创建一个新的 JavaScript Function对象 |
1445
1446场景示例:
1447创建JavaScript函数操作。
1448
1449```c++
1450JSVM_Value SayHello(JSVM_Env env, JSVM_CallbackInfo info)
1451{
1452    printf("Hello\n");
1453    JSVM_Value ret;
1454    OH_JSVM_CreateInt32(env, 2, &ret);
1455    return ret;
1456}
1457
1458static JSVM_Value JsvmCreateFunction(JSVM_Env env, JSVM_CallbackInfo info)
1459{
1460    JSVM_CallbackStruct param;
1461    param.data = nullptr;
1462    param.callback = SayHello;
1463
1464    JSVM_Value funcValue = nullptr;
1465    JSVM_Status status = OH_JSVM_CreateFunction(env, "func", JSVM_AUTO_LENGTH, &param, &funcValue);
1466    return funcValue;
1467}
1468```
1469
1470在C/C++侧调用JS方法。
1471
1472```c++
1473static JSVM_Value CallFunction(JSVM_Env env, JSVM_CallbackInfo info)
1474{
1475    size_t argc = 1;
1476    JSVM_Value args[1];
1477    JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL));
1478    if (argc < 1) {
1479        OH_LOG_ERROR(LOG_APP, "Wrong number of arguments");
1480        return nullptr;
1481    }
1482
1483    JSVM_ValueType valuetype;
1484    JSVM_CALL(OH_JSVM_Typeof(env, args[0], &valuetype));
1485    if (valuetype != JSVM_ValueType::JSVM_FUNCTION) {
1486        OH_LOG_ERROR(LOG_APP, "Wrong type of argment. Expects a function.");
1487        return nullptr;
1488    }
1489
1490    JSVM_Value global;
1491    JSVM_CALL(OH_JSVM_GetGlobal(env, &global));
1492
1493    JSVM_Value ret;
1494    JSVM_CALL(OH_JSVM_CallFunction(env, global, args[0], 0, nullptr, &ret));
1495    return ret;
1496}
1497```
1498
1499创建JavaScript函数:
1500
1501```c++
1502JSVM_Value script;
1503OH_JSVM_CreateStringUtf8(env, "return a + b;", JSVM_AUTO_LENGTH, &script);
1504JSVM_Value param1;
1505JSVM_Value param2;
1506OH_JSVM_CreateStringUtf8(env, "a", JSVM_AUTO_LENGTH, &param1);
1507OH_JSVM_CreateStringUtf8(env, "b", JSVM_AUTO_LENGTH, &param2);
1508JSVM_Value argus[] = {param1, param2};
1509JSVM_Value func;
1510OH_JSVM_CreateFunctionWithScript(env, "add", JSVM_AUTO_LENGTH, 2, argus, script, &func);
1511```
1512
1513### 对象绑定操作
1514
1515**场景介绍**
1516
1517对象绑定操作。
1518
1519**接口说明**
1520| 接口 | 功能说明 |
1521| -------- | -------- |
1522|OH_JSVM_DefineClass| 用于在JavaScript中定义一个类,并与对应的C类进行封装和交互。它提供了创建类的构造函数、定义属性和方法的能力,以及在C和JavaScript之间进行数据交互的支持。 |
1523|OH_JSVM_Wrap| 在 JavaScript 对象中封装原生实例。稍后可以使用 OH_JSVM_Unwrap() 检索原生实例。 |
1524|OH_JSVM_Unwrap | 使用 OH_JSVM_Wrap() 检索先前封装在 JavaScript 对象中的原生实例。 |
1525|OH_JSVM_RemoveWrap | 检索先前封装在 JavaScript 对象中的原生实例并移除封装。 |
1526|OH_JSVM_TypeTagObject | 将 type_tag 指针的值与 JavaScript 对象或外部对象相关联。 |
1527|OH_JSVM_CheckObjectTypeTag | 检查给定的类型标签是否与对象上的类型标签匹配。 |
1528|OH_JSVM_AddFinalizer | 为对象添加 JSVM_Finalize 回调,以便在 JavaScript 对象被垃圾回收时调用来释放原生对象。 |
1529|OH_JSVM_DefineClassWithPropertyHandler | 定义一个具有给定类名、构造函数、属性和回调处理程序的JavaScript类,并作为函数回调进行调用。属性操作包括getter、setter、deleter、enumerator等。 |
1530|OH_JSVM_DefineClassWithOptions | 定义一个具有给定类名、构造函数、属性和回调处理程序、父类的JavaScript类,并根据传入了DefineClassOptions来决定是否需要为所定义的Class设置属性代理、预留internal-field槽位、为class作为函数进行调用时设置函数回调。|
1531
1532场景示例:
1533对象绑定操作。
1534
1535```c++
1536static int aa = 0;
1537
1538static JSVM_Value AssertEqual(JSVM_Env env, JSVM_CallbackInfo info)
1539{
1540    size_t argc = 2;
1541    JSVM_Value args[2];
1542    JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL));
1543
1544    bool isStrictEquals = false;
1545    OH_JSVM_StrictEquals(env, args[0], args[1], &isStrictEquals);
1546    return nullptr;
1547}
1548
1549static napi_value TestWrap(napi_env env1, napi_callback_info info)
1550{
1551    OH_LOG_ERROR(LOG_APP, "testWrap start");
1552    JSVM_InitOptions init_options;
1553    memset(&init_options, 0, sizeof(init_options));
1554    if (aa == 0) {
1555        OH_JSVM_Init(&init_options);
1556        aa++;
1557    }
1558    JSVM_VM vm;
1559    JSVM_CreateVMOptions options;
1560    memset(&options, 0, sizeof(options));
1561    OH_JSVM_CreateVM(&options, &vm);
1562    JSVM_VMScope vm_scope;
1563    OH_JSVM_OpenVMScope(vm, &vm_scope);
1564    JSVM_Env env;
1565    JSVM_CallbackStruct param[1];
1566    param[0].data = nullptr;
1567    param[0].callback = AssertEqual;
1568    JSVM_PropertyDescriptor descriptor[] = {
1569        {"assertEqual", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
1570    };
1571    OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env);
1572    JSVM_EnvScope envScope;
1573    OH_JSVM_OpenEnvScope(env, &envScope);
1574    JSVM_HandleScope handlescope;
1575    OH_JSVM_OpenHandleScope(env, &handlescope);
1576    JSVM_Value testClass = nullptr;
1577    JSVM_CallbackStruct param1;
1578    param1.data = nullptr;
1579    param1.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value {
1580        JSVM_Value thisVar = nullptr;
1581        OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr);
1582
1583        return thisVar;
1584    };
1585    OH_JSVM_DefineClass(env, "TestClass", JSVM_AUTO_LENGTH, &param1, 0, nullptr, &testClass);
1586
1587    JSVM_Value instanceValue = nullptr;
1588    OH_JSVM_NewInstance(env, testClass, 0, nullptr, &instanceValue);
1589
1590    const char *testStr = "test";
1591    OH_JSVM_Wrap(
1592        env, instanceValue, (void *)testStr, [](JSVM_Env env, void *data, void *hint) {}, nullptr, nullptr);
1593    const char *tmpTestStr = nullptr;
1594    OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr);
1595    const char *tmpTestStr1 = nullptr;
1596    OH_JSVM_RemoveWrap(env, instanceValue, (void **)&tmpTestStr1);
1597    OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr1);
1598    OH_JSVM_CloseHandleScope(env, handlescope);
1599    OH_JSVM_CloseEnvScope(env, envScope);
1600    OH_JSVM_DestroyEnv(env);
1601    OH_JSVM_CloseVMScope(vm, vm_scope);
1602    OH_JSVM_DestroyVM(vm);
1603    OH_LOG_ERROR(LOG_APP, "testWrap pass");
1604    return nullptr;
1605}
1606```
1607
1608场景示例:
1609对象绑定及监听拦截属性操作。
1610
1611```c++
1612static int aa = 0;
1613static JSVM_Value hello(JSVM_Env env, JSVM_CallbackInfo info) {
1614    JSVM_Value output;
1615    void *data = nullptr;
1616    OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data);
1617    OH_JSVM_CreateStringUtf8(env, (char *)data, strlen((char *)data), &output);
1618    return output;
1619}
1620
1621static JSVM_CallbackStruct hello_cb = {hello, (void *)"Hello"};
1622static intptr_t externals[] = {
1623    (intptr_t)&hello_cb,
1624    0,
1625};
1626
1627static void test1() { OH_LOG_INFO(LOG_APP, "test1 called"); }
1628
1629struct Test {
1630    void *ptr1;
1631    void *ptr2;
1632};
1633
1634static JSVM_Value assertEqual(JSVM_Env env, JSVM_CallbackInfo info) {
1635    size_t argc = 2;
1636    JSVM_Value args[2];
1637    JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL));
1638
1639    bool isStrictEquals = false;
1640    OH_JSVM_StrictEquals(env, args[0], args[1], &isStrictEquals);
1641    return nullptr;
1642}
1643
1644static JSVM_Value GetPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value thisArg, JSVM_Value data) {
1645    // 该回调是由对象上的获取请求触发的
1646    char strValue[100];
1647    size_t size = 0;
1648    OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size);
1649    JSVM_Value newResult = nullptr;
1650    char newStr[] = "new return value hahaha from name listening";
1651    OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult);
1652    int signBit = 0;
1653    size_t wordCount = 2;
1654    uint64_t wordsOut[2] = {0ULL, 0ULL};
1655    JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
1656    if (status == JSVM_OK) {
1657        OH_LOG_INFO(LOG_APP, "GetPropertyCbInfo wordCount is %{public}zu", wordCount);
1658        auto test = reinterpret_cast<Test *>(wordsOut);
1659        typedef void (*callTest1)();
1660        callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1);
1661        callTe();
1662    }
1663    return nullptr;
1664}
1665
1666static JSVM_Value SetPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value property, JSVM_Value thisArg, JSVM_Value data) {
1667    // 该回调是由对象上的设置请求触发的
1668    char strValue[100];
1669    size_t size = 0;
1670    OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size);
1671    JSVM_Value newResult = nullptr;
1672    char newStr[] = "new return value hahaha from name listening";
1673    OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult);
1674    int signBit = 0;
1675    size_t wordCount = 2;
1676    uint64_t wordsOut[2] = {0ULL, 0ULL};
1677    JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
1678    if (status == JSVM_OK) {
1679        OH_LOG_INFO(LOG_APP, "SetPropertyCbInfo wordCount is %{public}zu", wordCount);
1680        auto test = reinterpret_cast<Test *>(wordsOut);
1681        typedef void (*callTest1)();
1682        callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1);
1683        callTe();
1684    }
1685    return nullptr;
1686}
1687
1688static JSVM_Value DeleterPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value thisArg, JSVM_Value data) {
1689    // 该回调是由对象上的删除请求触发的
1690    char strValue[100];
1691    size_t size = 0;
1692    OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size);
1693    JSVM_Value newResult = nullptr;
1694    bool returnValue = false;
1695    OH_JSVM_GetBoolean(env, returnValue, &newResult);
1696    int signBit = 0;
1697    size_t wordCount = 2;
1698    uint64_t wordsOut[2] = {0ULL, 0ULL};
1699    JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
1700    if (status == JSVM_OK) {
1701        OH_LOG_INFO(LOG_APP, "DeleterPropertyCbInfo wordCount is %{public}zu", wordCount);
1702        auto test = reinterpret_cast<Test *>(wordsOut);
1703        typedef void (*callTest1)();
1704        callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1);
1705        callTe();
1706    }
1707    return nullptr;
1708}
1709
1710static JSVM_Value EnumeratorPropertyCbInfo(JSVM_Env env, JSVM_Value thisArg, JSVM_Value data) {
1711    // 该回调是由获取对象上的所有属性请求触发的
1712    JSVM_Value testArray = nullptr;
1713    OH_JSVM_CreateArrayWithLength(env, 2, &testArray);
1714    JSVM_Value name1 = nullptr;
1715    char newStr1[] = "hahaha";
1716    OH_JSVM_CreateStringUtf8(env, newStr1, strlen(newStr1), &name1);
1717    JSVM_Value name2 = nullptr;
1718    char newStr2[] = "heheheh";
1719    OH_JSVM_CreateStringUtf8(env, newStr2, strlen(newStr2), &name2);
1720
1721    OH_JSVM_SetElement(env, testArray, 0, name1);
1722    OH_JSVM_SetElement(env, testArray, 1, name2);
1723    int signBit = 0;
1724    size_t wordCount = 2;
1725    uint64_t wordsOut[2] = {0ULL, 0ULL};
1726    JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
1727    if (status == JSVM_OK) {
1728        OH_LOG_INFO(LOG_APP, "EnumeratorPropertyCbInfo wordCount is %{public}zu", wordCount);
1729        auto test = reinterpret_cast<Test *>(wordsOut);
1730        typedef void (*callTest1)();
1731        callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1);
1732        callTe();
1733    }
1734    return nullptr;
1735}
1736
1737static JSVM_Value IndexedPropertyGet(JSVM_Env env, JSVM_Value index, JSVM_Value thisArg, JSVM_Value data) {
1738    // 该回调是由获取实例对象的索引属性触发的
1739    uint32_t value = 0;
1740    OH_JSVM_GetValueUint32(env, index, &value);
1741
1742    JSVM_Value newResult = nullptr;
1743    char newStr[] = "new return value hahaha from index listening";
1744    OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult);
1745    int signBit = 0;
1746    size_t wordCount = 2;
1747    uint64_t wordsOut[2] = {0ULL, 0ULL};
1748    JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
1749    if (status == JSVM_OK) {
1750        OH_LOG_INFO(LOG_APP, "IndexedPropertyGet wordCount is %{public}zu", wordCount);
1751        auto test = reinterpret_cast<Test *>(wordsOut);
1752        typedef void (*callTest1)();
1753        callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1);
1754        callTe();
1755    }
1756    return nullptr;
1757}
1758
1759static JSVM_Value IndexedPropertySet(JSVM_Env env, JSVM_Value index, JSVM_Value property, JSVM_Value thisArg, JSVM_Value data) {
1760    // 该回调是由设置实例对象的索引属性触发的
1761    uint32_t value = 0;
1762    OH_JSVM_GetValueUint32(env, index, &value);
1763    char str[100];
1764    size_t size = 0;
1765    OH_JSVM_GetValueStringUtf8(env, property, str, 100, &size);
1766    JSVM_Value newResult = nullptr;
1767    char newStr[] = "new return value hahaha from name listening";
1768    OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult);
1769    int signBit = 0;
1770    size_t wordCount = 2;
1771    uint64_t wordsOut[2] = {0ULL, 0ULL};
1772    JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
1773    if (status == JSVM_OK) {
1774        OH_LOG_INFO(LOG_APP, "IndexedPropertySet wordCount is %{public}zu", wordCount);
1775        auto test = reinterpret_cast<Test *>(wordsOut);
1776        typedef void (*callTest1)();
1777        callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1);
1778        callTe();
1779    }
1780    return nullptr;
1781}
1782
1783static JSVM_Value IndexedPropertyDeleter(JSVM_Env env, JSVM_Value index, JSVM_Value thisArg, JSVM_Value data) {
1784    // 该回调是由删除实例对象的索引属性触发的
1785    uint32_t value = 0;
1786    OH_JSVM_GetValueUint32(env, index, &value);
1787    JSVM_Value newResult = nullptr;
1788    bool returnValue = false;
1789    OH_JSVM_GetBoolean(env, returnValue, &newResult);
1790    int signBit = 0;
1791    size_t wordCount = 2;
1792    uint64_t wordsOut[2] = {0ULL, 0ULL};
1793    JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
1794    if (status == JSVM_OK) {
1795        OH_LOG_INFO(LOG_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount);
1796        auto test = reinterpret_cast<Test *>(wordsOut);
1797        typedef void (*callTest1)();
1798        callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1);
1799        callTe();
1800    }
1801    return nullptr;
1802}
1803
1804static JSVM_Value IndexedPropertyEnumerator(JSVM_Env env, JSVM_Value thisArg, JSVM_Value data) {
1805    // 该回调是由获取对象上的所有索引属性请求触发的
1806    JSVM_Value testArray = nullptr;
1807    OH_JSVM_CreateArrayWithLength(env, 2, &testArray);
1808    JSVM_Value index1 = nullptr;
1809    OH_JSVM_CreateUint32(env, 1, &index1);
1810    JSVM_Value index2 = nullptr;
1811    OH_JSVM_CreateUint32(env, 2, &index2);
1812    OH_JSVM_SetElement(env, testArray, 0, index1);
1813    OH_JSVM_SetElement(env, testArray, 1, index2);
1814    int signBit = 0;
1815    size_t wordCount = 2;
1816    uint64_t wordsOut[2] = {0ULL, 0ULL};
1817    JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
1818    if (status == JSVM_OK) {
1819        OH_LOG_INFO(LOG_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount);
1820        auto test = reinterpret_cast<Test *>(wordsOut);
1821        typedef void (*callTest1)();
1822        callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1);
1823        callTe();
1824    }
1825    return nullptr;
1826}
1827
1828static napi_value TestDefineClassWithProperty(napi_env env1, napi_callback_info info) {
1829    OH_LOG_ERROR(LOG_APP, "TestDefineClassWithProperty start");
1830    JSVM_InitOptions init_options;
1831    memset(&init_options, 0, sizeof(init_options));
1832    init_options.externalReferences = externals;
1833    if (aa == 0) {
1834        OH_JSVM_Init(&init_options);
1835        aa++;
1836    }
1837    JSVM_VM vm;
1838    JSVM_CreateVMOptions options;
1839    memset(&options, 0, sizeof(options));
1840    OH_JSVM_CreateVM(&options, &vm);
1841    JSVM_VMScope vm_scope;
1842    OH_JSVM_OpenVMScope(vm, &vm_scope);
1843    JSVM_Env env;
1844    JSVM_CallbackStruct param[1];
1845    param[0].data = nullptr;
1846    param[0].callback = assertEqual;
1847    JSVM_PropertyDescriptor descriptor[] = {
1848        {"assertEqual", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
1849    };
1850    OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env);
1851    JSVM_EnvScope envScope;
1852    OH_JSVM_OpenEnvScope(env, &envScope);
1853    JSVM_HandleScope handlescope;
1854    OH_JSVM_OpenHandleScope(env, &handlescope);
1855
1856
1857    JSVM_CallbackStruct param1;
1858    param1.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value {
1859        JSVM_Value thisVar = nullptr;
1860        OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr);
1861        return thisVar;
1862    };
1863    param1.data = nullptr;
1864
1865    JSVM_Value res = nullptr;
1866    Test *test = new Test();
1867    test->ptr1 = (void *)test1;
1868    test->ptr2 = (void *)test1;
1869    OH_LOG_INFO(LOG_APP, "OH_JSVM_CreateBigintWords 111 word count %{public}d",
1870                sizeof(*test) / sizeof(uint64_t));
1871    JSVM_Status status = OH_JSVM_CreateBigintWords(env, 1, 2, reinterpret_cast<const uint64_t *>(test), &res);
1872
1873    // 初始化propertyCfg
1874    JSVM_PropertyHandlerConfigurationStruct propertyCfg;
1875    propertyCfg.genericNamedPropertyGetterCallback = GetPropertyCbInfo;
1876    propertyCfg.genericNamedPropertySetterCallback = SetPropertyCbInfo;
1877    propertyCfg.genericNamedPropertyDeleterCallback = DeleterPropertyCbInfo;
1878    propertyCfg.genericNamedPropertyEnumeratorCallback = EnumeratorPropertyCbInfo;
1879    propertyCfg.genericIndexedPropertyGetterCallback = IndexedPropertyGet;
1880    propertyCfg.genericIndexedPropertySetterCallback = IndexedPropertySet;
1881    propertyCfg.genericIndexedPropertyDeleterCallback = IndexedPropertyDeleter;
1882    propertyCfg.genericIndexedPropertyEnumeratorCallback = IndexedPropertyEnumerator;
1883    propertyCfg.namedPropertyData = res;
1884    propertyCfg.indexedPropertyData = res;
1885
1886    JSVM_CallbackStruct callbackStruct;
1887    callbackStruct.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value {
1888        OH_LOG_INFO(LOG_APP, "call as a function called");
1889        JSVM_Value thisVar = nullptr;
1890        void *innerData;
1891        size_t argc = 1;
1892        JSVM_Value args[1];
1893        OH_JSVM_GetCbInfo(env, info, &argc, args, &thisVar, &innerData);
1894        OH_LOG_INFO(LOG_APP, "function call as function result is %{public}s", reinterpret_cast<char *>(innerData));
1895        uint32_t ret = 0;
1896        OH_JSVM_GetValueUint32(env, args[0], &ret);
1897        const char testStr[] = "hello world 111111";
1898        JSVM_Value setvalueName = nullptr;
1899        JSVM_CALL(OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName));
1900        return setvalueName;
1901    };
1902    char data[100] = "1111 hello world";
1903    callbackStruct.data = data;
1904    JSVM_Value testWrapClass = nullptr;
1905
1906    // 将属性的访问监听注册在propertyCfg中
1907    OH_JSVM_DefineClassWithPropertyHandler(env, "TestWrapClass", NAPI_AUTO_LENGTH, &param1, 0, nullptr, &propertyCfg,
1908                                           &callbackStruct, &testWrapClass);
1909    JSVM_Value instanceValue = nullptr;
1910    OH_JSVM_NewInstance(env, testWrapClass, 0, nullptr, &instanceValue);
1911    const char testStr[] = "hello world";
1912    JSVM_Value setvalueName = nullptr;
1913    OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName);
1914
1915    // 1. 名称属性回调
1916    // 设置属性
1917    OH_JSVM_SetNamedProperty(env, instanceValue, "str11", setvalueName);
1918    OH_JSVM_SetNamedProperty(env, instanceValue, "str123", setvalueName);
1919
1920    // 获取属性
1921    JSVM_Value valueName = nullptr;
1922    OH_JSVM_GetNamedProperty(env, instanceValue, "str11", &valueName);
1923    char str[100];
1924    size_t size = 0;
1925    OH_JSVM_GetValueStringUtf8(env, valueName, str, 100, &size);
1926
1927    // 获取所有属性的名称
1928    JSVM_Value allPropertyNames = nullptr;
1929    OH_JSVM_GetAllPropertyNames(env, instanceValue, JSVM_KEY_OWN_ONLY,
1930                                static_cast<JSVM_KeyFilter>(JSVM_KEY_ENUMERABLE | JSVM_KEY_SKIP_SYMBOLS),
1931                                JSVM_KEY_NUMBERS_TO_STRINGS, &allPropertyNames);
1932    uint32_t nameSize = 0;
1933    OH_JSVM_GetArrayLength(env, allPropertyNames, &nameSize);
1934    JSVM_Value propertyName = nullptr;
1935    for (uint32_t i = 0; i < nameSize; ++i) {
1936        OH_JSVM_GetElement(env, allPropertyNames, i, &propertyName);
1937        char str[100];
1938        size_t size = 0;
1939        OH_JSVM_GetValueStringUtf8(env, propertyName, str, 100, &size);
1940    }
1941
1942    // 删除属性
1943    bool result = false;
1944    propertyName = nullptr;
1945    char propertyChar[] = "str11";
1946    OH_JSVM_CreateStringUtf8(env, propertyChar, strlen(propertyChar), &propertyName);
1947    OH_JSVM_DeleteProperty(env, instanceValue, propertyName, &result);
1948
1949    // 2. 索引属性回调
1950    // 设置属性
1951    JSVM_Value jsIndex = nullptr;
1952    uint32_t index = 0;
1953    OH_JSVM_CreateUint32(env, index, &jsIndex);
1954    OH_JSVM_SetProperty(env, instanceValue, jsIndex, setvalueName);
1955    JSVM_Value jsIndex1 = nullptr;
1956    index = 1;
1957    OH_JSVM_CreateUint32(env, index, &jsIndex1);
1958    OH_JSVM_SetProperty(env, instanceValue, jsIndex1, setvalueName);
1959
1960    // 获取属性
1961    JSVM_Value valueName1 = nullptr;
1962    OH_JSVM_GetProperty(env, instanceValue, jsIndex, &valueName1);
1963    char str1[100];
1964    size_t size1 = 0;
1965    OH_JSVM_GetValueStringUtf8(env, valueName1, str1, 100, &size1);
1966
1967    // 获取所有属性的名称
1968    JSVM_Value allPropertyNames1 = nullptr;
1969    OH_JSVM_GetAllPropertyNames(env, instanceValue, JSVM_KEY_OWN_ONLY,
1970                                static_cast<JSVM_KeyFilter>(JSVM_KEY_ENUMERABLE | JSVM_KEY_SKIP_SYMBOLS),
1971                                JSVM_KEY_NUMBERS_TO_STRINGS, &allPropertyNames1);
1972    uint32_t nameSize1 = 0;
1973    OH_JSVM_GetArrayLength(env, allPropertyNames1, &nameSize1);
1974    JSVM_Value propertyName1 = nullptr;
1975    for (uint32_t i = 0; i < nameSize1; ++i) {
1976        OH_JSVM_GetElement(env, allPropertyNames1, i, &propertyName1);
1977        char str[100];
1978        size_t size = 0;
1979        OH_JSVM_GetValueStringUtf8(env, propertyName1, str, 100, &size);
1980    }
1981
1982    // 删除属性
1983    bool result1 = false;
1984    OH_JSVM_DeleteProperty(env, instanceValue, jsIndex, &result1);
1985
1986    // 3. 作为函数的回调
1987    JSVM_Value gloablObj = nullptr;
1988    OH_JSVM_GetGlobal(env, &gloablObj);
1989    OH_JSVM_SetNamedProperty(env, gloablObj, "myTestInstance", instanceValue);
1990    OH_LOG_INFO(LOG_APP, "set property on global object");
1991    std::string innerSourcecodestr = R"(
1992    {
1993        let res = myTestInstance(12);
1994    })";
1995    JSVM_Value innerSourcecodevalue;
1996    OH_JSVM_CreateStringUtf8(env, innerSourcecodestr.c_str(), innerSourcecodestr.size(), &innerSourcecodevalue);
1997    JSVM_Script innerscript;
1998    OH_JSVM_CompileScript(env, innerSourcecodevalue, nullptr, 0, true, nullptr, &innerscript);
1999    JSVM_Value innerResult;
2000    OH_JSVM_RunScript(env, innerscript, &innerResult);
2001
2002    OH_JSVM_CloseHandleScope(env, handlescope);
2003    OH_JSVM_CloseEnvScope(env, envScope);
2004    OH_JSVM_DestroyEnv(env);
2005    OH_JSVM_CloseVMScope(vm, vm_scope);
2006    OH_JSVM_DestroyVM(vm);
2007    OH_LOG_ERROR(LOG_APP, "TestDefineClassWithProperty pass");
2008    return nullptr;
2009}
2010```
2011场景示例:设置父类并通过DefineClassOptions设置监听拦截属性操作
2012
2013具体示例参考[使用JSVM进行class相关开发](use-jsvm-about-class.md)。
2014
2015### 版本管理
2016
2017**场景介绍**
2018
2019获取当前版本信息。
2020
2021**接口说明**
2022| 接口 | 功能说明 |
2023| -------- | -------- |
2024|OH_JSVM_GetVersion| 返回JSVM运行时支持的最高JSVM API版本 |
2025|OH_JSVM_GetVMInfo| 返回虚拟机的信息 |
2026
2027场景示例:
2028获取当前版本信息。
2029
2030```c++
2031JSVM_VMInfo result;
2032OH_JSVM_GetVMInfo(&result);
2033uint32_t versionId = 0;
2034OH_JSVM_GetVersion(env, &versionId);
2035```
2036
2037### 内存管理
2038
2039**场景介绍**
2040
2041内存管理。
2042
2043**接口说明**
2044| 接口                                          | 功能说明                                                                                                   |
2045| ------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
2046| OH_JSVM_AdjustExternalMemory                | 将因JavaScript对象而保持活跃的外部分配的内存大小及时通知给底层虚拟机,虚拟机后续触发GC时,就会综合内外内存状态来判断是否进行全局GC。即增大外部内存分配,则会增大触发全局GC的概率;反之减少。 |
2047| OH_JSVM_MemoryPressureNotification          | 通知虚拟机系统内存压力层级,并有选择地触发垃圾回收。                                                                             |
2048| OH_JSVM_AllocateArrayBufferBackingStoreData | 申请一块 BackingStore 内存。 |
2049| OH_JSVM_FreeArrayBufferBackingStoreData | 释放 BackingStore 内存。 |
2050| OH_JSVM_CreateArrayBufferFromBackingStoreData | 基于申请的 BackingStore 内存创建 array buffer。 |
2051
2052> 使用 BackingStore 属于高危操作,使用者需确保内存使用正确。请参考下方正确示例,谨慎操作。
2053
2054场景示例:
2055内存管理。
2056
2057```c++
2058// 分别在调用OH_JSVM_AdjustExternalMemory前后来查看底层虚拟机视角下外部分配的内存大小
2059int64_t result = 0;
2060OH_JSVM_AdjustExternalMemory(env, 0, &result); // 假设外部分配内存的变化不变
2061OH_LOG_INFO(LOG_APP, "Before AdjustExternalMemory: %{public}lld\n", result); // 得到调整前的数值
2062// 调整外部分配的内存大小通知给底层虚拟机(此示例假设内存使用量增加)
2063int64_t memoryIncrease = 1024 * 1024; // 增加 1 MB
2064OH_JSVM_AdjustExternalMemory(env, memoryIncrease, &result);
2065OH_LOG_INFO(LOG_APP, "After AdjustExternalMemory: %{public}lld\n", result); // 得到调整后的数值
2066```
2067```c++
2068// 打开一个Handle scope,在scope范围内申请大量内存来测试函数功能;
2069// 分别在“完成申请后”、“关闭scope后”和“调用OH_JSVM_MemoryPressureNotification后”三个节点查看内存状态
2070JSVM_HandleScope tmpscope = nullptr;
2071OH_JSVM_OpenHandleScope(env, &tmpscope);
2072for (int i = 0; i < 1000000; ++i) {
2073    JSVM_Value obj;
2074    OH_JSVM_CreateObject(env, &obj);
2075}
2076JSVM_HeapStatistics mem;
2077OH_JSVM_GetHeapStatistics(vm, &mem); // 获取虚拟机堆的统计数据
2078OH_LOG_INFO(LOG_APP, "%{public}zu\n", mem.usedHeapSize); // 申请完成后,内存处于最大状态
2079OH_JSVM_CloseHandleScope(env, tmpscope); // 关闭Handle scope
2080
2081OH_JSVM_GetHeapStatistics(vm, &mem);
2082OH_LOG_INFO(LOG_APP, "%{public}zu\n", mem.usedHeapSize); // 关闭scope后,GC并没有立即回收
2083
2084// 通知虚拟机系统内存压力层级,并有选择地触发垃圾回收
2085OH_JSVM_MemoryPressureNotification(env, JSVM_MEMORY_PRESSURE_LEVEL_CRITICAL); // 假设内存压力处于临界状态
2086
2087OH_JSVM_GetHeapStatistics(vm, &mem);
2088OH_LOG_INFO(LOG_APP, "%{public}zu\n", mem.usedHeapSize); // 触发垃圾回收后
2089```
2090
2091BackingStore 正确使用示例
2092``` c++
2093void *backingStore;
2094JSVM_Value arrayBuffer;
2095
2096// 申请一块大小为 100 字节的 BackingStore 内存
2097OH_JSVM_AllocateArrayBufferBackingStoreData(100, JSVM_ZERO_INITIALIZED, &backingStore);
2098
2099// 在之前申请的 BackingStore 上创建一个 ArrayBuffer,位置为距离 BackingStore 起始地址加 30 字节处,大小为 20 字节
2100OH_JSVM_CreateArrayBufferFromBackingStoreData(env, backingStore, 100, 30, 20, &arrayBuffer);
2101
2102// 在 JS 中使用创建的 ArrayBuffer
2103JSVM_Value js_global;
2104JSVM_Value name;
2105OH_JSVM_GetGlobal(env, &js_global);
2106OH_JSVM_CreateStringUtf8(env, "buffer", JSVM_AUTO_LENGTH, &name);
2107OH_JSVM_SetProperty(env, js_global, name, arrayBuffer);
2108
2109JSVM_Script script;
2110JSVM_Value scriptString;
2111JSVM_Value result;
2112const char *src = R"JS(
2113function writeBuffer(data) {
2114  let view = new Uint8Array(data);
2115  // Write some values to the ArrayBuffer
2116  for (let i = 0; i < view.length; i++) {
2117    view[i] = i % 256;
2118  }
2119}
2120writeBuffer(buffer)
2121)JS";
2122OH_JSVM_CreateStringUtf8(env, src, JSVM_AUTO_LENGTH, &scriptString);
2123OH_JSVM_CompileScriptWithOptions(env, scriptString, 0, nullptr, &script);
2124OH_JSVM_RunScript(env, script, &result);
2125
2126// 检查 ArrayBuffer 的内容
2127uint8_t *array = static_cast<uint8_t*>(backingStore);
2128for (auto i = 0; i < 100; ++i) {
2129  if (array[i] != i % 256) {
2130    return false;
2131  }
2132}
2133
2134// 释放 array buffer. 注意对于这种方式创建的 ArrayBuffer, 在释放对应的 BackingStore 之前,
2135// 务必使用 OH_JSVM_DetachArraybuffer 将所有使用当前的 BackingStore 创建的 ArrayBuffer 释放
2136// 否则可能产生不可预测的内存问题,请谨慎使用
2137OH_JSVM_DetachArraybuffer(env, arrayBuffer);
2138
2139// 释放申请的 backing store 内存
2140OH_JSVM_FreeArrayBufferBackingStoreData(backingStore);
2141```
2142### Promise操作
2143
2144**场景介绍**
2145
2146Promise相关操作。
2147
2148**接口说明**
2149| 接口 | 功能说明 |
2150| -------- | -------- |
2151|OH_JSVM_CreatePromise| 创建一个延迟对象和一个JavaScript promise |
2152|OH_JSVM_ResolveDeferred| 通过与之关联的延迟对象来解析JavaScript promise |
2153|OH_JSVM_RejectDeferred| 通过与之关联的延迟对象来拒绝JavaScript Promise |
2154|OH_JSVM_IsPromise| 查询Promise是否为原生Promise对象 |
2155
2156场景示例:
2157Promise相关操作。
2158
2159```c++
2160JSVM_Deferred deferred;
2161JSVM_Value promise;
2162OH_JSVM_CreatePromise(env, &deferred, &promise);
2163
2164// 模拟异步操作
2165int result = 42;
2166bool success = true;
2167if (success)
2168{
2169    // 解析Promise,并传递结果
2170    JSVM_Value value;
2171    OH_JSVM_CreateInt32(env, result, &value);
2172    OH_JSVM_ResolveDeferred(env, deferred, value);
2173} else {
2174    // 拒绝Promise,并传递错误信息
2175    JSVM_Value code = nullptr;
2176    JSVM_Value message = nullptr;
2177    OH_JSVM_CreateStringUtf8(env, "600", JSVM_AUTO_LENGTH, &code);
2178    OH_JSVM_CreateStringUtf8(env, "Async operation failed", JSVM_AUTO_LENGTH, &message);
2179    JSVM_Value error = nullptr;
2180    OH_JSVM_CreateError(env, code, message, &error);
2181    OH_JSVM_RejectDeferred(env, deferred, error);
2182}
2183```
2184
2185### JSON操作
2186
2187**场景介绍**
2188
2189JSON操作。
2190
2191**接口说明**
2192
2193| 接口 | 功能说明 |
2194| -------- | -------- |
2195|OH_JSVM_JsonParse| 解析JSON字符串,并返回成功解析的值 |
2196|OH_JSVM_JsonStringify| 将对象字符串化,并返回成功转换后的字符串 |
2197
2198场景示例:
2199解析JSON操作。
2200
2201```c++
2202std::string sourcecodestr = "{\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}" ;
2203JSVM_Value jsonString;
2204OH_JSVM_CreateStringUtf8(env, sourcecodestr.c_str(), sourcecodestr.size(), &jsonString);
2205JSVM_Value result;
2206OH_JSVM_JsonParse(env, jsonString, &result);
2207```
2208
2209### 创建和使用虚拟机的启动快照
2210
2211**场景介绍**
2212
2213创建和使用虚拟机的启动快照。
2214
2215**接口说明**
2216| 接口 | 功能说明 |
2217| -------- | -------- |
2218|OH_JSVM_CreateSnapshot| 用于创建虚拟机的启动快照 |
2219|OH_JSVM_CreateEnvFromSnapshot| 基于启动快照创建jsvm环境 |
2220
2221场景示例:
2222[创建和使用虚拟机的启动快照。](use-jsvm-create-snapshot.md)
2223
2224### 检查传入的值是否可调用
2225
2226**场景介绍**
2227
2228检查传入的值是否可调用。
2229
2230**接口说明**
2231| 接口 | 功能说明 |
2232| -------- | -------- |
2233|OH_JSVM_IsCallable| 检查传入的值是否可调用 |
2234
2235场景示例:
2236检查传入的值是否可调用。
2237
2238```c++
2239static JSVM_Value NapiIsCallable(JSVM_Env env, JSVM_CallbackInfo info) {
2240    JSVM_Value value, rst;
2241    size_t argc = 1;
2242    bool isCallable = false;
2243    JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, &value, NULL, NULL));
2244    JSVM_CALL(OH_JSVM_IsCallable(env, value, &isCallable));
2245    OH_JSVM_GetBoolean(env, isCallable, &rst);
2246    return rst;
2247}
2248
2249static napi_value MyJSVMDemo([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) {
2250    std::thread t([]() {
2251        // create vm, and open vm scope
2252        JSVM_VM vm;
2253        JSVM_CreateVMOptions options;
2254        memset(&options, 0, sizeof(options));
2255        OH_JSVM_CreateVM(&options, &vm);
2256        JSVM_VMScope vmScope;
2257        OH_JSVM_OpenVMScope(vm, &vmScope);
2258        JSVM_CallbackStruct param[] = {
2259            {.data = nullptr, .callback = NapiIsCallable},
2260        };
2261        JSVM_PropertyDescriptor descriptor[] = {
2262            {"napiIsCallable", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
2263        };
2264        // create env, register native method, and open env scope
2265        JSVM_Env env;
2266        OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env);
2267        JSVM_EnvScope envScope;
2268        OH_JSVM_OpenEnvScope(env, &envScope);
2269        // open handle scope
2270        JSVM_HandleScope handleScope;
2271        OH_JSVM_OpenHandleScope(env, &handleScope);
2272        std::string sourceCodeStr = R"JS(
2273        function addNumbers(num1, num2)
2274        {
2275            var rst= num1 + num2;
2276            return rst;
2277        }
2278        let rst = napiIsCallable(addNumbers);
2279        )JS";
2280        // compile js script
2281        JSVM_Value sourceCodeValue;
2282        OH_JSVM_CreateStringUtf8(env, sourceCodeStr.c_str(), sourceCodeStr.size(), &sourceCodeValue);
2283        JSVM_Script script;
2284        OH_JSVM_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script);
2285        JSVM_Value result;
2286        // run js script
2287        OH_JSVM_RunScript(env, script, &result);
2288        JSVM_ValueType type;
2289        OH_JSVM_Typeof(env, result, &type);
2290        OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type);
2291        // exit vm and clean memory
2292        OH_JSVM_CloseHandleScope(env, handleScope);
2293        OH_JSVM_CloseEnvScope(env, envScope);
2294        OH_JSVM_DestroyEnv(env);
2295        OH_JSVM_CloseVMScope(vm, vmScope);
2296        OH_JSVM_DestroyVM(vm);
2297    });
2298    t.detach();
2299    return nullptr;
2300}
2301```
2302
2303### Lock操作
2304
2305**场景介绍**
2306
2307Lock操作。
2308
2309**接口说明**
2310| 接口 | 功能说明 |
2311| -------- | -------- |
2312|OH_JSVM_IsLocked| 判断当前线程是否持有指定环境的锁 |
2313|OH_JSVM_AcquireLock| 获取指定环境的锁 |
2314|OH_JSVM_ReleaseLock| 释放指定环境的锁 |
2315
2316场景示例:
2317加锁解锁操作。
2318
2319```c++
2320class LockWrapper {
2321 public:
2322  LockWrapper(JSVM_Env env) : env(env) {
2323    OH_JSVM_IsLocked(env, &isLocked);
2324    if (!isLocked) {
2325      OH_JSVM_AcquireLock(env);
2326      OH_JSVM_GetVM(env, &vm);
2327      OH_JSVM_OpenVMScope(vm, &vmScope);
2328      OH_JSVM_OpenEnvScope(env, &envScope);
2329    }
2330  }
2331
2332  ~LockWrapper() {
2333    if (!isLocked) {
2334      OH_JSVM_CloseEnvScope(env, envScope);
2335      OH_JSVM_CloseVMScope(vm, vmScope);
2336      OH_JSVM_ReleaseLock(env);
2337    }
2338  }
2339
2340  LockWrapper(const LockWrapper&) = delete;
2341  LockWrapper& operator=(const LockWrapper&) = delete;
2342  LockWrapper(LockWrapper&&) = delete;
2343  void* operator new(size_t) = delete;
2344  void* operator new[](size_t) = delete;
2345
2346 private:
2347  JSVM_Env env;
2348  JSVM_EnvScope envScope;
2349  JSVM_VMScope vmScope;
2350  JSVM_VM vm;
2351  bool isLocked;
2352};
2353
2354static int aa = 0;
2355
2356static napi_value Add([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) {
2357    static JSVM_VM vm;
2358    static JSVM_Env env;
2359    if (aa == 0) {
2360        OH_JSVM_Init(nullptr);
2361        aa++;
2362        // create vm
2363        JSVM_CreateVMOptions options;
2364        memset(&options, 0, sizeof(options));
2365        OH_JSVM_CreateVM(&options, &vm);
2366        // create env
2367        OH_JSVM_CreateEnv(vm, 0, nullptr, &env);
2368    }
2369
2370    std::thread t1([]() {
2371        LockWrapper lock(env);
2372        JSVM_HandleScope handleScope;
2373        OH_JSVM_OpenHandleScope(env, &handleScope);
2374        JSVM_Value value;
2375        JSVM_Status rst = OH_JSVM_CreateInt32(env, 32, &value); // 32: numerical value
2376        if (rst == JSVM_OK) {
2377            OH_LOG_INFO(LOG_APP, "JSVM:t1 OH_JSVM_CreateInt32 suc");
2378        } else {
2379            OH_LOG_ERROR(LOG_APP, "JSVM:t1 OH_JSVM_CreateInt32 fail");
2380        }
2381        int32_t num1 = 0;
2382        OH_JSVM_GetValueInt32(env, value, &num1);
2383        OH_LOG_INFO(LOG_APP, "JSVM:t1 num1 = %{public}d", num1);
2384        OH_JSVM_CloseHandleScope(env, handleScope);
2385    });
2386    std::thread t2([]() {
2387        LockWrapper lock(env);
2388        JSVM_HandleScope handleScope;
2389        OH_JSVM_OpenHandleScope(env, &handleScope);
2390        JSVM_Value value;
2391        JSVM_Status rst = OH_JSVM_CreateInt32(env, 32, &value); // 32: numerical value
2392        if (rst == JSVM_OK) {
2393            OH_LOG_INFO(LOG_APP, "JSVM:t2 OH_JSVM_CreateInt32 suc");
2394        } else {
2395            OH_LOG_ERROR(LOG_APP, "JSVM:t2 OH_JSVM_CreateInt32 fail");
2396        }
2397        int32_t num1 = 0;
2398        OH_JSVM_GetValueInt32(env, value, &num1);
2399        OH_LOG_INFO(LOG_APP, "JSVM:t2 num1 = %{public}d", num1);
2400        OH_JSVM_CloseHandleScope(env, handleScope);
2401    });
2402    t1.detach();
2403    t2.detach();
2404    return nullptr;
2405}
2406```
2407
2408### 设置与获取和当前运行的JSVM环境相关联的数据
2409
2410**场景介绍**
2411
2412调用OH_JSVM_SetInstanceData接口,设置与当前运行的JSVM环境相关联的数据。
2413
2414**接口说明**
2415| 接口 | 功能说明 |
2416| -------- | -------- |
2417|OH_JSVM_SetInstanceData| 设置与当前运行的JSVM环境相关联的数据 |
2418|OH_JSVM_GetInstanceData| 获取与当前运行的JSVM环境相关联的数据 |
2419
2420场景示例:
2421设置并获取与当前运行的JSVM环境相关联的数据。
2422
2423```c++
2424JSVM_VM vm;
2425JSVM_CreateVMOptions options;
2426JSVM_VMScope vm_scope;
2427JSVM_Env env;
2428JSVM_EnvScope envScope;
2429JSVM_HandleScope handlescope;
2430
2431static int aa = 0;
2432struct InstanceData {
2433    int32_t value;
2434};
2435
2436// 初始化虚拟机,创建JSVM运行环境
2437void init_JSVM_environment(){
2438    JSVM_InitOptions init_options;
2439    memset(&init_options, 0, sizeof(init_options));
2440    if (aa == 0) {
2441        OH_JSVM_Init(&init_options);
2442        aa++;
2443    }
2444    memset(&options, 0, sizeof(options));
2445    OH_JSVM_CreateVM(&options, &vm);
2446    OH_JSVM_OpenVMScope(vm, &vm_scope);
2447    OH_JSVM_CreateEnv(vm, 0, nullptr, &env);
2448    OH_JSVM_OpenEnvScope(env, &envScope);
2449    OH_JSVM_OpenHandleScope(env, &handlescope);
2450}
2451
2452// 退出虚拟机,释放对应的环境
2453napi_value close_JSVM_environment(napi_env env1, napi_callback_info info)
2454{
2455    OH_JSVM_CloseHandleScope(env, handlescope);
2456    OH_JSVM_CloseEnvScope(env, envScope);
2457    OH_JSVM_DestroyEnv(env);
2458    OH_JSVM_CloseVMScope(vm, vm_scope);
2459    OH_JSVM_DestroyVM(vm);
2460    napi_value result;
2461    char* s = "ok";
2462    napi_create_string_latin1(env1, s, strlen(s), &result);
2463    return result;
2464}
2465
2466//清除和释放与实例相关联的内存资源
2467void InstanceFinalizeCallback(JSVM_Env env, void *finalizeData, void *finalizeHint)
2468{
2469    if (finalizeData) {
2470        InstanceData *data = reinterpret_cast<InstanceData *>(finalizeData);
2471        free(data);
2472        *(InstanceData **)finalizeData = nullptr;
2473    }
2474}
2475
2476static napi_value GetInstanceData(napi_env env1, napi_callback_info info)
2477{
2478    InstanceData *instanceData = reinterpret_cast<InstanceData *>(malloc(sizeof(InstanceData)));
2479    if (instanceData == nullptr) {
2480        printf("Memory allocation failed!\n");
2481        return nullptr;
2482    }
2483    size_t argc = 1;
2484    napi_value args[1] = {nullptr};
2485    //用于获取回调函数参数
2486    napi_get_cb_info(env1, info, &argc, args , nullptr, nullptr);
2487    napi_valuetype valuetype0;
2488    napi_typeof(env1, args[0], &valuetype0);
2489    int32_t tmp = 0;
2490    napi_get_value_int32(env1, args[0], &tmp);
2491    instanceData->value = tmp;
2492    //将获得的参数与当前运行的JSVM环境关联起来
2493    OH_JSVM_SetInstanceData(env, instanceData, InstanceFinalizeCallback, nullptr);
2494    InstanceData *resData = nullptr;
2495    //获取与当前运行的JSVM环境相关联的数据
2496    OH_JSVM_GetInstanceData(env, (void **)&resData);
2497    napi_value result;
2498    napi_create_uint32(env1, resData->value, &result);
2499    return result;
2500}
2501```
2502
2503### 任务队列
2504
2505**场景介绍**
2506
2507在虚拟机内部启动任务队列的运行,检查队列中是否有待处理的微任务。任务队列可由外部事件循环执行。
2508
2509**接口说明**
2510| 接口 | 功能说明 |
2511| -------- | -------- |
2512|OH_JSVM_PumpMessageLoop| 启动任务队列的运行 |
2513|OH_JSVM_PerformMicrotaskCheckpoint| 执行任务队列里的微任务 |
2514
2515场景示例:
2516[使用JSVM-API接口进行任务队列相关开发](use-jsvm-execute_tasks.md)