• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/module/module_tools.h"
17 
18 #include "ecmascript/ecma_context.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/jspandafile/js_pandafile_executor.h"
21 #include "ecmascript/module/js_module_manager.h"
22 #include "ecmascript/module/js_shared_module.h"
23 #include "ecmascript/module/module_logger.h"
24 #include "ecmascript/module/module_manager_helper.h"
25 #include "ecmascript/module/module_path_helper.h"
26 #include "ecmascript/require/js_cjs_module.h"
27 
28 
29 namespace panda::ecmascript {
30 
GetModuleValueFromIndexBindingForLog(JSThread * thread,JSHandle<SourceTextModule> module,JSTaggedValue resolvedBinding,int32_t index)31 JSTaggedValue ModuleTools::GetModuleValueFromIndexBindingForLog(
32     JSThread *thread, JSHandle<SourceTextModule> module, JSTaggedValue resolvedBinding, int32_t index)
33 {
34     JSHandle<ResolvedRecordIndexBinding> binding(thread, resolvedBinding);
35     JSHandle<SourceTextModule> resolvedModule =
36         ModuleManagerHelper::GetResolvedRecordIndexBindingModule(thread, module, binding);
37     ModuleLogger *moduleLogger =
38         thread->GetCurrentEcmaContext()->GetModuleLogger();
39     moduleLogger->InsertModuleLoadInfo(module, resolvedModule, index);
40     return ModuleManagerHelper::GetModuleValue(thread, resolvedModule, binding->GetIndex());
41 }
42 
43 // use for moduleLogger is not nullptr
GetModuleValueFromRecordBindingForLog(JSThread * thread,JSHandle<SourceTextModule> module,JSTaggedValue resolvedBinding,int32_t index)44 JSTaggedValue ModuleTools::GetModuleValueFromRecordBindingForLog(
45     JSThread *thread, JSHandle<SourceTextModule> module, JSTaggedValue resolvedBinding, int32_t index)
46 {
47     JSHandle<ResolvedRecordBinding> binding(thread, resolvedBinding);
48     JSHandle<SourceTextModule> resolvedModule =
49         ModuleManagerHelper::GetResolvedRecordBindingModule(thread, module, binding);
50     ModuleLogger *moduleLogger =
51         thread->GetCurrentEcmaContext()->GetModuleLogger();
52     moduleLogger->InsertModuleLoadInfo(module, resolvedModule, index);
53     return ModuleManagerHelper::GetModuleValue(thread, resolvedModule, binding->GetBindingName());
54 }
55 
56 // use for moduleLogger is not nullptr
ProcessModuleLoadInfo(JSThread * thread,JSHandle<SourceTextModule> currentModule,JSTaggedValue resolvedBinding,int32_t index)57 JSTaggedValue ModuleTools::ProcessModuleLoadInfo(JSThread *thread, JSHandle<SourceTextModule> currentModule,
58     JSTaggedValue resolvedBinding, int32_t index)
59 {
60     ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
61     JSMutableHandle<JSTaggedValue> res(thread, thread->GlobalConstants()->GetUndefined());
62     if (resolvedBinding.IsResolvedIndexBinding()) {
63         ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject());
64         JSTaggedValue resolvedModule = binding->GetModule();
65         JSHandle<SourceTextModule> module(thread, resolvedModule);
66         ASSERT(resolvedModule.IsSourceTextModule());
67 
68         // Support for only modifying var value of HotReload.
69         // Cause patchFile exclude the record of importing modifying var. Can't reresolve moduleRecord.
70         EcmaContext *context = thread->GetCurrentEcmaContext();
71         if (context->GetStageOfHotReload() == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) {
72             const JSHandle<JSTaggedValue> resolvedModuleOfHotReload =
73                 context->FindPatchModule(module->GetEcmaModuleRecordNameString());
74             if (!resolvedModuleOfHotReload->IsHole()) {
75                 resolvedModule = resolvedModuleOfHotReload.GetTaggedValue();
76                 JSHandle<SourceTextModule> moduleOfHotReload(thread, resolvedModule);
77                 moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
78                 return ModuleManagerHelper::GetModuleValue(thread, moduleOfHotReload, binding->GetIndex());
79             }
80         }
81         moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
82         return ModuleManagerHelper::GetModuleValue(thread, module, binding->GetIndex());
83     }
84     if (resolvedBinding.IsResolvedBinding()) {
85         ResolvedBinding *binding = ResolvedBinding::Cast(resolvedBinding.GetTaggedObject());
86         JSTaggedValue resolvedModule = binding->GetModule();
87         JSHandle<SourceTextModule> module(thread, resolvedModule);
88         if (SourceTextModule::IsNativeModule(module->GetTypes())) {
89             moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
90             return ModuleManagerHelper::UpdateBindingAndGetModuleValue(
91                 thread, currentModule, module, index, binding->GetBindingName());
92         }
93         if (module->GetTypes() == ModuleTypes::CJS_MODULE) {
94             moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
95             return ModuleManagerHelper::UpdateBindingAndGetModuleValue(
96                 thread, currentModule, module, index, binding->GetBindingName());
97         }
98     }
99     if (resolvedBinding.IsResolvedRecordIndexBinding()) {
100         return GetModuleValueFromIndexBindingForLog(thread, currentModule, resolvedBinding, index);
101     }
102     if (resolvedBinding.IsResolvedRecordBinding()) { // LCOV_EXCL_BR_LINE
103         return GetModuleValueFromRecordBindingForLog(thread, currentModule, resolvedBinding, index);
104     }
105     LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding";
106     UNREACHABLE();
107 }
108 
ProcessModuleNameSpaceLoadInfo(JSThread * thread,JSHandle<SourceTextModule> currentModule,JSHandle<SourceTextModule> requiredModule)109 JSTaggedValue ModuleTools::ProcessModuleNameSpaceLoadInfo(
110     JSThread *thread, JSHandle<SourceTextModule> currentModule, JSHandle<SourceTextModule> requiredModule)
111 {
112     ModuleTypes moduleType = requiredModule->GetTypes();
113     ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
114     // if requiredModule is Native module
115     if (SourceTextModule::IsNativeModule(moduleType)) {
116         moduleLogger->InsertModuleLoadInfo(currentModule, requiredModule, -1);
117         return SourceTextModule::Cast(requiredModule.GetTaggedValue())->GetModuleValue(thread, 0, false);
118     }
119     // if requiredModule is CommonJS
120     if (moduleType == ModuleTypes::CJS_MODULE) {
121         moduleLogger->InsertModuleLoadInfo(currentModule, requiredModule, -1);
122         CString cjsModuleName = SourceTextModule::GetModuleName(requiredModule.GetTaggedValue());
123         JSHandle<JSTaggedValue> moduleNameHandle(thread->GetEcmaVM()->GetFactory()->NewFromUtf8(cjsModuleName));
124         return CjsModule::SearchFromModuleCache(thread, moduleNameHandle).GetTaggedValue();
125     }
126     // if requiredModule is ESM
127     moduleLogger->InsertModuleLoadInfo(currentModule, requiredModule, -1);
128     JSHandle<JSTaggedValue> moduleNamespace = SourceTextModule::GetModuleNamespace(thread, requiredModule);
129     ASSERT(moduleNamespace->IsModuleNamespace());
130     return moduleNamespace.GetTaggedValue();
131 }
132 
GetLazyModuleValueFromIndexBindingForLog(JSThread * thread,JSHandle<SourceTextModule> module,JSTaggedValue resolvedBinding,int32_t index)133 JSTaggedValue ModuleTools::GetLazyModuleValueFromIndexBindingForLog(
134     JSThread *thread, JSHandle<SourceTextModule> module, JSTaggedValue resolvedBinding, int32_t index)
135 {
136     JSHandle<ResolvedRecordIndexBinding> binding(thread, resolvedBinding);
137     JSHandle<JSTaggedValue> recordName(thread, binding->GetModuleRecord());
138     ASSERT(recordName->IsString());
139     // moduleRecord is string, find at current vm
140     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
141     CString recordNameStr = ModulePathHelper::Utf8ConvertToString(recordName.GetTaggedValue());
142     JSHandle<SourceTextModule> resolvedModule;
143     if (moduleManager->IsLocalModuleLoaded(recordNameStr)) {
144         resolvedModule = moduleManager->HostGetImportedModule(recordNameStr);
145         if (!moduleManager->IsEvaluatedModule(recordNameStr)) {
146             SourceTextModule::Evaluate(thread, resolvedModule, nullptr);
147             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
148         }
149     } else {
150         auto isMergedAbc = !module->GetEcmaModuleRecordNameString().empty();
151         CString fileName = ModulePathHelper::Utf8ConvertToString(binding->GetAbcFileName());
152         if (!JSPandaFileExecutor::LazyExecuteModule(thread,
153             recordNameStr, fileName, isMergedAbc)) { // LCOV_EXCL_BR_LINE
154             LOG_ECMA(FATAL) << "LazyExecuteModule failed";
155         }
156         resolvedModule = moduleManager->HostGetImportedModule(recordNameStr);
157     }
158     ModuleLogger *moduleLogger =
159         thread->GetCurrentEcmaContext()->GetModuleLogger();
160     moduleLogger->InsertModuleLoadInfo(module, resolvedModule, index);
161     return ModuleManagerHelper::GetModuleValue(thread, resolvedModule, binding->GetIndex());
162 }
163 
164 // use for moduleLogger is not nullptr
GetLazyModuleValueFromRecordBindingForLog(JSThread * thread,JSHandle<SourceTextModule> module,JSTaggedValue resolvedBinding,int32_t index)165 JSTaggedValue ModuleTools::GetLazyModuleValueFromRecordBindingForLog(
166     JSThread *thread, JSHandle<SourceTextModule> module, JSTaggedValue resolvedBinding, int32_t index)
167 {
168     JSHandle<ResolvedRecordBinding> binding(thread, resolvedBinding);
169     JSHandle<JSTaggedValue> recordName(thread, binding->GetModuleRecord());
170     ASSERT(recordName->IsString());
171     // moduleRecord is string, find at current vm
172     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
173     CString recordNameStr = ModulePathHelper::Utf8ConvertToString(recordName.GetTaggedValue());
174     JSHandle<SourceTextModule> resolvedModule;
175     if (moduleManager->IsLocalModuleLoaded(recordNameStr)) {
176         resolvedModule = moduleManager->HostGetImportedModule(recordNameStr);
177         if (!moduleManager->IsEvaluatedModule(recordNameStr)) {
178             SourceTextModule::Evaluate(thread, resolvedModule, nullptr);
179             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
180         }
181     } else {
182         auto isMergedAbc = !module->GetEcmaModuleRecordNameString().empty();
183         CString fileName = module->GetEcmaModuleFilenameString();
184         if (!JSPandaFileExecutor::LazyExecuteModule(thread,
185             recordNameStr, fileName, isMergedAbc)) { // LCOV_EXCL_BR_LINE
186             LOG_ECMA(FATAL) << "LazyExecuteModule failed";
187         }
188         resolvedModule = moduleManager->HostGetImportedModule(recordNameStr);
189     }
190     ModuleLogger *moduleLogger =
191         thread->GetCurrentEcmaContext()->GetModuleLogger();
192     moduleLogger->InsertModuleLoadInfo(module, resolvedModule, index);
193     return ModuleManagerHelper::GetModuleValue(thread, resolvedModule, binding->GetBindingName());
194 }
195 
196 // use for moduleLogger is not nullptr
ProcessLazyModuleLoadInfo(JSThread * thread,JSHandle<SourceTextModule> currentModule,JSTaggedValue resolvedBinding,int32_t index)197 JSTaggedValue ModuleTools::ProcessLazyModuleLoadInfo(JSThread *thread, JSHandle<SourceTextModule> currentModule,
198     JSTaggedValue resolvedBinding, int32_t index)
199 {
200     ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
201     JSMutableHandle<JSTaggedValue> res(thread, thread->GlobalConstants()->GetUndefined());
202     if (resolvedBinding.IsResolvedIndexBinding()) {
203         JSHandle<ResolvedIndexBinding> binding(thread, resolvedBinding);
204         JSTaggedValue resolvedModule = binding->GetModule();
205         JSMutableHandle<SourceTextModule> module(thread, resolvedModule);
206         ASSERT(resolvedModule.IsSourceTextModule());
207         // Support for only modifying var value of HotReload.
208         // Cause patchFile exclude the record of importing modifying var. Can't reresolve moduleRecord.
209         EcmaContext *context = thread->GetCurrentEcmaContext();
210         if (context->GetStageOfHotReload() == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) {
211             const JSHandle<JSTaggedValue> resolvedModuleOfHotReload =
212                 context->FindPatchModule(module->GetEcmaModuleRecordNameString());
213             if (!resolvedModuleOfHotReload->IsHole()) {
214                 resolvedModule = resolvedModuleOfHotReload.GetTaggedValue();
215                 module.Update(resolvedModule);
216             }
217         }
218         if (module->GetStatus() < ModuleStatus::EVALUATED) {
219             SourceTextModule::Evaluate(thread, module, nullptr, 0, ExecuteTypes::LAZY);
220         }
221         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
222         moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
223         return ModuleManagerHelper::GetModuleValue(thread, module, binding->GetIndex());
224     }
225     if (resolvedBinding.IsResolvedBinding()) {
226         JSHandle<ResolvedBinding> binding(thread, resolvedBinding);
227         JSTaggedValue resolvedModule = binding->GetModule();
228         JSHandle<SourceTextModule> module(thread, resolvedModule);
229         ModuleTypes moduleType = module->GetTypes();
230         if (SourceTextModule::IsNativeModule(moduleType)) {
231             SourceTextModule::EvaluateNativeModule(thread, module, moduleType);
232             moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
233             return ModuleManagerHelper::UpdateBindingAndGetModuleValue(
234                 thread, currentModule, module, index, binding->GetBindingName());
235         }
236         if (SourceTextModule::IsCjsModule(moduleType)) {
237             ModuleStatus status = module->GetStatus();
238             if (status < ModuleStatus::EVALUATED) {
239                 SourceTextModule::ModuleExecution(thread, module, nullptr, 0);
240                 SourceTextModule::RecordEvaluatedOrError(thread, module);
241                 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
242             }
243             moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
244             return ModuleManagerHelper::UpdateBindingAndGetModuleValue(
245                 thread, currentModule, module, index, binding->GetBindingName());
246         }
247     }
248     if (resolvedBinding.IsResolvedRecordIndexBinding()) {
249         return GetLazyModuleValueFromIndexBindingForLog(thread, currentModule, resolvedBinding, index);
250     }
251     if (resolvedBinding.IsResolvedRecordBinding()) { // LCOV_EXCL_BR_LINE
252         return GetLazyModuleValueFromRecordBindingForLog(thread, currentModule, resolvedBinding, index);
253     }
254     LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding";
255     UNREACHABLE();
256 }
257 } // namespace panda::ecmascript
258