1/*
2 * Copyright (c) 2021-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/js_module_source_text.h"
17
18#include "ecmascript/builtins/builtins_promise.h"
19#include "ecmascript/interpreter/interpreter.h"
20#include "ecmascript/jobs/micro_job_queue.h"
21#include "ecmascript/jspandafile/js_pandafile_executor.h"
22#include "ecmascript/jspandafile/js_pandafile_manager.h"
23#include "ecmascript/module/module_logger.h"
24#include "ecmascript/module/js_shared_module_manager.h"
25#include "ecmascript/module/module_path_helper.h"
26#include "ecmascript/object_fast_operator-inl.h"
27#include "ecmascript/runtime_lock.h"
28#include "ecmascript/patch/quick_fix_manager.h"
29
30namespace panda::ecmascript {
31using PathHelper = base::PathHelper;
32using StringHelper = base::StringHelper;
33using GlobalError = containers::ContainerError;
34
35CVector<std::string> SourceTextModule::GetExportedNames(JSThread *thread, const JSHandle<SourceTextModule> &module,
36                                                        const JSHandle<TaggedArray> &exportStarSet)
37{
38    CVector<std::string> exportedNames;
39    // 1. Let module be this Source Text Module Record.
40    // 2. If exportStarSet contains module, then
41    if (exportStarSet->GetIdx(module.GetTaggedValue()) != TaggedArray::MAX_ARRAY_INDEX) {
42        // a. Assert: We've reached the starting point of an import * circularity.
43        // b. Return a new empty List.
44        return exportedNames;
45    }
46    // 3. Append module to exportStarSet.
47    size_t len = exportStarSet->GetLength();
48    JSHandle<TaggedArray> newExportStarSet = TaggedArray::SetCapacity(thread, exportStarSet, len + 1);
49    newExportStarSet->Set(thread, len, module.GetTaggedValue());
50
51    JSTaggedValue entryValue = module->GetLocalExportEntries();
52    // 5. For each ExportEntry Record e in module.[[LocalExportEntries]], do
53    AddExportName<LocalExportEntry>(thread, entryValue, exportedNames);
54
55    // 6. For each ExportEntry Record e in module.[[IndirectExportEntries]], do
56    entryValue = module->GetIndirectExportEntries();
57    AddExportName<IndirectExportEntry>(thread, entryValue, exportedNames);
58
59    entryValue = module->GetStarExportEntries();
60    auto globalConstants = thread->GlobalConstants();
61    if (!entryValue.IsUndefined()) {
62        JSMutableHandle<StarExportEntry> ee(thread, globalConstants->GetUndefined());
63        JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
64
65        // 7. For each ExportEntry Record e in module.[[StarExportEntries]], do
66        JSHandle<TaggedArray> starExportEntries(thread, entryValue);
67        size_t starExportEntriesLen = starExportEntries->GetLength();
68        for (size_t idx = 0; idx < starExportEntriesLen; idx++) {
69            ee.Update(starExportEntries->Get(idx));
70            // a. Let requestedModule be ? HostResolveImportedModule(module, e.[[ModuleRequest]]).
71            moduleRequest.Update(ee->GetModuleRequest());
72            SetExportName(thread, moduleRequest, module, exportedNames, newExportStarSet);
73            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, exportedNames);
74        }
75    }
76    return exportedNames;
77}
78
79// new way with module
80JSHandle<JSTaggedValue> SourceTextModule::HostResolveImportedModuleWithMerge(JSThread *thread,
81    const JSHandle<SourceTextModule> &module, const JSHandle<JSTaggedValue> &moduleRequest, bool executeFromJob)
82{
83    CString moduleRequestName = ModulePathHelper::Utf8ConvertToString(moduleRequest.GetTaggedValue());
84    CString requestStr = ReplaceModuleThroughFeature(thread, moduleRequestName);
85
86    CString baseFilename {};
87    StageOfHotReload stageOfHotReload = thread->GetCurrentEcmaContext()->GetStageOfHotReload();
88    if (stageOfHotReload == StageOfHotReload::BEGIN_EXECUTE_PATCHMAIN ||
89        stageOfHotReload == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) {
90        baseFilename = thread->GetEcmaVM()->GetQuickFixManager()->GetBaseFileName(module);
91    } else {
92        baseFilename = module->GetEcmaModuleFilenameString();
93    }
94
95    auto moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
96    auto [isNative, moduleType] = SourceTextModule::CheckNativeModule(requestStr);
97    if (isNative) {
98        if (moduleManager->IsLocalModuleLoaded(requestStr)) {
99            return JSHandle<JSTaggedValue>(moduleManager->HostGetImportedModule(requestStr));
100        }
101        return moduleManager->ResolveNativeModule(requestStr, baseFilename, moduleType);
102    }
103    CString recordName = module->GetEcmaModuleRecordNameString();
104    std::shared_ptr<JSPandaFile> jsPandaFile =
105        JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, baseFilename, recordName);
106    if (jsPandaFile == nullptr) { // LCOV_EXCL_BR_LINE
107        LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " <<  baseFilename;
108    }
109
110    CString outFileName = baseFilename;
111    CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(
112        thread, jsPandaFile.get(), outFileName, recordName, requestStr);
113    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
114
115#if defined(PANDA_TARGET_WINDOWS) || defined(PANDA_TARGET_MACOS)
116    if (entryPoint == ModulePathHelper::PREVIEW_OF_ACROSS_HAP_FLAG) {
117        THROW_SYNTAX_ERROR_AND_RETURN(thread, "", thread->GlobalConstants()->GetHandledUndefined());
118    }
119#endif
120    return SharedModuleManager::GetInstance()->ResolveImportedModuleWithMerge(thread, outFileName, entryPoint,
121                                                                              executeFromJob);
122}
123
124// old way with bundle
125JSHandle<JSTaggedValue> SourceTextModule::HostResolveImportedModule(JSThread *thread,
126                                                                    const JSHandle<SourceTextModule> &module,
127                                                                    const JSHandle<JSTaggedValue> &moduleRequest,
128                                                                    bool executeFromJob)
129{
130    auto moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
131    CString moduleRequestStr = ModulePathHelper::Utf8ConvertToString(moduleRequest.GetTaggedValue());
132    if (moduleManager->IsLocalModuleLoaded(moduleRequestStr)) {
133        return JSHandle<JSTaggedValue>(moduleManager->HostGetImportedModule(moduleRequestStr));
134    }
135
136    CString dirname = base::PathHelper::ResolveDirPath(module->GetEcmaModuleFilenameString());
137    CString moduleFilename = ResolveFilenameFromNative(thread, dirname, moduleRequestStr);
138    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
139    return SharedModuleManager::GetInstance()->ResolveImportedModule(thread,
140        moduleFilename, executeFromJob);
141}
142
143bool SourceTextModule::CheckCircularImport(const JSHandle<SourceTextModule> &module,
144    const JSHandle<JSTaggedValue> &exportName,
145    CVector<std::pair<JSHandle<SourceTextModule>, JSHandle<JSTaggedValue>>> &resolveVector)
146{
147    for (auto rr : resolveVector) {
148        // a. If module and r.[[Module]] are the same Module Record and
149        // SameValue(exportName, r.[[ExportName]]) is true, then
150        if (JSTaggedValue::SameValue(rr.first.GetTaggedValue(), module.GetTaggedValue()) &&
151            JSTaggedValue::SameValue(rr.second, exportName)) {
152            // i. Assert: This is a circular import request.
153            // ii. Return true.
154            return true;
155        }
156    }
157    return false;
158}
159
160JSHandle<JSTaggedValue> SourceTextModule::ResolveExportObject(JSThread *thread,
161                                                              const JSHandle<SourceTextModule> &module,
162                                                              const JSHandle<JSTaggedValue> &exports,
163                                                              const JSHandle<JSTaggedValue> &exportName)
164{
165    // Let module be this Source Text Module Record.
166    auto globalConstants = thread->GlobalConstants();
167    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
168    // For CJS, if exports is not JSObject, means the CJS module use default output
169    JSHandle<JSTaggedValue> defaultString = globalConstants->GetHandledDefaultString();
170    if (JSTaggedValue::SameValue(exportName, defaultString)) {
171        // bind with a number
172        return JSHandle<JSTaggedValue>::Cast(factory->NewResolvedIndexBindingRecord(module, -1));
173    }
174    if (exports->IsNativeModuleFailureInfo()) {
175        return JSHandle<JSTaggedValue>::Cast(factory->NewResolvedIndexBindingRecord(module, -1));
176    }
177    if (exports->IsJSObject()) {
178        JSHandle<JSTaggedValue> resolution(thread, JSTaggedValue::Hole());
179        JSObject *exportObject = JSObject::Cast(exports.GetTaggedValue().GetTaggedObject());
180        TaggedArray *properties = TaggedArray::Cast(exportObject->GetProperties().GetTaggedObject());
181        if (!properties->IsDictionaryMode()) {
182            JSHandle<JSHClass> jsHclass(thread, exportObject->GetJSHClass());
183            // Get layoutInfo and compare the input and output names of files
184            LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject());
185            if (layoutInfo->NumberOfElements() != 0) {
186                resolution = ResolveElementOfObject(thread, jsHclass, exportName, module);
187            }
188        } else {
189            NameDictionary *dict = NameDictionary::Cast(properties);
190            int entry = dict->FindEntry(exportName.GetTaggedValue());
191            if (entry != -1) {
192                resolution = JSHandle<JSTaggedValue>::Cast(factory->NewResolvedIndexBindingRecord(module, entry));
193            }
194        }
195        if (!resolution->IsUndefined()) {
196            return resolution;
197        }
198    }
199    return globalConstants->GetHandledNull();
200}
201
202JSHandle<JSTaggedValue> SourceTextModule::ResolveNativeStarExport(JSThread *thread,
203                                                                  const JSHandle<SourceTextModule> &nativeModule,
204                                                                  const JSHandle<JSTaggedValue> &exportName)
205{
206    if (nativeModule->GetStatus() != ModuleStatus::EVALUATED) {
207        auto moduleType = nativeModule->GetTypes();
208        if (!LoadNativeModule(thread, nativeModule, moduleType)) {
209            return thread->GlobalConstants()->GetHandledNull();
210        }
211        nativeModule->SetStatus(ModuleStatus::EVALUATED);
212    }
213
214    JSHandle<JSTaggedValue> nativeExports(thread, nativeModule->GetModuleValue(thread, 0, false));
215    return SourceTextModule::ResolveExportObject(thread, nativeModule, nativeExports, exportName);
216}
217
218JSHandle<JSTaggedValue> SourceTextModule::ResolveCjsStarExport(JSThread *thread,
219                                                               const JSHandle<SourceTextModule> &cjsModule,
220                                                               const JSHandle<JSTaggedValue> &exportName)
221{
222    if (cjsModule->GetStatus() != ModuleStatus::EVALUATED) {
223        SourceTextModule::ModuleExecution(thread, cjsModule);
224        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, thread->GlobalConstants()->GetHandledNull());
225        cjsModule->SetStatus(ModuleStatus::EVALUATED);
226    }
227
228    CString moduleName = GetModuleName(cjsModule.GetTaggedValue());
229    JSHandle<JSTaggedValue> cjsModuleName(thread->GetEcmaVM()->GetFactory()->NewFromUtf8(moduleName));
230    JSHandle<JSTaggedValue> cjsExports = CjsModule::SearchFromModuleCache(thread, cjsModuleName);
231    return SourceTextModule::ResolveExportObject(thread, cjsModule, cjsExports, exportName);
232}
233
234JSHandle<JSTaggedValue> SourceTextModule::ResolveExport(JSThread *thread, const JSHandle<SourceTextModule> &module,
235    const JSHandle<JSTaggedValue> &exportName,
236    CVector<std::pair<JSHandle<SourceTextModule>, JSHandle<JSTaggedValue>>> &resolveVector)
237{
238    // 1. Let module be this Source Text Module Record.
239    auto globalConstants = thread->GlobalConstants();
240    // Check if circular import request.
241    // 2.For each Record { [[Module]], [[ExportName]] } r in resolveVector, do
242    if (CheckCircularImport(module, exportName, resolveVector)) {
243        return globalConstants->GetHandledNull();
244    }
245    // 3. Append the Record { [[Module]]: module, [[ExportName]]: exportName } to resolveVector.
246    resolveVector.emplace_back(std::make_pair(module, exportName));
247    // 4. For each ExportEntry Record e in module.[[LocalExportEntries]], do
248    JSHandle<JSTaggedValue> localExportEntriesTv(thread, module->GetLocalExportEntries());
249    if (!localExportEntriesTv->IsUndefined()) {
250        JSHandle<JSTaggedValue> resolution = ResolveLocalExport(thread, localExportEntriesTv, exportName, module);
251        if (!resolution->IsUndefined()) {
252            return resolution;
253        }
254    }
255    // 5. For each ExportEntry Record e in module.[[IndirectExportEntries]], do
256    JSHandle<JSTaggedValue> indirectExportEntriesTv(thread, module->GetIndirectExportEntries());
257    if (!indirectExportEntriesTv->IsUndefined()) {
258        JSHandle<JSTaggedValue> resolution = ResolveIndirectExport(thread, indirectExportEntriesTv,
259                                                                   exportName, module, resolveVector);
260        RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
261        if (!resolution->IsUndefined()) {
262            return resolution;
263        }
264    }
265    // 6. If SameValue(exportName, "default") is true, then
266    JSHandle<JSTaggedValue> defaultString = globalConstants->GetHandledDefaultString();
267    if (JSTaggedValue::SameValue(exportName, defaultString)) {
268        // a. Assert: A default export was not explicitly defined by this module.
269        // b. Return null.
270        // c. NOTE: A default export cannot be provided by an export *.
271        return globalConstants->GetHandledNull();
272    }
273    // 7. Let starResolution be null.
274    JSMutableHandle<JSTaggedValue> starResolution(thread, globalConstants->GetNull());
275    // 8. For each ExportEntry Record e in module.[[StarExportEntries]], do
276    JSTaggedValue starExportEntriesTv = module->GetStarExportEntries();
277    if (starExportEntriesTv.IsUndefined()) {
278        return starResolution;
279    }
280    JSMutableHandle<StarExportEntry> ee(thread, globalConstants->GetUndefined());
281    JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
282    JSHandle<TaggedArray> starExportEntries(thread, starExportEntriesTv);
283    size_t starExportEntriesLen = starExportEntries->GetLength();
284    for (size_t idx = 0; idx < starExportEntriesLen; idx++) {
285        ee.Update(starExportEntries->Get(idx));
286        moduleRequest.Update(ee->GetModuleRequest());
287        JSHandle<JSTaggedValue> result = GetStarResolution(thread, exportName, moduleRequest,
288                                                           module, starResolution, resolveVector);
289        RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
290        if (result->IsString() || result->IsException()) {
291            return result;
292        }
293    }
294    // 9. Return starResolution.
295    return starResolution;
296}
297
298std::pair<bool, ModuleTypes> SourceTextModule::CheckNativeModule(const CString &moduleRequestName)
299{
300    if (moduleRequestName[0] != '@' ||
301        StringHelper::StringStartWith(moduleRequestName, ModulePathHelper::PREFIX_BUNDLE) ||
302        StringHelper::StringStartWith(moduleRequestName, ModulePathHelper::PREFIX_PACKAGE) ||
303        StringHelper::StringStartWith(moduleRequestName, ModulePathHelper::PREFIX_NORMALIZED_NOT_SO) ||
304        moduleRequestName.find(':') == CString::npos) {
305        return {false, ModuleTypes::UNKNOWN};
306    }
307
308    if (StringHelper::StringStartWith(moduleRequestName, ModulePathHelper::REQUIRE_NAPI_OHOS_PREFIX)) {
309        return {true, ModuleTypes::OHOS_MODULE};
310    }
311    /*
312    * moduleRequestName: @app:xxx/xxx
313    *                  : @normalized:Y&xxx
314    */
315    if (StringHelper::StringStartWith(moduleRequestName, ModulePathHelper::REQUIRE_NAPI_APP_PREFIX) ||
316        StringHelper::StringStartWith(moduleRequestName, ModulePathHelper::PREFIX_NORMALIZED_SO)) {
317        return {true, ModuleTypes::APP_MODULE};
318    }
319    if (StringHelper::StringStartWith(moduleRequestName, ModulePathHelper::REQUIRE_NAITVE_MODULE_PREFIX)) {
320        return {true, ModuleTypes::NATIVE_MODULE};
321    }
322    return {true, ModuleTypes::INTERNAL_MODULE};
323}
324
325Local<JSValueRef> SourceTextModule::GetRequireNativeModuleFunc(EcmaVM *vm, ModuleTypes moduleType)
326{
327    Local<ObjectRef> globalObject = JSNApi::GetGlobalObject(vm);
328    auto globalConstants = vm->GetJSThread()->GlobalConstants();
329    auto funcName = (moduleType == ModuleTypes::NATIVE_MODULE) ?
330        globalConstants->GetHandledRequireNativeModuleString() :
331        globalConstants->GetHandledRequireNapiString();
332    return globalObject->Get(vm, JSNApiHelper::ToLocal<StringRef>(funcName));
333}
334
335void SourceTextModule::MakeNormalizedAppArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
336    const CString &soPath, const CString &moduleName)
337{
338    CString soName = ModulePathHelper::GetNormalizedPathFromOhmUrl(soPath);
339    CString path = ModulePathHelper::GetBundleNameFromNormalized(vm, soPath) + PathHelper::SLASH_TAG + moduleName;
340    // use module name as so name
341    arguments[0] = StringRef::NewFromUtf8(vm, soName.c_str());
342    arguments.emplace_back(BooleanRef::New(vm, true));
343    arguments.emplace_back(StringRef::NewFromUtf8(vm, path.c_str()));
344}
345
346void SourceTextModule::MakeAppArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
347    const CString &soPath, const CString &moduleName, const CString &requestName)
348{
349    if (!StringHelper::StringStartWith(requestName, ModulePathHelper::REQUIRE_NAPI_APP_PREFIX)) {
350        return MakeNormalizedAppArgs(vm, arguments, soPath, moduleName);
351    }
352    size_t pos = soPath.find_last_of(PathHelper::SLASH_TAG);
353    if (pos == CString::npos) { // LCOV_EXCL_BR_LINE
354        LOG_FULL(FATAL) << "Invalid native module " << soPath;
355        UNREACHABLE();
356    }
357    CString soName = soPath.substr(pos + 1);
358    CString path = soPath.substr(0, pos);
359    // use module name as so name
360    arguments[0] = StringRef::NewFromUtf8(vm, soName.c_str());
361    arguments.emplace_back(BooleanRef::New(vm, true));
362    arguments.emplace_back(StringRef::NewFromUtf8(vm, path.c_str()));
363}
364
365void SourceTextModule::MakeInternalArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
366    const CString &moduleRequestName)
367{
368    arguments.emplace_back(BooleanRef::New(vm, false));
369    arguments.emplace_back(StringRef::NewFromUtf8(vm, ""));
370    CString moduleDir = PathHelper::GetInternalModulePrefix(moduleRequestName);
371    arguments.emplace_back(StringRef::NewFromUtf8(vm, moduleDir.c_str()));
372}
373
374Local<JSValueRef> SourceTextModule::LoadNativeModuleImpl(EcmaVM *vm, JSThread *thread,
375    const JSHandle<SourceTextModule> &requiredModule, ModuleTypes moduleType)
376{
377    CString moduleRequestName = requiredModule->GetEcmaModuleRecordNameString();
378    bool enableESMTrace = thread->GetEcmaVM()->GetJSOptions().EnableESMTrace();
379    if (enableESMTrace) {
380        CString traceInfo = "LoadNativeModule: " + moduleRequestName;
381        ECMA_BYTRACE_START_TRACE(HITRACE_TAG_ARK, traceInfo.c_str());
382    }
383    ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
384    if (moduleLogger != nullptr) {
385        moduleLogger->SetStartTime(moduleRequestName);
386    }
387    CString soName = PathHelper::GetStrippedModuleName(moduleRequestName);
388
389    CString fileName = requiredModule->GetEcmaModuleFilenameString();
390    CString moduleName = ModulePathHelper::GetModuleNameWithBaseFile(fileName);
391    std::vector<Local<JSValueRef>> arguments;
392    LOG_FULL(DEBUG) << "Request module is " << moduleRequestName;
393
394    arguments.emplace_back(StringRef::NewFromUtf8(vm, soName.c_str()));
395    if (moduleType == ModuleTypes::APP_MODULE) {
396        MakeAppArgs(vm, arguments, soName, moduleName, moduleRequestName);
397    } else if (moduleType == ModuleTypes::INTERNAL_MODULE) {
398        MakeInternalArgs(vm, arguments, moduleRequestName);
399    }
400    auto maybeFuncRef = GetRequireNativeModuleFunc(vm, moduleType);
401    // some function(s) may not registered in global object for non-main thread
402    if (!maybeFuncRef->IsFunction(vm)) {
403        LOG_FULL(WARN) << "Not found require func";
404        if (enableESMTrace) {
405            ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
406        }
407        if (moduleLogger != nullptr) {
408            moduleLogger->SetEndTime(moduleRequestName);
409        }
410        return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
411    }
412
413    Local<FunctionRef> funcRef = maybeFuncRef;
414    auto exportObject = funcRef->Call(vm, JSValueRef::Undefined(vm), arguments.data(), arguments.size());
415    if (enableESMTrace) {
416        ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
417    }
418    if (moduleLogger != nullptr) {
419        moduleLogger->SetEndTime(moduleRequestName);
420    }
421    return exportObject;
422}
423
424Local<JSValueRef> SourceTextModule::LoadNativeModuleMayThrowError(JSThread *thread,
425    const JSHandle<SourceTextModule> &requiredModule, ModuleTypes moduleType)
426{
427    EcmaVM *vm = thread->GetEcmaVM();
428    EscapeLocalScope scope(vm);
429
430    auto exportObject = LoadNativeModuleImpl(vm, thread, requiredModule, moduleType);
431    if (exportObject->IsNativeModuleFailureInfoObject(vm) || exportObject->IsUndefined()) {
432        CString errorMsg = "load native module failed.";
433        LOG_FULL(ERROR) << errorMsg.c_str();
434        auto error = GlobalError::ReferenceError(thread, errorMsg.c_str());
435        THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error,
436            JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined())));
437    }
438    return scope.Escape(exportObject);
439}
440
441bool SourceTextModule::LoadNativeModule(JSThread *thread, const JSHandle<SourceTextModule> &requiredModule,
442                                        ModuleTypes moduleType)
443{
444    EcmaVM *vm = thread->GetEcmaVM();
445    [[maybe_unused]] LocalScope scope(vm);
446
447    auto exportObject = LoadNativeModuleImpl(vm, thread, requiredModule, moduleType);
448    if (UNLIKELY(exportObject->IsUndefined())) {
449        CString fileName = requiredModule->GetEcmaModuleFilenameString();
450        CString moduleName = ModulePathHelper::GetModuleNameWithBaseFile(fileName);
451        LOG_FULL(ERROR) << "export objects of native so is undefined, so name is " << moduleName;
452        return false;
453    }
454    if (UNLIKELY(exportObject->IsNativeModuleFailureInfoObject(vm))) {
455        requiredModule->StoreModuleValue(thread, 0, JSNApiHelper::ToJSHandle(exportObject));
456        LOG_FULL(ERROR) << "loading fails, NativeModuleErrorObject is returned";
457        return false;
458    }
459    ASSERT(!thread->HasPendingException());
460    requiredModule->StoreModuleValue(thread, 0, JSNApiHelper::ToJSHandle(exportObject));
461    return true;
462}
463
464void SourceTextModule::EvaluateNativeModule(JSThread *thread, JSHandle<SourceTextModule> nativeModule,
465                                            ModuleTypes moduleType)
466{
467    if (nativeModule->GetStatus() == ModuleStatus::EVALUATED) {
468        return;
469    }
470    if (!SourceTextModule::LoadNativeModule(thread, nativeModule, moduleType)) {
471        LOG_FULL(INFO) << "LoadNativeModule " << nativeModule->GetEcmaModuleRecordNameString() << " failed";
472        return;
473    }
474    nativeModule->SetStatus(ModuleStatus::EVALUATED);
475}
476
477int SourceTextModule::HandleInstantiateException([[maybe_unused]] JSHandle<SourceTextModule> &module,
478                                                 const CVector<JSHandle<SourceTextModule>> &stack, int result)
479{
480    // a. For each module m in stack, do
481    for (auto mm : stack) {
482        // i. Assert: m.[[Status]] is "instantiating".
483        ASSERT(mm->GetStatus() == ModuleStatus::INSTANTIATING);
484        // ii. Set m.[[Status]] to "uninstantiated".
485        mm->SetStatus(ModuleStatus::UNINSTANTIATED);
486        // iii. Set m.[[Environment]] to undefined.
487        // iv. Set m.[[DFSIndex]] to undefined.
488        mm->SetDFSIndex(SourceTextModule::UNDEFINED_INDEX);
489        // v. Set m.[[DFSAncestorIndex]] to undefined.
490        mm->SetDFSAncestorIndex(SourceTextModule::UNDEFINED_INDEX);
491    }
492    // b. Assert: module.[[Status]] is "uninstantiated".
493    ASSERT(module->GetStatus() == ModuleStatus::UNINSTANTIATED);
494    // c. return result
495    return result;
496}
497
498int SourceTextModule::Instantiate(JSThread *thread, const JSHandle<JSTaggedValue> &moduleHdl,
499    bool executeFromJob)
500{
501    STACK_LIMIT_CHECK(thread, SourceTextModule::UNDEFINED_INDEX);
502    ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SourceTextModule::Instantiate");
503    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX);
504    JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleHdl);
505    // 1. Let module be this Source Text Module Record.
506    // 2. Assert: module.[[Status]] is one of UNLINKED, LINKED, EVALUATING-ASYNC, or EVALUATED.
507    ModuleStatus status = module->GetStatus();
508    ASSERT(status == ModuleStatus::UNINSTANTIATED || status == ModuleStatus::INSTANTIATED ||
509           status == ModuleStatus::EVALUATING_ASYNC || status == ModuleStatus::EVALUATED);
510    // 3. Let stack be a new empty List.
511    CVector<JSHandle<SourceTextModule>> stack;
512    // 4. Let result be InnerModuleInstantiation(module, stack, 0).
513    JSHandle<ModuleRecord> moduleRecord = JSHandle<ModuleRecord>::Cast(module);
514    int result = SourceTextModule::InnerModuleInstantiation(thread, moduleRecord, stack, 0, executeFromJob);
515    // 5. If result is an abrupt completion, then
516    if (thread->HasPendingException()) {
517        return HandleInstantiateException(module, stack, result);
518    }
519    // 6. Assert: module.[[Status]] is one of LINKED, EVALUATING-ASYNC, or EVALUATED.
520    status = module->GetStatus();
521    ASSERT(status == ModuleStatus::INSTANTIATED || status == ModuleStatus::EVALUATING_ASYNC ||
522           status == ModuleStatus::EVALUATED);
523    // 7. Assert: stack is empty.
524    ASSERT(stack.empty());
525    // 8. Return undefined.
526    SharedModuleManager::GetInstance()->TransferSModule(thread);
527    return SourceTextModule::UNDEFINED_INDEX;
528}
529
530std::optional<std::set<uint32_t>> SourceTextModule::GetConcurrentRequestedModules(const JSHandle<Method> &method)
531{
532    const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
533    const MethodLiteral *methodLiteral = method->GetMethodLiteral();
534    ASSERT(methodLiteral != nullptr);
535    return methodLiteral->GetConcurrentRequestedModules(jsPandaFile);
536}
537
538void SourceTextModule::DFSModuleInstantiation(JSHandle<SourceTextModule> &module,
539                                              CVector<JSHandle<SourceTextModule>> &stack)
540{
541    // 1. Assert: module occurs exactly once in stack.
542    // 2. Assert: module.[[DFSAncestorIndex]] is less than or equal to module.[[DFSIndex]].
543    int dfsAncIdx = module->GetDFSAncestorIndex();
544    int dfsIdx = module->GetDFSIndex();
545    ASSERT(dfsAncIdx <= dfsIdx);
546    // 3. If module.[[DFSAncestorIndex]] equals module.[[DFSIndex]], then
547    if (dfsAncIdx == dfsIdx) {
548        // a. Let done be false.
549        bool done = false;
550        // b. Repeat, while done is false,
551        while (!done) {
552            // i. Let requiredModule be the last element in stack.
553            JSHandle<SourceTextModule> requiredModule = stack.back();
554            // ii. Remove the last element of stack.
555            stack.pop_back();
556            // iii. Set requiredModule.[[Status]] to "instantiated".
557            requiredModule->SetStatus(ModuleStatus::INSTANTIATED);
558            // iv. If requiredModule and module are the same Module Record, set done to true.
559            if (JSTaggedValue::SameValue(module.GetTaggedValue(), requiredModule.GetTaggedValue())) {
560                done = true;
561            }
562        }
563    }
564}
565
566std::optional<int> SourceTextModule::HandleInnerModuleInstantiation(JSThread *thread,
567                                                                    JSHandle<SourceTextModule> &module,
568                                                                    JSMutableHandle<JSTaggedValue> &required,
569                                                                    CVector<JSHandle<SourceTextModule>> &stack,
570                                                                    int &index, bool executeFromJob)
571{
572    // a. Let requiredModule be ? HostResolveImportedModule(module, required).
573    JSMutableHandle<SourceTextModule> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
574    CString moduleRecordName = module->GetEcmaModuleRecordNameString();
575    if (moduleRecordName.empty()) {
576        JSHandle<JSTaggedValue> requiredVal =
577            SourceTextModule::HostResolveImportedModule(thread, module, required, executeFromJob);
578        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX);
579        requiredModule.Update(JSHandle<SourceTextModule>::Cast(requiredVal));
580    } else {
581        JSHandle<JSTaggedValue> requiredVal =
582            SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required, executeFromJob);
583        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX);
584        requiredModule.Update(JSHandle<SourceTextModule>::Cast(requiredVal));
585    }
586
587    // b. Set index to ? InnerModuleInstantiation(requiredModule, stack, index).
588    JSHandle<ModuleRecord> requiredModuleRecord = JSHandle<ModuleRecord>::Cast(requiredModule);
589    index = SourceTextModule::InnerModuleInstantiation(thread,
590        requiredModuleRecord, stack, index, executeFromJob);
591    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
592    // c. Assert: requiredModule.[[Status]] is one of LINKING, LINKED, EVALUATING-ASYNC, or EVALUATED.
593    ModuleStatus requiredModuleStatus = requiredModule->GetStatus();
594    ASSERT(requiredModuleStatus == ModuleStatus::INSTANTIATING ||
595           requiredModuleStatus == ModuleStatus::INSTANTIATED ||
596           requiredModuleStatus == ModuleStatus::EVALUATING_ASYNC ||
597           requiredModuleStatus == ModuleStatus::EVALUATED);
598    // d. Assert: requiredModule.[[Status]] is "instantiating" if and only if requiredModule is in stack.
599    // e. If requiredModule.[[Status]] is "instantiating", then
600    if (requiredModuleStatus == ModuleStatus::INSTANTIATING) {
601        // d. Assert: requiredModule.[[Status]] is "instantiating" if and only if requiredModule is in stack.
602        ASSERT(std::find(stack.begin(), stack.end(), requiredModule) != stack.end());
603        // i. Assert: requiredModule is a Source Text Module Record.
604        // ii. Set module.[[DFSAncestorIndex]] to min(
605        //    module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]]).
606        int dfsAncIdx = std::min(module->GetDFSAncestorIndex(), requiredModule->GetDFSAncestorIndex());
607        module->SetDFSAncestorIndex(dfsAncIdx);
608    }
609    return std::nullopt;
610}
611
612int SourceTextModule::InnerModuleInstantiation(JSThread *thread, const JSHandle<ModuleRecord> &moduleRecord,
613    CVector<JSHandle<SourceTextModule>> &stack, int index, bool executeFromJob)
614{
615    // Add a safepoint here to check if a suspension is needed.
616    thread->CheckSafepointIfSuspended();
617    // 1. If module is not a Source Text Module Record, then
618    if (!moduleRecord.GetTaggedValue().IsSourceTextModule()) {
619        STACK_LIMIT_CHECK(thread, SourceTextModule::UNDEFINED_INDEX);
620        SourceTextModule::Instantiate(thread, JSHandle<JSTaggedValue>::Cast(moduleRecord));
621        //  a. Perform ? module.Instantiate().
622        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
623        //  b. Return index.
624        return index;
625    }
626    JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
627    // 2. If module.[[Status]] is one of LINKING, LINKED, EVALUATING-ASYNC, or EVALUATED, then Return index.
628    ModuleStatus status = module->GetStatus();
629    if (status == ModuleStatus::INSTANTIATING ||
630        status == ModuleStatus::INSTANTIATED ||
631        status == ModuleStatus::EVALUATING_ASYNC ||
632        status == ModuleStatus::EVALUATED) {
633        return index;
634    }
635    // 3. Assert: module.[[Status]] is "uninstantiated".
636    ASSERT(status == ModuleStatus::UNINSTANTIATED);
637    // 4. Set module.[[Status]] to "instantiating".
638    module->SetStatus(ModuleStatus::INSTANTIATING);
639    // 5. Set module.[[DFSIndex]] to index.
640    module->SetDFSIndex(index);
641    // 6. Set module.[[DFSAncestorIndex]] to index.
642    module->SetDFSAncestorIndex(index);
643    // 7. Set index to index + 1.
644    index++;
645    // 8. Append module to stack.
646    stack.emplace_back(module);
647    // 9. For each String required that is an element of module.[[RequestedModules]], do
648    if (!module->GetRequestedModules().IsUndefined()) {
649        JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
650        size_t requestedModulesLen = requestedModules->GetLength();
651        JSMutableHandle<JSTaggedValue> required(thread, thread->GlobalConstants()->GetUndefined());
652        for (size_t idx = 0; idx < requestedModulesLen; idx++) {
653            required.Update(requestedModules->Get(idx));
654            auto result = HandleInnerModuleInstantiation(thread, module, required, stack, index, executeFromJob);
655            if (UNLIKELY(result.has_value())) { // exception occurs
656                return result.value();
657            }
658        }
659    }
660    // Adapter new opcode
661    // 10. Perform ? ModuleDeclarationEnvironmentSetup(module).
662    if (module->GetIsNewBcVersion()) {
663        SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(thread, module);
664    } else {
665        SourceTextModule::ModuleDeclarationEnvironmentSetup(thread, module);
666    }
667    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
668    DFSModuleInstantiation(module, stack);
669    return index;
670}
671
672void SourceTextModule::ModuleDeclarationEnvironmentSetup(JSThread *thread,
673                                                         const JSHandle<SourceTextModule> &module)
674{
675    CheckResolvedBinding(thread, module);
676    if (module->GetImportEntries().IsUndefined()) {
677        return;
678    }
679    ASSERT(!SourceTextModule::IsSharedModule(module));
680    // 2. Assert: All named exports from module are resolvable.
681    // 3. Let realm be module.[[Realm]].
682    // 4. Assert: realm is not undefined.
683    // 5. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
684    JSHandle<TaggedArray> importEntries(thread, module->GetImportEntries());
685    size_t importEntriesLen = importEntries->GetLength();
686    JSHandle<NameDictionary> map(NameDictionary::Create(thread,
687        NameDictionary::ComputeHashTableSize(importEntriesLen)));
688    // 6. Set module.[[Environment]] to env.
689    module->SetEnvironment(thread, map);
690    // 7. Let envRec be env's EnvironmentRecord.
691    JSMutableHandle<JSTaggedValue> envRec(thread, module->GetEnvironment());
692    ASSERT(!envRec->IsUndefined());
693    // 8. For each ImportEntry Record in in module.[[ImportEntries]], do
694    auto globalConstants = thread->GlobalConstants();
695    JSMutableHandle<ImportEntry> in(thread, globalConstants->GetUndefined());
696    JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
697    JSMutableHandle<JSTaggedValue> importName(thread, globalConstants->GetUndefined());
698    JSMutableHandle<JSTaggedValue> localName(thread, globalConstants->GetUndefined());
699    for (size_t idx = 0; idx < importEntriesLen; idx++) {
700        in.Update(importEntries->Get(idx));
701        localName.Update(in->GetLocalName());
702        importName.Update(in->GetImportName());
703        moduleRequest.Update(in->GetModuleRequest());
704        // a. Let importedModule be ! HostResolveImportedModule(module, in.[[ModuleRequest]]).
705        JSMutableHandle<SourceTextModule> importedModule(thread, thread->GlobalConstants()->GetUndefined());
706        CString moduleRecordName = module->GetEcmaModuleRecordNameString();
707        if (moduleRecordName.empty()) {
708            JSHandle<JSTaggedValue> importedVal =
709            SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest);
710            RETURN_IF_ABRUPT_COMPLETION(thread);
711            importedModule.Update(JSHandle<SourceTextModule>::Cast(importedVal));
712        } else {
713            JSHandle<JSTaggedValue> importedVal =
714                SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest);
715            RETURN_IF_ABRUPT_COMPLETION(thread);
716            importedModule.Update(JSHandle<SourceTextModule>::Cast(importedVal));
717        }
718        // c. If in.[[ImportName]] is "*", then
719        JSHandle<JSTaggedValue> starString = globalConstants->GetHandledStarString();
720        if (JSTaggedValue::SameValue(importName, starString)) {
721            // i. Let namespace be ? GetModuleNamespace(importedModule).
722            JSHandle<JSTaggedValue> moduleNamespace = SourceTextModule::GetModuleNamespace(thread, importedModule);
723            // ii. Perform ! envRec.CreateImmutableBinding(in.[[LocalName]], true).
724            // iii. Call envRec.InitializeBinding(in.[[LocalName]], namespace).
725            JSHandle<NameDictionary> mapHandle = JSHandle<NameDictionary>::Cast(envRec);
726            JSHandle<NameDictionary> newMap = NameDictionary::Put(thread, mapHandle, localName, moduleNamespace,
727                                                                  PropertyAttributes::Default());
728            envRec.Update(newMap);
729        } else {
730            // i. Let resolution be ? importedModule.ResolveExport(in.[[ImportName]], « »).
731            CVector<std::pair<JSHandle<SourceTextModule>, JSHandle<JSTaggedValue>>> resolveVector;
732            JSHandle<JSTaggedValue> resolution =
733                SourceTextModule::ResolveExport(thread, importedModule, importName, resolveVector);
734            RETURN_IF_ABRUPT_COMPLETION(thread);
735            // ii. If resolution is null or "ambiguous", throw a SyntaxError exception.
736            if (resolution->IsNull() || resolution->IsString()) {
737                CString requestMod = ModulePathHelper::ReformatPath(ConvertToString(moduleRequest.GetTaggedValue()));
738                CString msg = "the requested module '" + requestMod + GetResolveErrorReason(resolution) +
739                    ConvertToString(importName.GetTaggedValue());
740                if (!module->GetEcmaModuleRecordNameString().empty()) {
741                    CString recordStr = ModulePathHelper::ReformatPath(module->GetEcmaModuleRecordNameString());
742                    msg += "' which imported by '" + recordStr + "'";
743                } else {
744                    msg += "' which imported by '" + module->GetEcmaModuleFilenameString() + "'";
745                }
746                THROW_ERROR(thread, ErrorType::SYNTAX_ERROR, msg.c_str());
747            }
748            // iii. Call envRec.CreateImportBinding(
749            //    in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
750            JSHandle<NameDictionary> mapHandle = JSHandle<NameDictionary>::Cast(envRec);
751            JSHandle<NameDictionary> newMap = NameDictionary::Put(thread, mapHandle, localName, resolution,
752                                                                  PropertyAttributes::Default());
753            envRec.Update(newMap);
754        }
755    }
756
757    module->SetEnvironment(thread, envRec);
758}
759
760void SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(JSThread *thread,
761                                                              const JSHandle<SourceTextModule> &module)
762{
763    bool enableESMTrace = thread->GetEcmaVM()->GetJSOptions().EnableESMTrace();
764    if (enableESMTrace) {
765        CString traceInfo = "SourceTextModule::Instantiating: " +
766            module->GetEcmaModuleRecordNameString();
767        ECMA_BYTRACE_START_TRACE(HITRACE_TAG_ARK, traceInfo.c_str());
768    }
769    if (IsSharedModule(module) && SharedModuleManager::GetInstance()->IsInstantiatedSModule(thread, module)) {
770        if (enableESMTrace) {
771            ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
772        }
773        return;
774    }
775    CheckResolvedIndexBinding(thread, module);
776    if (module->GetImportEntries().IsUndefined()) {
777        if (enableESMTrace) {
778            ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
779        }
780        return;
781    }
782    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
783
784    // 2. Assert: All named exports from module are resolvable.
785    // 3. Let realm be module.[[Realm]].
786    // 4. Assert: realm is not undefined.
787    // 5. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
788    JSHandle<TaggedArray> importEntries(thread, module->GetImportEntries());
789    size_t importEntriesLen = importEntries->GetLength();
790    JSHandle<TaggedArray> arr = factory->NewTaggedArray(importEntriesLen);
791    // 7. Let envRec be env's EnvironmentRecord.
792    JSHandle<TaggedArray> envRec = arr;
793    // 8. For each ImportEntry Record in in module.[[ImportEntries]], do
794    auto globalConstants = thread->GlobalConstants();
795    JSMutableHandle<ImportEntry> in(thread, globalConstants->GetUndefined());
796    JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
797    JSMutableHandle<JSTaggedValue> importName(thread, globalConstants->GetUndefined());
798    for (size_t idx = 0; idx < importEntriesLen; idx++) {
799        in.Update(importEntries->Get(idx));
800        importName.Update(in->GetImportName());
801        moduleRequest.Update(in->GetModuleRequest());
802        // a. Let importedModule be ! HostResolveImportedModule(module, in.[[ModuleRequest]]).
803        JSMutableHandle<SourceTextModule> importedModule(thread, thread->GlobalConstants()->GetUndefined());
804        CString moduleRecordName = module->GetEcmaModuleRecordNameString();
805        if (moduleRecordName.empty()) {
806            JSHandle<JSTaggedValue> importedVal =
807                SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest);
808            RETURN_IF_ABRUPT_COMPLETION(thread);
809            importedModule.Update(JSHandle<SourceTextModule>::Cast(importedVal));
810        } else {
811            JSHandle<JSTaggedValue> importedVal =
812                SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest);
813            RETURN_IF_ABRUPT_COMPLETION(thread);
814            importedModule.Update(JSHandle<SourceTextModule>::Cast(importedVal));
815        }
816        // c. If in.[[ImportName]] is "*", then
817        JSHandle<JSTaggedValue> starString = globalConstants->GetHandledStarString();
818        if (JSTaggedValue::SameValue(importName, starString)) {
819            // need refactor
820            envRec = JSSharedModule::CloneEnvForSModule(thread, module, envRec);
821            module->SetEnvironment(thread, envRec);
822            if (enableESMTrace) {
823                ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
824            }
825            return;
826        }
827        // i. Let resolution be ? importedModule.ResolveExport(in.[[ImportName]], « »).
828        CVector<std::pair<JSHandle<SourceTextModule>, JSHandle<JSTaggedValue>>> resolveVector;
829        JSHandle<JSTaggedValue> resolution =
830            SourceTextModule::ResolveExport(thread, importedModule, importName, resolveVector);
831        RETURN_IF_ABRUPT_COMPLETION(thread);
832        // ii. If resolution is null or "ambiguous", throw a SyntaxError exception.
833        if (resolution->IsNull() || resolution->IsString()) {
834            CString requestMod = ModulePathHelper::ReformatPath(ConvertToString(moduleRequest.GetTaggedValue()));
835            CString msg = "the requested module '" + requestMod + GetResolveErrorReason(resolution) +
836                        ConvertToString(importName.GetTaggedValue());
837            if (!module->GetEcmaModuleRecordNameString().empty()) {
838                CString recordStr = ModulePathHelper::ReformatPath(
839                    module->GetEcmaModuleRecordNameString());
840                msg += "' which imported by '" + recordStr + "'";
841            } else {
842                msg += "' which imported by '" + module->GetEcmaModuleFilenameString() + "'";
843            }
844            THROW_ERROR(thread, ErrorType::SYNTAX_ERROR, msg.c_str());
845        }
846        // iii. Call envRec.CreateImportBinding(
847        //    in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
848        envRec->Set(thread, idx, resolution);
849    }
850    envRec = JSSharedModule::CloneEnvForSModule(thread, module, envRec);
851    module->SetEnvironment(thread, envRec);
852    if (enableESMTrace) {
853        ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
854    }
855}
856
857JSHandle<JSTaggedValue> SourceTextModule::GetModuleNamespace(JSThread *thread,
858                                                             const JSHandle<SourceTextModule> &module)
859{
860    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
861    // 1. Assert: module is an instance of a concrete subclass of Module Record.
862    // 2. Assert: module.[[Status]] is not "uninstantiated".
863    ASSERT(module->GetStatus() != ModuleStatus::UNINSTANTIATED);
864    // 3. Let namespace be module.[[Namespace]].
865    JSMutableHandle<JSTaggedValue> moduleNamespace(thread, module->GetNamespace().GetWeakRawValue());
866    // If namespace is undefined, then
867    if (moduleNamespace->IsUndefined()) {
868        // a. Let exportedNames be ? module.GetExportedNames(« »).
869        JSHandle<TaggedArray> exportStarSet = factory->EmptyArray();
870        CVector<std::string> exportedNames = SourceTextModule::GetExportedNames(thread, module, exportStarSet);
871        // b. Let unambiguousNames be a new empty List.
872        JSHandle<TaggedArray> unambiguousNames = factory->NewTaggedArray(exportedNames.size());
873        // c. For each name that is an element of exportedNames, do
874        size_t idx = 0;
875        for (std::string &name : exportedNames) {
876            // i. Let resolution be ? module.ResolveExport(name, « »).
877            CVector<std::pair<JSHandle<SourceTextModule>, JSHandle<JSTaggedValue>>> resolveVector;
878            JSHandle<JSTaggedValue> nameHandle = JSHandle<JSTaggedValue>::Cast(factory->NewFromStdString(name));
879            JSHandle<JSTaggedValue> resolution =
880                SourceTextModule::ResolveExport(thread, module, nameHandle, resolveVector);
881            RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
882            // ii. If resolution is a ResolvedBinding Record, append name to unambiguousNames.
883            if (resolution->IsModuleBinding()) {
884                unambiguousNames->Set(thread, idx, nameHandle);
885                idx++;
886            }
887        }
888        JSHandle<TaggedArray> fixUnambiguousNames = TaggedArray::SetCapacity(thread, unambiguousNames, idx);
889        JSHandle<JSTaggedValue> moduleTagged = JSHandle<JSTaggedValue>::Cast(module);
890        JSHandle<ModuleNamespace> np =
891            ModuleNamespace::ModuleNamespaceCreate(thread, moduleTagged, fixUnambiguousNames);
892        moduleNamespace.Update(np.GetTaggedValue());
893    }
894    return moduleNamespace;
895}
896
897void SourceTextModule::HandleEvaluateResult(JSThread *thread, JSHandle<SourceTextModule> &module,
898    JSHandle<PromiseCapability> &capability, const CVector<JSHandle<SourceTextModule>> &stack, int result)
899{
900    ModuleStatus status;
901    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
902    // 9. If result is an abrupt completion, then
903    if (thread->HasPendingException()) {
904        // a. For each module m in stack, do
905        for (auto mm : stack) {
906            // i. Assert: m.[[Status]] is "evaluating".
907            ASSERT(mm->GetStatus() == ModuleStatus::EVALUATING);
908            // ii. Set m.[[Status]] to "evaluated".
909            mm->SetStatus(ModuleStatus::EVALUATED);
910            // iii. Set m.[[EvaluationError]] to result.
911            mm->SetEvaluationError(result);
912        }
913        // b. Assert: module.[[Status]] is "evaluated" and module.[[EvaluationError]] is result.
914        status = module->GetStatus();
915        ASSERT(status == ModuleStatus::EVALUATED && module->GetEvaluationError() == result);
916        //d. Perform ! Call(capability.[[Reject]], undefined, « result.[[Value]] »).
917        JSHandle<JSTaggedValue> reject(thread, capability->GetReject());
918        JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
919        EcmaRuntimeCallInfo *info =
920            EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefined, undefined, 1);
921        RETURN_IF_ABRUPT_COMPLETION(thread);
922        info->SetCallArg(JSTaggedValue(result));
923        [[maybe_unused]] JSTaggedValue res = JSFunction::Call(info);
924        RETURN_IF_ABRUPT_COMPLETION(thread);
925    // 10. Else,
926    } else {
927        // a. Assert: module.[[Status]] is either EVALUATING-ASYNC or EVALUATED.
928        status = module->GetStatus();
929        ASSERT(status == ModuleStatus::EVALUATING_ASYNC || status == ModuleStatus::EVALUATED);
930        // b. Assert: module.[[EvaluationError]] is EMPTY.
931        ASSERT(module->GetEvaluationError() == SourceTextModule::UNDEFINED_INDEX);
932        // c. If module.[[AsyncEvaluation]] is false, then
933        //    i. Assert: module.[[Status]] is EVALUATED.
934        //    ii. Perform ! Call(capability.[[Resolve]], undefined, « undefined »).
935        if (!module->IsAsyncEvaluating()) {
936            ASSERT(status == ModuleStatus::EVALUATED);
937        }
938        // d. Assert: stack is empty.
939        ASSERT(stack.empty());
940    }
941}
942
943JSTaggedValue SourceTextModule::Evaluate(JSThread *thread, const JSHandle<SourceTextModule> &moduleHdl,
944                                         const void *buffer, size_t size, bool executeFromJob)
945{
946    ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SourceTextModule::Evaluate");
947    // 1. Let module be this Source Text Module Record.
948    // 2. Assert: module.[[Status]] is one of LINKED, EVALUATING-ASYNC, or EVALUATED.
949    JSMutableHandle<SourceTextModule> module(thread, moduleHdl);
950    ModuleStatus status = module->GetStatus();
951    ASSERT((status == ModuleStatus::INSTANTIATED || status == ModuleStatus::EVALUATING_ASYNC ||
952            status == ModuleStatus::EVALUATED));
953    // 3. If module.[[Status]] is either EVALUATING-ASYNC or EVALUATED, set module to module.[[CycleRoot]].
954    if (status == ModuleStatus::EVALUATING_ASYNC || status == ModuleStatus::EVALUATED) {
955        module.Update(module->GetCycleRoot());
956    }
957    // 4. If module.[[TopLevelCapability]] is not EMPTY, then
958    //     a. Return module.[[TopLevelCapability]].[[Promise]].
959    // 5. Let stack be a new empty List.
960    CVector<JSHandle<SourceTextModule>> stack;
961    // 6. Let capability be ! NewPromiseCapability(%Promise%).
962    auto vm = thread->GetEcmaVM();
963    JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
964    JSHandle<PromiseCapability> capability =
965        JSPromise::NewPromiseCapability(thread, JSHandle<JSTaggedValue>::Cast(env->GetPromiseFunction()));
966    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
967    // 7. Set module.[[TopLevelCapability]] to capability.
968    if (!SourceTextModule::IsSharedModule(module)) {
969        module->SetTopLevelCapability(thread, capability);
970    }
971
972    // 8. Let result be Completion(InnerModuleEvaluation(module, stack, 0)).
973    int result = SourceTextModule::InnerModuleEvaluation(thread, module, stack, 0, buffer, size, executeFromJob);
974    HandleEvaluateResult(thread, module, capability, stack, result);
975    if (!thread->HasPendingException() && !executeFromJob) {
976        job::MicroJobQueue::ExecutePendingJob(thread, thread->GetCurrentEcmaContext()->GetMicroJobQueue());
977    }
978    ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
979    if ((moduleLogger != nullptr) && !executeFromJob) {
980        moduleLogger->InsertEntryPointModule(module);
981    }
982    // Return capability.[[Promise]].
983    return capability->GetPromise();
984}
985
986int SourceTextModule::EvaluateForConcurrent(JSThread *thread, const JSHandle<SourceTextModule> &module,
987                                            const JSHandle<Method> &method)
988{
989    // 1. Let module be this Source Text Module Record.
990    // 2. Assert: module.[[Status]] is "instantiated" or "evaluated".
991    [[maybe_unused]] ModuleStatus status = module->GetStatus();
992    ASSERT((status == ModuleStatus::INSTANTIATED || status == ModuleStatus::EVALUATED));
993    // 4. Let result be InnerModuleEvaluation(module, stack, 0)
994    JSHandle<ModuleRecord> moduleRecord = JSHandle<ModuleRecord>::Cast(module);
995    int result = SourceTextModule::ModuleEvaluation(thread, moduleRecord, 0, method);
996    // 5. If result is an abrupt completion, then
997    if (thread->HasPendingException()) {
998        return result;
999    } else {
1000        job::MicroJobQueue::ExecutePendingJob(thread, thread->GetCurrentEcmaContext()->GetMicroJobQueue());
1001        return SourceTextModule::UNDEFINED_INDEX;
1002    }
1003}
1004
1005int SourceTextModule::InnerModuleEvaluationUnsafe(JSThread *thread, const JSHandle<ModuleRecord> &moduleRecord,
1006    CVector<JSHandle<SourceTextModule>> &stack, int index, const void *buffer, size_t size, bool executeFromJob)
1007{
1008    STACK_LIMIT_CHECK(thread, index);
1009    if (!moduleRecord.GetTaggedValue().IsSourceTextModule()) {
1010        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
1011        JSTaggedValue promise = SourceTextModule::Evaluate(thread, JSHandle<SourceTextModule>::Cast(moduleRecord));
1012        PromiseState state = JSPromise::Cast(moduleRecord.GetTaggedValue().GetTaggedObject())->GetPromiseState();
1013        ASSERT(state != PromiseState::PENDING);
1014        if (state == PromiseState::REJECTED) {
1015            ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1016            JSTaggedValue promiseResult = JSPromise::Cast(promise.GetTaggedObject())->GetPromiseResult();
1017            JSHandle<JSObject> error =
1018                factory->GetJSError(base::ErrorType::ERROR, nullptr, StackCheck::NO);
1019            THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error.GetTaggedValue(), promiseResult.GetInt());
1020        }
1021        return index;
1022    }
1023    JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
1024    ModuleStatus status = module->GetStatus();
1025    if (status == ModuleStatus::EVALUATING_ASYNC || status == ModuleStatus::EVALUATED) {
1026        if (module->GetEvaluationError() == SourceTextModule::UNDEFINED_INDEX) {
1027            return index;
1028        }
1029        // Otherwise return module.[[EvaluationError]].
1030        return module->GetEvaluationError();
1031    }
1032    if (status == ModuleStatus::EVALUATING) {
1033        return index;
1034    }
1035    ASSERT(status == ModuleStatus::INSTANTIATED);
1036    module->SetStatus(ModuleStatus::EVALUATING);
1037    module->SetDFSIndex(index);
1038    module->SetDFSAncestorIndex(index);
1039    module->SetPendingAsyncDependencies(0);
1040    index++;
1041    stack.emplace_back(module);
1042    ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
1043    if (!module->GetRequestedModules().IsUndefined()) {
1044        JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
1045        size_t requestedModulesLen = requestedModules->GetLength();
1046        JSMutableHandle<JSTaggedValue> required(thread, thread->GlobalConstants()->GetUndefined());
1047        JSHandle<SourceTextModule> requiredModule;
1048        for (size_t idx = 0; idx < requestedModulesLen; idx++) {
1049            // check if requiredModule is marked lazy
1050            if (module->IsLazyImportModule(idx)) {
1051                continue;
1052            }
1053            required.Update(requestedModules->Get(idx));
1054            CString moduleRecordName = module->GetEcmaModuleRecordNameString();
1055            if (moduleRecordName.empty()) {
1056                requiredModule = JSHandle<SourceTextModule>::Cast(
1057                    SourceTextModule::HostResolveImportedModule(thread, module, required));
1058            } else {
1059                requiredModule = JSHandle<SourceTextModule>::Cast(
1060                    SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required));
1061                RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
1062            }
1063            if (moduleLogger != nullptr) {
1064                moduleLogger->InsertParentModule(module, requiredModule);
1065            }
1066            ModuleTypes moduleType = requiredModule->GetTypes();
1067            if (SourceTextModule::IsNativeModule(moduleType)) {
1068                EvaluateNativeModule(thread, requiredModule, moduleType);
1069                continue;
1070            }
1071            // if requiredModule is jsonModule, then don't need to execute.
1072            if (moduleType == ModuleTypes::JSON_MODULE) {
1073                requiredModule->SetStatus(ModuleStatus::EVALUATED);
1074                continue;
1075            }
1076
1077            index = SourceTextModule::InnerModuleEvaluation(
1078                thread, requiredModule, stack, index, buffer, size, executeFromJob);
1079            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
1080            ModuleStatus requiredModuleStatus = requiredModule->GetStatus();
1081            ASSERT(requiredModuleStatus == ModuleStatus::EVALUATING ||
1082                   requiredModuleStatus == ModuleStatus::EVALUATING_ASYNC ||
1083                   requiredModuleStatus == ModuleStatus::EVALUATED);
1084            if (requiredModuleStatus == ModuleStatus::EVALUATING) {
1085                ASSERT(std::find(stack.begin(), stack.end(), requiredModule) != stack.end());
1086            }
1087            if (std::find(stack.begin(), stack.end(), requiredModule) != stack.end()) {
1088                ASSERT(requiredModuleStatus == ModuleStatus::EVALUATING);
1089            }
1090
1091            if (requiredModuleStatus == ModuleStatus::EVALUATING) {
1092                int dfsAncIdx = std::min(module->GetDFSAncestorIndex(), requiredModule->GetDFSAncestorIndex());
1093                module->SetDFSAncestorIndex(dfsAncIdx);
1094            } else {
1095                requiredModule = JSHandle<SourceTextModule>(thread, requiredModule->GetCycleRoot());
1096                requiredModuleStatus = requiredModule->GetStatus();
1097                ASSERT(requiredModuleStatus == ModuleStatus::EVALUATING_ASYNC ||
1098                       requiredModuleStatus == ModuleStatus::EVALUATED);
1099                if (requiredModule->GetEvaluationError() != SourceTextModule::UNDEFINED_INDEX) {
1100                    return requiredModule->GetEvaluationError();
1101                }
1102            }
1103            if (requiredModule->IsAsyncEvaluating()) {
1104                module->SetPendingAsyncDependencies(module->GetPendingAsyncDependencies() + 1);
1105                AddAsyncParentModule(thread, requiredModule, module);
1106            }
1107        }
1108    }
1109    int pendingAsyncDependencies = module->GetPendingAsyncDependencies();
1110    bool hasTLA = module->GetHasTLA();
1111    auto moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
1112    // 12. If module.[[PendingAsyncDependencies]] > 0 or module.[[HasTLA]] is true, then
1113    if (pendingAsyncDependencies > 0 || hasTLA) {
1114        // a. Assert: module.[[AsyncEvaluation]] is false and was never previously set to true.
1115        ASSERT(module->GetAsyncEvaluatingOrdinal() == NOT_ASYNC_EVALUATED);
1116        // b. Set module.[[AsyncEvaluation]] to true.
1117        module->SetAsyncEvaluatingOrdinal(moduleManager->NextModuleAsyncEvaluatingOrdinal());
1118        // d. If module.[[PendingAsyncDependencies]] = 0, perform ExecuteAsyncModule(module).
1119        if (pendingAsyncDependencies == 0) {
1120            SourceTextModule::ExecuteAsyncModule(thread, module, buffer, size, executeFromJob);
1121            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
1122        }
1123    } else {
1124        // 13. Else, Perform ? module.ExecuteModule().
1125        SourceTextModule::ModuleExecution(thread, module, buffer, size, executeFromJob);
1126        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
1127    }
1128    // 14. Assert: module occurs exactly once in stack.
1129    // 15. Assert: module.[[DFSAncestorIndex]] ≤ module.[[DFSIndex]].
1130    int dfsAncIdx = module->GetDFSAncestorIndex();
1131    int dfsIdx = module->GetDFSIndex();
1132    ASSERT(dfsAncIdx <= dfsIdx);
1133    // 16. If module.[[DFSAncestorIndex]] = module.[[DFSIndex]], then
1134    if (dfsAncIdx == dfsIdx) {
1135        // a. Let done be false.
1136        bool done = false;
1137        // b. Repeat, while done is false,
1138        while (!done) {
1139            // i. Let requiredModule be the last element in stack.
1140            JSHandle<SourceTextModule> requiredModule = stack.back();
1141            // ii. Remove the last element of stack.
1142            stack.pop_back();
1143            // iii. Assert: requiredModule is a Cyclic Module Record.
1144            // iv. If requiredModule.[[AsyncEvaluation]] is false, set requiredModule.[[Status]] to EVALUATED.
1145            // v. Otherwise, set requiredModule.[[Status]] to EVALUATING-ASYNC.
1146            if (!requiredModule->IsAsyncEvaluating()) {
1147                requiredModule->SetStatus(ModuleStatus::EVALUATED);
1148            } else {
1149                requiredModule->SetStatus(ModuleStatus::EVALUATING_ASYNC);
1150            }
1151            // vi. If requiredModule and module are the same Module Record, set done to true.
1152            if (JSTaggedValue::SameValue(module.GetTaggedValue(), requiredModule.GetTaggedValue())) {
1153                done = true;
1154            }
1155            // vii. Set requiredModule.[[CycleRoot]] to module.
1156            if (!SourceTextModule::IsSharedModule(requiredModule)) {
1157                requiredModule->SetCycleRoot(thread, module);
1158            }
1159        }
1160    }
1161    return index;
1162}
1163bool SourceTextModule::IsEvaluatedModule(JSThread *thread, StateVisit &stateVisit,
1164                                         const JSHandle<SourceTextModule> &module)
1165{
1166    return GetModuleEvaluatingType(thread, stateVisit, module) == ModuleStatus::EVALUATED;
1167}
1168
1169ModuleStatus SourceTextModule::GetModuleEvaluatingType(JSThread *thread, StateVisit &stateVisit,
1170                                                       const JSHandle<SourceTextModule> &module)
1171{
1172    RuntimeLockHolder locker(thread, stateVisit.mutex);
1173    return module->GetStatus();
1174}
1175
1176int SourceTextModule::InnerModuleEvaluation(JSThread *thread, const JSHandle<SourceTextModule> &module,
1177                                            CVector<JSHandle<SourceTextModule>> &stack, int index,
1178                                            const void *buffer, size_t size, bool executeFromJob)
1179{
1180    bool isShared = IsSharedModule(module);
1181    JSHandle<ModuleRecord> moduleRecord = JSHandle<ModuleRecord>::Cast(module);
1182    if (!isShared) {
1183        return SourceTextModule::InnerModuleEvaluationUnsafe(
1184            thread, moduleRecord, stack, index, buffer, size, executeFromJob);
1185    } else {
1186        StateVisit &stateVisit = SharedModuleManager::GetInstance()->findModuleMutexWithLock(thread, module);
1187        if (module->GetStatus() == ModuleStatus::EVALUATING &&
1188                stateVisit.threadId == thread->GetThreadId()) {
1189            return index;
1190        }
1191        RuntimeLockHolder locker(thread, stateVisit.mutex);
1192        if (module->GetStatus() == ModuleStatus::INSTANTIATED) {
1193            stateVisit.threadId = thread->GetThreadId();
1194            int idx = SourceTextModule::InnerModuleEvaluationUnsafe(
1195                thread, moduleRecord, stack, index, buffer, size, executeFromJob);
1196            return idx;
1197        }
1198        return index;
1199    }
1200    LOG_FULL(FATAL) << "This line is unreachable";
1201    UNREACHABLE();
1202}
1203
1204void SourceTextModule::HandleConcurrentEvaluateResult(JSThread *thread, JSHandle<SourceTextModule> &module,
1205    const CVector<JSHandle<SourceTextModule>> &stack, int result)
1206{
1207    ModuleStatus status;
1208    // 9. If result is an abrupt completion, then
1209    if (thread->HasPendingException()) {
1210        // a. For each module m in stack, do
1211        for (auto mm : stack) {
1212            // i. Assert: m.[[Status]] is "evaluating".
1213            ASSERT(mm->GetStatus() == ModuleStatus::EVALUATING);
1214            // ii. Set m.[[Status]] to "evaluated".
1215            mm->SetStatus(ModuleStatus::EVALUATED);
1216            // iii. Set m.[[EvaluationError]] to result.
1217            mm->SetEvaluationError(result);
1218        }
1219        // b. Assert: module.[[Status]] is "evaluated" and module.[[EvaluationError]] is result.
1220        status = module->GetStatus();
1221        ASSERT(status == ModuleStatus::EVALUATED && module->GetEvaluationError() == result);
1222    // 10. Else,
1223    } else {
1224        // a. Assert: module.[[Status]] is either EVALUATING-ASYNC or EVALUATED.
1225        status = module->GetStatus();
1226        ASSERT(status == ModuleStatus::EVALUATING_ASYNC || status == ModuleStatus::EVALUATED);
1227        // b. Assert: module.[[EvaluationError]] is EMPTY.
1228        ASSERT(module->GetEvaluationError() == SourceTextModule::UNDEFINED_INDEX);
1229        // c. If module.[[AsyncEvaluation]] is false, then
1230        //    i. Assert: module.[[Status]] is EVALUATED.
1231        if (!module->IsAsyncEvaluating()) {
1232            ASSERT(status == ModuleStatus::EVALUATED);
1233        }
1234        // d. Assert: stack is empty.
1235        ASSERT(stack.empty());
1236    }
1237}
1238
1239int SourceTextModule::ModuleEvaluation(JSThread *thread, const JSHandle<ModuleRecord> &moduleRecord,
1240                                       int index, const JSHandle<Method> &method)
1241{
1242    JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
1243    if (!module->GetRequestedModules().IsUndefined()) {
1244        JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
1245        size_t requestedModulesLen = requestedModules->GetLength();
1246        JSMutableHandle<JSTaggedValue> required(thread, thread->GlobalConstants()->GetUndefined());
1247        auto coRequestedModules = GetConcurrentRequestedModules(method);
1248        for (size_t idx = 0; idx < requestedModulesLen; idx++) {
1249            if (coRequestedModules.has_value() && coRequestedModules.value().count(idx) == 0) {
1250                // skip the unused module
1251                continue;
1252            }
1253            required.Update(requestedModules->Get(idx));
1254            JSMutableHandle<SourceTextModule> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
1255            CString moduleRecordName = module->GetEcmaModuleRecordNameString();
1256            if (moduleRecordName.empty()) {
1257                requiredModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, required));
1258                RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
1259            } else {
1260                requiredModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required));
1261                RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
1262            }
1263            ModuleTypes moduleType = requiredModule->GetTypes();
1264            if (SourceTextModule::IsNativeModule(moduleType)) {
1265                EvaluateNativeModule(thread, requiredModule, moduleType);
1266                continue;
1267            }
1268            if (moduleType == ModuleTypes::JSON_MODULE) {
1269                requiredModule->SetStatus(ModuleStatus::EVALUATED);
1270                continue;
1271            }
1272            CVector<JSHandle<SourceTextModule>> stack;
1273            int result = SourceTextModule::InnerModuleEvaluation(thread, requiredModule, stack, 0);
1274            index += result;
1275            HandleConcurrentEvaluateResult(thread, requiredModule, stack, result);
1276            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
1277        }
1278    }
1279    return index;
1280}
1281
1282Expected<JSTaggedValue, bool> SourceTextModule::ModuleExecution(JSThread *thread,
1283    const JSHandle<SourceTextModule> &module, const void *buffer, size_t size, bool executeFromJob)
1284{
1285    CString moduleFilenameStr {};
1286    if (thread->GetCurrentEcmaContext()->GetStageOfHotReload() == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) {
1287        moduleFilenameStr = thread->GetEcmaVM()->GetQuickFixManager()->GetBaseFileName(module);
1288    } else {
1289        moduleFilenameStr = module->GetEcmaModuleFilenameString();
1290    }
1291    std::string entryPoint;
1292    CString moduleRecordName = module->GetEcmaModuleRecordNameString();
1293    if (moduleRecordName.empty()) {
1294        entryPoint = JSPandaFile::ENTRY_FUNCTION_NAME;
1295    } else {
1296        entryPoint = moduleRecordName;
1297    }
1298
1299    std::shared_ptr<JSPandaFile> jsPandaFile;
1300    if (buffer != nullptr) {
1301        jsPandaFile =
1302            JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFilenameStr, entryPoint, buffer, size);
1303    } else {
1304        jsPandaFile =
1305            JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFilenameStr, entryPoint);
1306    }
1307
1308    if (jsPandaFile == nullptr) { // LCOV_EXCL_BR_LINE
1309        LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " <<  moduleFilenameStr;
1310    }
1311    return JSPandaFileExecutor::Execute(thread, jsPandaFile.get(), entryPoint, executeFromJob);
1312}
1313
1314void SourceTextModule::AddImportEntry(JSThread *thread, const JSHandle<SourceTextModule> &module,
1315                                      const JSHandle<ImportEntry> &importEntry, size_t idx, uint32_t len)
1316{
1317    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1318    JSTaggedValue importEntries = module->GetImportEntries();
1319    if (importEntries.IsUndefined()) {
1320        JSHandle<TaggedArray> array = factory->NewTaggedArray(len);
1321        array->Set(thread, idx, importEntry.GetTaggedValue());
1322        module->SetImportEntries(thread, array);
1323    } else {
1324        JSHandle<TaggedArray> entries(thread, importEntries);
1325        if (len > entries->GetLength()) {
1326            entries = TaggedArray::SetCapacity(thread, entries, len);
1327            entries->Set(thread, idx, importEntry.GetTaggedValue());
1328            module->SetImportEntries(thread, entries);
1329            return;
1330        }
1331        entries->Set(thread, idx, importEntry.GetTaggedValue());
1332    }
1333}
1334
1335void SourceTextModule::AddLocalExportEntry(JSThread *thread, const JSHandle<SourceTextModule> &module,
1336                                           const JSHandle<LocalExportEntry> &exportEntry, size_t idx, uint32_t len)
1337{
1338    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1339    JSTaggedValue localExportEntries = module->GetLocalExportEntries();
1340    if (localExportEntries.IsUndefined()) {
1341        JSHandle<TaggedArray> array = factory->NewTaggedArray(len);
1342        array->Set(thread, idx, exportEntry.GetTaggedValue());
1343        module->SetLocalExportEntries(thread, array);
1344    } else {
1345        JSHandle<TaggedArray> entries(thread, localExportEntries);
1346        entries->Set(thread, idx, exportEntry.GetTaggedValue());
1347    }
1348}
1349
1350void SourceTextModule::AddIndirectExportEntry(JSThread *thread, const JSHandle<SourceTextModule> &module,
1351                                              const JSHandle<IndirectExportEntry> &exportEntry,
1352                                              size_t idx, uint32_t len)
1353{
1354    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1355    JSTaggedValue indirectExportEntries = module->GetIndirectExportEntries();
1356    if (indirectExportEntries.IsUndefined()) {
1357        JSHandle<TaggedArray> array = factory->NewTaggedArray(len);
1358        array->Set(thread, idx, exportEntry.GetTaggedValue());
1359        module->SetIndirectExportEntries(thread, array);
1360    } else {
1361        JSHandle<TaggedArray> entries(thread, indirectExportEntries);
1362        entries->Set(thread, idx, exportEntry.GetTaggedValue());
1363    }
1364}
1365
1366void SourceTextModule::AddStarExportEntry(JSThread *thread, const JSHandle<SourceTextModule> &module,
1367                                          const JSHandle<StarExportEntry> &exportEntry, size_t idx, uint32_t len)
1368{
1369    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1370    JSTaggedValue starExportEntries = module->GetStarExportEntries();
1371    if (starExportEntries.IsUndefined()) {
1372        JSHandle<TaggedArray> array = factory->NewTaggedArray(len);
1373        array->Set(thread, idx, exportEntry.GetTaggedValue());
1374        module->SetStarExportEntries(thread, array);
1375    } else {
1376        JSHandle<TaggedArray> entries(thread, starExportEntries);
1377        entries->Set(thread, idx, exportEntry.GetTaggedValue());
1378    }
1379}
1380
1381JSTaggedValue SourceTextModule::GetModuleValue(JSThread *thread, int32_t index, bool isThrow)
1382{
1383    DISALLOW_GARBAGE_COLLECTION;
1384    JSTaggedValue dictionary = GetNameDictionary();
1385    if (dictionary.IsUndefined()) {
1386        if (isThrow) {
1387            THROW_REFERENCE_ERROR_AND_RETURN(thread, "module environment is undefined", JSTaggedValue::Exception());
1388        }
1389        return JSTaggedValue::Hole();
1390    }
1391
1392    TaggedArray *array = TaggedArray::Cast(dictionary.GetTaggedObject());
1393    return array->Get(index);
1394}
1395
1396JSTaggedValue SourceTextModule::GetModuleValue(JSThread *thread, JSTaggedValue key, bool isThrow)
1397{
1398    DISALLOW_GARBAGE_COLLECTION;
1399    JSTaggedValue dictionary = GetNameDictionary();
1400    if (dictionary.IsUndefined()) {
1401        if (isThrow) {
1402            THROW_REFERENCE_ERROR_AND_RETURN(thread, "module environment is undefined", JSTaggedValue::Exception());
1403        }
1404        return JSTaggedValue::Hole();
1405    }
1406
1407    NameDictionary *dict = NameDictionary::Cast(dictionary.GetTaggedObject());
1408    int entry = dict->FindEntry(key);
1409    if (entry != -1) {
1410        return dict->GetValue(entry);
1411    }
1412
1413    // when key is exportName, need to get localName
1414    JSTaggedValue exportEntriesTv = GetLocalExportEntries();
1415    if (!exportEntriesTv.IsUndefined()) {
1416        JSTaggedValue resolution = FindByExport(exportEntriesTv, key, dictionary);
1417        if (!resolution.IsHole()) {
1418            return resolution;
1419        }
1420    }
1421
1422    return JSTaggedValue::Hole();
1423}
1424
1425JSTaggedValue SourceTextModule::GetValueFromExportObject(JSThread *thread, JSHandle<JSTaggedValue> &exportObject,
1426    int32_t index)
1427{
1428    if (index == SourceTextModule::UNDEFINED_INDEX) {
1429        return exportObject.GetTaggedValue();
1430    }
1431    return ObjectFastOperator::FastGetPropertyByPorpsIndex(thread, exportObject.GetTaggedValue(), index);
1432}
1433
1434JSTaggedValue SourceTextModule::FindByExport(const JSTaggedValue &exportEntriesTv, const JSTaggedValue &key,
1435                                             const JSTaggedValue &dictionary)
1436{
1437    DISALLOW_GARBAGE_COLLECTION;
1438    NameDictionary *dict = NameDictionary::Cast(dictionary.GetTaggedObject());
1439    TaggedArray *exportEntries = TaggedArray::Cast(exportEntriesTv.GetTaggedObject());
1440    size_t exportEntriesLen = exportEntries->GetLength();
1441    for (size_t idx = 0; idx < exportEntriesLen; idx++) {
1442        LocalExportEntry *ee = LocalExportEntry::Cast(exportEntries->Get(idx).GetTaggedObject());
1443        if (!JSTaggedValue::SameValue(ee->GetExportName(), key)) {
1444            continue;
1445        }
1446        JSTaggedValue localName = ee->GetLocalName();
1447        int entry = dict->FindEntry(localName);
1448        if (entry != -1) {
1449            return dict->GetValue(entry);
1450        }
1451    }
1452
1453    return JSTaggedValue::Hole();
1454}
1455
1456void SourceTextModule::StoreModuleValue(JSThread *thread, int32_t index, const JSHandle<JSTaggedValue> &value)
1457{
1458    JSHandle<SourceTextModule> module(thread, this);
1459    JSTaggedValue localExportEntries = module->GetLocalExportEntries();
1460    ASSERT(localExportEntries.IsTaggedArray());
1461
1462    JSHandle<JSTaggedValue> data(thread, module->GetNameDictionary());
1463    if (data->IsUndefined()) {
1464        ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1465        uint32_t size = TaggedArray::Cast(localExportEntries.GetTaggedObject())->GetLength();
1466        ASSERT(index < static_cast<int32_t>(size));
1467        if (SourceTextModule::IsSharedModule(module)) {
1468            data = JSHandle<JSTaggedValue>(factory->NewSTaggedArray(size,
1469                JSTaggedValue::Hole(), MemSpaceType::SHARED_OLD_SPACE));
1470        } else {
1471            data = JSHandle<JSTaggedValue>(factory->NewTaggedArray(size));
1472        }
1473        module->SetNameDictionary(thread, data);
1474    }
1475    JSHandle<TaggedArray> arr(data);
1476    arr->Set(thread, index, value);
1477}
1478
1479//  discard instructions won't consider shared-module.
1480void SourceTextModule::StoreModuleValue(JSThread *thread, const JSHandle<JSTaggedValue> &key,
1481                                        const JSHandle<JSTaggedValue> &value)
1482{
1483    JSHandle<SourceTextModule> module(thread, this);
1484    JSMutableHandle<JSTaggedValue> data(thread, module->GetNameDictionary());
1485    if (data->IsUndefined()) {
1486        data.Update(NameDictionary::Create(thread, DEFAULT_DICTIONART_CAPACITY));
1487    }
1488    JSHandle<NameDictionary> dataDict = JSHandle<NameDictionary>::Cast(data);
1489    data.Update(NameDictionary::Put(thread, dataDict, key, value, PropertyAttributes::Default()));
1490
1491    module->SetNameDictionary(thread, data);
1492}
1493
1494void SourceTextModule::SetExportName(JSThread *thread, const JSHandle<JSTaggedValue> &moduleRequest,
1495                                     const JSHandle<SourceTextModule> &module,
1496                                     CVector<std::string> &exportedNames, JSHandle<TaggedArray> &newExportStarSet)
1497
1498{
1499    JSMutableHandle<SourceTextModule> requestedModule(thread, thread->GlobalConstants()->GetUndefined());
1500    CString moduleRecordName = module->GetEcmaModuleRecordNameString();
1501    if (moduleRecordName.empty()) {
1502        JSHandle<JSTaggedValue> requestedVal =
1503            SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest);
1504        RETURN_IF_ABRUPT_COMPLETION(thread);
1505        requestedModule.Update(JSHandle<SourceTextModule>::Cast(requestedVal));
1506    } else {
1507        JSHandle<JSTaggedValue> requestedVal =
1508            SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest);
1509        RETURN_IF_ABRUPT_COMPLETION(thread);
1510        requestedModule.Update(JSHandle<SourceTextModule>::Cast(requestedVal));
1511    }
1512    // b. Let starNames be ? requestedModule.GetExportedNames(exportStarSet).
1513    CVector<std::string> starNames =
1514        SourceTextModule::GetExportedNames(thread, requestedModule, newExportStarSet);
1515    // c. For each element n of starNames, do
1516    for (std::string &nn : starNames) {
1517        // i. If SameValue(n, "default") is false, then
1518        if (nn != "default" && std::find(exportedNames.begin(), exportedNames.end(), nn) == exportedNames.end()) {
1519            // 1. If n is not an element of exportedNames, then
1520            //    a. Append n to exportedNames.
1521            exportedNames.emplace_back(nn);
1522        }
1523    }
1524}
1525
1526JSHandle<JSTaggedValue> SourceTextModule::GetStarResolution(JSThread *thread,
1527                                                            const JSHandle<JSTaggedValue> &exportName,
1528                                                            const JSHandle<JSTaggedValue> &moduleRequest,
1529                                                            const JSHandle<SourceTextModule> &module,
1530                                                            JSMutableHandle<JSTaggedValue> &starResolution,
1531                                                            CVector<std::pair<JSHandle<SourceTextModule>,
1532                                                            JSHandle<JSTaggedValue>>> &resolveVector)
1533{
1534    auto globalConstants = thread->GlobalConstants();
1535    // a. Let importedModule be ? HostResolveImportedModule(module, e.[[ModuleRequest]]).
1536    JSMutableHandle<SourceTextModule> importedModule(thread, thread->GlobalConstants()->GetUndefined());
1537    CString moduleRecordName = module->GetEcmaModuleRecordNameString();
1538    if (moduleRecordName.empty()) {
1539        JSHandle<JSTaggedValue> importedVal =
1540            SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest);
1541        RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1542        importedModule.Update(JSHandle<SourceTextModule>::Cast(importedVal));
1543    } else {
1544        JSHandle<JSTaggedValue> importedVal =
1545            SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest);
1546        RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1547        importedModule.Update(JSHandle<SourceTextModule>::Cast(importedVal));
1548    }
1549    // b. Let resolution be ? importedModule.ResolveExport(exportName, resolveVector).
1550    auto moduleType = importedModule->GetTypes();
1551    bool isNativeModule = IsNativeModule(moduleType);
1552    JSHandle<JSTaggedValue> resolution;
1553    if (UNLIKELY(isNativeModule || moduleType == ModuleTypes::CJS_MODULE)) {
1554        resolution = isNativeModule
1555            ? SourceTextModule::ResolveNativeStarExport(thread, importedModule, exportName)
1556            : SourceTextModule::ResolveCjsStarExport(thread, importedModule, exportName);
1557    } else {
1558        resolution = SourceTextModule::ResolveExport(thread, importedModule, exportName, resolveVector);
1559    }
1560
1561    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1562    // c. If resolution is "ambiguous", return "ambiguous".
1563    if (resolution->IsString()) { // if resolution is string, resolution must be "ambiguous"
1564        return globalConstants->GetHandledAmbiguousString();
1565    }
1566    // d. If resolution is not null, then
1567    if (resolution->IsNull()) {
1568        return globalConstants->GetHandledNull();
1569    }
1570    // i. Assert: resolution is a ResolvedBinding Record.
1571    ASSERT(resolution->IsResolvedBinding() || resolution->IsResolvedIndexBinding());
1572    // ii. If starResolution is null, set starResolution to resolution.
1573    if (starResolution->IsNull()) {
1574        starResolution.Update(resolution.GetTaggedValue());
1575    } else {
1576        // 1. Assert: There is more than one * import that includes the requested name.
1577        // 2. If resolution.[[Module]] and starResolution.[[Module]] are not the same Module Record or
1578        // SameValue(
1579        //    resolution.[[BindingName]], starResolution.[[BindingName]]) is false, return "ambiguous".
1580        // Adapter new opcode
1581        if (resolution->IsResolvedBinding()) {
1582            JSHandle<ResolvedBinding> resolutionBd = JSHandle<ResolvedBinding>::Cast(resolution);
1583            JSHandle<ResolvedBinding> starResolutionBd = JSHandle<ResolvedBinding>::Cast(starResolution);
1584            if ((!JSTaggedValue::SameValue(resolutionBd->GetModule(), starResolutionBd->GetModule())) ||
1585                (!JSTaggedValue::SameValue(
1586                    resolutionBd->GetBindingName(), starResolutionBd->GetBindingName()))) {
1587                return globalConstants->GetHandledAmbiguousString();
1588            }
1589        } else {
1590            JSHandle<ResolvedIndexBinding> resolutionBd = JSHandle<ResolvedIndexBinding>::Cast(resolution);
1591            JSHandle<ResolvedIndexBinding> starResolutionBd = JSHandle<ResolvedIndexBinding>::Cast(starResolution);
1592            if ((!JSTaggedValue::SameValue(resolutionBd->GetModule(), starResolutionBd->GetModule())) ||
1593                resolutionBd->GetIndex() != starResolutionBd->GetIndex()) {
1594                return globalConstants->GetHandledAmbiguousString();
1595            }
1596        }
1597    }
1598    return resolution;
1599}
1600
1601template <typename T>
1602void SourceTextModule::AddExportName(JSThread *thread, const JSTaggedValue &exportEntry,
1603                                     CVector<std::string> &exportedNames)
1604{
1605    if (!exportEntry.IsUndefined()) {
1606        JSMutableHandle<T> ee(thread, thread->GlobalConstants()->GetUndefined());
1607        JSHandle<TaggedArray> exportEntries(thread, exportEntry);
1608        size_t exportEntriesLen = exportEntries->GetLength();
1609        for (size_t idx = 0; idx < exportEntriesLen; idx++) {
1610            ee.Update(exportEntries->Get(idx));
1611            // a. Assert: module provides the direct binding for this export.
1612            // b. Append e.[[ExportName]] to exportedNames.
1613            std::string exportName = EcmaStringAccessor(ee->GetExportName()).ToStdString();
1614            exportedNames.emplace_back(exportName);
1615        }
1616    }
1617}
1618
1619JSHandle<JSTaggedValue> SourceTextModule::ResolveElementOfObject(JSThread *thread,
1620                                                                 const JSHandle<JSHClass> &hclass,
1621                                                                 const JSHandle<JSTaggedValue> &exportName,
1622                                                                 const JSHandle<SourceTextModule> &module)
1623{
1624    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1625    int idx = JSHClass::FindPropertyEntry(thread, *hclass, exportName.GetTaggedValue());
1626    if (idx != -1) {
1627        return JSHandle<JSTaggedValue>::Cast(factory->NewResolvedIndexBindingRecord(module, idx));
1628    }
1629    return thread->GlobalConstants()->GetHandledUndefined();
1630}
1631
1632JSHandle<JSTaggedValue> SourceTextModule::ResolveLocalExport(JSThread *thread,
1633                                                             const JSHandle<JSTaggedValue> &exportEntry,
1634                                                             const JSHandle<JSTaggedValue> &exportName,
1635                                                             const JSHandle<SourceTextModule> &module)
1636{
1637    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1638    JSMutableHandle<LocalExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
1639    JSMutableHandle<JSTaggedValue> localName(thread, thread->GlobalConstants()->GetUndefined());
1640
1641    JSHandle<TaggedArray> localExportEntries(exportEntry);
1642    size_t localExportEntriesLen = localExportEntries->GetLength();
1643    for (size_t idx = 0; idx < localExportEntriesLen; idx++) {
1644        ee.Update(localExportEntries->Get(idx));
1645        // a. If SameValue(exportName, e.[[ExportName]]) is true, then
1646        // if module is type of CommonJS or native, export first, check after execution.
1647        auto moduleType = module->GetTypes();
1648        if (IsNativeModule(moduleType) || moduleType == ModuleTypes::CJS_MODULE) {
1649            return JSHandle<JSTaggedValue>::Cast(factory->NewResolvedBindingRecord(module, exportName));
1650        }
1651
1652        if ((JSTaggedValue::SameValue(ee->GetExportName(), exportName.GetTaggedValue()))) {
1653            // Adapter new module
1654            if (module->GetIsNewBcVersion()) {
1655                return JSHandle<JSTaggedValue>::Cast(factory->NewResolvedIndexBindingRecord(module,
1656                    ee->GetLocalIndex()));
1657            }
1658            // i. Assert: module provides the direct binding for this export.
1659            // ii. Return ResolvedBinding Record { [[Module]]: module, [[BindingName]]: e.[[LocalName]] }.
1660            localName.Update(ee->GetLocalName());
1661            return JSHandle<JSTaggedValue>::Cast(factory->NewResolvedBindingRecord(module, localName));
1662        }
1663    }
1664    return thread->GlobalConstants()->GetHandledUndefined();
1665}
1666
1667JSHandle<JSTaggedValue> SourceTextModule::ResolveIndirectExport(JSThread *thread,
1668                                                                const JSHandle<JSTaggedValue> &exportEntry,
1669                                                                const JSHandle<JSTaggedValue> &exportName,
1670                                                                const JSHandle<SourceTextModule> &module,
1671                                                                CVector<std::pair<JSHandle<SourceTextModule>,
1672                                                                JSHandle<JSTaggedValue>>> &resolveVector)
1673{
1674    auto globalConstants = thread->GlobalConstants();
1675    JSTaggedValue undefined = globalConstants->GetUndefined();
1676    JSMutableHandle<IndirectExportEntry> ee(thread, undefined);
1677    JSMutableHandle<JSTaggedValue> moduleRequest(thread, undefined);
1678    JSMutableHandle<JSTaggedValue> importName(thread, undefined);
1679    JSHandle<TaggedArray> indirectExportEntries(exportEntry);
1680    size_t indirectExportEntriesLen = indirectExportEntries->GetLength();
1681    for (size_t idx = 0; idx < indirectExportEntriesLen; idx++) {
1682        ee.Update(indirectExportEntries->Get(idx));
1683        //  a. If SameValue(exportName, e.[[ExportName]]) is true, then
1684        if (JSTaggedValue::SameValue(exportName.GetTaggedValue(), ee->GetExportName())) {
1685            // i. Assert: module imports a specific binding for this export.
1686            // ii. Let importedModule be ? HostResolveImportedModule(module, e.[[ModuleRequest]]).
1687            moduleRequest.Update(ee->GetModuleRequest());
1688            JSMutableHandle<SourceTextModule> requestedModule(thread, undefined);
1689            CString moduleRecordName = module->GetEcmaModuleRecordNameString();
1690            if (moduleRecordName.empty()) {
1691                requestedModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest));
1692            } else {
1693                requestedModule.Update(
1694                    SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest));
1695            }
1696            RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1697            // iii. Return importedModule.ResolveExport(e.[[ImportName]], resolveVector).
1698            importName.Update(ee->GetImportName());
1699            return SourceTextModule::ResolveExport(thread, requestedModule, importName, resolveVector);
1700        }
1701    }
1702    return thread->GlobalConstants()->GetHandledUndefined();
1703}
1704
1705void SourceTextModule::CheckResolvedBinding(JSThread *thread, const JSHandle<SourceTextModule> &module)
1706{
1707    auto globalConstants = thread->GlobalConstants();
1708    // 1. For each ExportEntry Record e in module.[[IndirectExportEntries]], do
1709    JSTaggedValue indirectExportEntriesTv = module->GetIndirectExportEntries();
1710    if (indirectExportEntriesTv.IsUndefined()) {
1711        return;
1712    }
1713
1714    JSMutableHandle<IndirectExportEntry> ee(thread, globalConstants->GetUndefined());
1715    JSMutableHandle<JSTaggedValue> exportName(thread, globalConstants->GetUndefined());
1716    JSHandle<TaggedArray> indirectExportEntries(thread, indirectExportEntriesTv);
1717    size_t indirectExportEntriesLen = indirectExportEntries->GetLength();
1718    for (size_t idx = 0; idx < indirectExportEntriesLen; idx++) {
1719        ee.Update(indirectExportEntries->Get(idx));
1720        // a. Let resolution be ? module.ResolveExport(e.[[ExportName]], « »).
1721        exportName.Update(ee->GetExportName());
1722        CVector<std::pair<JSHandle<SourceTextModule>, JSHandle<JSTaggedValue>>> resolveVector;
1723        JSHandle<JSTaggedValue> resolution =
1724            SourceTextModule::ResolveExport(thread, module, exportName, resolveVector);
1725        RETURN_IF_ABRUPT_COMPLETION(thread);
1726        // b. If resolution is null or "ambiguous", throw a SyntaxError exception.
1727        if (resolution->IsNull() || resolution->IsString()) {
1728            CString requestMod = ModulePathHelper::ReformatPath(ConvertToString(ee->GetModuleRequest()));
1729            CString msg = "the requested module '" + requestMod + GetResolveErrorReason(resolution) +
1730                          ConvertToString(exportName.GetTaggedValue());
1731            if (!module->GetEcmaModuleRecordNameString().empty()) {
1732            CString recordStr = ModulePathHelper::ReformatPath(module->GetEcmaModuleRecordNameString());
1733                msg += "' which exported by '" + recordStr + "'";
1734            } else {
1735                msg += "' which exported by '" + module->GetEcmaModuleFilenameString() + "'";
1736            }
1737            THROW_ERROR(thread, ErrorType::SYNTAX_ERROR, msg.c_str());
1738        }
1739        // c. Assert: resolution is a ResolvedBinding Record.
1740        ASSERT(resolution->IsResolvedBinding());
1741    }
1742}
1743
1744void SourceTextModule::CheckResolvedIndexBinding(JSThread *thread, const JSHandle<SourceTextModule> &module)
1745{
1746    auto globalConstants = thread->GlobalConstants();
1747    // 1. For each ExportEntry Record e in module.[[IndirectExportEntries]], do
1748    JSTaggedValue indirectExportEntriesTv = module->GetIndirectExportEntries();
1749    if (indirectExportEntriesTv.IsUndefined()) {
1750        return;
1751    }
1752
1753    JSMutableHandle<IndirectExportEntry> ee(thread, globalConstants->GetUndefined());
1754    JSMutableHandle<JSTaggedValue> exportName(thread, globalConstants->GetUndefined());
1755    JSHandle<TaggedArray> indirectExportEntries(thread, indirectExportEntriesTv);
1756    size_t indirectExportEntriesLen = indirectExportEntries->GetLength();
1757    for (size_t idx = 0; idx < indirectExportEntriesLen; idx++) {
1758        ee.Update(indirectExportEntries->Get(idx));
1759        // a. Let resolution be ? module.ResolveExport(e.[[ExportName]], « »).
1760        exportName.Update(ee->GetExportName());
1761        CVector<std::pair<JSHandle<SourceTextModule>, JSHandle<JSTaggedValue>>> resolveVector;
1762        JSHandle<JSTaggedValue> resolution =
1763            SourceTextModule::ResolveExport(thread, module, exportName, resolveVector);
1764        RETURN_IF_ABRUPT_COMPLETION(thread);
1765        // b. If resolution is null or "ambiguous", throw a SyntaxError exception.
1766        if (resolution->IsNull() || resolution->IsString()) {
1767            CString requestMod = ModulePathHelper::ReformatPath(ConvertToString(ee->GetModuleRequest()));
1768            CString msg = "the requested module '" + requestMod + GetResolveErrorReason(resolution) +
1769                ConvertToString(exportName.GetTaggedValue());
1770            if (!module->GetEcmaModuleRecordNameString().empty()) {
1771                CString record = ModulePathHelper::ReformatPath(module->GetEcmaModuleRecordNameString());
1772                msg += "' which exported by '" + record + "'";
1773            } else {
1774                msg += "' which exported by '" + module->GetEcmaModuleFilenameString() + "'";
1775            }
1776            THROW_ERROR(thread, ErrorType::SYNTAX_ERROR, msg.c_str());
1777        }
1778    }
1779}
1780
1781CString SourceTextModule::GetModuleName(JSTaggedValue currentModule)
1782{
1783    SourceTextModule *module = SourceTextModule::Cast(currentModule.GetTaggedObject());
1784    CString recordName = module->GetEcmaModuleRecordNameString();
1785    if (recordName.empty()) {
1786        recordName = module->GetEcmaModuleFilenameString();
1787    }
1788    return recordName;
1789}
1790
1791bool SourceTextModule::IsDynamicModule(LoadingTypes types)
1792{
1793    return types == LoadingTypes::DYNAMITC_MODULE;
1794}
1795
1796bool SourceTextModule::IsAsyncEvaluating()
1797{
1798    return GetAsyncEvaluatingOrdinal() >= FIRST_ASYNC_EVALUATING_ORDINAL;
1799}
1800
1801void SourceTextModule::AddAsyncParentModule(JSThread *thread, JSHandle<SourceTextModule> &module,
1802                                            JSHandle<SourceTextModule> &parent)
1803{
1804    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1805    JSTaggedValue asyncParentModules = module->GetAsyncParentModules();
1806    if (asyncParentModules.IsUndefined()) {
1807        JSHandle<TaggedArray> array = factory->NewTaggedArray(1);
1808        array->Set(thread, 0, parent.GetTaggedValue());
1809        module->SetAsyncParentModules(thread, array);
1810    } else {
1811        JSHandle<TaggedArray> array(thread, asyncParentModules);
1812        ASSERT(array->GetLength() > 0);
1813        array = TaggedArray::SetCapacity(thread, array, array->GetLength() + 1);
1814        array->Set(thread, array->GetLength() - 1, parent.GetTaggedValue());
1815        module->SetAsyncParentModules(thread, array);
1816    }
1817}
1818
1819void SourceTextModule::ExecuteAsyncModule(JSThread *thread, const JSHandle<SourceTextModule> &module,
1820                                          const void *buffer, size_t size, bool executeFromJob)
1821{
1822    // 1. Assert: module.[[Status]] is either EVALUATING or EVALUATING-ASYNC.
1823    ASSERT(module->GetStatus() == ModuleStatus::EVALUATING || module->GetStatus() == ModuleStatus::EVALUATING_ASYNC);
1824    // 2. Assert: module.[[HasTLA]] is true.
1825    ASSERT(module->GetHasTLA());
1826    CString moduleFilenameStr = module->GetEcmaModuleFilenameString();
1827
1828    std::string entryPoint;
1829    CString moduleRecordName = module->GetEcmaModuleRecordNameString();
1830    if (moduleRecordName.empty()) {
1831        entryPoint = JSPandaFile::ENTRY_FUNCTION_NAME;
1832    } else {
1833        entryPoint = moduleRecordName;
1834    }
1835
1836    std::shared_ptr<JSPandaFile> jsPandaFile;
1837    if (buffer != nullptr) {
1838        jsPandaFile =
1839            JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFilenameStr, entryPoint, buffer, size);
1840    } else {
1841        jsPandaFile =
1842            JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFilenameStr, entryPoint);
1843    }
1844
1845    if (jsPandaFile == nullptr) { // LCOV_EXCL_BR_LINE
1846        LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << moduleFilenameStr;
1847    }
1848    Expected<JSTaggedValue, bool> result =
1849        JSPandaFileExecutor::Execute(thread, jsPandaFile.get(), entryPoint, executeFromJob);
1850    ASSERT(result.Value().IsJSPromise());
1851    // 3. Let capability be ! NewPromiseCapability(%Promise%).
1852    // 4. Let fulfilledClosure be a new Abstract Closure with no parameters that captures module and performs
1853    //    the following steps when called:
1854    //    a. Perform AsyncModuleExecutionFulfilled(module).
1855    //    b. Return undefined.
1856    // 5. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 0, "", « »).
1857    // 6. Let rejectedClosure be a new Abstract Closure with parameters (error) that captures module and performs
1858    //    the following steps when called:
1859    //    a. Perform AsyncModuleExecutionRejected(module, error).
1860    //    b. Return undefined.
1861    // 7. Let onRejected be CreateBuiltinFunction(rejectedClosure, 0, "", « »).
1862    // 8. Perform PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected).
1863    JSHandle<JSPromise> promise(thread, result.Value());
1864    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1865    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1866    JSHandle<JSAsyncModuleFulfilledFunction> onFulfilled =
1867                    factory->CreateJSAsyncModuleFulfilledFunction();
1868    onFulfilled->SetModule(thread, module);
1869
1870    JSHandle<JSAsyncModuleRejectedFunction> onRejected =
1871                    factory->CreateJSAsyncModuleRejectedFunction();
1872    onRejected->SetModule(thread, module);
1873    JSHandle<PromiseCapability> tcap =
1874                    JSPromise::NewPromiseCapability(thread, JSHandle<JSTaggedValue>::Cast(env->GetPromiseFunction()));
1875    RETURN_IF_ABRUPT_COMPLETION(thread);
1876    builtins::BuiltinsPromise::PerformPromiseThen(
1877        thread, promise, JSHandle<JSTaggedValue>::Cast(onFulfilled),
1878        JSHandle<JSTaggedValue>::Cast(onRejected), tcap);
1879}
1880
1881void SourceTextModule::GatherAvailableAncestors(JSThread *thread, const JSHandle<SourceTextModule> &module,
1882                                                AsyncParentCompletionSet &execList)
1883{
1884    auto globalConstants = thread->GlobalConstants();
1885    JSTaggedValue asyncParentModulesValue = module->GetAsyncParentModules();
1886    if (asyncParentModulesValue.IsUndefined()) {
1887        return;
1888    }
1889    JSMutableHandle<SourceTextModule> cycleRoot(thread, globalConstants->GetUndefined());
1890    JSHandle<TaggedArray> asyncParentModules(thread, asyncParentModulesValue);
1891    size_t asyncParentModulesLen = asyncParentModules->GetLength();
1892    // 1. For each Cyclic Module Record m of module.[[AsyncParentModules]], do
1893    for (size_t idx = 0; idx < asyncParentModulesLen; idx++) {
1894        JSHandle<SourceTextModule> parentModule(thread, asyncParentModules->Get(idx));
1895        // a. If execList does not contain m and m.[[CycleRoot]].[[EvaluationError]] is EMPTY, then
1896        cycleRoot.Update(parentModule->GetCycleRoot());
1897        if (execList.find(parentModule) == execList.end() &&
1898            cycleRoot->GetEvaluationError() == SourceTextModule::UNDEFINED_INDEX) {
1899            // i. Assert: m.[[Status]] is EVALUATING-ASYNC.
1900            ASSERT(parentModule->GetStatus() == ModuleStatus::EVALUATING_ASYNC);
1901            // ii. Assert: m.[[EvaluationError]] is EMPTY.
1902            ASSERT(parentModule->GetEvaluationError() == SourceTextModule::UNDEFINED_INDEX);
1903            // iii. Assert: m.[[AsyncEvaluation]] is true.
1904            ASSERT(parentModule->IsAsyncEvaluating());
1905            // iv. Assert: m.[[PendingAsyncDependencies]] > 0.
1906            ASSERT(parentModule->GetPendingAsyncDependencies() > 0);
1907            // v. Set m.[[PendingAsyncDependencies]] to m.[[PendingAsyncDependencies]] - 1.
1908            parentModule->SetPendingAsyncDependencies(parentModule->GetPendingAsyncDependencies() - 1);
1909            // vi. If m.[[PendingAsyncDependencies]] = 0, then
1910            //     1. Append m to execList.
1911            //     2. If m.[[HasTLA]] is false, perform GatherAvailableAncestors(m, execList).
1912            if (parentModule->GetPendingAsyncDependencies() == 0) {
1913                execList.insert(parentModule);
1914                if (!parentModule->GetHasTLA()) {
1915                    GatherAvailableAncestors(thread, parentModule, execList);
1916                }
1917            }
1918        }
1919    }
1920}
1921
1922void SourceTextModule::AsyncModuleExecutionFulfilled(JSThread *thread, const JSHandle<SourceTextModule> &module)
1923{
1924    // 1. If module.[[Status]] is EVALUATED, then
1925    //    a. Assert: module.[[EvaluationError]] is not EMPTY.
1926    //    b. Return UNUSED.
1927    if (module->GetStatus() == ModuleStatus::EVALUATED) {
1928        ASSERT(module->GetEvaluationError() != SourceTextModule::UNDEFINED_INDEX);
1929        return;
1930    }
1931    // 2. Assert: module.[[Status]] is EVALUATING-ASYNC.
1932    ASSERT(module->GetStatus() == ModuleStatus::EVALUATING_ASYNC);
1933    // 3. Assert: module.[[AsyncEvaluation]] is true.
1934    ASSERT(module->IsAsyncEvaluating());
1935    // 4. Assert: module.[[EvaluationError]] is EMPTY.
1936    ASSERT(module->GetEvaluationError() == SourceTextModule::UNDEFINED_INDEX);
1937    // 5. Set module.[[AsyncEvaluation]] to false.
1938    module->SetAsyncEvaluatingOrdinal(ASYNC_EVALUATE_DID_FINISH);
1939    // 6. Set module.[[Status]] to EVALUATED.
1940    module->SetStatus(ModuleStatus::EVALUATED);
1941    // 7. If module.[[TopLevelCapability]] is not EMPTY, then
1942    //    a. Assert: module.[[CycleRoot]] is module.
1943    //    b. Perform ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »).
1944    auto globalConstants = thread->GlobalConstants();
1945    JSTaggedValue topLevelCapabilityValue = module->GetTopLevelCapability();
1946    if (!topLevelCapabilityValue.IsUndefined()) {
1947        ASSERT(JSTaggedValue::SameValue(module->GetCycleRoot(), module.GetTaggedValue()));
1948        JSHandle<PromiseCapability> topLevelCapability(thread, topLevelCapabilityValue);
1949        JSHandle<JSTaggedValue> resolve(thread, topLevelCapability->GetResolve());
1950        JSHandle<JSTaggedValue> undefined = globalConstants->GetHandledUndefined();
1951        EcmaRuntimeCallInfo *info =
1952            EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefined, undefined, 1);
1953        RETURN_IF_ABRUPT_COMPLETION(thread);
1954        info->SetCallArg(JSTaggedValue::Undefined());
1955        [[maybe_unused]] JSTaggedValue res = JSFunction::Call(info);
1956        RETURN_IF_ABRUPT_COMPLETION(thread);
1957    }
1958    // 8. Let execList be a new empty List.
1959    AsyncParentCompletionSet execList;
1960    // 9. Perform GatherAvailableAncestors(module, execList).
1961    // 10. Let sortedExecList be a List whose elements are the elements of execList,
1962    //     in the order in which they had their [[AsyncEvaluation]] fields set to true in InnerModuleEvaluation.
1963    GatherAvailableAncestors(thread, module, execList);
1964    // 11. Assert: All elements of sortedExecList have their [[AsyncEvaluation]] field set to true,
1965    //     [[PendingAsyncDependencies]] field set to 0, and [[EvaluationError]] field set to EMPTY.
1966    // 12. For each Cyclic Module Record m of sortedExecList, do
1967    for (JSHandle<SourceTextModule> m : execList) {
1968        // a. If m.[[Status]] is EVALUATED, then
1969        //    i. Assert: m.[[EvaluationError]] is not EMPTY.
1970        if (m->GetStatus() == ModuleStatus::EVALUATED) {
1971            ASSERT(m->GetEvaluationError() != UNDEFINED_INDEX);
1972        // b. Else if m.[[HasTLA]] is true, then
1973        //    i. Perform ExecuteAsyncModule(m).
1974        } else if (m->GetHasTLA()) {
1975            ExecuteAsyncModule(thread, m);
1976        // c. Else,
1977        } else {
1978            // i. Let result be m.ExecuteModule().
1979            Expected<JSTaggedValue, bool> result = SourceTextModule::ModuleExecution(thread, m);
1980            // ii. If result is an abrupt completion, then
1981            //     1. Perform AsyncModuleExecutionRejected(m, result.[[Value]]).
1982            if (thread->HasPendingException() || !result || result.Value().IsException()) {
1983                AsyncModuleExecutionRejected(thread, m, JSTaggedValue::Exception());
1984            // iii. Else,
1985            } else {
1986                // 1. Set m.[[Status]] to EVALUATED.
1987                m->SetStatus(ModuleStatus::EVALUATED);
1988                // 2. If m.[[TopLevelCapability]] is not EMPTY, then
1989                //    a. Assert: m.[[CycleRoot]] is m.
1990                //    b. Perform ! Call(m.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »).
1991                JSTaggedValue capabilityValue = m->GetTopLevelCapability();
1992                if (!capabilityValue.IsUndefined()) {
1993                    ASSERT(JSTaggedValue::SameValue(m->GetCycleRoot(), m.GetTaggedValue()));
1994                    JSHandle<PromiseCapability> topLevelCapability(thread, capabilityValue);
1995                    JSHandle<JSTaggedValue> resolve(thread, topLevelCapability->GetResolve());
1996                    JSHandle<JSTaggedValue> undefined = globalConstants->GetHandledUndefined();
1997                    EcmaRuntimeCallInfo *info =
1998                            EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefined, undefined, 1);
1999                    RETURN_IF_ABRUPT_COMPLETION(thread);
2000                    info->SetCallArg(JSTaggedValue::Undefined());
2001                    [[maybe_unused]] JSTaggedValue res = JSFunction::Call(info);
2002                    RETURN_IF_ABRUPT_COMPLETION(thread);
2003                }
2004            }
2005        }
2006    }
2007}
2008
2009void SourceTextModule::AsyncModuleExecutionRejected(JSThread *thread, const JSHandle<SourceTextModule> &module,
2010                                                    JSTaggedValue error)
2011{
2012    // 1. If module.[[Status]] is EVALUATED, then
2013    //    a. Assert: module.[[EvaluationError]] is not EMPTY.
2014    //    b. Return UNUSED.
2015    if (module->GetStatus() == ModuleStatus::EVALUATED) {
2016        ASSERT(module->GetEvaluationError() != SourceTextModule::UNDEFINED_INDEX);
2017        return;
2018    }
2019    // 2. Assert: module.[[Status]] is EVALUATING-ASYNC.
2020    ASSERT(module->GetStatus() == ModuleStatus::EVALUATING_ASYNC);
2021    // 3. Assert: module.[[AsyncEvaluation]] is true.
2022    ASSERT(module->IsAsyncEvaluating());
2023    // 4. Assert: module.[[EvaluationError]] is EMPTY.
2024    ASSERT(module->GetEvaluationError() == SourceTextModule::UNDEFINED_INDEX);
2025    // 5. Set module.[[EvaluationError]] to ThrowCompletion(error).
2026    module->SetEvaluationError(MODULE_ERROR);
2027    // 6. Set module.[[Status]] to EVALUATED.
2028    module->SetStatus(ModuleStatus::EVALUATED);
2029    // 7. For each Cyclic Module Record m of module.[[AsyncParentModules]], do
2030    //    a. Perform AsyncModuleExecutionRejected(m, error).
2031    auto globalConstants = thread->GlobalConstants();
2032    JSTaggedValue asyncParentModulesValue = module->GetAsyncParentModules();
2033    if (!asyncParentModulesValue.IsUndefined()) {
2034        JSMutableHandle<SourceTextModule> parentModule(thread, globalConstants->GetUndefined());
2035        JSHandle<TaggedArray> asyncParentModules(thread, asyncParentModulesValue);
2036        size_t asyncParentModulesLen = asyncParentModules->GetLength();
2037        for (size_t idx = 0; idx < asyncParentModulesLen; idx++) {
2038            parentModule.Update(asyncParentModules->Get(idx));
2039            AsyncModuleExecutionRejected(thread, parentModule, error);
2040        }
2041    }
2042
2043    // 8. If module.[[TopLevelCapability]] is not EMPTY, then
2044    //    a. Assert: module.[[CycleRoot]] is module.
2045    //    b. Perform ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »).
2046    JSTaggedValue topLevelCapabilityValue = module->GetTopLevelCapability();
2047    if (!topLevelCapabilityValue.IsUndefined()) {
2048        JSHandle<JSTaggedValue> exceptionHandle(thread, error);
2049        // if caught exceptionHandle type is JSError
2050        if (exceptionHandle->IsJSError()) {
2051            thread->GetCurrentEcmaContext()->HandleUncaughtException(error);
2052        }
2053        ASSERT(JSTaggedValue::SameValue(module->GetCycleRoot(), module.GetTaggedValue()));
2054        JSHandle<PromiseCapability> topLevelCapability(thread, topLevelCapabilityValue);
2055        JSHandle<JSTaggedValue> reject(thread, topLevelCapability->GetReject());
2056        JSHandle<JSTaggedValue> undefined = globalConstants->GetHandledUndefined();
2057        EcmaRuntimeCallInfo *info =
2058            EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefined, undefined, 1);
2059        RETURN_IF_ABRUPT_COMPLETION(thread);
2060        info->SetCallArg(error);
2061        [[maybe_unused]] JSTaggedValue res = JSFunction::Call(info);
2062        RETURN_IF_ABRUPT_COMPLETION(thread);
2063    }
2064}
2065
2066JSTaggedValue SourceTextModule::AsyncModuleFulfilledFunc(EcmaRuntimeCallInfo *argv)
2067{
2068    ASSERT(argv);
2069    JSThread *thread = argv->GetThread();
2070    [[maybe_unused]] EcmaHandleScope handleScope(thread);
2071    JSHandle<JSAsyncModuleFulfilledFunction> fulfilledFunc =
2072        JSHandle<JSAsyncModuleFulfilledFunction>::Cast(base::BuiltinsBase::GetConstructor(argv));
2073    JSHandle<SourceTextModule> module(thread, fulfilledFunc->GetModule());
2074    AsyncModuleExecutionFulfilled(thread, module);
2075    return JSTaggedValue::Undefined();
2076}
2077
2078JSTaggedValue SourceTextModule::AsyncModuleRejectedFunc(EcmaRuntimeCallInfo *argv)
2079{
2080    // 1. Let F be the active function object.
2081    ASSERT(argv);
2082    JSThread *thread = argv->GetThread();
2083    [[maybe_unused]] EcmaHandleScope handleScope(thread);
2084    JSHandle<JSAsyncModuleRejectedFunction> rejectedFunc =
2085        JSHandle<JSAsyncModuleRejectedFunction>::Cast(base::BuiltinsBase::GetConstructor(argv));
2086    JSHandle<SourceTextModule> module(thread, rejectedFunc->GetModule());
2087    [[maybe_unused]] JSHandle<JSTaggedValue> value = base::BuiltinsBase::GetCallArg(argv, 0);
2088    AsyncModuleExecutionRejected(thread, module, value.GetTaggedValue());
2089    return JSTaggedValue::Undefined();
2090}
2091
2092void SourceTextModule::CheckCircularImportTool(JSThread *thread, const CString &circularModuleRecordName,
2093                                               CList<CString> &referenceList, bool printOtherCircular)
2094{
2095    referenceList.push_back(circularModuleRecordName);
2096    JSMutableHandle<SourceTextModule> moduleRecord(thread, thread->GlobalConstants()->GetUndefined());
2097    auto moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
2098    if (moduleManager->IsLocalModuleLoaded(circularModuleRecordName)) {
2099        moduleRecord.Update(moduleManager->HostGetImportedModule(circularModuleRecordName));
2100    } else {
2101        moduleRecord.Update(moduleManager->HostResolveImportedModule(circularModuleRecordName));
2102        RETURN_IF_ABRUPT_COMPLETION(thread);
2103    }
2104    CString requiredModuleName;
2105    SourceTextModule::SearchCircularImport(
2106        thread, circularModuleRecordName, moduleRecord, referenceList, requiredModuleName, printOtherCircular);
2107}
2108
2109void SourceTextModule::SearchCircularImport(JSThread *thread, const CString &circularModuleRecordName,
2110                                            const JSHandle<SourceTextModule> &module,
2111                                            CList<CString> &referenceList,
2112                                            CString &requiredModuleName, bool printOtherCircular)
2113{
2114    if (module->GetRequestedModules().IsUndefined()) {
2115        return;
2116    }
2117    auto globalConstants = thread->GlobalConstants();
2118    JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
2119    size_t requestedModulesLen = requestedModules->GetLength();
2120    JSMutableHandle<JSTaggedValue> required(thread, globalConstants->GetUndefined());
2121    JSMutableHandle<SourceTextModule> requiredModule(thread, globalConstants->GetUndefined());
2122    for (size_t idx = 0; idx < requestedModulesLen; idx++) {
2123        required.Update(requestedModules->Get(idx));
2124        requiredModule.Update(JSHandle<SourceTextModule>::Cast(
2125            SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required)));
2126        RETURN_IF_ABRUPT_COMPLETION(thread);
2127        requiredModuleName = requiredModule->GetEcmaModuleRecordNameString();
2128        referenceList.push_back(requiredModuleName);
2129        if (requiredModuleName == circularModuleRecordName) {
2130            PrintCircular(referenceList, ERROR);
2131        } else if (printOtherCircular && IsCircular(referenceList, requiredModuleName)) {
2132            PrintCircular(referenceList, WARN);
2133        } else {
2134            SourceTextModule::SearchCircularImport(thread, circularModuleRecordName,
2135                requiredModule, referenceList, requiredModuleName, printOtherCircular);
2136        }
2137        referenceList.pop_back();
2138    }
2139}
2140
2141bool SourceTextModule::IsCircular(const CList<CString> &referenceList,
2142                                  const CString &requiredModuleName)
2143{
2144    for (auto iter = referenceList.begin(), end = --referenceList.end(); iter != end; ++iter) {
2145        if (requiredModuleName == *iter) {
2146            return true;
2147        }
2148    }
2149    return false;
2150}
2151
2152void SourceTextModule::PrintCircular(const CList<CString> &referenceList, Level level)
2153{
2154    LOG_ECMA(INFO) << "checkCircularImport begin ----------------------------------------";
2155    if (level == Level::ERROR) {
2156        for (auto iter : referenceList) {
2157            LOG_ECMA(ERROR) << "checkCircularImport record: " << iter;
2158        }
2159    } else {
2160        for (auto iter : referenceList) {
2161            LOG_ECMA(WARN) << "checkCircularImport record: " << iter;
2162        }
2163    }
2164    LOG_ECMA(INFO) << "checkCircularImport end ------------------------------------------";
2165}
2166
2167CString SourceTextModule::ReplaceModuleThroughFeature(JSThread *thread, const CString &requestName)
2168{
2169    auto vm = thread->GetEcmaVM();
2170    // check if module need to be mock
2171    if (vm->IsMockModule(requestName)) {
2172        return vm->GetMockModule(requestName);
2173    }
2174
2175    // Load the replaced module, hms -> system hsp
2176    if (vm->IsHmsModule(requestName)) {
2177        return vm->GetHmsModule(requestName);
2178    }
2179    return requestName;
2180}
2181} // namespace panda::ecmascript
2182