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