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