1# Working with Objects Using JSVM-API
2
3## Overview
4
5JSVM-API provides APIs for basic JavaScript (JS) object operations, including creating an object, obtaining the prototype of an object, freezing or sealing an object, and checking the object type. You can use these APIs to manage JS objects.
6
7## Basic Concepts
8
9You may need to define and operate objects when using JSVM-API in development. For example, define an API with an object as an input parameter, perform operations on the object, and have a result object returned. In this process, you need to ensure that the API definition is clear and compatible with the properties and methods of the object.
10
11- API: defines the interaction protocol between components. An API includes input parameters, output result, and possible error handling. By calling APIs, components can interact and exchange data with each other without knowing the internal implementation details.
12- Object: a composite data type that allows values of different types to be stored as an independent entity in JS. An object is a collection of properties and methods. A property is a value associated with an object, and a method is an operation that the object can perform.
13
14## Available APIs
15
16| API                      | Description                                    |
17| -------------------------- | -------------------------------------------- |
18| OH_JSVM_GetPrototype         | Obtains the prototype of a JS object.            |
19| OH_JSVM_CreateObject         | Creates a default JS object.                  |
20| OH_JSVM_ObjectFreeze         | Freezes a JS object. Once a JS object is frozen, new properties cannot be added to it, existing properties cannot be removed, the enumerability, configurability, or writability of existing properties cannot be changed, and the values of existing properties cannot be changed.                            |
21| 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.                            |
22| OH_JSVM_Typeof                | Returns the type of a JS object. |
23| OH_JSVM_Instanceof            | Checks whether an object is an instance of a constructor.   |
24| OH_JSVM_TypeTagObject       | Associates the value of the **type_tag** pointer with a JS object or an external object.                 |
25| OH_JSVM_CheckObjectTypeTag | Checks whether a tag matches the tag type of an object.|
26| OH_JSVM_CreateSymbol         | Creates a symbol object based on the given descriptor.                    |
27|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.|
28| OH_JSVM_CreateExternal       | Creates a JS object that wraps an external pointer.              |
29| OH_JSVM_GetValueExternal    | Obtains the external data pointer previously passed to **OH_JSVM_CreateExternal**.                 |
30
31## Example
32
33If you are just starting out with JSVM-API, see [JSVM-API Development Process](use-jsvm-process.md). The following only demonstrates the C++ and ArkTS code for object management APIs.
34
35### OH_JSVM_GetPrototype
36
37Obtains the prototype of a JS object.
38
39CPP code:
40
41```cpp
42// hello.cpp
43#include "napi/native_api.h"
44#include "ark_runtime/jsvm.h"
45#include <hilog/log.h>
46// Register the GetPrototype callback.
47// Define OH_JSVM_GetPrototype.
48static JSVM_Value GetPrototype(JSVM_Env env, JSVM_CallbackInfo info)
49{
50    size_t argc = 1;
51    JSVM_Value argv[1] = {nullptr};
52    OH_JSVM_GetCbInfo(env, info, &argc, argv, nullptr, nullptr);
53    JSVM_Value result{nullptr};
54    JSVM_Status status = OH_JSVM_GetPrototype(env, argv[0], &result);
55    if (status != JSVM_OK) {
56        OH_LOG_ERROR(LOG_APP, "JSVM GetPrototype fail");
57    } else {
58        OH_LOG_INFO(LOG_APP, "JSVM GetPrototype success");
59    }
60    return result;
61}
62static JSVM_CallbackStruct param[] = {
63    {.data = nullptr, .callback = GetPrototype},
64};
65static JSVM_CallbackStruct *method = param;
66// Set a property descriptor named getPrototype and associate it with a callback. This allows the GetPrototype callback to be called from JS.
67static JSVM_PropertyDescriptor descriptor[] = {
68    {"getPrototype", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
69};
70// Call the C++ code from JS.
71const char* srcCallNative = R"JS(const myObject = {};
72    const proto = getPrototype(myObject);
73    console.log(proto === Object.prototype);)JS";
74```
75
76**Expected output**
77```ts
78JSVM GetPrototype success
79```
80
81### OH_JSVM_CreateObject
82
83Creates a default JS object.
84
85CPP code:
86
87```cpp
88// hello.cpp
89#include "napi/native_api.h"
90#include "ark_runtime/jsvm.h"
91#include <hilog/log.h>
92// Define OH_JSVM_CreateObject.
93static JSVM_Value CreateObject(JSVM_Env env, JSVM_CallbackInfo info)
94{
95    JSVM_Value object = nullptr;
96    // Create an empty object.
97    JSVM_Status status = OH_JSVM_CreateObject(env, &object);
98    if (status != JSVM_OK) {
99        OH_LOG_ERROR(LOG_APP, "JSVM CreateObject fail");
100    } else {
101        OH_LOG_INFO(LOG_APP, "JSVM CreateObject success");
102    }
103    // Set the object property.
104    JSVM_Value name = nullptr;
105    // Set the property name to "name".
106    OH_JSVM_CreateStringUtf8(env, "name", JSVM_AUTO_LENGTH, &name);
107    JSVM_Value value = nullptr;
108    // Set the property value to "Hello from N-API!"
109    OH_JSVM_CreateStringUtf8(env, "Hello OH_JSVM_CreateObject!", JSVM_AUTO_LENGTH, &value);
110    // Set the property on the object.
111    OH_JSVM_SetProperty(env, object, name, value);
112    return object;
113}
114// Register the CreateObject callback.
115static JSVM_CallbackStruct param[] = {
116    {.data = nullptr, .callback = CreateObject},
117};
118static JSVM_CallbackStruct *method = param;
119// Set a property descriptor named createObject and associate it with a callback. This allows the CreateObject callback to be called from JS.
120static JSVM_PropertyDescriptor descriptor[] = {
121    {"createObject", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
122};
123// Call the C++ code from JS.
124const char* srcCallNative = R"JS(createObject())JS";
125```
126
127**Expected output**
128```ts
129JSVM CreateObject success
130```
131
132### OH_JSVM_ObjectFreeze
133
134Freezes 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.
135
136CPP code:
137
138```cpp
139// hello.cpp
140#include "napi/native_api.h"
141#include "ark_runtime/jsvm.h"
142#include <hilog/log.h>
143// Define OH_JSVM_ObjectFreeze.
144static JSVM_Value ObjectFreeze(JSVM_Env env, JSVM_CallbackInfo info)
145{
146    // Accept an object passed in from JS.
147    size_t argc = 1;
148    JSVM_Value argv[1] = {nullptr};
149    OH_JSVM_GetCbInfo(env, info, &argc, argv, nullptr, nullptr);
150    // Call OH_JSVM_ObjectFreeze to freeze the object passed in.
151    JSVM_Status status = OH_JSVM_ObjectFreeze(env, argv[0]);
152    if (status == JSVM_OK) {
153        OH_LOG_INFO(LOG_APP, "Test JSVM OH_JSVM_ObjectFreeze success");
154    }
155    // Check whether the properties of the frozen object can be modified.
156    JSVM_Value value = nullptr;
157    OH_JSVM_CreateInt32(env, 111111, &value);
158    OH_JSVM_SetNamedProperty(env, argv[0], "data", value);
159    // Return the properties modified after the freezing to JS.
160    return argv[0];
161}
162// Register the ObjectFreeze callback.
163static JSVM_CallbackStruct param[] = {
164    {.data = nullptr, .callback = ObjectFreeze},
165};
166static JSVM_CallbackStruct *method = param;
167// Set a property descriptor named objectFreeze and associate it with a callback. This allows the ObjectFreeze callback to be called from JS.
168static JSVM_PropertyDescriptor descriptor[] = {
169    {"objectFreeze", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
170};
171// Call the C++ code from JS.
172const char* srcCallNative = R"JS(let obj = { data: 55, message: "hello world"};
173  objectFreeze(obj))JS";
174```
175
176**Expected output**
177```ts
178Test JSVM OH_JSVM_ObjectFreeze success
179```
180
181### OH_JSVM_ObjectSeal
182
183Seals a JS object. Once a JS object is sealed, new properties cannot be added to it and all existing properties are marked as unconfigurable.
184
185CPP code:
186
187```cpp
188// hello.cpp
189#include "napi/native_api.h"
190#include "ark_runtime/jsvm.h"
191#include <hilog/log.h>
192// Define OH_JSVM_ObjectSeal.
193static JSVM_Value ObjectSeal(JSVM_Env env, JSVM_CallbackInfo info)
194{
195    // Accept an object passed in from JS.
196    size_t argc = 1;
197    JSVM_Value argv[1] = {nullptr};
198    OH_JSVM_GetCbInfo(env, info, &argc, argv, nullptr, nullptr);
199    // Call OH_JSVM_ObjectSeal to seal the object passed in.
200    JSVM_Status status = OH_JSVM_ObjectSeal(env, argv[0]);
201    if (status == JSVM_OK) {
202        OH_LOG_INFO(LOG_APP, "Test JSVM OH_JSVM_ObjectSeal success");
203    }
204    // Check whether the properties of the sealed object can be modified, deleted, or added.
205    // Modify a property of the sealed object.
206    JSVM_Value changeValue = nullptr;
207    OH_JSVM_CreateInt32(env, 111111, &changeValue);
208    OH_JSVM_SetNamedProperty(env, argv[0], "data", changeValue);
209    // Delete a property from the sealed object.
210    JSVM_Value deleteProperty = nullptr;
211    OH_JSVM_CreateStringUtf8(env, "message", JSVM_AUTO_LENGTH, &deleteProperty);
212    bool result = false;
213    OH_JSVM_DeleteProperty(env, argv[0], deleteProperty, &result);
214    if (result) {
215        OH_LOG_INFO(LOG_APP, "Test JSVM OH_JSVM_ObjectSeal failed");
216    }
217    // Add a property to the sealed object.
218    JSVM_Value addValue = nullptr;
219    OH_JSVM_CreateStringUtf8(env, "addValue", JSVM_AUTO_LENGTH, &addValue);
220    OH_JSVM_SetNamedProperty(env, argv[0], "newProperty", addValue);
221    // Return the modified object to JS.
222    return argv[0];
223}
224// Register the ObjectSeal callback.
225static JSVM_CallbackStruct param[] = {
226    {.data = nullptr, .callback = ObjectSeal},
227};
228static JSVM_CallbackStruct *method = param;
229// Set a property descriptor named objectSeal and associate it with a callback. This allows the ObjectSeal callback to be called from JS.
230static JSVM_PropertyDescriptor descriptor[] = {
231    {"objectSeal", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
232};
233// Call the C++ code from JS.
234const char* srcCallNative = R"JS( let obj = { data: 55, message: "hello world"};
235  objectSeal(obj))JS";
236```
237
238**Expected output**
239```ts
240Test JSVM OH_JSVM_ObjectSeal success
241```
242
243### OH_JSVM_Typeof
244
245Returns the type of a JS object.
246
247CPP code:
248
249```cpp
250// hello.cpp
251#include "napi/native_api.h"
252#include "ark_runtime/jsvm.h"
253#include <hilog/log.h>
254// Define OH_JSVM_Typeof.
255static JSVM_Value GetTypeof(JSVM_Env env, JSVM_CallbackInfo info) {
256    size_t argc = 1;
257    JSVM_Value args[1] = {nullptr};
258    OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
259    JSVM_ValueType valueType;
260    OH_JSVM_Typeof(env, args[0], &valueType);
261    JSVM_Value type = nullptr;
262    switch (valueType) {
263    case JSVM_UNDEFINED:
264        OH_LOG_INFO(LOG_APP, "JSVM Input type is undefined");
265        OH_JSVM_CreateStringUtf8(env, "Input type is undefined", JSVM_AUTO_LENGTH, &type);
266        break;
267    case JSVM_NULL:
268        OH_LOG_INFO(LOG_APP, "JSVM Input type is null");
269        OH_JSVM_CreateStringUtf8(env, "Input type is null", JSVM_AUTO_LENGTH, &type);
270        break;
271    case JSVM_BOOLEAN:
272        OH_LOG_INFO(LOG_APP, "JSVM Input type is boolean");
273        OH_JSVM_CreateStringUtf8(env, "Input type is boolean", JSVM_AUTO_LENGTH, &type);
274        break;
275    case JSVM_NUMBER:
276        OH_LOG_INFO(LOG_APP, "JSVM Input type is number");
277        OH_JSVM_CreateStringUtf8(env, "Input type is number", JSVM_AUTO_LENGTH, &type);
278        break;
279    case JSVM_STRING:
280        OH_LOG_INFO(LOG_APP, "JSVM Input type is string");
281        OH_JSVM_CreateStringUtf8(env, "Input type is string", JSVM_AUTO_LENGTH, &type);
282        break;
283    case JSVM_SYMBOL:
284        OH_LOG_INFO(LOG_APP, "JSVM Input type is symbol");
285        OH_JSVM_CreateStringUtf8(env, "Input type is symbol", JSVM_AUTO_LENGTH, &type);
286        break;
287    case JSVM_OBJECT:
288        OH_LOG_INFO(LOG_APP, "JSVM Input type is object");
289        OH_JSVM_CreateStringUtf8(env, "Input type is object", JSVM_AUTO_LENGTH, &type);
290        break;
291    case JSVM_FUNCTION:
292        OH_LOG_INFO(LOG_APP, "JSVM Input type is function");
293        OH_JSVM_CreateStringUtf8(env, "Input type is function", JSVM_AUTO_LENGTH, &type);
294        break;
295    case JSVM_EXTERNAL:
296        OH_LOG_INFO(LOG_APP, "JSVM Input type is external");
297        OH_JSVM_CreateStringUtf8(env, "Input type is external", JSVM_AUTO_LENGTH, &type);
298        break;
299    case JSVM_BIGINT:
300        OH_LOG_INFO(LOG_APP, "JSVM Input type is bigint");
301        OH_JSVM_CreateStringUtf8(env, "Input type is bigint", JSVM_AUTO_LENGTH, &type);
302        break;
303    default:
304        OH_LOG_INFO(LOG_APP, "JSVM Input type does not match any");
305        OH_JSVM_CreateStringUtf8(env, " ", JSVM_AUTO_LENGTH, &type);
306        break;
307    }
308    return type;
309}
310// Register the GetTypeof callback.
311static JSVM_CallbackStruct param[] = {
312    {.data = nullptr, .callback = GetTypeof},
313};
314static JSVM_CallbackStruct *method = param;
315// Set a property descriptor named getTypeof and associate it with a callback. This allows the GetTypeof callback to be called from JS.
316static JSVM_PropertyDescriptor descriptor[] = {
317    {"getTypeof", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
318};
319// Call the C++ code from JS.
320const char* srcCallNative = R"JS(getTypeof(true);)JS";
321```
322
323**Expected output**
324```ts
325JSVM Input type is boolean
326```
327
328### OH_JSVM_Instanceof
329
330Checks whether an object is an instance of a constructor.
331
332CPP code:
333
334```cpp
335// hello.cpp
336#include "napi/native_api.h"
337#include "ark_runtime/jsvm.h"
338#include <hilog/log.h>
339// Define OH_JSVM_Instanceof.
340static JSVM_Value InstanceOf(JSVM_Env env, JSVM_CallbackInfo info)
341{
342    // Obtain the two parameters passed from JS.
343    size_t argc = 2;
344    JSVM_Value args[2] = {nullptr};
345    OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
346    bool result = false;
347    JSVM_Status status = OH_JSVM_Instanceof(env, args[0], args[1], &result);
348    if (status != JSVM_OK) {
349        OH_LOG_ERROR(LOG_APP, "JSVM InstanceOf fail");
350    } else {
351        OH_LOG_INFO(LOG_APP, "JSVM InstanceOf: %{public}d", result);
352    }
353    JSVM_Value returnValue = nullptr;
354    OH_JSVM_GetBoolean(env, result, &returnValue);
355    return returnValue;
356}
357// Register the InstanceOf callback.
358static JSVM_CallbackStruct param[] = {
359    {.data = nullptr, .callback = InstanceOf},
360};
361static JSVM_CallbackStruct *method = param;
362// Set a property descriptor named instanceOf and associate it with a callback. This allows the InstanceOf callback to be called from JS.
363static JSVM_PropertyDescriptor descriptor[] = {
364    {"instanceOf", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
365};
366// Call the C++ code from JS.
367const char* srcCallNative = R"JS(class Person {
368        name;
369        age;
370        constructor(name, age) {
371          this.name = name;
372          this.age = age;
373        }
374      }
375     instanceOf(new Person('Alice', 30), Person);
376     ;)JS";
377```
378
379**Expected output**
380```ts
381JSVM InstanceOf: 1
382```
383
384### OH_JSVM_TypeTagObject
385
386Associate the value of the **type_tag** pointer with a JS object so that the object can be identified more accurately.
387
388### OH_JSVM_CheckObjectTypeTag
389
390Checks whether a tag matches the tag type of an object.
391
392CPP code:
393
394```cpp
395// hello.cpp
396#include "napi/native_api.h"
397#include "ark_runtime/jsvm.h"
398#include <hilog/log.h>
399#define NUMBERINT_FOUR 4
400// Define a static constant JSVM_TypeTag array to store type tags.
401static const JSVM_TypeTag TagsData[NUMBERINT_FOUR] = {
402    {0x9e4b2449547061b3, 0x33999f8a6516c499},
403    {0x1d55a794c53a726d, 0x43633f509f9c944e},
404    {0, 0}, // Indicates the default tag or no tag.
405    {0x6a971439f5b2e5d7, 0x531dc28a7e5317c0},
406};
407// Define OH_JSVM_TypeTagObject.
408static JSVM_Value SetTypeTagToObject(JSVM_Env env, JSVM_CallbackInfo info)
409{
410    // Obtain the two parameters passed from JS.
411    size_t argc = 2;
412    JSVM_Value args[2] = {nullptr};
413    OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
414    // Obtain the index number and convert it to JSVM_Value.
415    int32_t index = 0;
416    OH_JSVM_GetValueInt32(env, args[1], &index);
417    // Set the type tag for the parameter (object).
418    JSVM_Status status = OH_JSVM_TypeTagObject(env, args[0], &TagsData[index]);
419    // Convert the bool value to JSVM_Value and return it.
420    JSVM_Value result = nullptr;
421    if (status != JSVM_OK) {
422        OH_LOG_ERROR(LOG_APP, "JSVM SetTypeTagToObject fail");
423        OH_JSVM_GetBoolean(env, false, &result);
424    } else {
425        OH_LOG_INFO(LOG_APP, "JSVM SetTypeTagToObject success");
426        OH_JSVM_GetBoolean(env, true, &result);
427    }
428    return result;
429}
430// Define OH_JSVM_CheckObjectTypeTag.
431static JSVM_Value CheckObjectTypeTag(JSVM_Env env, JSVM_CallbackInfo info)
432{
433    // Obtain the two parameters passed from JS.
434    size_t argc = 2;
435    JSVM_Value args[2] = {nullptr};
436    OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
437    // Obtain the index number and convert it to JSVM_Value.
438    int32_t index = 0;
439    OH_JSVM_GetValueInt32(env, args[1], &index);
440    // Check the type tag of the object.
441    bool checkResult = false;
442    JSVM_Status status = OH_JSVM_CheckObjectTypeTag(env, args[0], &TagsData[index], &checkResult);
443    if (status != JSVM_OK) {
444        OH_LOG_ERROR(LOG_APP, "JSVM SetTypeTagToObject fail");
445    } else {
446        OH_LOG_INFO(LOG_APP, "JSVM SetTypeTagToObject:%{public}d", checkResult);
447    }
448    // Convert the bool value to JSVM_Value and return it.
449    JSVM_Value checked = nullptr;
450    OH_JSVM_GetBoolean(env, checkResult, &checked);
451    return checked;
452}
453// Registers the SetTypeTagToObject and CheckObjectTypeTag callbacks.
454static JSVM_CallbackStruct param[] = {
455    {.data = nullptr, .callback = SetTypeTagToObject},
456    {.data = nullptr, .callback = CheckObjectTypeTag},
457};
458static JSVM_CallbackStruct *method = param;
459// Set property descriptors named setTypeTagToObject and CheckObjectTypeTag, and associate them with a callback each. This allows the SetTypeTagToObject and CheckObjectTypeTag callbacks to be called from JS.
460static JSVM_PropertyDescriptor descriptor[] = {
461    {"setTypeTagToObject", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
462    {"checkObjectTypeTag", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
463};
464// Call the C++ code from JS.
465const char* srcCallNative = R"JS(
466         class Obj {
467           data;
468           message;
469         }
470         let obj= { data: 0, message: "hello world"};
471         setTypeTagToObject(obj, 0);
472         checkObjectTypeTag(obj,0);)JS";
473```
474
475**Expected output**
476```ts
477JSVM SetTypeTagToObject success
478JSVM SetTypeTagToObject:1
479```
480
481### OH_JSVM_CreateExternal
482
483Use **OH_JSVM_CreateExternal** to create a JS object that wraps an external pointer.
484**NOTE**<br>When a JS object is garbage-collected, the content pointed to by the wrapped external pointer is not directly managed by GC. Only the function corresponding to the third input parameter (if it is not nullptr) is called.
485
486CPP code:
487
488```cpp
489// hello.cpp
490#include "napi/native_api.h"
491#include "ark_runtime/jsvm.h"
492#include <hilog/log.h>
493// Define OH_JSVM_CreateExternal.
494static JSVM_Value CreateExternal(JSVM_Env env, JSVM_CallbackInfo info)
495{
496    size_t dataSize = 10;
497    void *data = malloc(dataSize);
498    if (data == nullptr) {
499        OH_LOG_ERROR(LOG_APP, "JSVM Failed to malloc.");
500        return nullptr;
501    }
502    memset(data, 0, dataSize);
503    const char* testStr = "test";
504    JSVM_Value external = nullptr;
505    JSVM_Status status = OH_JSVM_CreateExternal(
506        env, data, [](JSVM_Env env, void *data, void *hint) {free(data);}, (void *)testStr, &external);
507    if (status != JSVM_OK) {
508        OH_LOG_ERROR(LOG_APP, "JSVM Failed to create external data, status:%{public}d.", status);
509        free(data);
510        data = nullptr;
511        return nullptr;
512    } else {
513        OH_LOG_INFO(LOG_APP, "JSVM CreateExternal success");
514    }
515    return external;
516}
517// Register the CreateExternal callback.
518static JSVM_CallbackStruct param[] = {
519    {.data = nullptr, .callback = CreateExternal},
520};
521static JSVM_CallbackStruct *method = param;
522// Set a property descriptor named createExternal and associate it with a callback. This allows the CreateExternal callback to be called from JS.
523static JSVM_PropertyDescriptor descriptor[] = {
524    {"createExternal", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
525};
526// Call the C++ code from JS.
527const char* srcCallNative = R"JS(createExternal())JS";
528```
529
530**Expected output**
531```ts
532JSVM CreateExternal success
533```
534
535### OH_JSVM_GetValueExternal
536
537Use **OH_JSVM_CreateExternal** to create a JS object that wraps a custom C/C++ object, and use **OH_JSVM_GetValueExternal** to obtain the pointer to the external object wrapped by **OH_JSVM_CreateExternal**.
538
539CPP code:
540
541```cpp
542// hello.cpp
543#include "napi/native_api.h"
544#include "ark_runtime/jsvm.h"
545#include <hilog/log.h>
546// Define OH_JSVM_GetValueExternal.
547static JSVM_Value GetValueExternal(JSVM_Env env, JSVM_CallbackInfo info)
548{
549    static int data = 0x12345;
550    JSVM_Value externalValue = nullptr;
551    JSVM_Status status = OH_JSVM_CreateExternal(env, (void*)&data, nullptr, nullptr, &externalValue);
552    if (status != JSVM_OK) {
553        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CreateExternal fail");
554    } else {
555        OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_CreateExternal sucess");
556    }
557    void *data_value;
558    status = OH_JSVM_GetValueExternal(env, externalValue, &data_value);
559    if (status != JSVM_OK) {
560        OH_LOG_ERROR(LOG_APP, "JSVM GetValueExternal fail");
561    } else {
562        OH_LOG_INFO(LOG_APP, "JSVM GetValueExternal sucess");
563    }
564    // Convert the sign bit into a value of int type and pass it.
565    JSVM_Value returnValue = nullptr;
566    int retData = *static_cast<int *>(data_value);
567    OH_JSVM_CreateInt32(env, retData, &returnValue);
568    return returnValue;
569}
570// Register the GetValueExternal callback.
571static JSVM_CallbackStruct param[] = {
572    {.data = nullptr, .callback = GetValueExternal},
573};
574static JSVM_CallbackStruct *method = param;
575// Set a property descriptor named getValueExternal and associate it with a callback. This allows the GetValueExternal callback to be called from JS.
576static JSVM_PropertyDescriptor descriptor[] = {
577    {"getValueExternal", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
578};
579// Call the C++ code from JS.
580const char* srcCallNative = R"JS(getValueExternal())JS";
581```
582
583**Expected output**
584```ts
585JSVM OH_JSVM_CreateExternal sucess
586JSVM GetValueExternal sucess
587```
588
589### OH_JSVM_CreateSymbol
590
591Create a symbol. Symbol is a special data type used to indicate a unique identifier. Unlike strings or numbers, the value of a symbol is unique. Even if two symbols have the same description, they are not equal. Symbols are often used as keys for object properties to ensure property uniqueness.
592
593CPP code:
594
595```cpp
596// hello.cpp
597#include "napi/native_api.h"
598#include "ark_runtime/jsvm.h"
599#include <hilog/log.h>
600// Define OH_JSVM_CreateSymbol.
601static JSVM_Value CreateSymbol(JSVM_Env env, JSVM_CallbackInfo info)
602{
603    JSVM_Value result = nullptr;
604    const char *des = "only";
605    OH_JSVM_CreateStringUtf8(env, des, JSVM_AUTO_LENGTH, &result);
606    JSVM_Value returnSymbol = nullptr;
607    OH_JSVM_CreateSymbol(env, result, &returnSymbol);
608    JSVM_ValueType valuetypeSymbol;
609    OH_JSVM_Typeof(env, returnSymbol, &valuetypeSymbol);
610    if (valuetypeSymbol == JSVM_SYMBOL) {
611        OH_LOG_INFO(LOG_APP, "JSVM CreateSymbol Success");
612    } else {
613        OH_LOG_INFO(LOG_APP, "JSVM CreateSymbol fail");
614    }
615    return returnSymbol;
616}
617// Register the CreateSymbol callback.
618static JSVM_CallbackStruct param[] = {
619    {.data = nullptr, .callback = CreateSymbol},
620};
621static JSVM_CallbackStruct *method = param;
622// Set a property descriptor named createSymbol and associate it with a callback. This allows the CreateSymbol callback to be called from JS.
623static JSVM_PropertyDescriptor descriptor[] = {
624    {"createSymbol", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
625};
626// Call the C++ code from JS.
627const char* srcCallNative = R"JS(createSymbol())JS";
628```
629
630**Expected output**
631```ts
632JSVM CreateSymbol Success
633```
634
635### OH_JSVM_SymbolFor
636
637Searches 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.
638
639CPP code:
640
641```cpp
642// hello.cpp
643#include "napi/native_api.h"
644#include "ark_runtime/jsvm.h"
645#include <hilog/log.h>
646// Define a constant to store the maximum length of a string.
647static const int MAX_BUFFER_SIZE = 128;
648// Define OH_JSVM_SymbolFor.
649static JSVM_Value SymbolFor(JSVM_Env env, JSVM_CallbackInfo info)
650{
651    JSVM_Value description = nullptr;
652    OH_JSVM_CreateStringUtf8(env, "test_demo", 9, &description);
653    char buffer[MAX_BUFFER_SIZE];
654    size_t bufferSize = MAX_BUFFER_SIZE;
655    size_t copied = 0;
656    OH_JSVM_GetValueStringUtf8(env, description, buffer, bufferSize, &copied);
657    JSVM_Value symbol = nullptr;
658    OH_JSVM_CreateSymbol(env, description, &symbol);
659    JSVM_Value result_symbol = nullptr;
660    JSVM_Status status = OH_JSVM_SymbolFor(env, buffer, copied, &result_symbol);
661    JSVM_ValueType valuetypeSymbol;
662    OH_JSVM_Typeof(env, result_symbol, &valuetypeSymbol);
663    if (valuetypeSymbol == JSVM_SYMBOL && status == JSVM_OK) {
664        OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_SymbolFor success");
665    }
666    // Return the result.
667    return result_symbol;
668}
669// Register the SymbolFor callback.
670static JSVM_CallbackStruct param[] = {
671    {.data = nullptr, .callback = SymbolFor},
672};
673static JSVM_CallbackStruct *method = param;
674// Set a property descriptor named symbolFor and associate it with a callback. This allows the SymbolFor callback to be called from JS.
675static JSVM_PropertyDescriptor descriptor[] = {
676    {"symbolFor", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
677};
678// Call the C++ code from JS.
679const char* srcCallNative = R"JS(symbolFor())JS";
680```
681
682**Expected output**
683```ts
684JSVM OH_JSVM_SymbolFor success
685```
686