• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "ecmascript/jspandafile/js_pandafile_executor.h"
17 
18 #include "ecmascript/base/path_helper.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/jspandafile/js_pandafile_manager.h"
21 #include "ecmascript/jspandafile/program_object.h"
22 #include "ecmascript/jspandafile/quick_fix_manager.h"
23 #include "ecmascript/mem/c_string.h"
24 #include "ecmascript/mem/c_containers.h"
25 #include "ecmascript/module/js_module_manager.h"
26 
27 namespace panda::ecmascript {
28 using PathHelper = base::PathHelper;
ExecuteFromFile(JSThread * thread,const CString & filename,std::string_view entryPoint,bool needUpdate,bool excuteFromJob)29 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteFromFile(JSThread *thread, const CString &filename,
30     std::string_view entryPoint, bool needUpdate, bool excuteFromJob)
31 {
32     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteFromFile filename " << filename;
33     CString entry;
34     CString name;
35     CString normalName = PathHelper::NormalizePath(filename);
36     EcmaVM *vm = thread->GetEcmaVM();
37     if (!vm->IsBundlePack()) {
38 #if defined(PANDA_TARGET_LINUX) || defined(OHOS_UNIT_TEST)
39         name = filename;
40         entry = entryPoint.data();
41 #else
42         if (excuteFromJob) {
43             entry = entryPoint.data();
44         } else {
45             entry = PathHelper::ParseOhmUrl(vm, normalName, name);
46         }
47 #if !WIN_OR_MAC_OR_IOS_PLATFORM
48         if (name.empty()) {
49             name = vm->GetAssetPath();
50         }
51 #elif defined(PANDA_TARGET_WINDOWS)
52         CString assetPath = vm->GetAssetPath();
53         name = assetPath + "\\" + JSPandaFile::MERGE_ABC_NAME;
54 #else
55         CString assetPath = vm->GetAssetPath();
56         name = assetPath + "/" + JSPandaFile::MERGE_ABC_NAME;
57 #endif
58 #endif
59     } else {
60         name = filename;
61         entry = entryPoint.data();
62     }
63 
64     const JSPandaFile *jsPandaFile =
65         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, name, entry, needUpdate);
66     if (jsPandaFile == nullptr) {
67         CString msg = "Load file with filename '" + name + "' failed, recordName '" + entry + "'";
68         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
69     }
70     CString realEntry = entry;
71     // If it is an old record, delete the bundleName and moduleName
72     if (!jsPandaFile->IsBundlePack() && !excuteFromJob && !vm->GetBundleName().empty()) {
73         const_cast<JSPandaFile *>(jsPandaFile)->CheckIsRecordWithBundleName(vm);
74         if (!jsPandaFile->IsRecordWithBundleName()) {
75             PathHelper::CroppingRecord(realEntry);
76         }
77     }
78     bool isModule = jsPandaFile->IsModule(thread, realEntry, entry);
79     if (thread->HasPendingException()) {
80         vm->HandleUncaughtException(thread->GetException().GetTaggedObject());
81         return Unexpected(false);
82     }
83     if (isModule) {
84         [[maybe_unused]] EcmaHandleScope scope(thread);
85         ModuleManager *moduleManager = vm->GetModuleManager();
86         JSHandle<JSTaggedValue> moduleRecord(thread->GlobalConstants()->GetHandledUndefined());
87         if (jsPandaFile->IsBundlePack()) {
88             moduleRecord = moduleManager->HostResolveImportedModule(name);
89         } else {
90             moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(name, realEntry);
91         }
92         SourceTextModule::Instantiate(thread, moduleRecord);
93         if (thread->HasPendingException()) {
94             if (!excuteFromJob) {
95                 vm->HandleUncaughtException(thread->GetException().GetTaggedObject());
96             }
97             return Unexpected(false);
98         }
99         JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
100         module->SetStatus(ModuleStatus::INSTANTIATED);
101         SourceTextModule::Evaluate(thread, module, nullptr, 0, excuteFromJob);
102         return JSTaggedValue::Undefined();
103     }
104     return JSPandaFileExecutor::Execute(thread, jsPandaFile, realEntry.c_str(), excuteFromJob);
105 }
106 
ExecuteFromBuffer(JSThread * thread,const void * buffer,size_t size,std::string_view entryPoint,const CString & filename,bool needUpdate)107 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteFromBuffer(JSThread *thread,
108     const void *buffer, size_t size, std::string_view entryPoint, const CString &filename, bool needUpdate)
109 {
110     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteFromBuffer filename " << filename;
111     CString normalName = PathHelper::NormalizePath(filename);
112     const JSPandaFile *jsPandaFile =
113         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, normalName, entryPoint, buffer, size, needUpdate);
114     if (jsPandaFile == nullptr) {
115         CString msg = "Load file with filename '" + normalName + "' failed, recordName '" + entryPoint.data() + "'";
116         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
117     }
118 
119     CString entry = entryPoint.data();
120     bool isModule = jsPandaFile->IsModule(thread, entry);
121     if (isModule) {
122         bool isBundle = jsPandaFile->IsBundlePack();
123         return CommonExecuteBuffer(thread, isBundle, normalName, entry, buffer, size);
124     }
125     return JSPandaFileExecutor::Execute(thread, jsPandaFile, entry);
126 }
127 
ExecuteModuleBuffer(JSThread * thread,const void * buffer,size_t size,const CString & filename,bool needUpdate)128 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteModuleBuffer(
129     JSThread *thread, const void *buffer, size_t size, const CString &filename, bool needUpdate)
130 {
131     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteModuleBuffer filename " << filename;
132     CString name;
133     EcmaVM *vm = thread->GetEcmaVM();
134 #if !WIN_OR_MAC_OR_IOS_PLATFORM
135     name = vm->GetAssetPath();
136 #elif defined(PANDA_TARGET_WINDOWS)
137     CString assetPath = vm->GetAssetPath();
138     name = assetPath + "\\" + JSPandaFile::MERGE_ABC_NAME;
139 #else
140     CString assetPath = vm->GetAssetPath();
141     name = assetPath + "/" + JSPandaFile::MERGE_ABC_NAME;
142 #endif
143     CString normalName = PathHelper::NormalizePath(filename);
144     CString entry = PathHelper::ParseOhmUrl(vm, normalName, name);
145     const JSPandaFile *jsPandaFile =
146         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, name, entry, buffer, size, needUpdate);
147     if (jsPandaFile == nullptr) {
148         CString msg = "Load file with filename '" + name + "' failed, recordName '" + entry + "'";
149         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
150     }
151     bool isBundle = jsPandaFile->IsBundlePack();
152     CString realEntry = entry;
153     if (!isBundle) {
154         const_cast<JSPandaFile *>(jsPandaFile)->CheckIsRecordWithBundleName(vm);
155         if (!jsPandaFile->IsRecordWithBundleName()) {
156             PathHelper::CroppingRecord(realEntry);
157         }
158     }
159     // will be refactored, temporarily use the function IsModule to verify realEntry
160     [[maybe_unused]] bool isModule = jsPandaFile->IsModule(thread, realEntry, entry);
161     if (thread->HasPendingException()) {
162         vm->HandleUncaughtException(thread->GetException().GetTaggedObject());
163         return Unexpected(false);
164     }
165     ASSERT(isModule);
166     return CommonExecuteBuffer(thread, isBundle, name, realEntry, buffer, size);
167 }
168 
CommonExecuteBuffer(JSThread * thread,bool isBundle,const CString & filename,const CString & entry,const void * buffer,size_t size)169 Expected<JSTaggedValue, bool> JSPandaFileExecutor::CommonExecuteBuffer(JSThread *thread,
170     bool isBundle, const CString &filename, const CString &entry, const void *buffer, size_t size)
171 {
172     [[maybe_unused]] EcmaHandleScope scope(thread);
173     EcmaVM *vm = thread->GetEcmaVM();
174     ModuleManager *moduleManager = vm->GetModuleManager();
175     moduleManager->SetExecuteMode(true);
176     JSHandle<JSTaggedValue> moduleRecord(thread->GlobalConstants()->GetHandledUndefined());
177     if (isBundle) {
178         moduleRecord = moduleManager->HostResolveImportedModule(buffer, size, filename);
179     } else {
180         moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(filename, entry);
181     }
182     SourceTextModule::Instantiate(thread, moduleRecord);
183     if (thread->HasPendingException()) {
184         vm->HandleUncaughtException(thread->GetException().GetTaggedObject());
185         return Unexpected(false);
186     }
187     JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
188     module->SetStatus(ModuleStatus::INSTANTIATED);
189     SourceTextModule::Evaluate(thread, module, buffer, size);
190     return JSTaggedValue::Undefined();
191 }
192 
Execute(JSThread * thread,const JSPandaFile * jsPandaFile,std::string_view entryPoint,bool excuteFromJob)193 Expected<JSTaggedValue, bool> JSPandaFileExecutor::Execute(JSThread *thread, const JSPandaFile *jsPandaFile,
194                                                            std::string_view entryPoint, bool excuteFromJob)
195 {
196     // For Ark application startup
197     EcmaVM *vm = thread->GetEcmaVM();
198     Expected<JSTaggedValue, bool> result = vm->InvokeEcmaEntrypoint(jsPandaFile, entryPoint, excuteFromJob);
199     if (result) {
200         QuickFixManager *quickFixManager = vm->GetQuickFixManager();
201         quickFixManager->LoadPatchIfNeeded(thread, CstringConvertToStdString(jsPandaFile->GetJSPandaFileDesc()));
202     }
203     return result;
204 }
205 }  // namespace panda::ecmascript
206