13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "sourceTextModuleRecord.h"
173af6ab5fSopenharmony_ci#include <binder/scope.h>
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_cinamespace panda::es2panda::parser {
203af6ab5fSopenharmony_ci    int SourceTextModuleRecord::AddModuleRequest(const ModuleRequestRecord record)
213af6ab5fSopenharmony_ci    {
223af6ab5fSopenharmony_ci        ASSERT(!record.source_.Empty());
233af6ab5fSopenharmony_ci        hasLazyImport_ = hasLazyImport_ || record.isLazy_;
243af6ab5fSopenharmony_ci
253af6ab5fSopenharmony_ci        int moduleRequestsSize = static_cast<int>(moduleRequestsMap_.size());
263af6ab5fSopenharmony_ci        if (moduleRequestsMap_.find(record) == moduleRequestsMap_.end()) {
273af6ab5fSopenharmony_ci            moduleRequests_.emplace_back(record);
283af6ab5fSopenharmony_ci        }
293af6ab5fSopenharmony_ci        auto insertedRes = moduleRequestsMap_.insert(std::make_pair(record, moduleRequestsSize));
303af6ab5fSopenharmony_ci        return insertedRes.first->second;
313af6ab5fSopenharmony_ci    }
323af6ab5fSopenharmony_ci
333af6ab5fSopenharmony_ci    // import x from 'test.js'
343af6ab5fSopenharmony_ci    // import {x} from 'test.js'
353af6ab5fSopenharmony_ci    // import {x as y} from 'test.js'
363af6ab5fSopenharmony_ci    // import defaultExport from 'test.js'
373af6ab5fSopenharmony_ci    void SourceTextModuleRecord::AddImportEntry(SourceTextModuleRecord::ImportEntry *entry)
383af6ab5fSopenharmony_ci    {
393af6ab5fSopenharmony_ci        CHECK_NOT_NULL(entry);
403af6ab5fSopenharmony_ci        ASSERT(entry != nullptr);
413af6ab5fSopenharmony_ci        ASSERT(!entry->importName_.Empty());
423af6ab5fSopenharmony_ci        ASSERT(!entry->localName_.Empty());
433af6ab5fSopenharmony_ci        ASSERT(entry->moduleRequestIdx_ != -1);
443af6ab5fSopenharmony_ci        regularImportEntries_.insert(std::make_pair(entry->localName_, entry));
453af6ab5fSopenharmony_ci        // the implicit indirect exports should be insert into indirectExportsEntries
463af6ab5fSopenharmony_ci        // when add an ImportEntry.
473af6ab5fSopenharmony_ci        // e.g. export { x }; import { x } from 'test.js'
483af6ab5fSopenharmony_ci        CheckImplicitIndirectExport(entry);
493af6ab5fSopenharmony_ci    }
503af6ab5fSopenharmony_ci
513af6ab5fSopenharmony_ci    // import * as x from 'test.js'
523af6ab5fSopenharmony_ci    void SourceTextModuleRecord::AddStarImportEntry(SourceTextModuleRecord::ImportEntry *entry)
533af6ab5fSopenharmony_ci    {
543af6ab5fSopenharmony_ci        ASSERT(!entry->localName_.Empty());
553af6ab5fSopenharmony_ci        ASSERT(entry->importName_.Empty());
563af6ab5fSopenharmony_ci        ASSERT(entry->moduleRequestIdx_ != -1);
573af6ab5fSopenharmony_ci        namespaceImportEntries_.push_back(entry);
583af6ab5fSopenharmony_ci    }
593af6ab5fSopenharmony_ci
603af6ab5fSopenharmony_ci    // export {x}
613af6ab5fSopenharmony_ci    // export {x as y}
623af6ab5fSopenharmony_ci    // export VariableStatement
633af6ab5fSopenharmony_ci    // export Declaration
643af6ab5fSopenharmony_ci    // export default ...
653af6ab5fSopenharmony_ci    bool SourceTextModuleRecord::AddLocalExportEntry(SourceTextModuleRecord::ExportEntry *entry)
663af6ab5fSopenharmony_ci    {
673af6ab5fSopenharmony_ci        CHECK_NOT_NULL(entry);
683af6ab5fSopenharmony_ci        ASSERT(entry->importName_.Empty());
693af6ab5fSopenharmony_ci        ASSERT(!entry->localName_.Empty());
703af6ab5fSopenharmony_ci        ASSERT(!entry->exportName_.Empty());
713af6ab5fSopenharmony_ci        ASSERT(entry->moduleRequestIdx_ == -1);
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_ci        // the implicit indirect exports should be insert into indirectExportsEntries
743af6ab5fSopenharmony_ci        // when add an ExportEntry.
753af6ab5fSopenharmony_ci        // e.g. import { x } from 'test.js'; export { x }
763af6ab5fSopenharmony_ci        if (CheckImplicitIndirectExport(entry)) {
773af6ab5fSopenharmony_ci            return true;
783af6ab5fSopenharmony_ci        }
793af6ab5fSopenharmony_ci        if (!HasDuplicateExport(entry->exportName_)) {
803af6ab5fSopenharmony_ci            localExportEntries_.insert(std::make_pair(entry->localName_, entry));
813af6ab5fSopenharmony_ci            return true;
823af6ab5fSopenharmony_ci        }
833af6ab5fSopenharmony_ci        return false;
843af6ab5fSopenharmony_ci    }
853af6ab5fSopenharmony_ci
863af6ab5fSopenharmony_ci    // export {x} from 'test.js'
873af6ab5fSopenharmony_ci    // export {x as y} from 'test.js'
883af6ab5fSopenharmony_ci    // import { x } from 'test.js'; export { x }
893af6ab5fSopenharmony_ci    bool SourceTextModuleRecord::AddIndirectExportEntry(SourceTextModuleRecord::ExportEntry *entry)
903af6ab5fSopenharmony_ci    {
913af6ab5fSopenharmony_ci        CHECK_NOT_NULL(entry);
923af6ab5fSopenharmony_ci        ASSERT(entry != nullptr);
933af6ab5fSopenharmony_ci        ASSERT(!entry->importName_.Empty());
943af6ab5fSopenharmony_ci        ASSERT(!entry->exportName_.Empty());
953af6ab5fSopenharmony_ci        ASSERT(entry->localName_.Empty());
963af6ab5fSopenharmony_ci        ASSERT(entry->moduleRequestIdx_ != -1);
973af6ab5fSopenharmony_ci        if (!HasDuplicateExport(entry->exportName_)) {
983af6ab5fSopenharmony_ci            indirectExportEntries_.push_back(entry);
993af6ab5fSopenharmony_ci            return true;
1003af6ab5fSopenharmony_ci        }
1013af6ab5fSopenharmony_ci        return false;
1023af6ab5fSopenharmony_ci    }
1033af6ab5fSopenharmony_ci
1043af6ab5fSopenharmony_ci    // export * from 'test.js'
1053af6ab5fSopenharmony_ci    void SourceTextModuleRecord::AddStarExportEntry(SourceTextModuleRecord::ExportEntry *entry)
1063af6ab5fSopenharmony_ci    {
1073af6ab5fSopenharmony_ci        ASSERT(entry->importName_.Empty());
1083af6ab5fSopenharmony_ci        ASSERT(entry->localName_.Empty());
1093af6ab5fSopenharmony_ci        ASSERT(entry->exportName_.Empty());
1103af6ab5fSopenharmony_ci        ASSERT(entry->moduleRequestIdx_ != -1);
1113af6ab5fSopenharmony_ci        starExportEntries_.push_back(entry);
1123af6ab5fSopenharmony_ci    }
1133af6ab5fSopenharmony_ci
1143af6ab5fSopenharmony_ci    bool SourceTextModuleRecord::HasDuplicateExport(util::StringView exportName) const
1153af6ab5fSopenharmony_ci    {
1163af6ab5fSopenharmony_ci        for (auto const &entryUnit : localExportEntries_) {
1173af6ab5fSopenharmony_ci            const SourceTextModuleRecord::ExportEntry *e = entryUnit.second;
1183af6ab5fSopenharmony_ci            if (exportName == e->exportName_) {
1193af6ab5fSopenharmony_ci                return true;
1203af6ab5fSopenharmony_ci            }
1213af6ab5fSopenharmony_ci        }
1223af6ab5fSopenharmony_ci
1233af6ab5fSopenharmony_ci        for (const auto *e : indirectExportEntries_) {
1243af6ab5fSopenharmony_ci            if (exportName == e->exportName_) {
1253af6ab5fSopenharmony_ci                return true;
1263af6ab5fSopenharmony_ci            }
1273af6ab5fSopenharmony_ci        }
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_ci        return false;
1303af6ab5fSopenharmony_ci    }
1313af6ab5fSopenharmony_ci
1323af6ab5fSopenharmony_ci    bool SourceTextModuleRecord::CheckImplicitIndirectExport(SourceTextModuleRecord::ExportEntry *exportEntry)
1333af6ab5fSopenharmony_ci    {
1343af6ab5fSopenharmony_ci        CHECK_NOT_NULL(exportEntry);
1353af6ab5fSopenharmony_ci        ASSERT(exportEntry != nullptr);
1363af6ab5fSopenharmony_ci        ASSERT(!exportEntry->localName_.Empty());
1373af6ab5fSopenharmony_ci        auto regularImport = regularImportEntries_.find(exportEntry->localName_);
1383af6ab5fSopenharmony_ci        if (regularImport != regularImportEntries_.end()) {
1393af6ab5fSopenharmony_ci            ConvertLocalExportToIndirect(regularImport->second, exportEntry);
1403af6ab5fSopenharmony_ci            return AddIndirectExportEntry(exportEntry);
1413af6ab5fSopenharmony_ci        }
1423af6ab5fSopenharmony_ci        return false;
1433af6ab5fSopenharmony_ci    }
1443af6ab5fSopenharmony_ci
1453af6ab5fSopenharmony_ci    void SourceTextModuleRecord::CheckImplicitIndirectExport(SourceTextModuleRecord::ImportEntry *importEntry)
1463af6ab5fSopenharmony_ci    {
1473af6ab5fSopenharmony_ci        ASSERT(!importEntry->localName_.Empty());
1483af6ab5fSopenharmony_ci        auto range = localExportEntries_.equal_range(importEntry->localName_);
1493af6ab5fSopenharmony_ci        // not found implicit indirect
1503af6ab5fSopenharmony_ci        if (range.first == range.second) {
1513af6ab5fSopenharmony_ci            return;
1523af6ab5fSopenharmony_ci        }
1533af6ab5fSopenharmony_ci
1543af6ab5fSopenharmony_ci        for (auto it = range.first; it != range.second; ++it) {
1553af6ab5fSopenharmony_ci            SourceTextModuleRecord::ExportEntry *exportEntry = it->second;
1563af6ab5fSopenharmony_ci            ConvertLocalExportToIndirect(importEntry, exportEntry);
1573af6ab5fSopenharmony_ci            indirectExportEntries_.push_back(exportEntry);
1583af6ab5fSopenharmony_ci        }
1593af6ab5fSopenharmony_ci        localExportEntries_.erase(range.first, range.second);
1603af6ab5fSopenharmony_ci    }
1613af6ab5fSopenharmony_ci
1623af6ab5fSopenharmony_ci    void SourceTextModuleRecord::ConvertLocalExportToIndirect(SourceTextModuleRecord::ImportEntry *importEntry,
1633af6ab5fSopenharmony_ci                                                              SourceTextModuleRecord::ExportEntry *exportEntry)
1643af6ab5fSopenharmony_ci    {
1653af6ab5fSopenharmony_ci        CHECK_NOT_NULL(importEntry);
1663af6ab5fSopenharmony_ci        ASSERT(exportEntry->importName_.Empty());
1673af6ab5fSopenharmony_ci        ASSERT(exportEntry->moduleRequestIdx_ == -1);
1683af6ab5fSopenharmony_ci        ASSERT(!importEntry->importName_.Empty());
1693af6ab5fSopenharmony_ci        ASSERT(importEntry->moduleRequestIdx_ != -1);
1703af6ab5fSopenharmony_ci        exportEntry->importName_ = importEntry->importName_;
1713af6ab5fSopenharmony_ci        exportEntry->moduleRequestIdx_ = importEntry->moduleRequestIdx_;
1723af6ab5fSopenharmony_ci        exportEntry->localName_ = util::StringView("");
1733af6ab5fSopenharmony_ci    }
1743af6ab5fSopenharmony_ci
1753af6ab5fSopenharmony_ci    void SourceTextModuleRecord::AssignIndexToModuleVariable(binder::ModuleScope *moduleScope)
1763af6ab5fSopenharmony_ci    {
1773af6ab5fSopenharmony_ci        uint32_t index = 0;
1783af6ab5fSopenharmony_ci        for (auto it = localExportEntries_.begin(); it != localExportEntries_.end();
1793af6ab5fSopenharmony_ci             it = localExportEntries_.upper_bound(it->first)) {
1803af6ab5fSopenharmony_ci            auto variable = CheckAndAssignIndex(moduleScope, it->first, &index);
1813af6ab5fSopenharmony_ci            if (variable != nullptr && variable->IsModuleVariable() && variable->Declaration()->IsConstDecl()) {
1823af6ab5fSopenharmony_ci                auto range = localExportEntries_.equal_range(it->first);
1833af6ab5fSopenharmony_ci                for (auto local_iter = range.first; local_iter != range.second; local_iter++) {
1843af6ab5fSopenharmony_ci                    local_iter->second->SetAsConstant();
1853af6ab5fSopenharmony_ci                }
1863af6ab5fSopenharmony_ci            }
1873af6ab5fSopenharmony_ci        }
1883af6ab5fSopenharmony_ci
1893af6ab5fSopenharmony_ci        index = 0;
1903af6ab5fSopenharmony_ci        for (const auto &elem : regularImportEntries_) {
1913af6ab5fSopenharmony_ci            CheckAndAssignIndex(moduleScope, elem.first, &index);
1923af6ab5fSopenharmony_ci        }
1933af6ab5fSopenharmony_ci    }
1943af6ab5fSopenharmony_ci
1953af6ab5fSopenharmony_ci    binder::Variable *SourceTextModuleRecord::CheckAndAssignIndex(binder::ModuleScope *moduleScope,
1963af6ab5fSopenharmony_ci                                                                  util::StringView name,
1973af6ab5fSopenharmony_ci                                                                  uint32_t *index) const
1983af6ab5fSopenharmony_ci    {
1993af6ab5fSopenharmony_ci        auto modulevar = moduleScope->FindLocal(name);
2003af6ab5fSopenharmony_ci        if (modulevar != nullptr) {
2013af6ab5fSopenharmony_ci            moduleScope->AssignIndexToModuleVariable(name, *index);
2023af6ab5fSopenharmony_ci            (*index)++;
2033af6ab5fSopenharmony_ci        }
2043af6ab5fSopenharmony_ci        return modulevar;
2053af6ab5fSopenharmony_ci    }
2063af6ab5fSopenharmony_ci
2073af6ab5fSopenharmony_ci    void SourceTextModuleRecord::RemoveDefaultLocalExportEntry()
2083af6ab5fSopenharmony_ci    {
2093af6ab5fSopenharmony_ci        util::StringView localName = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME;
2103af6ab5fSopenharmony_ci        localExportEntries_.erase(localName);
2113af6ab5fSopenharmony_ci    }
2123af6ab5fSopenharmony_ci
2133af6ab5fSopenharmony_ci    int SourceTextModuleRecord::GetModuleRequestIdx(const util::StringView localName)
2143af6ab5fSopenharmony_ci    {
2153af6ab5fSopenharmony_ci        for (const auto &it : regularImportEntries_) {
2163af6ab5fSopenharmony_ci            if (it.first != localName) {
2173af6ab5fSopenharmony_ci                continue;
2183af6ab5fSopenharmony_ci            }
2193af6ab5fSopenharmony_ci
2203af6ab5fSopenharmony_ci            return it.second->moduleRequestIdx_;
2213af6ab5fSopenharmony_ci        }
2223af6ab5fSopenharmony_ci
2233af6ab5fSopenharmony_ci        for (const auto &it : namespaceImportEntries_) {
2243af6ab5fSopenharmony_ci            if (it->localName_ != localName) {
2253af6ab5fSopenharmony_ci                continue;
2263af6ab5fSopenharmony_ci            }
2273af6ab5fSopenharmony_ci
2283af6ab5fSopenharmony_ci            return it->moduleRequestIdx_;
2293af6ab5fSopenharmony_ci        }
2303af6ab5fSopenharmony_ci
2313af6ab5fSopenharmony_ci        return SourceTextModuleRecord::INVALID_MODULEREQUEST_ID;
2323af6ab5fSopenharmony_ci    }
2333af6ab5fSopenharmony_ci} // namespace panda::es2panda::parser
234