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 JSHandle<LocalExportEntry> localExportEntry = factory->NewLocalExportEntry();
105 for (size_t idx = 0; idx < localExportNum; idx++) {
106 auto localNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
107 auto exportNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
108 StringData sd = pandaFile_.GetStringData(panda_file::File::EntityId(localNameOffset));
109 JSHandle<JSTaggedValue> localName(thread,
110 factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii));
111
112 sd = pandaFile_.GetStringData(panda_file::File::EntityId(exportNameOffset));
113 JSHandle<JSTaggedValue> exportName(thread,
114 factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii));
115
116 localExportEntry = factory->NewLocalExportEntry(exportName, localName);
117 localExportEntries->Set(thread, idx, localExportEntry);
118 }
119 entryDataSp_ = sp;
120 moduleRecord->SetLocalExportEntries(thread, localExportEntries);
121 }
122
EnumerateIndirectExportEntry(JSThread * thread,const JSHandle<TaggedArray> & requestModuleArray,JSHandle<SourceTextModule> & moduleRecord)123 void ModuleDataAccessor::EnumerateIndirectExportEntry(JSThread *thread, const JSHandle<TaggedArray> &requestModuleArray,
124 JSHandle<SourceTextModule> &moduleRecord)
125 {
126 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
127 auto globalConstants = thread->GlobalConstants();
128 auto sp = entryDataSp_;
129 size_t requestArraySize = requestModuleArray->GetLength();
130
131 auto indirectExportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
132 if (indirectExportNum == 0) {
133 entryDataSp_ = sp;
134 return;
135 }
136 JSHandle<TaggedArray> indirectExportEntries = factory->NewTaggedArray(indirectExportNum);
137 JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
138 JSHandle<IndirectExportEntry> indirectExportEntry = factory->NewIndirectExportEntry();
139 for (size_t idx = 0; idx < indirectExportNum; idx++) {
140 auto exportNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
141 auto importNameOffset = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
142 auto moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(&sp));
143 StringData sd = pandaFile_.GetStringData(panda_file::File::EntityId(exportNameOffset));
144 JSHandle<JSTaggedValue> exportName(thread,
145 factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii));
146
147 sd = pandaFile_.GetStringData(panda_file::File::EntityId(importNameOffset));
148 JSHandle<JSTaggedValue> importName(thread,
149 factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii));
150
151 if (requestArraySize != 0) {
152 moduleRequest.Update(requestModuleArray->Get(moduleRequestIdx));
153 }
154 indirectExportEntry = factory->NewIndirectExportEntry(exportName, moduleRequest, importName);
155 indirectExportEntries->Set(thread, idx, indirectExportEntry);
156 }
157 entryDataSp_ = sp;
158 moduleRecord->SetIndirectExportEntries(thread, indirectExportEntries);
159 }
160
EnumerateStarExportEntry(JSThread * thread,const JSHandle<TaggedArray> & requestModuleArray,JSHandle<SourceTextModule> & moduleRecord)161 void ModuleDataAccessor::EnumerateStarExportEntry(JSThread *thread, const JSHandle<TaggedArray> &requestModuleArray,
162 JSHandle<SourceTextModule> &moduleRecord)
163 {
164 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
165 auto globalConstants = thread->GlobalConstants();
166 auto sp = entryDataSp_;
167 size_t requestArraySize = requestModuleArray->GetLength();
168
169 auto starExportNum = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
170 if (starExportNum == 0) {
171 entryDataSp_ = sp;
172 return;
173 }
174 JSHandle<TaggedArray> starExportEntries = factory->NewTaggedArray(starExportNum);
175 JSMutableHandle<JSTaggedValue> moduleRequest(thread, globalConstants->GetUndefined());
176 JSHandle<StarExportEntry> starExportEntry = factory->NewStarExportEntry();
177 for (size_t idx = 0; idx < starExportNum; idx++) {
178 auto moduleRequestIdx = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint16_t)>(&sp));
179 if (requestArraySize != 0) {
180 moduleRequest.Update(requestModuleArray->Get(moduleRequestIdx));
181 }
182
183 starExportEntry = factory->NewStarExportEntry(moduleRequest);
184 starExportEntries->Set(thread, idx, starExportEntry.GetTaggedValue());
185 }
186 entryDataSp_ = sp;
187 moduleRecord->SetStarExportEntries(thread, starExportEntries);
188 }
189 } // namespace panda::ecmascript
190