1 /* 2 * Copyright (c) 2021 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 "sourceTextModuleRecord.h" 17 #include <binder/scope.h> 18 19 namespace panda::es2panda::parser { AddModuleRequest(const ModuleRequestRecord record)20 int SourceTextModuleRecord::AddModuleRequest(const ModuleRequestRecord record) 21 { 22 ASSERT(!record.source_.Empty()); 23 hasLazyImport_ = hasLazyImport_ || record.isLazy_; 24 25 int moduleRequestsSize = static_cast<int>(moduleRequestsMap_.size()); 26 if (moduleRequestsMap_.find(record) == moduleRequestsMap_.end()) { 27 moduleRequests_.emplace_back(record); 28 } 29 auto insertedRes = moduleRequestsMap_.insert(std::make_pair(record, moduleRequestsSize)); 30 return insertedRes.first->second; 31 } 32 33 // import x from 'test.js' 34 // import {x} from 'test.js' 35 // import {x as y} from 'test.js' 36 // import defaultExport from 'test.js' AddImportEntry(SourceTextModuleRecord::ImportEntry * entry)37 void SourceTextModuleRecord::AddImportEntry(SourceTextModuleRecord::ImportEntry *entry) 38 { 39 CHECK_NOT_NULL(entry); 40 ASSERT(entry != nullptr); 41 ASSERT(!entry->importName_.Empty()); 42 ASSERT(!entry->localName_.Empty()); 43 ASSERT(entry->moduleRequestIdx_ != -1); 44 regularImportEntries_.insert(std::make_pair(entry->localName_, entry)); 45 // the implicit indirect exports should be insert into indirectExportsEntries 46 // when add an ImportEntry. 47 // e.g. export { x }; import { x } from 'test.js' 48 CheckImplicitIndirectExport(entry); 49 } 50 51 // import * as x from 'test.js' AddStarImportEntry(SourceTextModuleRecord::ImportEntry * entry)52 void SourceTextModuleRecord::AddStarImportEntry(SourceTextModuleRecord::ImportEntry *entry) 53 { 54 ASSERT(!entry->localName_.Empty()); 55 ASSERT(entry->importName_.Empty()); 56 ASSERT(entry->moduleRequestIdx_ != -1); 57 namespaceImportEntries_.push_back(entry); 58 } 59 60 // export {x} 61 // export {x as y} 62 // export VariableStatement 63 // export Declaration 64 // export default ... AddLocalExportEntry(SourceTextModuleRecord::ExportEntry * entry)65 bool SourceTextModuleRecord::AddLocalExportEntry(SourceTextModuleRecord::ExportEntry *entry) 66 { 67 CHECK_NOT_NULL(entry); 68 ASSERT(entry->importName_.Empty()); 69 ASSERT(!entry->localName_.Empty()); 70 ASSERT(!entry->exportName_.Empty()); 71 ASSERT(entry->moduleRequestIdx_ == -1); 72 73 // the implicit indirect exports should be insert into indirectExportsEntries 74 // when add an ExportEntry. 75 // e.g. import { x } from 'test.js'; export { x } 76 if (CheckImplicitIndirectExport(entry)) { 77 return true; 78 } 79 if (!HasDuplicateExport(entry->exportName_)) { 80 localExportEntries_.insert(std::make_pair(entry->localName_, entry)); 81 return true; 82 } 83 return false; 84 } 85 86 // export {x} from 'test.js' 87 // export {x as y} from 'test.js' 88 // import { x } from 'test.js'; export { x } AddIndirectExportEntry(SourceTextModuleRecord::ExportEntry * entry)89 bool SourceTextModuleRecord::AddIndirectExportEntry(SourceTextModuleRecord::ExportEntry *entry) 90 { 91 CHECK_NOT_NULL(entry); 92 ASSERT(entry != nullptr); 93 ASSERT(!entry->importName_.Empty()); 94 ASSERT(!entry->exportName_.Empty()); 95 ASSERT(entry->localName_.Empty()); 96 ASSERT(entry->moduleRequestIdx_ != -1); 97 if (!HasDuplicateExport(entry->exportName_)) { 98 indirectExportEntries_.push_back(entry); 99 return true; 100 } 101 return false; 102 } 103 104 // export * from 'test.js' AddStarExportEntry(SourceTextModuleRecord::ExportEntry * entry)105 void SourceTextModuleRecord::AddStarExportEntry(SourceTextModuleRecord::ExportEntry *entry) 106 { 107 ASSERT(entry->importName_.Empty()); 108 ASSERT(entry->localName_.Empty()); 109 ASSERT(entry->exportName_.Empty()); 110 ASSERT(entry->moduleRequestIdx_ != -1); 111 starExportEntries_.push_back(entry); 112 } 113 HasDuplicateExport(util::StringView exportName) const114 bool SourceTextModuleRecord::HasDuplicateExport(util::StringView exportName) const 115 { 116 for (auto const &entryUnit : localExportEntries_) { 117 const SourceTextModuleRecord::ExportEntry *e = entryUnit.second; 118 if (exportName == e->exportName_) { 119 return true; 120 } 121 } 122 123 for (const auto *e : indirectExportEntries_) { 124 if (exportName == e->exportName_) { 125 return true; 126 } 127 } 128 129 return false; 130 } 131 CheckImplicitIndirectExport(SourceTextModuleRecord::ExportEntry * exportEntry)132 bool SourceTextModuleRecord::CheckImplicitIndirectExport(SourceTextModuleRecord::ExportEntry *exportEntry) 133 { 134 CHECK_NOT_NULL(exportEntry); 135 ASSERT(exportEntry != nullptr); 136 ASSERT(!exportEntry->localName_.Empty()); 137 auto regularImport = regularImportEntries_.find(exportEntry->localName_); 138 if (regularImport != regularImportEntries_.end()) { 139 ConvertLocalExportToIndirect(regularImport->second, exportEntry); 140 return AddIndirectExportEntry(exportEntry); 141 } 142 return false; 143 } 144 CheckImplicitIndirectExport(SourceTextModuleRecord::ImportEntry * importEntry)145 void SourceTextModuleRecord::CheckImplicitIndirectExport(SourceTextModuleRecord::ImportEntry *importEntry) 146 { 147 ASSERT(!importEntry->localName_.Empty()); 148 auto range = localExportEntries_.equal_range(importEntry->localName_); 149 // not found implicit indirect 150 if (range.first == range.second) { 151 return; 152 } 153 154 for (auto it = range.first; it != range.second; ++it) { 155 SourceTextModuleRecord::ExportEntry *exportEntry = it->second; 156 ConvertLocalExportToIndirect(importEntry, exportEntry); 157 indirectExportEntries_.push_back(exportEntry); 158 } 159 localExportEntries_.erase(range.first, range.second); 160 } 161 ConvertLocalExportToIndirect(SourceTextModuleRecord::ImportEntry * importEntry,SourceTextModuleRecord::ExportEntry * exportEntry)162 void SourceTextModuleRecord::ConvertLocalExportToIndirect(SourceTextModuleRecord::ImportEntry *importEntry, 163 SourceTextModuleRecord::ExportEntry *exportEntry) 164 { 165 CHECK_NOT_NULL(importEntry); 166 ASSERT(exportEntry->importName_.Empty()); 167 ASSERT(exportEntry->moduleRequestIdx_ == -1); 168 ASSERT(!importEntry->importName_.Empty()); 169 ASSERT(importEntry->moduleRequestIdx_ != -1); 170 exportEntry->importName_ = importEntry->importName_; 171 exportEntry->moduleRequestIdx_ = importEntry->moduleRequestIdx_; 172 exportEntry->localName_ = util::StringView(""); 173 } 174 AssignIndexToModuleVariable(binder::ModuleScope * moduleScope)175 void SourceTextModuleRecord::AssignIndexToModuleVariable(binder::ModuleScope *moduleScope) 176 { 177 uint32_t index = 0; 178 for (auto it = localExportEntries_.begin(); it != localExportEntries_.end(); 179 it = localExportEntries_.upper_bound(it->first)) { 180 auto variable = CheckAndAssignIndex(moduleScope, it->first, &index); 181 if (variable != nullptr && variable->IsModuleVariable() && variable->Declaration()->IsConstDecl()) { 182 auto range = localExportEntries_.equal_range(it->first); 183 for (auto local_iter = range.first; local_iter != range.second; local_iter++) { 184 local_iter->second->SetAsConstant(); 185 } 186 } 187 } 188 189 index = 0; 190 for (const auto &elem : regularImportEntries_) { 191 CheckAndAssignIndex(moduleScope, elem.first, &index); 192 } 193 } 194 CheckAndAssignIndex(binder::ModuleScope * moduleScope,util::StringView name,uint32_t * index) const195 binder::Variable *SourceTextModuleRecord::CheckAndAssignIndex(binder::ModuleScope *moduleScope, 196 util::StringView name, 197 uint32_t *index) const 198 { 199 auto modulevar = moduleScope->FindLocal(name); 200 if (modulevar != nullptr) { 201 moduleScope->AssignIndexToModuleVariable(name, *index); 202 (*index)++; 203 } 204 return modulevar; 205 } 206 RemoveDefaultLocalExportEntry()207 void SourceTextModuleRecord::RemoveDefaultLocalExportEntry() 208 { 209 util::StringView localName = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME; 210 localExportEntries_.erase(localName); 211 } 212 GetModuleRequestIdx(const util::StringView localName)213 int SourceTextModuleRecord::GetModuleRequestIdx(const util::StringView localName) 214 { 215 for (const auto &it : regularImportEntries_) { 216 if (it.first != localName) { 217 continue; 218 } 219 220 return it.second->moduleRequestIdx_; 221 } 222 223 for (const auto &it : namespaceImportEntries_) { 224 if (it->localName_ != localName) { 225 continue; 226 } 227 228 return it->moduleRequestIdx_; 229 } 230 231 return SourceTextModuleRecord::INVALID_MODULEREQUEST_ID; 232 } 233 } // namespace panda::es2panda::parser 234