# 使用JSVM-API接å£è¿›è¡Œç”Ÿå‘½å‘¨æœŸç›¸å…³å¼€å‘ ## 简介 在JSVM-APIä¸ï¼ŒJSVM_Value是一个表示JavaScript值的抽象类型,它å¯ä»¥è¡¨ç¤ºä»»ä½•JavaScript值,包括基本类型(如数å—ã€å—符串ã€å¸ƒå°”值)和对象类型(如数组ã€å‡½æ•°ã€å¯¹è±¡ç‰ï¼‰ã€‚ JSVM_Value的生命周期与其在JavaScriptä¸çš„对应值的生命周期紧密相关。当JavaScript值被垃圾回收时,与之关è”çš„JSVM_Value也将ä¸å†æœ‰æ•ˆã€‚é‡è¦çš„æ˜¯ä¸è¦åœ¨JavaScript值ä¸å†å˜åœ¨æ—¶å°è¯•使用JSVM_Value。 框架层的scope通常用于管ç†JSVM_Value的生命周期。在JSVM-APIä¸ï¼Œå¯ä»¥ä½¿ç”¨OH_JSVM_OpenHandleScopeå’ŒOH_JSVM_CloseHandleScope函数æ¥åˆ›å»ºå’Œé”€æ¯scope。通过在scope内创建JSVM_Value,å¯ä»¥ç¡®ä¿åœ¨scopeç»“æŸæ—¶è‡ªåŠ¨é‡Šæ”¾JSVM_Value,é¿å…å†…å˜æ³„æ¼ã€‚ JSVM_Ref是一个JSVM-API类型,用于管ç†JSVM_Value的生命周期。JSVM_Refå…许您在JSVM_Valueçš„ç”Ÿå‘½å‘¨æœŸå†…ä¿æŒå¯¹å…¶çš„引用,å³ä½¿å®ƒå·²ç»è¶…出了其原始上下文的范围。这使得您å¯ä»¥åœ¨ä¸åŒçš„上下文ä¸å…±äº«JSVM_Value,并确ä¿åœ¨ä¸å†éœ€è¦æ—¶æ£ç¡®é‡Šæ”¾å…¶å†…å˜ã€‚ åˆç†ä½¿ç”¨OH_JSVM_OpenHandleScopeå’ŒOH_JSVM_CloseHandleScope管ç†JSVM_Value的生命周期,åšåˆ°ç”Ÿå‘½å‘¨æœŸæœ€å°åŒ–,é¿å…å‘ç”Ÿå†…å˜æ³„æ¼é—®é¢˜ã€‚ æ¯ä¸ªJSVM_Value属于特定的HandleScope,HandleScope通过OH_JSVM_OpenHandleScopeå’ŒOH_JSVM_CloseHandleScopeæ¥å»ºç«‹å’Œå…³é—,HandleScopeå…³é—åŽï¼Œæ‰€å±žçš„JSVM_Value就会自动释放。 ## 基本概念 JSVM-APIæä¾›äº†ä¸€ç»„功能,使开å‘人员能够在JSVM-API模å—ä¸åˆ›å»ºå’Œæ“作JavaScript对象,管ç†å¼•用和生命周期,并注册垃圾回收回调函数ç‰ã€‚䏋颿˜¯ä¸€äº›åŸºæœ¬æ¦‚念: - **作用域**:用于创建一个范围,在范围内声明的引用在范围外部将ä¸å†ç”Ÿæ•ˆã€‚JSVM-APIæä¾›äº†åˆ›å»ºã€å…³é—普通和å¯é€ƒé€¸çš„作用域的函数。 - **引用管ç†**:JSVM-APIæä¾›å‡½æ•°æ¥åˆ›å»ºã€åˆ 除和管ç†å¯¹è±¡çš„引用,以延长对象的生命周期,并é¿å…在使用对象时å‘ç”Ÿå†…å˜æ³„æ¼ã€‚ - **å¯é€ƒé€¸çš„作用域**:å…许在创建的作用域ä¸å£°æ˜Žçš„对象返回到父作用域,通过OH_JSVM_OpenEscapableHandleScopeå’ŒOH_JSVM_CloseEscapableHandleScope进行管ç†ã€‚ - **垃圾回收回调**:å…许注册回调函数,以便在JavaScriptå¯¹è±¡è¢«åžƒåœ¾å›žæ”¶æ—¶æ‰§è¡Œç‰¹å®šçš„æ¸…ç†æ“作。 这些基本概念使开å‘人员能够在JSVM-API模å—ä¸å®‰å…¨ä¸”有效地æ“作JavaScriptå¯¹è±¡ï¼Œå¹¶ç¡®ä¿æ£ç¡®ç®¡ç†å¯¹è±¡çš„生命周期。 ## 接å£è¯´æ˜Ž | æŽ¥å£ | 功能说明 | |----------------------------|--------------------------------| | OH_JSVM_OpenHandleScope | 打开一个Handle scope,确ä¿scope范围内的JSVM_Valueä¸è¢«GC回收 | | OH_JSVM_CloseHandleScope | å…³é—Handle scope| | OH_JSVM_OpenEscapableHandleScope | 打开一个新的scope逃逸Handle scope,在关é—该scope之å‰åˆ›å»ºçš„对象与父作用域有相åŒçš„生命周期 | | OH_JSVM_CloseEscapableHandleScope | å…³é—一个scope,在æ¤scope范围外创建的对象ä¸å—çˆ¶ä½œç”¨åŸŸä¿æŠ¤ | | OH_JSVM_EscapeHandle | å°†JavaScriptå¯¹è±¡çš„å¥æŸ„æå‡åˆ°å¤–部作用域,确ä¿åœ¨å¤–部作用域ä¸å¯ä»¥æŒç»åœ°ä½¿ç”¨è¯¥å¯¹è±¡ | | OH_JSVM_CreateReference | 以指定的引用计数为JavaScript对象创建一个新的引用,该引用将指å‘ä¼ å…¥çš„å¯¹è±¡ï¼Œå¼•ç”¨å…许在ä¸åŒçš„上下文ä¸ä½¿ç”¨å’Œå…±äº«å¯¹è±¡ï¼Œå¹¶ä¸”å¯ä»¥æœ‰æ•ˆåœ°è·Ÿè¸ªå¯¹è±¡çš„生命周期 | | OH_JSVM_DeleteReference | 释放由OH_JSVM_CreateReference创建的引用,确ä¿å¯¹è±¡åœ¨ä¸å†è¢«ä½¿ç”¨æ—¶èƒ½å¤Ÿè¢«æ£ç¡®åœ°é‡Šæ”¾å’Œå›žæ”¶ï¼Œé¿å…å†…å˜æ³„æ¼ | | OH_JSVM_ReferenceRef | å¢žåŠ ç”±OH_JSVM_CreateReference创建的引用的引用计数,以确ä¿å¯¹è±¡åœ¨æœ‰å¼•用时ä¸ä¼šè¢«æå‰é‡Šæ”¾ | | OH_JSVM_ReferenceUnref | å‡å°‘引用计数,用于管ç†å¼•用计数。| | OH_JSVM_GetReferenceValue | å‡å°‘ç”±OH_JSVM_CreateReferenceåˆ›å»ºçš„å¼•ç”¨çš„å¼•ç”¨è®¡æ•°ï¼Œä»¥ç¡®ä¿æ²¡æœ‰ä»»ä½•引用指å‘该对象时能æ£ç¡®åœ°é‡Šæ”¾å’Œå›žæ”¶ | | OH_JSVM_AddFinalizer | ä¸ºå¯¹è±¡æ·»åŠ JSVM_Finalize回调,以便在JavaScript对象被垃圾回收时调用æ¥é‡Šæ”¾åŽŸç”Ÿå¯¹è±¡ã€‚| ## 使用示例 JSVM-API接å£å¼€å‘æµç¨‹å‚考[使用JSVM-API实现JS与C/C++è¯è¨€äº¤äº’开呿µç¨‹](use-jsvm-process.md),本文仅对接å£å¯¹åº”C++相关代ç 进行展示。 ### OH_JSVM_OpenHandleScopeã€OH_JSVM_CloseHandleScope 通过接å£OH_JSVM_OpenHandleScope创建一个上下文环境使用。需è¦ä½¿ç”¨OH_JSVM_CloseHandleScope进行关é—。用于管ç†JavaScript对象的生命周期确ä¿åœ¨JSVM-API模å—代ç 处ç†JavaScript对象时能够æ£ç¡®åœ°ç®¡ç†å…¶å¥æŸ„,以é¿å…出现垃圾回收相关的问题。 cpp部分代ç ```cpp // OH_JSVM_OpenHandleScopeã€OH_JSVM_CloseHandleScopeçš„ä¸‰ç§æ ·ä¾‹æ–¹æ³• static JSVM_Value HandleScopeFor(JSVM_Env env, JSVM_CallbackInfo info) { // 在for循环ä¸é¢‘ç¹è°ƒç”¨JSVM接å£åˆ›å»ºjs对象时,è¦åŠ handle_scopeåŠæ—¶é‡Šæ”¾ä¸å†ä½¿ç”¨çš„资æºã€‚ // 下é¢ä¾‹åä¸ï¼Œæ¯æ¬¡å¾ªçŽ¯ç»“æŸå±€éƒ¨å˜é‡res的生命周期已结æŸï¼Œå› æ¤åŠ scopeåŠæ—¶é‡Šæ”¾å…¶æŒæœ‰çš„js对象,防æ¢å†…å˜æ³„æ¼ constexpr uint32_t DIFF_VALUE_HUNDRED_THOUSAND = 10000; JSVM_Value checked = nullptr; for (int i = 0; i < DIFF_VALUE_HUNDRED_THOUSAND; i++) { JSVM_HandleScope scope = nullptr; JSVM_Status status = OH_JSVM_OpenHandleScope(env, &scope); if (status != JSVM_OK || scope == nullptr) { OH_JSVM_GetBoolean(env, false, &checked); OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_OpenHandleScope: failed"); return checked; } JSVM_Value res = nullptr; OH_JSVM_CreateObject(env, &res); status = OH_JSVM_CloseHandleScope(env, scope); if (status != JSVM_OK) { OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CloseHandleScope: failed"); } } OH_JSVM_GetBoolean(env, true, &checked); OH_LOG_INFO(LOG_APP, "JSVM HandleScopeFor: success"); return checked; } // HandleScopeFor注册回调 static JSVM_CallbackStruct param[] = { {.callback = HandleScopeFor, .data = nullptr}, }; static JSVM_CallbackStruct *method = param; // HandleScopeFor方法别å,供JS调用 static JSVM_PropertyDescriptor descriptor[] = { {"HandleScopeFor", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, }; ``` 预期输出 ``` JSVM HandleScopeFor: success ``` ### OH_JSVM_OpenEscapableHandleScopeã€OH_JSVM_CloseEscapableHandleScopeã€OH_JSVM_EscapeHandle é€šè¿‡æŽ¥å£ OH_JSVM_OpenEscapableHandleScope 创建出一个å¯é€ƒé€¸çš„ handel scope,å¯å°† 1 个范围内声明的值返回到父作用域。创建的 scope 需使用 OH_JSVM_CloseEscapableHandleScope 进行关é—。OH_JSVM_EscapeHandle å°†ä¼ å…¥çš„ JavaScript 对象的生命周期æå‡åˆ°å…¶çˆ¶ä½œç”¨åŸŸã€‚ 通过上述接å£å¯ä»¥æ›´çµæ´»çš„使用管ç†ä¼ 入的 JavaScript 对象,特别是在处ç†è·¨ä½œç”¨åŸŸçš„å€¼ä¼ é€’æ—¶éžå¸¸æœ‰ç”¨ã€‚ cpp 部分代ç ```cpp // OH_JSVM_OpenEscapableHandleScopeã€OH_JSVM_CloseEscapableHandleScopeã€OH_JSVM_EscapeHandleçš„æ ·ä¾‹æ–¹æ³• static JSVM_Value EscapableHandleScopeTest(JSVM_Env env, JSVM_CallbackInfo info) { // 创建一个å¯é€ƒé€¸çš„奿Ÿ„作用域 JSVM_EscapableHandleScope scope = nullptr; JSVM_Status status = OH_JSVM_OpenEscapableHandleScope(env, &scope); if (status != JSVM_OK) { OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_OpenEscapableHandleScope: failed"); return nullptr; } // 在å¯é€ƒé€¸çš„奿Ÿ„作用域内创建一个obj JSVM_Value obj; OH_JSVM_CreateObject(env, &obj); // åœ¨å¯¹è±¡ä¸æ·»åŠ å±žæ€§ JSVM_Value value = nullptr; OH_JSVM_CreateStringUtf8(env, "Test jsvm_escapable_handle_scope", JSVM_AUTO_LENGTH, &value); OH_JSVM_SetNamedProperty(env, obj, "name", value); // 调用OH_JSVM_EscapeHandle将对象逃逸到作用域之外 JSVM_Value escapedObj = nullptr; OH_JSVM_EscapeHandle(env, scope, obj, &escapedObj); // å…³é—å¯é€ƒé€¸çš„奿Ÿ„作用域,清ç†èµ„æº status = OH_JSVM_CloseEscapableHandleScope(env, scope); if (status != JSVM_OK) { OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CloseEscapableHandleScope: failed"); return nullptr; } // æ¤æ—¶çš„escapedObj已逃逸,å¯ä»¥åœ¨ä½œç”¨åŸŸå¤–ç»§ç»ä½¿ç”¨escapedObj bool result = false; OH_JSVM_CreateStringUtf8(env, "name", JSVM_AUTO_LENGTH, &value); OH_JSVM_HasProperty(env, escapedObj, value, &result); if (result) { OH_LOG_INFO(LOG_APP, "JSVM EscapableHandleScopeTest: success"); } return escapedObj; } // EscapableHandleScopeTest注册回调 static JSVM_CallbackStruct param[] = { {.callback = EscapableHandleScopeTest, .data = nullptr}, }; static JSVM_CallbackStruct *method = param; // EscapableHandleScopeTest方法别å,供JS调用 static JSVM_PropertyDescriptor descriptor[] = { {"escapableHandleScopeTest", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, }; const char *srcCallNative = "escapableHandleScopeTest()"; ``` 预期输出 ``` JSVM EscapableHandleScopeTest: success ``` ### OH_JSVM_CreateReferenceã€OH_JSVM_DeleteReferenceã€OH_JSVM_GetReferenceValue 1. 调用 OH_JSVM_CreateReference 为 JavaScript å˜é‡åˆ›å»ºä¸€ä¸ªå¼•用,以延长其生命周期。 2. 调用 OH_JSVM_GetReferenceValue 获å–与引用关è”çš„ JavaScript å˜é‡ã€‚ 3. 调用 OH_JSVM_DeleteReference åˆ é™¤ä¼ å…¥çš„å¼•ç”¨ã€‚ 调用者需è¦è‡ªå·±ç®¡ç†å¼•用生命周期,引用有效期间 JavaScript å˜é‡ä¸ä¼šè¢«åžƒåœ¾å›žæ”¶å¤„ç†ã€‚ ### OH_JSVM_ReferenceRefã€OH_JSVM_ReferenceUnref å¢žåŠ /å‡å°‘ ä¼ å…¥çš„å¼•ç”¨çš„å¼•ç”¨è®¡æ•°ï¼Œå¹¶èŽ·å–æ–°çš„计数。当引用计数被置为 0 åŽï¼Œå¯¹äºŽå¯ä»¥è¢«è®¾ç½®ä¸ºå¼±å¼•用的 JavaScript 类型(对象ã€å‡½æ•°ã€å¤–部å˜é‡ï¼‰ï¼Œå¼•用将被置为弱引用,在垃圾回收机制认为必è¦çš„æ—¶å€™è¯¥å˜é‡ä¼šè¢«å›žæ”¶ï¼Œå½“å˜é‡è¢«å›žæ”¶åŽï¼Œè°ƒç”¨ OH_JSVM_GetReferenceValue 会获得 JavaScript NULL;对于ä¸å¯è¢«ç½®ä¸ºå¼±å¼•用的 JavaScript 类型,该引用会被清除,调用 OH_JSVM_GetReferenceValue 会获得 JavaScript NULL。 cpp部分代ç ```cpp static JSVM_Value UseReference(JSVM_Env env, JSVM_CallbackInfo info) { // 创建 JavaScript 对象 JSVM_Value obj = nullptr; OH_JSVM_CreateObject(env, &obj); JSVM_Value value = nullptr; OH_JSVM_CreateStringUtf8(env, "UseReference", JSVM_AUTO_LENGTH, &value); OH_JSVM_SetNamedProperty(env, obj, "name", value); JSVM_Ref g_ref = nullptr; // 创建对JavaScript对象的引用 JSVM_Status status = OH_JSVM_CreateReference(env, obj, 1, &g_ref); if (status != JSVM_OK) { return nullptr; } // å¢žåŠ ä¼ å…¥å¼•ç”¨çš„å¼•ç”¨è®¡æ•°å¹¶è¿”å›žç”Ÿæˆçš„引用计数 uint32_t result; OH_JSVM_ReferenceRef(env, g_ref, &result); OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_ReferenceRef, count = %{public}d.", result); if (result != 2) { OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_ReferenceRef: failed"); return nullptr; } // å‡å°‘ä¼ å…¥å¼•ç”¨çš„å¼•ç”¨è®¡æ•°å¹¶è¿”å›žç”Ÿæˆçš„引用计数 uint32_t num; OH_JSVM_ReferenceUnref(env, g_ref, &num); OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_ReferenceUnref, count = %{public}d.", num); if (num != 1) { return nullptr; } JSVM_Value object = nullptr; // 通过调用OH_JSVM_GetReferenceValue获å–引用的JavaScript对象 status = OH_JSVM_GetReferenceValue(env, g_ref, &object); if (status != JSVM_OK) { OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_GetReferenceValue: failed"); return nullptr; } // ä¸å†ä½¿ç”¨å¼•用,通过调用OH_JSVM_DeleteReferenceåˆ é™¤å¯¹JavaScript对象的引用 status = OH_JSVM_DeleteReference(env, g_ref); if (status != JSVM_OK) { OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_DeleteReference: failed"); return nullptr; } // 将获å–到的对象返回 OH_LOG_INFO(LOG_APP, "JSVM UseReference success"); return object; } // CreateReferenceã€UseReferenceã€DeleteReference注册回调 static JSVM_CallbackStruct param[] = { {.callback = UseReference, .data = nullptr}, }; static JSVM_CallbackStruct *method = param; // CreateReferenceã€UseReferenceã€DeleteReference方法别å,供JS调用 static JSVM_PropertyDescriptor descriptor[] = { {"useReference", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, }; const char *srcCallNative = "useReference()"; ``` 预期结果 ``` JSVM OH_JSVM_ReferenceRef, count = 2. JSVM OH_JSVM_ReferenceUnref, count = 1. JSVM UseReference success ``` ### OH_JSVM_AddFinalizer 为 JavaScript å¯¹è±¡æ·»åŠ JSVM_Finalize 回调,当 JavaScript 对象被垃圾回收时执行函数回调,该接å£é€šå¸¸è¢«ç”¨äºŽé‡Šæ”¾ä¸Ž JavaScript å¯¹è±¡ç›¸å…³çš„åŽŸç”Ÿå¯¹è±¡ã€‚å¦‚æžœä¼ å…¥çš„å‚æ•°ç±»åž‹ä¸æ˜¯ JavaScript 对象,该接å£è°ƒç”¨å¤±è´¥å¹¶è¿”回错误ç 。 Finalizer æ–¹æ³•è¢«æ³¨å†ŒåŽæ— æ³•å–æ¶ˆï¼Œå¦‚果在调用 OH_JSVM_DestroyEnv å‰å‡æœªè¢«æ‰§è¡Œï¼Œåˆ™åœ¨ OH_JVSM_DestroyEnv 时执行。 cpp 部分代ç ```cpp static int AddFinalizer(JSVM_VM vm, JSVM_Env env) { // 打开 handlescope JSVM_HandleScope handleScope; CHECK_RET(OH_JSVM_OpenHandleScope(env, &handleScope)); // 创建 object 并设置回调 JSVM_Value obj; CHECK_RET(OH_JSVM_CreateObject(env, &obj)); CHECK_RET(OH_JSVM_AddFinalizer( env, obj, nullptr, [](JSVM_Env env, void *data, void *hint) -> void { // Finalizer 方法,å¯åœ¨è¯¥æ–¹æ³•䏿¸…ç† Native 对象 OH_LOG_INFO(LOG_APP, "JSVM: finalizer called."); }, nullptr, nullptr)); OH_LOG_INFO(LOG_APP, "JSVM: finalizer added."); // å…³é— handlescopeï¼Œè§¦å‘ GC,GC æ—¶ Finalizer 会被调用 CHECK_RET(OH_JSVM_CloseHandleScope(env, handleScope)); OH_LOG_INFO(LOG_APP, "JSVM: before call gc."); CHECK_RET(OH_JSVM_MemoryPressureNotification(env, JSVM_MemoryPressureLevel::JSVM_MEMORY_PRESSURE_LEVEL_CRITICAL)); OH_LOG_INFO(LOG_APP, "JSVM: after call gc."); return 0; } static void RunDemo(JSVM_VM vm, JSVM_Env env) { if (AddFinalizer(vm, env) != 0) { OH_LOG_INFO(LOG_APP, "Run PromiseRegisterHandler failed"); } } ``` 预期结果 ``` JSVM: finalizer added. JSVM: before call gc. JSVM: finalizer called. JSVM: after call gc. ```