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 #include "napi/native_api.h"
17 #include "hilog/log.h"
18 #include "ark_runtime/jsvm.h"
19
20 #define LOG_DOMAIN 0x3200
21 #define LOG_TAG "APP"
22
23 static int g_aa = 0;
24
25 #define CHECK_RET(theCall) \
26 do { \
27 JSVM_Status cond = theCall; \
28 if ((cond) != JSVM_OK) { \
29 const JSVM_ExtendedErrorInfo *info; \
30 OH_JSVM_GetLastErrorInfo(env, &info); \
31 OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d message = %{public}s", \
32 __FILE__, __LINE__, cond, info != nullptr ? info->errorMessage : ""); \
33 return -1; \
34 } \
35 } while (0)
36
37 #define CHECK(theCall) \
38 do { \
39 JSVM_Status cond = theCall; \
40 if ((cond) != JSVM_OK) { \
41 OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d", __FILE__, __LINE__, \
42 cond); \
43 return -1; \
44 } \
45 } while (0)
46
47 // 用于调用theCall并检查其返回值是否为JSVM_OK。
48 // 如果不是,则调用OH_JSVM_GetLastErrorInfo处理错误并返回retVal。
49 #define JSVM_CALL_BASE(env, theCall, retVal) \
50 do { \
51 JSVM_Status cond = theCall; \
52 if (cond != JSVM_OK) { \
53 const JSVM_ExtendedErrorInfo *info; \
54 OH_JSVM_GetLastErrorInfo(env, &info); \
55 OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d message = %{public}s", \
56 __FILE__, __LINE__, cond, info != nullptr ? info->errorMessage : ""); \
57 return retVal; \
58 } \
59 } while (0)
60
61 // JSVM_CALL_BASE的简化版本,返回nullptr
62 #define JSVM_CALL(theCall) JSVM_CALL_BASE(env, theCall, nullptr)
63
64 // [Start oh_jsvm_get_version_and_vm_info]
65 // OH_JSVM_GetVersion的样例方法
GetVersion(JSVM_Env env,JSVM_CallbackInfo info)66 static JSVM_Value GetVersion(JSVM_Env env, JSVM_CallbackInfo info)
67 {
68 uint32_t jsVersion = 0;
69 // 调用接口,获取当前JSVM运行时支持的最高JSVM API版本
70 JSVM_CALL(OH_JSVM_GetVersion(env, &jsVersion));
71 int value = static_cast<int>(jsVersion);
72 OH_LOG_INFO(LOG_APP, "JSVM GetVersion success:%{public}d", value);
73 return nullptr;
74 }
75
76 // OH_JSVM_GetVMInfo的样例方法
77 // 打印JSVM(JavaScript虚拟机)的各项信息
PrintVmInfo(JSVM_VMInfo vmInfo)78 void PrintVmInfo(JSVM_VMInfo vmInfo)
79 {
80 OH_LOG_INFO(LOG_APP, "JSVM API apiVersion: %{public}d", vmInfo.apiVersion);
81 OH_LOG_INFO(LOG_APP, "JSVM API engine: %{public}s", vmInfo.engine);
82 OH_LOG_INFO(LOG_APP, "JSVM API version: %{public}s", vmInfo.version);
83 OH_LOG_INFO(LOG_APP, "JSVM API cachedDataVersionTag: 0x%{public}x", vmInfo.cachedDataVersionTag);
84 }
85
GetVMInfo(JSVM_Env env,JSVM_CallbackInfo info)86 static JSVM_Value GetVMInfo(JSVM_Env env, JSVM_CallbackInfo info)
87 {
88 // 调用接口,获取虚拟机的信息
89 JSVM_VMInfo result;
90 JSVM_CALL(OH_JSVM_GetVMInfo(&result));
91 // 输出VM虚拟机信息
92 PrintVmInfo(result);
93 return nullptr;
94 }
95
96 // IsStrictEquals注册回调
97 static JSVM_CallbackStruct param[] = {
98 {.data = nullptr, .callback = GetVersion},
99 {.data = nullptr, .callback = GetVMInfo},
100 };
101 static JSVM_CallbackStruct *method = param;
102 // IsStrictEquals方法别名,供JS调用
103 static JSVM_PropertyDescriptor descriptor[] = {
104 {"getVersion", nullptr, method, nullptr, nullptr, nullptr, JSVM_DEFAULT},
105 {"getVMInfo", nullptr, method + 1, nullptr, nullptr, nullptr, JSVM_DEFAULT},
106 };
107
108 // 样例测试js
109 static const char *STR_TASK = R"JS(getVersion();getVMInfo();)JS";
110 // [End oh_jsvm_get_version_and_vm_info]
111
TestJSVM()112 static int32_t TestJSVM()
113 {
114 JSVM_InitOptions initOptions = {0};
115 JSVM_VM vm;
116 JSVM_Env env = nullptr;
117 JSVM_VMScope vmScope;
118 JSVM_EnvScope envScope;
119 JSVM_HandleScope handleScope;
120 JSVM_Value result;
121 // 初始化JavaScript引擎实例
122 if (g_aa == 0) {
123 g_aa++;
124 CHECK(OH_JSVM_Init(&initOptions));
125 }
126 // 创建JSVM环境
127 CHECK(OH_JSVM_CreateVM(nullptr, &vm));
128 CHECK(OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env));
129 CHECK(OH_JSVM_OpenVMScope(vm, &vmScope));
130 CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
131 CHECK_RET(OH_JSVM_OpenHandleScope(env, &handleScope));
132
133 // 通过script调用测试函数
134 JSVM_Script script;
135 JSVM_Value jsSrc;
136 CHECK_RET(OH_JSVM_CreateStringUtf8(env, STR_TASK, JSVM_AUTO_LENGTH, &jsSrc));
137 CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script));
138 CHECK_RET(OH_JSVM_RunScript(env, script, &result));
139
140 // 销毁JSVM环境
141 CHECK_RET(OH_JSVM_CloseHandleScope(env, handleScope));
142 CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
143 CHECK(OH_JSVM_CloseVMScope(vm, vmScope));
144 CHECK(OH_JSVM_DestroyEnv(env));
145 CHECK(OH_JSVM_DestroyVM(vm));
146 return 0;
147 }
148
RunTest(napi_env env,napi_callback_info info)149 static napi_value RunTest(napi_env env, napi_callback_info info)
150 {
151 TestJSVM();
152 return nullptr;
153 }
154
155 // 模块注册信息,供arkts侧调用
156 EXTERN_C_START
Init(napi_env env,napi_value exports)157 static napi_value Init(napi_env env, napi_value exports)
158 {
159 napi_property_descriptor desc[] = {{"runTest", nullptr, RunTest, nullptr, nullptr, nullptr, napi_default, nullptr}};
160 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
161 return exports;
162 }
163 EXTERN_C_END
164
165 static napi_module demoModule = {
166 .nm_version = 1,
167 .nm_flags = 0,
168 .nm_filename = nullptr,
169 .nm_register_func = Init,
170 .nm_modname = "getversion",
171 .nm_priv = ((void *)0),
172 .reserved = {0},
173 };
174
RegisterEntryModule(void)175 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
176