1 /*
2 * Copyright (c) 2022 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/jspandafile/accessor/module_data_accessor.h"
17 #include "ecmascript/jspandafile/js_pandafile_manager.h"
18
19 namespace panda::ecmascript {
ModuleDataAccessor(const panda_file::File & pandaFile,panda_file::File::EntityId moduleDataId)20 ModuleDataAccessor::ModuleDataAccessor(const panda_file::File &pandaFile, panda_file::File::EntityId moduleDataId)
21 : pandaFile_(pandaFile), moduleDataId_(moduleDataId)
22 {
23 auto sp = pandaFile_.GetSpanFromId(moduleDataId);
24
25 auto moduleSp = sp.SubSpan(panda_file::ID_SIZE); // skip literalnum
26
27 numModuleRequests_ = panda_file::helpers::Read<panda_file::ID_SIZE>(&moduleSp);
28
29 for (size_t idx = 0; idx < numModuleRequests_; idx++) {
30 auto value = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&moduleSp));
31 moduleRequests_.emplace_back(value);
32 }
33
34 entryDataSp_ = moduleSp;
35 }
36
EnumerateImportEntry(JSThread * thread,const JSHandle<TaggedArray> & requestModuleArray,JSHandle<SourceTextModule> & moduleRecord)37 void ModuleDataAccessor::EnumerateImportEntry(JSThread *thread,
38 const JSHandle<TaggedArray> &requestModuleArray,
39 JSHandle<SourceTextModule> &moduleRecord)
40 {
41 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
42 auto globalConstants = thread->GlobalConstants();
43 size_t requestArraySize = requestModuleArray->GetLength();
44 auto sp = entryDataSp_;
45
46 auto regularImportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
47 JSHandle<TaggedArray> regularImportEntries = factory->NewTaggedArray(regularImportNum);
48 JSMutableHandle<JSTaggedValue> importName(thread, globalConstants->GetUndefined());
49 JSMutableHandle<JSTaggedValue> localName(thread, globalConstants->GetUndefined());
50 JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
51
52 for (size_t idx = 0; idx < regularImportNum; idx++) {
53 auto localNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
54 auto importNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
55 auto moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(&sp));
56 StringData sd = pandaFile_.GetStringData(panda_file::File::EntityId(localNameOffset));
57 localName.Update(JSTaggedValue(factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii)));
58
59 sd = pandaFile_.GetStringData(panda_file::File::EntityId(importNameOffset));
60 importName.Update(JSTaggedValue(factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii)));
61
62 if (requestArraySize != 0) {
63 moduleRequest.Update(requestModuleArray->Get(moduleRequestIdx));
64 }
65 JSHandle<ImportEntry> importEntry = factory->NewImportEntry(moduleRequest, importName, localName);
66 regularImportEntries->Set(thread, idx, importEntry);
67 }
68
69 auto namespaceImportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
70 auto totalSize = regularImportNum + namespaceImportNum;
71 if (totalSize == 0) {
72 entryDataSp_ = sp;
73 return;
74 }
75 JSHandle<TaggedArray> importEntries = TaggedArray::SetCapacity(thread, regularImportEntries, totalSize);
76 importName.Update(globalConstants->GetHandledStarString());
77 for (size_t idx = regularImportNum; idx < totalSize; idx++) {
78 auto localNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
79 auto moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(&sp));
80 StringData sd = pandaFile_.GetStringData(panda_file::File::EntityId(localNameOffset));
81 localName.Update(JSTaggedValue(factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii)));
82
83 if (requestArraySize != 0) {
84 moduleRequest.Update(requestModuleArray->Get(moduleRequestIdx));
85 }
86 JSHandle<ImportEntry> importEntry = factory->NewImportEntry(moduleRequest, importName, localName);
87 importEntries->Set(thread, idx, importEntry);
88 }
89 entryDataSp_ = sp;
90 moduleRecord->SetImportEntries(thread, importEntries);
91 }
92
EnumerateLocalExportEntry(JSThread * thread,JSHandle<SourceTextModule> & moduleRecord)93 void ModuleDataAccessor::EnumerateLocalExportEntry(JSThread *thread, JSHandle<SourceTextModule> &moduleRecord)
94 {
95 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
96 auto sp = entryDataSp_;
97
98 auto localExportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
99 if (localExportNum == 0) {
100 entryDataSp_ = sp;
101 return;
102 }
103 JSHandle<TaggedArray> localExportEntries = factory->NewTaggedArray(localExportNum);
104 uint32_t localIndex = -1;
105 JSMutableHandle<JSTaggedValue> distinctLocalName(thread, JSTaggedValue::Undefined());
106
107 for (size_t idx = 0; idx < localExportNum; idx++) {
108 auto localNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
109 auto exportNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
110 StringData sd = pandaFile_.GetStringData(panda_file::File::EntityId(localNameOffset));
111 JSHandle<JSTaggedValue> localName(thread,
112 factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii));
113
114 sd = pandaFile_.GetStringData(panda_file::File::EntityId(exportNameOffset));
115 JSHandle<JSTaggedValue> exportName(thread,
116 factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii));
117
118 if (!JSTaggedValue::StrictEqual(thread, distinctLocalName, localName)) {
119 distinctLocalName.Update(localName);
120 localIndex++;
121 }
122 JSHandle<LocalExportEntry> localExportEntry = factory->NewLocalExportEntry(exportName, localName, localIndex);
123 localExportEntries->Set(thread, idx, localExportEntry);
124 }
125 entryDataSp_ = sp;
126 moduleRecord->SetLocalExportEntries(thread, localExportEntries);
127 }
128
EnumerateIndirectExportEntry(JSThread * thread,const JSHandle<TaggedArray> & requestModuleArray,JSHandle<SourceTextModule> & moduleRecord)129 void ModuleDataAccessor::EnumerateIndirectExportEntry(JSThread *thread, const JSHandle<TaggedArray> &requestModuleArray,
130 JSHandle<SourceTextModule> &moduleRecord)
131 {
132 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
133 auto globalConstants = thread->GlobalConstants();
134 auto sp = entryDataSp_;
135 size_t requestArraySize = requestModuleArray->GetLength();
136
137 auto indirectExportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
138 if (indirectExportNum == 0) {
139 entryDataSp_ = sp;
140 return;
141 }
142 JSHandle<TaggedArray> indirectExportEntries = factory->NewTaggedArray(indirectExportNum);
143 JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
144 JSHandle<IndirectExportEntry> indirectExportEntry = factory->NewIndirectExportEntry();
145 for (size_t idx = 0; idx < indirectExportNum; idx++) {
146 auto exportNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
147 auto importNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
148 auto moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(&sp));
149 StringData sd = pandaFile_.GetStringData(panda_file::File::EntityId(exportNameOffset));
150 JSHandle<JSTaggedValue> exportName(thread,
151 factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii));
152
153 sd = pandaFile_.GetStringData(panda_file::File::EntityId(importNameOffset));
154 JSHandle<JSTaggedValue> importName(thread,
155 factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii));
156
157 if (requestArraySize != 0) {
158 moduleRequest.Update(requestModuleArray->Get(moduleRequestIdx));
159 }
160 indirectExportEntry = factory->NewIndirectExportEntry(exportName, moduleRequest, importName);
161 indirectExportEntries->Set(thread, idx, indirectExportEntry);
162 }
163 entryDataSp_ = sp;
164 moduleRecord->SetIndirectExportEntries(thread, indirectExportEntries);
165 }
166
EnumerateStarExportEntry(JSThread * thread,const JSHandle<TaggedArray> & requestModuleArray,JSHandle<SourceTextModule> & moduleRecord)167 void ModuleDataAccessor::EnumerateStarExportEntry(JSThread *thread, const JSHandle<TaggedArray> &requestModuleArray,
168 JSHandle<SourceTextModule> &moduleRecord)
169 {
170 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
171 auto globalConstants = thread->GlobalConstants();
172 auto sp = entryDataSp_;
173 size_t requestArraySize = requestModuleArray->GetLength();
174
175 auto starExportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
176 if (starExportNum == 0) {
177 entryDataSp_ = sp;
178 return;
179 }
180 JSHandle<TaggedArray> starExportEntries = factory->NewTaggedArray(starExportNum);
181 JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
182 JSHandle<StarExportEntry> starExportEntry = factory->NewStarExportEntry();
183 for (size_t idx = 0; idx < starExportNum; idx++) {
184 auto moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(&sp));
185 if (requestArraySize != 0) {
186 moduleRequest.Update(requestModuleArray->Get(moduleRequestIdx));
187 }
188
189 starExportEntry = factory->NewStarExportEntry(moduleRequest);
190 starExportEntries->Set(thread, idx, starExportEntry.GetTaggedValue());
191 }
192 entryDataSp_ = sp;
193 moduleRecord->SetStarExportEntries(thread, starExportEntries);
194 }
195 } // namespace panda::ecmascript
196