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