1 /*
2 * Copyright (c) 2024 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 "node_api.h"
17 #include "ark_native_engine.h"
18 #include "ark_interop_log.h"
19 #include "cj_envsetup.h"
20
ParseLoadParams(napi_env env,napi_callback_info info,char * nameBuf,size_t & size)21 static bool ParseLoadParams(napi_env env, napi_callback_info info, char* nameBuf, size_t& size)
22 {
23 napi_value libNameValue;
24 size_t argCount = 1;
25 auto status = napi_get_cb_info(env, info, &argCount, &libNameValue, nullptr, nullptr);
26 if (status != napi_ok) {
27 napi_throw_error(env, "napi call fail", "napi_get_cb_info failed");
28 return false;
29 }
30
31 if (argCount != 1) {
32 napi_throw_error(env, "argument invalid", "need one argument");
33 return false;
34 }
35
36 napi_valuetype valuetype;
37 status = napi_typeof(env, libNameValue, &valuetype);
38 if (status != napi_ok) {
39 napi_throw_error(env, "napi call fail", "napi_typeof failed");
40 return false;
41 }
42 if (valuetype != napi_string) {
43 napi_throw_error(env, "argument invalid", "need a string");
44 return false;
45 }
46
47 status = napi_get_value_string_utf8(env, libNameValue, nameBuf, size, &size);
48 if (status != napi_ok) {
49 napi_throw_error(env, "argument invalid", "napi_get_value_string_utf8 not ok");
50 return false;
51 }
52 return true;
53 }
54
LoadArkCJModule(napi_env env,const char * libName,napi_value * result)55 static bool LoadArkCJModule(napi_env env, const char* libName, napi_value* result)
56 {
57 auto engine = reinterpret_cast<ArkNativeEngine*>(env);
58 auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
59 do {
60 const char* targetName;
61 const char* loaderName = "ARKTS_LoadModule";
62 #ifdef __OHOS__
63 targetName = "libark_interop.z.so";
64 #elif defined(__WINDOWS__)
65 targetName = "libark_interop.dll";
66 #elif defined(__LINUX__)
67 targetName = "libark_interop.so";
68 #endif
69 auto runtime = OHOS::CJEnv::LoadInstance();
70 auto handle = runtime->loadLibrary(0, targetName);
71 if (!handle) {
72 LOGE("open '%{public}s' failed", targetName);
73 return false;
74 }
75 auto symbol = runtime->getSymbol(handle, loaderName);
76 if (!symbol) {
77 LOGE("no symbol of '%{public}s'", loaderName);
78 return false;
79 }
80 auto loader = reinterpret_cast<napi_value(*)(EcmaVM*, const char*)>(symbol);
81 *result = loader(vm, libName);
82 } while (false);
83 return true;
84 }
85
LoadCJModule(napi_env env,napi_callback_info info)86 static napi_value LoadCJModule(napi_env env, napi_callback_info info)
87 {
88 napi_value result;
89 if (napi_get_undefined(env, &result) != napi_ok) {
90 return result;
91 }
92 constexpr size_t BUF_SIZE = 256;
93 char nameBuf[BUF_SIZE];
94 size_t realSize = BUF_SIZE;
95 if (!ParseLoadParams(env, info, nameBuf, realSize)) {
96 return result;
97 }
98 auto runtime = OHOS::CJEnv::LoadInstance();
99 runtime->initCJChipSDKNS("/system/lib64/chipset-pub-sdk");
100 runtime->initCJAppNS("/data/storage/el1/bundle/libs/arm64");
101 runtime->initCJSDKNS("/data/storage/el1/bundle/libs/arm64/ohos:"
102 "/data/storage/el1/bundle/libs/arm64/runtime");
103 runtime->initCJSysNS("/system/lib64:/system/lib64/platformsdk:/system/lib64/module:/system/lib64/ndk");
104 if (!runtime->startRuntime()) {
105 LOGE("start cjruntime failed");
106 return result;
107 }
108 if (!runtime->startUIScheduler()) {
109 LOGE("start cj ui context failed");
110 return result;
111 }
112
113 LoadArkCJModule(env, nameBuf, &result);
114 return result;
115 }
116
ExportLoadCJModule(napi_env env,napi_value exports)117 static napi_value ExportLoadCJModule(napi_env env, napi_value exports)
118 {
119 static napi_property_descriptor desc[] = {
120 {"requireCJLib", nullptr, LoadCJModule, nullptr, nullptr, nullptr, napi_default, nullptr}
121 };
122 napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc);
123 return exports;
124 }
125
LoadCJModuleRegister()126 extern "C" __attribute__((constructor)) void LoadCJModuleRegister()
127 {
128 static napi_module callbackModule = {
129 .nm_version = 1,
130 .nm_flags = 0,
131 .nm_filename = nullptr,
132 .nm_register_func = ExportLoadCJModule,
133 .nm_modname = "ark_interop_loader",
134 .nm_priv = nullptr,
135 .reserved = { 0 },
136 };
137 napi_module_register(&callbackModule);
138 }
139