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