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, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 519 {"add", NULL, ¶m[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, ¶m, &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, ¶m, &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, ¶m1); 1507OH_JSVM_CreateStringUtf8(env, "b", JSVM_AUTO_LENGTH, ¶m2); 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, ¶m[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, ¶m1, 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, ¶m[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, ¶m1, 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, ¶m[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)