• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "ecmascript/module/module_value_accessor.h"
16 
17 #include "ecmascript/module/module_logger.h"
18 #include "ecmascript/interpreter/slow_runtime_stub.h"
19 #include "ecmascript/interpreter/frame_handler.h"
20 #include "ecmascript/jspandafile/js_pandafile_executor.h"
21 #include "ecmascript/module/js_shared_module_manager.h"
22 #include "ecmascript/module/module_path_helper.h"
23 #include "ecmascript/require/js_cjs_module.h"
24 
25 namespace panda::ecmascript {
GetModuleValueInner(JSThread * thread,int32_t index)26 JSTaggedValue ModuleValueAccessor::GetModuleValueInner(JSThread *thread, int32_t index)
27 {
28     JSTaggedValue currentModule = GetCurrentModule(thread);
29     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
30         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
31     }
32     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(thread, index, false);
33 }
34 
GetModuleValueInner(JSThread * thread,int32_t index,JSTaggedValue jsFunc)35 JSTaggedValue ModuleValueAccessor::GetModuleValueInner(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
36 {
37     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread);
38     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
39         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
40     }
41     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(thread, index, false);
42 }
43 
GetModuleValueInner(JSThread * thread,int32_t index,JSHandle<JSTaggedValue> curModule)44 JSTaggedValue ModuleValueAccessor::GetModuleValueInner(JSThread *thread, int32_t index,
45     JSHandle<JSTaggedValue> curModule)
46 {
47     if (curModule->IsUndefined()) { // LCOV_EXCL_BR_LINE
48         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
49     }
50     return SourceTextModule::Cast(curModule->GetTaggedObject())->GetModuleValue(thread, index, false);
51 }
GetSendableModuleValueInner(JSThread * thread,int32_t index,JSTaggedValue jsFunc)52 JSTaggedValue ModuleValueAccessor::GetSendableModuleValueInner(JSThread* thread, int32_t index, JSTaggedValue jsFunc)
53 {
54     ModuleManager* moduleManager = thread->GetModuleManager();
55     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread);
56     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
57         LOG_FULL(FATAL) << "GetSendableModuleValueInner currentModule is undefined";
58     }
59     if (!SourceTextModule::IsSendableFunctionModule(currentModule)) {
60         return SourceTextModule::Cast(currentModule)->GetModuleValue(thread, index, false);
61     }
62     CString referenceName = SourceTextModule::GetModuleName(currentModule);
63     if (moduleManager->IsModuleLoaded(referenceName)) {
64         JSHandle<SourceTextModule> currentModuleHdl = moduleManager->GetImportedModule(referenceName);
65         if (currentModuleHdl->GetStatus() > ModuleStatus::INSTANTIATED) {
66             return currentModuleHdl->GetModuleValue(thread, index, false);
67         }
68     }
69     JSHandle<SourceTextModule> currentModuleHdl(thread, currentModule);
70     auto isMergedAbc = !currentModuleHdl->GetEcmaModuleRecordNameString().empty();
71     CString fileName = currentModuleHdl->GetEcmaModuleFilenameString();
72     if (!JSPandaFileExecutor::LazyExecuteModule(thread, referenceName, fileName, isMergedAbc)) { // LCOV_EXCL_BR_LINE
73         LOG_ECMA(FATAL) << "GetSendableModuleValueInner LazyExecuteModule failed";
74     }
75     ASSERT(moduleManager->IsModuleLoaded(referenceName));
76     return moduleManager->GetImportedModule(referenceName)->GetModuleValue(thread, index, false);
77 }
GetModuleValueOuter(JSThread * thread,int32_t index)78 JSTaggedValue ModuleValueAccessor::GetModuleValueOuter(JSThread* thread, int32_t index)
79 {
80     JSTaggedValue currentModule = GetCurrentModule(thread);
81     return GetModuleValueOuterInternal<false>(thread, index, currentModule);
82 }
83 
GetModuleValueOuter(JSThread * thread,int32_t index,JSTaggedValue jsFunc)84 JSTaggedValue ModuleValueAccessor::GetModuleValueOuter(JSThread* thread, int32_t index, JSTaggedValue jsFunc)
85 {
86     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread);
87     return GetModuleValueOuterInternal<false>(thread, index, currentModule);
88 }
89 
GetModuleValueOuter(JSThread * thread,int32_t index,JSHandle<JSTaggedValue> curModule)90 JSTaggedValue ModuleValueAccessor::GetModuleValueOuter(JSThread* thread, int32_t index,
91     JSHandle<JSTaggedValue> curModule)
92 {
93     return GetModuleValueOuterInternal<false>(thread, index, curModule.GetTaggedValue());
94 }
95 
GetLazyModuleValueOuter(JSThread * thread,int32_t index,JSTaggedValue jsFunc)96 JSTaggedValue ModuleValueAccessor::GetLazyModuleValueOuter(JSThread* thread, int32_t index, JSTaggedValue jsFunc)
97 {
98     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread);
99     return GetModuleValueOuterInternal<true>(thread, index, currentModule);
100 }
101 
GetSendableModuleValueOuter(JSThread * thread,int32_t index,JSTaggedValue jsFunc)102 JSTaggedValue ModuleValueAccessor::GetSendableModuleValueOuter(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
103 {
104     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread);
105     return GetSendableModuleValueOuterInternal<false>(thread, index, currentModule);
106 }
107 
GetLazySendableModuleValueOuter(JSThread * thread,int32_t index,JSTaggedValue jsFunc)108 JSTaggedValue ModuleValueAccessor::GetLazySendableModuleValueOuter(JSThread* thread, int32_t index,
109     JSTaggedValue jsFunc)
110 {
111     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread);
112     return GetSendableModuleValueOuterInternal<true>(thread, index, currentModule);
113 }
114 
GetModuleNamespace(JSThread * thread,int32_t index)115 JSTaggedValue ModuleValueAccessor::GetModuleNamespace(JSThread *thread, int32_t index)
116 {
117     JSTaggedValue currentModule = GetCurrentModule(thread);
118     return GetModuleNamespaceInternal(thread, index, currentModule);
119 }
120 
GetModuleNamespace(JSThread * thread,int32_t index,JSTaggedValue curFunc)121 JSTaggedValue ModuleValueAccessor::GetModuleNamespace(JSThread *thread, int32_t index, JSTaggedValue curFunc)
122 {
123     JSTaggedValue currentModule = JSFunction::Cast(curFunc.GetTaggedObject())->GetModule(thread);
124     return GetModuleNamespaceInternal(thread, index, currentModule);
125 }
GetNativeOrCjsModuleValue(JSThread * thread,JSHandle<SourceTextModule> module,int32_t index)126 JSTaggedValue ModuleValueAccessor::GetNativeOrCjsModuleValue(JSThread *thread, JSHandle<SourceTextModule> module,
127     int32_t index)
128 {
129     JSHandle<JSTaggedValue> exports = GetNativeOrCjsExports(thread, module.GetTaggedValue());
130     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
131     return SourceTextModule::GetValueFromExportObject(thread, exports, index);
132 }
GetNativeOrCjsModuleValue(JSThread * thread,JSHandle<SourceTextModule> module,JSTaggedValue bindingName)133 JSTaggedValue ModuleValueAccessor::GetNativeOrCjsModuleValue(JSThread *thread, JSHandle<SourceTextModule> module,
134     JSTaggedValue bindingName)
135 {
136     JSHandle<JSTaggedValue> exports = GetNativeOrCjsExports(thread, module.GetTaggedValue());
137     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
138     if (UNLIKELY(JSTaggedValue::SameValue(thread,
139         bindingName, thread->GlobalConstants()->GetHandledDefaultString().GetTaggedValue()))) {
140         return exports.GetTaggedValue();
141     }
142     // need fix
143     return JSHandle<JSTaggedValue>(thread, SlowRuntimeStub::LdObjByName(thread,
144                                                                         exports.GetTaggedValue(),
145                                                                         bindingName,
146                                                                         false,
147                                                                         JSTaggedValue::Undefined())).GetTaggedValue();
148 }
StoreModuleValue(JSThread * thread,int32_t index,JSTaggedValue value)149 void ModuleValueAccessor::StoreModuleValue(JSThread *thread, int32_t index, JSTaggedValue value)
150 {
151     JSHandle<SourceTextModule> currentModule(thread, GetCurrentModule(thread));
152     StoreModuleValueInternal(thread, currentModule, index, value);
153 }
154 
StoreModuleValue(JSThread * thread,int32_t index,JSTaggedValue value,JSTaggedValue jsFunc)155 void ModuleValueAccessor::StoreModuleValue(JSThread *thread, int32_t index, JSTaggedValue value, JSTaggedValue jsFunc)
156 {
157     JSHandle<SourceTextModule> currentModule(thread, JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread));
158     StoreModuleValueInternal(thread, currentModule, index, value);
159 }
GetCurrentModule(JSThread * thread)160 JSTaggedValue ModuleValueAccessor::GetCurrentModule(JSThread *thread)
161 {
162     FrameHandler frameHandler(thread);
163     JSTaggedValue currentFunc = frameHandler.GetFunction();
164     JSTaggedValue module = JSFunction::Cast(currentFunc.GetTaggedObject())->GetModule(thread);
165     if (SourceTextModule::IsSendableFunctionModule(module)) {
166         CString recordNameStr = SourceTextModule::GetModuleName(module);
167         return thread->GetModuleManager()->HostGetImportedModule(recordNameStr).GetTaggedValue();
168     }
169     return module;
170 }
GetModuleValue(JSThread * thread,JSHandle<SourceTextModule> module,int index)171 JSTaggedValue ModuleValueAccessor::GetModuleValue(JSThread *thread, JSHandle<SourceTextModule> module, int index)
172 {
173     ModuleTypes moduleType = module->GetTypes();
174     if (SourceTextModule::IsNativeModule(moduleType) || SourceTextModule::IsCjsModule(moduleType)) {
175         return GetNativeOrCjsModuleValue(thread, module, index);
176     }
177     return module->GetModuleValue(thread, index, false);
178 }
179 template <bool isLazy>
GetModuleValueOuterInternal(JSThread * thread,int32_t index,JSTaggedValue curModule)180 JSTaggedValue ModuleValueAccessor::GetModuleValueOuterInternal(JSThread *thread, int32_t index,
181     JSTaggedValue curModule)
182 {
183     if (curModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
184         LOG_FULL(FATAL) << "GetModuleValueOuterInternal currentModule failed";
185         UNREACHABLE();
186     }
187     JSHandle<SourceTextModule> currentModuleHdl(thread, curModule);
188     JSTaggedValue moduleEnvironment = currentModuleHdl->GetEnvironment(thread);
189     if (moduleEnvironment.IsUndefined()) {
190         return thread->GlobalConstants()->GetUndefined();
191     }
192     ASSERT(moduleEnvironment.IsTaggedArray());
193     JSTaggedValue resolvedBinding = TaggedArray::Cast(moduleEnvironment.GetTaggedObject())->Get(thread, index);
194     GetModuleValueFromBindingInfo info { thread, currentModuleHdl, resolvedBinding, index, false };
195     if (resolvedBinding.IsResolvedIndexBinding()) {
196         return GetModuleValueFromIndexBinding<isLazy>(info);
197     }
198     if (resolvedBinding.IsResolvedBinding()) {
199         return GetModuleValueFromBinding<isLazy>(info);
200     }
201     if (resolvedBinding.IsResolvedRecordIndexBinding()) {
202         return GetModuleValueFromRecordIndexBinding<isLazy>(info);
203     }
204     if (resolvedBinding.IsResolvedRecordBinding()) { // LCOV_EXCL_BR_LINE
205         return GetModuleValueFromRecordBinding<isLazy>(info);
206     }
207     std::ostringstream oss;
208     curModule.Dump(thread, oss);
209     LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding"
210         << ", index: " << index << ", currentModule: " << oss.str();
211     UNREACHABLE();
212 }
213 
214 template JSTaggedValue ModuleValueAccessor::GetModuleValueOuterInternal<true>(JSThread *, int32_t, JSTaggedValue);
215 template JSTaggedValue ModuleValueAccessor::GetModuleValueOuterInternal<false>(JSThread *, int32_t, JSTaggedValue);
216 
217 template <bool isLazy>
GetSendableModuleValueOuterInternal(JSThread * thread,int32_t index,JSTaggedValue curModule)218 JSTaggedValue ModuleValueAccessor::GetSendableModuleValueOuterInternal(JSThread *thread, int32_t index,
219     JSTaggedValue curModule)
220 {
221     if (curModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
222         LOG_FULL(FATAL) << "GetSendableModuleValueOuterInternal currentModule failed";
223         UNREACHABLE();
224     }
225     JSHandle<SourceTextModule> module(thread, curModule.GetTaggedObject());
226     JSTaggedValue moduleEnvironment = module->GetEnvironment(thread);
227     if (moduleEnvironment.IsUndefined()) {
228         return thread->GlobalConstants()->GetUndefined();
229     }
230     ASSERT(moduleEnvironment.IsTaggedArray());
231     JSTaggedValue resolvedBinding = TaggedArray::Cast(moduleEnvironment.GetTaggedObject())->Get(thread, index);
232     GetModuleValueFromBindingInfo info { thread, module, resolvedBinding, index, true };
233     if (resolvedBinding.IsResolvedRecordIndexBinding()) {
234         return GetModuleValueFromRecordIndexBinding<isLazy>(info);
235     }
236     if (resolvedBinding.IsResolvedIndexBinding()) {
237         return GetModuleValueFromIndexBinding<isLazy>(info);
238     }
239     if (resolvedBinding.IsResolvedRecordBinding()) {
240         return GetModuleValueFromRecordBinding<isLazy>(info);
241     }
242     LOG_ECMA(FATAL) << "Unexpect binding";
243     UNREACHABLE();
244 }
245 
246 template JSTaggedValue ModuleValueAccessor::GetSendableModuleValueOuterInternal<true>(JSThread *, int32_t,
247     JSTaggedValue);
248 template JSTaggedValue ModuleValueAccessor::GetSendableModuleValueOuterInternal<false>(JSThread *, int32_t,
249     JSTaggedValue);
250 
GetModuleNamespaceInternal(JSThread * thread,int32_t index,JSTaggedValue curModule)251 JSTaggedValue ModuleValueAccessor::GetModuleNamespaceInternal(JSThread *thread, int32_t index, JSTaggedValue curModule)
252 {
253     if (curModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
254         LOG_FULL(FATAL) << "GetModuleNamespace currentModule failed";
255         UNREACHABLE();
256     }
257     JSHandle<SourceTextModule> module(thread, SourceTextModule::Cast(curModule));
258     JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules(thread));
259     JSHandle<SourceTextModule> requiredModule =
260         SourceTextModule::GetModuleFromCacheOrResolveNewOne(thread, module, requestedModules, index);
261     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
262     ASSERT(requiredModule.GetTaggedValue().IsSourceTextModule());
263 
264     ModuleTypes moduleType = requiredModule->GetTypes();
265     // if requiredModule is Native module
266     if (SourceTextModule::IsNativeModule(moduleType)) {
267         LogModuleLoadInfo(thread, module, requiredModule, -1, false);
268         return requiredModule->GetModuleValue(thread, 0, false);
269     }
270     // if requiredModule is CommonJS
271     if (SourceTextModule::IsCjsModule(moduleType)) {
272         CString cjsModuleName = SourceTextModule::GetModuleName(requiredModule.GetTaggedValue());
273         JSHandle<JSTaggedValue> moduleNameHandle(thread->GetEcmaVM()->GetFactory()->NewFromUtf8(cjsModuleName));
274         LogModuleLoadInfo(thread, module, requiredModule, -1, false);
275         return CjsModule::SearchFromModuleCache(thread, moduleNameHandle).GetTaggedValue();
276     }
277     // if requiredModule is ESM
278     JSHandle<JSTaggedValue> moduleNamespace = SourceTextModule::GetModuleNamespace(thread, requiredModule);
279     ASSERT(moduleNamespace->IsModuleNamespace());
280     LogModuleLoadInfo(thread, module, requiredModule, -1, false);
281     return moduleNamespace.GetTaggedValue();
282 }
StoreModuleValueInternal(JSThread * thread,JSHandle<SourceTextModule> & curModule,int32_t index,JSTaggedValue value)283 void ModuleValueAccessor::StoreModuleValueInternal(JSThread *thread, JSHandle<SourceTextModule> &curModule,
284     int32_t index, JSTaggedValue value)
285 {
286     if (curModule.GetTaggedValue().IsUndefined()) { // LCOV_EXCL_BR_LINE
287         LOG_FULL(FATAL) << "StoreModuleValue currentModule failed";
288         UNREACHABLE();
289     }
290     JSHandle<JSTaggedValue> valueHandle(thread, value);
291     SourceTextModule::StoreModuleValue(thread, curModule, index, valueHandle);
292 }
293 
294 template <bool isLazy>
GetModuleValueFromIndexBinding(const GetModuleValueFromBindingInfo & info)295 JSTaggedValue ModuleValueAccessor::GetModuleValueFromIndexBinding(const GetModuleValueFromBindingInfo &info)
296 {
297     JSHandle<ResolvedIndexBinding> binding(info.thread, info.resolvedBinding);
298     JSMutableHandle<SourceTextModule> resolvedModule(info.thread, binding->GetModule(info.thread));
299     if (!info.isSendable && info.thread->GetStageOfHotReload() == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) {
300         const JSHandle<JSTaggedValue> resolvedModuleOfHotReload =
301             info.thread->GetEcmaVM()->FindPatchModule(resolvedModule->GetEcmaModuleRecordNameString());
302         if (!resolvedModuleOfHotReload->IsHole()) {
303             resolvedModule.Update(resolvedModuleOfHotReload);
304         }
305     }
306     if (info.isSendable && isLazy) { // bug need fix
307         SourceTextModule::Evaluate(info.thread, resolvedModule);
308     } else {
309         EvaluateModuleIfNeeded<isLazy>(info.thread, resolvedModule);
310     }
311     RETURN_VALUE_IF_ABRUPT_COMPLETION(info.thread, JSTaggedValue::Exception());
312     if (SourceTextModule::IsSharedModule(resolvedModule)) {
313         JSHandle<SourceTextModule> sharedModule = SharedModuleManager::GetInstance()->GetSModule(
314             info.thread, resolvedModule->GetEcmaModuleRecordNameString());
315         if (sharedModule.GetTaggedValue().IsSourceTextModule()) {
316             resolvedModule.Update(sharedModule);
317         }
318     }
319     LogModuleLoadInfo(info.thread, info.module, resolvedModule, info.index, info.isSendable);
320     return GetModuleValue(info.thread, resolvedModule, binding->GetIndex());
321 }
322 
323 template JSTaggedValue ModuleValueAccessor::GetModuleValueFromIndexBinding<true>(
324     const GetModuleValueFromBindingInfo &);
325 template JSTaggedValue ModuleValueAccessor::GetModuleValueFromIndexBinding<false>(
326     const GetModuleValueFromBindingInfo &);
327 
328 template <bool isLazy>
GetModuleValueFromBinding(const GetModuleValueFromBindingInfo & info)329 JSTaggedValue ModuleValueAccessor::GetModuleValueFromBinding(const GetModuleValueFromBindingInfo &info)
330 {
331     JSHandle<ResolvedBinding> binding(info.thread, info.resolvedBinding);
332     JSHandle<SourceTextModule> resolvedModule(info.thread, binding->GetModule(info.thread));
333     if (UNLIKELY(!SourceTextModule::IsNativeModule(resolvedModule->GetTypes()) &&
334         !SourceTextModule::IsCjsModule(resolvedModule->GetTypes()))) {
335         std::ostringstream oss;
336         info.module.GetTaggedValue().Dump(info.thread, oss);
337         LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding"
338             << ", index: " << info.index << ", currentModule: " << oss.str();
339     }
340     EvaluateModuleIfNeeded<isLazy>(info.thread, resolvedModule);
341     RETURN_VALUE_IF_ABRUPT_COMPLETION(info.thread, JSTaggedValue::Exception());
342     LogModuleLoadInfo(info.thread, info.module, resolvedModule, info.index, false);
343     return UpdateBindingAndGetModuleValue(info.thread, info.module, resolvedModule, info.index,
344         binding->GetBindingName(info.thread));
345 }
346 
347 template JSTaggedValue ModuleValueAccessor::GetModuleValueFromBinding<true>(const GetModuleValueFromBindingInfo &);
348 template JSTaggedValue ModuleValueAccessor::GetModuleValueFromBinding<false>(const GetModuleValueFromBindingInfo &);
349 
350 template <bool isLazy>
GetModuleValueFromRecordIndexBinding(const GetModuleValueFromBindingInfo & info)351 JSTaggedValue ModuleValueAccessor::GetModuleValueFromRecordIndexBinding(const GetModuleValueFromBindingInfo &info)
352 {
353     JSHandle<ResolvedRecordIndexBinding> binding(info.thread, info.resolvedBinding);
354     JSHandle<SourceTextModule> resolvedModule = GetResolvedModule<isLazy, ResolvedRecordIndexBinding>(
355         info.thread, info.module, binding,
356         ModulePathHelper::Utf8ConvertToString(info.thread, binding->GetModuleRecord(info.thread)));
357     RETURN_VALUE_IF_ABRUPT_COMPLETION(info.thread, JSTaggedValue::Exception());
358     LogModuleLoadInfo(info.thread, info.module, resolvedModule, info.index, info.isSendable);
359     return GetModuleValue(info.thread, resolvedModule, binding->GetIndex());
360 }
361 
362 template JSTaggedValue ModuleValueAccessor::GetModuleValueFromRecordIndexBinding<true>(
363     const GetModuleValueFromBindingInfo &);
364 template JSTaggedValue ModuleValueAccessor::GetModuleValueFromRecordIndexBinding<false>(
365     const GetModuleValueFromBindingInfo &);
366 
367 template <bool isLazy>
GetModuleValueFromRecordBinding(const GetModuleValueFromBindingInfo & info)368 JSTaggedValue ModuleValueAccessor::GetModuleValueFromRecordBinding(const GetModuleValueFromBindingInfo &info)
369 {
370     JSHandle<ResolvedRecordBinding> binding(info.thread, info.resolvedBinding);
371     JSHandle<SourceTextModule> resolvedModule = GetResolvedModule<isLazy, ResolvedRecordBinding>(
372         info.thread, info.module, binding,
373         ModulePathHelper::Utf8ConvertToString(info.thread, binding->GetModuleRecord(info.thread)));
374     RETURN_VALUE_IF_ABRUPT_COMPLETION(info.thread, JSTaggedValue::Exception());
375     LogModuleLoadInfo(info.thread, info.module, resolvedModule, info.index, info.isSendable);
376     return GetNativeOrCjsModuleValue(info.thread, resolvedModule, binding->GetBindingName(info.thread));
377 }
378 
379 template JSTaggedValue ModuleValueAccessor::GetModuleValueFromRecordBinding<true>(
380     const GetModuleValueFromBindingInfo &);
381 template JSTaggedValue ModuleValueAccessor::GetModuleValueFromRecordBinding<false>(
382     const GetModuleValueFromBindingInfo &);
383 
UpdateBindingAndGetModuleValue(JSThread * thread,JSHandle<SourceTextModule> module,JSHandle<SourceTextModule> requiredModule,int32_t index,JSTaggedValue bindingName)384 JSTaggedValue ModuleValueAccessor::UpdateBindingAndGetModuleValue(JSThread *thread, JSHandle<SourceTextModule> module,
385     JSHandle<SourceTextModule> requiredModule, int32_t index, JSTaggedValue bindingName)
386 {
387     // Get esm environment
388     JSHandle<JSTaggedValue> moduleEnvironment(thread, module->GetEnvironment(thread));
389     ASSERT(!moduleEnvironment->IsUndefined());
390     JSHandle<TaggedArray> environment = JSHandle<TaggedArray>::Cast(moduleEnvironment);
391     // rebinding here
392     JSHandle<JSTaggedValue> exports = GetNativeOrCjsExports(thread, requiredModule.GetTaggedValue());
393     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
394     JSHandle<JSTaggedValue> exportName(thread, bindingName);
395     JSHandle<JSTaggedValue> resolution =
396         SourceTextModule::ResolveExportObject(thread, requiredModule, exports, exportName);
397     // ii. If resolution is null or "ambiguous", throw a SyntaxError exception.
398     if (resolution->IsNull() || resolution->IsString()) {
399         CString requestMod = ModulePathHelper::ReformatPath(SourceTextModule::GetModuleName(
400             requiredModule.GetTaggedValue()));
401         CString recordStr = ModulePathHelper::ReformatPath(SourceTextModule::GetModuleName(
402             module.GetTaggedValue()));
403         CString msg = "the requested module '" + requestMod + SourceTextModule::GetResolveErrorReason(resolution) +
404             ModulePathHelper::Utf8ConvertToString(thread, bindingName) +
405             "' which imported by '" + recordStr + "'";
406         THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(
407             thread, ErrorType::SYNTAX_ERROR, msg.c_str(), JSTaggedValue::Exception());
408     }
409     // iii. Call envRec.CreateImportBinding(
410     // in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
411     ASSERT(resolution->IsResolvedIndexBinding());
412     ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolution.GetTaggedValue());
413     // for ResolvedBinding updated to ResolvedIndexBinding, set IsUpdatedFromResolvedBinding to true.
414     binding->SetIsUpdatedFromResolvedBinding(true);
415     environment->Set(thread, index, resolution);
416     return SourceTextModule::GetValueFromExportObject(thread, exports, binding->GetIndex());
417 }
418 
419 template <bool isLazy>
EvaluateModuleIfNeeded(JSThread * thread,JSHandle<SourceTextModule> module)420 void ModuleValueAccessor::EvaluateModuleIfNeeded(JSThread* thread, JSHandle<SourceTextModule> module)
421 {
422     if  (!isLazy) {
423         return;
424     }
425     if (module->GetStatus() >= ModuleStatus::EVALUATED) {
426         return;
427     }
428     const ModuleTypes moduleType = module->GetTypes();
429     if (SourceTextModule::IsNativeModule(moduleType)) {
430         SourceTextModule::EvaluateNativeModule(thread, module, moduleType);
431         return;
432     }
433     SourceTextModule::Evaluate(thread, module, nullptr, 0, ExecuteTypes::LAZY);
434 }
435 
436 template void ModuleValueAccessor::EvaluateModuleIfNeeded<true>(JSThread *, JSHandle<SourceTextModule>);
437 template void ModuleValueAccessor::EvaluateModuleIfNeeded<false>(JSThread *, JSHandle<SourceTextModule>);
438 
LogModuleLoadInfo(JSThread * thread,JSHandle<SourceTextModule> module,JSHandle<SourceTextModule> requiredModule,int32_t index,bool isSendable)439 void ModuleValueAccessor::LogModuleLoadInfo(JSThread* thread, JSHandle<SourceTextModule> module,
440     JSHandle<SourceTextModule> requiredModule, int32_t index, bool isSendable)
441 {
442     if (isSendable) {
443         return;
444     }
445     ModuleLogger *moduleLogger = thread->GetModuleLogger();
446     if (moduleLogger != nullptr) {
447         moduleLogger->InsertModuleLoadInfo(module, requiredModule, index);
448     }
449 }
GetNativeOrCjsExports(JSThread * thread,JSTaggedValue resolvedModule)450 JSHandle<JSTaggedValue> ModuleValueAccessor::GetNativeOrCjsExports(JSThread *thread, JSTaggedValue resolvedModule)
451 {
452     JSHandle<SourceTextModule> module(thread, resolvedModule);
453     // if cjsModule is not JSObject, means cjs uses default exports.
454     JSMutableHandle<JSTaggedValue> exports(thread, thread->GlobalConstants()->GetUndefined());
455     ModuleTypes moduleType = module->GetTypes();
456     if (SourceTextModule::IsNativeModule(moduleType)) {
457         exports.Update(module->GetModuleValue(thread, 0, false));
458         if (!exports->IsJSObject()) {
459             LOG_FULL(WARN) << "Load native module failed, so is " << SourceTextModule::GetModuleName(resolvedModule);
460         }
461         return exports;
462     }
463     if (SourceTextModule::IsCjsModule(moduleType)) {
464         CString cjsModuleName = SourceTextModule::GetModuleName(module.GetTaggedValue());
465         JSHandle<JSTaggedValue> moduleNameHandle(thread->GetEcmaVM()->GetFactory()->NewFromUtf8(cjsModuleName));
466         exports.Update(CjsModule::SearchFromModuleCache(thread, moduleNameHandle).GetTaggedValue());
467         if (exports->IsHole()) {
468             CString errorMsg =
469                 "Loading cjs module:" + SourceTextModule::GetModuleName(module.GetTaggedValue()) + ", failed";
470             JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception());
471             THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread,
472                 ErrorType::SYNTAX_ERROR, errorMsg.c_str(), exception);
473         }
474         return exports;
475     }
476     return exports;
477 }
478 
479 template <bool isLazy, typename BindingType>
GetResolvedModule(JSThread * thread,JSHandle<SourceTextModule> module,JSHandle<BindingType> binding,const CString & requestModuleRecordName)480 JSHandle<SourceTextModule> ModuleValueAccessor::GetResolvedModule(JSThread* thread, JSHandle<SourceTextModule> module,
481     JSHandle<BindingType> binding, const CString& requestModuleRecordName)
482 {
483     ModuleManager *moduleManager = thread->GetModuleManager();
484     const JSHandle<JSTaggedValue> cachedModule = moduleManager->TryGetImportedModule(requestModuleRecordName);
485     if (!cachedModule->IsUndefined()) {
486         JSHandle<SourceTextModule> resolvedModule = JSHandle<SourceTextModule>::Cast(cachedModule);
487         if (resolvedModule->GetStatus() >= ModuleStatus::EVALUATED) {
488             return resolvedModule;
489         }
490         if (isLazy) {
491             EvaluateModuleIfNeeded<isLazy>(thread, resolvedModule);
492             return resolvedModule;
493         }
494     }
495     CString fileName;
496     if constexpr (std::is_same<BindingType, ResolvedRecordIndexBinding>::value) {
497         fileName = ModulePathHelper::Utf8ConvertToString(thread, binding->GetAbcFileName(thread));
498     } else {
499         fileName = module->GetEcmaModuleFilenameString();
500     }
501     bool isMergedAbc = !module->GetEcmaModuleFilenameString().empty();
502     if (!JSPandaFileExecutor::LazyExecuteModule(thread, requestModuleRecordName, fileName,
503         isMergedAbc)) { // LCOV_EXCL_BR_LINE
504         LOG_ECMA(FATAL) << "LazyExecuteModule failed";
505     }
506     return moduleManager->HostGetImportedModule(requestModuleRecordName);
507 }
508 
509 template JSHandle<SourceTextModule> ModuleValueAccessor::GetResolvedModule<false, ResolvedRecordIndexBinding>(JSThread*,
510     JSHandle<SourceTextModule>, JSHandle<ResolvedRecordIndexBinding>, const CString &);
511 template JSHandle<SourceTextModule> ModuleValueAccessor::GetResolvedModule<true, ResolvedRecordIndexBinding>(JSThread*,
512     JSHandle<SourceTextModule>, JSHandle<ResolvedRecordIndexBinding>, const CString &);
513 template JSHandle<SourceTextModule> ModuleValueAccessor::GetResolvedModule<false, ResolvedRecordBinding>(JSThread*,
514     JSHandle<SourceTextModule>, JSHandle<ResolvedRecordBinding>, const CString &);
515 template JSHandle<SourceTextModule> ModuleValueAccessor::GetResolvedModule<true, ResolvedRecordBinding>(JSThread*,
516     JSHandle<SourceTextModule>, JSHandle<ResolvedRecordBinding>, const CString &);
517 
GetModuleValueInner(JSThread * thread,JSTaggedValue key)518 JSTaggedValue DeprecatedModuleValueAccessor::GetModuleValueInner(JSThread* thread, JSTaggedValue key)
519 {
520     JSTaggedValue currentModule = ModuleValueAccessor::GetCurrentModule(thread);
521     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
522         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
523         UNREACHABLE();
524     }
525     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(thread, key, false);
526 }
527 
GetModuleValueInner(JSThread * thread,JSTaggedValue key,JSTaggedValue jsFunc)528 JSTaggedValue DeprecatedModuleValueAccessor::GetModuleValueInner(JSThread* thread, JSTaggedValue key,
529     JSTaggedValue jsFunc)
530 {
531     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread);
532     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
533         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
534         UNREACHABLE();
535     }
536     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(thread, key, false);
537 }
538 
GetModuleValueOuter(JSThread * thread,JSTaggedValue key)539 JSTaggedValue DeprecatedModuleValueAccessor::GetModuleValueOuter(JSThread* thread, JSTaggedValue key)
540 {
541     JSTaggedValue currentModule = ModuleValueAccessor::GetCurrentModule(thread);
542     return GetModuleValueOuterInternal(thread, key, currentModule);
543 }
544 
GetModuleValueOuter(JSThread * thread,JSTaggedValue key,JSTaggedValue jsFunc)545 JSTaggedValue DeprecatedModuleValueAccessor::GetModuleValueOuter(JSThread* thread, JSTaggedValue key,
546     JSTaggedValue jsFunc)
547 {
548     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread);
549     return GetModuleValueOuterInternal(thread, key, currentModule);
550 }
551 
GetModuleNamespace(JSThread * thread,JSTaggedValue localName)552 JSTaggedValue DeprecatedModuleValueAccessor::GetModuleNamespace(JSThread* thread, JSTaggedValue localName)
553 {
554     JSTaggedValue currentModule = ModuleValueAccessor::GetCurrentModule(thread);
555     return GetModuleNamespaceInternal(thread, localName, currentModule);
556 }
557 
GetModuleNamespace(JSThread * thread,JSTaggedValue localName,JSTaggedValue curFunc)558 JSTaggedValue DeprecatedModuleValueAccessor::GetModuleNamespace(JSThread* thread, JSTaggedValue localName,
559     JSTaggedValue curFunc)
560 {
561     JSTaggedValue currentModule = JSFunction::Cast(curFunc.GetTaggedObject())->GetModule(thread);
562     return GetModuleNamespaceInternal(thread, localName, currentModule);
563 }
StoreModuleValue(JSThread * thread,JSTaggedValue key,JSTaggedValue value)564 void DeprecatedModuleValueAccessor::StoreModuleValue(JSThread* thread, JSTaggedValue key, JSTaggedValue value)
565 {
566     JSHandle<SourceTextModule> currentModule(thread, ModuleValueAccessor::GetCurrentModule(thread));
567     StoreModuleValueInternal(thread, currentModule, key, value);
568 }
569 
StoreModuleValue(JSThread * thread,JSTaggedValue key,JSTaggedValue value,JSTaggedValue jsFunc)570 void DeprecatedModuleValueAccessor::StoreModuleValue(JSThread* thread, JSTaggedValue key, JSTaggedValue value,
571     JSTaggedValue jsFunc)
572 {
573     JSHandle<SourceTextModule> currentModule(thread, JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(thread));
574     StoreModuleValueInternal(thread, currentModule, key, value);
575 }
GetModuleValueOuterInternal(JSThread * thread,JSTaggedValue key,JSTaggedValue curModule)576 JSTaggedValue DeprecatedModuleValueAccessor::GetModuleValueOuterInternal(JSThread* thread, JSTaggedValue key,
577     JSTaggedValue curModule)
578 {
579     if (curModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
580         LOG_FULL(FATAL) << "GetModuleValueOutter currentModule failed";
581         UNREACHABLE();
582     }
583     JSTaggedValue moduleEnvironment = SourceTextModule::Cast(curModule.GetTaggedObject())->GetEnvironment(thread);
584     if (moduleEnvironment.IsUndefined()) {
585         return thread->GlobalConstants()->GetUndefined();
586     }
587     int entry = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->FindEntry(thread, key);
588     if (entry == -1) {
589         return thread->GlobalConstants()->GetUndefined();
590     }
591     JSTaggedValue resolvedBinding = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->GetValue(thread, entry);
592     ASSERT(resolvedBinding.IsResolvedBinding());
593     ResolvedBinding *binding = ResolvedBinding::Cast(resolvedBinding.GetTaggedObject());
594     JSTaggedValue resolvedModule = binding->GetModule(thread);
595     ASSERT(resolvedModule.IsSourceTextModule());
596     SourceTextModule *module = SourceTextModule::Cast(resolvedModule.GetTaggedObject());
597     if (module->GetTypes() == ModuleTypes::CJS_MODULE) {
598         CString cjsModuleName = SourceTextModule::GetModuleName(JSTaggedValue(module));
599         JSHandle<JSTaggedValue> moduleNameHandle(thread->GetEcmaVM()->GetFactory()->NewFromUtf8(cjsModuleName));
600         return CjsModule::SearchFromModuleCache(thread, moduleNameHandle).GetTaggedValue();
601     }
602     return module->GetModuleValue(thread, binding->GetBindingName(thread), false);
603 }
GetModuleNamespaceInternal(JSThread * thread,JSTaggedValue localName,JSTaggedValue curModule)604 JSTaggedValue DeprecatedModuleValueAccessor::GetModuleNamespaceInternal(JSThread* thread, JSTaggedValue localName,
605     JSTaggedValue curModule)
606 {
607     if (curModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
608         LOG_FULL(FATAL) << "GetModuleNamespace currentModule failed";
609         UNREACHABLE();
610     }
611     JSTaggedValue moduleEnvironment = SourceTextModule::Cast(curModule.GetTaggedObject())->GetEnvironment(thread);
612     if (moduleEnvironment.IsUndefined()) {
613         return thread->GlobalConstants()->GetUndefined();
614     }
615     int entry = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->FindEntry(thread, localName);
616     if (entry == -1) {
617         return thread->GlobalConstants()->GetUndefined();
618     }
619     JSTaggedValue moduleNamespace = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->GetValue(thread, entry);
620     ASSERT(moduleNamespace.IsModuleNamespace());
621     return moduleNamespace;
622 }
623 
StoreModuleValueInternal(JSThread * thread,JSHandle<SourceTextModule> & curModule,JSTaggedValue key,JSTaggedValue value)624 void DeprecatedModuleValueAccessor::StoreModuleValueInternal(JSThread* thread, JSHandle<SourceTextModule> &curModule,
625     JSTaggedValue key, JSTaggedValue value)
626 {
627     if (curModule.GetTaggedValue().IsUndefined()) { // LCOV_EXCL_BR_LINE
628         LOG_FULL(FATAL) << "StoreModuleValue currentModule failed";
629         UNREACHABLE();
630     }
631     JSHandle<JSTaggedValue> keyHandle(thread, key);
632     JSHandle<JSTaggedValue> valueHandle(thread, value);
633     SourceTextModule::StoreModuleValue(thread, curModule, keyHandle, valueHandle);
634 }
635 } // namespace panda::ecmascript
636