1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 // [Start oh_jsvm_get_value_external]
17 #include "napi/native_api.h"
18 #include "ark_runtime/jsvm.h"
19 #include "hilog/log.h"
20 // [StartExclude oh_jsvm_get_value_external]
21 #define LOG_DOMAIN 0x3200
22 #define LOG_TAG "APP"
23
24 static int g_aa = 0;
25
26 #define CHECK_RET(theCall) \
27 do { \
28 JSVM_Status cond = theCall; \
29 if ((cond) != JSVM_OK) { \
30 const JSVM_ExtendedErrorInfo *info; \
31 OH_JSVM_GetLastErrorInfo(env, &info); \
32 OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d message = %{public}s", \
33 __FILE__, __LINE__, cond, info != nullptr ? info->errorMessage : ""); \
34 return -1; \
35 } \
36 } while (0)
37
38 #define CHECK(theCall) \
39 do { \
40 JSVM_Status cond = theCall; \
41 if ((cond) != JSVM_OK) { \
42 OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d", __FILE__, __LINE__, \
43 cond); \
44 return -1; \
45 } \
46 } while (0)
47
48 // 用于调用theCall并检查其返回值是否为JSVM_OK。
49 // 如果不是,则调用OH_JSVM_GetLastErrorInfo处理错误并返回retVal。
50 #define JSVM_CALL_BASE(env, theCall, retVal) \
51 do { \
52 JSVM_Status cond = theCall; \
53 if (cond != JSVM_OK) { \
54 const JSVM_ExtendedErrorInfo *info; \
55 OH_JSVM_GetLastErrorInfo(env, &info); \
56 OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d message = %{public}s", \
57 __FILE__, __LINE__, cond, info != nullptr ? info->errorMessage : ""); \
58 return retVal; \
59 } \
60 } while (0)
61
62 // JSVM_CALL_BASE的简化版本,返回nullptr
63 #define JSVM_CALL(theCall) JSVM_CALL_BASE(env, theCall, nullptr)
64 // [EndExclude oh_jsvm_get_value_external]
65
66 // OH_JSVM_GetValueExternal的样例方法
GetValueExternal(JSVM_Env env,JSVM_CallbackInfo info)67 static JSVM_Value GetValueExternal(JSVM_Env env, JSVM_CallbackInfo info)
68 {
69 static int data = 0x12345;
70 JSVM_Value externalValue = nullptr;
71 JSVM_Status status = OH_JSVM_CreateExternal(env, (void*)&data, nullptr, nullptr, &externalValue);
72 if (status != JSVM_OK) {
73 OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CreateExternal fail");
74 } else {
75 OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_CreateExternal success");
76 }
77 void *dataValue;
78 status = OH_JSVM_GetValueExternal(env, externalValue, &dataValue);
79 if (status != JSVM_OK) {
80 OH_LOG_ERROR(LOG_APP, "JSVM GetValueExternal fail");
81 } else {
82 OH_LOG_INFO(LOG_APP, "JSVM GetValueExternal success");
83 }
84 // 将符号位转化为int类型传出去
85 JSVM_Value returnValue = nullptr;
86 int retData = *static_cast<int *>(dataValue);
87 OH_JSVM_CreateInt32(env, retData, &returnValue);
88 return returnValue;
89 }
90 // GetValueExternal注册回调
91 static JSVM_CallbackStruct param[] = {
92 {.data = nullptr, .callback = GetValueExternal},
93 };
94 static JSVM_CallbackStruct *method = param;
95 // GetValueExternal方法别名,供JS调用
96 static JSVM_PropertyDescriptor descriptor[] = {
97 {"getValueExternal", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
98 };
99 // 样例测试js
100 const char* SRC_CALL_NATIVE = R"JS(getValueExternal())JS";
101 // [End oh_jsvm_get_value_external]
102
TestJSVM()103 static int32_t TestJSVM()
104 {
105 JSVM_InitOptions initOptions = {0};
106 JSVM_VM vm;
107 JSVM_Env env = nullptr;
108 JSVM_VMScope vmScope;
109 JSVM_EnvScope envScope;
110 JSVM_HandleScope handleScope;
111 JSVM_Value result;
112 // 初始化JavaScript引擎实例
113 if (g_aa == 0) {
114 g_aa++;
115 CHECK(OH_JSVM_Init(&initOptions));
116 }
117 // 创建JSVM环境
118 CHECK(OH_JSVM_CreateVM(nullptr, &vm));
119 CHECK(OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env));
120 CHECK(OH_JSVM_OpenVMScope(vm, &vmScope));
121 CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
122 CHECK_RET(OH_JSVM_OpenHandleScope(env, &handleScope));
123
124 // 通过script调用测试函数
125 JSVM_Script script;
126 JSVM_Value jsSrc;
127 CHECK_RET(OH_JSVM_CreateStringUtf8(env, SRC_CALL_NATIVE, JSVM_AUTO_LENGTH, &jsSrc));
128 CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script));
129 CHECK_RET(OH_JSVM_RunScript(env, script, &result));
130
131 // 销毁JSVM环境
132 CHECK_RET(OH_JSVM_CloseHandleScope(env, handleScope));
133 CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
134 CHECK(OH_JSVM_CloseVMScope(vm, vmScope));
135 CHECK(OH_JSVM_DestroyEnv(env));
136 CHECK(OH_JSVM_DestroyVM(vm));
137 return 0;
138 }
139
RunTest(napi_env env,napi_callback_info info)140 static napi_value RunTest(napi_env env, napi_callback_info info)
141 {
142 TestJSVM();
143 return nullptr;
144 }
145
146 // 模块注册信息,供arkts侧调用
147 EXTERN_C_START
Init(napi_env env,napi_value exports)148 static napi_value Init(napi_env env, napi_value exports)
149 {
150 napi_property_descriptor desc[] = {{"runTest", nullptr, RunTest, nullptr, nullptr, nullptr, napi_default, nullptr}};
151 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
152 return exports;
153 }
154 EXTERN_C_END
155
156 static napi_module demoModule = {
157 .nm_version = 1,
158 .nm_flags = 0,
159 .nm_filename = nullptr,
160 .nm_register_func = Init,
161 .nm_modname = "getvalueexternal",
162 .nm_priv = ((void *)0),
163 .reserved = {0},
164 };
165
RegisterEntryModule(void)166 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
167