1# JSVM-API Data Types and APIs 2 3## Data Types 4 5### JSVM_Status 6 7Defines an enum for the execution statuses returned by a JSVM-API call. 8 9Each time a JSVM-API function is called, **JSVM_Status** is returned indicating the execution result. 10 11```c++ 12 typedef enum { 13 JSVM_OK, /* Successful. */ 14 JSVM_INVALID_ARG, /* Invalid parameters. */ 15 JSVM_OBJECT_EXPECTED, /* An object is expected. */ 16 JSVM_STRING_EXPECTED, /* A string is expected. */ 17 JSVM_NAME_EXPECTED, /* A name is expected. */ 18 JSVM_FUNCTION_EXPECTED, /* A function is expected. */ 19 JSVM_NUMBER_EXPECTED, /* A number is expected. */ 20 JSVM_BOOL_EXPECTED, /* A Boolean value is expected. */ 21 JSVM_ARRAY_EXPECTED, /* An array is expected. */ 22 JSVM_GENERIC_FAILURE, /* Generic failure. */ 23 JSVM_PENDING_EXCEPTION, /* Pending exception. */ 24 JSVM_CENCELLED, /* Cancelled. */ 25 JSVM_ESCAPE_CALLED_TWICE, /* Escape is called twice. */ 26 JSVM_HANDLE_SCOPE_MISMATCH, /* Handle scope does not match. */ 27 JSVM_CALLBACK_SCOPE_MISMATCH, /* Callback scope does not match. */ 28 JSVM_QUEUE_FULL, /* The queue is full. */ 29 JSVM_CLOSING, /* Closing. */ 30 JSVM_BIGINT_EXPECTED, /* A Bigint value is expected. */ 31 JSVM_DATA_EXPECTED, /* A date is expected. */ 32 JSVM_ARRAYBUFFER_EXPECTED, /* An ArrayBuffer is expected. */ 33 JSVM_DETACHABLE_ARRAYBUFFER_EXPECTED, /* A detachable ArrayBuffer is expected. */ 34 JSVM_WOULD_DEADLOCK, /* About to deadlock. */ 35 JSVM_NO_EXTERNAL_BUFFERS_ALLOWED, /* External buffers are not allowed. */ 36 JSVM_CANNOT_RUN_JS, /* JS cannot be executed. */ 37 JSVM_JIT_MODE_EXPECTD, /* JIT mode is expected. */ 38 } JSVM_Status; 39``` 40 41### JSVM_ExtendedErrorInfo 42 43Defines a struct that represents detailed error information when a JSVM-API call fails. 44 45```c++ 46typedef struct { 47 const char* errorMessage; 48 void* engineReserved; 49 uint32_t engineErrorCode; 50 JSVM_Status errorCode; 51} JSVM_ExtendedErrorInfo; 52``` 53 54### JSVM_Value 55 56Defines a pointer to a JavaScript (JS) value. 57 58### JSVM_Env 59 60Defines the context for the underlying JSVM-API implementation. It is passed to the JSVM-API interface in a native function as an input parameter. 61 62- When the native addon exits, **JSVM_Env** becomes invalid and this event is passed to **OH_JSVM_SetInstanceData** via a callback. 63 64- Avoid caching **JSVM_Env** or passing **JSVM_Env** between different worker threads. 65 66- 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. 67 68### JSVM_ValueType 69 70Defines an enum for the **JSVM_Value** types. **JSVM_Value** includes the types defined in ECMAScript. **JSVM_EXTERNAL** indicates an external data type. 71 72```c++ 73typedef enum { 74 JSVM_UNDEFINED, 75 JSVM_NULL, 76 JSVM_BOOLEAN, 77 JSVM_NUMBER, 78 JSVM_STRING, 79 JSVM_SYMBOL, 80 JSVM_OBJECT, 81 JSVM_FUNCTION, 82 JSVM_EXTERNAL, 83 JSVM_BIGINT, 84} JSVM_ValueType; 85``` 86 87### JSVM_TypedarrayType 88 89Defines an enum for data types of the **TypedArray** object. 90 91```c++ 92typedef enum { 93 JSVM_INT8_ARRAY, 94 JSVM_UINT8_ARRAY, 95 JSVM_UINT8_CLAMPED_ARRAY, 96 JSVM_INT16_ARRAY, 97 JSVM_UINT16_ARRAY, 98 JSVM_INT32_ARRAY, 99 JSVM_UINT32_ARRAY, 100 JSVM_FLOAT32_ARRAY, 101 JSVM_FLOAT64_ARRAY, 102 JSVM_BIGINT64_ARRAY, 103 JSVM_BIGUINT64_ARRAY, 104} JSVM_TypedarrayType; 105``` 106 107### JSVM_RegExpFlags 108 109Defines an enum for regular expression flags. 110 111```c++ 112typedef enum { 113 JSVM_REGEXP_NONE = 0, 114 JSVM_REGEXP_GLOBAL = 1 << 0, 115 JSVM_REGEXP_IGNORE_CASE = 1 << 1, 116 JSVM_REGEXP_MULTILINE = 1 << 2, 117 JSVM_REGEXP_STICKY = 1 << 3, 118 JSVM_REGEXP_UNICODE = 1 << 4, 119 JSVM_REGEXP_DOT_ALL = 1 << 5, 120 JSVM_REGEXP_LINEAR = 1 << 6, 121 JSVM_REGEXP_HAS_INDICES = 1 << 7, 122 JSVM_REGEXP_UNICODE_SETS = 1 << 8, 123} JSVM_RegExpFlags; 124``` 125 126### Compilation Option Types 127#### JSVM_CompileOptions 128 129Defines a struct that represents the type of the elements in **options** of **OH_JSVM_CompileScriptWithOptions**. 130 131The struct consists of the following parameters: 132- **id**: identifies a compilation option. 133- **content**: specifies a compilation option. 134 135**id** and **content** together define a compilation option. 136 137```c 138typedef struct { 139 /** Compilation option type. */ 140 JSVM_CompileOptionId id; 141 /** Compilation option content. */ 142 union { 143 /** ptr type. */ 144 void *ptr; 145 /** int type. */ 146 int num; 147 /** bool type. */ 148 _Bool boolean; 149 } content; 150} JSVM_CompileOptions; 151``` 152 153#### JSVM_CompileOptionId 154 155Defines an enum for **id** in **JSVM_CompileOptions**. Each **id** corresponds to a **content** value. The value **JSVM_COMPILE_ENABLE_SOURCE_MAP** corresponds to bool and is valid only when **sourceMapUrl** in **JSVM_ScriptOrigin** is not empty. 156 157```c 158typedef enum { 159 /** Compilation mode. */ 160 JSVM_COMPILE_MODE, 161 /** Code cache. */ 162 JSVM_COMPILE_CODE_CACHE, 163 /** Script origin. */ 164 JSVM_COMPILE_SCRIPT_ORIGIN, 165 /** Compilation profile. */ 166 JSVM_COMPILE_COMPILE_PROFILE, 167 /** Switch for source map support. */ 168 JSVM_COMPILE_ENABLE_SOURCE_MAP, 169} JSVM_CompileOptionId; 170``` 171 172#### JSVM_CompileMode 173 174Defines an enum for the compilation modes when **id** is **JSVM_COMPILE_MODE**. 175 176- **JSVM_COMPILE_MODE_DEFAULT**: indicates the default compilation mode. 177- **JSVM_COMPILE_MODE_CONSUME_CODE_CACHE**: indicates the compilation with the code cache. 178- **JSVM_COMPILE_MODE_EAGER_COMPILE**: indicates full compilation. 179- **JSVM_COMPILE_MODE_PRODUCE_COMPILE_PROFILE**/**JSVM_COMPILE_MODE_CONSUME_COMPILE_PROFILE**: reserved at present. 180 181```c 182typedef enum { 183 /** Default mode. */ 184 JSVM_COMPILE_MODE_DEFAULT, 185 /** Compilation by leveraging the code cache. */ 186 JSVM_COMPILE_MODE_CONSUME_CODE_CACHE, 187 /** Full compilation. */ 188 JSVM_COMPILE_MODE_EAGER_COMPILE, 189 /** Compilation with a preset compilation profile. */ 190 JSVM_COMPILE_MODE_PRODUCE_COMPILE_PROFILE, 191 /** Compilation by using a compile profile. */ 192 JSVM_COMPILE_MODE_CONSUME_COMPILE_PROFILE, 193} JSVM_CompileMode; 194``` 195 196 197#### JSVM_CodeCache 198 199Defines a struct that represents the code cache when **id** is **JSVM_COMPILE_CODE_CACHE**. The struct consists of the following: 200 201- **cache**: pointer to the code cache to use. 202- **length**: size of the code cache. 203 204```c 205typedef struct { 206 /** cache pointer. */ 207 uint8_t *cache; 208 /** length. */ 209 size_t length; 210} JSVM_CodeCache; 211``` 212 213#### JSVM_ScriptOrigin 214 215Defines a struct that represents the source code of the script to compile when **id** is **JSVM_COMPILE_SCRIPT_ORIGIN**. The struct consists of the following: 216 217- **sourceMapUrl**: path of the source map. Currently, only the local paths of the device are supported. This parameter can be left empty. 218- **resourceName**: name of the JS script to be compiled. 219 220```c 221typedef struct { 222 /** Source map URL. */ 223 const char* sourceMapUrl; 224 /** Script to compile. */ 225 const char* resourceName; 226 /** Line offset in the script. */ 227 size_t resourceLineOffset; 228 /** Column offset in the script. */ 229 size_t resourceColumnOffset; 230} JSVM_ScriptOrigin; 231``` 232 233### JSVM 234### Memory Management Types 235 236JSVM-API provides the following memory management types: 237 238**JSVM_HandleScope** 239 240Data 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. 241 242**JSVM_EscapableHandleScope** 243 244- It is created by **OH_JSVM_OpenEscapableHandleScope** and closed by **OH_JSVM_CloseEscapableHandleScope**. 245 246- It is a special type of handle range used to return values created within the scope of **JSVM_EscapableHandleScope** to a parent scope. 247 248- 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. 249 250**JSVM_Ref** 251 252Reference to **JSVM_Value**, which allows you to manage the lifecycle of JS values. 253 254**JSVM_TypeTag** 255 256Struct containing two unsigned 64-bit integers to identify the type of a JSVM-API value. 257 258```c++ 259typedef struct { 260 uint64_t lower; 261 uint64_t upper; 262} JSVM_TypeTag; 263``` 264 265- 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. 266 267- 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. 268 269- 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. 270 271### Callback Types 272 273JSVM-API provides the following callback types: 274 275**JSVM_CallbackStruct** 276 277Callback function pointer and data for user-provided native callbacks, which are to be exposed to JS via JSVM-API. For example, you can use **OH_JSVM_CreateFunction** to create a JS function bound to a native callback defined by **JSVM_CallbackStruct**. Unless otherwise required in object lifecycle management, do not create a handle or callback scope in this callback. 278 279```c++ 280typedef struct { 281 JSVM_Value(*callback)(JSVM_Env env, JSVM_CallbackInfo info); 282 void* data; 283} JSVM_CallbackStruct; 284``` 285 286**JSVM_Callback** 287 288Alias of the **JSVM_CallbackStruct** pointer type. 289 290It is defined as follows: 291 292```c++ 293typedef JSVM_CallbackStruct* JSVM_Callback; 294``` 295 296**JSVM_CallbackInfo** 297 298User-defined native callback. The type of the first parameter is **JSVM_Env**, and that of the second parameter is **JSVM_CallbackInfo**. **JSVM_CallbackInfo** can be used to obtain additional information about the context in which the callback was invoked, for example, the parameter list. When a native callback is implemented, **OH_JSVM_GetCbInfo** is used to extract the invoking information from **JSVM_CallbackInfo**. 299 300**JSVM_Finalize** 301 302Function 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. 303 304The format is as follows: 305 306```c++ 307typedef void (*JSVM_Finalize)(JSVM_Env env, void* finalizeData, void* finalizeHint); 308``` 309 310**JSVM_PropertyHandlerConfigurationStruct** 311 312Callback to be invoked when the getter(), setter(), deleter(), or enumerator() of an object is executed. 313 314```c++ 315typedef struct { 316 JSVM_Value(JSVM_CDECL* genericNamedPropertyGetterCallback)(JSVM_Env env, 317 JSVM_Value name, 318 JSVM_Value thisArg, 319 JSVM_Value namedPropertyData); 320 JSVM_Value(JSVM_CDECL* genericNamedPropertySetterCallback)(JSVM_Env env, 321 JSVM_Value name, 322 JSVM_Value property, 323 JSVM_Value thisArg, 324 JSVM_Value namedPropertyData); 325 JSVM_Value(JSVM_CDECL* genericNamedPropertyDeleterCallback)(JSVM_Env env, 326 JSVM_Value name, 327 JSVM_Value thisArg, 328 JSVM_Value namedPropertyData); 329 JSVM_Value(JSVM_CDECL* genericNamedPropertyEnumeratorCallback)(JSVM_Env env, 330 JSVM_Value thisArg, 331 JSVM_Value namedPropertyData); 332 JSVM_Value(JSVM_CDECL* genericIndexedPropertyGetterCallback)(JSVM_Env env, 333 JSVM_Value index, 334 JSVM_Value thisArg, 335 JSVM_Value indexedPropertyData); 336 JSVM_Value(JSVM_CDECL* genericIndexedPropertySetterCallback)(JSVM_Env env, 337 JSVM_Value index, 338 JSVM_Value property, 339 JSVM_Value thisArg, 340 JSVM_Value indexedPropertyData); 341 JSVM_Value(JSVM_CDECL* genericIndexedPropertyDeleterCallback)(JSVM_Env env, 342 JSVM_Value index, 343 JSVM_Value thisArg, 344 JSVM_Value indexedPropertyData); 345 JSVM_Value(JSVM_CDECL* genericIndexedPropertyEnumeratorCallback)(JSVM_Env env, 346 JSVM_Value thisArg, 347 JSVM_Value indexedPropertyData); 348 JSVM_Value namedPropertyData; 349 JSVM_Value indexedPropertyData; 350} JSVM_PropertyHandlerConfigurationStruct; 351``` 352 353**JSVM_PropertyHandlerCfg** 354 355Pointer to the struct that contains a callback for property listening. 356 357The usage is as follows: 358 359```c++ 360typedef JSVM_PropertyHandlerConfigurationStruct* JSVM_PropertyHandlerCfg; 361``` 362 363## APIs 364 365JSVM-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. 366 367### Creating a VM Instance and JS Context 368 369#### When to Use 370 371Before executing JS code, you need to create a avaScript virtual machine (JSVM) and JS context. 372 373#### Available APIs 374| API| Description| 375| -------- | -------- | 376| OH_JSVM_Init| Initializes a JS engine instance.| 377| OH_JSVM_CreateVM| Creates a JSVM instance.| 378| OH_JSVM_DestroyVM| Destroys a JSVM instance.| 379| 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.| 380| OH_JSVM_CloseVMScope| Closes a VM scope.| 381| OH_JSVM_CreateEnv| Creates a JS context and registers the specified native function.| 382| OH_JSVM_DestroyEnv| Destroys a JS context.| 383| OH_JSVM_OpenEnvScope| Opens a JS context scope. The context can be used only within the scope.| 384| OH_JSVM_CloseEnvScope| Closes a JS context scope.| 385| OH_JSVM_OpenHandleScope| Opens a handle scope. **JSVM_Value** within the scope will not be garbage-collected.| 386| OH_JSVM_CloseHandleScope| Closes a handle scope.| 387 388##### Using **JSVM_InitOptions** 389You can use **JSVM_InitOptions** to initialize VM platforms with different capabilities. 390 391Example 1: Initialize a JSVM in normal mode. 392```c++ 393static void NormalInit(bool &vmInit) { 394 if (!vmInit) { 395 // The JSVM only needs to be initialized once. 396 JSVM_InitOptions initOptions; 397 memset(&initOptions, 0, sizeof(initOptions)); 398 OH_JSVM_Init(&initOptions); 399 vmInit = true; 400 } 401} 402``` 403 404Example 2: Initialize a JSVM with low memory usage. 405```c++ 406static void LowMemoryInit(bool &vmInit) { 407 if (!vmInit) { 408 // The JSVM only needs to be initialized once. 409 JSVM_InitOptions initOptions; 410 initOptions.argc = 4; 411 const char* argv[4]; 412 argv[1] = "--incremental-marking-hard-trigger=40"; 413 argv[2] = "--min-semi-space-size=4"; 414 argv[3] = "--max-semi-space-size=1"; 415 initOptions.argv = const_cast<char**>(argv); 416 OH_JSVM_Init(&initOptions); 417 vmInit = true; 418 } 419} 420``` 421 422Example 3: Initialize a JSVM with a low GC triggering frequency. 423```c++ 424static void LowGCFrequencyInit(bool &vmInit) { 425 if (!vmInit) { 426 // The JSVM only needs to be initialized once. 427 JSVM_InitOptions initOptions; 428 initOptions.argc = 4; 429 const char* argv[4]; 430 argv[1] = "--incremental-marking-hard-trigger=80"; 431 argv[2] = "--min-semi-space-size=16"; 432 argv[3] = "--max-semi-space-size=16"; 433 initOptions.argv = const_cast<char**>(argv); 434 OH_JSVM_Init(&initOptions); 435 vmInit = true; 436 } 437} 438``` 439 440Execution result: 441The preceding three interfaces can be used to initialize JSVMs with different capabilities. After initialization, a JSVM instance can be created to run JS scripts. Among the three interfaces: 442Calling **LowGCFrequencyInit** allows for fewer GCs than calling **NormalInit**. Calling **LowMemoryInit** allows for less memory usage than calling **NormalInit**. 443 444##### Creating a JSVM Instance 445 446Example: Create and destroy a JSVM instance (including the execution context). 447```c++ 448bool VM_INIT = false; 449 450static JSVM_Value ConsoleInfo(JSVM_Env env, JSVM_CallbackInfo info) { 451 size_t argc = 1; 452 JSVM_Value args[1]; 453 char log[256] = ""; 454 size_t logLength; 455 OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL); 456 457 OH_JSVM_GetValueStringUtf8(env, args[0], log, 255, &logLength); 458 log[255] = 0; 459 OH_LOG_INFO(LOG_APP, "JSVM API TEST: %{public}s", log); 460 return nullptr; 461} 462 463static JSVM_Value Add(JSVM_Env env, JSVM_CallbackInfo info) { 464 size_t argc = 2; 465 JSVM_Value args[2]; 466 OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL); 467 double num1, num2; 468 env, OH_JSVM_GetValueDouble(env, args[0], &num1); 469 OH_JSVM_GetValueDouble(env, args[1], &num2); 470 JSVM_Value sum = nullptr; 471 OH_JSVM_CreateDouble(env, num1 + num2, &sum); 472 return sum; 473} 474 475static napi_value MyJSVMDemo([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) { 476 std::thread t([]() { 477 // Initialized a JSVM with the required capability based on service requirements. 478 // 1. Call NormalInit to initialize the default JSVM. 479 // 2. Call LowMemoryInit to initialize a JSVM with low memory usage. 480 // 3. Call LowGCFrequencyInit to initialize a JSVM with a low GC triggering frequency. 481 NormalInit(VM_INIT); 482 // Create a VM instance and open the VM scope. 483 JSVM_VM vm; 484 JSVM_CreateVMOptions options; 485 memset(&options, 0, sizeof(options)); 486 OH_JSVM_CreateVM(&options, &vm); 487 488 JSVM_VMScope vmScope; 489 OH_JSVM_OpenVMScope(vm, &vmScope); 490 491 JSVM_CallbackStruct param[] = { 492 {.data = nullptr, .callback = ConsoleInfo}, 493 {.data = nullptr, .callback = Add}, 494 }; 495 JSVM_PropertyDescriptor descriptor[] = { 496 {"consoleinfo", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 497 {"add", NULL, ¶m[1], NULL, NULL, NULL, JSVM_DEFAULT}, 498 }; 499 // Create env, register a native method, and open an env scope. 500 JSVM_Env env; 501 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 502 503 JSVM_EnvScope envScope; 504 OH_JSVM_OpenEnvScope(env, &envScope); 505 506 // Open a handle scope. 507 JSVM_HandleScope handleScope; 508 OH_JSVM_OpenHandleScope(env, &handleScope); 509 510 std::string sourceCodeStr = "\ 511{\ 512let value = add(4.96, 5.28);\ 513consoleinfo('Result is:' + value);\ 514}\ 515"; 516 // Compile the JS script. 517 JSVM_Value sourceCodeValue; 518 OH_JSVM_CreateStringUtf8(env, sourceCodeStr.c_str(), sourceCodeStr.size(), &sourceCodeValue); 519 JSVM_Script script; 520 OH_JSVM_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script); 521 JSVM_Value result; 522 // Run the JS script. 523 OH_JSVM_RunScript(env, script, &result); 524 JSVM_ValueType type; 525 OH_JSVM_Typeof(env, result, &type); 526 OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type); 527 528 // Exit the VM and release the memory. 529 OH_JSVM_CloseHandleScope(env, handleScope); 530 531 OH_JSVM_CloseEnvScope(env, envScope); 532 OH_JSVM_DestroyEnv(env); 533 534 OH_JSVM_CloseVMScope(vm, vmScope); 535 OH_JSVM_DestroyVM(vm); 536 }); 537 538 t.detach(); 539 540 return nullptr; 541} 542``` 543 544### Compiling and Running JS Code 545 546#### When to Use 547 548Compile and run JS code. 549 550#### Available APIs 551| API | Description | 552| ------------------------------- | ---------------------------------------------------------------------------------- | 553| OH_JSVM_CompileScript | Compiles JS code and returns the compiled script bound to the current environment. | 554| OH_JSVM_CompileScriptWithOrigin | Compiles JS code and returns the compiled script bound to the current environment, with source code information including **sourceMapUrl** and source file name to process source map information.| 555| OH_JSVM_CompileScriptWithOptions | Compiles a script with the specified options. You can pass the compilation options via the **option** array, which supports option extensions.| 556| OH_JSVM_CreateCodeCache | Creates a code cache for the compiled script. | 557| OH_JSVM_RunScript | Runs a compile script. | 558 559#### Example 560 561Compile and run JS code (create a VM, register native functions, execute JS code, and destroy the VM). 562 563```c++ 564#include <cstring> 565#include <fstream> 566#include <string> 567#include <vector> 568 569// Add the dependency libjsvm.so. 570#include "ark_runtime/jsvm.h" 571 572using namespace std; 573 574static JSVM_Value Hello(JSVM_Env env, JSVM_CallbackInfo info) { 575 JSVM_Value output; 576 void* data = nullptr; 577 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data); 578 OH_JSVM_CreateStringUtf8(env, (char*)data, strlen((char*)data), &output); 579 return output; 580} 581 582static JSVM_CallbackStruct hello_cb = { Hello, (void*)"Hello" }; 583 584static string srcGlobal = R"JS( 585const concat = (...args) => args.reduce((a, b) => a + b); 586)JS"; 587 588static void RunScriptWithOption(JSVM_Env env, string& src, 589 uint8_t** dataPtr = nullptr, 590 size_t* lengthPtr = nullptr) { 591 JSVM_HandleScope handleScope; 592 OH_JSVM_OpenHandleScope(env, &handleScope); 593 594 JSVM_Value jsSrc; 595 OH_JSVM_CreateStringUtf8(env, src.c_str(), src.size(), &jsSrc); 596 597 uint8_t* data = dataPtr ? *dataPtr : nullptr; 598 auto compilMode = data ? JSVM_COMPILE_MODE_CONSUME_CODE_CACHE : JSVM_COMPILE_MODE_DEFAULT; 599 size_t length = lengthPtr ? *lengthPtr : 0; 600 JSVM_Script script; 601 // Compile the JS code. 602 JSVM_ScriptOrigin origin { 603 // In this example, the bundle name is helloworld, and the path of the source map is /data/app/el2/100/base/com.example.helloworld/files/index.js.map. 604 .sourceMapUrl = "/data/app/el2/100/base/com.example.helloworld/files/index.js.map", 605 // Name of the source file. 606 .resourceName = "index.js", 607 // Start row and column number of script in the source file 608 .resourceLineOffset = 0, 609 .resourceColumnOffset = 0, 610 }; 611 JSVM_CompileOptions option[3]; 612 option[0] = { 613 .id = JSVM_COMPILE_MODE, 614 .content = { .num = compilMode } 615 }; 616 JSVM_CodeCache codeCache = { 617 .cache = data, 618 .length = length 619 }; 620 option[1] = { 621 .id = JSVM_COMPILE_CODE_CACHE, 622 .content = { .ptr = &codeCache } 623 }; 624 // The default value of JSVM_COMPILE_ENABLE_SOURCE_MAP is false. If the value is true, sourceMapUrl cannot be empty. 625 option[2] = { 626 .id = JSVM_COMPILE_ENABLE_SOURCE_MAP, 627 .content = { .boolean = true } 628 }; 629 OH_JSVM_CompileScriptWithOptions(env, jsSrc, 3, option, &script); 630 631 JSVM_Value result; 632 // Run the JS code. 633 OH_JSVM_RunScript(env, script, &result); 634 635 char resultStr[128]; 636 size_t size; 637 OH_JSVM_GetValueStringUtf8(env, result, resultStr, 128, &size); 638 printf("%s\n", resultStr); 639 if (dataPtr && lengthPtr && *dataPtr == nullptr) { 640 // Save the script compiled from the JS source code to the cache to avoid repeated compilation and improve performance. 641 OH_JSVM_CreateCodeCache(env, script, (const uint8_t**)dataPtr, lengthPtr); 642 printf("Code cache created with length = %ld\n", *lengthPtr); 643 } 644 645 OH_JSVM_CloseHandleScope(env, handleScope); 646} 647 648static void RunScript(JSVM_Env env, string& src, 649 bool withOrigin = false, 650 uint8_t** dataPtr = nullptr, 651 size_t* lengthPtr = nullptr) { 652 JSVM_HandleScope handleScope; 653 OH_JSVM_OpenHandleScope(env, &handleScope); 654 655 JSVM_Value jsSrc; 656 OH_JSVM_CreateStringUtf8(env, src.c_str(), src.size(), &jsSrc); 657 658 uint8_t* data = dataPtr ? *dataPtr : nullptr; 659 size_t length = lengthPtr ? *lengthPtr : 0; 660 bool cacheRejected = true; 661 JSVM_Script script; 662 // Compile the JS code. 663 if (withOrigin) { 664 JSVM_ScriptOrigin origin { 665 // In this example, the bundle name is helloworld, and the path of the source map is /data/app/el2/100/base/com.example.helloworld/files/index.js.map. 666 .sourceMapUrl = "/data/app/el2/100/base/com.example.helloworld/files/index.js.map", 667 // Name of the source file. 668 .resourceName = "index.js", 669 // Start row and column number of script in the source file 670 .resourceLineOffset = 0, 671 .resourceColumnOffset = 0, 672 }; 673 OH_JSVM_CompileScriptWithOrigin(env, jsSrc, data, length, true, &cacheRejected, &origin, &script); 674 } else { 675 OH_JSVM_CompileScript(env, jsSrc, data, length, true, &cacheRejected, &script); 676 } 677 printf("Code cache is %s\n", cacheRejected ? "rejected" : "used"); 678 679 JSVM_Value result; 680 // Run the JS code. 681 OH_JSVM_RunScript(env, script, &result); 682 683 char resultStr[128]; 684 size_t size; 685 OH_JSVM_GetValueStringUtf8(env, result, resultStr, 128, &size); 686 printf("%s\n", resultStr); 687 if (dataPtr && lengthPtr && *dataPtr == nullptr) { 688 // Save the script compiled from the JS source code to the cache to avoid repeated compilation and improve performance. 689 OH_JSVM_CreateCodeCache(env, script, (const uint8_t**)dataPtr, lengthPtr); 690 printf("Code cache created with length = %ld\n", *lengthPtr); 691 } 692 693 OH_JSVM_CloseHandleScope(env, handleScope); 694} 695 696static void CreateSnapshot() { 697 JSVM_VM vm; 698 JSVM_CreateVMOptions options; 699 memset(&options, 0, sizeof(options)); 700 options.isForSnapshotting = true; 701 OH_JSVM_CreateVM(&options, &vm); 702 JSVM_VMScope vmScope; 703 OH_JSVM_OpenVMScope(vm, &vmScope); 704 705 JSVM_Env env; 706 // 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. 707 JSVM_PropertyDescriptor descriptors[] = { 708 { "hello", NULL, &hello_cb, NULL, NULL, NULL, JSVM_DEFAULT } 709 }; 710 OH_JSVM_CreateEnv(vm, 1, descriptors, &env); 711 712 JSVM_EnvScope envScope; 713 OH_JSVM_OpenEnvScope(env, &envScope); 714 // Execute the JS source code src, which can contain any JS syntax. The registered native function can also be invoked. 715 string src = srcGlobal + "concat(hello(), ', ', 'World from CreateSnapshot!');"; 716 RunScript(env, src, true); 717 718 // 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. 719 const char* blobData = nullptr; 720 size_t blobSize = 0; 721 JSVM_Env envs[1] = { env }; 722 OH_JSVM_CreateSnapshot(vm, 1, envs, &blobData, &blobSize); 723 printf("Snapshot blob size = %ld\n", blobSize); 724 725 // If you need to save the snapshot to a file, also consider the read/write permissions on the file in the application. 726 ofstream file("/data/storage/el2/base/files/blob.bin", ios::out | ios::binary | ios::trunc); 727 file.write(blobData, blobSize); 728 file.close(); 729 730 OH_JSVM_CloseEnvScope(env, envScope); 731 OH_JSVM_DestroyEnv(env); 732 OH_JSVM_CloseVMScope(vm, vmScope); 733 OH_JSVM_DestroyVM(vm); 734} 735 736void RunWithoutSnapshot(uint8_t** dataPtr, size_t* lengthPtr) { 737 // Create a VM instance. 738 JSVM_VM vm; 739 OH_JSVM_CreateVM(nullptr, &vm); 740 JSVM_VMScope vmScope; 741 OH_JSVM_OpenVMScope(vm, &vmScope); 742 743 JSVM_Env env; 744 // 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. 745 JSVM_PropertyDescriptor descriptors[] = { 746 { "hello", NULL, &hello_cb, NULL, NULL, NULL, JSVM_DEFAULT } 747 }; 748 OH_JSVM_CreateEnv(vm, 1, descriptors, &env); 749 JSVM_EnvScope envScope; 750 OH_JSVM_OpenEnvScope(env, &envScope); 751 // Execute the JS source code src, which can contain any JS syntax. The registered native function can also be invoked. 752 auto src = srcGlobal + "concat(hello(), ', ', 'World', ' from RunWithoutSnapshot!')"; 753 // Use RunScriptWithOption, which covers all the functionalities of the **Compile** APIs and provides extensions. 754 RunScriptWithOption(env, src, dataPtr, lengthPtr); 755 756 OH_JSVM_CloseEnvScope(env, envScope); 757 OH_JSVM_DestroyEnv(env); 758 OH_JSVM_CloseVMScope(vm, vmScope); 759 OH_JSVM_DestroyVM(vm); 760} 761 762void RunWithSnapshot(uint8_t **dataPtr, size_t *lengthPtr) { 763 // The lifetime of blobData cannot be shorter than that of the vm. 764 // If the snapshot needs to be read from a file, also consider the read/write permissions on the file in the application. 765 vector<char> blobData; 766 ifstream file("/data/storage/el2/base/files/blob.bin", ios::in | ios::binary | ios::ate); 767 size_t blobSize = file.tellg(); 768 blobData.resize(blobSize); 769 file.seekg(0, ios::beg); 770 file.read(blobData.data(), blobSize); 771 file.close(); 772 773 // Create a VM instance. 774 JSVM_VM vm; 775 JSVM_CreateVMOptions options; 776 memset(&options, 0, sizeof(options)); 777 options.snapshotBlobData = blobData.data(); 778 options.snapshotBlobSize = blobSize; 779 OH_JSVM_CreateVM(&options, &vm); 780 JSVM_VMScope vmScope; 781 OH_JSVM_OpenVMScope(vm, &vmScope); 782 783 // Create env from a snapshot. 784 JSVM_Env env; 785 OH_JSVM_CreateEnvFromSnapshot(vm, 0, &env); 786 JSVM_EnvScope envScope; 787 OH_JSVM_OpenEnvScope(env, &envScope); 788 789 // 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. 790 string src = "concat(hello(), ', ', 'World', ' from RunWithSnapshot!')"; 791 RunScript(env, src, true, dataPtr, lengthPtr); 792 793 OH_JSVM_CloseEnvScope(env, envScope); 794 OH_JSVM_DestroyEnv(env); 795 OH_JSVM_CloseVMScope(vm, vmScope); 796 OH_JSVM_DestroyVM(vm); 797} 798 799void PrintVmInfo() { 800 JSVM_VMInfo vmInfo; 801 OH_JSVM_GetVMInfo(&vmInfo); 802 printf("apiVersion: %d\n", vmInfo.apiVersion); 803 printf("engine: %s\n", vmInfo.engine); 804 printf("version: %s\n", vmInfo.version); 805 printf("cachedDataVersionTag: 0x%x\n", vmInfo.cachedDataVersionTag); 806} 807 808static intptr_t externals[] = { 809 (intptr_t)&hello_cb, 810 0, 811}; 812 813int main(int argc, char *argv[]) { 814 if (argc <= 1) { 815 printf("Usage: %s gen-snapshot|use-snapshot|no-snapshot\n", argv[0]); 816 return 0; 817 } 818 819 JSVM_InitOptions initOptions; 820 memset(&initOptions, 0, sizeof(initOptions)); 821 initOptions.externalReferences = externals; 822 // Initialize the VM, which can be initialized only once in a process. 823 OH_JSVM_Init(&initOptions); 824 PrintVmInfo(); 825 826 if (argv[1] == string("gen-snapshot")) { 827 CreateSnapshot(); 828 return 0; 829 } 830 831 // 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. 832 const auto useSnapshot = argv[1] == string("use-snapshot"); 833 const auto run = useSnapshot ? RunWithSnapshot : RunWithoutSnapshot; 834 uint8_t* data = nullptr; 835 size_t length = 0; 836 run(&data, &length); 837 run(&data, &length); 838 delete[] data; 839 840 return 0; 841} 842``` 843 844### Compiling the Wasm Module 845 846#### When to Use 847 848JSVM-API provides APIs for compiling the WebAssembly (Wasm) bytecode, optimizing Wasm functions, and serializing and deserializing Wasm caches. 849 850#### Available APIs 851 852| API | Description | 853| --------------------------- | ------------------------------------------------------------------------------------ | 854| OH_JSVM_CompileWasmModule | Compiles the Wasm bytecode into a Wasm module. If the **cache** parameter is passed in, the cache will be deserialized into a Wasm module first. The compilation is performed when the deserialization fails.| 855| OH_JSVM_CompileWasmFunction | Compiles the function with the specified ID in a Wasm module into the optimized machine code. Currently, only the highest optimization level is enabled. The validity of the function ID is ensured by the caller. | 856| OH_JSVM_IsWasmModuleObject | Checks whether the input value is a Wasm module. | 857| OH_JSVM_CreateWasmCache | Serializes the machine code in a Wasm module into a Wasm cache. If the Wasm module does not contain machine code, the serialization will fail. | 858| OH_JSVM_ReleaseCache | Releases a Wasm cache instance created by JSVM-API. The **cacheType** and **cacheData** passed in must match. Otherwise, undefined behavior may occur. | 859 860#### Example 861 862See [Working with Wasm Using JSVM-API](use-jsvm-about-wasm.md). 863 864### Exception Handling 865 866#### When to Use 867 868Capture, throw, and clear JS exceptions as required. 869 870#### Available APIs 871| API| Description| 872| -------- | -------- | 873| OH_JSVM_Throw| Throws a JS value.| 874| OH_JSVM_ThrowTypeError| Throws a JS type error.| 875| OH_JSVM_ThrowRangeError| Throws a JS range error.| 876| OH_JSVM_IsError| Checks whether a JS value indicates an error.| 877| OH_JSVM_CreateError| Creates a JS error.| 878| OH_JSVM_CreateTypeError| Creates a JS type error and returns it.| 879| OH_JSVM_CreateRangeError| Creates a JS range error and returns it.| 880| OH_JSVM_ThrowError| Throws a JS exception.| 881| OH_JSVM_GetAndClearLastException| Obtains and clears the last JS exception.| 882| OH_JSVM_IsExceptionPending| Checks whether an exception occurs.| 883| OH_JSVM_GetLastErrorInfo| Obtains information about the last exception.| 884| OH_JSVM_ThrowSyntaxError| Throws a JS syntax error.| 885| OH_JSVM_CreateSyntaxError| Creates a JS syntax error and returns it.| 886 887#### Example 888Create, judge, and throw a JS type error. 889 890```c++ 891JSVM_Value code = nullptr; 892JSVM_Value message = nullptr; 893OH_JSVM_CreateStringUtf8(env, "500", JSVM_AUTO_LENGTH, &code); 894OH_JSVM_CreateStringUtf8(env, "type error 500", JSVM_AUTO_LENGTH, &message); 895JSVM_Value error = nullptr; 896OH_JSVM_CreateTypeError(env, code, message, &error); 897bool isError = false; 898OH_JSVM_IsError(env, error, &isError); 899OH_JSVM_ThrowTypeError(env, nullptr, "type error1"); 900``` 901 902Call **OH_JSVM_GetAndClearLastException** to log the exception information as a string to the console. 903 904```c++ 905if (status != JSVM_OK) // An exception occurs when the execution fails. 906{ 907 bool isPending = false; 908 if (JSVM_OK == OH_JSVM_IsExceptionPending((env), &isPending) && isPending) 909 { 910 JSVM_Value error; 911 if (JSVM_OK == OH_JSVM_GetAndClearLastException((env), &error)) 912 { 913 // Obtain the exception stack. 914 JSVM_Value stack; 915 OH_JSVM_GetNamedProperty((env), error, "stack", &stack); 916 917 JSVM_Value message; 918 OH_JSVM_GetNamedProperty((env), error, "message", &message); 919 920 char stackstr[256]; 921 OH_JSVM_GetValueStringUtf8(env, stack, stackstr, 256, nullptr); 922 OH_LOG_INFO(LOG_APP, "JSVM error stack: %{public}s", stackstr); 923 924 char messagestr[256]; 925 OH_JSVM_GetValueStringUtf8(env, message, messagestr, 256, nullptr); 926 OH_LOG_INFO(LOG_APP, "JSVM error message: %{public}s", messagestr); 927 } 928 } 929} 930``` 931 932### Object Lifetime Management 933 934When 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. 935 936 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. 937 938However, 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. 939 940#### Available APIs 941| API| Description| 942| -------- | -------- | 943| OH_JSVM_OpenHandleScope| Opens a handle scope. The object within the scope will not be garbage-collected until the handle scope is closed.| 944| OH_JSVM_CloseHandleScope| Closes a handle scope. The object within the scope will be garbage-collected after the handle scope is closed.| 945| 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.| 946| OH_JSVM_CloseEscapableHandleScope| Closes an escapable handle scope.| 947| OH_JSVM_EscapeHandle| Promotes a handle to a JS object so that it is valid for the lifetime of the outer scope.| 948| 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 monitors the lifecycle of the object.| 949| 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.| 950| OH_JSVM_ReferenceRef| Increments the reference count of the reference created by **OH_JSVM_CreateReference** so that the object referenced will not be released.| 951| 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.| 952| OH_JSVM_GetReferenceValue| Obtains the object referenced by **OH_JSVM_CreateReference**.| 953| OH_JSVM_RetainScript | Retains a **JSVM_Script** persistently so that it can be used out of the current scope.| 954| OH_JSVM_ReleaseScript | Releases a **JSVM_Script** that is persistently retained. The released **JSVM_Script** will no longer be used and must be left empty.| 955 956#### Example 957 958Use a handle scope to protect an object created within the scope from being reclaimed. 959 960```c++ 961JSVM_HandleScope scope; 962OH_JSVM_OpenHandleScope(env, &scope); 963JSVM_Value obj = nullptr; 964OH_JSVM_CreateObject(env, &obj); 965OH_JSVM_CloseHandleScope(env, scope); 966``` 967 968Use an escapable handle scope to protect an object from being reclaimed within its parent scope. 969 970```c++ 971JSVM_EscapableHandleScope scope; 972JSVM_CALL(env, OH_JSVM_OpenEscapableHandleScope(env, &scope)); 973JSVM_Value output = NULL; 974JSVM_Value escapee = NULL; 975JSVM_CALL(env, OH_JSVM_CreateObject(env, &output)); 976JSVM_CALL(env, OH_JSVM_EscapeHandle(env, scope, output, &escapee)); 977JSVM_CALL(env, OH_JSVM_CloseEscapableHandleScope(env, scope)); 978return escapee; 979``` 980 981Reference a JS object and release the reference. 982 983```c++ 984JSVM_Value obj = nullptr; 985OH_JSVM_CreateObject(env, &obj); 986// Create a reference. 987JSVM_Ref reference; 988OH_JSVM_CreateReference(env, obj, 1, &reference); 989 990// Create a reference with a JS object. 991JSVM_Value result; 992OH_JSVM_GetReferenceValue(env, reference, &result); 993 994// Release the reference. 995OH_JSVM_DeleteReference(env, reference); 996``` 997 998Use **RetainScript()** to persistently hold **JSVM_Script** and use it. 999 1000```c++ 1001JSVM_HandleScope scope; 1002OH_JSVM_OpenHandleScope(env, &scope); 1003JSVM_Script script; 1004JSVM_Value jsSrc; 1005std::string src(R"JS( 1006let a = 37; 1007a = a * 9; 1008)JS"); 1009OH_JSVM_CreateStringUtf8(env, src.c_str(), src.size(), &jsSrc); 1010OH_JSVM_CompileScriptWithOptions(env, jsSrc, 0, nullptr, &script); 1011OH_JSVM_RetainScript(env, script); 1012OH_JSVM_CloseHandleScope(env, scope); 1013 1014// Run a JSVM script. 1015OH_JSVM_OpenHandleScope(env, &scope); 1016JSVM_Value result; 1017OH_JSVM_RunScript(env, script, &result); 1018 1019// Release a JSVM script and set it to null. 1020OH_JSVM_ReleaseScript(env, script); 1021script = nullptr; 1022OH_JSVM_CloseHandleScope(env, scope); 1023``` 1024 1025### Creating JS Object Types and Basic Types 1026 1027#### When to Use 1028 1029Create JS object types and basic types. 1030 1031#### Available APIs 1032| API| Description| 1033| -------- | -------- | 1034|OH_JSVM_CreateArray | Creates a JS array object.| 1035|OH_JSVM_CreateArrayWithLength | Creates a JS array object of the specified length.| 1036|OH_JSVM_CreateArraybuffer | Creates an **ArrayBuffer** object of the specified size.| 1037|OH_JSVM_CreateDate | Creates a date object representing the given number of milliseconds.| 1038|OH_JSVM_CreateExternal | Creates a JS object that wraps an external pointer.| 1039|OH_JSVM_CreateObject | Creates a default JS object.| 1040|OH_JSVM_CreateSymbol | Creates a symbol object based on the given descriptor.| 1041|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.| 1042|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.| 1043|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.| 1044|OH_JSVM_CreateInt32 | Creates a JS number object from a C Int32_t object.| 1045|OH_JSVM_CreateUint32 | Creates a JS number object from a C Uint32_t object.| 1046|OH_JSVM_CreateInt64 | Creates a JS number object from a C Int64_t object.| 1047|OH_JSVM_CreateDouble | Creates a JS number object from a C Double object.| 1048|OH_JSVM_CreateBigintInt64 | Creates a JS BigInt object from a C Int64 object.| 1049|OH_JSVM_CreateBigintUint64 | Creates a JS BigInt object from a C Uint64 object.| 1050|OH_JSVM_CreateBigintWords | Creates a JS BigInt object from a C Uint64_t array.| 1051|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.| 1052|OH_JSVM_CreateStringUtf16 | Creates a JS string object from a UTF16-encoded C string.| 1053|OH_JSVM_CreateStringUtf8 | Creates a JS string object from a UTF8-encoded C string.| 1054|OH_JSVM_CreateMap | Creates a JS **Map** object.| 1055|OH_JSVM_CreateRegExp | Creates a JS regular expression object based on the given string.| 1056|OH_JSVM_CreateSet | Creates a JS **Set** object.| 1057 1058#### Example 1059 1060Create a JS array of the specified length. 1061 1062```c++ 1063size_t arrayLength = 2; 1064JSVM_Value arr; 1065 1066OH_JSVM_CreateArrayWithLength(env, arrayLength, &arr); 1067for (uint32_t i = 0; i < arrayLength; i++) 1068{ 1069 JSVM_Value element; 1070 OH_JSVM_CreateUint32(env, i * 2, &element); 1071 OH_JSVM_SetElement(env, arr, i, element); 1072} 1073``` 1074 1075Create a JS Int32Array. 1076 1077```c++ 1078JSVM_Value arrayBuffer = nullptr; 1079void *arrayBufferPtr = nullptr; 1080size_t arrayBufferSize = 16; 1081size_t typedArrayLength = 4; 1082OH_JSVM_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer); 1083 1084void *tmpArrayBufferPtr = nullptr; 1085size_t arrayBufferLength = 0; 1086OH_JSVM_GetArraybufferInfo(env, arrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength); 1087 1088JSVM_Value result; 1089OH_JSVM_CreateTypedarray(env, JSVM_TypedarrayType::JSVM_INT32_ARRAY, typedArrayLength, arrayBuffer, 0, &result); 1090return result; 1091``` 1092 1093Create JS numbers and strings. 1094 1095```c++ 1096const char *testStringStr = "test"; 1097JSVM_Value testString = nullptr; 1098OH_JSVM_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString); 1099 1100JSVM_Value testNumber1 = nullptr; 1101JSVM_Value testNumber2 = nullptr; 1102OH_JSVM_CreateDouble(env, 10.1, &testNumber1); 1103OH_JSVM_CreateInt32(env, 10, &testNumber2); 1104``` 1105 1106Create a map. 1107 1108```c++ 1109JSVM_Value value = nullptr; 1110OH_JSVM_CreateMap(env, &value); 1111``` 1112 1113Create a regular expression. 1114 1115```c++ 1116JSVM_Value value = nullptr; 1117const char testStr[] = "ab+c"; 1118OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &value); 1119JSVM_Value result = nullptr; 1120OH_JSVM_CreateRegExp(env, value, JSVM_RegExpFlags::JSVM_REGEXP_GLOBAL, &result); 1121``` 1122 1123Create a **set()** instance. 1124 1125```c++ 1126JSVM_Value value; 1127OH_JSVM_CreateSet(env, &value); 1128``` 1129 1130### Obtaining C Types or JS Type Information from JS Types 1131 1132#### When to Use 1133 1134Obtain C types or JS type information from JS types. 1135 1136#### Available APIs 1137| API| Description| 1138| -------- | -------- | 1139|OH_JSVM_GetArrayLength | Obtains the length of an array.| 1140|OH_JSVM_GetArraybufferInfo | Obtains the underlying data buffer of an **ArrayBuffer** and its length.| 1141|OH_JSVM_GetPrototype | Obtains the prototype of a JS object.| 1142|OH_JSVM_GetTypedarrayInfo | Obtains information about a **TypedArray** object.| 1143|OH_JSVM_GetDataviewInfo | Obtains information about a **DataView** object.| 1144|OH_JSVM_GetDateValue | Obtains the C double primitive of the time value for the given JS **Date** object.| 1145|OH_JSVM_GetValueBool | Obtains the C Boolean primitive equivalent of the given JS Boolean.| 1146|OH_JSVM_GetValueDouble | Obtains the C Double primitive equivalent of the given JS number.| 1147|OH_JSVM_GetValueBigintInt64 | Obtains the C Int64_t primitive equivalent of the given JS BigInt.| 1148|OH_JSVM_GetValueBigintUint64 | Obtains the C Uint64_t primitive equivalent of the given JS BigInt.| 1149|OH_JSVM_GetValueBigintWords | Obtains the underlying data of a given JS BigInt object, that is, the word representation of BigInt data.| 1150|OH_JSVM_GetValueExternal | Obtains the external data pointer previously passed to **OH_JSVM_CreateExternal**.| 1151|OH_JSVM_GetValueInt32 | Obtains the C Int32 primitive equivalent of the given JS number.| 1152|OH_JSVM_GetValueInt64 | Obtains the C Int64 primitive equivalent of the given JS number.| 1153|OH_JSVM_GetValueStringLatin1 | Obtains the ISO-8859-1-encoded string from the given JS string.| 1154|OH_JSVM_GetValueStringUtf8 | Obtains the UTF8-encoded string from the given JS string.| 1155|OH_JSVM_GetValueStringUtf16 | Obtains the UTF16-encoded string from the given JS string.| 1156|OH_JSVM_GetValueUint32 | Obtains the C primitive equivalent (a Uint32) of the given JS number.| 1157|OH_JSVM_GetBoolean | Obtains a JS singleton object that is used to represent the given Boolean value.| 1158|OH_JSVM_GetGlobal | Obtains the **global** object of the current environment.| 1159|OH_JSVM_GetNull | Obtains the JS **null** object.| 1160|OH_JSVM_GetUndefined | Obtains the JS **Undefined** object.| 1161 1162#### Example 1163 1164Create a JS BigInt object from a C Int64 object and obtain the C Int64_t primitive equivalent. 1165 1166```c++ 1167int64_t testValue = INT64_MAX; 1168JSVM_Value result = nullptr; 1169OH_JSVM_CreateBigintInt64(env, testValue, &result); 1170int64_t resultValue = 0; 1171bool flag = false; 1172OH_JSVM_GetValueBigintInt64(env, result, &resultValue, &flag); 1173``` 1174 1175Create an Int32Array and obtain its information such as the length and byte offset. 1176 1177```c++ 1178JSVM_Value arrayBuffer = nullptr; 1179void *arrayBufferPtr = nullptr; 1180size_t arrayBufferSize = 16; 1181size_t typedArrayLength = 4; 1182OH_JSVM_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer); 1183 1184bool isArrayBuffer = false; 1185OH_JSVM_IsArraybuffer(env, arrayBuffer, &isArrayBuffer); 1186 1187JSVM_Value result; 1188OH_JSVM_CreateTypedarray(env, JSVM_TypedarrayType::JSVM_INT32_ARRAY, typedArrayLength, arrayBuffer, 0, &result); 1189 1190bool isTypedArray = false; 1191OH_JSVM_IsTypedarray(env, result, &isTypedArray); 1192 1193 1194JSVM_TypedarrayType type; 1195size_t length = 0; 1196void *data = nullptr; 1197JSVM_Value retArrayBuffer; 1198size_t byteOffset = -1; 1199OH_JSVM_GetTypedarrayInfo(env, result, &type, &length, &data, &retArrayBuffer, &byteOffset); 1200 1201 1202bool retIsArrayBuffer = false; 1203OH_JSVM_IsArraybuffer(env, retArrayBuffer, &retIsArrayBuffer); 1204void *tmpArrayBufferPtr = nullptr; 1205size_t arrayBufferLength = 0; 1206OH_JSVM_GetArraybufferInfo(env, retArrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength); 1207``` 1208 1209Create a JS string object from a UTF8-encoded C string and obtain the C string. 1210 1211```c++ 1212const char *testStringStr = "testString"; 1213JSVM_Value testString = nullptr; 1214OH_JSVM_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString); 1215 1216char buffer[128]; 1217size_t bufferSize = 128; 1218size_t copied; 1219 1220OH_JSVM_GetValueStringUtf8(env, testString, buffer, bufferSize, &copied); 1221``` 1222 1223### Working with JS Values and Abstract Operations 1224 1225#### When to Use 1226 1227Perform abstract operations on JS values. 1228 1229#### Available APIs 1230| API| Description| 1231| -------- | -------- | 1232|OH_JSVM_CoerceToBool | Converts a JS value to an object of the Boolean type.| 1233|OH_JSVM_CoerceToNumber | Converts a JS value to an object of the number type.| 1234|OH_JSVM_CoerceToObject | Converts a JS value to an object of the object type.| 1235|OH_JSVM_CoerceToString | Converts a JS value to an object of the string type.| 1236|OH_JSVM_CoerceToBigInt | Converts a JS value to an object of the BigInt type.| 1237|OH_JSVM_Typeof | Returns the type of a JS object.| 1238|OH_JSVM_Instanceof | Checks whether an object is an instance of a constructor.| 1239|OH_JSVM_IsArray | Checks whether a JS object is an array.| 1240|OH_JSVM_IsArraybuffer | Checks whether a JS object is an array buffer.| 1241|OH_JSVM_IsDate | Checks whether a JS object is a **Date** object.| 1242|OH_JSVM_IsTypedarray | Checks whether a JS object is a **TypedArray** object.| 1243|OH_JSVM_IsDataview | Checks whether a JS object is a **DataView** object.| 1244|OH_JSVM_IsUndefined | Checks whether the value passed in is **Undefined**. This API is equivalent to executing JS code **value === undefined**.| 1245|OH_JSVM_IsNull | Checks whether the value passed in is a **Null** object. This API is equivalent to executing JS code **value === null**.| 1246|OH_JSVM_IsNullOrUndefined | Checks whether the value passed in is **Null** or **Undefined**. This API is equivalent to executing JS code **value == null**.| 1247|OH_JSVM_IsBoolean | Checks whether the value passed in is a Boolean value. This API is equivalent to executing JS code **typeof value ==='boolean'**.| 1248|OH_JSVM_IsNumber | Checks whether the value passed in is a number. This API is equivalent to executing JS code **typeof value === 'number'**.| 1249|OH_JSVM_IsString | Checks whether the value passed in is a string. This API is equivalent to executing JS code **typeof value === 'string'**.| 1250|OH_JSVM_IsSymbol | Checks whether the value passed in is a symbol. This API is equivalent to executing JS code **typeof value === 'symbol'**.| 1251|OH_JSVM_IsFunction | Checks whether the value passed in is a function. This API is equivalent to executing JS code **typeof value === 'function'**.| 1252|OH_JSVM_IsObject | Checks whether the value passed in is an object .| 1253|OH_JSVM_IsBigInt | Checks whether the value passed in is a BigInt. This API is equivalent to executing JS code **typeof value === 'bigint'**.| 1254|OH_JSVM_IsConstructor | Checks whether the value passed in is a constructor.| 1255|OH_JSVM_IsMap | Checks whether the value passed in is a map.| 1256|OH_JSVM_IsSet | Checks whether the value passed in is a **set()** instance.| 1257|OH_JSVM_IsRegExp | Checks whether the value passed in is a regular expression.| 1258|OH_JSVM_StrictEquals | Checks whether two **JSVM_Value** objects are strictly equal.| 1259|OH_JSVM_Equals | Checks whether two **JSVM_Value** objects are roughly equal.| 1260|OH_JSVM_DetachArraybuffer | Calls the **Detach()** operation of an **ArrayBuffer** object.| 1261|OH_JSVM_IsDetachedArraybuffer | Checks whether an **ArrayBuffer** object has been detached.| 1262 1263#### Example 1264 1265Check whether a JS value is of the array type. 1266 1267```c++ 1268JSVM_Value array = nullptr; 1269OH_JSVM_CreateArray(env, &array); 1270bool isArray = false; 1271OH_JSVM_IsArray(env, array, &isArray); 1272``` 1273 1274Convert a JS int32 value to a string. 1275 1276```c++ 1277int32_t num = 123; 1278JSVM_Value intValue; 1279OH_JSVM_CreateInt32(env, num, &intValue); 1280JSVM_Value stringValue; 1281OH_JSVM_CoerceToString(env, intValue, &stringValue); 1282 1283char buffer[128]; 1284size_t bufferSize = 128; 1285size_t copied = 0; 1286 1287OH_JSVM_GetValueStringUtf8(env, stringValue, buffer, bufferSize, &copied); 1288// buffer:"123"; 1289``` 1290 1291Convert a JS boolean value to a bigint. 1292 1293```c++ 1294JSVM_Value boolValue; 1295OH_JSVM_GetBoolean(env, false, &boolValue); 1296JSVM_Value bigIntValue; 1297OH_JSVM_CoerceToBigInt(env, boolValue, &bigIntValue); 1298``` 1299 1300Check 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. 1301 1302```c++ 1303JSVM_Value value = nullptr; 1304JSVM_Value value1 = nullptr; 1305OH_JSVM_CreateArray(env, &value); 1306 1307OH_JSVM_CreateInt32(env, 10, &value1); 1308bool isArray = true; 1309OH_JSVM_StrictEquals(env, value, value, &isArray); 1310``` 1311 1312Check 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 in other cases. 1313 1314```c++ 1315JSVM_HandleScope handleScope; 1316OH_JSVM_OpenHandleScope(env, &handleScope); 1317const char testStr[] = "1"; 1318JSVM_Value lhs = nullptr; 1319OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &lhs); 1320JSVM_Value rhs; 1321OH_JSVM_CreateInt32(env, 1, &rhs); 1322bool isEquals = false; 1323OH_JSVM_Equals(env, lhs, rhs, &isEquals); // The value of isEquals is true. 1324OH_JSVM_CloseHandleScope(env, handleScope); 1325``` 1326 1327Check whether the JS value is a constructor. 1328 1329```c++ 1330JSVM_Value SayHello(JSVM_Env env, JSVM_CallbackInfo info) 1331{ 1332 return nullptr; 1333} 1334JSVM_Value value = nullptr; 1335JSVM_CallbackStruct param; 1336param.data = nullptr; 1337param.callback = SayHello; 1338OH_JSVM_CreateFunction(env, "func", JSVM_AUTO_LENGTH, ¶m, &value); 1339bool isConstructor = false; 1340OH_JSVM_IsConstructor(env, value, &isConstructor); // The value of isConstructor is true. 1341``` 1342 1343Check whether the JS value is of the map type. 1344 1345```c++ 1346JSVM_Value value = nullptr; 1347OH_JSVM_CreateMap(env, &value); 1348bool isMap = false; 1349OH_JSVM_IsMap(env, value, &isMap); // The value of isMap is true. 1350``` 1351 1352Check whether the JS value is a **Set()** instance. 1353 1354```c++ 1355JSVM_Value value; 1356OH_JSVM_CreateSet(env, &value); 1357bool isSet = false; 1358OH_JSVM_IsSet(env, value, &isSet); // The value of isSet is true. 1359``` 1360 1361Check whether the JS value is a regular expression. 1362 1363```c++ 1364JSVM_Value value = nullptr; 1365const char testStr[] = "ab+c"; 1366OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &value); 1367JSVM_Value result = nullptr; 1368OH_JSVM_CreateRegExp(env, value, JSVM_RegExpFlags::JSVM_REGEXP_GLOBAL, &result); 1369bool isRegExp = false; 1370OH_JSVM_IsRegExp(env, result, &isRegExp); 1371``` 1372 1373### Working with JS Properties 1374 1375#### When to Use 1376 1377Set, get, delete, and check properties of JS objects. 1378 1379#### Available APIs 1380| API| Description| 1381| -------- | -------- | 1382|OH_JSVM_GetPropertyNames | Obtains the names of all enumerable properties of a JS object as a JS array.| 1383|OH_JSVM_GetAllPropertyNames | Obtains the names of all available properties of a JS object as a JS array.| 1384|OH_JSVM_SetProperty | Sets a property for a JS object.| 1385|OH_JSVM_GetProperty | Obtains the requested property from a JS object.| 1386|OH_JSVM_HasProperty | Checks whether a JS object has the specified property.| 1387|OH_JSVM_DeleteProperty | Deletes a property from a JS object.| 1388|OH_JSVM_HasOwnProperty | Checks whether a JS object has the specified own property.| 1389|OH_JSVM_SetNamedProperty | Sets a property with the given property name for a JS object. This API is equivalent to calling **OH_JSVM_SetProperty** with a **JSVM_Value** created from the string passed in as **utf8Name**.| 1390|OH_JSVM_GetNamedProperty | Obtains the property from a JS object with the given property name. This API is equivalent to calling **OH_JSVM_GetProperty** with a **JSVM_Value** created from the string passed in as **utf8Name**.| 1391|OH_JSVM_HasNamedProperty | Checks whether a JS object has the specified property. This API is equivalent to calling **OH_JSVM_HasProperty** using a **JSVM_Value** created from the string passed in as **utf8Name**.| 1392|OH_JSVM_SetElement | Sets an element at the specified index for a JS object.| 1393|OH_JSVM_GetElement | Obtains the element at the specified index of a JS object.| 1394|OH_JSVM_HasElement | Checks whether a JS object has an element at the specified index.| 1395|OH_JSVM_DeleteElement | Deletes the element at the specified index from a JS object.| 1396|OH_JSVM_DefineProperties | Defines multiple properties for a JS object.| 1397|OH_JSVM_ObjectFreeze | Freeze 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.| 1398|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.| 1399|OH_JSVM_ObjectSetPrototypeOf | Sets a prototype for a given object.| 1400|OH_JSVM_ObjectGetPrototypeOf | Obtains the prototype of a JS object.| 1401 1402#### Example 1403 1404Set, get, delete, and check properties of a JS object. 1405 1406```c++ 1407// Create an empty object. 1408JSVM_Value myObject = nullptr; 1409OH_JSVM_CreateObject(env, &myObject); 1410 1411// Set properties. 1412const char *testNameStr = "John Doe"; 1413JSVM_Value propValue = nullptr; 1414JSVM_Value key; 1415OH_JSVM_CreateStringUtf8(env, "name", JSVM_AUTO_LENGTH, &key); 1416OH_JSVM_CreateStringUtf8(env, testNameStr, strlen(testNameStr), &propValue); 1417OH_JSVM_SetProperty(env, myObject, key, propValue); 1418 1419// Obtain properties. 1420JSVM_Value propResult = nullptr; 1421OH_JSVM_GetProperty(env, myObject, key, &propResult); 1422 1423// Check whether a property exists. 1424bool hasProperty = false; 1425OH_JSVM_HasNamedProperty(env, myObject, "name", &hasProperty); 1426 // The property exists. Perform subsequent processing accordingly. 1427 if (hasProperty) 1428 { 1429 // Obtain all property names of the object. 1430 JSVM_Value propNames = nullptr; 1431 OH_JSVM_GetPropertyNames(env, myObject, &propNames); 1432 1433 bool isArray = false; 1434 OH_JSVM_IsArray(env, propNames, &isArray); 1435 1436 uint32_t arrayLength = 0; 1437 OH_JSVM_GetArrayLength(env, propNames, &arrayLength); 1438 // Traverse property elements. 1439 for (uint32_t i = 0; i < arrayLength; i++) 1440 { 1441 bool hasElement = false; 1442 OH_JSVM_HasElement(env, propNames, i, &hasElement); 1443 1444 JSVM_Value propName = nullptr; 1445 OH_JSVM_GetElement(env, propNames, i, &propName); 1446 1447 bool hasProp = false; 1448 OH_JSVM_HasProperty(env, myObject, propName, &hasProp); 1449 1450 JSVM_Value propValue = nullptr; 1451 OH_JSVM_GetProperty(env, myObject, propName, &propValue); 1452 } 1453 } 1454 1455// Delete a property. 1456OH_JSVM_DeleteProperty(env, myObject, key, &hasProperty); 1457 1458// Set the object prototype. 1459JSVM_Value value; 1460OH_JSVM_CreateSet(env, &value); 1461OH_JSVM_ObjectSetPrototypeOf(env, myObject, value); 1462 1463// Obtain the object prototype. 1464JSVM_Value proto; 1465OH_JSVM_ObjectGetPrototypeOf(env, myObject, &proto); 1466``` 1467 1468### Working with JS Functions 1469 1470#### When to Use 1471 1472Call back JS code into native code and call JS functions from native code. 1473 1474#### Available APIs 1475| API| Description| 1476| -------- | -------- | 1477|OH_JSVM_CallFunction | Calls a JS function from a C/C++ addon.| 1478|OH_JSVM_CreateFunction | Creates a JS function object in native code, which allows calling into the native code from JS.| 1479|OH_JSVM_GetCbInfo | Obtains detailed information about the call, such as the parameters and **this** pointer, from the given callback information.| 1480|OH_JSVM_GetNewTarget | Obtains the **new.target** of the constructor call.| 1481|OH_JSVM_NewInstance | Creates an instance based on the given constructor.| 1482|OH_JSVM_CreateFunctionWithScript | Creates a JS function object based on the given function body and parameter list.| 1483 1484#### Example 1485 1486Create a JS function. 1487 1488```c++ 1489JSVM_Value SayHello(JSVM_Env env, JSVM_CallbackInfo info) 1490{ 1491 printf("Hello\n"); 1492 JSVM_Value ret; 1493 OH_JSVM_CreateInt32(env, 2, &ret); 1494 return ret; 1495} 1496 1497static JSVM_Value JsvmCreateFunction(JSVM_Env env, JSVM_CallbackInfo info) 1498{ 1499 JSVM_CallbackStruct param; 1500 param.data = nullptr; 1501 param.callback = SayHello; 1502 1503 JSVM_Value funcValue = nullptr; 1504 JSVM_Status status = OH_JSVM_CreateFunction(env, "func", JSVM_AUTO_LENGTH, ¶m, &funcValue); 1505 return funcValue; 1506} 1507``` 1508 1509Obtain and call the JS function from C/C++. 1510 1511```c++ 1512static JSVM_Value CallFunction(JSVM_Env env, JSVM_CallbackInfo info) 1513{ 1514 size_t argc = 1; 1515 JSVM_Value args[1]; 1516 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL)); 1517 1518 JSVM_ASSERT(env, argc >= 1, "Wrong number of arguments"); 1519 1520 JSVM_ValueType valuetype; 1521 JSVM_CALL(env, OH_JSVM_Typeof(env, args[0], &valuetype)); 1522 JSVM_ASSERT(env, valuetype == JSVM_ValueType::JSVM_FUNCTION, "Wrong type of argment. Expects a string."); 1523 1524 JSVM_Value global; 1525 JSVM_CALL(env, OH_JSVM_GetGlobal(env, &global)); 1526 1527 JSVM_Value ret; 1528 JSVM_CALL(env, OH_JSVM_CallFunction(env, global, args[0], 0, nullptr, &ret)); 1529 return ret; 1530} 1531``` 1532 1533Create a function. 1534 1535```c++ 1536JSVM_Value script; 1537OH_JSVM_CreateStringUtf8(env, "return a + b;", JSVM_AUTO_LENGTH, &script); 1538JSVM_Value param1; 1539JSVM_Value param2; 1540OH_JSVM_CreateStringUtf8(env, "a", JSVM_AUTO_LENGTH, ¶m1); 1541OH_JSVM_CreateStringUtf8(env, "b", JSVM_AUTO_LENGTH, ¶m2); 1542JSVM_Value argus[] = {param1, param2}; 1543JSVM_Value func; 1544OH_JSVM_CreateFunctionWithScript(env, "add", JSVM_AUTO_LENGTH, 2, argus, script, &func); 1545``` 1546 1547### Wrapping Objects 1548 1549#### When to Use 1550 1551Wrap native classes and instances so that the class constructor and methods can be called from JS. 1552 1553#### Available APIs 1554| API| Description| 1555| -------- | -------- | 1556|OH_JSVM_DefineClass| Defines a JS class and associated functions within a C/C++ addon. It allows you to define a constructor, methods, and properties that can be accessed from JS.| 1557|OH_JSVM_Wrap| Wraps a native instance in a JS object. You can use **OH_JSVM_Unwrap()** to retrieve the native instance later.| 1558|OH_JSVM_Unwrap | Retrieves a native instance from a JS object.| 1559|OH_JSVM_RemoveWrap | Retrieves a native instance previously wrapped in a JS object and removes the wrapping.| 1560|OH_JSVM_TypeTagObject | Associates the value of the **type_tag** pointer with a JS object or an external object.| 1561|OH_JSVM_CheckObjectTypeTag | Check whether a tag matches the tag type of an object.| 1562|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.| 1563|OH_JSVM_DefineClassWithPropertyHandler | Defines a JS class with the given class name, constructor, property, and callback handler, and calls it as a function callback. The property operations include getter, setter, deleter, and enumerator.| 1564|OH_JSVM_DefineClassWithOptions | Defines a JS class with the given class name, constructor, properties, callback handler, and parent class. The **DefineClassOptions** parameter specifies whether to set a property proxy for the defined class, reserve the internal-field slot, and set a callback when the class is called as a function. | 1565 1566#### Example 1567 1568Wrap a native object in a JS object. 1569 1570```c++ 1571static JSVM_Value AssertEqual(JSVM_Env env, JSVM_CallbackInfo info) 1572{ 1573 size_t argc = 2; 1574 JSVM_Value args[2]; 1575 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL)); 1576 1577 bool isStrictEquals = false; 1578 OH_JSVM_StrictEquals(env, args[0], args[1], &isStrictEquals); 1579 return nullptr; 1580} 1581 1582static napi_value TestWrap(napi_env env1, napi_callback_info info) 1583{ 1584 OH_LOG_ERROR(LOG_APP, "testWrap start"); 1585 JSVM_InitOptions init_options; 1586 memset(&init_options, 0, sizeof(init_options)); 1587 init_options.externalReferences = externals; 1588 if (aa == 0) { 1589 OH_JSVM_Init(&init_options); 1590 aa++; 1591 } 1592 JSVM_VM vm; 1593 JSVM_CreateVMOptions options; 1594 memset(&options, 0, sizeof(options)); 1595 OH_JSVM_CreateVM(&options, &vm); 1596 JSVM_VMScope vm_scope; 1597 OH_JSVM_OpenVMScope(vm, &vm_scope); 1598 JSVM_Env env; 1599 JSVM_CallbackStruct param[1]; 1600 param[0].data = nullptr; 1601 param[0].callback = AssertEqual; 1602 JSVM_PropertyDescriptor descriptor[] = { 1603 {"assertEqual", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 1604 }; 1605 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 1606 JSVM_EnvScope envScope; 1607 OH_JSVM_OpenEnvScope(env, &envScope); 1608 JSVM_HandleScope handlescope; 1609 OH_JSVM_OpenHandleScope(env, &handlescope); 1610 JSVM_Value testClass = nullptr; 1611 JSVM_CallbackStruct param1; 1612 param1.data = nullptr; 1613 param1.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { 1614 JSVM_Value thisVar = nullptr; 1615 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr); 1616 1617 return thisVar; 1618 }; 1619 OH_JSVM_DefineClass(env, "TestClass", JSVM_AUTO_LENGTH, ¶m1, 0, nullptr, &testClass); 1620 1621 JSVM_Value instanceValue = nullptr; 1622 OH_JSVM_NewInstance(env, testClass, 0, nullptr, &instanceValue); 1623 1624 const char *testStr = "test"; 1625 OH_JSVM_Wrap( 1626 env, instanceValue, (void *)testStr, [](JSVM_Env env, void *data, void *hint) {}, nullptr, nullptr); 1627 const char *tmpTestStr = nullptr; 1628 OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr); 1629 const char *tmpTestStr1 = nullptr; 1630 OH_JSVM_RemoveWrap(env, instanceValue, (void **)&tmpTestStr1); 1631 OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr1); 1632 OH_JSVM_CloseHandleScope(env, handlescope); 1633 OH_JSVM_CloseEnvScope(env, envScope); 1634 OH_JSVM_DestroyEnv(env); 1635 OH_JSVM_CloseVMScope(vm, vm_scope); 1636 OH_JSVM_DestroyVM(vm); 1637 OH_LOG_ERROR(LOG_APP, "testWrap pass"); 1638 return nullptr; 1639} 1640``` 1641 1642 1643Wrap a native object and register a listener for property access operations. 1644 1645```c++ 1646static int aa = 0; 1647static JSVM_Value hello(JSVM_Env env, JSVM_CallbackInfo info) { 1648 JSVM_Value output; 1649 void *data = nullptr; 1650 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data); 1651 OH_JSVM_CreateStringUtf8(env, (char *)data, strlen((char *)data), &output); 1652 return output; 1653} 1654 1655static JSVM_CallbackStruct hello_cb = {hello, (void *)"Hello"}; 1656static intptr_t externals[] = { 1657 (intptr_t)&hello_cb, 1658 0, 1659}; 1660 1661static void test1() { OH_LOG_INFO(LOG_APP, "test1 called"); } 1662 1663struct Test { 1664 void *ptr1; 1665 void *ptr2; 1666}; 1667 1668static JSVM_Value assertEqual(JSVM_Env env, JSVM_CallbackInfo info) { 1669 size_t argc = 2; 1670 JSVM_Value args[2]; 1671 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL)); 1672 1673 bool isStrictEquals = false; 1674 OH_JSVM_StrictEquals(env, args[0], args[1], &isStrictEquals); 1675 return nullptr; 1676} 1677 1678static JSVM_Value GetPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value thisArg, JSVM_Value data) { 1679 // This callback is triggered by the getter of the object. 1680 char strValue[100]; 1681 size_t size; 1682 OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size); 1683 JSVM_Value newResult = nullptr; 1684 char newStr[] = "new return value hahaha from name listening"; 1685 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1686 int signBit = 0; 1687 size_t wordCount = 2; 1688 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1689 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1690 if (status == JSVM_OK) { 1691 OH_LOG_INFO(LOG_APP, "GetPropertyCbInfo wordCount is %{public}zu", wordCount); 1692 auto test = reinterpret_cast<Test *>(wordsOut); 1693 typedef void (*callTest1)(); 1694 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1695 callTe(); 1696 } 1697 return nullptr; 1698} 1699 1700static JSVM_Value SetPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value property, JSVM_Value thisArg, JSVM_Value data) { 1701 // This callback is triggered by the setter of the object. 1702 char strValue[100]; 1703 size_t size; 1704 OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size); 1705 JSVM_Value newResult = nullptr; 1706 char newStr[] = "new return value hahaha from name listening"; 1707 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1708 int signBit = 0; 1709 size_t wordCount = 2; 1710 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1711 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1712 if (status == JSVM_OK) { 1713 OH_LOG_INFO(LOG_APP, "SetPropertyCbInfo wordCount is %{public}zu", wordCount); 1714 auto test = reinterpret_cast<Test *>(wordsOut); 1715 typedef void (*callTest1)(); 1716 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1717 callTe(); 1718 } 1719 return nullptr; 1720} 1721 1722static JSVM_Value DeleterPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value thisArg, JSVM_Value data) { 1723 // This callback is triggered by the deleter of the object. 1724 char strValue[100]; 1725 size_t size; 1726 OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size); 1727 JSVM_Value newResult = nullptr; 1728 bool returnValue = false; 1729 OH_JSVM_GetBoolean(env, returnValue, &newResult); 1730 int signBit = 0; 1731 size_t wordCount = 2; 1732 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1733 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1734 if (status == JSVM_OK) { 1735 OH_LOG_INFO(LOG_APP, "DeleterPropertyCbInfo wordCount is %{public}zu", wordCount); 1736 auto test = reinterpret_cast<Test *>(wordsOut); 1737 typedef void (*callTest1)(); 1738 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1739 callTe(); 1740 } 1741 return nullptr; 1742} 1743 1744static JSVM_Value EnumeratorPropertyCbInfo(JSVM_Env env, JSVM_Value thisArg, JSVM_Value data) { 1745 // This callback is triggered by the enumerator of an object. 1746 JSVM_Value testArray = nullptr; 1747 OH_JSVM_CreateArrayWithLength(env, 2, &testArray); 1748 JSVM_Value name1 = nullptr; 1749 char newStr1[] = "hahaha"; 1750 OH_JSVM_CreateStringUtf8(env, newStr1, strlen(newStr1), &name1); 1751 JSVM_Value name2 = nullptr; 1752 char newStr2[] = "heheheh"; 1753 OH_JSVM_CreateStringUtf8(env, newStr2, strlen(newStr2), &name2); 1754 1755 OH_JSVM_SetElement(env, testArray, 0, name1); 1756 OH_JSVM_SetElement(env, testArray, 1, name2); 1757 int signBit = 0; 1758 size_t wordCount = 2; 1759 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1760 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1761 if (status == JSVM_OK) { 1762 OH_LOG_INFO(LOG_APP, "EnumeratorPropertyCbInfo wordCount is %{public}zu", wordCount); 1763 auto test = reinterpret_cast<Test *>(wordsOut); 1764 typedef void (*callTest1)(); 1765 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1766 callTe(); 1767 } 1768 return nullptr; 1769} 1770 1771static JSVM_Value IndexedPropertyGet(JSVM_Env env, JSVM_Value index, JSVM_Value thisArg, JSVM_Value data) { 1772 // This callback is triggered by the indexed getter. 1773 uint32_t value; 1774 OH_JSVM_GetValueUint32(env, index, &value); 1775 1776 JSVM_Value newResult = nullptr; 1777 char newStr[] = "new return value hahaha from index listening"; 1778 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1779 int signBit = 0; 1780 size_t wordCount = 2; 1781 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1782 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1783 if (status == JSVM_OK) { 1784 OH_LOG_INFO(LOG_APP, "IndexedPropertyGet wordCount is %{public}zu", wordCount); 1785 auto test = reinterpret_cast<Test *>(wordsOut); 1786 typedef void (*callTest1)(); 1787 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1788 callTe(); 1789 } 1790 return nullptr; 1791} 1792 1793static JSVM_Value IndexedPropertySet(JSVM_Env env, JSVM_Value index, JSVM_Value property, JSVM_Value thisArg, JSVM_Value data) { 1794 // This callback is triggered by the indexed setter. 1795 uint32_t value; 1796 OH_JSVM_GetValueUint32(env, index, &value); 1797 char str[100]; 1798 size_t size; 1799 OH_JSVM_GetValueStringUtf8(env, property, str, 100, &size); 1800 JSVM_Value newResult = nullptr; 1801 char newStr[] = "new return value hahaha from name listening"; 1802 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1803 int signBit = 0; 1804 size_t wordCount = 2; 1805 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1806 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1807 if (status == JSVM_OK) { 1808 OH_LOG_INFO(LOG_APP, "IndexedPropertySet wordCount is %{public}zu", wordCount); 1809 auto test = reinterpret_cast<Test *>(wordsOut); 1810 typedef void (*callTest1)(); 1811 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1812 callTe(); 1813 } 1814 return nullptr; 1815} 1816 1817static JSVM_Value IndexedPropertyDeleter(JSVM_Env env, JSVM_Value index, JSVM_Value thisArg, JSVM_Value data) { 1818 // This callback is triggered by the indexed deleter. 1819 uint32_t value; 1820 OH_JSVM_GetValueUint32(env, index, &value); 1821 JSVM_Value newResult = nullptr; 1822 bool returnValue = false; 1823 OH_JSVM_GetBoolean(env, returnValue, &newResult); 1824 int signBit = 0; 1825 size_t wordCount = 2; 1826 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1827 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1828 if (status == JSVM_OK) { 1829 OH_LOG_INFO(LOG_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount); 1830 auto test = reinterpret_cast<Test *>(wordsOut); 1831 typedef void (*callTest1)(); 1832 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1833 callTe(); 1834 } 1835 return nullptr; 1836} 1837 1838static JSVM_Value IndexedPropertyEnumerator(JSVM_Env env, JSVM_Value thisArg, JSVM_Value data) { 1839 // This callback is triggered by the indexed enumerator. 1840 JSVM_Value testArray = nullptr; 1841 OH_JSVM_CreateArrayWithLength(env, 2, &testArray); 1842 JSVM_Value index1 = nullptr; 1843 OH_JSVM_CreateUint32(env, 1, &index1); 1844 JSVM_Value index2 = nullptr; 1845 OH_JSVM_CreateUint32(env, 2, &index2); 1846 OH_JSVM_SetElement(env, testArray, 0, index1); 1847 OH_JSVM_SetElement(env, testArray, 1, index2); 1848 int signBit = 0; 1849 size_t wordCount = 2; 1850 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1851 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1852 if (status == JSVM_OK) { 1853 OH_LOG_INFO(LOG_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount); 1854 auto test = reinterpret_cast<Test *>(wordsOut); 1855 typedef void (*callTest1)(); 1856 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1857 callTe(); 1858 } 1859 return nullptr; 1860} 1861 1862static napi_value TestDefineClassWithProperty(napi_env env1, napi_callback_info info) { 1863 OH_LOG_ERROR(LOG_APP, "TestDefineClassWithProperty start"); 1864 JSVM_InitOptions init_options; 1865 memset(&init_options, 0, sizeof(init_options)); 1866 init_options.externalReferences = externals; 1867 if (aa == 0) { 1868 OH_JSVM_Init(&init_options); 1869 aa++; 1870 } 1871 JSVM_VM vm; 1872 JSVM_CreateVMOptions options; 1873 memset(&options, 0, sizeof(options)); 1874 OH_JSVM_CreateVM(&options, &vm); 1875 JSVM_VMScope vm_scope; 1876 OH_JSVM_OpenVMScope(vm, &vm_scope); 1877 JSVM_Env env; 1878 JSVM_CallbackStruct param[1]; 1879 param[0].data = nullptr; 1880 param[0].callback = assertEqual; 1881 JSVM_PropertyDescriptor descriptor[] = { 1882 {"assertEqual", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 1883 }; 1884 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 1885 JSVM_EnvScope envScope; 1886 OH_JSVM_OpenEnvScope(env, &envScope); 1887 JSVM_HandleScope handlescope; 1888 OH_JSVM_OpenHandleScope(env, &handlescope); 1889 1890 1891 JSVM_CallbackStruct param1; 1892 param1.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { 1893 JSVM_Value thisVar = nullptr; 1894 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr); 1895 return thisVar; 1896 }; 1897 param1.data = nullptr; 1898 1899 JSVM_Value res = nullptr; 1900 Test *test = new Test(); 1901 test->ptr1 = (void *)test1; 1902 test->ptr2 = (void *)test1; 1903 OH_LOG_INFO(LOG_APP, "OH_JSVM_CreateBigintWords 111 word count %{public}d", 1904 sizeof(*test) / sizeof(uint64_t)); 1905 JSVM_Status status = OH_JSVM_CreateBigintWords(env, 1, 2, reinterpret_cast<const uint64_t *>(test), &res); 1906 1907 // Initialize propertyCfg. 1908 JSVM_PropertyHandlerConfigurationStruct propertyCfg; 1909 propertyCfg.genericNamedPropertyGetterCallback = GetPropertyCbInfo; 1910 propertyCfg.genericNamedPropertySetterCallback = SetPropertyCbInfo; 1911 propertyCfg.genericNamedPropertyDeleterCallback = DeleterPropertyCbInfo; 1912 propertyCfg.genericNamedPropertyEnumeratorCallback = EnumeratorPropertyCbInfo; 1913 propertyCfg.genericIndexedPropertyGetterCallback = IndexedPropertyGet; 1914 propertyCfg.genericIndexedPropertySetterCallback = IndexedPropertySet; 1915 propertyCfg.genericIndexedPropertyDeleterCallback = IndexedPropertyDeleter; 1916 propertyCfg.genericIndexedPropertyEnumeratorCallback = IndexedPropertyEnumerator; 1917 propertyCfg.namedPropertyData = res; 1918 propertyCfg.indexedPropertyData = res; 1919 1920 JSVM_CallbackStruct callbackStruct; 1921 callbackStruct.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { 1922 OH_LOG_INFO(LOG_APP, "call as a function called"); 1923 JSVM_Value thisVar = nullptr; 1924 void *innerData; 1925 size_t argc = 1; 1926 JSVM_Value args[1]; 1927 OH_JSVM_GetCbInfo(env, info, &argc, args, &thisVar, &innerData); 1928 OH_LOG_INFO(LOG_APP, "function call as function result is %{public}s", reinterpret_cast<char *>(innerData)); 1929 uint32_t ret = 0; 1930 OH_JSVM_GetValueUint32(env, args[0], &ret); 1931 const char testStr[] = "hello world 111111"; 1932 JSVM_Value setvalueName = nullptr; 1933 JSVM_CALL(env, OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName)); 1934 return setvalueName; 1935 }; 1936 char data[100] = "1111 hello world"; 1937 callbackStruct.data = data; 1938 JSVM_Value testWrapClass = nullptr; 1939 1940 // Register a property access listener in propertyCfg. 1941 OH_JSVM_DefineClassWithPropertyHandler(env, "TestWrapClass", NAPI_AUTO_LENGTH, ¶m1, 0, nullptr, &propertyCfg, 1942 &callbackStruct, &testWrapClass); 1943 JSVM_Value instanceValue = nullptr; 1944 OH_JSVM_NewInstance(env, testWrapClass, 0, nullptr, &instanceValue); 1945 const char testStr[] = "hello world"; 1946 JSVM_Value setvalueName = nullptr; 1947 OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName); 1948 1949 // 1. Callbacks for properties. 1950 // Set properties. 1951 OH_JSVM_SetNamedProperty(env, instanceValue, "str11", setvalueName); 1952 OH_JSVM_SetNamedProperty(env, instanceValue, "str123", setvalueName); 1953 1954 // Obtain a property. 1955 JSVM_Value valueName = nullptr; 1956 OH_JSVM_GetNamedProperty(env, instanceValue, "str11", &valueName); 1957 char str[100]; 1958 size_t size; 1959 OH_JSVM_GetValueStringUtf8(env, valueName, str, 100, &size); 1960 1961 // Obtain all property names. 1962 JSVM_Value allPropertyNames = nullptr; 1963 OH_JSVM_GetAllPropertyNames(env, instanceValue, JSVM_KEY_OWN_ONLY, 1964 static_cast<JSVM_KeyFilter>(JSVM_KEY_ENUMERABLE | JSVM_KEY_SKIP_SYMBOLS), 1965 JSVM_KEY_NUMBERS_TO_STRINGS, &allPropertyNames); 1966 uint32_t nameSize = 0; 1967 OH_JSVM_GetArrayLength(env, allPropertyNames, &nameSize); 1968 JSVM_Value propertyName = nullptr; 1969 for (uint32_t i = 0; i < nameSize; ++i) { 1970 OH_JSVM_GetElement(env, allPropertyNames, i, &propertyName); 1971 char str[100]; 1972 size_t size; 1973 OH_JSVM_GetValueStringUtf8(env, propertyName, str, 100, &size); 1974 } 1975 1976 // Delete a property. 1977 bool result = false; 1978 propertyName = nullptr; 1979 char propertyChar[] = "str11"; 1980 OH_JSVM_CreateStringUtf8(env, propertyChar, strlen(propertyChar), &propertyName); 1981 OH_JSVM_DeleteProperty(env, instanceValue, propertyName, &result); 1982 1983 // 2. Callbacks for index properties. 1984 // Set properties. 1985 JSVM_Value jsIndex = nullptr; 1986 uint32_t index = 0; 1987 OH_JSVM_CreateUint32(env, index, &jsIndex); 1988 OH_JSVM_SetProperty(env, instanceValue, jsIndex, setvalueName); 1989 JSVM_Value jsIndex1 = nullptr; 1990 index = 1; 1991 OH_JSVM_CreateUint32(env, index, &jsIndex1); 1992 OH_JSVM_SetProperty(env, instanceValue, jsIndex1, setvalueName); 1993 1994 // Obtain a property. 1995 JSVM_Value valueName1 = nullptr; 1996 OH_JSVM_GetProperty(env, instanceValue, jsIndex, &valueName1); 1997 char str1[100]; 1998 size_t size1; 1999 OH_JSVM_GetValueStringUtf8(env, valueName1, str1, 100, &size1); 2000 2001 // Obtain all property names. 2002 JSVM_Value allPropertyNames1 = nullptr; 2003 OH_JSVM_GetAllPropertyNames(env, instanceValue, JSVM_KEY_OWN_ONLY, 2004 static_cast<JSVM_KeyFilter>(JSVM_KEY_ENUMERABLE | JSVM_KEY_SKIP_SYMBOLS), 2005 JSVM_KEY_NUMBERS_TO_STRINGS, &allPropertyNames1); 2006 uint32_t nameSize1 = 0; 2007 OH_JSVM_GetArrayLength(env, allPropertyNames1, &nameSize); 2008 JSVM_Value propertyName1 = nullptr; 2009 for (uint32_t i = 0; i < nameSize1; ++i) { 2010 OH_JSVM_GetElement(env, allPropertyNames1, i, &propertyName1); 2011 char str[100]; 2012 size_t size; 2013 OH_JSVM_GetValueStringUtf8(env, propertyName1, str, 100, &size); 2014 } 2015 2016 // Delete a property. 2017 bool result1 = false; 2018 OH_JSVM_DeleteProperty(env, instanceValue, jsIndex, &result1); 2019 2020 // 3. Callback of a function. 2021 JSVM_Value gloablObj = nullptr; 2022 OH_JSVM_GetGlobal(env, &gloablObj); 2023 OH_JSVM_SetNamedProperty(env, gloablObj, "myTestInstance", instanceValue); 2024 OH_LOG_INFO(LOG_APP, "set property on global object"); 2025 std::string innerSourcecodestr = R"( 2026 { 2027 let res = myTestInstance(12); 2028 })"; 2029 JSVM_Value innerSourcecodevalue; 2030 OH_JSVM_CreateStringUtf8(env, innerSourcecodestr.c_str(), innerSourcecodestr.size(), &innerSourcecodevalue); 2031 JSVM_Script innerscript; 2032 OH_JSVM_CompileScript(env, innerSourcecodevalue, nullptr, 0, true, nullptr, &innerscript); 2033 JSVM_Value innerResult; 2034 OH_JSVM_RunScript(env, innerscript, &innerResult); 2035 2036 OH_JSVM_CloseHandleScope(env, handlescope); 2037 OH_JSVM_CloseEnvScope(env, envScope); 2038 OH_JSVM_DestroyEnv(env); 2039 OH_JSVM_CloseVMScope(vm, vm_scope); 2040 OH_JSVM_DestroyVM(vm); 2041 OH_LOG_ERROR(LOG_APP, "TestDefineClassWithProperty pass"); 2042 return nullptr; 2043} 2044``` 2045Set a parent class and register a listener for property access operations. 2046 2047See [Working with Classes Using JSVM-API](use-jsvm-about-class.md). 2048 2049### Version Management 2050 2051#### When to Use 2052 2053Obtain version information. 2054 2055#### Available APIs 2056| API| Description| 2057| -------- | -------- | 2058|OH_JSVM_GetVersion| Obtains the latest JSVM API version supported by the JSVM runtime.| 2059|OH_JSVM_GetVMInfo| Obtains the VM information.| 2060 2061#### Example 2062 2063Obtain version information. 2064 2065```c++ 2066JSVM_VMInfo result; 2067OH_JSVM_GetVMInfo(&result); 2068uint32_t versionId = 0; 2069OH_JSVM_GetVersion(env, &versionId); 2070``` 2071 2072### Memory Management 2073 2074#### When to Use 2075 2076Perform memory management. 2077 2078#### Available APIs 2079| API | Description | 2080| ------------------------------------------- | ------------------------------------------------------------------------------------------------------ | 2081| OH_JSVM_AdjustExternalMemory | Adjusts the amount of registered external memory used to give the JSVM an indication of the amount of externally allocated memory that is kept alive by JS objects. The JSVM then determines whether to perform global GC. Increasing the externally allocated memory will increase the probability of triggering global.| 2082| OH_JSVM_MemoryPressureNotification | Notifies the VM of the memory pressure level and selectively triggers GC. | 2083| OH_JSVM_AllocateArrayBufferBackingStoreData | Allocates memory for a backing store.| 2084| OH_JSVM_FreeArrayBufferBackingStoreData | Releases the backing store memory.| 2085| OH_JSVM_CreateArrayBufferFromBackingStoreData | Creates an array buffer based on the backing store memory allocated.| 2086 2087> Using a backing store is a critical operation. You must ensure correct use of memory and exercise caution when using it. For details, see the following example. 2088 2089#### Example 2090 2091Perform memory management. 2092 2093```c++ 2094// Before and after calling OH_JSVM_AdjustExternalMemory, check the memory allocated externally from the perspective of the underlying VM. 2095int64_t result; 2096OH_JSVM_AdjustExternalMemory(env, 0, &result); // The externally allocated memory remains unchanged. 2097OH_LOG_INFO(LOG_APP, "Before AdjustExternalMemory: %{public}lld\n", result); // Obtain the memory value before the adjustment. 2098// Increase the memory usage and notify the VM of the change. 2099int64_t memoryIncrease = 1024 * 1024; // Increase the memory by 1 MB. 2100OH_JSVM_AdjustExternalMemory(env, memoryIncrease, &result); 2101OH_LOG_INFO(LOG_APP, "After AdjustExternalMemory: %{public}lld\n", result); // Obtain the memory value after the adjustment. 2102``` 2103```c++ 2104// Open a handle scope and apply for a large amount of memory within the scope to test the function. 2105// Check the memory status after the memory is allocated, after the scope is closed, and after OH_JSVM_MemoryPressureNotification is called. 2106JSVM_HandleScope tmpscope; 2107OH_JSVM_OpenHandleScope(env, &tmpscope); 2108for (int i = 0; i < 1000000; ++i) { 2109 JSVM_Value obj; 2110 OH_JSVM_CreateObject(env, &obj); 2111} 2112JSVM_HeapStatistics mem; 2113OH_JSVM_GetHeapStatistics(vm, &mem); // Obtain the heap statistics of the VM. 2114OH_LOG_INFO(LOG_APP, " %{public}zu\n", mem.usedHeapSize); // After the requested memory is allocated, the memory is of the maximum size. 2115OH_JSVM_CloseHandleScope (env, tmpscope); // Close the handle scope. 2116 2117OH_JSVM_GetHeapStatistics(vm, &mem); 2118OH_LOG_INFO(LOG_APP, " %{public}zu\n", mem.usedHeapSize); // After the scope is closed, GC is not performed immediately. 2119 2120// Notify the VM of the memory pressure level and selectively trigger GC. 2121OH_JSVM_MemoryPressureNotification(env, JSVM_MEMORY_PRESSURE_LEVEL_CRITICAL); // The memory pressure is in the critical state. 2122 2123OH_JSVM_GetHeapStatistics(vm, &mem); 2124OH_LOG_INFO(LOG_APP, " %{public}zu\n", mem.usedHeapSize); // After GC is triggered. 2125``` 2126 2127Example 2128``` c++ 2129void *backingStore; 2130JSVM_Value arrayBuffer; 2131 2132// Allocate memory of 100 bytes for a backing store. 2133OH_JSVM_AllocateArrayBufferBackingStoreData(100, JSVM_ZERO_INITIALIZED, &backingStore); 2134 2135// In the allocated memory, create an ArrayBuffer of 20 bytes at 30 bytes away from the start address of the backing store. 2136OH_JSVM_CreateArrayBufferFromBackingStoreData(env, backingStore, 100, 30, 20, &arrayBuffer); 2137 2138// Use the created ArrayBuffer in JS. 2139JSVM_Value js_global; 2140JSVM_Value name; 2141OH_JSVM_GetGlobal(jsvm_env, &js_global); 2142OH_JSVM_CreateStringUtf8(jsvm_env, "buffer", JSVM_AUTO_LENGTH, &name); 2143OH_JSVM_SetProperty(env, js_global, name, arrayBuffer); 2144 2145JSVM_Script script; 2146JSVM_Value scriptString; 2147JSVM_Value result; 2148const char *src = R"JS( 2149function writeBuffer(data) { 2150 let view = new Uint8Array(data); 2151 // Write some values to the ArrayBuffer 2152 for (let i = 0; i < view.length; i++) { 2153 view[i] = i % 256; 2154 } 2155} 2156writeBuffer(buffer) 2157)JS"; 2158OH_JSVM_CreateStringUtf8(env, src, JSVM_AUTO_LENGTH, &scriptString); 2159OH_JSVM_CompileScriptWithOptions(env, scriptString, 0, nullptr, &script); 2160OH_JSVM_RunScript(env, script, &result); 2161 2162// Check the ArrayBuffer content. 2163uint8_t *array = static_cast<uint8_t*>(backingStore); 2164for (auto i = 0; i < 100; ++i) { 2165 if (array[i] != i % 25 % 256) { 2166 return false; 2167 } 2168} 2169 2170// Release the ArrayBuffer. Before releasing the backing store, you must 2171// call OH_JSVM_DetachArraybuffer to release all ArrayBuffers created in the backing store. 2172// Otherwise, unpredictable memory problems may occur. 2173OH_JSVM_DetachArraybuffer(env, arrayBuffer); 2174 2175// Release the memory allocated for the backing store. 2176OH_JSVM_FreeArrayBufferBackingStoreData(backingStore); 2177``` 2178### Promises 2179 2180#### When to Use 2181 2182Perform operations related to promises. 2183 2184#### Available APIs 2185| API| Description| 2186| -------- | -------- | 2187|OH_JSVM_CreatePromise| Creates a **deferred** object and a JS promise.| 2188|OH_JSVM_ResolveDeferred| Resolves a JS promise by using the **deferred** object associated with it.| 2189|OH_JSVM_RejectDeferred| Rejects a JS promise by using the **deferred** object associated with it.| 2190|OH_JSVM_IsPromise| Checks whether a promise object is a native promise object.| 2191 2192#### Example 2193 2194Perform operations related to promises. 2195 2196```c++ 2197JSVM_Deferred deferred; 2198JSVM_Value promise; 2199OH_JSVM_CreatePromise(env, &deferred, &promise); 2200 2201// Perform an asynchronous operation. 2202int result = 42; 2203bool success = true; 2204if (success) 2205{ 2206 // Resolve the promise and pass the result. 2207 JSVM_Value value; 2208 OH_JSVM_CreateInt32(env, result, &value); 2209 OH_JSVM_ResolveDeferred(env, deferred, value); 2210} else { 2211 // Reject the promise and pass the error information. 2212 JSVM_Value code = nullptr; 2213 JSVM_Value message = nullptr; 2214 OH_JSVM_CreateStringUtf8(env, "600", JSVM_AUTO_LENGTH, &code); 2215 OH_JSVM_CreateStringUtf8(env, "Async operation failed", JSVM_AUTO_LENGTH, &message); 2216 JSVM_Value error = nullptr; 2217 OH_JSVM_CreateError(env, code, message, &error); 2218 OH_JSVM_RejectDeferred(env, deferred, error); 2219} 2220``` 2221 2222### JSON Operations 2223 2224#### When to Use 2225 2226Perform JSON operations. 2227 2228#### Available APIs 2229 2230| API| Description| 2231| -------- | -------- | 2232|OH_JSVM_JsonParse| Parses a JSON string and returns the parsed value.| 2233|OH_JSVM_JsonStringify| Converts a JS object into a JSON string and returns the converted string.| 2234 2235#### Example 2236 2237Parse JSON strings. 2238 2239```c++ 2240std::string sourcecodestr = "{\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}" ; 2241JSVM_Value jsonString; 2242OH_JSVM_CreateStringUtf8(env, sourcecodestr.c_str(), sourcecodestr.size(), &jsonString) 2243JSVM_Value result; 2244OH_JSVM_JsonParse(env, jsonString, &result); 2245``` 2246 2247### Creating and Using a VM Startup Snapshot 2248 2249#### When to Use 2250 2251Create and use a VM startup snapshot. 2252 2253#### Available APIs 2254| API| Description| 2255| -------- | -------- | 2256|OH_JSVM_CreateSnapshot| Creates a VM startup snapshot.| 2257|OH_JSVM_CreateEnvFromSnapshot| Creates a JSVM environment from a startup snapshot.| 2258 2259#### Example 2260 2261See [Working with VM Snapshots Using JSVM-API](use-jsvm-create-snapshot.md). 2262 2263### Checking Input Parameters 2264 2265#### When to Use 2266 2267Check whether the input parameters are callable. 2268 2269#### Available APIs 2270| API| Description| 2271| -------- | -------- | 2272|OH_JSVM_IsCallable| Checks whether the input parameters are callable. | 2273 2274#### Example 2275 2276Check whether input parameters are callable. 2277 2278```c++ 2279static JSVM_Value NapiIsCallable(JSVM_Env env, JSVM_CallbackInfo info) { 2280 JSVM_Value value, rst; 2281 size_t argc = 1; 2282 bool isCallable = false; 2283 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, &value, NULL, NULL)); 2284 JSVM_CALL(env, OH_JSVM_IsCallable(env, value, &isCallable)); 2285 OH_JSVM_GetBoolean(env, isCallable, &rst); 2286 return rst; 2287} 2288 2289static napi_value MyJSVMDemo([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) { 2290 std::thread t([]() { 2291 // Create a VM instance and open the VM scope. 2292 JSVM_VM vm; 2293 JSVM_CreateVMOptions options; 2294 memset(&options, 0, sizeof(options)); 2295 OH_JSVM_CreateVM(&options, &vm); 2296 JSVM_VMScope vmScope; 2297 OH_JSVM_OpenVMScope(vm, &vmScope); 2298 JSVM_CallbackStruct param[] = { 2299 {.data = nullptr, .callback = NapiIsCallable}, 2300 }; 2301 JSVM_PropertyDescriptor descriptor[] = { 2302 {"napiIsCallable", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 2303 }; 2304 // Create env, register a native method, and open an env scope. 2305 JSVM_Env env; 2306 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 2307 JSVM_EnvScope envScope; 2308 OH_JSVM_OpenEnvScope(env, &envScope); 2309 // Open a handle scope. 2310 JSVM_HandleScope handleScope; 2311 OH_JSVM_OpenHandleScope(env, &handleScope); 2312 std::string sourceCodeStr = R"JS( 2313 function addNumbers(num1, num2) 2314 { 2315 var rst= num1 + num2; 2316 return rst; 2317 } 2318 let rst = napiIsCallable(addNumbers); 2319 )JS"; 2320 // Compile the JS script. 2321 JSVM_Value sourceCodeValue; 2322 OH_JSVM_CreateStringUtf8(env, sourceCodeStr.c_str(), sourceCodeStr.size(), &sourceCodeValue); 2323 JSVM_Script script; 2324 OH_JSVM_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script); 2325 JSVM_Value result; 2326 // Run the JS script. 2327 OH_JSVM_RunScript(env, script, &result); 2328 JSVM_ValueType type; 2329 OH_JSVM_Typeof(env, result, &type); 2330 OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type); 2331 // Exit the VM and release the memory. 2332 OH_JSVM_CloseHandleScope(env, handleScope); 2333 OH_JSVM_CloseEnvScope(env, envScope); 2334 OH_JSVM_DestroyEnv(env); 2335 OH_JSVM_CloseVMScope(vm, vmScope); 2336 OH_JSVM_DestroyVM(vm); 2337 }); 2338 t.detach(); 2339 return nullptr; 2340} 2341``` 2342 2343### Lock Operations 2344 2345#### When to Use 2346 2347Perform lock operations. 2348 2349#### Available APIs 2350| API| Description| 2351| -------- | -------- | 2352|OH_JSVM_IsLocked| Checks whether the current thread holds a lock of the specified environment.| 2353|OH_JSVM_AcquireLock| Obtains a lock.| 2354|OH_JSVM_ReleaseLock| Releases a lock.| 2355 2356#### Example 2357 2358Obtain and release a lock. 2359 2360```c++ 2361class LockWrapper { 2362 public: 2363 LockWrapper(JSVM_Env env) : env(env) { 2364 OH_JSVM_IsLocked(env, &isLocked); 2365 if (!isLocked) { 2366 OH_JSVM_AcquireLock(env); 2367 OH_JSVM_GetVM(env, &vm); 2368 OH_JSVM_OpenVMScope(vm, &vmScope); 2369 OH_JSVM_OpenEnvScope(env, &envScope); 2370 } 2371 } 2372 2373 ~LockWrapper() { 2374 if (!isLocked) { 2375 OH_JSVM_CloseEnvScope(env, envScope); 2376 OH_JSVM_CloseVMScope(vm, vmScope); 2377 OH_JSVM_ReleaseLock(env); 2378 } 2379 } 2380 2381 LockWrapper(const LockWrapper&) = delete; 2382 LockWrapper& operator=(const LockWrapper&) = delete; 2383 LockWrapper(LockWrapper&&) = delete; 2384 void* operator new(size_t) = delete; 2385 void* operator new[](size_t) = delete; 2386 2387 private: 2388 JSVM_Env env; 2389 JSVM_EnvScope envScope; 2390 JSVM_VMScope vmScope; 2391 JSVM_VM vm; 2392 bool isLocked; 2393}; 2394 2395static napi_value Add([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) { 2396 static JSVM_VM vm; 2397 static JSVM_Env env; 2398 if (aa == 0) { 2399 OH_JSVM_Init(nullptr); 2400 aa++; 2401 // create vm 2402 JSVM_CreateVMOptions options; 2403 memset(&options, 0, sizeof(options)); 2404 OH_JSVM_CreateVM(&options, &vm); 2405 // create env 2406 OH_JSVM_CreateEnv(vm, 0, nullptr, &env); 2407 } 2408 2409 std::thread t1([]() { 2410 LockWrapper lock(env); 2411 JSVM_HandleScope handleScope; 2412 OH_JSVM_OpenHandleScope(env, &handleScope); 2413 JSVM_Value value; 2414 JSVM_Status rst = OH_JSVM_CreateInt32(env, 32, &value); // 32: numerical value 2415 if (rst == JSVM_OK) { 2416 OH_LOG_INFO(LOG_APP, "JSVM:t1 OH_JSVM_CreateInt32 suc"); 2417 } else { 2418 OH_LOG_ERROR(LOG_APP, "JSVM:t1 OH_JSVM_CreateInt32 fail"); 2419 } 2420 int32_t num1; 2421 OH_JSVM_GetValueInt32(env, value, &num1); 2422 OH_LOG_INFO(LOG_APP, "JSVM:t1 num1 = %{public}d", num1); 2423 OH_JSVM_CloseHandleScope(env, handleScope); 2424 }); 2425 std::thread t2([]() { 2426 LockWrapper lock(env); 2427 JSVM_HandleScope handleScope; 2428 OH_JSVM_OpenHandleScope(env, &handleScope); 2429 JSVM_Value value; 2430 JSVM_Status rst = OH_JSVM_CreateInt32(env, 32, &value); // 32: numerical value 2431 if (rst == JSVM_OK) { 2432 OH_LOG_INFO(LOG_APP, "JSVM:t2 OH_JSVM_CreateInt32 suc"); 2433 } else { 2434 OH_LOG_ERROR(LOG_APP, "JSVM:t2 OH_JSVM_CreateInt32 fail"); 2435 } 2436 int32_t num1; 2437 OH_JSVM_GetValueInt32(env, value, &num1); 2438 OH_LOG_INFO(LOG_APP, "JSVM:t2 num1 = %{public}d", num1); 2439 OH_JSVM_CloseHandleScope(env, handleScope); 2440 }); 2441 t1.detach(); 2442 t2.detach(); 2443 return nullptr; 2444} 2445``` 2446 2447### Setting and Obtaining Data Associated with a JSVM Instance 2448 2449#### When to Use 2450 2451Set and obtain the data associated with a JSVM instance. 2452 2453#### Available APIs 2454| API| Description| 2455| -------- | -------- | 2456|OH_JSVM_SetInstanceData| Sets data to be associated with a JSVM instance.| 2457|OH_JSVM_GetInstanceData| Obtains the data associated with a JSVM instance.| 2458 2459#### Example 2460 2461Set and obtain the data associated with a JSVM instance. 2462 2463```c++ 2464JSVM_VM vm; 2465JSVM_CreateVMOptions options; 2466JSVM_VMScope vm_scope; 2467JSVM_Env env; 2468JSVM_EnvScope envScope; 2469JSVM_HandleScope handlescope; 2470 2471static int aa = 0; 2472struct InstanceData { 2473 int32_t value; 2474}; 2475 2476// Initialize the VM and create a JSVM instance. 2477void init_JSVM_environment(){ 2478 JSVM_InitOptions init_options; 2479 memset(&init_options, 0, sizeof(init_options)); 2480 if (aa == 0) { 2481 OH_JSVM_Init(&init_options); 2482 aa++; 2483 } 2484 memset(&options, 0, sizeof(options)); 2485 OH_JSVM_CreateVM(&options, &vm); 2486 OH_JSVM_OpenVMScope(vm, &vm_scope); 2487 OH_JSVM_CreateEnv(vm, 0, nullptr, &env); 2488 OH_JSVM_OpenEnvScope(env, &envScope); 2489 OH_JSVM_OpenHandleScope(env, &handlescope); 2490} 2491 2492// Exit the VM and release the running environment. 2493napi_value close_JSVM_environment(napi_env env1, napi_callback_info info) 2494{ 2495 OH_JSVM_CloseHandleScope(env, handlescope); 2496 OH_JSVM_CloseEnvScope(env, envScope); 2497 OH_JSVM_DestroyEnv(env); 2498 OH_JSVM_CloseVMScope(vm, vm_scope); 2499 OH_JSVM_DestroyVM(vm); 2500 napi_value result; 2501 char* s = "ok"; 2502 napi_create_string_latin1(env1, s, strlen(s), &result); 2503 return result; 2504} 2505 2506// Clear and release the memory used by the instance. 2507void InstanceFinalizeCallback(JSVM_Env env, void *finalizeData, void *finalizeHint) 2508{ 2509 if (finalizeData) { 2510 InstanceData *data = reinterpret_cast<InstanceData *>(finalizeData); 2511 free(data); 2512 *(InstanceData **)finalizeData = nullptr; 2513 } 2514} 2515 2516static napi_value GetInstanceData(napi_env env1, napi_callback_info info) 2517{ 2518 InstanceData *instanceData = reinterpret_cast<InstanceData *>(malloc(sizeof(InstanceData))); 2519 if (instanceData == nullptr) { 2520 printf("Memory allocation failed!\n"); 2521 return nullptr; 2522 } 2523 size_t argc = 1; 2524 napi_value args[1] = {nullptr}; 2525 // Obtain the callback function parameters. 2526 napi_get_cb_info(env1, info, &argc, args , nullptr, nullptr); 2527 napi_valuetype valuetype0; 2528 napi_typeof(env1, args[0], &valuetype0); 2529 int32_t tmp = 0; 2530 napi_get_value_int32(env1, args[0], &tmp); 2531 instanceData->value = tmp; 2532 // Associate the obtained parameters with the current JSVM environment. 2533 OH_JSVM_SetInstanceData(env, instanceData, InstanceFinalizeCallback, nullptr); 2534 InstanceData *resData = nullptr; 2535 // Obtain the data associated with the JSVM instance. 2536 OH_JSVM_GetInstanceData(env, (void **)&resData); 2537 napi_value result; 2538 napi_create_uint32(env1, resData->value, &result); 2539 return result; 2540} 2541``` 2542 2543### Task Queue 2544 2545#### When to Use 2546 2547Start the running of a task queue in a JSVM and check whether there are micro tasks waiting in the queue. The task queue can be executed cyclically by external events. 2548 2549#### Available APIs 2550| API| Description| 2551| -------- | -------- | 2552|OH_JSVM_PumpMessageLoop| Starts running a task queue.| 2553|OH_JSVM_PerformMicrotaskCheckpoint| Executes micro tasks in a task queue.| 2554 2555#### Example 2556 2557See [Working with Task Queues Using JSVM-API](use-jsvm-execute_tasks.md).