1e41f4b71Sopenharmony_ci# Performing Lifecycle Management Using JSVM-API
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Introduction
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ciIn JSVM-API, **JSVM_Value** is an abstract data type that represents a JavaScript (JS) value of any type, which includes the basic type (such as number, string, or Boolean) and the composite type (such as array, function, or object).
6e41f4b71Sopenharmony_ciThe **JSVM_Value** lifecycle is closely related to the lifecycle of the JS value. When a JS value is garbage-collected, the **JSVM_Value** associated with it is no longer valid. Avoid using the **JSVM_Value** when the JS value no longer exists.
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ciScope is used to manage the **JSVM_Value** lifecycle in the framework layer. You can use **OH_JSVM_OpenHandleScope** to create a scope and use **OH_JSVM_CloseHandleScope** to destroy a scope. By creating a **JSVM_Value** in a scope, you can ensure that the **JSVM_Value** is automatically released when the scope ends. This helps prevent memory leaks.
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ci**JSVM_Ref** is a JSVM-API data type used to manage the **JSVM_Value** lifecycle. It allows reference to a **JSVM_Value** during its lifecycle, even if the value is beyond its original context. The reference allows a **JSVM_Value** to be shared in different contexts and released in a timely manner.
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ciProperly using **OH_JSVM_OpenHandleScope** and **OH_JSVM_CloseHandleScope** can minimize the **JSVM_Value** lifecycle and prevent memory leaks.
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ciEach **JSVM_Value** belongs to a specific **HandleScope** instance, which is created by **OH_JSVM_OpenHandleScope** and closed by **OH_JSVM_CloseHandleScope**. After a **HandleScope** instance is closed, the corresponding **JSVM_Value** will be automatically released.
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci## Basic Concepts
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ciJSVM-API provides APIs for creating and manipulating JS objects, managing references to and lifecycle of the JS objects, and registering garbage collection (GC) callbacks in C/C++. Before you get started, you need to understand the following concepts:
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci- Scope: used to ensure that the objects created within a certain scope remain active and are properly cleared when no longer required. JSVM-API provides APIs for creating and closing normal and escapeable scopes.
21e41f4b71Sopenharmony_ci- Reference management: JSVM-API provides APIs for creating, deleting, and managing object references to extend the object lifecycle and prevent memory leaks when objects are used.
22e41f4b71Sopenharmony_ci- Escapeable scope: used to return the values created within the **escapable_handle_scope** to a parent scope. It is created by **OH_JSVM_OpenEscapableHandleScope** and closed by **OH_JSVM_CloseEscapableHandleScope**.
23e41f4b71Sopenharmony_ci- GC callback: You can register GC callbacks to perform specific cleanup operations when JS objects are garbage-collected.
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ciUnderstanding these concepts helps you securely and effectively manipulate JS objects in C/C++ and perform object lifecycle management.
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ci## Available APIs
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci| API                      | Description                      |
30e41f4b71Sopenharmony_ci|----------------------------|--------------------------------|
31e41f4b71Sopenharmony_ci| OH_JSVM_OpenHandleScope     | Opens a handle scope. **JSVM_Value** within the scope will not be garbage-collected.|
32e41f4b71Sopenharmony_ci| OH_JSVM_CloseHandleScope    | Closes a handle scope.|
33e41f4b71Sopenharmony_ci| 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.|
34e41f4b71Sopenharmony_ci| OH_JSVM_CloseEscapableHandleScope    | Closes an escapable handle scope.|
35e41f4b71Sopenharmony_ci| OH_JSVM_EscapeHandle         | Promotes a handle to a JS object so that it is valid for the lifetime of the outer scope.|
36e41f4b71Sopenharmony_ci| OH_JSVM_CreateReference      | Creates a reference with the specified reference count to the value passed in. The reference allows objects to be used and shared in different contexts and helps effective track of the object lifecycle.|
37e41f4b71Sopenharmony_ci| OH_JSVM_DeleteReference      | Releases 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.|
38e41f4b71Sopenharmony_ci| OH_JSVM_ReferenceRef         | Increments the reference count of the reference created by **OH_JSVM_CreateReference** so that the object referenced will not be released.|
39e41f4b71Sopenharmony_ci| 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.|
40e41f4b71Sopenharmony_ci| OH_JSVM_GetReferenceValue   | Obtains the object referenced by **OH_JSVM_CreateReference**. |
41e41f4b71Sopenharmony_ci| OH_JSVM_AddFinalizer          | Adds 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.|
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci## Example
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ciIf you are just starting out with JSVM-API, see [JSVM-API Development Process](use-jsvm-process.md). The following demonstrates only the C++ and ArkTS code related to lifecycle management APIs.
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ci### OH_JSVM_OpenHandleScope, OH_JSVM_CloseHandleScope
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ciUse **OH_JSVM_OpenHandleScope** to open a handle scope. Use **OH_JSVM_CloseHandleScope** to close a handle scope. Properly managing JS handle scopes can prevent GC problems.
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ciCPP code:
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ci```cpp
54e41f4b71Sopenharmony_ci// hello.cpp
55e41f4b71Sopenharmony_ci#include "napi/native_api.h"
56e41f4b71Sopenharmony_ci#include "ark_runtime/jsvm.h"
57e41f4b71Sopenharmony_ci#include <hilog/log.h>
58e41f4b71Sopenharmony_ci// Register the HandleScopeTest, HandleScope, and HandleScopeFor callbacks.
59e41f4b71Sopenharmony_cistatic JSVM_CallbackStruct param[] = {
60e41f4b71Sopenharmony_ci    {.data = nullptr, .callback = HandleScopeTest},
61e41f4b71Sopenharmony_ci    {.data = nullptr, .callback = HandleScope},
62e41f4b71Sopenharmony_ci    {.data = nullptr, .callback = HandleScopeFor},
63e41f4b71Sopenharmony_ci};
64e41f4b71Sopenharmony_cistatic JSVM_CallbackStruct *method = param;
65e41f4b71Sopenharmony_ci// Expose the HandleScopeTest, HandleScope, and HandleScopeFor callbacks to JS.
66e41f4b71Sopenharmony_cistatic JSVM_PropertyDescriptor descriptor[] = {
67e41f4b71Sopenharmony_ci    {"handleScopeTest", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
68e41f4b71Sopenharmony_ci    {"handleScope", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
69e41f4b71Sopenharmony_ci    {"handleScopeFor", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
70e41f4b71Sopenharmony_ci};
71e41f4b71Sopenharmony_cistatic int DIFF_VALUE_HUNDRED_THOUSAND = 100000;
72e41f4b71Sopenharmony_ci// Define OH_JSVM_OpenHandleScope and OH_JSVM_CloseHandleScope.
73e41f4b71Sopenharmony_cistatic JSVM_Value HandleScopeFor(JSVM_Env env, JSVM_CallbackInfo info)
74e41f4b71Sopenharmony_ci{
75e41f4b71Sopenharmony_ci    // When JSVM-API is frequently called to create JS objects in the for loop, use handle_scope to release resources in a timely manner when they are no longer required.
76e41f4b71Sopenharmony_ci    // In the following example, the lifecycle of the local variable res ends at the end of each loop. To prevent memory leaks, scope is used to release the JS object in a timely manner.
77e41f4b71Sopenharmony_ci    JSVM_Value checked = nullptr;
78e41f4b71Sopenharmony_ci    for (int i = 0; i < DIFF_VALUE_HUNDRED_THOUSAND; i++) {
79e41f4b71Sopenharmony_ci        JSVM_HandleScope scope = nullptr;
80e41f4b71Sopenharmony_ci        JSVM_Status status = OH_JSVM_OpenHandleScope(env, &scope);
81e41f4b71Sopenharmony_ci        if (status != JSVM_OK || scope == nullptr) {
82e41f4b71Sopenharmony_ci            OH_JSVM_GetBoolean(env, false, &checked);
83e41f4b71Sopenharmony_ci            OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_OpenHandleScope: failed");
84e41f4b71Sopenharmony_ci            return checked;
85e41f4b71Sopenharmony_ci        }
86e41f4b71Sopenharmony_ci        JSVM_Value res = nullptr;
87e41f4b71Sopenharmony_ci        OH_JSVM_CreateObject(env, &res);
88e41f4b71Sopenharmony_ci        status = OH_JSVM_CloseHandleScope(env, scope);
89e41f4b71Sopenharmony_ci        if (status != JSVM_OK) {
90e41f4b71Sopenharmony_ci            OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CloseHandleScope: failed");
91e41f4b71Sopenharmony_ci        }
92e41f4b71Sopenharmony_ci    }
93e41f4b71Sopenharmony_ci    OH_JSVM_GetBoolean(env, true, &checked);
94e41f4b71Sopenharmony_ci    OH_LOG_INFO(LOG_APP, "JSVM HandleScopeFor: success");
95e41f4b71Sopenharmony_ci    return checked;
96e41f4b71Sopenharmony_ci}
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_cistatic JSVM_Value HandleScopeTest(JSVM_Env env, JSVM_CallbackInfo info)
99e41f4b71Sopenharmony_ci{
100e41f4b71Sopenharmony_ci    // NOTE
101e41f4b71Sopenharmony_ci    // In the following code, obj is created within the handle scope, which is later closed by OH_JSVM_OpenHandleScope.
102e41f4b71Sopenharmony_ci    // After the handle scope is closed, results can still be returned normally
103e41f4b71Sopenharmony_ci    // because the results are returned as the return values of functions,
104e41f4b71Sopenharmony_ci    // instead of using obj outside the handle scope.
105e41f4b71Sopenharmony_ci    // Call OH_JSVM_OpenHandleScope to create a handle scope.
106e41f4b71Sopenharmony_ci    JSVM_HandleScope scope = nullptr;
107e41f4b71Sopenharmony_ci    JSVM_Status status = OH_JSVM_OpenHandleScope(env, &scope);
108e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
109e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_OpenHandleScope: failed");
110e41f4b71Sopenharmony_ci        return nullptr;
111e41f4b71Sopenharmony_ci    }
112e41f4b71Sopenharmony_ci    // Create an object within the handle scope.
113e41f4b71Sopenharmony_ci    JSVM_Value obj = nullptr;
114e41f4b71Sopenharmony_ci    OH_JSVM_CreateObject(env, &obj);
115e41f4b71Sopenharmony_ci    // Add properties to the object.
116e41f4b71Sopenharmony_ci    JSVM_Value value = nullptr;
117e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "test handleScope", JSVM_AUTO_LENGTH, &value);
118e41f4b71Sopenharmony_ci    OH_JSVM_SetNamedProperty(env, obj, "name", value);
119e41f4b71Sopenharmony_ci    // Close the handle scope. Then, the object handles created within the scope are automatically released.
120e41f4b71Sopenharmony_ci    status = OH_JSVM_CloseHandleScope(env, scope);
121e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
122e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CloseHandleScope: failed");
123e41f4b71Sopenharmony_ci        return nullptr;
124e41f4b71Sopenharmony_ci    }
125e41f4b71Sopenharmony_ci    OH_LOG_INFO(LOG_APP, "JSVM HandleScopeTest: success");
126e41f4b71Sopenharmony_ci    return obj;
127e41f4b71Sopenharmony_ci}
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_cistatic JSVM_Value HandleScope(JSVM_Env env, JSVM_CallbackInfo info)
130e41f4b71Sopenharmony_ci{
131e41f4b71Sopenharmony_ci    // Call OH_JSVM_OpenHandleScope to create a handle scope.
132e41f4b71Sopenharmony_ci    JSVM_HandleScope scope = nullptr;
133e41f4b71Sopenharmony_ci    JSVM_Status status = OH_JSVM_OpenHandleScope(env, &scope);
134e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
135e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_OpenHandleScope: failed");
136e41f4b71Sopenharmony_ci        return nullptr;
137e41f4b71Sopenharmony_ci    }
138e41f4b71Sopenharmony_ci    // Create an object within the handle scope.
139e41f4b71Sopenharmony_ci    JSVM_Value obj = nullptr;
140e41f4b71Sopenharmony_ci    OH_JSVM_CreateObject(env, &obj);
141e41f4b71Sopenharmony_ci    // Add properties to the object.
142e41f4b71Sopenharmony_ci    JSVM_Value value = nullptr;
143e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "handleScope", JSVM_AUTO_LENGTH, &value);
144e41f4b71Sopenharmony_ci    OH_JSVM_SetNamedProperty(env, obj, "name", value);
145e41f4b71Sopenharmony_ci    // Close the handle scope. Then, the object handles created within the scope are automatically released.
146e41f4b71Sopenharmony_ci    status = OH_JSVM_CloseHandleScope(env, scope);
147e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
148e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CloseHandleScope: failed");
149e41f4b71Sopenharmony_ci        return nullptr;
150e41f4b71Sopenharmony_ci    }
151e41f4b71Sopenharmony_ci    // After the handle scope is closed, add properties to the object. The previously set property 'name' becomes invalid.
152e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "001", JSVM_AUTO_LENGTH, &value);
153e41f4b71Sopenharmony_ci    OH_JSVM_SetNamedProperty(env, obj, "id", value);
154e41f4b71Sopenharmony_ci    // The property 'name' is invalid.
155e41f4b71Sopenharmony_ci    bool result = true;
156e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "name", JSVM_AUTO_LENGTH, &value);
157e41f4b71Sopenharmony_ci    OH_JSVM_HasProperty(env, obj, value, &result);
158e41f4b71Sopenharmony_ci    if (!result) {
159e41f4b71Sopenharmony_ci        OH_LOG_INFO(LOG_APP, "JSVM HandleScope: success");
160e41f4b71Sopenharmony_ci    }
161e41f4b71Sopenharmony_ci    return obj;
162e41f4b71Sopenharmony_ci}
163e41f4b71Sopenharmony_ci```
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ciArkTS code:
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ci```ts
168e41f4b71Sopenharmony_ciimport hilog from "@ohos.hilog"
169e41f4b71Sopenharmony_ci// Import the native APIs.
170e41f4b71Sopenharmony_ciimport napitest from "libentry.so"
171e41f4b71Sopenharmony_citry {
172e41f4b71Sopenharmony_ci  let script: string = `handleScopeTest()`;
173e41f4b71Sopenharmony_ci  let result = napitest.runJsVm(script);
174e41f4b71Sopenharmony_ci  hilog.info(0x0000, 'testJSVM', 'Test JSVM handleScopeTest: %{public}s', result);
175e41f4b71Sopenharmony_ci} catch (error) {
176e41f4b71Sopenharmony_ci  hilog.error(0x0000, 'testJSVM', 'Test JSVM handleScopeTest error: %{public}s', error.message);
177e41f4b71Sopenharmony_ci}
178e41f4b71Sopenharmony_citry {
179e41f4b71Sopenharmony_ci  let script: string = `handleScope()`;
180e41f4b71Sopenharmony_ci  let result = napitest.runJsVm(script);
181e41f4b71Sopenharmony_ci  hilog.info(0x0000, 'testJSVM', 'Test JSVM handleScope: %{public}s', result);
182e41f4b71Sopenharmony_ci} catch (error) {
183e41f4b71Sopenharmony_ci  hilog.error(0x0000, 'testJSVM', 'Test JSVM handleScope error: %{public}s', error.message);
184e41f4b71Sopenharmony_ci}
185e41f4b71Sopenharmony_citry {
186e41f4b71Sopenharmony_ci  let script: string = `handleScopeFor()`;
187e41f4b71Sopenharmony_ci  let result = napitest.runJsVm(script);
188e41f4b71Sopenharmony_ci  hilog.info(0x0000, 'testJSVM', 'Test JSVM handleScopeFor: %{public}s', result);
189e41f4b71Sopenharmony_ci} catch (error) {
190e41f4b71Sopenharmony_ci  hilog.error(0x0000, 'testJSVM', 'Test JSVM handleScopeFor error: %{public}s', error.message);
191e41f4b71Sopenharmony_ci}
192e41f4b71Sopenharmony_ci```
193e41f4b71Sopenharmony_ci
194e41f4b71Sopenharmony_ci### OH_JSVM_OpenEscapableHandleScope, OH_JSVM_CloseEscapableHandleScope, OH_JSVM_EscapeHandle
195e41f4b71Sopenharmony_ci
196e41f4b71Sopenharmony_ciUse **OH_JSVM_OpenEscapableHandleScope** to create an escapeable handle scope, which allows the declared values in the scope to be returned to the parent scope. Use **OH_JSVM_CloseEscapableHandleScope** to close an escapeable handle scope. Use **OH_JSVM_EscapeHandle** to promote the lifecycle of a JS object so that it is valid for the lifetime of the outer scope.
197e41f4b71Sopenharmony_ciThese APIs are helpful for managing ArkTS objects more flexibly in C/C++, especially when passing cross-scope values.
198e41f4b71Sopenharmony_ci
199e41f4b71Sopenharmony_ciCPP code:
200e41f4b71Sopenharmony_ci
201e41f4b71Sopenharmony_ci```cpp
202e41f4b71Sopenharmony_ci// hello.cpp
203e41f4b71Sopenharmony_ci#include "napi/native_api.h"
204e41f4b71Sopenharmony_ci#include "ark_runtime/jsvm.h"
205e41f4b71Sopenharmony_ci#include <hilog/log.h>
206e41f4b71Sopenharmony_ci// Define the EscapableHandleScopeTest callback.
207e41f4b71Sopenharmony_cistatic JSVM_CallbackStruct param[] = {
208e41f4b71Sopenharmony_ci    {.data = nullptr, .callback = EscapableHandleScopeTest},
209e41f4b71Sopenharmony_ci};
210e41f4b71Sopenharmony_cistatic JSVM_CallbackStruct *method = param;
211e41f4b71Sopenharmony_ci// Set a property descriptor named escapableHandleScopeTest and associate it with a callback. This allows the EscapableHandleScopeTest callback to be called from JS.
212e41f4b71Sopenharmony_cistatic JSVM_PropertyDescriptor descriptor[] = {
213e41f4b71Sopenharmony_ci    {"escapableHandleScopeTest", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
214e41f4b71Sopenharmony_ci};
215e41f4b71Sopenharmony_ci// Define OH_JSVM_OpenEscapableHandleScope, OH_JSVM_CloseEscapableHandleScope, and OH_JSVM_EscapeHandle.
216e41f4b71Sopenharmony_cistatic JSVM_Value EscapableHandleScopeTest(JSVM_Env env, JSVM_CallbackInfo info)
217e41f4b71Sopenharmony_ci{
218e41f4b71Sopenharmony_ci    // Create an escapeable handle scope.
219e41f4b71Sopenharmony_ci    JSVM_EscapableHandleScope scope = nullptr;
220e41f4b71Sopenharmony_ci    JSVM_Status status = OH_JSVM_OpenEscapableHandleScope(env, &scope);
221e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
222e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_OpenEscapableHandleScope: failed");
223e41f4b71Sopenharmony_ci        return nullptr;
224e41f4b71Sopenharmony_ci    }
225e41f4b71Sopenharmony_ci    // Create an object within the scope of the escapeable handle.
226e41f4b71Sopenharmony_ci    JSVM_Value obj;
227e41f4b71Sopenharmony_ci    OH_JSVM_CreateObject(env, &obj);
228e41f4b71Sopenharmony_ci    // Add properties to the object.
229e41f4b71Sopenharmony_ci    JSVM_Value value = nullptr;
230e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "Test jsvm_escapable_handle_scope", JSVM_AUTO_LENGTH, &value);
231e41f4b71Sopenharmony_ci    OH_JSVM_SetNamedProperty(env, obj, "name", value);
232e41f4b71Sopenharmony_ci    // Call OH_JSVM_EscapeHandle to promote the JS object handle to make it valid with the lifetime of the outer scope.
233e41f4b71Sopenharmony_ci    JSVM_Value escapedObj = nullptr;
234e41f4b71Sopenharmony_ci    OH_JSVM_EscapeHandle(env, scope, obj, &escapedObj);
235e41f4b71Sopenharmony_ci    // Close the escapeable handle scope to clear resources.
236e41f4b71Sopenharmony_ci    status = OH_JSVM_CloseEscapableHandleScope(env, scope);
237e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
238e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CloseEscapableHandleScope: failed");
239e41f4b71Sopenharmony_ci        return nullptr;
240e41f4b71Sopenharmony_ci    }
241e41f4b71Sopenharmony_ci    // Use escapedObj outside the scope. Since escapedObj has escaped, the property can be set successfully and obtained from ArkTs.
242e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "001", JSVM_AUTO_LENGTH, &value);
243e41f4b71Sopenharmony_ci    OH_JSVM_SetNamedProperty(env, obj, "id", value);
244e41f4b71Sopenharmony_ci    bool result = false;
245e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "id", JSVM_AUTO_LENGTH, &value);
246e41f4b71Sopenharmony_ci    OH_JSVM_HasProperty(env, obj, value, &result);
247e41f4b71Sopenharmony_ci    if (result) {
248e41f4b71Sopenharmony_ci        OH_LOG_INFO(LOG_APP, "JSVM EscapableHandleScopeTest: success");
249e41f4b71Sopenharmony_ci    }
250e41f4b71Sopenharmony_ci    return escapedObj;
251e41f4b71Sopenharmony_ci}
252e41f4b71Sopenharmony_ci```
253e41f4b71Sopenharmony_ci
254e41f4b71Sopenharmony_ci 
255e41f4b71Sopenharmony_ci
256e41f4b71Sopenharmony_ciArkTS code:
257e41f4b71Sopenharmony_ci
258e41f4b71Sopenharmony_ci```ts
259e41f4b71Sopenharmony_ciimport hilog from "@ohos.hilog"
260e41f4b71Sopenharmony_ci// Import the native APIs.
261e41f4b71Sopenharmony_ciimport napitest from "libentry.so"
262e41f4b71Sopenharmony_citry {
263e41f4b71Sopenharmony_ci  let script: string = `escapableHandleScopeTest()`;
264e41f4b71Sopenharmony_ci  let result = napitest.runJsVm(script);
265e41f4b71Sopenharmony_ci  hilog.info(0x0000, 'testJSVM', 'Test JSVM escapableHandleScopeTest: %{public}s', result);
266e41f4b71Sopenharmony_ci} catch (error) {
267e41f4b71Sopenharmony_ci  hilog.error(0x0000, 'testJSVM', 'Test JSVM escapableHandleScopeTest error: %{public}s', error.message);
268e41f4b71Sopenharmony_ci}
269e41f4b71Sopenharmony_ci```
270e41f4b71Sopenharmony_ci
271e41f4b71Sopenharmony_ci### OH_JSVM_CreateReference, OH_JSVM_DeleteReference
272e41f4b71Sopenharmony_ci
273e41f4b71Sopenharmony_ciUse **OH_JSVM_CreateReference** to create a reference for an object to extend its lifespan. The caller needs to manage the reference lifespan. Use **OH_JSVM_DeleteReference** to delete a reference.
274e41f4b71Sopenharmony_ci
275e41f4b71Sopenharmony_ci### OH_JSVM_ReferenceRef, OH_JSVM_ReferenceUnref
276e41f4b71Sopenharmony_ci
277e41f4b71Sopenharmony_ciUse **OH_JSVM_ReferenceRef** to increment the reference count of a reference and use **OH_JSVM_ReferenceUnref** to decrement the reference count of a reference, and return the new count value.
278e41f4b71Sopenharmony_ci
279e41f4b71Sopenharmony_ci### OH_JSVM_GetReferenceValue
280e41f4b71Sopenharmony_ci
281e41f4b71Sopenharmony_ciUse **OH_JSVM_GetReferenceValue** to obtain the JS object associated with the reference.
282e41f4b71Sopenharmony_ci
283e41f4b71Sopenharmony_ci### OH_JSVM_AddFinalizer
284e41f4b71Sopenharmony_ci
285e41f4b71Sopenharmony_ciUse **OH_JSVM_AddFinalizer** to add a **JSVM_Finalize** callback, which will be called when the JS object is garbage-collected.
286e41f4b71Sopenharmony_ci
287e41f4b71Sopenharmony_ciCPP code:
288e41f4b71Sopenharmony_ci
289e41f4b71Sopenharmony_ci```cpp
290e41f4b71Sopenharmony_ci// hello.cpp
291e41f4b71Sopenharmony_ci#include "napi/native_api.h"
292e41f4b71Sopenharmony_ci#include "ark_runtime/jsvm.h"
293e41f4b71Sopenharmony_ci#include <hilog/log.h>
294e41f4b71Sopenharmony_ci// Register the CreateReference, UseReference, and DeleteReference callbacks.
295e41f4b71Sopenharmony_cistatic JSVM_CallbackStruct param[] = {
296e41f4b71Sopenharmony_ci    {.data = nullptr, .callback = CreateReference},
297e41f4b71Sopenharmony_ci    {.data = nullptr, .callback = UseReference},
298e41f4b71Sopenharmony_ci    {.data = nullptr, .callback = DeleteReference},
299e41f4b71Sopenharmony_ci};
300e41f4b71Sopenharmony_cistatic JSVM_CallbackStruct *method = param;
301e41f4b71Sopenharmony_ci// Expose the CreateReference, UseReference, and DeleteReference callbacks to JS.
302e41f4b71Sopenharmony_cistatic JSVM_PropertyDescriptor descriptor[] = {
303e41f4b71Sopenharmony_ci    {"createReference", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
304e41f4b71Sopenharmony_ci    {"useReference", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
305e41f4b71Sopenharmony_ci    {"deleteReference", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
306e41f4b71Sopenharmony_ci};
307e41f4b71Sopenharmony_ci// Define OH_JSVM_CreateReference and OH_JSVM_AddFinalizer.
308e41f4b71Sopenharmony_cistatic JSVM_Value CreateReference(JSVM_Env env, JSVM_CallbackInfo info)
309e41f4b71Sopenharmony_ci{
310e41f4b71Sopenharmony_ci    JSVM_Ref g_ref = nullptr;
311e41f4b71Sopenharmony_ci    JSVM_Value obj = nullptr;
312e41f4b71Sopenharmony_ci    OH_JSVM_CreateObject(env, &obj);
313e41f4b71Sopenharmony_ci    JSVM_Value value = nullptr;
314e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "CreateReference", JSVM_AUTO_LENGTH, &value);
315e41f4b71Sopenharmony_ci    // Add a property to the object.
316e41f4b71Sopenharmony_ci    OH_JSVM_SetNamedProperty(env, obj, "name", value);
317e41f4b71Sopenharmony_ci    // Create a reference to the JS object.
318e41f4b71Sopenharmony_ci    JSVM_Status status = OH_JSVM_CreateReference(env, obj, 1, &g_ref);
319e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
320e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CreateReference: failed");
321e41f4b71Sopenharmony_ci        return nullptr;
322e41f4b71Sopenharmony_ci    }
323e41f4b71Sopenharmony_ci    JSVM_Finalize jSVM_Finalize = nullptr;
324e41f4b71Sopenharmony_ci    OH_JSVM_AddFinalizer(env, obj, nullptr, jSVM_Finalize, nullptr, &g_ref);
325e41f4b71Sopenharmony_ci    // Increment the reference count and return the new reference count.
326e41f4b71Sopenharmony_ci    uint32_t result;
327e41f4b71Sopenharmony_ci    OH_JSVM_ReferenceRef(env, g_ref, &result);
328e41f4b71Sopenharmony_ci    OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_ReferenceRef, count = %{public}d.", result);
329e41f4b71Sopenharmony_ci    if (result != 2) {
330e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_ReferenceRef: failed");
331e41f4b71Sopenharmony_ci        return nullptr;
332e41f4b71Sopenharmony_ci    }
333e41f4b71Sopenharmony_ci    OH_LOG_INFO(LOG_APP, "JSVM CreateReference success");
334e41f4b71Sopenharmony_ci    return obj;
335e41f4b71Sopenharmony_ci}
336e41f4b71Sopenharmony_ci// Define OH_JSVM_ReferenceRef and OH_JSVM_GetReferenceValue.
337e41f4b71Sopenharmony_cistatic JSVM_Value UseReference(JSVM_Env env, JSVM_CallbackInfo info)
338e41f4b71Sopenharmony_ci{
339e41f4b71Sopenharmony_ci    JSVM_Ref g_ref = nullptr;
340e41f4b71Sopenharmony_ci    JSVM_Value obj = nullptr;
341e41f4b71Sopenharmony_ci    OH_JSVM_CreateObject(env, &obj);
342e41f4b71Sopenharmony_ci    JSVM_Value value = nullptr;
343e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "UseReference", JSVM_AUTO_LENGTH, &value);
344e41f4b71Sopenharmony_ci    // Add a property to the object.
345e41f4b71Sopenharmony_ci    OH_JSVM_SetNamedProperty(env, obj, "name", value);
346e41f4b71Sopenharmony_ci    // Create a reference to the JS object.
347e41f4b71Sopenharmony_ci    JSVM_Status status = OH_JSVM_CreateReference(env, obj, 1, &g_ref);
348e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
349e41f4b71Sopenharmony_ci        return nullptr;
350e41f4b71Sopenharmony_ci    }
351e41f4b71Sopenharmony_ci    JSVM_Finalize jSVM_Finalize = nullptr;
352e41f4b71Sopenharmony_ci    OH_JSVM_AddFinalizer(env, obj, nullptr, jSVM_Finalize, nullptr, &g_ref);
353e41f4b71Sopenharmony_ci    // Increment the reference count and return the new reference count.
354e41f4b71Sopenharmony_ci    uint32_t result;
355e41f4b71Sopenharmony_ci    OH_JSVM_ReferenceRef(env, g_ref, &result);
356e41f4b71Sopenharmony_ci    OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_ReferenceRef, count = %{public}d.", result);
357e41f4b71Sopenharmony_ci    if (result != 2) {
358e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_ReferenceRef: failed");
359e41f4b71Sopenharmony_ci        return nullptr;
360e41f4b71Sopenharmony_ci    }
361e41f4b71Sopenharmony_ci    JSVM_Value object = nullptr;
362e41f4b71Sopenharmony_ci    // Call OH_JSVM_GetReferenceValue to obtain the referenced JS object.
363e41f4b71Sopenharmony_ci    status = OH_JSVM_GetReferenceValue(env, g_ref, &object);
364e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
365e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_GetReferenceValue: failed");
366e41f4b71Sopenharmony_ci        return nullptr;
367e41f4b71Sopenharmony_ci    }
368e41f4b71Sopenharmony_ci    // Return the obtained object.
369e41f4b71Sopenharmony_ci    OH_LOG_INFO(LOG_APP, "JSVM UseReference success");
370e41f4b71Sopenharmony_ci    return object;
371e41f4b71Sopenharmony_ci}
372e41f4b71Sopenharmony_ci// Define OH_JSVM_ReferenceUnref and OH_JSVM_DeleteReference.
373e41f4b71Sopenharmony_cistatic JSVM_Value DeleteReference(JSVM_Env env, JSVM_CallbackInfo info)
374e41f4b71Sopenharmony_ci{
375e41f4b71Sopenharmony_ci    JSVM_Ref g_ref = nullptr;
376e41f4b71Sopenharmony_ci    JSVM_Value obj = nullptr;
377e41f4b71Sopenharmony_ci    OH_JSVM_CreateObject(env, &obj);
378e41f4b71Sopenharmony_ci    JSVM_Value value = nullptr;
379e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "DeleteReference", JSVM_AUTO_LENGTH, &value);
380e41f4b71Sopenharmony_ci    // Add a property to the object.
381e41f4b71Sopenharmony_ci    OH_JSVM_SetNamedProperty(env, obj, "name", value);
382e41f4b71Sopenharmony_ci    // Create a reference to the JS object.
383e41f4b71Sopenharmony_ci    JSVM_Status status = OH_JSVM_CreateReference(env, obj, 1, &g_ref);
384e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
385e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CreateReference: failed");
386e41f4b71Sopenharmony_ci        return nullptr;
387e41f4b71Sopenharmony_ci    }
388e41f4b71Sopenharmony_ci    JSVM_Finalize jSVM_Finalize = nullptr;
389e41f4b71Sopenharmony_ci    OH_JSVM_AddFinalizer(env, obj, nullptr, jSVM_Finalize, nullptr, &g_ref);
390e41f4b71Sopenharmony_ci    // Increment the reference count and return the new reference count.
391e41f4b71Sopenharmony_ci    uint32_t result;
392e41f4b71Sopenharmony_ci    OH_JSVM_ReferenceRef(env, g_ref, &result);
393e41f4b71Sopenharmony_ci    OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_ReferenceRef, count = %{public}d.", result);
394e41f4b71Sopenharmony_ci    if (result != 2) {
395e41f4b71Sopenharmony_ci        return nullptr;
396e41f4b71Sopenharmony_ci    }
397e41f4b71Sopenharmony_ci    // Decrement the reference count and return the new reference count.
398e41f4b71Sopenharmony_ci    uint32_t num;
399e41f4b71Sopenharmony_ci    OH_JSVM_ReferenceUnref(env, g_ref, &num);
400e41f4b71Sopenharmony_ci    OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_ReferenceUnref, count = %{public}d.", num);
401e41f4b71Sopenharmony_ci    if (num != 1) {
402e41f4b71Sopenharmony_ci        return nullptr;
403e41f4b71Sopenharmony_ci    }
404e41f4b71Sopenharmony_ci    // Call OH_JSVM_DeleteReference to delete the reference to the JS object.
405e41f4b71Sopenharmony_ci    status = OH_JSVM_DeleteReference(env, g_ref);
406e41f4b71Sopenharmony_ci    if (status != JSVM_OK) {
407e41f4b71Sopenharmony_ci        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_DeleteReference: failed");
408e41f4b71Sopenharmony_ci        return nullptr;
409e41f4b71Sopenharmony_ci    }
410e41f4b71Sopenharmony_ci    JSVM_Value returnResult = nullptr;
411e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, "OH_JSVM_DeleteReference success", JSVM_AUTO_LENGTH, &returnResult);
412e41f4b71Sopenharmony_ci    OH_LOG_INFO(LOG_APP, "JSVM DeleteReference success");
413e41f4b71Sopenharmony_ci    return returnResult;
414e41f4b71Sopenharmony_ci}
415e41f4b71Sopenharmony_ci```
416e41f4b71Sopenharmony_ci
417e41f4b71Sopenharmony_ciArkTS code:
418e41f4b71Sopenharmony_ci
419e41f4b71Sopenharmony_ci```ts
420e41f4b71Sopenharmony_ciimport hilog from "@ohos.hilog"
421e41f4b71Sopenharmony_ci// Import the native APIs.
422e41f4b71Sopenharmony_ciimport napitest from "libentry.so"
423e41f4b71Sopenharmony_citry {
424e41f4b71Sopenharmony_ci  let script: string = `createReference();`;
425e41f4b71Sopenharmony_ci  let result = napitest.runJsVm(script);
426e41f4b71Sopenharmony_ci  hilog.info(0x0000, 'testJSVM', 'Test JSVM createReference: %{public}s', result);
427e41f4b71Sopenharmony_ci} catch (error) {
428e41f4b71Sopenharmony_ci  hilog.error(0x0000, 'testJSVM', 'Test JSVM createReference error: %{public}s', error.message);
429e41f4b71Sopenharmony_ci}
430e41f4b71Sopenharmony_citry {
431e41f4b71Sopenharmony_ci  let script: string = `useReference();`;
432e41f4b71Sopenharmony_ci  let result = napitest.runJsVm(script);
433e41f4b71Sopenharmony_ci  hilog.info(0x0000, 'testJSVM', 'Test JSVM useReference: %{public}s', result);
434e41f4b71Sopenharmony_ci} catch (error) {
435e41f4b71Sopenharmony_ci  hilog.error(0x0000, 'testJSVM', 'Test JSVM useReference error: %{public}s', error.message);
436e41f4b71Sopenharmony_ci}
437e41f4b71Sopenharmony_citry {
438e41f4b71Sopenharmony_ci  let script: string = `deleteReference();`;
439e41f4b71Sopenharmony_ci  let result = napitest.runJsVm(script);
440e41f4b71Sopenharmony_ci  hilog.info(0x0000, 'testJSVM', 'Test JSVM deleteReference: %{public}s', result);
441e41f4b71Sopenharmony_ci} catch (error) {
442e41f4b71Sopenharmony_ci  hilog.error(0x0000, 'testJSVM', 'Test JSVM deleteReference error: %{public}s', error.message);
443e41f4b71Sopenharmony_ci}
444e41f4b71Sopenharmony_ci```
445