/* * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ecmascript/module/accessor/module_data_accessor.h" #include "ecmascript/global_env_constants-inl.h" #include "ecmascript/jspandafile/js_pandafile_manager.h" #include "ecmascript/shared_objects/js_shared_array.h" namespace panda::ecmascript { ModuleDataAccessor::ModuleDataAccessor(const JSPandaFile *pandaFile, EntityId moduleDataId) : pandaFile_(pandaFile), moduleDataId_(moduleDataId) { auto &pf = *pandaFile_->GetPandaFile(); auto sp = pf.GetSpanFromId(moduleDataId); auto moduleSp = sp.SubSpan(panda_file::ID_SIZE); // skip literalnum numModuleRequests_ = panda_file::helpers::Read(&moduleSp); for (size_t idx = 0; idx < numModuleRequests_; idx++) { auto value = static_cast(panda_file::helpers::Read(&moduleSp)); moduleRequests_.emplace_back(value); } entryDataSp_ = moduleSp; } JSHandle ModuleDataAccessor::CreatEntries(JSThread *thread, uint32_t regularImportNum, SharedTypes sharedType) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle regularImportEntries; if (sharedType == SharedTypes::SHARED_MODULE) { regularImportEntries = factory->NewSTaggedArray(regularImportNum, JSTaggedValue::Hole(), MemSpaceType::SHARED_OLD_SPACE); } else { regularImportEntries = factory->NewTaggedArray(regularImportNum); } return regularImportEntries; } void ModuleDataAccessor::EnumerateImportEntry(JSThread *thread, JSHandle &moduleRecord) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); auto globalConstants = thread->GlobalConstants(); auto sp = entryDataSp_; SharedTypes sharedType = moduleRecord->GetSharedType(); uint32_t regularImportNum = panda_file::helpers::Read(&sp); JSHandle regularImportEntries = CreatEntries(thread, regularImportNum, sharedType); JSMutableHandle importName(thread, globalConstants->GetUndefined()); JSMutableHandle localName(thread, globalConstants->GetUndefined()); uint32_t moduleRequestIdx = 0; for (uint32_t idx = 0; idx < regularImportNum; idx++) { ReadRegularImportEntry(&sp, factory, importName, localName, moduleRequestIdx); JSHandle importEntry = factory->NewImportEntry(moduleRequestIdx, importName, localName, sharedType); regularImportEntries->Set(thread, idx, importEntry); } uint32_t namespaceImportNum = panda_file::helpers::Read(&sp); uint32_t totalSize = regularImportNum + namespaceImportNum; if (totalSize == 0) { entryDataSp_ = sp; return; } JSHandle importEntries; if (sharedType == SharedTypes::SHARED_MODULE) { importEntries = JSSharedArray::SetCapacity(thread, regularImportEntries, totalSize); } else { importEntries = TaggedArray::SetCapacity(thread, regularImportEntries, totalSize); } importName.Update(globalConstants->GetHandledStarString()); for (uint32_t idx = regularImportNum; idx < totalSize; idx++) { ReadNamespaceImportEntry(&sp, factory, localName, moduleRequestIdx); JSHandle importEntry = factory->NewImportEntry(moduleRequestIdx, importName, localName, sharedType); importEntries->Set(thread, idx, importEntry); } entryDataSp_ = sp; moduleRecord->SetImportEntries(thread, importEntries); } void ModuleDataAccessor::ReadRegularImportEntry(Span *sp, ObjectFactory *factory, JSMutableHandle &importName, JSMutableHandle &localName, uint32_t &moduleRequestIdx) { auto localNameOffset = static_cast(panda_file::helpers::Read(sp)); auto importNameOffset = static_cast(panda_file::helpers::Read(sp)); moduleRequestIdx = static_cast(panda_file::helpers::Read(sp)); auto sd = pandaFile_->GetStringData(panda_file::File::EntityId(localNameOffset)); localName.Update(JSTaggedValue(factory->GetRawStringFromStringTable(sd))); sd = pandaFile_->GetStringData(panda_file::File::EntityId(importNameOffset)); importName.Update(JSTaggedValue(factory->GetRawStringFromStringTable(sd))); } void ModuleDataAccessor::ReadNamespaceImportEntry(Span *sp, ObjectFactory *factory, JSMutableHandle &localName, uint32_t &moduleRequestIdx) { auto localNameOffset = static_cast(panda_file::helpers::Read(sp)); moduleRequestIdx = static_cast(panda_file::helpers::Read(sp)); auto sd = pandaFile_->GetStringData(panda_file::File::EntityId(localNameOffset)); localName.Update(JSTaggedValue(factory->GetRawStringFromStringTable(sd))); } void ModuleDataAccessor::EnumerateLocalExportEntry(JSThread *thread, JSHandle &moduleRecord) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); auto sp = entryDataSp_; auto localExportNum = panda_file::helpers::Read(&sp); if (localExportNum == 0) { entryDataSp_ = sp; return; } SharedTypes sharedType = moduleRecord->GetSharedType(); JSHandle localExportEntries = CreatEntries(thread, localExportNum, sharedType); uint32_t localIndex = -1; JSMutableHandle distinctLocalName(thread, JSTaggedValue::Undefined()); for (size_t idx = 0; idx < localExportNum; idx++) { auto localNameOffset = static_cast(panda_file::helpers::Read(&sp)); auto exportNameOffset = static_cast(panda_file::helpers::Read(&sp)); auto sd = pandaFile_->GetStringData(panda_file::File::EntityId(localNameOffset)); JSHandle localName(thread, factory->GetRawStringFromStringTable(sd)); sd = pandaFile_->GetStringData(panda_file::File::EntityId(exportNameOffset)); JSHandle exportName(thread, factory->GetRawStringFromStringTable(sd)); if (!JSTaggedValue::StrictEqual(thread, distinctLocalName, localName)) { distinctLocalName.Update(localName); localIndex++; } JSHandle localExportEntry = factory->NewLocalExportEntry(exportName, localName, localIndex, sharedType); localExportEntries->Set(thread, idx, localExportEntry); } entryDataSp_ = sp; moduleRecord->SetLocalExportEntries(thread, localExportEntries); } void ModuleDataAccessor::EnumerateIndirectExportEntry(JSThread *thread, JSHandle &moduleRecord) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); auto globalConstants = thread->GlobalConstants(); auto sp = entryDataSp_; auto indirectExportNum = panda_file::helpers::Read(&sp); if (indirectExportNum == 0) { entryDataSp_ = sp; return; } SharedTypes sharedType = moduleRecord->GetSharedType(); JSHandle indirectExportEntries = CreatEntries(thread, indirectExportNum, sharedType); JSMutableHandle moduleRequest(thread, globalConstants->GetUndefined()); for (size_t idx = 0; idx < indirectExportNum; idx++) { auto exportNameOffset = static_cast(panda_file::helpers::Read(&sp)); auto importNameOffset = static_cast(panda_file::helpers::Read(&sp)); auto moduleRequestIdx = static_cast(panda_file::helpers::Read(&sp)); auto sd = pandaFile_->GetStringData(panda_file::File::EntityId(exportNameOffset)); JSHandle exportName(thread, factory->GetRawStringFromStringTable(sd)); sd = pandaFile_->GetStringData(panda_file::File::EntityId(importNameOffset)); JSHandle importName(thread, factory->GetRawStringFromStringTable(sd)); JSHandle indirectExportEntry = factory->NewIndirectExportEntry(exportName, moduleRequestIdx, importName, sharedType); indirectExportEntries->Set(thread, idx, indirectExportEntry); } entryDataSp_ = sp; moduleRecord->SetIndirectExportEntries(thread, indirectExportEntries); } void ModuleDataAccessor::EnumerateStarExportEntry(JSThread *thread, JSHandle &moduleRecord) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); auto globalConstants = thread->GlobalConstants(); auto sp = entryDataSp_; uint32_t starExportNum = panda_file::helpers::Read(&sp); if (starExportNum == 0) { entryDataSp_ = sp; return; } SharedTypes sharedType = moduleRecord->GetSharedType(); JSHandle starExportEntries = CreatEntries(thread, starExportNum, sharedType); JSMutableHandle moduleRequest(thread, globalConstants->GetUndefined()); for (uint32_t idx = 0; idx < starExportNum; idx++) { uint32_t moduleRequestIdx = static_cast(panda_file::helpers::Read(&sp)); JSHandle starExportEntry = factory->NewStarExportEntry(moduleRequestIdx, sharedType); starExportEntries->Set(thread, idx, starExportEntry.GetTaggedValue()); } entryDataSp_ = sp; moduleRecord->SetStarExportEntries(thread, starExportEntries); } } // namespace panda::ecmascript