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 1565#### Example 1566 1567Wrap a native object in a JS object. 1568 1569```c++ 1570static JSVM_Value AssertEqual(JSVM_Env env, JSVM_CallbackInfo info) 1571{ 1572 size_t argc = 2; 1573 JSVM_Value args[2]; 1574 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL)); 1575 1576 bool isStrictEquals = false; 1577 OH_JSVM_StrictEquals(env, args[0], args[1], &isStrictEquals); 1578 return nullptr; 1579} 1580 1581static napi_value TestWrap(napi_env env1, napi_callback_info info) 1582{ 1583 OH_LOG_ERROR(LOG_APP, "testWrap start"); 1584 JSVM_InitOptions init_options; 1585 memset(&init_options, 0, sizeof(init_options)); 1586 init_options.externalReferences = externals; 1587 if (aa == 0) { 1588 OH_JSVM_Init(&init_options); 1589 aa++; 1590 } 1591 JSVM_VM vm; 1592 JSVM_CreateVMOptions options; 1593 memset(&options, 0, sizeof(options)); 1594 OH_JSVM_CreateVM(&options, &vm); 1595 JSVM_VMScope vm_scope; 1596 OH_JSVM_OpenVMScope(vm, &vm_scope); 1597 JSVM_Env env; 1598 JSVM_CallbackStruct param[1]; 1599 param[0].data = nullptr; 1600 param[0].callback = AssertEqual; 1601 JSVM_PropertyDescriptor descriptor[] = { 1602 {"assertEqual", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 1603 }; 1604 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 1605 JSVM_EnvScope envScope; 1606 OH_JSVM_OpenEnvScope(env, &envScope); 1607 JSVM_HandleScope handlescope; 1608 OH_JSVM_OpenHandleScope(env, &handlescope); 1609 JSVM_Value testClass = nullptr; 1610 JSVM_CallbackStruct param1; 1611 param1.data = nullptr; 1612 param1.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { 1613 JSVM_Value thisVar = nullptr; 1614 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr); 1615 1616 return thisVar; 1617 }; 1618 OH_JSVM_DefineClass(env, "TestClass", JSVM_AUTO_LENGTH, ¶m1, 0, nullptr, &testClass); 1619 1620 JSVM_Value instanceValue = nullptr; 1621 OH_JSVM_NewInstance(env, testClass, 0, nullptr, &instanceValue); 1622 1623 const char *testStr = "test"; 1624 OH_JSVM_Wrap( 1625 env, instanceValue, (void *)testStr, [](JSVM_Env env, void *data, void *hint) {}, nullptr, nullptr); 1626 const char *tmpTestStr = nullptr; 1627 OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr); 1628 const char *tmpTestStr1 = nullptr; 1629 OH_JSVM_RemoveWrap(env, instanceValue, (void **)&tmpTestStr1); 1630 OH_JSVM_Unwrap(env, instanceValue, (void **)&tmpTestStr1); 1631 OH_JSVM_CloseHandleScope(env, handlescope); 1632 OH_JSVM_CloseEnvScope(env, envScope); 1633 OH_JSVM_DestroyEnv(env); 1634 OH_JSVM_CloseVMScope(vm, vm_scope); 1635 OH_JSVM_DestroyVM(vm); 1636 OH_LOG_ERROR(LOG_APP, "testWrap pass"); 1637 return nullptr; 1638} 1639``` 1640 1641 1642Wrap a native object and register a listener for property access operations. 1643 1644```c++ 1645static int aa = 0; 1646static JSVM_Value hello(JSVM_Env env, JSVM_CallbackInfo info) { 1647 JSVM_Value output; 1648 void *data = nullptr; 1649 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data); 1650 OH_JSVM_CreateStringUtf8(env, (char *)data, strlen((char *)data), &output); 1651 return output; 1652} 1653 1654static JSVM_CallbackStruct hello_cb = {hello, (void *)"Hello"}; 1655static intptr_t externals[] = { 1656 (intptr_t)&hello_cb, 1657 0, 1658}; 1659 1660static void test1() { OH_LOG_INFO(LOG_APP, "test1 called"); } 1661 1662struct Test { 1663 void *ptr1; 1664 void *ptr2; 1665}; 1666 1667static JSVM_Value assertEqual(JSVM_Env env, JSVM_CallbackInfo info) { 1668 size_t argc = 2; 1669 JSVM_Value args[2]; 1670 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL)); 1671 1672 bool isStrictEquals = false; 1673 OH_JSVM_StrictEquals(env, args[0], args[1], &isStrictEquals); 1674 return nullptr; 1675} 1676 1677static JSVM_Value GetPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value thisArg, JSVM_Value data) { 1678 // This callback is triggered by the getter of the object. 1679 char strValue[100]; 1680 size_t size; 1681 OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size); 1682 JSVM_Value newResult = nullptr; 1683 char newStr[] = "new return value hahaha from name listening"; 1684 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1685 int signBit = 0; 1686 size_t wordCount = 2; 1687 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1688 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1689 if (status == JSVM_OK) { 1690 OH_LOG_INFO(LOG_APP, "GetPropertyCbInfo wordCount is %{public}zu", wordCount); 1691 auto test = reinterpret_cast<Test *>(wordsOut); 1692 typedef void (*callTest1)(); 1693 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1694 callTe(); 1695 } 1696 return nullptr; 1697} 1698 1699static JSVM_Value SetPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value property, JSVM_Value thisArg, JSVM_Value data) { 1700 // This callback is triggered by the setter of the object. 1701 char strValue[100]; 1702 size_t size; 1703 OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size); 1704 JSVM_Value newResult = nullptr; 1705 char newStr[] = "new return value hahaha from name listening"; 1706 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1707 int signBit = 0; 1708 size_t wordCount = 2; 1709 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1710 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1711 if (status == JSVM_OK) { 1712 OH_LOG_INFO(LOG_APP, "SetPropertyCbInfo wordCount is %{public}zu", wordCount); 1713 auto test = reinterpret_cast<Test *>(wordsOut); 1714 typedef void (*callTest1)(); 1715 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1716 callTe(); 1717 } 1718 return nullptr; 1719} 1720 1721static JSVM_Value DeleterPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value thisArg, JSVM_Value data) { 1722 // This callback is triggered by the deleter of the object. 1723 char strValue[100]; 1724 size_t size; 1725 OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size); 1726 JSVM_Value newResult = nullptr; 1727 bool returnValue = false; 1728 OH_JSVM_GetBoolean(env, returnValue, &newResult); 1729 int signBit = 0; 1730 size_t wordCount = 2; 1731 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1732 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1733 if (status == JSVM_OK) { 1734 OH_LOG_INFO(LOG_APP, "DeleterPropertyCbInfo wordCount is %{public}zu", wordCount); 1735 auto test = reinterpret_cast<Test *>(wordsOut); 1736 typedef void (*callTest1)(); 1737 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1738 callTe(); 1739 } 1740 return nullptr; 1741} 1742 1743static JSVM_Value EnumeratorPropertyCbInfo(JSVM_Env env, JSVM_Value thisArg, JSVM_Value data) { 1744 // This callback is triggered by the enumerator of an object. 1745 JSVM_Value testArray = nullptr; 1746 OH_JSVM_CreateArrayWithLength(env, 2, &testArray); 1747 JSVM_Value name1 = nullptr; 1748 char newStr1[] = "hahaha"; 1749 OH_JSVM_CreateStringUtf8(env, newStr1, strlen(newStr1), &name1); 1750 JSVM_Value name2 = nullptr; 1751 char newStr2[] = "heheheh"; 1752 OH_JSVM_CreateStringUtf8(env, newStr2, strlen(newStr2), &name2); 1753 1754 OH_JSVM_SetElement(env, testArray, 0, name1); 1755 OH_JSVM_SetElement(env, testArray, 1, name2); 1756 int signBit = 0; 1757 size_t wordCount = 2; 1758 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1759 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1760 if (status == JSVM_OK) { 1761 OH_LOG_INFO(LOG_APP, "EnumeratorPropertyCbInfo wordCount is %{public}zu", wordCount); 1762 auto test = reinterpret_cast<Test *>(wordsOut); 1763 typedef void (*callTest1)(); 1764 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1765 callTe(); 1766 } 1767 return nullptr; 1768} 1769 1770static JSVM_Value IndexedPropertyGet(JSVM_Env env, JSVM_Value index, JSVM_Value thisArg, JSVM_Value data) { 1771 // This callback is triggered by the indexed getter. 1772 uint32_t value; 1773 OH_JSVM_GetValueUint32(env, index, &value); 1774 1775 JSVM_Value newResult = nullptr; 1776 char newStr[] = "new return value hahaha from index listening"; 1777 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1778 int signBit = 0; 1779 size_t wordCount = 2; 1780 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1781 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1782 if (status == JSVM_OK) { 1783 OH_LOG_INFO(LOG_APP, "IndexedPropertyGet wordCount is %{public}zu", wordCount); 1784 auto test = reinterpret_cast<Test *>(wordsOut); 1785 typedef void (*callTest1)(); 1786 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1787 callTe(); 1788 } 1789 return nullptr; 1790} 1791 1792static JSVM_Value IndexedPropertySet(JSVM_Env env, JSVM_Value index, JSVM_Value property, JSVM_Value thisArg, JSVM_Value data) { 1793 // This callback is triggered by the indexed setter. 1794 uint32_t value; 1795 OH_JSVM_GetValueUint32(env, index, &value); 1796 char str[100]; 1797 size_t size; 1798 OH_JSVM_GetValueStringUtf8(env, property, str, 100, &size); 1799 JSVM_Value newResult = nullptr; 1800 char newStr[] = "new return value hahaha from name listening"; 1801 OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult); 1802 int signBit = 0; 1803 size_t wordCount = 2; 1804 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1805 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1806 if (status == JSVM_OK) { 1807 OH_LOG_INFO(LOG_APP, "IndexedPropertySet wordCount is %{public}zu", wordCount); 1808 auto test = reinterpret_cast<Test *>(wordsOut); 1809 typedef void (*callTest1)(); 1810 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1811 callTe(); 1812 } 1813 return nullptr; 1814} 1815 1816static JSVM_Value IndexedPropertyDeleter(JSVM_Env env, JSVM_Value index, JSVM_Value thisArg, JSVM_Value data) { 1817 // This callback is triggered by the indexed deleter. 1818 uint32_t value; 1819 OH_JSVM_GetValueUint32(env, index, &value); 1820 JSVM_Value newResult = nullptr; 1821 bool returnValue = false; 1822 OH_JSVM_GetBoolean(env, returnValue, &newResult); 1823 int signBit = 0; 1824 size_t wordCount = 2; 1825 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1826 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1827 if (status == JSVM_OK) { 1828 OH_LOG_INFO(LOG_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount); 1829 auto test = reinterpret_cast<Test *>(wordsOut); 1830 typedef void (*callTest1)(); 1831 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1832 callTe(); 1833 } 1834 return nullptr; 1835} 1836 1837static JSVM_Value IndexedPropertyEnumerator(JSVM_Env env, JSVM_Value thisArg, JSVM_Value data) { 1838 // This callback is triggered by the indexed enumerator. 1839 JSVM_Value testArray = nullptr; 1840 OH_JSVM_CreateArrayWithLength(env, 2, &testArray); 1841 JSVM_Value index1 = nullptr; 1842 OH_JSVM_CreateUint32(env, 1, &index1); 1843 JSVM_Value index2 = nullptr; 1844 OH_JSVM_CreateUint32(env, 2, &index2); 1845 OH_JSVM_SetElement(env, testArray, 0, index1); 1846 OH_JSVM_SetElement(env, testArray, 1, index2); 1847 int signBit = 0; 1848 size_t wordCount = 2; 1849 uint64_t wordsOut[2] = {0ULL, 0ULL}; 1850 JSVM_Status status = OH_JSVM_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut); 1851 if (status == JSVM_OK) { 1852 OH_LOG_INFO(LOG_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount); 1853 auto test = reinterpret_cast<Test *>(wordsOut); 1854 typedef void (*callTest1)(); 1855 callTest1 callTe = reinterpret_cast<callTest1>(test->ptr1); 1856 callTe(); 1857 } 1858 return nullptr; 1859} 1860 1861static napi_value TestDefineClassWithProperty(napi_env env1, napi_callback_info info) { 1862 OH_LOG_ERROR(LOG_APP, "TestDefineClassWithProperty start"); 1863 JSVM_InitOptions init_options; 1864 memset(&init_options, 0, sizeof(init_options)); 1865 init_options.externalReferences = externals; 1866 if (aa == 0) { 1867 OH_JSVM_Init(&init_options); 1868 aa++; 1869 } 1870 JSVM_VM vm; 1871 JSVM_CreateVMOptions options; 1872 memset(&options, 0, sizeof(options)); 1873 OH_JSVM_CreateVM(&options, &vm); 1874 JSVM_VMScope vm_scope; 1875 OH_JSVM_OpenVMScope(vm, &vm_scope); 1876 JSVM_Env env; 1877 JSVM_CallbackStruct param[1]; 1878 param[0].data = nullptr; 1879 param[0].callback = assertEqual; 1880 JSVM_PropertyDescriptor descriptor[] = { 1881 {"assertEqual", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 1882 }; 1883 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 1884 JSVM_EnvScope envScope; 1885 OH_JSVM_OpenEnvScope(env, &envScope); 1886 JSVM_HandleScope handlescope; 1887 OH_JSVM_OpenHandleScope(env, &handlescope); 1888 1889 1890 JSVM_CallbackStruct param1; 1891 param1.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { 1892 JSVM_Value thisVar = nullptr; 1893 OH_JSVM_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr); 1894 return thisVar; 1895 }; 1896 param1.data = nullptr; 1897 1898 JSVM_Value res = nullptr; 1899 Test *test = new Test(); 1900 test->ptr1 = (void *)test1; 1901 test->ptr2 = (void *)test1; 1902 OH_LOG_INFO(LOG_APP, "OH_JSVM_CreateBigintWords 111 word count %{public}d", 1903 sizeof(*test) / sizeof(uint64_t)); 1904 JSVM_Status status = OH_JSVM_CreateBigintWords(env, 1, 2, reinterpret_cast<const uint64_t *>(test), &res); 1905 1906 // Initialize propertyCfg. 1907 JSVM_PropertyHandlerConfigurationStruct propertyCfg; 1908 propertyCfg.genericNamedPropertyGetterCallback = GetPropertyCbInfo; 1909 propertyCfg.genericNamedPropertySetterCallback = SetPropertyCbInfo; 1910 propertyCfg.genericNamedPropertyDeleterCallback = DeleterPropertyCbInfo; 1911 propertyCfg.genericNamedPropertyEnumeratorCallback = EnumeratorPropertyCbInfo; 1912 propertyCfg.genericIndexedPropertyGetterCallback = IndexedPropertyGet; 1913 propertyCfg.genericIndexedPropertySetterCallback = IndexedPropertySet; 1914 propertyCfg.genericIndexedPropertyDeleterCallback = IndexedPropertyDeleter; 1915 propertyCfg.genericIndexedPropertyEnumeratorCallback = IndexedPropertyEnumerator; 1916 propertyCfg.namedPropertyData = res; 1917 propertyCfg.indexedPropertyData = res; 1918 1919 JSVM_CallbackStruct callbackStruct; 1920 callbackStruct.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { 1921 OH_LOG_INFO(LOG_APP, "call as a function called"); 1922 JSVM_Value thisVar = nullptr; 1923 void *innerData; 1924 size_t argc = 1; 1925 JSVM_Value args[1]; 1926 OH_JSVM_GetCbInfo(env, info, &argc, args, &thisVar, &innerData); 1927 OH_LOG_INFO(LOG_APP, "function call as function result is %{public}s", reinterpret_cast<char *>(innerData)); 1928 uint32_t ret = 0; 1929 OH_JSVM_GetValueUint32(env, args[0], &ret); 1930 const char testStr[] = "hello world 111111"; 1931 JSVM_Value setvalueName = nullptr; 1932 JSVM_CALL(env, OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName)); 1933 return setvalueName; 1934 }; 1935 char data[100] = "1111 hello world"; 1936 callbackStruct.data = data; 1937 JSVM_Value testWrapClass = nullptr; 1938 1939 // Register a property access listener in propertyCfg. 1940 OH_JSVM_DefineClassWithPropertyHandler(env, "TestWrapClass", NAPI_AUTO_LENGTH, ¶m1, 0, nullptr, &propertyCfg, 1941 &callbackStruct, &testWrapClass); 1942 JSVM_Value instanceValue = nullptr; 1943 OH_JSVM_NewInstance(env, testWrapClass, 0, nullptr, &instanceValue); 1944 const char testStr[] = "hello world"; 1945 JSVM_Value setvalueName = nullptr; 1946 OH_JSVM_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName); 1947 1948 // 1. Callbacks for properties. 1949 // Set properties. 1950 OH_JSVM_SetNamedProperty(env, instanceValue, "str11", setvalueName); 1951 OH_JSVM_SetNamedProperty(env, instanceValue, "str123", setvalueName); 1952 1953 // Obtain a property. 1954 JSVM_Value valueName = nullptr; 1955 OH_JSVM_GetNamedProperty(env, instanceValue, "str11", &valueName); 1956 char str[100]; 1957 size_t size; 1958 OH_JSVM_GetValueStringUtf8(env, valueName, str, 100, &size); 1959 1960 // Obtain all property names. 1961 JSVM_Value allPropertyNames = nullptr; 1962 OH_JSVM_GetAllPropertyNames(env, instanceValue, JSVM_KEY_OWN_ONLY, 1963 static_cast<JSVM_KeyFilter>(JSVM_KEY_ENUMERABLE | JSVM_KEY_SKIP_SYMBOLS), 1964 JSVM_KEY_NUMBERS_TO_STRINGS, &allPropertyNames); 1965 uint32_t nameSize = 0; 1966 OH_JSVM_GetArrayLength(env, allPropertyNames, &nameSize); 1967 JSVM_Value propertyName = nullptr; 1968 for (uint32_t i = 0; i < nameSize; ++i) { 1969 OH_JSVM_GetElement(env, allPropertyNames, i, &propertyName); 1970 char str[100]; 1971 size_t size; 1972 OH_JSVM_GetValueStringUtf8(env, propertyName, str, 100, &size); 1973 } 1974 1975 // Delete a property. 1976 bool result = false; 1977 propertyName = nullptr; 1978 char propertyChar[] = "str11"; 1979 OH_JSVM_CreateStringUtf8(env, propertyChar, strlen(propertyChar), &propertyName); 1980 OH_JSVM_DeleteProperty(env, instanceValue, propertyName, &result); 1981 1982 // 2. Callbacks for index properties. 1983 // Set properties. 1984 JSVM_Value jsIndex = nullptr; 1985 uint32_t index = 0; 1986 OH_JSVM_CreateUint32(env, index, &jsIndex); 1987 OH_JSVM_SetProperty(env, instanceValue, jsIndex, setvalueName); 1988 JSVM_Value jsIndex1 = nullptr; 1989 index = 1; 1990 OH_JSVM_CreateUint32(env, index, &jsIndex1); 1991 OH_JSVM_SetProperty(env, instanceValue, jsIndex1, setvalueName); 1992 1993 // Obtain a property. 1994 JSVM_Value valueName1 = nullptr; 1995 OH_JSVM_GetProperty(env, instanceValue, jsIndex, &valueName1); 1996 char str1[100]; 1997 size_t size1; 1998 OH_JSVM_GetValueStringUtf8(env, valueName1, str1, 100, &size1); 1999 2000 // Obtain all property names. 2001 JSVM_Value allPropertyNames1 = nullptr; 2002 OH_JSVM_GetAllPropertyNames(env, instanceValue, JSVM_KEY_OWN_ONLY, 2003 static_cast<JSVM_KeyFilter>(JSVM_KEY_ENUMERABLE | JSVM_KEY_SKIP_SYMBOLS), 2004 JSVM_KEY_NUMBERS_TO_STRINGS, &allPropertyNames1); 2005 uint32_t nameSize1 = 0; 2006 OH_JSVM_GetArrayLength(env, allPropertyNames1, &nameSize); 2007 JSVM_Value propertyName1 = nullptr; 2008 for (uint32_t i = 0; i < nameSize1; ++i) { 2009 OH_JSVM_GetElement(env, allPropertyNames1, i, &propertyName1); 2010 char str[100]; 2011 size_t size; 2012 OH_JSVM_GetValueStringUtf8(env, propertyName1, str, 100, &size); 2013 } 2014 2015 // Delete a property. 2016 bool result1 = false; 2017 OH_JSVM_DeleteProperty(env, instanceValue, jsIndex, &result1); 2018 2019 // 3. Callback of a function. 2020 JSVM_Value gloablObj = nullptr; 2021 OH_JSVM_GetGlobal(env, &gloablObj); 2022 OH_JSVM_SetNamedProperty(env, gloablObj, "myTestInstance", instanceValue); 2023 OH_LOG_INFO(LOG_APP, "set property on global object"); 2024 std::string innerSourcecodestr = R"( 2025 { 2026 let res = myTestInstance(12); 2027 })"; 2028 JSVM_Value innerSourcecodevalue; 2029 OH_JSVM_CreateStringUtf8(env, innerSourcecodestr.c_str(), innerSourcecodestr.size(), &innerSourcecodevalue); 2030 JSVM_Script innerscript; 2031 OH_JSVM_CompileScript(env, innerSourcecodevalue, nullptr, 0, true, nullptr, &innerscript); 2032 JSVM_Value innerResult; 2033 OH_JSVM_RunScript(env, innerscript, &innerResult); 2034 2035 OH_JSVM_CloseHandleScope(env, handlescope); 2036 OH_JSVM_CloseEnvScope(env, envScope); 2037 OH_JSVM_DestroyEnv(env); 2038 OH_JSVM_CloseVMScope(vm, vm_scope); 2039 OH_JSVM_DestroyVM(vm); 2040 OH_LOG_ERROR(LOG_APP, "TestDefineClassWithProperty pass"); 2041 return nullptr; 2042} 2043``` 2044 2045### Version Management 2046 2047#### When to Use 2048 2049Obtain version information. 2050 2051#### Available APIs 2052| API| Description| 2053| -------- | -------- | 2054|OH_JSVM_GetVersion| Obtains the latest JSVM API version supported by the JSVM runtime.| 2055|OH_JSVM_GetVMInfo| Obtains the VM information.| 2056 2057#### Example 2058 2059Obtain version information. 2060 2061```c++ 2062JSVM_VMInfo result; 2063OH_JSVM_GetVMInfo(&result); 2064uint32_t versionId = 0; 2065OH_JSVM_GetVersion(env, &versionId); 2066``` 2067 2068### Memory Management 2069 2070#### When to Use 2071 2072Perform memory management. 2073 2074#### Available APIs 2075| API | Description | 2076| ------------------------------------------- | ------------------------------------------------------------------------------------------------------ | 2077| 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.| 2078| OH_JSVM_MemoryPressureNotification | Notifies the VM of the memory pressure level and selectively triggers GC. | 2079| OH_JSVM_AllocateArrayBufferBackingStoreData | Allocates memory for a backing store.| 2080| OH_JSVM_FreeArrayBufferBackingStoreData | Releases the backing store memory.| 2081| OH_JSVM_CreateArrayBufferFromBackingStoreData | Creates an array buffer based on the backing store memory allocated.| 2082 2083> 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. 2084 2085#### Example 2086 2087Perform memory management. 2088 2089```c++ 2090// Before and after calling OH_JSVM_AdjustExternalMemory, check the memory allocated externally from the perspective of the underlying VM. 2091int64_t result; 2092OH_JSVM_AdjustExternalMemory(env, 0, &result); // The externally allocated memory remains unchanged. 2093OH_LOG_INFO(LOG_APP, "Before AdjustExternalMemory: %{public}lld\n", result); // Obtain the memory value before the adjustment. 2094// Increase the memory usage and notify the VM of the change. 2095int64_t memoryIncrease = 1024 * 1024; // Increase the memory by 1 MB. 2096OH_JSVM_AdjustExternalMemory(env, memoryIncrease, &result); 2097OH_LOG_INFO(LOG_APP, "After AdjustExternalMemory: %{public}lld\n", result); // Obtain the memory value after the adjustment. 2098``` 2099```c++ 2100// Open a handle scope and apply for a large amount of memory within the scope to test the function. 2101// Check the memory status after the memory is allocated, after the scope is closed, and after OH_JSVM_MemoryPressureNotification is called. 2102JSVM_HandleScope tmpscope; 2103OH_JSVM_OpenHandleScope(env, &tmpscope); 2104for (int i = 0; i < 1000000; ++i) { 2105 JSVM_Value obj; 2106 OH_JSVM_CreateObject(env, &obj); 2107} 2108JSVM_HeapStatistics mem; 2109OH_JSVM_GetHeapStatistics(vm, &mem); // Obtain the heap statistics of the VM. 2110OH_LOG_INFO(LOG_APP, " %{public}zu\n", mem.usedHeapSize); // After the requested memory is allocated, the memory is of the maximum size. 2111OH_JSVM_CloseHandleScope (env, tmpscope); // Close the handle scope. 2112 2113OH_JSVM_GetHeapStatistics(vm, &mem); 2114OH_LOG_INFO(LOG_APP, " %{public}zu\n", mem.usedHeapSize); // After the scope is closed, GC is not performed immediately. 2115 2116// Notify the VM of the memory pressure level and selectively trigger GC. 2117OH_JSVM_MemoryPressureNotification(env, JSVM_MEMORY_PRESSURE_LEVEL_CRITICAL); // The memory pressure is in the critical state. 2118 2119OH_JSVM_GetHeapStatistics(vm, &mem); 2120OH_LOG_INFO(LOG_APP, " %{public}zu\n", mem.usedHeapSize); // After GC is triggered. 2121``` 2122 2123**Example** 2124 2125``` c++ 2126void *backingStore; 2127JSVM_Value arrayBuffer; 2128 2129// Allocate memory of 100 bytes for a backing store. 2130OH_JSVM_AllocateArrayBufferBackingStoreData(100, JSVM_ZERO_INITIALIZED, &backingStore); 2131 2132// In the allocated memory, create an ArrayBuffer of 20 bytes at 30 bytes away from the start address of the backing store. 2133OH_JSVM_CreateArrayBufferFromBackingStoreData(env, backingStore, 100, 30, 20, &arrayBuffer); 2134 2135// Use the created ArrayBuffer in JS. 2136JSVM_Value js_global; 2137JSVM_Value name; 2138OH_JSVM_GetGlobal(jsvm_env, &js_global); 2139OH_JSVM_CreateStringUtf8(jsvm_env, "buffer", JSVM_AUTO_LENGTH, &name); 2140OH_JSVM_SetProperty(env, js_global, name, arrayBuffer); 2141 2142JSVM_Script script; 2143JSVM_Value scriptString; 2144JSVM_Value result; 2145const char *src = R"JS( 2146function writeBuffer(data) { 2147 let view = new Uint8Array(data); 2148 // Write some values to the ArrayBuffer 2149 for (let i = 0; i < view.length; i++) { 2150 view[i] = i % 256; 2151 } 2152} 2153writeBuffer(buffer) 2154)JS"; 2155OH_JSVM_CreateStringUtf8(env, src, JSVM_AUTO_LENGTH, &scriptString); 2156OH_JSVM_CompileScriptWithOptions(env, scriptString, 0, nullptr, &script); 2157OH_JSVM_RunScript(env, script, &result); 2158 2159// Check the ArrayBuffer content. 2160uint8_t *array = static_cast<uint8_t*>(backingStore); 2161for (auto i = 0; i < 100; ++i) { 2162 if (array[i] != i % 25 % 256) { 2163 return false; 2164 } 2165} 2166 2167// Release the ArrayBuffer. Before releasing the backing store, you must 2168// call OH_JSVM_DetachArraybuffer to release all ArrayBuffers created in the backing store. 2169// Otherwise, unpredictable memory problems may occur. 2170OH_JSVM_DetachArraybuffer(env, arrayBuffer); 2171 2172// Release the memory allocated for the backing store. 2173OH_JSVM_FreeArrayBufferBackingStoreData(backingStore); 2174``` 2175### Promises 2176 2177#### When to Use 2178 2179Perform operations related to promises. 2180 2181#### Available APIs 2182| API| Description| 2183| -------- | -------- | 2184|OH_JSVM_CreatePromise| Creates a **deferred** object and a JS promise.| 2185|OH_JSVM_ResolveDeferred| Resolves a JS promise by using the **deferred** object associated with it.| 2186|OH_JSVM_RejectDeferred| Rejects a JS promise by using the **deferred** object associated with it.| 2187|OH_JSVM_IsPromise| Checks whether a promise object is a native promise object.| 2188 2189#### Example 2190 2191Perform operations related to promises. 2192 2193```c++ 2194JSVM_Deferred deferred; 2195JSVM_Value promise; 2196OH_JSVM_CreatePromise(env, &deferred, &promise); 2197 2198// Perform an asynchronous operation. 2199int result = 42; 2200bool success = true; 2201if (success) 2202{ 2203 // Resolve the promise and pass the result. 2204 JSVM_Value value; 2205 OH_JSVM_CreateInt32(env, result, &value); 2206 OH_JSVM_ResolveDeferred(env, deferred, value); 2207} else { 2208 // Reject the promise and pass the error information. 2209 JSVM_Value code = nullptr; 2210 JSVM_Value message = nullptr; 2211 OH_JSVM_CreateStringUtf8(env, "600", JSVM_AUTO_LENGTH, &code); 2212 OH_JSVM_CreateStringUtf8(env, "Async operation failed", JSVM_AUTO_LENGTH, &message); 2213 JSVM_Value error = nullptr; 2214 OH_JSVM_CreateError(env, code, message, &error); 2215 OH_JSVM_RejectDeferred(env, deferred, error); 2216} 2217``` 2218 2219### JSON Operations 2220 2221#### When to Use 2222 2223Perform JSON operations. 2224 2225#### Available APIs 2226 2227| API| Description| 2228| -------- | -------- | 2229|OH_JSVM_JsonParse| Parses a JSON string and returns the parsed value.| 2230|OH_JSVM_JsonStringify| Converts a JS object into a JSON string and returns the converted string.| 2231 2232#### Example 2233 2234Parse JSON strings. 2235 2236```c++ 2237std::string sourcecodestr = "{\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}" ; 2238JSVM_Value jsonString; 2239OH_JSVM_CreateStringUtf8(env, sourcecodestr.c_str(), sourcecodestr.size(), &jsonString) 2240JSVM_Value result; 2241OH_JSVM_JsonParse(env, jsonString, &result); 2242``` 2243 2244### Creating and Using a VM Startup Snapshot 2245 2246#### When to Use 2247 2248Create and use a VM startup snapshot. 2249 2250#### Available APIs 2251| API| Description| 2252| -------- | -------- | 2253|OH_JSVM_CreateSnapshot| Creates a VM startup snapshot.| 2254|OH_JSVM_CreateEnvFromSnapshot| Creates a JSVM environment from a startup snapshot.| 2255 2256#### Example 2257 2258See [Working with VM Snapshots Using JSVM-API](use-jsvm-create-snapshot.md). 2259 2260### Checking Input Parameters 2261 2262#### When to Use 2263 2264Check whether the input parameters are callable. 2265 2266#### Available APIs 2267| API| Description| 2268| -------- | -------- | 2269|OH_JSVM_IsCallable| Checks whether the input parameters are callable. | 2270 2271#### Example 2272 2273Check whether input parameters are callable. 2274 2275```c++ 2276static JSVM_Value NapiIsCallable(JSVM_Env env, JSVM_CallbackInfo info) { 2277 JSVM_Value value, rst; 2278 size_t argc = 1; 2279 bool isCallable = false; 2280 JSVM_CALL(env, OH_JSVM_GetCbInfo(env, info, &argc, &value, NULL, NULL)); 2281 JSVM_CALL(env, OH_JSVM_IsCallable(env, value, &isCallable)); 2282 OH_JSVM_GetBoolean(env, isCallable, &rst); 2283 return rst; 2284} 2285 2286static napi_value MyJSVMDemo([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) { 2287 std::thread t([]() { 2288 // Create a VM instance and open the VM scope. 2289 JSVM_VM vm; 2290 JSVM_CreateVMOptions options; 2291 memset(&options, 0, sizeof(options)); 2292 OH_JSVM_CreateVM(&options, &vm); 2293 JSVM_VMScope vmScope; 2294 OH_JSVM_OpenVMScope(vm, &vmScope); 2295 JSVM_CallbackStruct param[] = { 2296 {.data = nullptr, .callback = NapiIsCallable}, 2297 }; 2298 JSVM_PropertyDescriptor descriptor[] = { 2299 {"napiIsCallable", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 2300 }; 2301 // Create env, register a native method, and open an env scope. 2302 JSVM_Env env; 2303 OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env); 2304 JSVM_EnvScope envScope; 2305 OH_JSVM_OpenEnvScope(env, &envScope); 2306 // Open a handle scope. 2307 JSVM_HandleScope handleScope; 2308 OH_JSVM_OpenHandleScope(env, &handleScope); 2309 std::string sourceCodeStr = R"JS( 2310 function addNumbers(num1, num2) 2311 { 2312 var rst= num1 + num2; 2313 return rst; 2314 } 2315 let rst = napiIsCallable(addNumbers); 2316 )JS"; 2317 // Compile the JS script. 2318 JSVM_Value sourceCodeValue; 2319 OH_JSVM_CreateStringUtf8(env, sourceCodeStr.c_str(), sourceCodeStr.size(), &sourceCodeValue); 2320 JSVM_Script script; 2321 OH_JSVM_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script); 2322 JSVM_Value result; 2323 // Run the JS script. 2324 OH_JSVM_RunScript(env, script, &result); 2325 JSVM_ValueType type; 2326 OH_JSVM_Typeof(env, result, &type); 2327 OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type); 2328 // Exit the VM and release the memory. 2329 OH_JSVM_CloseHandleScope(env, handleScope); 2330 OH_JSVM_CloseEnvScope(env, envScope); 2331 OH_JSVM_DestroyEnv(env); 2332 OH_JSVM_CloseVMScope(vm, vmScope); 2333 OH_JSVM_DestroyVM(vm); 2334 }); 2335 t.detach(); 2336 return nullptr; 2337} 2338``` 2339 2340### Lock Operations 2341 2342#### When to Use 2343 2344Perform lock operations. 2345 2346#### Available APIs 2347| API| Description| 2348| -------- | -------- | 2349|OH_JSVM_IsLocked| Checks whether the current thread holds a lock of the specified environment.| 2350|OH_JSVM_AcquireLock| Obtains a lock.| 2351|OH_JSVM_ReleaseLock| Releases a lock.| 2352 2353#### Example 2354 2355Obtain and release a lock. 2356 2357```c++ 2358class LockWrapper { 2359 public: 2360 LockWrapper(JSVM_Env env) : env(env) { 2361 OH_JSVM_IsLocked(env, &isLocked); 2362 if (!isLocked) { 2363 OH_JSVM_AcquireLock(env); 2364 OH_JSVM_GetVM(env, &vm); 2365 OH_JSVM_OpenVMScope(vm, &vmScope); 2366 OH_JSVM_OpenEnvScope(env, &envScope); 2367 } 2368 } 2369 2370 ~LockWrapper() { 2371 if (!isLocked) { 2372 OH_JSVM_CloseEnvScope(env, envScope); 2373 OH_JSVM_CloseVMScope(vm, vmScope); 2374 OH_JSVM_ReleaseLock(env); 2375 } 2376 } 2377 2378 LockWrapper(const LockWrapper&) = delete; 2379 LockWrapper& operator=(const LockWrapper&) = delete; 2380 LockWrapper(LockWrapper&&) = delete; 2381 void* operator new(size_t) = delete; 2382 void* operator new[](size_t) = delete; 2383 2384 private: 2385 JSVM_Env env; 2386 JSVM_EnvScope envScope; 2387 JSVM_VMScope vmScope; 2388 JSVM_VM vm; 2389 bool isLocked; 2390}; 2391 2392static napi_value Add([[maybe_unused]] napi_env _env, [[maybe_unused]] napi_callback_info _info) { 2393 static JSVM_VM vm; 2394 static JSVM_Env env; 2395 if (aa == 0) { 2396 OH_JSVM_Init(nullptr); 2397 aa++; 2398 // create vm 2399 JSVM_CreateVMOptions options; 2400 memset(&options, 0, sizeof(options)); 2401 OH_JSVM_CreateVM(&options, &vm); 2402 // create env 2403 OH_JSVM_CreateEnv(vm, 0, nullptr, &env); 2404 } 2405 2406 std::thread t1([]() { 2407 LockWrapper lock(env); 2408 JSVM_HandleScope handleScope; 2409 OH_JSVM_OpenHandleScope(env, &handleScope); 2410 JSVM_Value value; 2411 JSVM_Status rst = OH_JSVM_CreateInt32(env, 32, &value); // 32: numerical value 2412 if (rst == JSVM_OK) { 2413 OH_LOG_INFO(LOG_APP, "JSVM:t1 OH_JSVM_CreateInt32 suc"); 2414 } else { 2415 OH_LOG_ERROR(LOG_APP, "JSVM:t1 OH_JSVM_CreateInt32 fail"); 2416 } 2417 int32_t num1; 2418 OH_JSVM_GetValueInt32(env, value, &num1); 2419 OH_LOG_INFO(LOG_APP, "JSVM:t1 num1 = %{public}d", num1); 2420 OH_JSVM_CloseHandleScope(env, handleScope); 2421 }); 2422 std::thread t2([]() { 2423 LockWrapper lock(env); 2424 JSVM_HandleScope handleScope; 2425 OH_JSVM_OpenHandleScope(env, &handleScope); 2426 JSVM_Value value; 2427 JSVM_Status rst = OH_JSVM_CreateInt32(env, 32, &value); // 32: numerical value 2428 if (rst == JSVM_OK) { 2429 OH_LOG_INFO(LOG_APP, "JSVM:t2 OH_JSVM_CreateInt32 suc"); 2430 } else { 2431 OH_LOG_ERROR(LOG_APP, "JSVM:t2 OH_JSVM_CreateInt32 fail"); 2432 } 2433 int32_t num1; 2434 OH_JSVM_GetValueInt32(env, value, &num1); 2435 OH_LOG_INFO(LOG_APP, "JSVM:t2 num1 = %{public}d", num1); 2436 OH_JSVM_CloseHandleScope(env, handleScope); 2437 }); 2438 t1.detach(); 2439 t2.detach(); 2440 return nullptr; 2441} 2442``` 2443 2444### Setting and Obtaining Data Associated with a JSVM Instance 2445 2446#### When to Use 2447 2448Set and obtain the data associated with a JSVM instance. 2449 2450#### Available APIs 2451| API| Description| 2452| -------- | -------- | 2453|OH_JSVM_SetInstanceData| Sets data to be associated with a JSVM instance.| 2454|OH_JSVM_GetInstanceData| Obtains the data associated with a JSVM instance.| 2455 2456#### Example 2457 2458Set and obtain the data associated with a JSVM instance. 2459 2460```c++ 2461JSVM_VM vm; 2462JSVM_CreateVMOptions options; 2463JSVM_VMScope vm_scope; 2464JSVM_Env env; 2465JSVM_EnvScope envScope; 2466JSVM_HandleScope handlescope; 2467 2468static int aa = 0; 2469struct InstanceData { 2470 int32_t value; 2471}; 2472 2473// Initialize the VM and create a JSVM instance. 2474void init_JSVM_environment(){ 2475 JSVM_InitOptions init_options; 2476 memset(&init_options, 0, sizeof(init_options)); 2477 if (aa == 0) { 2478 OH_JSVM_Init(&init_options); 2479 aa++; 2480 } 2481 memset(&options, 0, sizeof(options)); 2482 OH_JSVM_CreateVM(&options, &vm); 2483 OH_JSVM_OpenVMScope(vm, &vm_scope); 2484 OH_JSVM_CreateEnv(vm, 0, nullptr, &env); 2485 OH_JSVM_OpenEnvScope(env, &envScope); 2486 OH_JSVM_OpenHandleScope(env, &handlescope); 2487} 2488 2489// Exit the VM and release the running environment. 2490napi_value close_JSVM_environment(napi_env env1, napi_callback_info info) 2491{ 2492 OH_JSVM_CloseHandleScope(env, handlescope); 2493 OH_JSVM_CloseEnvScope(env, envScope); 2494 OH_JSVM_DestroyEnv(env); 2495 OH_JSVM_CloseVMScope(vm, vm_scope); 2496 OH_JSVM_DestroyVM(vm); 2497 napi_value result; 2498 char* s = "ok"; 2499 napi_create_string_latin1(env1, s, strlen(s), &result); 2500 return result; 2501} 2502 2503// Clear and release the memory used by the instance. 2504void InstanceFinalizeCallback(JSVM_Env env, void *finalizeData, void *finalizeHint) 2505{ 2506 if (finalizeData) { 2507 InstanceData *data = reinterpret_cast<InstanceData *>(finalizeData); 2508 free(data); 2509 *(InstanceData **)finalizeData = nullptr; 2510 } 2511} 2512 2513static napi_value GetInstanceData(napi_env env1, napi_callback_info info) 2514{ 2515 InstanceData *instanceData = reinterpret_cast<InstanceData *>(malloc(sizeof(InstanceData))); 2516 if (instanceData == nullptr) { 2517 printf("Memory allocation failed!\n"); 2518 return nullptr; 2519 } 2520 size_t argc = 1; 2521 napi_value args[1] = {nullptr}; 2522 // Obtain the callback function parameters. 2523 napi_get_cb_info(env1, info, &argc, args , nullptr, nullptr); 2524 napi_valuetype valuetype0; 2525 napi_typeof(env1, args[0], &valuetype0); 2526 int32_t tmp = 0; 2527 napi_get_value_int32(env1, args[0], &tmp); 2528 instanceData->value = tmp; 2529 // Associate the obtained parameters with the current JSVM environment. 2530 OH_JSVM_SetInstanceData(env, instanceData, InstanceFinalizeCallback, nullptr); 2531 InstanceData *resData = nullptr; 2532 // Obtain the data associated with the JSVM instance. 2533 OH_JSVM_GetInstanceData(env, (void **)&resData); 2534 napi_value result; 2535 napi_create_uint32(env1, resData->value, &result); 2536 return result; 2537} 2538``` 2539 2540### Task Queue 2541 2542#### When to Use 2543 2544Start 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. 2545 2546#### Available APIs 2547| API| Description| 2548| -------- | -------- | 2549|OH_JSVM_PumpMessageLoop| Starts running a task queue.| 2550|OH_JSVM_PerformMicrotaskCheckpoint| Executes micro tasks in a task queue.| 2551 2552#### Example 2553 2554See [Working with Task Queues Using JSVM-API](use-jsvm-execute_tasks.md).