• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "frameworks/bridge/declarative_frontend/engine/v8/v8_declarative_engine.h"
17 
18 #include <dirent.h>
19 #include <dlfcn.h>
20 #include <fstream>
21 #include <streambuf>
22 #include <unistd.h>
23 
24 #include "native_engine/impl/v8/v8_native_engine.h"
25 #include "base/i18n/localization.h"
26 #include "base/json/json_util.h"
27 #include "base/log/ace_trace.h"
28 #include "base/log/event_report.h"
29 #include "base/utils/system_properties.h"
30 #include "base/utils/time_util.h"
31 #include "core/common/thread_checker.h"
32 #include "frameworks/bridge/common/dom/dom_type.h"
33 #include "frameworks/bridge/common/utils/utils.h"
34 #include "frameworks/bridge/common/utils/v8/v8_helper.h"
35 #include "frameworks/bridge/declarative_frontend/engine/bindings_implementation.h"
36 #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h"
37 #include "frameworks/bridge/declarative_frontend/engine/js_types.h"
38 #include "frameworks/bridge/declarative_frontend/engine/v8/v8_bindings.h"
39 #include "frameworks/bridge/declarative_frontend/engine/v8/v8_declarative_group_js_bridge.h"
40 #include "frameworks/bridge/declarative_frontend/engine/v8/v8_function_destroy_helper.h"
41 #include "frameworks/bridge/declarative_frontend/engine/v8/v8_module_manager.h"
42 #include "frameworks/bridge/declarative_frontend/engine/v8/v8_types.h"
43 #include "frameworks/bridge/declarative_frontend/jsview/js_view_register.h"
44 #include "frameworks/bridge/declarative_frontend/jsview/js_xcomponent.h"
45 #include "frameworks/bridge/js_frontend/engine/common/js_api_perf.h"
46 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
47 #include "frameworks/bridge/js_frontend/engine/common/runtime_constants.h"
48 #include "frameworks/core/common/ace_view.h"
49 #include "frameworks/core/common/container.h"
50 #include "frameworks/core/components/xcomponent/xcomponent_component_client.h"
51 
52 extern const char _binary_stateMgmt_js_start[];
53 extern const char _binary_stateMgmt_js_end[];
54 extern const char _binary_jsEnumStyle_js_start[];
55 extern const char _binary_jsEnumStyle_js_end[];
56 
57 namespace OHOS::Ace::Framework {
58 namespace {
59 
60 constexpr int32_t V8_MAX_STACK_SIZE = 1 * 1024 * 1024;
61 void* g_debugger = nullptr;
62 using StartDebug = void (*)(
63     const std::unique_ptr<v8::Platform>& platform, const v8::Local<v8::Context>& context, std::string componentName,
64     const bool isDebugMode, const int32_t instanceId);
65 using WaitingForIde = void (*)();
66 using StopDebug = void (*)();
67 
CallEvalBuf(v8::Isolate * isolate,const char * src,int32_t length=-1,const char * filename=nullptr)68 bool CallEvalBuf(v8::Isolate* isolate, const char* src, int32_t length = -1, const char* filename = nullptr)
69 {
70     CHECK_RUN_ON(JS);
71     ACE_DCHECK(isolate);
72     v8::HandleScope handleScope(isolate);
73     auto context = isolate->GetCurrentContext();
74     if (context.IsEmpty()) {
75         LOGE("CallEvalBuf, CurrentContext is empty!");
76         return false;
77     }
78     v8::TryCatch tryCatch(isolate);
79     if (src == nullptr || src[0] == '\0') {
80         LOGE("src is null");
81         return false;
82     }
83 
84     const char* origin = filename;
85     if (!origin) {
86         origin = "<anonymous>";
87     }
88 
89     v8::ScriptOrigin scriptOrigin(v8::String::NewFromUtf8(isolate, origin).ToLocalChecked());
90 
91     v8::Local<v8::String> source =
92         v8::String::NewFromUtf8(isolate, src, v8::NewStringType::kNormal, length).ToLocalChecked();
93     v8::Local<v8::Script> script;
94     if (!v8::Script::Compile(context, source, &scriptOrigin).ToLocal(&script)) {
95         LOGE("Compilation failed");
96         V8Utils::JsStdDumpErrorAce(isolate, &tryCatch);
97         return false;
98     }
99 
100     v8::Local<v8::Value> res;
101     if (!script->Run(context).ToLocal(&res)) {
102         LOGE("Run failed");
103         V8Utils::JsStdDumpErrorAce(isolate, &tryCatch);
104         return false;
105     }
106     return true;
107 }
108 
ParseLogContent(const std::vector<std::string> & params)109 std::string ParseLogContent(const std::vector<std::string>& params)
110 {
111     std::string ret;
112     if (params.empty()) {
113         return ret;
114     }
115     std::string formatStr = params[0];
116     int32_t size = params.size();
117     int32_t len = formatStr.size();
118     int32_t pos = 0;
119     int32_t count = 1;
120     for (; pos < len; ++pos) {
121         if (count >= size) {
122             break;
123         }
124         if (formatStr[pos] == '%') {
125             if (pos + 1 >= len) {
126                 break;
127             }
128             switch (formatStr[pos + 1]) {
129                 case 's':
130                 case 'j':
131                 case 'd':
132                 case 'O':
133                 case 'o':
134                 case 'i':
135                 case 'f':
136                 case 'c':
137                     ret += params[count++];
138                     ++pos;
139                     break;
140                 case '%':
141                     ret += formatStr[pos];
142                     ++pos;
143                     break;
144                 default:
145                     ret += formatStr[pos];
146                     break;
147             }
148         } else {
149             ret += formatStr[pos];
150         }
151     }
152     if (pos < len) {
153         ret += formatStr.substr(pos, len - pos);
154     }
155     return ret;
156 }
157 
GetLogLevelAndContent(const v8::FunctionCallbackInfo<v8::Value> & args,JsLogLevel & logLevel,std::string & content)158 void GetLogLevelAndContent(const v8::FunctionCallbackInfo<v8::Value>& args, JsLogLevel& logLevel, std::string& content)
159 {
160     v8::Isolate* isolate = args.GetIsolate();
161     ACE_DCHECK(isolate);
162     v8::Isolate::Scope isolateScope(isolate);
163     v8::HandleScope handleScope(isolate);
164     auto context = isolate->GetCurrentContext();
165     if (context.IsEmpty() || args.Length() == 0) {
166         LOGE("Get LogLevel and Content, context is empty");
167         return;
168     }
169     if (args.Length() == 1) {
170         v8::Local<v8::Value> str;
171         if (args[0]->ToString(context).ToLocal(&str)) {
172             v8::String::Utf8Value utf8(isolate, str);
173             if (*utf8) {
174                 content += *utf8;
175             }
176         } else {
177             content += "Error converting argument 1";
178         }
179     } else {
180         std::vector<std::string> params;
181         for (int32_t i = 0; i < args.Length(); i++) {
182             v8::Local<v8::Value> str;
183             if (args[i]->ToString(context).ToLocal(&str)) {
184                 v8::String::Utf8Value utf8(isolate, str);
185                 if (*utf8) {
186                     params.emplace_back(*utf8);
187                 }
188             }
189         }
190         content = ParseLogContent(params);
191     }
192     logLevel = static_cast<JsLogLevel>(args.Data()->Int32Value(context).ToChecked());
193 }
194 
AppLogPrint(const v8::FunctionCallbackInfo<v8::Value> & args)195 void AppLogPrint(const v8::FunctionCallbackInfo<v8::Value>& args)
196 {
197     JsLogLevel logLevel = JsLogLevel::INFO;
198     std::string fullString;
199     GetLogLevelAndContent(args, logLevel, fullString);
200     switch (logLevel) {
201         case JsLogLevel::DEBUG:
202             APP_LOGD("app Log: %{public}s", fullString.c_str());
203             break;
204         case JsLogLevel::INFO:
205             APP_LOGI("app Log: %{public}s", fullString.c_str());
206             break;
207         case JsLogLevel::WARNING:
208             APP_LOGW("app Log: %{public}s", fullString.c_str());
209             break;
210         case JsLogLevel::ERROR:
211             APP_LOGE("app Log: %{public}s", fullString.c_str());
212             break;
213     }
214 }
215 
JsLogPrint(const v8::FunctionCallbackInfo<v8::Value> & args)216 void JsLogPrint(const v8::FunctionCallbackInfo<v8::Value>& args)
217 {
218     JsLogLevel logLevel = JsLogLevel::INFO;
219     std::string fullString;
220     GetLogLevelAndContent(args, logLevel, fullString);
221     switch (logLevel) {
222         case JsLogLevel::DEBUG:
223             LOGD("ace Log: %{public}s", fullString.c_str());
224             break;
225         case JsLogLevel::INFO:
226             LOGI("ace Log: %{public}s", fullString.c_str());
227             break;
228         case JsLogLevel::WARNING:
229             LOGW("ace Log: %{public}s", fullString.c_str());
230             break;
231         case JsLogLevel::ERROR:
232             LOGE("ace Log: %{public}s", fullString.c_str());
233             break;
234     }
235 }
236 
JsPerfEnd(const v8::FunctionCallbackInfo<v8::Value> & args)237 void JsPerfEnd(const v8::FunctionCallbackInfo<v8::Value>& args)
238 {
239     LOGD("Enter JsPerfEnd");
240     if (args.Length() != PERF_ARGS_LEN) {
241         LOGE("argc error, argc = %{private}d", args.Length());
242         return;
243     }
244 
245     v8::Isolate* isolate = args.GetIsolate();
246     ACE_DCHECK(isolate);
247     v8::HandleScope handleScope(isolate);
248     auto context = isolate->GetCurrentContext();
249     if (context.IsEmpty()) {
250         LOGE("JsPerfEnd, CurrentContext is empty!");
251         return;
252     }
253 
254     v8::String::Utf8Value jsMethodName(isolate, args[PERF_ARGS_METHOD_IDX]);
255     if (!(*jsMethodName)) {
256         return;
257     }
258     std::string methodName(*jsMethodName);
259 
260     int64_t currentTime = GetMicroTickCount();
261     JsApiPerf::GetInstance().InsertJsEndLog(methodName, currentTime);
262 }
263 
JsPerfBegin(const v8::FunctionCallbackInfo<v8::Value> & args)264 void JsPerfBegin(const v8::FunctionCallbackInfo<v8::Value>& args)
265 {
266     LOGD("Enter JsPerfEnd");
267     if (args.Length() != PERF_ARGS_LEN) {
268         LOGE("argc error, argc = %{private}d", args.Length());
269         return;
270     }
271 
272     v8::Isolate* isolate = args.GetIsolate();
273     ACE_DCHECK(isolate);
274     v8::HandleScope handleScope(isolate);
275     auto context = isolate->GetCurrentContext();
276     if (context.IsEmpty()) {
277         LOGE("JsPerfBegin, CurrentContext is empty!");
278         return;
279     }
280 
281     v8::String::Utf8Value jsMethodName(isolate, args[PERF_ARGS_METHOD_IDX]);
282     if (!(*jsMethodName)) {
283         return;
284     }
285     std::string methodName(*jsMethodName);
286 
287     int64_t currentTime = GetMicroTickCount();
288     JsApiPerf::GetInstance().InsertJsBeginLog(methodName, currentTime);
289 }
290 
JsPerfSleep(const v8::FunctionCallbackInfo<v8::Value> & args)291 void JsPerfSleep(const v8::FunctionCallbackInfo<v8::Value>& args)
292 {
293     LOGD("Enter JsPerfEnd");
294     if (args.Length() != 1) {
295         LOGE("argc error, argc = %{private}d", args.Length());
296         return;
297     }
298 
299     v8::Isolate* isolate = args.GetIsolate();
300     ACE_DCHECK(isolate);
301     v8::HandleScope handleScope(isolate);
302     auto context = isolate->GetCurrentContext();
303     if (context.IsEmpty()) {
304         LOGE("CurrentContext is empty!");
305         return;
306     }
307 
308     int32_t valInt = args[0]->Int32Value(context).ToChecked();
309     usleep(valInt);
310 }
311 
JsPerfPrint(const v8::FunctionCallbackInfo<v8::Value> & args)312 void JsPerfPrint(const v8::FunctionCallbackInfo<v8::Value>& args)
313 {
314     v8::Isolate* isolate = args.GetIsolate();
315     ACE_DCHECK(isolate);
316 
317     v8::HandleScope handleScope(isolate);
318     auto context = isolate->GetCurrentContext();
319     if (context.IsEmpty()) {
320         LOGE("JsPerfPrint, CurrentContext is empty!");
321         return;
322     }
323 
324     // return the result
325     std::string ret = JsApiPerf::GetInstance().PrintToLogs();
326     v8::Local<v8::String> dataValue = v8::String::NewFromUtf8(isolate, ret.c_str()).ToLocalChecked();
327     args.GetReturnValue().Set(dataValue);
328 }
329 
330 } // namespace
331 
332 thread_local IsolateWrapper V8DeclarativeEngineInstance::isolate_;
333 
GetCurrentPage()334 RefPtr<JsAcePage> V8DeclarativeEngineInstance::GetCurrentPage()
335 {
336     LOGD("Enter GetRunningPage");
337     v8::Isolate* isolate = v8::Isolate::GetCurrent();
338     ACE_DCHECK(isolate);
339     auto stagingPage = static_cast<RefPtr<JsAcePage>*>(isolate->GetData(V8DeclarativeEngineInstance::STAGING_PAGE));
340     return *stagingPage;
341 }
342 
GetRunningPage(v8::Isolate * isolate)343 RefPtr<JsAcePage> V8DeclarativeEngineInstance::GetRunningPage(v8::Isolate* isolate)
344 {
345     LOGD("Enter GetRunningPage");
346     ACE_DCHECK(isolate);
347     auto runningPage = static_cast<RefPtr<JsAcePage>*>(isolate->GetData(V8DeclarativeEngineInstance::RUNNING_PAGE));
348     return *runningPage;
349 }
350 
GetStagingPage(v8::Isolate * isolate)351 RefPtr<JsAcePage> V8DeclarativeEngineInstance::GetStagingPage(v8::Isolate* isolate)
352 {
353     LOGD("Enter GetStagingPage");
354     ACE_DCHECK(isolate);
355     auto stagingPage = static_cast<RefPtr<JsAcePage>*>(isolate->GetData(V8DeclarativeEngineInstance::STAGING_PAGE));
356     return *stagingPage;
357 }
358 
TriggerPageUpdate()359 void V8DeclarativeEngineInstance::TriggerPageUpdate()
360 {
361     v8::Isolate* isolate = v8::Isolate::GetCurrent();
362     ACE_DCHECK(isolate);
363     auto delegate =
364         static_cast<RefPtr<FrontendDelegate>*>(isolate->GetData(V8DeclarativeEngineInstance::FRONTEND_DELEGATE));
365     auto pipelineContext = (*delegate)->GetPipelineContext();
366     pipelineContext->AddPageUpdateTask([] {});
367 }
368 
PostJsTask(std::function<void ()> && task)369 void V8DeclarativeEngineInstance::PostJsTask(std::function<void()>&& task)
370 {
371     v8::Isolate* isolate = v8::Isolate::GetCurrent();
372     ACE_DCHECK(isolate);
373     auto delegate =
374         static_cast<RefPtr<FrontendDelegate>*>(isolate->GetData(V8DeclarativeEngineInstance::FRONTEND_DELEGATE));
375     (*delegate)->PostJsTask(std::move(task));
376 }
377 
GetPipelineContext()378 RefPtr<PipelineContext> V8DeclarativeEngineInstance::GetPipelineContext()
379 {
380     v8::Isolate* isolate = v8::Isolate::GetCurrent();
381     ACE_DCHECK(isolate);
382     auto delegate =
383         static_cast<RefPtr<FrontendDelegate>*>(isolate->GetData(V8DeclarativeEngineInstance::FRONTEND_DELEGATE));
384     return (*delegate)->GetPipelineContext();
385 }
386 
FlushCommandBuffer(void * context,const std::string & command)387 void V8DeclarativeEngineInstance::FlushCommandBuffer(void* context, const std::string& command)
388 {
389     LOGI("flush command buffer");
390     auto v8Context = *(static_cast<v8::Local<v8::Context>*>(context));
391     v8::Isolate* isolate = v8Context->GetIsolate();
392     ACE_DCHECK(isolate);
393     bool result = CallEvalBuf(isolate, command.c_str());
394     if (!result) {
395         LOGE("failed to flush command");
396     }
397 }
CallJs(v8::Isolate * isolate,v8::Persistent<v8::Context,v8::CopyablePersistentTraits<v8::Context>> pcontext,const std::string & callbackId,const std::string & args,bool keepAlive,bool isGlobal)398 void V8DeclarativeEngineInstance::CallJs(v8::Isolate* isolate,
399     v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>> pcontext, const std::string& callbackId,
400     const std::string& args, bool keepAlive, bool isGlobal)
401 {
402     CHECK_RUN_ON(JS);
403     LOGD("Enter CallJs");
404     std::string keepAliveStr = keepAlive ? "true" : "false";
405     std::string callBuff = std::string("[{\"args\": [\"")
406                                .append(callbackId)
407                                .append("\",")
408                                .append(args)
409                                .append(",")
410                                .append(keepAliveStr)
411                                .append("], \"method\":\"callback\"}]");
412     LOGD("CallJs string: %{private}s", callBuff.c_str());
413 
414     ACE_DCHECK(isolate);
415     v8::HandleScope handleScope(isolate);
416     v8::Local<v8::Context> context = pcontext.Get(isolate);
417     if (context.IsEmpty()) {
418         LOGE("CallJs, context Is Empty");
419         return;
420     }
421 
422     v8::Context::Scope contextScope(context);
423     v8::Local<v8::Object> global = context->Global();
424     v8::Local<v8::String> funcName = v8::String::NewFromUtf8(isolate, "callJS").ToLocalChecked();
425     v8::Local<v8::Value> jsFuncVal;
426     bool succ = global->Get(context, funcName).ToLocal(&jsFuncVal);
427     if (!succ) {
428         LOGE("cannot find 'callJS' function from global object, this should not happen!");
429         return;
430     }
431 
432     v8::Local<v8::Function> jsFunc = v8::Local<v8::Function>::Cast(jsFuncVal);
433 
434     auto runningPage = static_cast<RefPtr<JsAcePage>*>(isolate->GetData(V8DeclarativeEngineInstance::RUNNING_PAGE));
435     int32_t instanceId = isGlobal ? DEFAULT_APP_ID : (*runningPage)->GetPageId();
436 
437     v8::Local<v8::String> callBufStr = v8::String::NewFromUtf8(isolate, callBuff.c_str()).ToLocalChecked();
438     v8::Local<v8::Value> jsonBuf;
439     if (!v8::JSON::Parse(context, callBufStr).ToLocal(&jsonBuf)) {
440         LOGE("Cannot parse callBuf to json format correctly, CallJs stop!");
441         return;
442     }
443     v8::Local<v8::Value> argv[] = { v8::Integer::New(isolate, instanceId), jsonBuf };
444     int32_t len = sizeof(argv) / sizeof(argv[0]);
445     v8::Local<v8::Value> res;
446     succ = jsFunc->Call(context, global, len, argv).ToLocal(&res);
447     if (succ) {
448         LOGD("func callJs success!");
449     } else {
450         LOGD("func callJs fail!");
451     }
452 
453     while (v8::platform::PumpMessageLoop(V8DeclarativeEngine::GetPlatform().get(), isolate)) {
454         continue;
455     }
456 }
457 
458 std::map<std::string, std::string> V8DeclarativeEngineInstance::mediaResourceFileMap_;
459 
460 std::unique_ptr<JsonValue> V8DeclarativeEngineInstance::currentConfigResourceData_;
461 
InitJSEnv()462 bool V8DeclarativeEngineInstance::InitJSEnv()
463 {
464     CHECK_RUN_ON(JS);
465     LOGI("Enter InitJSEnv");
466 
467     // create Isolate
468     create_params_.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
469     isolate_.Wrap(v8::Isolate::New(create_params_));
470     if (isolate_.IsEmpty()) {
471         EventInfo eventInfo;
472         eventInfo.eventType = EXCEPTION_JS;
473         eventInfo.errorType = static_cast<int32_t>(JsExcepType::JS_RUNTIME_OBJ_ERR);
474         EventReport::SendEvent(eventInfo);
475         LOGE("JS Engine cannot allocate JS runtime");
476         return false;
477     }
478 
479     isolate_->SetStackLimit(V8_MAX_STACK_SIZE);
480     isolate_->SetData(V8DeclarativeEngineInstance::FRONTEND_DELEGATE, static_cast<void*>(&frontendDelegate_));
481     isolate_->SetData(V8DeclarativeEngineInstance::RUNNING_PAGE, static_cast<void*>(&runningPage_));
482     isolate_->SetData(V8DeclarativeEngineInstance::STAGING_PAGE, static_cast<void*>(&stagingPage_));
483     isolate_->SetData(V8DeclarativeEngineInstance::DISPATCHER, static_cast<void*>(&dispatcher_));
484     isolate_->SetCaptureStackTraceForUncaughtExceptions(true);
485     // create context
486     InitJSContext();
487     return true;
488 }
489 
InitJSContext()490 void V8DeclarativeEngineInstance::InitJSContext()
491 {
492     CHECK_RUN_ON(JS);
493     LOGI("Enter InitJSContext");
494     v8::Isolate::Scope isolateScope(isolate_.Get());
495     v8::HandleScope handleScope(isolate_.Get());
496 
497     InitGlobalObjectTemplate();
498 
499     v8::Local<v8::Context> localContext =
500         v8::Context::New(isolate_.Get(), nullptr, globalObjectTemplate_.Get(isolate_.Get()));
501 
502     v8::Context::Scope contextScope(localContext);
503 
504     InitJsConsoleObject(localContext, isolate_.Get());
505     InitJsPerfUtilObject(localContext);
506     InitJsNativeModuleObject(localContext);
507     InitJsExportsUtilObject(localContext);
508 
509     LOGE("Loading State Mgmt JS lib for full and partial update combined");
510     InitAceModules(_binary_stateMgmt_js_start, _binary_stateMgmt_js_end, isolate_.Get());
511 
512     InitAceModules(_binary_jsEnumStyle_js_start, _binary_jsEnumStyle_js_end, isolate_.Get());
513 
514     auto groupJsBridge = DynamicCast<V8DeclarativeGroupJsBridge>(frontendDelegate_->GetGroupJsBridge());
515     if (groupJsBridge == nullptr || groupJsBridge->InitializeGroupJsBridge(localContext) == JS_CALL_FAIL) {
516         LOGE("JS Engine Initialize GroupJsBridge failed!");
517         EventReport::SendJsException(JsExcepType::JS_ENGINE_INIT_ERR);
518     }
519 
520     context_.Reset(isolate_.Get(), localContext);
521 
522     // load resourceConfig
523     currentConfigResourceData_ = JsonUtil::CreateArray(true);
524     frontendDelegate_->LoadResourceConfiguration(mediaResourceFileMap_, currentConfigResourceData_);
525 }
526 
InitAceModules(const char * start,const char * end,v8::Isolate * isolate)527 void V8DeclarativeEngineInstance::InitAceModules(const char* start, const char* end, v8::Isolate* isolate)
528 {
529     if (start == nullptr || end == nullptr) {
530         LOGE("Failed to init Ace modules, start or end can not be null!");
531         return;
532     }
533     bool evalAceModule = CallEvalBuf(isolate, start, end - start);
534     if (!evalAceModule) {
535         EventInfo eventInfo;
536         eventInfo.eventType = EXCEPTION_JS;
537         eventInfo.errorType = static_cast<int32_t>(JsExcepType::JS_CONTEXT_INIT_ERR);
538         EventReport::SendEvent(eventInfo);
539         LOGE("JS Engine created JS context but failed to init Ace modules!");
540     }
541 }
542 
InitJsConsoleObject(v8::Local<v8::Context> & localContext,v8::Isolate * isolate)543 void V8DeclarativeEngineInstance::InitJsConsoleObject(v8::Local<v8::Context>& localContext, v8::Isolate* isolate)
544 {
545     v8::Local<v8::Object> global = localContext->Global();
546     // app log method
547     v8::Local<v8::Value> console =
548         global->Get(localContext, v8::String::NewFromUtf8(isolate, "console").ToLocalChecked()).ToLocalChecked();
549     v8::Local<v8::Object> consoleObj = console->ToObject(localContext).ToLocalChecked();
550     consoleObj
551         ->Set(localContext, v8::String::NewFromUtf8(isolate, "log").ToLocalChecked(),
552             v8::Function::New(
553                 localContext, AppLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::INFO)))
554                 .ToLocalChecked())
555         .ToChecked();
556     consoleObj
557         ->Set(localContext, v8::String::NewFromUtf8(isolate, "debug").ToLocalChecked(),
558             v8::Function::New(
559                 localContext, AppLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::DEBUG)))
560                 .ToLocalChecked())
561         .ToChecked();
562     consoleObj
563         ->Set(localContext, v8::String::NewFromUtf8(isolate, "info").ToLocalChecked(),
564             v8::Function::New(
565                 localContext, AppLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::INFO)))
566                 .ToLocalChecked())
567         .ToChecked();
568     consoleObj
569         ->Set(localContext, v8::String::NewFromUtf8(isolate, "warn").ToLocalChecked(),
570             v8::Function::New(
571                 localContext, AppLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::WARNING)))
572                 .ToLocalChecked())
573         .ToChecked();
574     consoleObj
575         ->Set(localContext, v8::String::NewFromUtf8(isolate, "error").ToLocalChecked(),
576             v8::Function::New(
577                 localContext, AppLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::ERROR)))
578                 .ToLocalChecked())
579         .ToChecked();
580     // js framework log method
581     auto aceConsoleObj = v8::Object::New(isolate);
582     global->Set(localContext, v8::String::NewFromUtf8(isolate, "aceConsole").ToLocalChecked(), aceConsoleObj)
583         .ToChecked();
584     aceConsoleObj
585         ->Set(localContext, v8::String::NewFromUtf8(isolate, "log").ToLocalChecked(),
586             v8::Function::New(
587                 localContext, JsLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::INFO)))
588                 .ToLocalChecked())
589         .ToChecked();
590     aceConsoleObj
591         ->Set(localContext, v8::String::NewFromUtf8(isolate, "debug").ToLocalChecked(),
592             v8::Function::New(
593                 localContext, JsLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::DEBUG)))
594                 .ToLocalChecked())
595         .ToChecked();
596     aceConsoleObj
597         ->Set(localContext, v8::String::NewFromUtf8(isolate, "info").ToLocalChecked(),
598             v8::Function::New(
599                 localContext, JsLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::INFO)))
600                 .ToLocalChecked())
601         .ToChecked();
602     aceConsoleObj
603         ->Set(localContext, v8::String::NewFromUtf8(isolate, "warn").ToLocalChecked(),
604             v8::Function::New(
605                 localContext, JsLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::WARNING)))
606                 .ToLocalChecked())
607         .ToChecked();
608     aceConsoleObj
609         ->Set(localContext, v8::String::NewFromUtf8(isolate, "error").ToLocalChecked(),
610             v8::Function::New(
611                 localContext, JsLogPrint, v8::Integer::New(isolate, static_cast<int32_t>(JsLogLevel::ERROR)))
612                 .ToLocalChecked())
613         .ToChecked();
614 }
615 
InitJsPerfUtilObject(v8::Local<v8::Context> & localContext)616 void V8DeclarativeEngineInstance::InitJsPerfUtilObject(v8::Local<v8::Context>& localContext)
617 {
618     v8::Local<v8::Object> global = localContext->Global();
619 
620     auto perfUtilObj = v8::Object::New(isolate_.Get());
621     global->Set(localContext, v8::String::NewFromUtf8(isolate_.Get(), "perfutil").ToLocalChecked(), perfUtilObj)
622         .ToChecked();
623     perfUtilObj
624         ->Set(localContext, v8::String::NewFromUtf8(isolate_.Get(), "printlog").ToLocalChecked(),
625             v8::Function::New(localContext, JsPerfPrint).ToLocalChecked())
626         .ToChecked();
627     perfUtilObj
628         ->Set(localContext, v8::String::NewFromUtf8(isolate_.Get(), "sleep").ToLocalChecked(),
629             v8::Function::New(localContext, JsPerfSleep).ToLocalChecked())
630         .ToChecked();
631     perfUtilObj
632         ->Set(localContext, v8::String::NewFromUtf8(isolate_.Get(), "begin").ToLocalChecked(),
633             v8::Function::New(localContext, JsPerfBegin).ToLocalChecked())
634         .ToChecked();
635     perfUtilObj
636         ->Set(localContext, v8::String::NewFromUtf8(isolate_.Get(), "end").ToLocalChecked(),
637             v8::Function::New(localContext, JsPerfEnd).ToLocalChecked())
638         .ToChecked();
639 }
640 
641 thread_local std::unordered_map<int32_t, CopyablePersistent<v8::Object>>
642     V8DeclarativeEngineInstance::persistentRootViewMap_;
643 
PersistRootViewHandle(v8::Isolate * isolate,v8::Local<v8::Object> obj)644 void V8DeclarativeEngineInstance::PersistRootViewHandle(v8::Isolate* isolate, v8::Local<v8::Object> obj)
645 {
646     V8DeclarativeEngineInstance::persistentRootViewMap_.emplace(
647         V8DeclarativeEngineInstance::GetStagingPage(isolate)->GetPageId(),
648         CopyablePersistent<v8::Object>(isolate, obj));
649 }
650 
DestroyPersistRootViewHandle(int32_t pageId)651 void V8DeclarativeEngineInstance::DestroyPersistRootViewHandle(int32_t pageId)
652 {
653     CHECK_RUN_ON(JS);
654     if (V8DeclarativeEngineInstance::persistentRootViewMap_.count(pageId) != 0) {
655         v8::Isolate* isolate = GetV8Isolate();
656         ACE_DCHECK(isolate);
657         v8::Isolate::Scope isolateScope(isolate);
658         v8::HandleScope handleScope(isolate);
659         CopyablePersistent<v8::Object> rootView = V8DeclarativeEngineInstance::persistentRootViewMap_[pageId];
660         if (!rootView.IsEmpty()) {
661             v8::Local<v8::Object> previousRootObj = rootView.Get(isolate);
662             JSView* previousView = static_cast<JSView*>(previousRootObj->GetAlignedPointerFromInternalField(0));
663             previousView->Destroy(nullptr);
664         }
665         rootView.Reset();
666 
667         V8DeclarativeEngineInstance::persistentRootViewMap_.erase(pageId);
668     }
669 }
670 
DestroyAllPersistRootViewHandle()671 void V8DeclarativeEngineInstance::DestroyAllPersistRootViewHandle()
672 {
673     CHECK_RUN_ON(JS);
674     if (persistentRootViewMap_.size() > 0) {
675         LOGI("DestroyAllPersistRootViewHandle release left %zu views ", persistentRootViewMap_.size());
676     }
677     for (const auto& pair : persistentRootViewMap_) {
678         v8::Isolate* isolate = GetV8Isolate();
679         ACE_DCHECK(isolate);
680         v8::Isolate::Scope isolateScope(isolate);
681         v8::HandleScope handleScope(isolate);
682         CopyablePersistent<v8::Object> rootView = pair.second;
683         if (!rootView.IsEmpty()) {
684             v8::Local<v8::Object> previousRootObj = rootView.Get(isolate);
685             JSView* previousView = static_cast<JSView*>(previousRootObj->GetAlignedPointerFromInternalField(0));
686             previousView->Destroy(nullptr);
687         }
688         rootView.Reset();
689     }
690     persistentRootViewMap_.clear();
691 }
692 
RequireNativeModule(const v8::FunctionCallbackInfo<v8::Value> & args)693 void RequireNativeModule(const v8::FunctionCallbackInfo<v8::Value>& args)
694 {
695     v8::Isolate* isolate = args.GetIsolate();
696     v8::HandleScope handleScope(isolate);
697     auto localContext = isolate->GetCurrentContext();
698     if (localContext.IsEmpty()) {
699         LOGE("context is empty!");
700         return;
701     }
702     v8::String::Utf8Value value(isolate, args[0]->ToString(localContext).ToLocalChecked());
703     if (!(*value)) {
704         return;
705     }
706     std::string moduleName(*value);
707 
708     // init method
709     v8::Local<v8::Object> global = localContext->Global();
710     v8::Local<v8::Value> moduleObj =
711         global->Get(localContext, v8::String::NewFromUtf8(isolate, moduleName.c_str()).ToLocalChecked())
712             .ToLocalChecked();
713     if (!moduleObj->IsUndefined()) {
714         args.GetReturnValue().Set(moduleObj);
715         return;
716     }
717 
718     auto newObj = v8::Object::New(isolate);
719     if (ModuleManager::GetInstance()->InitModule(newObj, moduleName, isolate)) {
720         global->Set(localContext, v8::String::NewFromUtf8(isolate, moduleName.c_str()).ToLocalChecked(), newObj)
721             .ToChecked();
722         args.GetReturnValue().Set(newObj);
723     }
724 }
725 
InitJsNativeModuleObject(v8::Local<v8::Context> & localContext)726 void V8DeclarativeEngineInstance::InitJsNativeModuleObject(v8::Local<v8::Context>& localContext)
727 {
728     v8::Local<v8::Object> global = localContext->Global();
729 
730     global
731         ->Set(localContext, v8::String::NewFromUtf8(isolate_.Get(), "requireNativeModule").ToLocalChecked(),
732             v8::Function::New(localContext, RequireNativeModule).ToLocalChecked())
733         .ToChecked();
734 
735     ModuleManager::GetInstance()->InitTimerModule(localContext);
736 }
737 
InitJsExportsUtilObject(v8::Local<v8::Context> & localContext)738 void V8DeclarativeEngineInstance::InitJsExportsUtilObject(v8::Local<v8::Context>& localContext)
739 {
740     v8::Local<v8::Object> global = localContext->Global();
741 
742     auto exportsUtilObj = v8::Object::New(isolate_.Get());
743     global->Set(localContext, v8::String::NewFromUtf8(isolate_.Get(), "exports").ToLocalChecked(), exportsUtilObj)
744         .ToChecked();
745 }
746 
InitGlobalObjectTemplate()747 void V8DeclarativeEngineInstance::InitGlobalObjectTemplate()
748 {
749     v8::Isolate::Scope isolateScope(isolate_.Get());
750     v8::HandleScope handleScope(isolate_.Get());
751     v8::Local<v8::ObjectTemplate> globalObj = v8::ObjectTemplate::New(isolate_.Get());
752     JsRegisterViews(globalObj);
753 
754     globalObjectTemplate_.Reset(isolate_.Get(), globalObj);
755 }
756 
FireJsEvent(const std::string & param)757 bool V8DeclarativeEngineInstance::FireJsEvent(const std::string& param)
758 {
759     return true;
760 }
761 
GetI18nStringResource(const std::string & targetStringKey,const std::string & targetStringValue)762 std::unique_ptr<JsonValue> V8DeclarativeEngineInstance::GetI18nStringResource(
763     const std::string& targetStringKey, const std::string& targetStringValue)
764 {
765     auto resourceI18nFileNum = currentConfigResourceData_->GetArraySize();
766     for (int i = 0; i < resourceI18nFileNum; i++) {
767         auto priorResource = currentConfigResourceData_->GetArrayItem(i);
768         if ((priorResource->Contains(targetStringKey))) {
769             auto valuePair = priorResource->GetValue(targetStringKey);
770             if (valuePair->Contains(targetStringValue)) {
771                 return valuePair->GetValue(targetStringValue);
772             }
773         }
774     }
775 
776     return JsonUtil::Create(true);
777 }
778 
GetMediaResource(const std::string & targetFileName)779 std::string V8DeclarativeEngineInstance::GetMediaResource(const std::string& targetFileName)
780 {
781     auto iter = mediaResourceFileMap_.find(targetFileName);
782 
783     if (iter != mediaResourceFileMap_.end()) {
784         return iter->second;
785     }
786 
787     return std::string();
788 }
789 
~V8DeclarativeEngineInstance()790 V8DeclarativeEngineInstance::~V8DeclarativeEngineInstance()
791 {
792     CHECK_RUN_ON(JS);
793     LOG_DESTROY();
794     DestroyAllPersistRootViewHandle();
795     globalObjectTemplate_.Reset();
796     delete create_params_.array_buffer_allocator;
797 
798     // Destroy group bridge
799     auto groupJsBridge = DynamicCast<V8DeclarativeGroupJsBridge>(frontendDelegate_->GetGroupJsBridge());
800     if (groupJsBridge != nullptr) {
801         groupJsBridge->Destroy(GetV8Isolate());
802     }
803     // Force GC before dispose v8 isolate
804     auto* isolate = isolate_.Get();
805     if (isolate != nullptr) {
806         v8::Isolate::Scope isolateScope(isolate);
807         isolate->LowMemoryNotification();
808     }
809     // delete function template
810     V8FunctionDestroyCallbackHelper::DeleteFunctionTemplate(isolate_.Get());
811     // Just invalidate it, isolate_ will dispose when js-thread finished.
812     ModuleManager::GetInstance()->ClearTimerIsolate(isolate_.Get());
813     isolate_.Invalidate();
814 }
815 
LoadDebuggerSo()816 void LoadDebuggerSo()
817 {
818     LOGI("LoadDebuggerSo");
819     const std::string soDir = "libv8_debugger.z.so";
820     g_debugger = dlopen(soDir.c_str(), RTLD_LAZY);
821     if (g_debugger == nullptr) {
822         LOGE("cannot find debugger so");
823     }
824 }
825 
StartDebuggerAgent(const std::unique_ptr<v8::Platform> & platform,const v8::Local<v8::Context> & context,std::string componentName,const bool isDebugMode,const int32_t instanceId)826 void StartDebuggerAgent(
827     const std::unique_ptr<v8::Platform>& platform, const v8::Local<v8::Context>& context, std::string componentName,
828     const bool isDebugMode, const int32_t instanceId)
829 {
830     LOGI("StartAgent");
831     if (g_debugger == nullptr) {
832         LOGE("g_debugger is null");
833         return;
834     }
835     StartDebug startDebug = (StartDebug)dlsym(g_debugger, "StartDebug");
836     if (startDebug == nullptr) {
837         LOGE("StartDebug=NULL, dlerror=%s", dlerror());
838         return;
839     }
840     startDebug(platform, context, componentName, isDebugMode, instanceId);
841 }
842 
843 // -----------------------
844 // Start V8DeclarativeEngine
845 // -----------------------
846 
GetPlatform()847 std::unique_ptr<v8::Platform>& V8DeclarativeEngine::GetPlatform()
848 {
849     return V8Helper::GetPlatform();
850 }
851 
Initialize(const RefPtr<FrontendDelegate> & delegate)852 bool V8DeclarativeEngine::Initialize(const RefPtr<FrontendDelegate>& delegate)
853 {
854     CHECK_RUN_ON(JS);
855     ACE_SCOPED_TRACE("V8DeclarativeEngine::Initialize");
856     LOGI("V8DeclarativeEngine initialize");
857     ACE_DCHECK(delegate);
858 
859     // Initialize V8 engine
860     GetPlatform();
861 
862     // if load debugger.so successfully, debug mode
863     if (IsDebugVersion()) {
864         if (NeedDebugBreakPoint()) {
865             LOGI("NeedDebugBreakPoint = TRUE");
866         } else {
867             LOGI("NeedDebugBreakPoint = FALSE");
868         }
869         LoadDebuggerSo();
870         LOGI("debug mode in V8DeclarativeEngine");
871     }
872     // Initialize engine instance
873     engineInstance_ = AceType::MakeRefPtr<V8DeclarativeEngineInstance>(delegate);
874     bool res = engineInstance_->InitJSEnv();
875     if (!res) {
876         LOGE("V8DeclarativeEngine initialize failed: %{public}d", instanceId_);
877         return false;
878     }
879 
880     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
881     ACE_DCHECK(isolate);
882     {
883         v8::Isolate::Scope isolateScope(isolate);
884         v8::HandleScope handleScope(isolate);
885         auto context = engineInstance_->GetV8Context();
886         if (context.IsEmpty()) {
887             LOGE("Initialize, context Is Empty");
888             return false;
889         }
890         // debug mode
891         if (g_debugger != nullptr) {
892             std::string instanceName = GetInstanceName();
893             if (instanceName.empty()) {
894                 LOGE("GetInstanceName fail, %s", instanceName.c_str());
895                 return false;
896             }
897             StartDebuggerAgent(GetPlatform(), context, instanceName, NeedDebugBreakPoint(), instanceId_);
898         }
899     }
900     nativeEngine_ =
901         new V8NativeEngine(GetPlatform().get(), isolate, engineInstance_->GetContext(), static_cast<void*>(this));
902     engineInstance_->SetNativeEngine(nativeEngine_);
903     SetPostTask(nativeEngine_);
904 #if !defined(PREVIEW)
905     nativeEngine_->CheckUVLoop();
906 #endif
907     if (delegate && delegate->GetAssetManager()) {
908         std::vector<std::string> packagePath = delegate->GetAssetManager()->GetLibPath();
909         if (!packagePath.empty()) {
910             auto v8NativeEngine = static_cast<V8NativeEngine*>(nativeEngine_);
911             v8NativeEngine->SetPackagePath(packagePath);
912         }
913     }
914     RegisterWorker();
915 
916     return true;
917 }
918 
SetPostTask(NativeEngine * nativeEngine)919 void V8DeclarativeEngine::SetPostTask(NativeEngine* nativeEngine)
920 {
921     LOGI("SetPostTask");
922     auto weakDelegate = AceType::WeakClaim(AceType::RawPtr(engineInstance_->GetDelegate()));
923     auto&& postTask = [weakDelegate, nativeEngine = nativeEngine_, id = instanceId_](bool needSync) {
924         auto delegate = weakDelegate.Upgrade();
925         if (delegate == nullptr) {
926             LOGE("delegate is nullptr");
927             return;
928         }
929         delegate->PostJsTask([nativeEngine, needSync, id]() {
930             if (nativeEngine == nullptr) {
931                 return;
932             }
933             ContainerScope scope(id);
934             nativeEngine->Loop(LOOP_NOWAIT, needSync);
935         });
936     };
937     nativeEngine_->SetPostTask(postTask);
938 }
939 
RegisterInitWorkerFunc()940 void V8DeclarativeEngine::RegisterInitWorkerFunc()
941 {
942     WeakPtr<GroupJsBridge> weakJsBridge = engineInstance_->GetDelegate()->GetGroupJsBridge();
943     auto&& initWorkerFunc = [weakJsBridge, delegate = engineInstance_->GetDelegateForV8Data(),
944         dispatch = engineInstance_->GetJsMessageDispatcherForV8Data()](NativeEngine* nativeEngine) {
945         LOGI("WorkerCore RegisterInitWorkerFunc called");
946         if (nativeEngine == nullptr) {
947             LOGE("nativeEngine is nullptr");
948             return;
949         }
950         auto v8NativeEngine = static_cast<V8NativeEngine*>(nativeEngine);
951         if (v8NativeEngine == nullptr) {
952             LOGE("v8NativeEngine is nullptr");
953             return;
954         }
955         auto isolate = v8NativeEngine->GetIsolate();
956         if (isolate == nullptr) {
957             LOGE("isolate is nullptr");
958             return;
959         }
960 
961         v8::HandleScope handleScope(isolate);
962         v8::Local<v8::Context> localContext = v8NativeEngine->GetContext();
963         isolate->SetStackLimit(V8_MAX_STACK_SIZE);
964         isolate->SetData(V8DeclarativeEngineInstance::DISPATCHER, dispatch);
965         isolate->SetData(V8DeclarativeEngineInstance::FRONTEND_DELEGATE, delegate);
966         V8DeclarativeEngineInstance::InitJsConsoleObject(localContext, isolate);
967         V8DeclarativeEngineInstance::InitAceModules(_binary_jsEnumStyle_js_start, _binary_jsEnumStyle_js_end, isolate);
968         ModuleManager::InitTimerModule(localContext);
969 
970         auto jsBridge = DynamicCast<V8DeclarativeGroupJsBridge>(weakJsBridge.Upgrade());
971         if (jsBridge != nullptr) {
972             jsBridge->AddIsolateNativeEngineRelation(isolate, nativeEngine);
973             auto source = v8::String::NewFromUtf8(isolate, jsBridge->GetJsCode().c_str()).ToLocalChecked();
974             if (!CallEvalBuf(isolate, "var global = globalThis;\n")
975                 || jsBridge->InitializeGroupJsBridge(localContext) == JS_CALL_FAIL
976                 || jsBridge->CallEvalBuf(isolate, source) == JS_CALL_FAIL) {
977                 LOGE("Worker Initialize GroupJsBridge failed!");
978             }
979         } else {
980             LOGE("Worker Initialize GroupJsBridge failed, jsBridge is nullptr");
981         }
982     };
983     nativeEngine_->SetInitWorkerFunc(initWorkerFunc);
984 }
985 
RegisterAssetFunc()986 void V8DeclarativeEngine::RegisterAssetFunc()
987 {
988     auto weakAsset = WeakPtr<AssetManager>(engineInstance_->GetDelegate()->GetAssetManager());
989     auto&& assetFunc = [weakAsset](const std::string& uri, std::vector<uint8_t>& content, std::string& ami) {
990         LOGI("WorkerCore RegisterAssetFunc called");
991         auto asset = weakAsset.Upgrade();
992         if (!asset) {
993             LOGE("delegate is nullptr");
994             return;
995         }
996         FrontendDelegate::GetResourceData(uri, asset, content);
997     };
998     nativeEngine_->SetGetAssetFunc(assetFunc);
999 }
1000 
RegisterOffWorkerFunc()1001 void V8DeclarativeEngine::RegisterOffWorkerFunc()
1002 {
1003     WeakPtr<GroupJsBridge> weakJsBridge = engineInstance_->GetDelegate()->GetGroupJsBridge();
1004     auto&& offWorkerFunc = [weakJsBridge](NativeEngine* nativeEngine) {
1005         LOGI("WorkerCore RegisterOffWorkerFunc called");
1006         if (nativeEngine == nullptr) {
1007             LOGE("nativeEngine is nullptr");
1008             return;
1009         }
1010         auto v8NativeEngine = static_cast<V8NativeEngine*>(nativeEngine);
1011         if (v8NativeEngine == nullptr) {
1012             LOGE("v8NativeEngine is nullptr");
1013             return;
1014         }
1015         auto jsBridge = DynamicCast<V8DeclarativeGroupJsBridge>(weakJsBridge.Upgrade());
1016         if (jsBridge == nullptr) {
1017             LOGE("jsBridge is nullptr");
1018             return;
1019         }
1020         auto isolate = v8NativeEngine->GetIsolate();
1021         if (isolate == nullptr) {
1022             LOGE("isolate is nullptr");
1023             return;
1024         }
1025 
1026         jsBridge->Destroy(isolate, true);
1027     };
1028     nativeEngine_->SetOffWorkerFunc(offWorkerFunc);
1029 }
1030 
RegisterWorker()1031 void V8DeclarativeEngine::RegisterWorker()
1032 {
1033     nativeEngine_->SetWorkerAsyncWorkFunc(V8DeclarativeGroupJsBridge::NativeAsyncExecuteCallback,
1034         V8DeclarativeGroupJsBridge::NativeAsyncCompleteCallback);
1035     RegisterInitWorkerFunc();
1036     RegisterAssetFunc();
1037     RegisterOffWorkerFunc();
1038 }
1039 
~V8DeclarativeEngine()1040 V8DeclarativeEngine::~V8DeclarativeEngine()
1041 {
1042     CHECK_RUN_ON(JS);
1043     if (g_debugger != nullptr) {
1044         StopDebug stopDebug = (StopDebug)dlsym(g_debugger, "StopDebug");
1045         if (stopDebug != nullptr) {
1046             stopDebug();
1047         }
1048     }
1049     LOG_DESTROY();
1050     if (nativeEngine_ != nullptr) {
1051 #if !defined(PREVIEW)
1052         nativeEngine_->CancelCheckUVLoop();
1053 #endif
1054         delete nativeEngine_;
1055     }
1056     if (g_debugger != nullptr) {
1057         dlclose(g_debugger);
1058     }
1059 }
1060 
CallAppFunc(v8::Isolate * isolate,const v8::Local<v8::Context> & context,std::string appFuncName)1061 void V8DeclarativeEngine::CallAppFunc(
1062     v8::Isolate* isolate, const v8::Local<v8::Context>& context, std::string appFuncName)
1063 {
1064     (void)CallAppFunc(isolate, context, appFuncName, 0, nullptr);
1065 }
1066 
CallAppFunc(v8::Isolate * isolate,const v8::Local<v8::Context> & context,std::string appFuncName,int argc,v8::Local<v8::Value> * argv)1067 bool V8DeclarativeEngine::CallAppFunc(v8::Isolate* isolate, const v8::Local<v8::Context>& context,
1068     std::string appFuncName, int argc, v8::Local<v8::Value>* argv)
1069 {
1070     v8::Local<v8::Object> global = context->Global();
1071     v8::Local<v8::String> exportName = v8::String::NewFromUtf8(isolate, "exports").ToLocalChecked();
1072     v8::Local<v8::Value> exportval;
1073     bool succ = global->Get(context, exportName).ToLocal(&exportval);
1074     if (!succ) {
1075         LOGD("no property named \"export\" in global object");
1076         return false;
1077     }
1078     if (!exportval->IsObject()) {
1079         LOGD("property \"exports\" is not a object");
1080         return false;
1081     }
1082 
1083     v8::Local<v8::Object> exportobj = exportval->ToObject(context).ToLocalChecked();
1084     v8::Local<v8::String> defaultName = v8::String::NewFromUtf8(isolate, "default").ToLocalChecked();
1085     v8::Local<v8::Value> defaultval;
1086     succ = exportobj->Get(context, defaultName).ToLocal(&defaultval);
1087     if (!succ) {
1088         LOGD("no property named \"default\" in export object");
1089         return false;
1090     }
1091     if (!defaultval->IsObject()) {
1092         LOGD("property \"defaultval\" is not a object");
1093         return false;
1094     }
1095 
1096     v8::Local<v8::Object> defaultobj = defaultval->ToObject(context).ToLocalChecked();
1097     v8::Local<v8::String> funcName = v8::String::NewFromUtf8(isolate, appFuncName.c_str()).ToLocalChecked();
1098     v8::Local<v8::Value> jsFuncVal;
1099     succ = defaultobj->Get(context, funcName).ToLocal(&jsFuncVal);
1100     if (!succ) {
1101         LOGD("no property named \"%{public}s\" in global object", appFuncName.c_str());
1102         return false;
1103     }
1104     if (!jsFuncVal->IsFunction()) {
1105         LOGD("property \"%{public}s\" is not a function", appFuncName.c_str());
1106         return false;
1107     }
1108 
1109     v8::Local<v8::Function> jsFunc = v8::Local<v8::Function>::Cast(jsFuncVal);
1110     v8::Local<v8::Value> res;
1111     succ = jsFunc->Call(context, defaultobj, argc, argv).ToLocal(&res);
1112     if (!succ) {
1113         LOGD("call failed");
1114         return false;
1115     }
1116     return res->IsTrue();
1117 }
1118 
LoadJs(const std::string & url,const RefPtr<JsAcePage> & page,bool isMainPage)1119 void V8DeclarativeEngine::LoadJs(const std::string& url, const RefPtr<JsAcePage>& page, bool isMainPage)
1120 {
1121     LOGI("Enter LoadJs");
1122     ACE_SCOPED_TRACE("V8DeclarativeEngine::LoadJS");
1123     ACE_DCHECK(engineInstance_);
1124 
1125     if (g_debugger != nullptr) {
1126         WaitingForIde waitingForIde = (WaitingForIde)dlsym(g_debugger, "WaitingForIde");
1127         if (waitingForIde != nullptr) {
1128             waitingForIde();
1129         }
1130     }
1131 
1132     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1133     ACE_DCHECK(isolate);
1134     v8::Isolate::Scope isolateScope(isolate);
1135     v8::HandleScope handleScope(isolate);
1136     auto context = engineInstance_->GetV8Context();
1137     v8::Context::Scope contextScope(context);
1138 
1139     engineInstance_->SetStagingPage(page);
1140     if (isMainPage) {
1141         ACE_DCHECK(!engineInstance_->GetRunningPage());
1142         engineInstance_->SetRunningPage(page);
1143     }
1144 
1145     auto delegate =
1146         static_cast<RefPtr<FrontendDelegate>*>(isolate->GetData(V8DeclarativeEngineInstance::FRONTEND_DELEGATE));
1147     v8::TryCatch tryCatch(isolate);
1148 
1149     if (isMainPage) {
1150         std::string commonsJsContent;
1151         if ((*delegate)->GetAssetContent("commons.js", commonsJsContent)) {
1152             bool commonsJsResult = CallEvalBuf(isolate, commonsJsContent.c_str(), -1, "commons.js");
1153             if (!commonsJsResult) {
1154                 LOGE("fail to execute load commonsjs script");
1155                 return;
1156             }
1157         }
1158         std::string vendorsJsContent;
1159         if ((*delegate)->GetAssetContent("vendors.js", vendorsJsContent)) {
1160             bool vendorsJsResult = CallEvalBuf(isolate, vendorsJsContent.c_str(), -1, "vendors.js");
1161             if (!vendorsJsResult) {
1162                 LOGE("fail to execute load vendorsjs script");
1163                 return;
1164             }
1165         }
1166         std::string appjsContent;
1167         if (!(*delegate)->GetAssetContent("app.js", appjsContent)) {
1168             LOGE("js file load failed!");
1169             return;
1170         }
1171         std::string appMap;
1172         if ((*delegate)->GetAssetContent("app.js.map", appMap)) {
1173             page->SetAppMap(appMap);
1174         } else {
1175             LOGI("app map is missing!");
1176         }
1177         bool result = CallEvalBuf(isolate, appjsContent.c_str(), -1, "app.js");
1178         if (!result) {
1179             LOGE("failed to execute Loadjs script");
1180             return;
1181         }
1182         auto container = Container::Current();
1183         if (container && container->IsMainWindow()) {
1184             CallAppFunc(isolate, context, "onCreate");
1185         }
1186     }
1187 
1188     if (g_debugger != nullptr) {
1189         WaitingForIde waitingForIde = (WaitingForIde)dlsym(g_debugger, "WaitingForIde");
1190         if (waitingForIde != nullptr) {
1191             waitingForIde();
1192         }
1193     }
1194 
1195     std::string jsContent;
1196     LOGI("Enter LoadJs file:%s", url.c_str());
1197     if (!(*delegate)->GetAssetContent(url, jsContent)) {
1198         LOGE("js file load failed!");
1199         return;
1200     }
1201 
1202     std::string jsSourceMap;
1203     if ((*delegate)->GetAssetContent(url + ".map", jsSourceMap)) {
1204         page->SetPageMap(jsSourceMap);
1205     } else {
1206         LOGI("js source map load failed!");
1207     }
1208     bool result = CallEvalBuf(isolate, jsContent.c_str(), -1, url.c_str());
1209     if (!result) {
1210         LOGE("failed to execute Loadjs script");
1211         return;
1212     }
1213 
1214     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1215         continue;
1216     }
1217 }
1218 
UpdateRunningPage(const RefPtr<JsAcePage> & page)1219 void V8DeclarativeEngine::UpdateRunningPage(const RefPtr<JsAcePage>& page)
1220 {
1221     ACE_DCHECK(engineInstance_);
1222     LOGD("Enter UpdateRunningPage %d", page->GetPageId());
1223     engineInstance_->SetRunningPage(page);
1224 }
1225 
UpdateStagingPage(const RefPtr<JsAcePage> & page)1226 void V8DeclarativeEngine::UpdateStagingPage(const RefPtr<JsAcePage>& page)
1227 {
1228     LOGD("Enter UpdateStagingPage %d", page->GetPageId());
1229     ACE_DCHECK(engineInstance_);
1230     engineInstance_->SetStagingPage(page);
1231 }
1232 
ResetStagingPage()1233 void V8DeclarativeEngine::ResetStagingPage()
1234 {
1235     ACE_DCHECK(engineInstance_);
1236     LOGD("Enter ResetStagingPage");
1237     auto runningPage = engineInstance_->GetRunningPage();
1238     engineInstance_->ResetStagingPage(runningPage);
1239 }
1240 
DestroyPageInstance(int32_t pageId)1241 void V8DeclarativeEngine::DestroyPageInstance(int32_t pageId)
1242 {
1243     LOGI("Enter DestroyPageInstance %d", pageId);
1244     ACE_DCHECK(engineInstance_);
1245 
1246     engineInstance_->DestroyPersistRootViewHandle(pageId);
1247 }
1248 
DestroyApplication(const std::string & packageName)1249 void V8DeclarativeEngine::DestroyApplication(const std::string& packageName)
1250 {
1251     LOGI("Enter DestroyApplication: destroy, packageName %{public}s", packageName.c_str());
1252     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1253     ACE_DCHECK(isolate);
1254     v8::HandleScope handleScope(isolate);
1255     v8::Isolate::Scope isolateScope(isolate);
1256     auto context = engineInstance_->GetV8Context();
1257     if (context.IsEmpty()) {
1258         LOGE("Destroy Application, context Is Empty");
1259         return;
1260     }
1261     v8::Context::Scope contextScope(context);
1262 
1263     v8::TryCatch tryCatch(isolate);
1264 
1265     auto container = Container::Current();
1266     if (container && container->IsMainWindow()) {
1267         CallAppFunc(isolate, context, "onDestroy");
1268     }
1269 
1270     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1271         continue;
1272     }
1273 }
1274 
UpdateApplicationState(const std::string & packageName,Frontend::State state)1275 void V8DeclarativeEngine::UpdateApplicationState(const std::string& packageName, Frontend::State state)
1276 {
1277     LOGD("Enter UpdateApplicationState: destroy, packageName %{public}s", packageName.c_str());
1278     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1279     ACE_DCHECK(isolate);
1280     v8::HandleScope handleScope(isolate);
1281     auto context = engineInstance_->GetV8Context();
1282     if (context.IsEmpty()) {
1283         LOGE("Destroy Application, context Is Empty");
1284         return;
1285     }
1286 
1287     if (state == Frontend::State::ON_SHOW) {
1288         CallAppFunc(isolate, context, "onShow");
1289     } else if (state == Frontend::State::ON_HIDE) {
1290         CallAppFunc(isolate, context, "onHide");
1291     }
1292 
1293     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1294         continue;
1295     }
1296 }
1297 
OnWindowDisplayModeChanged(bool isShownInMultiWindow,const std::string & data)1298 void V8DeclarativeEngine::OnWindowDisplayModeChanged(bool isShownInMultiWindow, const std::string& data)
1299 {
1300     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1301     ACE_DCHECK(isolate);
1302     v8::HandleScope handleScope(isolate);
1303     auto context = engineInstance_->GetV8Context();
1304     if (context.IsEmpty()) {
1305         LOGE("Destroy Application, context Is Empty");
1306         return;
1307     }
1308 
1309     v8::Local<v8::Boolean> v8Bool = v8::Boolean::New(isolate, isShownInMultiWindow);
1310     v8::Local<v8::String> v8Data = v8::String::NewFromUtf8(isolate, data.c_str()).ToLocalChecked();
1311     auto jsonValue = v8::JSON::Parse(context, v8Data);
1312     if (jsonValue.IsEmpty()) {
1313         LOGE("jsonValue is empty");
1314         return;
1315     }
1316     v8::Local<v8::Value> v8Config = jsonValue.ToLocalChecked();
1317     v8::Local<v8::Value> argv[] = { v8Bool, v8Config };
1318     int32_t argc = 2;
1319     (void)CallAppFunc(isolate, context, "onWindowDisplayModeChanged", argc, argv);
1320     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1321         continue;
1322     }
1323 }
1324 
OnNewWant(const std::string & data)1325 void V8DeclarativeEngine::OnNewWant(const std::string& data)
1326 {
1327     LOGD("V8DeclarativeEngine::OnNewWant");
1328     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1329     ACE_DCHECK(isolate);
1330     v8::HandleScope handleScope(isolate);
1331     v8::Isolate::Scope isolateScope(isolate);
1332     auto context = engineInstance_->GetV8Context();
1333     if (context.IsEmpty()) {
1334         LOGE("AceAbility Sava date, context Is Empty");
1335         return;
1336     }
1337     v8::Context::Scope contextScope(context);
1338     v8::TryCatch tryCatch(isolate);
1339     v8::Local<v8::String> v8Data = v8::String::NewFromUtf8(isolate, data.c_str()).ToLocalChecked();
1340     auto jsonValue = v8::JSON::Parse(context, v8Data);
1341     if (jsonValue.IsEmpty()) {
1342         v8::Local<v8::Object> tmpData = v8::Object::New(isolate);
1343         v8::Local<v8::Value> argv[] = { tmpData };
1344         int len = 1;
1345         if (!CallAppFunc(isolate, context, "onNewWant", len, argv)) {
1346             return;
1347         }
1348     } else {
1349         v8::Local<v8::Value> dataValue = jsonValue.ToLocalChecked();
1350         v8::Local<v8::Value> argv[] = { dataValue };
1351         int32_t len = 1;
1352         if (!CallAppFunc(isolate, context, "onNewWant", len, argv)) {
1353             return;
1354         }
1355     }
1356 
1357     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1358         continue;
1359     }
1360 }
1361 
OnSaveAbilityState(std::string & saveData)1362 void V8DeclarativeEngine::OnSaveAbilityState(std::string& saveData)
1363 {
1364     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1365     ACE_DCHECK(isolate);
1366     v8::HandleScope handleScope(isolate);
1367     v8::Isolate::Scope isolateScope(isolate);
1368     auto context = engineInstance_->GetV8Context();
1369     if (context.IsEmpty()) {
1370         LOGE("AceAbility Sava data, context Is Empty");
1371         return;
1372     }
1373 
1374     v8::Local<v8::Object> data = v8::Object::New(isolate);
1375     v8::Local<v8::Value> argv[] = { data };
1376     int len = 1;
1377     CallAppFunc(isolate, context, "onSaveAbilityState", len, argv);
1378     v8::Local<v8::String> propertyEntries = v8::JSON::Stringify(context, data).ToLocalChecked();
1379     v8::String::Utf8Value utf8Value(isolate, propertyEntries);
1380     if (*utf8Value) {
1381         saveData = *utf8Value;
1382     }
1383     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1384         continue;
1385     }
1386 }
1387 
OnRestoreAbilityState(const std::string & data)1388 void V8DeclarativeEngine::OnRestoreAbilityState(const std::string& data)
1389 {
1390     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1391     ACE_DCHECK(isolate);
1392     v8::HandleScope handleScope(isolate);
1393     v8::Isolate::Scope isolateScope(isolate);
1394     auto context = engineInstance_->GetV8Context();
1395     if (context.IsEmpty()) {
1396         LOGE("AceAbility Restore data, context Is Empty");
1397         return;
1398     }
1399     v8::Context::Scope contextScope(context);
1400 
1401     v8::TryCatch tryCatch(isolate);
1402 
1403     v8::Local<v8::String> v8Data = v8::String::NewFromUtf8(isolate, data.c_str()).ToLocalChecked();
1404     auto jsonValue = v8::JSON::Parse(context, v8Data);
1405     if (jsonValue.IsEmpty()) {
1406         LOGE("AceAbility RestoreAbility, data Is Empty");
1407         return;
1408     }
1409     v8::Local<v8::Value> dataValue = v8::JSON::Parse(context, v8Data).ToLocalChecked();
1410     v8::Local<v8::Value> argv[] = { dataValue };
1411     int32_t len = 1;
1412 
1413     if (!CallAppFunc(isolate, context, "onRestoreAbilityState", len, argv)) {
1414         return;
1415     }
1416 
1417     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1418         continue;
1419     }
1420 }
1421 
OnActive()1422 void V8DeclarativeEngine::OnActive()
1423 {
1424     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1425     ACE_DCHECK(isolate);
1426     v8::HandleScope handleScope(isolate);
1427     v8::Isolate::Scope isolateScope(isolate);
1428     auto context = engineInstance_->GetV8Context();
1429     if (context.IsEmpty()) {
1430         LOGE("AceAbility OnActive, context Is Empty");
1431         return;
1432     }
1433     v8::Context::Scope contextScope(context);
1434 
1435     v8::TryCatch tryCatch(isolate);
1436 
1437     CallAppFunc(isolate, context, "onActive");
1438     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1439         continue;
1440     }
1441 }
1442 
OnInactive()1443 void V8DeclarativeEngine::OnInactive()
1444 {
1445     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1446     ACE_DCHECK(isolate);
1447     v8::HandleScope handleScope(isolate);
1448     v8::Isolate::Scope isolateScope(isolate);
1449     auto context = engineInstance_->GetV8Context();
1450     if (context.IsEmpty()) {
1451         LOGE("AceAbility OnInactive, context Is Empty");
1452         return;
1453     }
1454     v8::Context::Scope contextScope(context);
1455 
1456     v8::TryCatch tryCatch(isolate);
1457 
1458     CallAppFunc(isolate, context, "onInactive");
1459     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1460         continue;
1461     }
1462 }
1463 
OnMemoryLevel(const int32_t level)1464 void V8DeclarativeEngine::OnMemoryLevel(const int32_t level)
1465 {
1466     LOGD("AceAbility Enter OnMemoryLevel");
1467     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1468     ACE_DCHECK(isolate);
1469     v8::HandleScope handleScope(isolate);
1470     v8::Isolate::Scope isolateScope(isolate);
1471     auto context = engineInstance_->GetV8Context();
1472     if (context.IsEmpty()) {
1473         LOGE("AceAbility OnMemoryLevel, context Is Empty");
1474         return;
1475     }
1476     v8::Context::Scope contextScope(context);
1477 
1478     v8::TryCatch tryCatch(isolate);
1479 
1480     v8::Local<v8::Integer> v8Integer = v8::Uint32::NewFromUnsigned(isolate, level);
1481     v8::Local<v8::Value> argv[] = { v8Integer };
1482     int32_t len = 1;
1483 
1484     if (!CallAppFunc(isolate, context, "onMemoryLevel", len, argv)) {
1485         return;
1486     }
1487     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1488         continue;
1489     }
1490 }
1491 
OnConfigurationUpdated(const std::string & data)1492 void V8DeclarativeEngine::OnConfigurationUpdated(const std::string& data)
1493 {
1494     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1495     ACE_DCHECK(isolate);
1496     v8::HandleScope handleScope(isolate);
1497     auto context = engineInstance_->GetV8Context();
1498     if (context.IsEmpty()) {
1499         LOGE("Destroy Application, context Is Empty");
1500         return;
1501     }
1502 
1503     v8::Local<v8::String> v8Data = v8::String::NewFromUtf8(isolate, data.c_str()).ToLocalChecked();
1504     auto jsonValue = v8::JSON::Parse(context, v8Data);
1505     if (jsonValue.IsEmpty()) {
1506         LOGE("jsonValue is empty");
1507         return;
1508     }
1509     v8::Local<v8::Value> ResourceConfiguration = jsonValue.ToLocalChecked();
1510     v8::Local<v8::Value> argv[] = { ResourceConfiguration };
1511     int32_t argc = 1;
1512     (void)CallAppFunc(isolate, context, "onConfigurationUpdated", argc, argv);
1513     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1514         continue;
1515     }
1516 }
1517 
OnRemoteTerminated()1518 void V8DeclarativeEngine::OnRemoteTerminated()
1519 {
1520     LOGD("AceAbility Enter OnRemoteTerminated");
1521     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1522     ACE_DCHECK(isolate);
1523     v8::HandleScope handleScope(isolate);
1524     v8::Isolate::Scope isolateScope(isolate);
1525     auto context = engineInstance_->GetV8Context();
1526     if (context.IsEmpty()) {
1527         LOGE("AceAbility OnRemoteTerminated, context Is Empty");
1528         return;
1529     }
1530     v8::Context::Scope contextScope(context);
1531 
1532     v8::TryCatch tryCatch(isolate);
1533 
1534     CallAppFunc(isolate, context, "onRemoteTerminated");
1535     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1536         continue;
1537     }
1538 }
1539 
OnCompleteContinuation(const int32_t code)1540 void V8DeclarativeEngine::OnCompleteContinuation(const int32_t code)
1541 {
1542     LOGD("AceAbility Enter OnCompleteContinuation");
1543     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1544     ACE_DCHECK(isolate);
1545     v8::HandleScope handleScope(isolate);
1546     v8::Isolate::Scope isolateScope(isolate);
1547     auto context = engineInstance_->GetV8Context();
1548     if (context.IsEmpty()) {
1549         LOGE("AceAbility OnCompleteContinuation, context Is Empty");
1550         return;
1551     }
1552     v8::Context::Scope contextScope(context);
1553 
1554     v8::TryCatch tryCatch(isolate);
1555 
1556     v8::Local<v8::Integer> v8Integer = v8::Uint32::NewFromUnsigned(isolate, code);
1557     v8::Local<v8::Value> argv[] = { v8Integer };
1558     int32_t len = 1;
1559 
1560     (void)CallAppFunc(isolate, context, "onCompleteContinuation", len, argv);
1561     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1562         continue;
1563     }
1564 }
1565 
1566 
OnRestoreData(const std::string & data)1567 bool V8DeclarativeEngine::OnRestoreData(const std::string& data)
1568 {
1569     LOGD("AceAbility Enter OnRestoreData");
1570     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1571     ACE_DCHECK(isolate);
1572     v8::HandleScope handleScope(isolate);
1573     v8::Isolate::Scope isolateScope(isolate);
1574     auto context = engineInstance_->GetV8Context();
1575     if (context.IsEmpty()) {
1576         LOGE("AceAbility OnRestoreData, context Is Empty");
1577         return false;
1578     }
1579     v8::Context::Scope contextScope(context);
1580 
1581     v8::TryCatch tryCatch(isolate);
1582 
1583     v8::Local<v8::String> v8Data = v8::String::NewFromUtf8(isolate, data.c_str()).ToLocalChecked();
1584     auto jsonValue = v8::JSON::Parse(context, v8Data);
1585     if (jsonValue.IsEmpty()) {
1586         LOGE("jsonValue is empty");
1587         return false;
1588     }
1589     v8::Local<v8::Value> dataValue = jsonValue.ToLocalChecked();
1590     v8::Local<v8::Value> argv[] = { dataValue };
1591     int32_t len = 1;
1592 
1593     if (!CallAppFunc(isolate, context, "onRestoreData", len, argv)) {
1594         return false;
1595     }
1596 
1597     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1598         continue;
1599     }
1600 
1601     return true;
1602 }
1603 
OnStartContinuation()1604 bool V8DeclarativeEngine::OnStartContinuation()
1605 {
1606     LOGE("AceAbility Enter OnStartContinuation");
1607     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1608     ACE_DCHECK(isolate);
1609     v8::HandleScope handleScope(isolate);
1610     v8::Isolate::Scope isolateScope(isolate);
1611     auto context = engineInstance_->GetV8Context();
1612     if (context.IsEmpty()) {
1613         LOGE("AceAbility OnStartContinuation, context Is Empty");
1614         return false;
1615     }
1616     v8::Context::Scope contextScope(context);
1617 
1618     v8::TryCatch tryCatch(isolate);
1619 
1620     int len = 0;
1621     auto argv = nullptr;
1622     if (!CallAppFunc(isolate, context, "onStartContinuation", len, argv)) {
1623         return false;
1624     }
1625 
1626     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1627         continue;
1628     }
1629 
1630     return true;
1631 }
1632 
OnSaveData(std::string & saveData)1633 void V8DeclarativeEngine::OnSaveData(std::string& saveData)
1634 {
1635     LOGE("AceAbility Enter save data");
1636     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1637     ACE_DCHECK(isolate);
1638     v8::HandleScope handleScope(isolate);
1639     v8::Isolate::Scope isolateScope(isolate);
1640     auto context = engineInstance_->GetV8Context();
1641     if (context.IsEmpty()) {
1642         LOGE("AceAbility Sava date, context Is Empty");
1643         return;
1644     }
1645     v8::Context::Scope contextScope(context);
1646 
1647     v8::TryCatch tryCatch(isolate);
1648 
1649     v8::Local<v8::Object> data = v8::Object::New(isolate);
1650     v8::Local<v8::Value> argv[] = { data };
1651     int len = 1;
1652 
1653     if (CallAppFunc(isolate, context, "onSaveData", len, argv)) {
1654         v8::Local<v8::String> propertyEntries = v8::JSON::Stringify(context, data).ToLocalChecked();
1655         v8::String::Utf8Value utf8Value(isolate, propertyEntries);
1656         saveData = *utf8Value;
1657     }
1658 
1659     while (v8::platform::PumpMessageLoop(GetPlatform().get(), isolate)) {
1660         continue;
1661     }
1662 }
1663 
TimerCallback(const std::string & callbackId,const std::string & delay,bool isInterval)1664 void V8DeclarativeEngine::TimerCallback(const std::string& callbackId, const std::string& delay, bool isInterval)
1665 {
1666     LOGD("Enter TimerCallback");
1667     ACE_DCHECK(engineInstance_);
1668     v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1669     ACE_DCHECK(isolate);
1670     v8::Isolate::Scope isolateScope(isolate);
1671     v8::HandleScope handleScope(isolate);
1672     auto context = engineInstance_->GetV8Context();
1673     v8::Context::Scope contextScope(context);
1674 
1675     auto delegate =
1676         static_cast<RefPtr<FrontendDelegate>*>(isolate->GetData(V8DeclarativeEngineInstance::FRONTEND_DELEGATE));
1677     if (isInterval) {
1678         TimerCallJs(callbackId, isInterval);
1679         (*delegate)->WaitTimer(callbackId, delay, isInterval, false);
1680     } else {
1681         TimerCallJs(callbackId, isInterval);
1682         ModuleManager::GetInstance()->RemoveCallbackFunc(std::stoi(callbackId), isInterval);
1683         (*delegate)->ClearTimer(callbackId);
1684     }
1685 }
1686 
TimerCallJs(const std::string & callbackId,bool isInterval)1687 void V8DeclarativeEngine::TimerCallJs(const std::string& callbackId, bool isInterval)
1688 {
1689     ACE_DCHECK(engineInstance_);
1690     v8::Isolate* isolate = ModuleManager::GetInstance()->GetCallbackIsolate(std::stoi(callbackId), isInterval);
1691     ACE_DCHECK(isolate);
1692     if (isolate == nullptr) {
1693         LOGW("CallbackIsolate is null when TimerCallJs is called.");
1694         return;
1695     }
1696     v8::Isolate::Scope isolateScope(isolate);
1697     v8::HandleScope handleScope(isolate);
1698     auto context = isolate->GetCurrentContext();
1699     v8::Context::Scope contextScope(context);
1700 
1701     v8::TryCatch tryCatch(isolate);
1702     v8::Local<v8::Function> jsFunc =
1703         ModuleManager::GetInstance()->GetCallbackFunc(std::stoi(callbackId), isInterval).Get(isolate);
1704     if (!jsFunc->IsFunction()) {
1705         LOGE("timer jsFunc callbackId = %s is not a function", callbackId.c_str());
1706         return;
1707     }
1708     std::vector<CopyablePersistent<v8::Value>> jsargv =
1709         ModuleManager::GetInstance()->GetCallbackArray(std::stoi(callbackId), isInterval);
1710     v8::Local<v8::Value> res;
1711     if (jsargv.empty()) {
1712         LOGI("jsargv is empty");
1713         v8::Local<v8::Value> argv[] = {};
1714         bool succ = jsFunc->Call(context, context->Global(), 0, argv).ToLocal(&res);
1715         if (succ) {
1716             LOGI("call timer callback success");
1717         } else {
1718             V8Utils::JsStdDumpErrorAce(isolate, &tryCatch);
1719             LOGE("call timer callback fail");
1720         }
1721     } else {
1722         LOGI("jsargv's size is %{private}zu", jsargv.size());
1723         v8::Local<v8::Value>* argv = new v8::Local<v8::Value>[jsargv.size()];
1724         uint32_t index = 0;
1725         while (index < jsargv.size()) {
1726             argv[index] = jsargv[index].Get(isolate);
1727             ++index;
1728         }
1729 
1730         bool succ = jsFunc->Call(context, context->Global(), jsargv.size(), argv).ToLocal(&res);
1731         if (succ) {
1732             LOGI("call timer callback success");
1733         } else {
1734             V8Utils::JsStdDumpErrorAce(isolate, &tryCatch);
1735             LOGE("call timer callback fail");
1736         }
1737         delete[] argv;
1738     }
1739 }
1740 
MediaQueryCallback(const std::string & callbackId,const std::string & args)1741 void V8DeclarativeEngine::MediaQueryCallback(const std::string& callbackId, const std::string& args)
1742 {
1743     JsEngine::MediaQueryCallback(callbackId, args);
1744 }
1745 
RequestAnimationCallback(const std::string & callbackId,uint64_t timeStamp)1746 void V8DeclarativeEngine::RequestAnimationCallback(const std::string& callbackId, uint64_t timeStamp)
1747 {
1748     LOGD("Enter RequestAnimationCallback");
1749 }
1750 
JsCallback(const std::string & callbackId,const std::string & args)1751 void V8DeclarativeEngine::JsCallback(const std::string& callbackId, const std::string& args)
1752 {
1753     LOGD("Enter JSCallback");
1754 }
1755 
FireAsyncEvent(const std::string & eventId,const std::string & param)1756 void V8DeclarativeEngine::FireAsyncEvent(const std::string& eventId, const std::string& param)
1757 {
1758     LOGW("V8DeclarativeEngine FireAsyncEvent is unusable");
1759 }
1760 
FireSyncEvent(const std::string & eventId,const std::string & param)1761 void V8DeclarativeEngine::FireSyncEvent(const std::string& eventId, const std::string& param)
1762 {
1763     LOGW("V8DeclarativeEngine FireAsyncEvent is unusable");
1764 }
1765 
InitXComponent()1766 void V8DeclarativeEngine::InitXComponent()
1767 {
1768     ACE_DCHECK(engineInstance_);
1769     isolateXComp_ = engineInstance_->GetV8Isolate();
1770     if (!isolateXComp_) {
1771         LOGE("InitXComponent isolateXComp_ is null.");
1772         return;
1773     }
1774     ACE_DCHECK(isolateXComp_);
1775     v8::Isolate::Scope isolateScope(isolateXComp_);
1776     v8::HandleScope handleScope(isolateXComp_);
1777     auto context = isolateXComp_->GetCurrentContext();
1778     if (context.IsEmpty()) {
1779         LOGE("InitXComponent context is empty");
1780         return;
1781     }
1782     ctxXComp_.Reset(isolateXComp_, context);
1783 }
1784 
FireExternalEvent(const std::string & componentId,const uint32_t nodeId,const bool isDestroy)1785 void V8DeclarativeEngine::FireExternalEvent(const std::string& componentId, const uint32_t nodeId, const bool isDestroy)
1786 {
1787     CHECK_RUN_ON(JS);
1788     if (isDestroy) {
1789         XComponentComponentClient::GetInstance().DeleteFromXcomponentsMapById(componentId);
1790         XComponentClient::GetInstance().DeleteControllerFromJSXComponentControllersMap(componentId);
1791         XComponentClient::GetInstance().DeleteFromNativeXcomponentsMapById(componentId);
1792         XComponentClient::GetInstance().DeleteFromJsValMapById(componentId);
1793         return;
1794     }
1795     InitXComponent();
1796     std::tie(nativeXComponentImpl_, nativeXComponent_) =
1797         XComponentClient::GetInstance().GetNativeXComponentFromXcomponentsMap(componentId);
1798     RefPtr<XComponentComponent> xcomponent =
1799         XComponentComponentClient::GetInstance().GetXComponentFromXcomponentsMap(componentId);
1800     if (!xcomponent) {
1801         LOGE("FireExternalEvent xcomponent is null.");
1802         return;
1803     }
1804     auto textureId = static_cast<int64_t>(xcomponent->GetTextureId());
1805     auto container = Container::Current();
1806     if (!container) {
1807         LOGE("FireExternalEvent Current container null");
1808         return;
1809     }
1810     auto nativeView = static_cast<AceView*>(container->GetView());
1811     if (!nativeView) {
1812         LOGE("FireExternalEvent nativeView null");
1813         return;
1814     }
1815     auto nativeWindow = const_cast<void*>(nativeView->GetNativeWindowById(textureId));
1816     if (!nativeWindow) {
1817         LOGE("FireExternalEvent nativeWindow invalid");
1818         return;
1819     }
1820 
1821     nativeXComponentImpl_->SetSurface(nativeWindow);
1822     nativeXComponentImpl_->SetXComponentId(xcomponent->GetId());
1823     auto v8NativeEngine = static_cast<V8NativeEngine*>(nativeEngine_);
1824     if (v8NativeEngine == nullptr) {
1825         LOGE("FireExternalEvent v8NativeEngine is nullptr");
1826         return;
1827     }
1828     std::string arguments;
1829     v8::Local<v8::Object> renderContext = v8NativeEngine->LoadModuleByName(xcomponent->GetLibraryName(), true,
1830                                                                            arguments, OH_NATIVE_XCOMPONENT_OBJ,
1831                                                                            reinterpret_cast<void*>(nativeXComponent_));
1832     renderContextXComp_.Reset(isolateXComp_, renderContext);
1833     auto objContext = V8Object(renderContext);
1834     JSRef<JSObject> obj = JSRef<JSObject>::Make(objContext);
1835     XComponentClient::GetInstance().AddJsValToJsValMap(componentId, obj);
1836     auto delegate =
1837         static_cast<RefPtr<FrontendDelegate>*>(isolateXComp_->GetData(V8DeclarativeEngineInstance::FRONTEND_DELEGATE));
1838     v8::TryCatch tryCatch(isolateXComp_);
1839     auto task = [weak = WeakClaim(this), xcomponent]() {
1840         auto pool = xcomponent->GetTaskPool();
1841         if (!pool) {
1842             return;
1843         }
1844         auto bridge = weak.Upgrade();
1845         if (bridge) {
1846             pool->NativeXComponentInit(
1847                 bridge->nativeXComponent_, AceType::WeakClaim(AceType::RawPtr(bridge->nativeXComponentImpl_)));
1848         }
1849     };
1850     if (*delegate == nullptr) {
1851         LOGE("FireExternalEvent delegate is null.");
1852         return;
1853     }
1854     (*delegate)->PostSyncTaskToPage(task);
1855 }
1856 
SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher> & dispatcher)1857 void V8DeclarativeEngine::SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher)
1858 {
1859     ACE_DCHECK(engineInstance_);
1860     LOGD("Enter SetJsMessageDispatcher");
1861     engineInstance_->SetJsMessageDispatcher(dispatcher);
1862 }
1863 
RunGarbageCollection()1864 void V8DeclarativeEngine::RunGarbageCollection()
1865 {
1866     if (engineInstance_) {
1867         v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1868         if (isolate != nullptr) {
1869             v8::Isolate::Scope isolateScope(isolate);
1870             LOGD("Sending LowMemoryNotification to V8");
1871             isolate->LowMemoryNotification();
1872         }
1873     }
1874 }
1875 
GetGroupJsBridge()1876 RefPtr<GroupJsBridge> V8DeclarativeEngine::GetGroupJsBridge()
1877 {
1878     return AceType::MakeRefPtr<V8DeclarativeGroupJsBridge>();
1879 }
1880 
NotifyAppStorage(const std::string & key,const std::string & value)1881 void V8DeclarativeEngine::NotifyAppStorage(const std::string& key, const std::string& value)
1882 {
1883     if (engineInstance_) {
1884         v8::Isolate* isolate = engineInstance_->GetV8Isolate();
1885         if (isolate != nullptr) {
1886             v8::Isolate::Scope isolateScope(isolate);
1887             std::string str = "notifyAppStorageChange('" + key + "', '" + value + "');\n";
1888             bool result = CallEvalBuf(isolate, str.c_str());
1889             if (!result) {
1890                 LOGE("failed to notify AppStorage");
1891             }
1892         }
1893     }
1894 }
1895 
1896 } // namespace OHOS::Ace::Framework
1897