1# JSVM-API Data Types and APIs 2 3## Data Types 4 5### JSVM_Status 6 7Enum indicating the execution status of a JSVM-API call. 8 9Each time a JSVM-API function is called, a value of **JSVM_Status** is returned indicating the execution result. 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 42Struct that holds detailed error information when a JSVM-API call fails. 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 55Pointer used to represent a JavaScript (JS) value. 56 57### JSVM_Env 58 59- Context used by the underlying JSVM-API implementation. It is passed to the native functions when they are invoked, and must be passed back when JSVM-API calls are made. 60 61- When a native addon exits, **JSVM_Env** becomes invalid and this event is passed to **OH_JSVM_SetInstanceData** via a callback. 62 63- Avoid caching **JSVM_Env** or passing **JSVM_Env** between different worker threads. 64 65- If **JSVM_Env** is shared between different threads, the **threadlocal** variable must be isolated across threads. For this purpose, close the env scope of the current thread before switching to another thread and open a new env scope in each thread switched to. 66 67### JSVM_ValueType 68 69Enum indicating the type of **JSVM_Value**. The **JSVM_Value** types include the types defined in ECMAScript. **JSVM_EXTERNAL** indicates an external data type. 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 88Enum indicating the data type of the binary **TypedArray** object. 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### Memory Management Types 107 108JSVM-API provides the following memory management types: 109 110**JSVM_HandleScope** 111 112Data used to manage the lifecycle of JS objects. It allows JS objects to remain active within a certain range for use in JS code. When **JSVM_HandleScope** is created, all JS objects created in this range remain active until the end. This can prevent released objects from being used in JS code, which improves code reliability and performance. 113 114**JSVM_EscapableHandleScope** 115 116- It is created by **OH_JSVM_OpenEscapableHandleScope** and closed by **OH_JSVM_CloseEscapableHandleScope**. 117 118- It is a special type of handle range used to return values created within the scope of **JSVM_EscapableHandleScope** to a parent scope. 119 120- You can use **OH_JSVM_EscapeHandle** to promote **JSVM_EscapableHandleScope** to a JS object so that it is valid for the lifetime of the outer scope. 121 122**JSVM_Ref** 123 124Reference to **JSVM_Value**, which allows you to manage the lifecycle of JS values. 125 126**JSVM_TypeTag** 127 128Struct containing two unsigned 64-bit integers to identify the type of a JSVM-API value. 129 130```c++ 131typedef struct { 132 uint64_t lower; 133 uint64_t upper; 134} JSVM_TypeTag; 135``` 136 137- It is a 128-bit value stored as two unsigned 64-bit integers. It is used to tag JS objects to ensure that they are of a certain type. 138 139- This is a stronger check than **OH_JSVM_Instanceof** because **OH_JSVM_Instanceof** may report a false positive if the object's prototype is manipulated. 140 141- The combination of **JSVM_TypeTag** and **OH_JSVM_Wrap** is useful because it ensures that the pointer retrieved from a wrapped object can be safely converted to the native type corresponding to the type tag that had been previously applied to the JS object. 142 143### Callback Types 144 145JSVM-API provides the following callback types: 146 147**JSVM_CallbackInfo** 148 149User-defined native function, which is exposed to JS via JSVM-API. Generally, no handle or callback scope is created inside this callback. 150 151**JSVM_CallbackStruct** 152 153Function pointer type and data for user-provided native functions, which are to be exposed to JS via JSVM-API. 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 164User-defined native function exposed to JS. Unless otherwise required in object lifecycle management, no handle or callback scope is created in this callback. 165 166The usage is as follows: 167 168```c++ 169typedef JSVM_CallbackStruct* JSVM_Callback; 170``` 171 172**JSVM_Finalize** 173 174Function pointer, which is passed in APIs such as **OH_JSVM_SetInstanceData**, **OH_JSVM_CreateExternal**, and **OH_JSVM_Wrap**. **JSVM_Finalize** is called to release the native object when a JS object is garbage collected. 175 176The format is as follows: 177 178```c++ 179typedef void (JSVM_Finalize)(JSVM_Env env, void finalizeData, void* finalizeHint); 180``` 181 182**JSVM_PropertyHandlerConfigurationStruct** 183 184Callback to be invoked when the getter(), setter(), deleter(), or enumerator() of an object is executed. 185 186```c++ 187typedef struct { 188 JSVM_Value(JSVM_CDECL* genericNamedPropertyGetterCallback)(JSVM_Env env, 189 JSVM_Value name, 190 JSVM_Value thisArg, 191 JSVM_Value namedPropertyData); 192 JSVM_Value(JSVM_CDECL* genericNamedPropertySetterCallback)(JSVM_Env env, 193 JSVM_Value name, 194 JSVM_Value property, 195 JSVM_Value thisArg, 196 JSVM_Value namedPropertyData); 197 JSVM_Value(JSVM_CDECL* genericNamedPropertyDeleterCallback)(JSVM_Env env, 198 JSVM_Value name, 199 JSVM_Value thisArg, 200 JSVM_Value namedPropertyData); 201 JSVM_Value(JSVM_CDECL* genericNamedPropertyEnumeratorCallback)(JSVM_Env env, 202 JSVM_Value thisArg, 203 JSVM_Value namedPropertyData); 204 JSVM_Value(JSVM_CDECL* genericIndexedPropertyGetterCallback)(JSVM_Env env, 205 JSVM_Value index, 206 JSVM_Value thisArg, 207 JSVM_Value indexedPropertyData); 208 JSVM_Value(JSVM_CDECL* genericIndexedPropertySetterCallback)(JSVM_Env env, 209 JSVM_Value index, 210 JSVM_Value property, 211 JSVM_Value thisArg, 212 JSVM_Value indexedPropertyData); 213 JSVM_Value(JSVM_CDECL* genericIndexedPropertyDeleterCallback)(JSVM_Env env, 214 JSVM_Value index, 215 JSVM_Value thisArg, 216 JSVM_Value indexedPropertyData); 217 JSVM_Value(JSVM_CDECL* genericIndexedPropertyEnumeratorCallback)(JSVM_Env env, 218 JSVM_Value thisArg, 219 JSVM_Value indexedPropertyData); 220 JSVM_Value namedPropertyData; 221 JSVM_Value indexedPropertyData; 222} JSVM_PropertyHandlerConfigurationStruct; 223``` 224 225**JSVM_PropertyHandlerCfg** 226 227Pointer to the struct that contains a callback for property listening. 228 229The usage is as follows: 230 231```c++ 232typedef JSVM_PropertyHandlerConfigurationStruct* JSVM_PropertyHandlerCfg; 233``` 234 235## APIs 236 237JSVM-API provides capabilities of the standard JS engine. JSVM-API can be dynamically linked to JS engine libraries of different versions to shield the differences between engine interfaces. JSVM-API provides capabilities, such as VM lifecycle management, JS context management, JS code execution, JS/C++ interaction, context snapshot management, and code caching. Read on the following for details. 238 239### Creating a VM Instance and JS Context 240 241#### When to Use 242 243Before executing JS code, you need to create a JS VM and JS context. 244 245#### Available APIs 246| API| Description| 247| -------- | -------- | 248| OH_JSVM_Init| Initializes a JS engine instance.| 249| OH_JSVM_CreateVM| Creates a JS VM instance.| 250| OH_JSVM_DestroyVM| Destroys a JS VM instance.| 251| OH_JSVM_OpenVMScope| Opens a VM scope. The VM instance can be used only within the scope and will not be garbage-collected until the scope is closed.| 252| OH_JSVM_CloseVMScope| Closes a VM scope.| 253| OH_JSVM_CreateEnv| Creates a JS context and registers the specified native function.| 254| OH_JSVM_DestroyEnv| Destroys a JS context.| 255| OH_JSVM_OpenEnvScope| Opens a JS context scope. The context can be used only within the scope.| 256| OH_JSVM_CloseEnvScope| Closes a JS context scope.| 257| OH_JSVM_OpenHandleScope| Opens a handle scope. **JSVM_Value** within the scope will not be garbage-collected.| 258| OH_JSVM_CloseHandleScope| Close a handle scope.| 259 260Example: 261Create a JS VM instance and then destroy it. 262 263```c++ 264bool VM_INIT = false; 265 266static JSVM_Value ConsoleInfo(JSVM_Env env, JSVM_CallbackInfo info) { 267 size_t argc = 1; 268 JSVM_Value args[1]; 269 char log[256] = ""; 270 size_t logLength; 271 OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL); 272 273 OH_JSVM_GetValueStringUtf8(env, args[0], log, 255, &logLength); 274 log[255] = 0; 275 OH_LOG_INFO(LOG_APP, "JSVM API TEST: %{public}s", log); 276 return nullptr; 277} 278 279static JSVM_Value Add(JSVM_Env env, JSVM_CallbackInfo info) { 280 size_t argc = 2; 281 JSVM_Value args[2]; 282 OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL); 283 double num1, num2; 284 env, OH_JSVM_GetValueDouble(env, args[0], &num1); 285 OH_JSVM_GetValueDouble(env, args[1], &num2); 286 JSVM_Value sum = nullptr; 287 OH_JSVM_CreateDouble(env, num1 + num2, &sum); 288 return sum; 289} 290 291static napi_value MyJSVMDemo([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) { 292 std::thread t([]() { 293 if (!VM_INIT) { 294 // The JSVM only needs to be initialized once. 295 JSVM_InitOptions initOptions; 296 memset(&initOptions, 0, sizeof(initOptions)); 297 OH_JSVM_Init(&initOptions); 298 VM_INIT = true; 299 } 300 // Create a VM instance and open the VM scope. 301 JSVM_VM vm; 302 JSVM_CreateVMOptions options; 303 memset(&options, 0, sizeof(options)); 304 OH_JSVM_CreateVM(&options, &vm); 305 306 JSVM_VMScope vmScope; 307 OH_JSVM_OpenVMScope(vm, &vmScope); 308 309 JSVM_CallbackStruct param[] = { 310 {.data = nullptr, .callback = ConsoleInfo}, 311 {.data = nullptr, .callback = Add}, 312 }; 313 JSVM_PropertyDescriptor descriptor[] = { 314 {"consoleinfo", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 315 {"add", NULL, ¶m[1], NULL, NULL, NULL, JSVM_DEFAULT}, 316 }; 317 // Create env, register a native method, and open an env scope. 318 JSVM_Env env; 319 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 320 321 JSVM_EnvScope envScope; 322 OH_JSVM_OpenEnvScope(env, &envScope); 323 324 // Open a handle scope. 325 JSVM_HandleScope handleScope; 326 OH_JSVM_OpenHandleScope(env, &handleScope); 327 328 std::string sourceCodeStr = "\ 329{\ 330let value = add(4.96, 5.28);\ 331consoleinfo('Result is:' + value);\ 332}\ 333"; 334 // Compile the JS script. 335 JSVM_Value sourceCodeValue; 336 OH_JSVM_CreateStringUtf8(env, sourceCodeStr.c_str(), sourceCodeStr.size(), &sourceCodeValue); 337 JSVM_Script script; 338 OH_JSVM_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script); 339 JSVM_Value result; 340 // Run the JS script. 341 OH_JSVM_RunScript(env, script, &result); 342 JSVM_ValueType type; 343 OH_JSVM_Typeof(env, result, &type); 344 OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type); 345 346 // Exit the VM and release the memory. 347 OH_JSVM_CloseHandleScope(env, handleScope); 348 349 OH_JSVM_CloseEnvScope(env, envScope); 350 OH_JSVM_DestroyEnv(env); 351 352 OH_JSVM_CloseVMScope(vm, vmScope); 353 OH_JSVM_DestroyVM(vm); 354 }); 355 356 t.detach(); 357 358 return nullptr; 359} 360``` 361 362### Compiling and Running JS Code 363 364#### When to Use 365 366Compile and run JS code. 367 368#### Available APIs 369| API| Description| 370| -------- | -------- | 371| OH_JSVM_CompileScript| Compiles JS code and returns the compiled script bound to the current environment.| 372| OH_JSVM_CreateCodeCache| Creates a code cache for the compiled script.| 373| OH_JSVM_RunScript| Runs a JS script.| 374 375Example: 376Compile and run JS code (create a VM, register native functions, execute JS code, and destroy the VM). 377 378```c++ 379#include <cstring> 380#include <fstream> 381#include <string> 382#include <vector> 383 384// Add the dependency libjsvm.so. 385#include "ark_runtime/jsvm.h" 386 387using namespace std; 388 389static JSVM_Value Hello(JSVM_Env env, JSVM_CallbackInfo info) { 390 JSVM_Value output; 391 void* data = nullptr; 392 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data); 393 OH_JSVM_CreateStringUtf8(env, (char*)data, strlen((char*)data), &output); 394 return output; 395} 396 397static JSVM_CallbackStruct hello_cb = { Hello, (void*)"Hello" }; 398 399static string srcGlobal = R"JS( 400const concat = (...args) => args.reduce((a, b) => a + b); 401)JS"; 402 403static void RunScript(JSVM_Env env, string& src, 404 const uint8_t** dataPtr = nullptr, 405 size_t* lengthPtr = nullptr) { 406 JSVM_HandleScope handleScope; 407 OH_JSVM_OpenHandleScope(env, &handleScope); 408 409 JSVM_Value jsSrc; 410 OH_JSVM_CreateStringUtf8(env, src.c_str(), src.size(), &jsSrc); 411 412 const uint8_t* data = dataPtr ? *dataPtr : nullptr; 413 size_t length = lengthPtr ? *lengthPtr : 0; 414 bool cacheRejected = true; 415 JSVM_Script script; 416 // Compile the JS code. 417 OH_JSVM_CompileScript(env, jsSrc, data, length, true, &cacheRejected, &script); 418 printf("Code cache is %s\n", cacheRejected ? "rejected" : "used"); 419 420 JSVM_Value result; 421 // Run the JS code. 422 OH_JSVM_RunScript(env, script, &result); 423 424 char resultStr[128]; 425 size_t size; 426 OH_JSVM_GetValueStringUtf8(env, result, resultStr, 128, &size); 427 printf("%s\n", resultStr); 428 if (dataPtr && lengthPtr && *dataPtr == nullptr) { 429 // Save the script compiled from the JS source code to the cache to avoid repeated compilation and improve performance. 430 OH_JSVM_CreateCodeCache(env, script, dataPtr, lengthPtr); 431 printf("Code cache created with length = %ld\n", *lengthPtr); 432 } 433 434 OH_JSVM_CloseHandleScope(env, handleScope); 435} 436 437static void CreateSnapshot() { 438 JSVM_VM vm; 439 JSVM_CreateVMOptions options; 440 memset(&options, 0, sizeof(options)); 441 options.isForSnapshotting = true; 442 OH_JSVM_CreateVM(&options, &vm); 443 JSVM_VMScope vmScope; 444 OH_JSVM_OpenVMScope(vm, &vmScope); 445 446 JSVM_Env env; 447 // Register the native function as a method that can be called by a JS API. hello_cb holds the pointer and parameters of the native function. 448 JSVM_PropertyDescriptor descriptors[] = { 449 { "hello", NULL, &hello_cb, NULL, NULL, NULL, JSVM_DEFAULT } 450 }; 451 OH_JSVM_CreateEnv(vm, 1, descriptors, &env); 452 453 JSVM_EnvScope envScope; 454 OH_JSVM_OpenEnvScope(env, &envScope); 455 // Execute the JS source code src, which can contain any JS syntax. The registered native function can also be invoked. 456 string src = srcGlobal + "concat(hello(), ', ', 'World from CreateSnapshot!');"; 457 RunScript(env, src); 458 459 // Create a snapshot and save the current env to a string. The string can be used to restore the env to avoid repeatedly defining the properties in the env. 460 const char* blobData = nullptr; 461 size_t blobSize = 0; 462 JSVM_Env envs[1] = { env }; 463 OH_JSVM_CreateSnapshot(vm, 1, envs, &blobData, &blobSize); 464 printf("Snapshot blob size = %ld\n", blobSize); 465 466 // If you need to save the snapshot to a file, also consider the read/write permissions on the file in the application. 467 ofstream file("/data/storage/el2/base/files/blob.bin", ios::out | ios::binary | ios::trunc); 468 file.write(blobData, blobSize); 469 file.close(); 470 471 OH_JSVM_CloseEnvScope(env, envScope); 472 OH_JSVM_DestroyEnv(env); 473 OH_JSVM_CloseVMScope(vm, vmScope); 474 OH_JSVM_DestroyVM(vm); 475} 476 477void RunWithoutSnapshot(const uint8_t** dataPtr, size_t* lengthPtr) { 478 // Create a VM instance. 479 JSVM_VM vm; 480 OH_JSVM_CreateVM(nullptr, &vm); 481 JSVM_VMScope vmScope; 482 OH_JSVM_OpenVMScope(vm, &vmScope); 483 484 JSVM_Env env; 485 // Register the native function as a method that can be called by a JS API. hello_cb holds the pointer and parameters of the native function. 486 JSVM_PropertyDescriptor descriptors[] = { 487 { "hello", NULL, &hello_cb, NULL, NULL, NULL, JSVM_DEFAULT } 488 }; 489 OH_JSVM_CreateEnv(vm, 1, descriptors, &env); 490 JSVM_EnvScope envScope; 491 OH_JSVM_OpenEnvScope(env, &envScope); 492 // Execute the JS source code src, which can contain any JS syntax. The registered native function can also be invoked. 493 auto src = srcGlobal + "concat(hello(), ', ', 'World', ' from RunWithoutSnapshot!')"; 494 RunScript(env, src, dataPtr, lengthPtr); 495 496 OH_JSVM_CloseEnvScope(env, envScope); 497 OH_JSVM_DestroyEnv(env); 498 OH_JSVM_CloseVMScope(vm, vmScope); 499 OH_JSVM_DestroyVM(vm); 500} 501 502void RunWithSnapshot(const uint8_t **dataPtr, size_t *lengthPtr) { 503 // The lifetime of blobData must not be shorter than that of the vm. 504 // If the snapshot needs to be read from a file, also consider the read/write permissions on the file in the application. 505 vector<char> blobData; 506 ifstream file("/data/storage/el2/base/files/blob.bin", ios::in | ios::binary | ios::ate); 507 size_t blobSize = file.tellg(); 508 blobData.resize(blobSize); 509 file.seekg(0, ios::beg); 510 file.read(blobData.data(), blobSize); 511 file.close(); 512 513 // Create a VM instance. 514 JSVM_VM vm; 515 JSVM_CreateVMOptions options; 516 memset(&options, 0, sizeof(options)); 517 options.snapshotBlobData = blobData.data(); 518 options.snapshotBlobSize = blobSize; 519 OH_JSVM_CreateVM(&options, &vm); 520 JSVM_VMScope vmScope; 521 OH_JSVM_OpenVMScope(vm, &vmScope); 522 523 // Create env from a snapshot. 524 JSVM_Env env; 525 OH_JSVM_CreateEnvFromSnapshot(vm, 0, &env); 526 JSVM_EnvScope envScope; 527 OH_JSVM_OpenEnvScope(env, &envScope); 528 529 // Run the JS script. Because the snapshot contains hello() defined in env, you do not need to redefine hello(). If dataPtr contains the compiled JS script, the JS script can be directly executed, which avoids repeated compilation from the source code. 530 string src = "concat(hello(), ', ', 'World', ' from RunWithSnapshot!')"; 531 RunScript(env, src, dataPtr, lengthPtr); 532 533 OH_JSVM_CloseEnvScope(env, envScope); 534 OH_JSVM_DestroyEnv(env); 535 OH_JSVM_CloseVMScope(vm, vmScope); 536 OH_JSVM_DestroyVM(vm); 537} 538 539void PrintVmInfo() { 540 JSVM_VMInfo vmInfo; 541 OH_JSVM_GetVMInfo(&vmInfo); 542 printf("apiVersion: %d\n", vmInfo.apiVersion); 543 printf("engine: %s\n", vmInfo.engine); 544 printf("version: %s\n", vmInfo.version); 545 printf("cachedDataVersionTag: 0x%x\n", vmInfo.cachedDataVersionTag); 546} 547 548static intptr_t externals[] = { 549 (intptr_t)&hello_cb, 550 0, 551}; 552 553int main(int argc, char *argv[]) { 554 if (argc <= 1) { 555 printf("Usage: %s gen-snapshot|use-snapshot|no-snapshot\n", argv[0]); 556 return 0; 557 } 558 559 JSVM_InitOptions initOptions; 560 memset(&initOptions, 0, sizeof(initOptions)); 561 initOptions.externalReferences = externals; 562 // Initialize the VM, which can be initialized only once in a process. 563 OH_JSVM_Init(&initOptions); 564 PrintVmInfo(); 565 566 if (argv[1] == string("gen-snapshot")) { 567 CreateSnapshot(); 568 return 0; 569 } 570 571 // The snapshot records the JS context at a certain time and can be used to quickly restore JS context across processes as long as the snapshot is within the lifecycle. 572 const auto useSnapshot = argv[1] == string("use-snapshot"); 573 const auto run = useSnapshot ? RunWithSnapshot : RunWithoutSnapshot; 574 const uint8_t* data = nullptr; 575 size_t length = 0; 576 run(&data, &length); 577 run(&data, &length); 578 delete[] data; 579 580 return 0; 581} 582``` 583 584### Exception Handling 585 586#### When to Use 587 588Capture, throw, and clear JS exceptions as required. 589 590#### Available APIs 591| API| Description| 592| -------- | -------- | 593| OH_JSVM_Throw| Throws a JS value.| 594| OH_JSVM_ThrowTypeError| Throws a JS type error.| 595| OH_JSVM_ThrowRangeError| Throws a JS range error.| 596| OH_JSVM_IsError| Checks whether a JS value indicates an error.| 597| OH_JSVM_CreateError| Creates a JS error.| 598| OH_JSVM_CreateTypeError| Creates a JS type error and returns it.| 599| OH_JSVM_CreateRangeError| Creates a JS range error and returns it.| 600| OH_JSVM_ThrowError| Throws a JS exception.| 601| OH_JSVM_GetAndClearLastException| Obtains and clears the last JS exception.| 602| OH_JSVM_IsExceptionPending| Checks whether an exception occurs.| 603| OH_JSVM_GetLastErrorInfo| Obtains information about the last exception.| 604| OH_JSVM_ThrowSyntaxError| Throws a JS syntax error.| 605| OH_JSVM_CreateSyntaxError| Creates a JS syntax error and returns it.| 606 607Example: 608The following walks you through on how to Create, judge, and throw a JS type error. 609 610```c++ 611JSVM_Value code = nullptr; 612JSVM_Value message = nullptr; 613OH_JSVM_CreateStringUtf8(env, "500", JSVM_AUTO_LENGTH, &code); 614OH_JSVM_CreateStringUtf8(env, "type error 500", JSVM_AUTO_LENGTH, &message); 615JSVM_Value error = nullptr; 616OH_JSVM_CreateTypeError(env, code, message, &error); 617bool isError = false; 618OH_JSVM_IsError(env, error, &isError); 619OH_JSVM_ThrowTypeError(env, nullptr, "type error1"); 620``` 621 622Call OH_JSVM_GetAndClearLastException to log the exception information as a string to the console. 623 624```c++ 625if (status != JSVM_OK) // An exception occurs when the execution fails. 626{ 627 bool isPending = false; 628 if (JSVM_OK == OH_JSVM_IsExceptionPending((env), &isPending) && isPending) 629 { 630 JSVM_Value error; 631 if (JSVM_OK == OH_JSVM_GetAndClearLastException((env), &error)) 632 { 633 // Obtain the exception stack. 634 JSVM_Value stack; 635 OH_JSVM_GetNamedProperty((env), error, "stack", &stack); 636 637 JSVM_Value message; 638 OH_JSVM_GetNamedProperty((env), error, "message", &message); 639 640 char stackstr[256]; 641 OH_JSVM_GetValueStringUtf8(env, stack, stackstr, 256, nullptr); 642 OH_LOG_INFO(LOG_APP, "JSVM error stack: %{public}s", stackstr); 643 644 char messagestr[256]; 645 OH_JSVM_GetValueStringUtf8(env, message, messagestr, 256, nullptr); 646 OH_LOG_INFO(LOG_APP, "JSVM error message: %{public}s", messagestr); 647 } 648 } 649} 650``` 651 652### Object Lifetime Management 653 654When JSVM-API calls are made, handles to objects in the heap for the underlying VM may be returned as **JSVM_Value**s. These handles must hold the objects live until they are no longer required by the native code. Otherwise, the objects will be collected. 655 656 When an object handle is returned, it is associated with a scope. The lifecycle of the default scope is tied to the lifecycle of the native method call. By default, a handle remains valid and the object associated with it will be held live for the lifecycle of the native method call. 657 658However, in many cases, you may need to adjust the lifecycle to be shorter or longer than that of the native method. The following describes the JSVM-API methods that can be used to change the lifecycle of a handle. 659 660#### Available APIs 661| API| Description| 662| -------- | -------- | 663| OH_JSVM_OpenHandleScope| Opens a handle scope. The object within the scope will not be garbage-collected until the handle scope is closed.| 664| OH_JSVM_CloseHandleScope| Closes a handle scope. The object within the scope will be garbage-collected after the handle scope is closed.| 665| OH_JSVM_OpenEscapableHandleScope| Opens an escapable handle scope. Before this scope is closed, the object created within the scope has the same lifecycle as its parent scope.| 666| OH_JSVM_CloseEscapableHandleScope| Closes an escapable handle scope.| 667| OH_JSVM_EscapeHandle| Promotes a handle to a JS object so that it is valid for the lifetime of the outer scope.| 668| OH_JSVM_CreateReference| Creates a new reference with the specified reference count to the value passed in. The reference allows objects to be used and shared in different contexts and effectively tracks the lifecycle of the object.| 669| OH_JSVM_DeleteReference| Release the reference created by **OH_JSVM_CreateReference**. This allows objects to be correctly released and reclaimed when they are no longer required, avoiding memory leaks.| 670| OH_JSVM_ReferenceRef| Increments the reference count of the reference created by **OH_JSVM_CreateReference** so that the object referenced will not be released.| 671| OH_JSVM_ReferenceUnref| Decrements the reference count of the reference created by **OH_JSVM_CreateReference** so that the object can be correctly released and reclaimed when it is not referenced.| 672| OH_JSVM_GetReferenceValue| Obtains the object referenced by **OH_JSVM_CreateReference**.| 673 674Example: 675Use a handle scope to protect an object created within the scope from being reclaimed. 676 677```c++ 678JSVM_HandleScope scope; 679OH_JSVM_OpenHandleScope(env, &scope); 680JSVM_Value obj = nullptr; 681OH_JSVM_CreateObject(env, &obj); 682OH_JSVM_CloseHandleScope(env, scope); 683``` 684 685Use an escapable handle scope to protect an object from being reclaimed within its parent scope. 686 687```c++ 688JSVM_EscapableHandleScope scope; 689JSVM_CALL(env, OH_JSVM_OpenEscapableHandleScope(env, &scope)); 690JSVM_Value output = NULL; 691JSVM_Value escapee = NULL; 692JSVM_CALL(env, OH_JSVM_CreateObject(env, &output)); 693JSVM_CALL(env, OH_JSVM_EscapeHandle(env, scope, output, &escapee)); 694JSVM_CALL(env, OH_JSVM_CloseEscapableHandleScope(env, scope)); 695return escapee; 696``` 697 698Reference a JS object and release the reference. 699 700```c++ 701JSVM_Value obj = nullptr; 702OH_JSVM_CreateObject(env, &obj); 703// Create a reference. 704JSVM_Ref reference; 705OH_JSVM_CreateReference(env, obj, 1, &reference); 706 707// Create a reference with a JS object. 708JSVM_Value result; 709OH_JSVM_GetReferenceValue(env, reference, &result); 710 711// Release the reference. 712OH_JSVM_DeleteReference(env, reference); 713``` 714 715### Creating JS Object Types and Basic Types 716 717#### When to Use 718 719Create JS object types and basic types. 720 721#### Available APIs 722| API| Description| 723| -------- | -------- | 724|OH_JSVM_CreateArray | Creates a JS array object.| 725|OH_JSVM_CreateArrayWithLength | Creates a JS array object of the specified length.| 726|OH_JSVM_CreateArraybuffer | Creates an ArrayBuffer object of the specified size.| 727|OH_JSVM_CreateDate | Creates a **Date** object representing the given number of milliseconds. | 728|OH_JSVM_CreateExternal | Creates a JS object that wraps an external pointer.| 729|OH_JSVM_CreateExternalArraybuffer | Creates a JS object that wraps an external Arraybuffer.| 730|OH_JSVM_CreateObject | Creates a default JS object.| 731|OH_JSVM_CreateSymbol | Creates a symbol object based on the given descriptor.| 732|OH_JSVM_SymbolFor | Searches for a symbol with the given key in a global (runtime-wide) symbol registry. If a match is found, the symbol will be returned. Otherwise, a symbol will be created in the registry.| 733|OH_JSVM_CreateTypedarray | Creates a JS TypedArray object for an ArrayBuffer. The TypedArray object provides an array-like view over an underlying data buffer, where each element has the same underlying binary scalar data type.| 734|OH_JSVM_CreateDataview | Creates a JS DataView object for an ArrayBuffer. The DataView object provides an array-like view of over an underlying data buffer.| 735|OH_JSVM_CreateInt32 | Creates a JS number object from a C Int32_t object.| 736|OH_JSVM_CreateUint32 | Creates a JS number object from a C Uint32_t object.| 737|OH_JSVM_CreateInt64 | Creates a JS number object from a C Int64_t object.| 738|OH_JSVM_CreateDouble | Creates a JS number object from a C Double object.| 739|OH_JSVM_CreateBigintInt64 | Creates a JS BigInt object from a C Int64 object.| 740|OH_JSVM_CreateBigintUint64 | Creates a JS BigInt object from a C Uint64 object.| 741|OH_JSVM_CreateBigintWords | Creates a JS BigInt object from a C Uint64_t array.| 742|OH_JSVM_CreateStringLatin1 | Creates a JS string object from an ISO-8859-1-encoded C string. ISO-8859-1 is also referred to as Latin-1.| 743|OH_JSVM_CreateStringUtf16 | Creates a JS string object from a UTF16-encoded C string.| 744|OH_JSVM_CreateStringUtf8 | Creates a JS string object from a UTF8-encoded C string.| 745 746Example: 747Create a JS array of the specified length. 748 749```c++ 750size_t arrayLength = 2; 751JSVM_Value arr; 752 753OH_JSVM_CreateArrayWithLength(env, arrayLength, &arr); 754for (uint32_t i = 0; i < arrayLength; i++) 755{ 756 JSVM_Value element; 757 OH_JSVM_CreateUint32(env, i * 2, &element); 758 OH_JSVM_SetElement(env, arr, i, element); 759} 760``` 761 762Create a JS Int32Array. 763 764```c++ 765JSVM_Value arrayBuffer = nullptr; 766void *arrayBufferPtr = nullptr; 767size_t arrayBufferSize = 16; 768size_t typedArrayLength = 4; 769OH_JSVM_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer); 770 771void *tmpArrayBufferPtr = nullptr; 772size_t arrayBufferLength = 0; 773OH_JSVM_GetArraybufferInfo(env, arrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength); 774 775JSVM_Value result; 776OH_JSVM_CreateTypedarray(env, JSVM_TypedarrayType::JSVM_INT32_ARRAY, typedArrayLength, arrayBuffer, 0, &result); 777return result; 778``` 779 780Create JS numbers and strings. 781 782```c++ 783const char *testStringStr = "test"; 784JSVM_Value testString = nullptr; 785OH_JSVM_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString); 786 787JSVM_Value testNumber1 = nullptr; 788JSVM_Value testNumber2 = nullptr; 789OH_JSVM_CreateDouble(env, 10.1, &testNumber1); 790OH_JSVM_CreateInt32(env, 10, &testNumber2); 791``` 792 793### Obtaining C Types or JS Type Information from JS Types 794 795#### When to Use 796 797Obtaining C types or JS type information from JS types. 798 799#### Available APIs 800| API| Description| 801| -------- | -------- | 802|OH_JSVM_GetArrayLength | Obtains the length of an array.| 803|OH_JSVM_GetArraybufferInfo | Obtains the underlying data buffer of an ArrayBuffer and its length.| 804|OH_JSVM_GetPrototype | Obtains the prototype of a JS object.| 805|OH_JSVM_GetTypedarrayInfo | Obtains information about a TypedArray object.| 806|OH_JSVM_GetDataviewInfo | Obtains information about a DataView object.| 807|OH_JSVM_GetDateValue | Obtains the C double primitive of the time value for the given JS **Date** object.| 808|OH_JSVM_GetValueBool | Obtains the C Boolean primitive equivalent of the given JS Boolean.| 809|OH_JSVM_GetValueDouble | Obtains the C Double primitive equivalent of the given JS number.| 810|OH_JSVM_GetValueBigintInt64 | Obtains the C Int64_t primitive equivalent of the given JS BigInt.| 811|OH_JSVM_GetValueBigintUint64 | Obtains the C Uint64_t primitive equivalent of the given JS BigInt.| 812|OH_JSVM_GetValueBigintWords | Obtains the underlying data of a given JS BigInt object, that is, the word representation of BigInt data.| 813|OH_JSVM_GetValueExternal | Obtains the external data pointer previously passed to **OH_JSVM_CreateExternal**.| 814|OH_JSVM_GetValueInt32 | Obtains the C Int32 primitive equivalent of the given JS number.| 815|OH_JSVM_GetValueInt64 | Obtains the C Int64 primitive equivalent of the given JS number.| 816|OH_JSVM_GetValueStringLatin1 | Obtains the ISO-8859-1-encoded string from the given JS string.| 817|OH_JSVM_GetValueStringUtf8 | Obtains the UTF8-encoded string from the given JS string.| 818|OH_JSVM_GetValueStringUtf16 | Obtains the UTF16-encoded string from the given JS string.| 819|OH_JSVM_GetValueUint32 | Obtains the C primitive equivalent (a Uint32) of the given JS number.| 820|OH_JSVM_GetBoolean | Obtains a JS singleton object that is used to represent the given Boolean value.| 821|OH_JSVM_GetGlobal | Obtains the **global** object of the current environment.| 822|OH_JSVM_GetNull | Obtains the JS **null** object.| 823|OH_JSVM_GetUndefined | Obtains the JS **Undefined** object.| 824 825Example: 826Creates a JS BigInt object from a C Int64 object and obtain the C Int64_t primitive equivalent. 827 828```c++ 829int64_t testValue = INT64_MAX; 830JSVM_Value result = nullptr; 831OH_JSVM_CreateBigintInt64(env, testValue, &result); 832int64_t resultValue = 0; 833bool flag = false; 834OH_JSVM_GetValueBigintInt64(env, result, &resultValue, &flag); 835``` 836 837Create an Int32Array and obtain its information such as the length and byte offset. 838 839```c++ 840JSVM_Value arrayBuffer = nullptr; 841void *arrayBufferPtr = nullptr; 842size_t arrayBufferSize = 16; 843size_t typedArrayLength = 4; 844OH_JSVM_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer); 845 846bool isArrayBuffer = false; 847OH_JSVM_IsArraybuffer(env, arrayBuffer, &isArrayBuffer); 848 849JSVM_Value result; 850OH_JSVM_CreateTypedarray(env, JSVM_TypedarrayType::JSVM_INT32_ARRAY, typedArrayLength, arrayBuffer, 0, &result); 851 852bool isTypedArray = false; 853OH_JSVM_IsTypedarray(env, result, &isTypedArray); 854 855 856JSVM_TypedarrayType type; 857size_t length = 0; 858void *data = nullptr; 859JSVM_Value retArrayBuffer; 860size_t byteOffset = -1; 861OH_JSVM_GetTypedarrayInfo(env, result, &type, &length, &data, &retArrayBuffer, &byteOffset); 862 863 864bool retIsArrayBuffer = false; 865OH_JSVM_IsArraybuffer(env, retArrayBuffer, &retIsArrayBuffer); 866void *tmpArrayBufferPtr = nullptr; 867size_t arrayBufferLength = 0; 868OH_JSVM_GetArraybufferInfo(env, retArrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength); 869``` 870 871Creates a JS string object from a UTF8-encoded C string and obtain the C string. 872 873```c++ 874const char *testStringStr = "testString"; 875JSVM_Value testString = nullptr; 876OH_JSVM_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString); 877 878char buffer[128]; 879size_t bufferSize = 128; 880size_t copied; 881 882OH_JSVM_GetValueStringUtf8(env, testString, buffer, bufferSize, &copied); 883``` 884 885### Working with JS Values and Abstract Operations 886 887#### When to Use 888 889Perform abstract operations on JS values. 890 891#### Available APIs 892| API| Description| 893| -------- | -------- | 894|OH_JSVM_CoerceToBool | Converts a JS value to an object of the Boolean type.| 895|OH_JSVM_CoerceToNumber | Converts a JS value to an object of the number type.| 896|OH_JSVM_CoerceToObject | Converts a JS value to an object of the object type.| 897|OH_JSVM_CoerceToString | Converts a JS value to an object of the string type.| 898|OH_JSVM_Typeof | Returns the type of a JS object.| 899|OH_JSVM_Instanceof | Checks whether an object is an instance of a constructor.| 900|OH_JSVM_IsArray | Checks whether a JS object is an array.| 901|OH_JSVM_IsArraybuffer | Checks whether a JS object is an array buffer.| 902|OH_JSVM_IsDate | Checks whether a JS object is a date.| 903|OH_JSVM_IsTypedarray | Checks whether a JS object is a typed array.| 904|OH_JSVM_IsDataview | Checks whether a JS object is a **DataView**.| 905|OH_JSVM_IsUndefined | Checks whether the value passed in is **Undefined**. This API is equivalent to executing JS code **value === undefined**.| 906|OH_JSVM_IsNull | Checks whether the value passed in is a **Null** object. This API is equivalent to executing JS code **value === null**.| 907|OH_JSVM_IsNullOrUndefined | Checks whether the value passed in is **Null** or **Undefined**. This API is equivalent to executing JS code **value == null**.| 908|OH_JSVM_IsBoolean | Checks whether the value passed in is a Boolean value. This API is equivalent to executing JS code **typeof value ==='boolean'**.| 909|OH_JSVM_IsNumber | Checks whether the value passed in is a number. This API is equivalent to executing JS code **typeof value === 'number'**.| 910|OH_JSVM_IsString | Checks whether the value passed in is a string. This API is equivalent to executing JS code **typeof value === 'string'**.| 911|OH_JSVM_IsSymbol | Checks whether the value passed in is a symbol. This API is equivalent to executing JS code **typeof value === 'symbol'**.| 912|OH_JSVM_IsFunction | Checks whether the value passed in is a function. This API is equivalent to executing JS code **typeof value === 'function'**.| 913|OH_JSVM_IsObject | Checks whether the value passed in is an object .| 914|OH_JSVM_IsBigInt | Checks whether the value passed in is a BigInt. This API is equivalent to executing JS code **typeof value === 'bigint'**.| 915|OH_JSVM_StrictEquals | Checks whether two **JSVM_Value** objects are strictly equal.| 916|OH_JSVM_Equals | Checks whether two **JSVM_Value** objects are roughly equal.| 917|OH_JSVM_DetachArraybuffer | Calls the **Detach()** operation of an **ArrayBuffer** object.| 918|OH_JSVM_IsDetachedArraybuffer | Checks whether an **ArrayBuffer** object has been detached.| 919 920Example: 921Check whether a JS value is of the array type. 922 923```c++ 924JSVM_Value array = nullptr; 925OH_JSVM_CreateArray(env, &array); 926bool isArray = false; 927OH_JSVM_IsArray(env, array, &isArray); 928``` 929 930Converts a JS int32 value to a string. 931 932```c++ 933int32_t num = 123; 934JSVM_Value intValue; 935OH_JSVM_CreateInt32(env, num, &intValue); 936JSVM_Value stringValue; 937OH_JSVM_CoerceToString(env, intValue, &stringValue); 938 939char buffer[128]; 940size_t bufferSize = 128; 941size_t copied = 0; 942 943OH_JSVM_GetValueStringUtf8(env, stringValue, buffer, bufferSize, &copied); 944// buffer:"123"; 945``` 946 947Check whether two JS values are strictly equal as follows: Compare the operand types first. If the operand types are different, the values are different. If the operand types are the same, compare the two values. If the values are the same, **true** is returned. 948 949```c++ 950JSVM_Value value = nullptr; 951JSVM_Value value1 = nullptr; 952OH_JSVM_CreateArray(env, &value); 953 954OH_JSVM_CreateInt32(env, 10, &value1); 955bool isArray = true; 956OH_JSVM_StrictEquals(env, value, value, &isArray); 957``` 958 959Check whether two JS values are roughly equal as follows: Compare the operand types first. If the operand types are different but can be converted to the same type, convert the operand types to the same type and check whether the values are strictly equal. If the values are the same, **true** is returned. **false** is returned other cases. 960 961```c++ 962JSVM_HandleScope handleScope; 963OH_JSVM_OpenHandleScope(env, &handleScope); 964const char testStr[] = "1"; 965JSVM_Value lhs = nullptr; 966OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &lhs); 967JSVM_Value rhs; 968OH_JSVM_CreateInt32(env, 1, &rhs); 969bool isEquals = false; 970OH_JSVM_Equals(env, lhs, rhs, &isEquals); // The value of isEquals is true. 971OH_JSVM_CloseHandleScope(env, handleScope); 972``` 973 974### Working with JS Properties 975 976#### When to Use 977 978Set, get, delete, and check properties of JS objects. 979 980#### Available APIs 981| API| Description| 982| -------- | -------- | 983|OH_JSVM_GetPropertyNames | Obtains the names of all enumerable properties of a JS object as a JS array.| 984|OH_JSVM_GetAllPropertyNames | Obtains the names of all available properties of a JS object as a JS array.| 985|OH_JSVM_SetProperty | Sets a property for a JS object.| 986|OH_JSVM_GetProperty | Obtains the requested property from a JS object.| 987|OH_JSVM_HasProperty | Checks whether a JS object has the named property.| 988|OH_JSVM_DeleteProperty | Deletes a property from a JS object.| 989|OH_JSVM_HasOwnProperty | Checks whether a JS object has the named own property.| 990|OH_JSVM_SetNamedProperty | Sets a property with the given property name for a JS object. This API is equivalent to calling **OH_JSVM_SetNamedProperty** with a **JSVM_Value** created from the string passed in as **utf8Name**.| 991|OH_JSVM_GetNamedProperty | Obtains the property from a JS object with the given property name. This API is equivalent to calling **OH_JSVM_GetNamedProperty** with a **JSVM_Value** created from the string passed in as **utf8Name**.| 992|OH_JSVM_HasNamedProperty | Checks whether a JS object has the named property. This API is equivalent to calling **OH_JSVM_HasProperty** using a **JSVM_Value** created from the string passed in as **utf8Name**.| 993|OH_JSVM_SetElement | Sets an element at the specified index for a JS object.| 994|OH_JSVM_GetElement | Obtains the element at the specified index of a JS object.| 995|OH_JSVM_HasElement | Checks whether a JS object has an element at the specified index.| 996|OH_JSVM_DeleteElement | Deletes the element at the specified index from a JS object.| 997|OH_JSVM_DefineProperties | Defines multiple properties for a JS object.| 998|OH_JSVM_ObjectFreeze | Freezes a JS object. Once a JS object is frozen, new properties cannot be added to it, existing properties cannot be removed, the enumerability, configurability, or writability of existing properties cannot be changed, and the values of existing properties cannot be changed.| 999|OH_JSVM_ObjectSeal | Seals a JS object. Once a JS object is sealed, new properties cannot be added to it and all existing properties are marked as unconfigurable. | 1000 1001Example: 1002Set, get, delete, and check properties of a JS object. 1003 1004```c++ 1005// Create an empty object. 1006JSVM_Value myObject = nullptr; 1007OH_JSVM_CreateObject(env, &myObject); 1008 1009// Set properties. 1010const char *testNameStr = "John Doe"; 1011JSVM_Value propValue = nullptr; 1012JSVM_Value key; 1013OH_JSVM_CreateStringUtf8(env, "name", JSVM_AUTO_LENGTH, &key); 1014OH_JSVM_CreateStringUtf8(env, testNameStr, strlen(testNameStr), &propValue); 1015OH_JSVM_SetProperty(env, myObject, key, propValue); 1016 1017// Obtain properties. 1018JSVM_Value propResult = nullptr; 1019OH_JSVM_GetProperty(env, myObject, key, &propResult); 1020 1021// Check whether a property exists. 1022bool hasProperty = false; 1023OH_JSVM_HasNamedProperty(env, myObject, "name", &hasProperty); 1024 // The property exists. Perform subsequent processing accordingly. 1025 if (hasProperty) 1026 { 1027 // Obtain all property names of the object. 1028 JSVM_Value propNames = nullptr; 1029 OH_JSVM_GetPropertyNames(env, myObject, &propNames); 1030 1031 bool isArray = false; 1032 OH_JSVM_IsArray(env, propNames, &isArray); 1033 1034 uint32_t arrayLength = 0; 1035 OH_JSVM_GetArrayLength(env, propNames, &arrayLength); 1036 // Traverse property elements. 1037 for (uint32_t i = 0; i < arrayLength; i++) 1038 { 1039 bool hasElement = false; 1040 OH_JSVM_HasElement(env, propNames, i, &hasElement); 1041 1042 JSVM_Value propName = nullptr; 1043 OH_JSVM_GetElement(env, propNames, i, &propName); 1044 1045 bool hasProp = false; 1046 OH_JSVM_HasProperty(env, myObject, propName, &hasProp); 1047 1048 JSVM_Value propValue = nullptr; 1049 OH_JSVM_GetProperty(env, myObject, propName, &propValue); 1050 } 1051 } 1052 1053// Delete a property. 1054OH_JSVM_DeleteProperty(env, myObject, key, &hasProperty); 1055``` 1056 1057### Working with JS Functions 1058 1059#### When to Use 1060 1061Call back JS code into native code and call JS functions from native code. 1062 1063#### Available APIs 1064| API| Description| 1065| -------- | -------- | 1066|OH_JSVM_CallFunction | Calls a JS function from a C/C++ addon.| 1067|OH_JSVM_CreateFunction | Creates a JS function object in native code, which allows calling into the native code from JS.| 1068|OH_JSVM_GetCbInfo | Obtains detailed information about the call, such as the parameters and **this** pointer, from the given callback information.| 1069|OH_JSVM_GetNewTarget | Obtains the **new.target** of the constructor call.| 1070|OH_JSVM_NewInstance | Creates an instance based on the given constructor.| 1071 1072Example: 1073Create a JS function. 1074 1075```c++ 1076JSVM_Value SayHello(JSVM_Env env, JSVM_CallbackInfo info) 1077{ 1078 printf("Hello\n"); 1079 JSVM_Value ret; 1080 OH_JSVM_CreateInt32(env, 2, &ret); 1081 return ret; 1082} 1083 1084static JSVM_Value JsvmCreateFunction(JSVM_Env env, JSVM_CallbackInfo info) 1085{ 1086 JSVM_CallbackStruct param; 1087 param.data = nullptr; 1088 param.callback = SayHello; 1089 1090 JSVM_Value funcValue = nullptr; 1091 JSVM_Status status = OH_JSVM_CreateFunction(env, "func", JSVM_AUTO_LENGTH, ¶m, &funcValue); 1092 return funcValue; 1093} 1094``` 1095 1096Obtain and call the JS function from C/C++. 1097 1098```c++ 1099static JSVM_Value CallFunction(JSVM_Env env, JSVM_CallbackInfo info) 1100{ 1101 size_t argc = 1; 1102 JSVM_Value args[1]; 1103 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL)); 1104 1105 JSVM_ASSERT(env, argc >= 1, "Wrong number of arguments"); 1106 1107 JSVM_ValueType valuetype; 1108 JSVM_CALL(env, OH_JSVM_Typeof(env, args[0], &valuetype)); 1109 JSVM_ASSERT(env, valuetype == JSVM_ValueType::JSVM_FUNCTION, "Wrong type of argment. Expects a string."); 1110 1111 JSVM_Value global; 1112 JSVM_CALL(env, OH_JSVM_GetGlobal(env, &global)); 1113 1114 JSVM_Value ret; 1115 JSVM_CALL(env, OH_JSVM_CallFunction(env, global, args[0], 0, nullptr, &ret)); 1116 return ret; 1117} 1118``` 1119 1120### Wrapping Objects 1121 1122#### When to Use 1123 1124Wrap native classes and instances so that the class constructor and methods can be called from JS. 1125 1126#### Available APIs 1127| API| Description| 1128| -------- | -------- | 1129|OH_JSVM_DefineClass| Defines a JS class and associated functions within a C/C++ addon. It allows you to define class constructors, methods, and properties that can be accessed from JS.| 1130|OH_JSVM_Wrap| Wraps a native instance in a JS object. You can use **OH_JSVM_Unwrap()** to retrieve the native instance later.| 1131|OH_JSVM_Unwrap | Retrieves a native instance from a JS object.| 1132|OH_JSVM_RemoveWrap | Retrieves a native instance previously wrapped in a JS object and removes the wrapping.| 1133|OH_JSVM_TypeTagObject | Associates the value of the **type_tag** pointer with a JS object or an external object.| 1134|OH_JSVM_CheckObjectTypeTag | Checks whether a tag matches the tag type of an object.| 1135|OH_JSVM_AddFinalizer | Add a **JSVM_Finalize** callback to a JS object. The callback will be invoked to release the native object when the JS object is garbage-collected.| 1136|OH_JSVM_PostFinalizer | Schedules a **JSVM_Finalize** callback to be called asynchronously in the event loop.| 1137|OH_JSVM_DefineClassWithPropertyHandler | Defines a JS class with the given class name, constructor, properties, and callback hander. The property operations include **getter()**, **setter()**, **deleter()**, and **enumerator()** and are called via callbacks.| 1138 1139Example: 1140Wrap a native object in a JS object. 1141 1142```c++ 1143static JSVM_Value AssertEqual(JSVM_Env env, JSVM_CallbackInfo info) 1144{ 1145 size_t argc = 2; 1146 JSVM_Value args[2]; 1147 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL)); 1148 1149 bool isStrictEquals = false; 1150 OH_JSVM_StrictEquals(env, args[0], args[1], &isStrictEquals); 1151 return nullptr; 1152} 1153 1154static napi_value TestWrap(napi_env env1, napi_callback_info info) 1155{ 1156 OH_LOG_ERROR(LOG_APP, "testWrap start"); 1157 JSVM_InitOptions init_options; 1158 memset(&init_options, 0, sizeof(init_options)); 1159 init_options.externalReferences = externals; 1160 if (aa == 0) { 1161 OH_JSVM_Init(&init_options); 1162 aa++; 1163 } 1164 JSVM_VM vm; 1165 JSVM_CreateVMOptions options; 1166 memset(&options, 0, sizeof(options)); 1167 OH_JSVM_CreateVM(&options, &vm); 1168 JSVM_VMScope vm_scope; 1169 OH_JSVM_OpenVMScope(vm, &vm_scope); 1170 JSVM_Env env; 1171 JSVM_CallbackStruct param[1]; 1172 param[0].data = nullptr; 1173 param[0].callback = AssertEqual; 1174 JSVM_PropertyDescriptor descriptor[] = { 1175 {"assertEqual", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 1176 }; 1177 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 1178 JSVM_EnvScope envScope; 1179 OH_JSVM_OpenEnvScope(env, &envScope); 1180 JSVM_HandleScope handlescope; 1181 OH_JSVM_OpenHandleScope(env, &handlescope); 1182 JSVM_Value testClass = nullptr; 1183 JSVM_CallbackStruct param1; 1184 param1.data = nullptr; 1185 param1.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { 1186 JSVM_Value thisVar = nullptr; 1187 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr); 1188 1189 return thisVar; 1190 }; 1191 OH_JSVM_DefineClass(env, "TestClass", JSVM_AUTO_LENGTH, ¶m1, 0, nullptr, &testClass); 1192 1193 JSVM_Value instanceValue = nullptr; 1194 OH_JSVM_NewInstance(env, testClass, 0, nullptr, &instanceValue); 1195 1196 const char *testStr = "test"; 1197 OH_JSVM_Wrap( 1198 env, instanceValue, (void *)testStr, [](JSVM_Env env, void *data, void *hint) {}, nullptr, nullptr); 1199 const char *tmpTestStr = nullptr; 1200 OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr); 1201 const char *tmpTestStr1 = nullptr; 1202 OH_JSVM_RemoveWrap(env, instanceValue, (void **)&tmpTestStr1); 1203 OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr1); 1204 OH_JSVM_CloseHandleScope(env, handlescope); 1205 OH_JSVM_CloseEnvScope(env, envScope); 1206 OH_JSVM_DestroyEnv(env); 1207 OH_JSVM_CloseVMScope(vm, vm_scope); 1208 OH_JSVM_DestroyVM(vm); 1209 OH_LOG_ERROR(LOG_APP, "testWrap pass"); 1210 return nullptr; 1211} 1212``` 1213 1214Example: 1215Wrap a native object and register a listener for property access operations. 1216 1217```c++ 1218static int aa = 0; 1219static JSVM_Value hello(JSVM_Env env, JSVM_CallbackInfo info) { 1220 JSVM_Value output; 1221 void *data = nullptr; 1222 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data); 1223 OH_JSVM_CreateStringUtf8(env, (char *)data, strlen((char *)data), &output); 1224 return output; 1225} 1226 1227static JSVM_CallbackStruct hello_cb = {hello, (void *)"Hello"}; 1228static intptr_t externals[] = { 1229 (intptr_t)&hello_cb, 1230 0, 1231}; 1232 1233static void test1() { OH_LOG_INFO(LOG_APP, "test1 called"); } 1234 1235struct Test { 1236 void *ptr1; 1237 void *ptr2; 1238}; 1239 1240static JSVM_Value assertEqual(JSVM_Env env, JSVM_CallbackInfo info) { 1241 size_t argc = 2; 1242 JSVM_Value args[2]; 1243 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL)); 1244 1245 bool isStrictEquals = false; 1246 OH_JSVM_StrictEquals(env, args[0], args[1], &isStrictEquals); 1247 return nullptr; 1248} 1249 1250static JSVM_Value GetPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value thisArg, JSVM_Value data) { 1251 // This callback is triggered by a request for getting a property from an object. 1252 char strValue[100]; 1253 size_t size; 1254 OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size); 1255 JSVM_Value newResult = nullptr; 1256 char newStr[] = "new return value hahaha from name listening"; 1257 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1258 int signBit = 0; 1259 size_t wordCount = 2; 1260 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1261 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1262 if (status == JSVM_OK) { 1263 OH_LOG_INFO(LOG_APP, "GetPropertyCbInfo wordCount is %{public}zu", wordCount); 1264 auto test = reinterpret_cast<Test *>(wordsOut); 1265 typedef void (*callTest1)(); 1266 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1267 callTe(); 1268 } 1269 return nullptr; 1270} 1271 1272static JSVM_Value SetPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value property, JSVM_Value thisArg, JSVM_Value data) { 1273 // This callback is triggered by a request for setting a property for an object. 1274 char strValue[100]; 1275 size_t size; 1276 OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size); 1277 JSVM_Value newResult = nullptr; 1278 char newStr[] = "new return value hahaha from name listening"; 1279 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1280 int signBit = 0; 1281 size_t wordCount = 2; 1282 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1283 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1284 if (status == JSVM_OK) { 1285 OH_LOG_INFO(LOG_APP, "SetPropertyCbInfo wordCount is %{public}zu", wordCount); 1286 auto test = reinterpret_cast<Test *>(wordsOut); 1287 typedef void (*callTest1)(); 1288 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1289 callTe(); 1290 } 1291 return nullptr; 1292} 1293 1294static JSVM_Value DeleterPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value thisArg, JSVM_Value data) { 1295 // This callback is triggered by a request for deleting a property from an object. 1296 char strValue[100]; 1297 size_t size; 1298 OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size); 1299 JSVM_Value newResult = nullptr; 1300 bool returnValue = false; 1301 OH_JSVM_GetBoolean(env, returnValue, &newResult); 1302 int signBit = 0; 1303 size_t wordCount = 2; 1304 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1305 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1306 if (status == JSVM_OK) { 1307 OH_LOG_INFO(LOG_APP, "DeleterPropertyCbInfo wordCount is %{public}zu", wordCount); 1308 auto test = reinterpret_cast<Test *>(wordsOut); 1309 typedef void (*callTest1)(); 1310 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1311 callTe(); 1312 } 1313 return nullptr; 1314} 1315 1316static JSVM_Value EnumeratorPropertyCbInfo(JSVM_Env env, JSVM_Value thisArg, JSVM_Value data) { 1317 // This callback is triggered by a request for getting all properties of an object. 1318 JSVM_Value testArray = nullptr; 1319 OH_JSVM_CreateArrayWithLength(env, 2, &testArray); 1320 JSVM_Value name1 = nullptr; 1321 char newStr1[] = "hahaha"; 1322 OH_JSVM_CreateStringUtf8(env, newStr1, strlen(newStr1), &name1); 1323 JSVM_Value name2 = nullptr; 1324 char newStr2[] = "heheheh"; 1325 OH_JSVM_CreateStringUtf8(env, newStr2, strlen(newStr2), &name2); 1326 1327 OH_JSVM_SetElement(env, testArray, 0, name1); 1328 OH_JSVM_SetElement(env, testArray, 1, name2); 1329 int signBit = 0; 1330 size_t wordCount = 2; 1331 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1332 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1333 if (status == JSVM_OK) { 1334 OH_LOG_INFO(LOG_APP, "EnumeratorPropertyCbInfo wordCount is %{public}zu", wordCount); 1335 auto test = reinterpret_cast<Test *>(wordsOut); 1336 typedef void (*callTest1)(); 1337 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1338 callTe(); 1339 } 1340 return nullptr; 1341} 1342 1343static JSVM_Value IndexedPropertyGet(JSVM_Env env, JSVM_Value index, JSVM_Value thisArg, JSVM_Value data) { 1344 // This function is triggered by getting an indexed property of an instance. 1345 uint32_t value; 1346 OH_JSVM_GetValueUint32(env, index, &value); 1347 1348 JSVM_Value newResult = nullptr; 1349 char newStr[] = "new return value hahaha from index listening"; 1350 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1351 int signBit = 0; 1352 size_t wordCount = 2; 1353 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1354 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1355 if (status == JSVM_OK) { 1356 OH_LOG_INFO(LOG_APP, "IndexedPropertyGet wordCount is %{public}zu", wordCount); 1357 auto test = reinterpret_cast<Test *>(wordsOut); 1358 typedef void (*callTest1)(); 1359 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1360 callTe(); 1361 } 1362 return nullptr; 1363} 1364 1365static JSVM_Value IndexedPropertySet(JSVM_Env env, JSVM_Value index, JSVM_Value property, JSVM_Value thisArg, JSVM_Value data) { 1366 // This function is triggered by setting an indexed property of an instance. 1367 uint32_t value; 1368 OH_JSVM_GetValueUint32(env, index, &value); 1369 char str[100]; 1370 size_t size; 1371 OH_JSVM_GetValueStringUtf8(env, property, str, 100, &size); 1372 JSVM_Value newResult = nullptr; 1373 char newStr[] = "new return value hahaha from name listening"; 1374 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1375 int signBit = 0; 1376 size_t wordCount = 2; 1377 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1378 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1379 if (status == JSVM_OK) { 1380 OH_LOG_INFO(LOG_APP, "IndexedPropertySet wordCount is %{public}zu", wordCount); 1381 auto test = reinterpret_cast<Test *>(wordsOut); 1382 typedef void (*callTest1)(); 1383 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1384 callTe(); 1385 } 1386 return nullptr; 1387} 1388 1389static JSVM_Value IndexedPropertyDeleter(JSVM_Env env, JSVM_Value index, JSVM_Value thisArg, JSVM_Value data) { 1390 // This function is triggered by deleting an indexed property from an instance. 1391 uint32_t value; 1392 OH_JSVM_GetValueUint32(env, index, &value); 1393 JSVM_Value newResult = nullptr; 1394 bool returnValue = false; 1395 OH_JSVM_GetBoolean(env, returnValue, &newResult); 1396 int signBit = 0; 1397 size_t wordCount = 2; 1398 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1399 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1400 if (status == JSVM_OK) { 1401 OH_LOG_INFO(LOG_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount); 1402 auto test = reinterpret_cast<Test *>(wordsOut); 1403 typedef void (*callTest1)(); 1404 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1405 callTe(); 1406 } 1407 return nullptr; 1408} 1409 1410static JSVM_Value IndexedPropertyEnumerator(JSVM_Env env, JSVM_Value thisArg, JSVM_Value data) { 1411 // This function is triggered by getting all indexed properties from an object. 1412 JSVM_Value testArray = nullptr; 1413 OH_JSVM_CreateArrayWithLength(env, 2, &testArray); 1414 JSVM_Value index1 = nullptr; 1415 OH_JSVM_CreateUint32(env, 1, &index1); 1416 JSVM_Value index2 = nullptr; 1417 OH_JSVM_CreateUint32(env, 2, &index2); 1418 OH_JSVM_SetElement(env, testArray, 0, index1); 1419 OH_JSVM_SetElement(env, testArray, 1, index2); 1420 int signBit = 0; 1421 size_t wordCount = 2; 1422 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1423 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1424 if (status == JSVM_OK) { 1425 OH_LOG_INFO(LOG_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount); 1426 auto test = reinterpret_cast<Test *>(wordsOut); 1427 typedef void (*callTest1)(); 1428 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1429 callTe(); 1430 } 1431 return nullptr; 1432} 1433 1434static napi_value TestDefineClassWithProperty(napi_env env1, napi_callback_info info) { 1435 OH_LOG_ERROR(LOG_APP, "TestDefineClassWithProperty start"); 1436 JSVM_InitOptions init_options; 1437 memset(&init_options, 0, sizeof(init_options)); 1438 init_options.externalReferences = externals; 1439 if (aa == 0) { 1440 OH_JSVM_Init(&init_options); 1441 aa++; 1442 } 1443 JSVM_VM vm; 1444 JSVM_CreateVMOptions options; 1445 memset(&options, 0, sizeof(options)); 1446 OH_JSVM_CreateVM(&options, &vm); 1447 JSVM_VMScope vm_scope; 1448 OH_JSVM_OpenVMScope(vm, &vm_scope); 1449 JSVM_Env env; 1450 JSVM_CallbackStruct param[1]; 1451 param[0].data = nullptr; 1452 param[0].callback = assertEqual; 1453 JSVM_PropertyDescriptor descriptor[] = { 1454 {"assertEqual", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 1455 }; 1456 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 1457 JSVM_EnvScope envScope; 1458 OH_JSVM_OpenEnvScope(env, &envScope); 1459 JSVM_HandleScope handlescope; 1460 OH_JSVM_OpenHandleScope(env, &handlescope); 1461 1462 1463 JSVM_CallbackStruct param1; 1464 param1.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { 1465 JSVM_Value thisVar = nullptr; 1466 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr); 1467 return thisVar; 1468 }; 1469 param1.data = nullptr; 1470 1471 JSVM_Value res = nullptr; 1472 Test *test = new Test(); 1473 test->ptr1 = (void *)test1; 1474 test->ptr2 = (void *)test1; 1475 OH_LOG_INFO(LOG_APP, "OH_JSVM_CreateBigintWords 111 word count %{public}d", 1476 sizeof(*test) / sizeof(uint64_t)); 1477 JSVM_Status status = OH_JSVM_CreateBigintWords(env, 1, 2, reinterpret_cast<const uint64_t *>(test), &res); 1478 1479 // Initialize propertyCfg. 1480 JSVM_PropertyHandlerConfigurationStruct propertyCfg; 1481 propertyCfg.genericNamedPropertyGetterCallback = GetPropertyCbInfo; 1482 propertyCfg.genericNamedPropertySetterCallback = SetPropertyCbInfo; 1483 propertyCfg.genericNamedPropertyDeleterCallback = DeleterPropertyCbInfo; 1484 propertyCfg.genericNamedPropertyEnumeratorCallback = EnumeratorPropertyCbInfo; 1485 propertyCfg.genericIndexedPropertyGetterCallback = IndexedPropertyGet; 1486 propertyCfg.genericIndexedPropertySetterCallback = IndexedPropertySet; 1487 propertyCfg.genericIndexedPropertyDeleterCallback = IndexedPropertyDeleter; 1488 propertyCfg.genericIndexedPropertyEnumeratorCallback = IndexedPropertyEnumerator; 1489 propertyCfg.namedPropertyData = res; 1490 propertyCfg.indexedPropertyData = res; 1491 1492 JSVM_CallbackStruct callbackStruct; 1493 callbackStruct.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { 1494 OH_LOG_INFO(LOG_APP, "call as a function called"); 1495 JSVM_Value thisVar = nullptr; 1496 void *innerData; 1497 size_t argc = 1; 1498 JSVM_Value args[1]; 1499 OH_JSVM_GetCbInfo(env, info, &argc, args, &thisVar, &innerData); 1500 OH_LOG_INFO(LOG_APP, "function call as function result is %{public}s", reinterpret_cast<char *>(innerData)); 1501 uint32_t ret = 0; 1502 OH_JSVM_GetValueUint32(env, args[0], &ret); 1503 const char testStr[] = "hello world 111111"; 1504 JSVM_Value setvalueName = nullptr; 1505 JSVM_CALL(env, OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName)); 1506 return setvalueName; 1507 }; 1508 char data[100] = "1111 hello world"; 1509 callbackStruct.data = data; 1510 JSVM_Value testWrapClass = nullptr; 1511 1512 // Register a property access listener in propertyCfg. 1513 OH_JSVM_DefineClassWithPropertyHandler(env, "TestWrapClass", NAPI_AUTO_LENGTH, ¶m1, 0, nullptr, &propertyCfg, 1514 &callbackStruct, &testWrapClass); 1515 JSVM_Value instanceValue = nullptr; 1516 OH_JSVM_NewInstance(env, testWrapClass, 0, nullptr, &instanceValue); 1517 const char testStr[] = "hello world"; 1518 JSVM_Value setvalueName = nullptr; 1519 OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName); 1520 1521 // 1522 // Set a property. 1523 OH_JSVM_SetNamedProperty(env, instanceValue, "str11", setvalueName); 1524 OH_JSVM_SetNamedProperty(env, instanceValue, "str123", setvalueName); 1525 1526 // Get a property. 1527 JSVM_Value valueName = nullptr; 1528 OH_JSVM_GetNamedProperty(env, instanceValue, "str11", &valueName); 1529 char str[100]; 1530 size_t size; 1531 OH_JSVM_GetValueStringUtf8(env, valueName, str, 100, &size); 1532 1533 // Get all property names. 1534 JSVM_Value allPropertyNames = nullptr; 1535 OH_JSVM_GetAllPropertyNames(env, instanceValue, JSVM_KEY_OWN_ONLY, 1536 static_cast<JSVM_KeyFilter>(JSVM_KEY_ENUMERABLE | JSVM_KEY_SKIP_SYMBOLS), 1537 JSVM_KEY_NUMBERS_TO_STRINGS, &allPropertyNames); 1538 uint32_t nameSize = 0; 1539 OH_JSVM_GetArrayLength(env, allPropertyNames, &nameSize); 1540 JSVM_Value propertyName = nullptr; 1541 for (uint32_t i = 0; i < nameSize; ++i) { 1542 OH_JSVM_GetElement(env, allPropertyNames, i, &propertyName); 1543 char str[100]; 1544 size_t size; 1545 OH_JSVM_GetValueStringUtf8(env, propertyName, str, 100, &size); 1546 } 1547 1548 // Delete a property. 1549 bool result = false; 1550 propertyName = nullptr; 1551 char propertyChar[] = "str11"; 1552 OH_JSVM_CreateStringUtf8(env, propertyChar, strlen(propertyChar), &propertyName); 1553 OH_JSVM_DeleteProperty(env, instanceValue, propertyName, &result); 1554 1555 // 1556 // Set a property. 1557 JSVM_Value jsIndex = nullptr; 1558 uint32_t index = 0; 1559 OH_JSVM_CreateUint32(env, index, &jsIndex); 1560 OH_JSVM_SetProperty(env, instanceValue, jsIndex, setvalueName); 1561 JSVM_Value jsIndex1 = nullptr; 1562 index = 1; 1563 OH_JSVM_CreateUint32(env, index, &jsIndex1); 1564 OH_JSVM_SetProperty(env, instanceValue, jsIndex1, setvalueName); 1565 1566 // Get a property. 1567 JSVM_Value valueName1 = nullptr; 1568 OH_JSVM_GetProperty(env, instanceValue, jsIndex, &valueName1); 1569 char str1[100]; 1570 size_t size1; 1571 OH_JSVM_GetValueStringUtf8(env, valueName1, str1, 100, &size1); 1572 1573 // Get all property names. 1574 JSVM_Value allPropertyNames1 = nullptr; 1575 OH_JSVM_GetAllPropertyNames(env, instanceValue, JSVM_KEY_OWN_ONLY, 1576 static_cast<JSVM_KeyFilter>(JSVM_KEY_ENUMERABLE | JSVM_KEY_SKIP_SYMBOLS), 1577 JSVM_KEY_NUMBERS_TO_STRINGS, &allPropertyNames1); 1578 uint32_t nameSize1 = 0; 1579 OH_JSVM_GetArrayLength(env, allPropertyNames1, &nameSize); 1580 JSVM_Value propertyName1 = nullptr; 1581 for (uint32_t i = 0; i < nameSize1; ++i) { 1582 OH_JSVM_GetElement(env, allPropertyNames1, i, &propertyName1); 1583 char str[100]; 1584 size_t size; 1585 OH_JSVM_GetValueStringUtf8(env, propertyName1, str, 100, &size); 1586 } 1587 1588 // Delete a property. 1589 bool result1 = false; 1590 OH_JSVM_DeleteProperty(env, instanceValue, jsIndex, &result1); 1591 1592 // 1593 JSVM_Value gloablObj = nullptr; 1594 OH_JSVM_GetGlobal(env, &gloablObj); 1595 OH_JSVM_SetNamedProperty(env, gloablObj, "myTestInstance", instanceValue); 1596 OH_LOG_INFO(LOG_APP, "set property on global object"); 1597 std::string innerSourcecodestr = R"( 1598 { 1599 let res = myTestInstance(12); 1600 })"; 1601 JSVM_Value innerSourcecodevalue; 1602 OH_JSVM_CreateStringUtf8(env, innerSourcecodestr.c_str(), innerSourcecodestr.size(), &innerSourcecodevalue); 1603 JSVM_Script innerscript; 1604 OH_JSVM_CompileScript(env, innerSourcecodevalue, nullptr, 0, true, nullptr, &innerscript); 1605 JSVM_Value innerResult; 1606 OH_JSVM_RunScript(env, innerscript, &innerResult); 1607 1608 OH_JSVM_CloseHandleScope(env, handlescope); 1609 OH_JSVM_CloseEnvScope(env, envScope); 1610 OH_JSVM_DestroyEnv(env); 1611 OH_JSVM_CloseVMScope(vm, vm_scope); 1612 OH_JSVM_DestroyVM(vm); 1613 OH_LOG_ERROR(LOG_APP, "TestDefineClassWithProperty pass"); 1614 return nullptr; 1615} 1616``` 1617 1618### Version Management 1619 1620#### When to Use 1621 1622Obtain version information. 1623 1624#### Available APIs 1625| API| Description| 1626| -------- | -------- | 1627|OH_JSVM_GetVersion| Obtains the latest JSVM API version supported by the JSVM runtime.| 1628|OH_JSVM_GetVMInfo| Obtains the VM information.| 1629 1630Example: 1631Obtain version information. 1632 1633```c++ 1634JSVM_VMInfo result; 1635OH_JSVM_GetVMInfo(&result); 1636uint32_t versionId = 0; 1637OH_JSVM_GetVersion(env, &versionId); 1638``` 1639 1640### Memory Management 1641 1642#### When to Use 1643 1644Perform memory management. 1645 1646#### Available APIs 1647| API| Description| 1648| -------- | -------- | 1649|OH_JSVM_AdjustExternalMemory| Informs the underlying engine that the VM system memory is insufficient and selectively triggers garbage collection.| 1650|OH_JSVM_MemoryPressureNotification| Creates a deferred object and a JS promise.| 1651 1652Example: 1653Perform memory management. 1654 1655```c++ 1656int64_t change = 1024 * 1024; // Allocate 1 MB of memory. 1657int64_t result; 1658OH_JSVM_AdjustExternalMemory(env, change, &result); 1659``` 1660 1661### Promises 1662 1663#### When to Use 1664 1665Perform operations related to promises. 1666 1667#### Available APIs 1668| API| Description| 1669| -------- | -------- | 1670|OH_JSVM_CreatePromise| Creates a deferred object and a JS promise.| 1671|OH_JSVM_ResolveDeferred| Resolves a JS promise by using the deferred object associated with it.| 1672|OH_JSVM_RejectDeferred| Rejects a JS promise by using the deferred object associated with it.| 1673|OH_JSVM_IsPromise| Checks whether a promise object is a native promise object.| 1674 1675Example: 1676Perform operations related to promises. 1677 1678```c++ 1679JSVM_Deferred deferred; 1680JSVM_Value promise; 1681OH_JSVM_CreatePromise(env, &deferred, &promise); 1682 1683// Perform an asynchronous operation. 1684int result = 42; 1685bool success = true; 1686if (success) 1687{ 1688 // Resolve the promise and pass the result. 1689 JSVM_Value value; 1690 OH_JSVM_CreateInt32(env, result, &value); 1691 OH_JSVM_ResolveDeferred(env, deferred, value); 1692} else { 1693 // Reject the promise and pass the error information. 1694 JSVM_Value code = nullptr; 1695 JSVM_Value message = nullptr; 1696 OH_JSVM_CreateStringUtf8(env, "600", JSVM_AUTO_LENGTH, &code); 1697 OH_JSVM_CreateStringUtf8(env, "Async operation failed", JSVM_AUTO_LENGTH, &message); 1698 JSVM_Value error = nullptr; 1699 OH_JSVM_CreateError(env, code, message, &error); 1700 OH_JSVM_RejectDeferred(env, deferred, error); 1701} 1702``` 1703 1704### JSON Operations 1705 1706#### When to Use 1707 1708Perform JSON operations. 1709 1710#### Available APIs 1711 1712| API| Description| 1713| -------- | -------- | 1714|OH_JSVM_JsonParse| Parses a JSON string and returns the parsed value.| 1715|OH_JSVM_JsonStringify| Converts a JS object into a JSON string and returns the converted string.| 1716 1717Example: 1718Parse JSON strings. 1719 1720```c++ 1721std::string sourcecodestr = "{\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}" ; 1722JSVM_Value jsonString; 1723OH_JSVM_CreateStringUtf8(env, sourcecodestr.c_str(), sourcecodestr.size(), &jsonString) 1724JSVM_Value result; 1725OH_JSVM_JsonParse(env, jsonString, &result); 1726``` 1727 1728### Creating VM Startup Snapshots 1729 1730#### When to Use 1731 1732Create a VM startup snapshot. 1733 1734#### Available APIs 1735| API| Description| 1736| -------- | -------- | 1737|OH_JSVM_CreateSnapshot| Creates a VM startup snapshot.| 1738 1739Example: 1740Create a VM startup snapshot. 1741 1742```c++ 1743JSVM_VM vm; 1744JSVM_CreateVMOptions options; 1745memset(&options, 0, sizeof(options)); 1746OH_JSVM_CreateVM(&options, &vm); 1747JSVM_Env env; 1748JSVM_CallbackStruct param[1]; 1749param[0].data = nullptr; 1750param[0].callback = AssertEqual; 1751JSVM_PropertyDescriptor descriptor[] = { 1752 {"test", nullptr, ¶m[0], nullptr, nullptr, nullptr, JSVM_DEFAULT}, 1753}; 1754OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 1755const char *blobData = nullptr; 1756size_t blobSize = 0; 1757JSVM_Env envs[1] = {env}; 1758OH_JSVM_CreateSnapshot(vm, 1, envs, &blobData, &blobSize); 1759``` 1760 1761### Checking Input Parameters 1762 1763#### When to Use 1764 1765Check whether the input parameters are callable. 1766 1767#### Available APIs 1768| API| Description| 1769| -------- | -------- | 1770|OH_JSVM_IsCallable| Checks whether input parameters are callable.| 1771 1772Example: 1773Check whether input parameters are callable. 1774 1775```c++ 1776static JSVM_Value NapiIsCallable(JSVM_Env env, JSVM_CallbackInfo info) { 1777 JSVM_Value value, rst; 1778 size_t argc = 1; 1779 bool isCallable = false; 1780 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, &value, NULL, NULL)); 1781 JSVM_CALL(env, OH_JSVM_IsCallable(env, value, &isCallable)); 1782 OH_JSVM_GetBoolean(env, isCallable, &rst); 1783 return rst; 1784} 1785 1786static napi_value MyJSVMDemo([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) { 1787 std::thread t([]() { 1788 // Create a VM instance and open the VM scope. 1789 JSVM_VM vm; 1790 JSVM_CreateVMOptions options; 1791 memset(&options, 0, sizeof(options)); 1792 OH_JSVM_CreateVM(&options, &vm); 1793 JSVM_VMScope vmScope; 1794 OH_JSVM_OpenVMScope(vm, &vmScope); 1795 JSVM_CallbackStruct param[] = { 1796 {.data = nullptr, .callback = NapiIsCallable}, 1797 }; 1798 JSVM_PropertyDescriptor descriptor[] = { 1799 {"napiIsCallable", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 1800 }; 1801 // Create env, register a native method, and open an env scope. 1802 JSVM_Env env; 1803 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 1804 JSVM_EnvScope envScope; 1805 OH_JSVM_OpenEnvScope(env, &envScope); 1806 // Open a handle scope. 1807 JSVM_HandleScope handleScope; 1808 OH_JSVM_OpenHandleScope(env, &handleScope); 1809 std::string sourceCodeStr = R"JS( 1810 function addNumbers(num1, num2) 1811 { 1812 var rst= num1 + num2; 1813 return rst; 1814 } 1815 let rst = napiIsCallable(addNumbers); 1816 )JS"; 1817 // Compile the JS script. 1818 JSVM_Value sourceCodeValue; 1819 OH_JSVM_CreateStringUtf8(env, sourceCodeStr.c_str(), sourceCodeStr.size(), &sourceCodeValue); 1820 JSVM_Script script; 1821 OH_JSVM_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script); 1822 JSVM_Value result; 1823 // Run the JS script. 1824 OH_JSVM_RunScript(env, script, &result); 1825 JSVM_ValueType type; 1826 OH_JSVM_Typeof(env, result, &type); 1827 OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type); 1828 // Exit the VM and release the memory. 1829 OH_JSVM_CloseHandleScope(env, handleScope); 1830 OH_JSVM_CloseEnvScope(env, envScope); 1831 OH_JSVM_DestroyEnv(env); 1832 OH_JSVM_CloseVMScope(vm, vmScope); 1833 OH_JSVM_DestroyVM(vm); 1834 }); 1835 t.detach(); 1836 return nullptr; 1837} 1838``` 1839 1840### Lock Operations 1841 1842#### When to Use 1843 1844Perform lock operations. 1845 1846#### Available APIs 1847| API| Description| 1848| -------- | -------- | 1849|OH_JSVM_IsLocked| Checks whether the current thread holds a lock of the specified environment.| 1850|OH_JSVM_AcquireLock| Obtains a lock.| 1851|OH_JSVM_ReleaseLock| Releases a lock.| 1852 1853Example: 1854Obtain and release a lock. 1855 1856```c++ 1857static napi_value MyJSVMDemo([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) { 1858 // Create a VM instance and open the VM scope. 1859 JSVM_VM vm; 1860 JSVM_CreateVMOptions options; 1861 memset(&options, 0, sizeof(options)); 1862 OH_JSVM_CreateVM(&options, &vm); 1863 JSVM_VMScope vmScope; 1864 OH_JSVM_OpenVMScope(vm, &vmScope); 1865 // Create env, register a native method, and open an env scope. 1866 JSVM_Env env; 1867 OH_JSVM_CreateEnv(vm, 0, nullptr, &env); 1868 JSVM_EnvScope envScope; 1869 OH_JSVM_OpenEnvScope(env, &envScope); 1870 // Open a handle scope. 1871 JSVM_HandleScope handleScope; 1872 OH_JSVM_OpenHandleScope(env, &handleScope); 1873 std::thread t1([vm, env]() { 1874 bool isLocked = false; 1875 OH_JSVM_IsLocked(env, &isLocked); 1876 if (!isLocked) { 1877 OH_JSVM_AcquireLock(env); 1878 } 1879 JSVM_VMScope vmScope; 1880 OH_JSVM_OpenVMScope(vm, &vmScope); 1881 JSVM_EnvScope envScope; 1882 OH_JSVM_OpenEnvScope(env, &envScope); 1883 JSVM_HandleScope handleScope; 1884 OH_JSVM_OpenHandleScope(env, &handleScope); 1885 JSVM_Value value; 1886 JSVM_Status rst = OH_JSVM_CreateInt32(env, 32, &value); // 32: numerical value 1887 if (rst) { 1888 OH_LOG_INFO(LOG_APP, "JSVM:t1 OH_JSVM_CreateInt32 suc"); 1889 } else { 1890 OH_LOG_ERROR(LOG_APP, "JSVM:t1 OH_JSVM_CreateInt32 fail"); 1891 } 1892 int32_t num1; 1893 OH_JSVM_GetValueInt32(env, value, &num1); 1894 OH_LOG_INFO(LOG_APP, "JSVM:t1 num1 = %{public}d", num1); 1895 OH_JSVM_CloseHandleScope(env, handleScope); 1896 OH_JSVM_CloseEnvScope(env, envScope); 1897 OH_JSVM_DestroyEnv(env); 1898 OH_JSVM_IsLocked(env, &isLocked); 1899 if (isLocked) { 1900 OH_JSVM_ReleaseLock(env); 1901 } 1902 }); 1903 std::thread t2([vm, env]() { 1904 bool isLocked = false; 1905 OH_JSVM_IsLocked(env, &isLocked); 1906 if (!isLocked) { 1907 OH_JSVM_AcquireLock(env); 1908 } 1909 JSVM_VMScope vmScope; 1910 OH_JSVM_OpenVMScope(vm, &vmScope); 1911 JSVM_EnvScope envScope; 1912 OH_JSVM_OpenEnvScope(env, &envScope); 1913 JSVM_HandleScope handleScope; 1914 OH_JSVM_OpenHandleScope(env, &handleScope); 1915 JSVM_Value value; 1916 JSVM_Status rst = OH_JSVM_CreateInt32(env, 32, &value); // 32: numerical value 1917 if (rst) { 1918 OH_LOG_INFO(LOG_APP, "JSVM:t2 OH_JSVM_CreateInt32 suc"); 1919 } else { 1920 OH_LOG_ERROR(LOG_APP, "JSVM:t2 OH_JSVM_CreateInt32 fail"); 1921 } 1922 int32_t num1; 1923 OH_JSVM_GetValueInt32(env, value, &num1); 1924 OH_LOG_INFO(LOG_APP, "JSVM:t2 num1 = %{public}d", num1); 1925 OH_JSVM_CloseHandleScope(env, handleScope); 1926 OH_JSVM_CloseEnvScope(env, envScope); 1927 OH_JSVM_DestroyEnv(env); 1928 OH_JSVM_IsLocked(env, &isLocked); 1929 if (isLocked) { 1930 OH_JSVM_ReleaseLock(env); 1931 } 1932 }); 1933 t1.detach(); 1934 t2.detach(); 1935 sleep(10); 1936 // Exit the VM and release the memory. 1937 OH_JSVM_CloseHandleScope(env, handleScope); 1938 OH_JSVM_CloseEnvScope(env, envScope); 1939 OH_JSVM_DestroyEnv(env); 1940 OH_JSVM_CloseVMScope(vm, vmScope); 1941 OH_JSVM_DestroyVM(vm); 1942 return nullptr; 1943} 1944``` 1945