1 /*
2 * Copyright (c) 2022-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/module/accessor/module_data_accessor.h"
17
18 #include "ecmascript/global_env_constants-inl.h"
19 #include "ecmascript/jspandafile/js_pandafile_manager.h"
20 #include "ecmascript/shared_objects/js_shared_array.h"
21
22 namespace panda::ecmascript {
ModuleDataAccessor(const JSPandaFile * pandaFile,EntityId moduleDataId)23 ModuleDataAccessor::ModuleDataAccessor(const JSPandaFile *pandaFile, EntityId moduleDataId)
24 : pandaFile_(pandaFile), moduleDataId_(moduleDataId)
25 {
26 auto &pf = *pandaFile_->GetPandaFile();
27 auto sp = pf.GetSpanFromId(moduleDataId);
28
29 auto moduleSp = sp.SubSpan(panda_file::ID_SIZE); // skip literalnum
30
31 numModuleRequests_ = panda_file::helpers::Read<panda_file::ID_SIZE>(&moduleSp);
32
33 for (size_t idx = 0; idx < numModuleRequests_; idx++) {
34 auto value = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&moduleSp));
35 moduleRequests_.emplace_back(value);
36 }
37
38 entryDataSp_ = moduleSp;
39 }
40
CreatEntries(JSThread * thread,uint32_t regularImportNum,SharedTypes sharedType)41 JSHandle<TaggedArray> ModuleDataAccessor::CreatEntries(JSThread *thread, uint32_t regularImportNum,
42 SharedTypes sharedType)
43 {
44 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
45 JSHandle<TaggedArray> regularImportEntries;
46 if (sharedType == SharedTypes::SHARED_MODULE) {
47 regularImportEntries = factory->NewSTaggedArray(regularImportNum, JSTaggedValue::Hole(),
48 MemSpaceType::SHARED_OLD_SPACE);
49 } else {
50 regularImportEntries = factory->NewTaggedArray(regularImportNum);
51 }
52 return regularImportEntries;
53 }
54
EnumerateImportEntry(JSThread * thread,JSHandle<SourceTextModule> & moduleRecord)55 void ModuleDataAccessor::EnumerateImportEntry(JSThread *thread, JSHandle<SourceTextModule> &moduleRecord)
56 {
57 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
58 auto globalConstants = thread->GlobalConstants();
59 auto sp = entryDataSp_;
60 SharedTypes sharedType = moduleRecord->GetSharedType();
61 uint32_t regularImportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
62 JSHandle<TaggedArray> regularImportEntries = CreatEntries(thread, regularImportNum, sharedType);
63
64 JSMutableHandle<JSTaggedValue> importName(thread, globalConstants->GetUndefined());
65 JSMutableHandle<JSTaggedValue> localName(thread, globalConstants->GetUndefined());
66 uint32_t moduleRequestIdx = 0;
67
68 for (uint32_t idx = 0; idx < regularImportNum; idx++) {
69 ReadRegularImportEntry(&sp, factory, importName, localName, moduleRequestIdx);
70 JSHandle<ImportEntry> importEntry = factory->NewImportEntry(moduleRequestIdx, importName, localName,
71 sharedType);
72 regularImportEntries->Set(thread, idx, importEntry);
73 }
74 uint32_t namespaceImportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
75 uint32_t totalSize = regularImportNum + namespaceImportNum;
76 if (totalSize == 0) {
77 entryDataSp_ = sp;
78 return;
79 }
80 JSHandle<TaggedArray> importEntries;
81 if (sharedType == SharedTypes::SHARED_MODULE) {
82 importEntries = JSSharedArray::SetCapacity(thread, regularImportEntries, totalSize);
83 } else {
84 importEntries = TaggedArray::SetCapacity(thread, regularImportEntries, totalSize);
85 }
86
87 importName.Update(globalConstants->GetHandledStarString());
88
89 for (uint32_t idx = regularImportNum; idx < totalSize; idx++) {
90 ReadNamespaceImportEntry(&sp, factory, localName, moduleRequestIdx);
91 JSHandle<ImportEntry> importEntry = factory->NewImportEntry(moduleRequestIdx, importName, localName,
92 sharedType);
93 importEntries->Set(thread, idx, importEntry);
94 }
95 entryDataSp_ = sp;
96 moduleRecord->SetImportEntries(thread, importEntries);
97 }
98
ReadRegularImportEntry(Span<const uint8_t> * sp,ObjectFactory * factory,JSMutableHandle<JSTaggedValue> & importName,JSMutableHandle<JSTaggedValue> & localName,uint32_t & moduleRequestIdx)99 void ModuleDataAccessor::ReadRegularImportEntry(Span<const uint8_t> *sp, ObjectFactory *factory,
100 JSMutableHandle<JSTaggedValue> &importName,
101 JSMutableHandle<JSTaggedValue> &localName,
102 uint32_t &moduleRequestIdx)
103 {
104 auto localNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(sp));
105 auto importNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(sp));
106 moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(sp));
107 auto sd = pandaFile_->GetStringData(panda_file::File::EntityId(localNameOffset));
108 localName.Update(JSTaggedValue(factory->GetRawStringFromStringTable(sd)));
109
110 sd = pandaFile_->GetStringData(panda_file::File::EntityId(importNameOffset));
111 importName.Update(JSTaggedValue(factory->GetRawStringFromStringTable(sd)));
112 }
113
ReadNamespaceImportEntry(Span<const uint8_t> * sp,ObjectFactory * factory,JSMutableHandle<JSTaggedValue> & localName,uint32_t & moduleRequestIdx)114 void ModuleDataAccessor::ReadNamespaceImportEntry(Span<const uint8_t> *sp, ObjectFactory *factory,
115 JSMutableHandle<JSTaggedValue> &localName,
116 uint32_t &moduleRequestIdx)
117 {
118 auto localNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(sp));
119 moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(sp));
120 auto sd = pandaFile_->GetStringData(panda_file::File::EntityId(localNameOffset));
121 localName.Update(JSTaggedValue(factory->GetRawStringFromStringTable(sd)));
122 }
123
EnumerateLocalExportEntry(JSThread * thread,JSHandle<SourceTextModule> & moduleRecord)124 void ModuleDataAccessor::EnumerateLocalExportEntry(JSThread *thread, JSHandle<SourceTextModule> &moduleRecord)
125 {
126 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
127 auto sp = entryDataSp_;
128 auto localExportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
129 if (localExportNum == 0) {
130 entryDataSp_ = sp;
131 return;
132 }
133 SharedTypes sharedType = moduleRecord->GetSharedType();
134 JSHandle<TaggedArray> localExportEntries = CreatEntries(thread, localExportNum, sharedType);
135
136 uint32_t localIndex = -1;
137 JSMutableHandle<JSTaggedValue> distinctLocalName(thread, JSTaggedValue::Undefined());
138 for (size_t idx = 0; idx < localExportNum; idx++) {
139 auto localNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
140 auto exportNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
141 auto sd = pandaFile_->GetStringData(panda_file::File::EntityId(localNameOffset));
142 JSHandle<JSTaggedValue> localName(thread, factory->GetRawStringFromStringTable(sd));
143
144 sd = pandaFile_->GetStringData(panda_file::File::EntityId(exportNameOffset));
145 JSHandle<JSTaggedValue> exportName(thread, factory->GetRawStringFromStringTable(sd));
146
147 if (!JSTaggedValue::StrictEqual(thread, distinctLocalName, localName)) {
148 distinctLocalName.Update(localName);
149 localIndex++;
150 }
151 JSHandle<LocalExportEntry> localExportEntry = factory->NewLocalExportEntry(exportName, localName, localIndex,
152 sharedType);
153 localExportEntries->Set(thread, idx, localExportEntry);
154 }
155 entryDataSp_ = sp;
156 moduleRecord->SetLocalExportEntries(thread, localExportEntries);
157 }
158
EnumerateIndirectExportEntry(JSThread * thread,JSHandle<SourceTextModule> & moduleRecord)159 void ModuleDataAccessor::EnumerateIndirectExportEntry(JSThread *thread, JSHandle<SourceTextModule> &moduleRecord)
160 {
161 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
162 auto globalConstants = thread->GlobalConstants();
163 auto sp = entryDataSp_;
164
165 auto indirectExportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
166 if (indirectExportNum == 0) {
167 entryDataSp_ = sp;
168 return;
169 }
170
171 SharedTypes sharedType = moduleRecord->GetSharedType();
172 JSHandle<TaggedArray> indirectExportEntries = CreatEntries(thread, indirectExportNum, sharedType);
173 JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
174 for (size_t idx = 0; idx < indirectExportNum; idx++) {
175 auto exportNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
176 auto importNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
177 auto moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(&sp));
178 auto sd = pandaFile_->GetStringData(panda_file::File::EntityId(exportNameOffset));
179 JSHandle<JSTaggedValue> exportName(thread, factory->GetRawStringFromStringTable(sd));
180
181 sd = pandaFile_->GetStringData(panda_file::File::EntityId(importNameOffset));
182 JSHandle<JSTaggedValue> importName(thread, factory->GetRawStringFromStringTable(sd));
183
184 JSHandle<IndirectExportEntry> indirectExportEntry = factory->NewIndirectExportEntry(exportName,
185 moduleRequestIdx, importName, sharedType);
186 indirectExportEntries->Set(thread, idx, indirectExportEntry);
187 }
188 entryDataSp_ = sp;
189 moduleRecord->SetIndirectExportEntries(thread, indirectExportEntries);
190 }
191
EnumerateStarExportEntry(JSThread * thread,JSHandle<SourceTextModule> & moduleRecord)192 void ModuleDataAccessor::EnumerateStarExportEntry(JSThread *thread, JSHandle<SourceTextModule> &moduleRecord)
193 {
194 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
195 auto globalConstants = thread->GlobalConstants();
196 auto sp = entryDataSp_;
197
198 uint32_t starExportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
199 if (starExportNum == 0) {
200 entryDataSp_ = sp;
201 return;
202 }
203
204 SharedTypes sharedType = moduleRecord->GetSharedType();
205 JSHandle<TaggedArray> starExportEntries = CreatEntries(thread, starExportNum, sharedType);
206 JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
207 for (uint32_t idx = 0; idx < starExportNum; idx++) {
208 uint32_t moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(&sp));
209
210 JSHandle<StarExportEntry> starExportEntry = factory->NewStarExportEntry(moduleRequestIdx, sharedType);
211 starExportEntries->Set(thread, idx, starExportEntry.GetTaggedValue());
212 }
213 entryDataSp_ = sp;
214 moduleRecord->SetStarExportEntries(thread, starExportEntries);
215 }
216 } // namespace panda::ecmascript
217