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