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