• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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