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