1 /*
2 * Copyright (c) 2021-2022 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 "bridge/declarative_frontend/engine/quickjs/modules/qjs_module_manager.h"
17
18 #include "base/log/log.h"
19 #include "bridge/declarative_frontend/engine/quickjs/modules/qjs_curves_module.h"
20 #include "bridge/declarative_frontend/engine/quickjs/modules/qjs_matrix4_module.h"
21 #include "bridge/declarative_frontend/engine/quickjs/modules/qjs_router_module.h"
22 #include "bridge/declarative_frontend/engine/quickjs/qjs_declarative_engine.h"
23 #include "bridge/js_frontend/engine/common/js_constants.h"
24 #include "bridge/js_frontend/engine/quickjs/qjs_utils.h"
25 #include "core/common/container.h"
26
27 namespace OHOS::Ace::Framework {
28 namespace {
29 constexpr int32_t CUSTOM_FULL_WINDOW_LENGTH = 3;
30 constexpr int32_t ARGS_FULL_WINDOW_LENGTH = 2;
31 } // namespace
32
GetInstance()33 ModuleManager* ModuleManager::GetInstance()
34 {
35 static ModuleManager instance;
36 return &instance;
37 }
38
AppGetInfo(JSContext * ctx,JSValue value,int32_t argc,JSValueConst * argv)39 JSValue AppGetInfo(JSContext* ctx, JSValue value, int32_t argc, JSValueConst* argv)
40 {
41 auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
42 if (instance == nullptr) {
43 LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
44 return JS_NULL;
45 }
46 auto delegate = instance->GetDelegate();
47 if (!delegate) {
48 LOGE("get frontend delegate failed");
49 return JS_NULL;
50 }
51 JSValue appInfo = JS_NewObject(ctx);
52 auto appId = delegate->GetAppID();
53 auto appName = delegate->GetAppName();
54 auto versionName = delegate->GetVersionName();
55 auto versionCode = delegate->GetVersionCode();
56 JS_SetPropertyStr(ctx, appInfo, "appID", JS_NewString(ctx, appId.c_str()));
57 JS_SetPropertyStr(ctx, appInfo, "appName", JS_NewString(ctx, appName.c_str()));
58 JS_SetPropertyStr(ctx, appInfo, "versionName", JS_NewString(ctx, versionName.c_str()));
59 JS_SetPropertyStr(ctx, appInfo, "versionCode", JS_NewInt32(ctx, versionCode));
60 return appInfo;
61 }
62
AppTerminate(JSContext * ctx,JSValue value,int32_t argc,JSValueConst * argv)63 JSValue AppTerminate(JSContext* ctx, JSValue value, int32_t argc, JSValueConst* argv)
64 {
65 auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
66 if (instance == nullptr) {
67 LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
68 return JS_NULL;
69 }
70 auto delegate = instance->GetDelegate();
71 if (!delegate) {
72 LOGE("get frontend delegate failed");
73 return JS_NULL;
74 }
75 auto pipelineContext = instance->GetPipelineContext(ctx);
76 if (!pipelineContext) {
77 LOGE("get frontend pipelineContext failed");
78 return JS_NULL;
79 }
80 auto uiTaskExecutor = delegate->GetUiTask();
81 WeakPtr<PipelineBase> pipelineContextWeak(pipelineContext);
82 uiTaskExecutor.PostTask([pipelineContextWeak]() mutable {
83 auto pipelineContext = pipelineContextWeak.Upgrade();
84 if (pipelineContext) {
85 pipelineContext->Finish();
86 }
87 });
88 return JS_NULL;
89 }
90
ParseFullWindowParams(JSContext * ctx,JSValue params,std::string & duration)91 void ParseFullWindowParams(JSContext* ctx, JSValue params, std::string& duration)
92 {
93 JSPropertyEnum* tab = nullptr;
94 uint32_t paramLen = 0;
95 if (JS_IsObject(params)) {
96 JS_GetOwnPropertyNames(ctx, &tab, ¶mLen, params, JS_GPN_STRING_MASK);
97 const char* jsDurationKey = JS_AtomToCString(ctx, tab[0].atom);
98 if (jsDurationKey == nullptr) {
99 JS_FreeAtom(ctx, tab[0].atom);
100 js_free(ctx, tab);
101 LOGE("jsDurationKey is null.");
102 return;
103 }
104 if (std::strcmp(jsDurationKey, "duration") == 0) {
105 JSValue valObject = JS_GetProperty(ctx, params, tab[0].atom);
106 if (JS_IsString(valObject) || JS_IsNumber(valObject)) {
107 ScopedString styleVal(ctx, valObject);
108 const char* valDuration = styleVal.get();
109 duration = valDuration;
110 }
111 JS_FreeValue(ctx, valObject);
112 }
113 JS_FreeAtom(ctx, tab[0].atom);
114 JS_FreeCString(ctx, jsDurationKey);
115 }
116 js_free(ctx, tab);
117 }
118
AppRequestFullWindow(JSContext * ctx,JSValue value,int32_t argc,JSValueConst * argv)119 JSValue AppRequestFullWindow(JSContext* ctx, JSValue value, int32_t argc, JSValueConst* argv)
120 {
121 JSPropertyEnum* pTab = nullptr;
122 uint32_t len = 0;
123 int32_t duration = -1;
124 if (JS_IsObject(value) && JS_IsArray(ctx, value)) {
125 JS_GetOwnPropertyNames(ctx, &pTab, &len, value, JS_GPN_STRING_MASK);
126 if (len < ARGS_FULL_WINDOW_LENGTH) {
127 LOGW("RequestFullWindow: invalid callback value");
128 js_free(ctx, pTab);
129 return JS_NULL;
130 }
131 if (len == CUSTOM_FULL_WINDOW_LENGTH) {
132 JSValue jsDuration = JS_GetProperty(ctx, value, pTab[0].atom);
133 std::string valDuration;
134 ParseFullWindowParams(ctx, jsDuration, valDuration);
135 if (!valDuration.empty()) {
136 duration = StringToInt(valDuration);
137 }
138 if (duration < 0) {
139 duration = -1;
140 }
141 JS_FreeValue(ctx, jsDuration);
142 }
143 js_free(ctx, pTab);
144 }
145 auto instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
146 WeakPtr<PipelineBase> pipelineContextWeak = instance->GetDelegate()->GetPipelineContext();
147 auto uiTaskExecutor = instance->GetDelegate()->GetUiTask();
148 uiTaskExecutor.PostTask([pipelineContextWeak, duration]() mutable {
149 auto pipelineContext = pipelineContextWeak.Upgrade();
150 if (pipelineContext) {
151 pipelineContext->RequestFullWindow(duration);
152 }
153 });
154 return JS_NULL;
155 }
156
AppSetImageCacheCount(JSContext * ctx,JSValue value,int32_t argc,JSValueConst * argv)157 JSValue AppSetImageCacheCount(JSContext* ctx, JSValue value, int32_t argc, JSValueConst* argv)
158 {
159 auto container = Container::Current();
160 if (!container) {
161 LOGE("current container is null");
162 return JS_NULL;
163 }
164 auto pipelineContext = container->GetPipelineContext();
165 if (!pipelineContext) {
166 LOGE("get pipelineContext failed");
167 return JS_NULL;
168 }
169 auto taskExecutor = pipelineContext->GetTaskExecutor();
170 if (!taskExecutor) {
171 LOGE("taskExecutor is null.");
172 return JS_NULL;
173 }
174 WeakPtr<PipelineBase> pipelineContextWeak(pipelineContext);
175 int32_t size;
176 JS_ToInt32(ctx, &size, argv[0]);
177 size = size > 0 ? size : 0;
178 taskExecutor->PostTask([pipelineContextWeak, size]() mutable {
179 auto pipelineContext = pipelineContextWeak.Upgrade();
180 if (pipelineContext) {
181 auto imageCache = pipelineContext->GetImageCache();
182 if (imageCache) {
183 imageCache->SetCapacity(size);
184 } else {
185 LOGW("image cache is null");
186 }
187 }
188 }, TaskExecutor::TaskType::UI);
189 return JS_NULL;
190 }
191
AppSetImageRawDataCacheSize(JSContext * ctx,JSValue value,int32_t argc,JSValueConst * argv)192 JSValue AppSetImageRawDataCacheSize(JSContext* ctx, JSValue value, int32_t argc, JSValueConst* argv)
193 {
194 auto container = Container::Current();
195 if (!container) {
196 LOGE("current container is null");
197 return JS_NULL;
198 }
199 auto pipelineContext = container->GetPipelineContext();
200 if (!pipelineContext) {
201 LOGE("get pipelineContext failed");
202 return JS_NULL;
203 }
204 auto taskExecutor = pipelineContext->GetTaskExecutor();
205 if (!taskExecutor) {
206 LOGE("taskExecutor is null.");
207 return JS_NULL;
208 }
209 WeakPtr<PipelineBase> pipelineContextWeak(pipelineContext);
210 int32_t size;
211 JS_ToInt32(ctx, &size, argv[0]);
212 size = size > 0 ? size : 0;
213 taskExecutor->PostTask([pipelineContextWeak, size]() mutable {
214 auto pipelineContext = pipelineContextWeak.Upgrade();
215 if (pipelineContext) {
216 auto imageCache = pipelineContext->GetImageCache();
217 if (imageCache) {
218 imageCache->SetCapacity(size);
219 } else {
220 LOGW("image cache is null");
221 }
222 }
223 }, TaskExecutor::TaskType::UI);
224 return JS_NULL;
225 }
226
AppSetImageFileCacheSize(JSContext * ctx,JSValue value,int32_t argc,JSValueConst * argv)227 JSValue AppSetImageFileCacheSize(JSContext* ctx, JSValue value, int32_t argc, JSValueConst* argv)
228 {
229 auto container = Container::Current();
230 if (!container) {
231 LOGE("current container is null");
232 return JS_NULL;
233 }
234 auto pipelineContext = container->GetPipelineContext();
235 if (!pipelineContext) {
236 LOGE("get pipelineContext failed");
237 return JS_NULL;
238 }
239 auto taskExecutor = pipelineContext->GetTaskExecutor();
240 if (!taskExecutor) {
241 LOGE("taskExecutor is null.");
242 return JS_NULL;
243 }
244 WeakPtr<PipelineBase> pipelineContextWeak(pipelineContext);
245 int32_t size;
246 JS_ToInt32(ctx, &size, argv[0]);
247 size = size > 0 ? size : 0;
248 taskExecutor->PostTask([pipelineContextWeak, size]() mutable {
249 auto pipelineContext = pipelineContextWeak.Upgrade();
250 if (pipelineContext) {
251 auto imageCache = pipelineContext->GetImageCache();
252 if (imageCache) {
253 imageCache->SetCacheFileLimit(size);
254 } else {
255 LOGW("image cache is null");
256 }
257 }
258 }, TaskExecutor::TaskType::UI);
259 return JS_NULL;
260 }
261
InitAppModule(JSContext * ctx,JSValue & moduleObj)262 void InitAppModule(JSContext* ctx, JSValue& moduleObj)
263 {
264 JS_SetPropertyStr(ctx, moduleObj, APP_GET_INFO, JS_NewCFunction(ctx, AppGetInfo, APP_GET_INFO, 0));
265 JS_SetPropertyStr(ctx, moduleObj, APP_TERMINATE, JS_NewCFunction(ctx, AppTerminate, APP_TERMINATE, 0));
266 JS_SetPropertyStr(ctx, moduleObj, APP_REQUEST_FULL_WINDOW,
267 JS_NewCFunction(ctx, AppRequestFullWindow, APP_REQUEST_FULL_WINDOW, 1));
268 JS_SetPropertyStr(ctx, moduleObj, APP_SET_IMAGE_CACHE_COUNT,
269 JS_NewCFunction(ctx, AppSetImageCacheCount, APP_SET_IMAGE_CACHE_COUNT, 1));
270 JS_SetPropertyStr(ctx, moduleObj, APP_SET_IMAGE_RAWDATA_CACHE_SIZE,
271 JS_NewCFunction(ctx, AppSetImageRawDataCacheSize, APP_SET_IMAGE_RAWDATA_CACHE_SIZE, 1));
272 JS_SetPropertyStr(ctx, moduleObj, APP_SET_IMAGE_FILE_CACHE_SIZE,
273 JS_NewCFunction(ctx, AppSetImageFileCacheSize, APP_SET_IMAGE_FILE_CACHE_SIZE, 1));
274 }
275
InitModule(JSContext * ctx,const std::string & moduleName,JSValue & jsObject)276 bool ModuleManager::InitModule(JSContext* ctx, const std::string& moduleName, JSValue& jsObject)
277 {
278 static const std::unordered_map<std::string, void (*)(JSContext * ctx, JSValue & jsObject)> MODULE_LIST = {
279 { "system.router", [](JSContext* ctx, JSValue& jsObject) { InitRouterModule(ctx, jsObject); } },
280 { "ohos.router", [](JSContext* ctx, JSValue& jsObject) { InitRouterModule(ctx, jsObject); } },
281 { "system.curves", [](JSContext* ctx, JSValue& jsObject) { InitCurvesModule(ctx, jsObject); } },
282 { "ohos.curves", [](JSContext* ctx, JSValue& jsObject) { InitCurvesModule(ctx, jsObject); } },
283 { "system.matrix4", [](JSContext* ctx, JSValue& jsObject) { InitMatrix4Module(ctx, jsObject); } },
284 { "ohos.matrix4", [](JSContext* ctx, JSValue& jsObject) { InitMatrix4Module(ctx, jsObject); } },
285 { "system.app", [](JSContext* ctx, JSValue& jsObject) { InitAppModule(ctx, jsObject); } },
286 { "ohos.app", [](JSContext* ctx, JSValue& jsObject) { InitAppModule(ctx, jsObject); } },
287 };
288 auto iter = MODULE_LIST.find(moduleName);
289 if (iter != MODULE_LIST.end()) {
290 iter->second(ctx, jsObject);
291 LOGD("ModuleManager InitModule is %{private}s", moduleName.c_str());
292 return true;
293 } else {
294 LOGE("register module is not found");
295 return false;
296 }
297 }
298
SetTimeout(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)299 JSValue SetTimeout(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
300 {
301 return ModuleManager::GetInstance()->SetWaitTimer(ctx, argc, argv, false);
302 }
303
SetInterval(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)304 JSValue SetInterval(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
305 {
306 return ModuleManager::GetInstance()->SetWaitTimer(ctx, argc, argv, true);
307 }
308
ClearTimeout(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)309 JSValue ClearTimeout(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
310 {
311 return ModuleManager::GetInstance()->ClearWaitTimer(ctx, argc, argv, false);
312 }
313
ClearInterval(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)314 JSValue ClearInterval(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
315 {
316 return ModuleManager::GetInstance()->ClearWaitTimer(ctx, argc, argv, true);
317 }
318
CanIUse(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)319 JSValue CanIUse(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
320 {
321 LOGD("CanIUse argc is %d", argc);
322
323 if (argc != 1) {
324 LOGE("CanIUse: invalid value");
325 return JS_NULL;
326 }
327
328 QJSContext::Scope scp(ctx);
329 if (!JS_IsString(argv[0])) {
330 LOGE("CanIUse: invalid input");
331 return JS_NULL;
332 }
333
334 ScopedString targetString(ctx, argv[0]);
335 std::string syscapString = targetString.get();
336
337 bool ret = Ace::SystemProperties::IsSyscapExist(syscapString.c_str());
338
339 return JS_NewBool(ctx, ret);
340 }
341
SetWaitTimer(JSContext * ctx,int32_t argc,JSValueConst * argv,bool isInterval)342 JSValue ModuleManager::SetWaitTimer(JSContext* ctx, int32_t argc, JSValueConst* argv, bool isInterval)
343 {
344 LOGD("SetWaitTimer argc is %d", argc);
345
346 auto instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
347 if (instance == nullptr) {
348 LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
349 return JS_NULL;
350 }
351
352 if (argc < 1) {
353 LOGW("JsSetTimer: invalid callback value");
354 return JS_NULL;
355 }
356
357 JSValue jsFunc = JS_DupValue(ctx, argv[0]);
358 if (!JS_IsFunction(ctx, jsFunc)) {
359 LOGW("argv[0] is not function");
360 return JS_NULL;
361 }
362
363 uint32_t delay = 0;
364 std::vector<JSValue> callbackArray;
365 if (argc < 2 || !JS_IsNumber(argv[1])) {
366 uint32_t callbackId = ModuleManager::GetInstance()->AddCallback(jsFunc, callbackArray, isInterval);
367 instance->GetDelegate()->WaitTimer(std::to_string(callbackId), std::to_string(delay), isInterval, true);
368 return JS_NULL;
369 }
370
371 JS_ToUint32(ctx, &delay, argv[1]);
372 for (int index = 2; index < argc; ++index) {
373 callbackArray.emplace_back(JS_DupValue(ctx, argv[index]));
374 }
375
376 uint32_t callbackId = ModuleManager::GetInstance()->AddCallback(jsFunc, callbackArray, isInterval);
377 instance->GetDelegate()->WaitTimer(std::to_string(callbackId), std::to_string(delay), isInterval, true);
378
379 return JS_NewInt32(ctx, callbackId);
380 }
381
AddCallback(JSValue callbackFunc,std::vector<JSValue> callbackArray,bool isInterval)382 uint32_t ModuleManager::AddCallback(JSValue callbackFunc, std::vector<JSValue> callbackArray, bool isInterval)
383 {
384 if (isInterval) {
385 return AddCallback(intervalCallbackFuncMap_, intervalCallbackArrayMap_, callbackFunc, callbackArray);
386 } else {
387 return AddCallback(callbackFuncMap_, callbackArrayMap_, callbackFunc, callbackArray);
388 }
389 }
390
AddCallback(std::unordered_map<uint32_t,JSValue> & callbackFuncMap,std::unordered_map<uint32_t,std::vector<JSValue>> & callbackArrayMap,JSValue callbackFunc,std::vector<JSValue> callbackArray)391 uint32_t ModuleManager::AddCallback(std::unordered_map<uint32_t, JSValue>& callbackFuncMap,
392 std::unordered_map<uint32_t, std::vector<JSValue>>& callbackArrayMap, JSValue callbackFunc,
393 std::vector<JSValue> callbackArray)
394 {
395 ++callbackId_;
396 callbackFuncMap[callbackId_] = callbackFunc;
397 if (!callbackArray.empty()) {
398 callbackArrayMap[callbackId_] = callbackArray;
399 }
400 return callbackId_;
401 }
402
GetCallbackFunc(uint32_t callbackId,bool isInterval)403 JSValue ModuleManager::GetCallbackFunc(uint32_t callbackId, bool isInterval)
404 {
405 if (isInterval) {
406 return intervalCallbackFuncMap_[callbackId];
407 } else {
408 return callbackFuncMap_[callbackId];
409 }
410 }
411
GetCallbackArray(uint32_t callbackId,bool isInterval)412 std::vector<JSValue> ModuleManager::GetCallbackArray(uint32_t callbackId, bool isInterval)
413 {
414 if (isInterval) {
415 return GetCallbackArray(intervalCallbackArrayMap_, callbackId);
416 } else {
417 return GetCallbackArray(callbackArrayMap_, callbackId);
418 }
419 }
420
GetCallbackArray(std::unordered_map<uint32_t,std::vector<JSValue>> & callbackArrayMap,uint32_t callbackId)421 std::vector<JSValue> ModuleManager::GetCallbackArray(
422 std::unordered_map<uint32_t, std::vector<JSValue>>& callbackArrayMap, uint32_t callbackId)
423 {
424 if (callbackArrayMap.find(callbackId) != callbackArrayMap.end()) {
425 return callbackArrayMap[callbackId];
426 }
427 std::vector<JSValue> emptyRet;
428 return emptyRet;
429 }
430
ClearWaitTimer(JSContext * ctx,int32_t argc,JSValueConst * argv,bool isInterval)431 JSValue ModuleManager::ClearWaitTimer(JSContext* ctx, int32_t argc, JSValueConst* argv, bool isInterval)
432 {
433 if (argc < 0 || !JS_IsNumber(argv[0])) {
434 LOGE("args[0] is not number");
435 return JS_NULL;
436 }
437
438 uint32_t callbackId;
439 JS_ToUint32(ctx, &callbackId, argv[0]);
440 ModuleManager::GetInstance()->RemoveCallbackFunc(ctx, callbackId, isInterval);
441 auto instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
442 if (instance == nullptr) {
443 LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
444 return JS_NULL;
445 }
446 instance->GetDelegate()->ClearTimer(std::to_string(callbackId));
447 return JS_NULL;
448 }
449
RemoveCallbackFunc(JSContext * ctx,uint32_t callbackId,bool isInterval)450 void ModuleManager::RemoveCallbackFunc(JSContext* ctx, uint32_t callbackId, bool isInterval)
451 {
452 if (isInterval) {
453 RemoveCallbackFunc(ctx, intervalCallbackFuncMap_, intervalCallbackArrayMap_, callbackId);
454 } else {
455 RemoveCallbackFunc(ctx, callbackFuncMap_, callbackArrayMap_, callbackId);
456 }
457 }
458
RemoveCallbackFunc(JSContext * ctx,std::unordered_map<uint32_t,JSValue> & callbackFuncMap,std::unordered_map<uint32_t,std::vector<JSValue>> & callbackArrayMap,uint32_t callbackId)459 void ModuleManager::RemoveCallbackFunc(JSContext* ctx, std::unordered_map<uint32_t, JSValue>& callbackFuncMap,
460 std::unordered_map<uint32_t, std::vector<JSValue>>& callbackArrayMap, uint32_t callbackId)
461 {
462 JS_FreeValue(ctx, callbackFuncMap[callbackId]);
463 callbackFuncMap.erase(callbackId);
464
465 if (callbackArrayMap.find(callbackId) != callbackArrayMap.end()) {
466 uint32_t index = 0;
467 while (index < callbackArrayMap[callbackId].size()) {
468 JS_FreeValue(ctx, callbackArrayMap[callbackId][index]);
469 ++index;
470 }
471 callbackArrayMap.erase(callbackId);
472 }
473 }
474
InitTimerModule(JSContext * ctx)475 void ModuleManager::InitTimerModule(JSContext* ctx)
476 {
477 JSValue globalObj = JS_GetGlobalObject(ctx);
478 JS_SetPropertyStr(ctx, globalObj, SET_TIMEOUT, JS_NewCFunction(ctx, SetTimeout, SET_TIMEOUT, 2));
479 JS_SetPropertyStr(ctx, globalObj, SET_INTERVAL, JS_NewCFunction(ctx, SetInterval, SET_INTERVAL, 2));
480 JS_SetPropertyStr(ctx, globalObj, CLEAR_TIMEOUT, JS_NewCFunction(ctx, ClearTimeout, CLEAR_TIMEOUT, 1));
481 JS_SetPropertyStr(ctx, globalObj, CLEAR_INTERVAL, JS_NewCFunction(ctx, ClearInterval, CLEAR_INTERVAL, 1));
482 JS_FreeValue(ctx, globalObj);
483 }
484
InitSyscapModule(JSContext * ctx)485 void ModuleManager::InitSyscapModule(JSContext* ctx)
486 {
487 JSValue globalObj = JS_GetGlobalObject(ctx);
488 JS_SetPropertyStr(ctx, globalObj, CAN_IUSE, JS_NewCFunction(ctx, CanIUse, CAN_IUSE, 1));
489 JS_FreeValue(ctx, globalObj);
490 }
491
492 } // namespace OHOS::Ace::Framework
493