// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/ast/modules.h"

#include "src/ast/ast-value-factory.h"
#include "src/ast/scopes.h"
#include "src/heap/local-factory-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/objects-inl.h"
#include "src/parsing/pending-compilation-error-handler.h"

namespace v8 {
namespace internal {

bool SourceTextModuleDescriptor::AstRawStringComparer::operator()(
    const AstRawString* lhs, const AstRawString* rhs) const {
  return ThreeWayCompare(lhs, rhs) < 0;
}

int SourceTextModuleDescriptor::AstRawStringComparer::ThreeWayCompare(
    const AstRawString* lhs, const AstRawString* rhs) {
  // Fast path for equal pointers: a pointer is not strictly less than itself.
  if (lhs == rhs) return false;

  // Order by contents (ordering by hash is unstable across runs).
  if (lhs->is_one_byte() != rhs->is_one_byte()) {
    return lhs->is_one_byte() ? -1 : 1;
  }
  if (lhs->byte_length() != rhs->byte_length()) {
    return lhs->byte_length() - rhs->byte_length();
  }
  return memcmp(lhs->raw_data(), rhs->raw_data(), lhs->byte_length());
}

bool SourceTextModuleDescriptor::ModuleRequestComparer::operator()(
    const AstModuleRequest* lhs, const AstModuleRequest* rhs) const {
  if (int specifier_comparison = AstRawStringComparer::ThreeWayCompare(
          lhs->specifier(), rhs->specifier()))
    return specifier_comparison < 0;

  if (lhs->import_assertions()->size() != rhs->import_assertions()->size())
    return (lhs->import_assertions()->size() <
            rhs->import_assertions()->size());

  auto lhsIt = lhs->import_assertions()->cbegin();
  auto rhsIt = rhs->import_assertions()->cbegin();
  for (; lhsIt != lhs->import_assertions()->cend(); ++lhsIt, ++rhsIt) {
    if (int assertion_key_comparison =
            AstRawStringComparer::ThreeWayCompare(lhsIt->first, rhsIt->first))
      return assertion_key_comparison < 0;

    if (int assertion_value_comparison = AstRawStringComparer::ThreeWayCompare(
            lhsIt->second.first, rhsIt->second.first))
      return assertion_value_comparison < 0;
  }

  return false;
}

void SourceTextModuleDescriptor::AddImport(
    const AstRawString* import_name, const AstRawString* local_name,
    const AstRawString* module_request,
    const ImportAssertions* import_assertions, const Scanner::Location loc,
    const Scanner::Location specifier_loc, Zone* zone) {
  Entry* entry = zone->New<Entry>(loc);
  entry->local_name = local_name;
  entry->import_name = import_name;
  entry->module_request =
      AddModuleRequest(module_request, import_assertions, specifier_loc, zone);
  AddRegularImport(entry);
}

void SourceTextModuleDescriptor::AddStarImport(
    const AstRawString* local_name, const AstRawString* module_request,
    const ImportAssertions* import_assertions, const Scanner::Location loc,
    const Scanner::Location specifier_loc, Zone* zone) {
  Entry* entry = zone->New<Entry>(loc);
  entry->local_name = local_name;
  entry->module_request =
      AddModuleRequest(module_request, import_assertions, specifier_loc, zone);
  AddNamespaceImport(entry, zone);
}

void SourceTextModuleDescriptor::AddEmptyImport(
    const AstRawString* module_request,
    const ImportAssertions* import_assertions,
    const Scanner::Location specifier_loc, Zone* zone) {
  AddModuleRequest(module_request, import_assertions, specifier_loc, zone);
}

void SourceTextModuleDescriptor::AddExport(const AstRawString* local_name,
                                           const AstRawString* export_name,
                                           Scanner::Location loc, Zone* zone) {
  Entry* entry = zone->New<Entry>(loc);
  entry->export_name = export_name;
  entry->local_name = local_name;
  AddRegularExport(entry);
}

void SourceTextModuleDescriptor::AddExport(
    const AstRawString* import_name, const AstRawString* export_name,
    const AstRawString* module_request,
    const ImportAssertions* import_assertions, const Scanner::Location loc,
    const Scanner::Location specifier_loc, Zone* zone) {
  DCHECK_NOT_NULL(import_name);
  DCHECK_NOT_NULL(export_name);
  Entry* entry = zone->New<Entry>(loc);
  entry->export_name = export_name;
  entry->import_name = import_name;
  entry->module_request =
      AddModuleRequest(module_request, import_assertions, specifier_loc, zone);
  AddSpecialExport(entry, zone);
}

void SourceTextModuleDescriptor::AddStarExport(
    const AstRawString* module_request,
    const ImportAssertions* import_assertions, const Scanner::Location loc,
    const Scanner::Location specifier_loc, Zone* zone) {
  Entry* entry = zone->New<Entry>(loc);
  entry->module_request =
      AddModuleRequest(module_request, import_assertions, specifier_loc, zone);
  AddSpecialExport(entry, zone);
}

namespace {
template <typename LocalIsolate>
Handle<PrimitiveHeapObject> ToStringOrUndefined(LocalIsolate* isolate,
                                                const AstRawString* s) {
  if (s == nullptr) return isolate->factory()->undefined_value();
  return s->string();
}
}  // namespace

template <typename LocalIsolate>
Handle<ModuleRequest> SourceTextModuleDescriptor::AstModuleRequest::Serialize(
    LocalIsolate* isolate) const {
  // The import assertions will be stored in this array in the form:
  // [key1, value1, location1, key2, value2, location2, ...]
  Handle<FixedArray> import_assertions_array =
      isolate->factory()->NewFixedArray(
          static_cast<int>(import_assertions()->size() * 3));

  int i = 0;
  for (auto iter = import_assertions()->cbegin();
       iter != import_assertions()->cend(); ++iter, i += 3) {
    import_assertions_array->set(i, *iter->first->string());
    import_assertions_array->set(i + 1, *iter->second.first->string());
    import_assertions_array->set(i + 2,
                                 Smi::FromInt(iter->second.second.beg_pos));
  }
  return v8::internal::ModuleRequest::New(isolate, specifier()->string(),
                                          import_assertions_array);
}
template Handle<ModuleRequest>
SourceTextModuleDescriptor::AstModuleRequest::Serialize(Isolate* isolate) const;
template Handle<ModuleRequest>
SourceTextModuleDescriptor::AstModuleRequest::Serialize(
    LocalIsolate* isolate) const;

template <typename LocalIsolate>
Handle<SourceTextModuleInfoEntry> SourceTextModuleDescriptor::Entry::Serialize(
    LocalIsolate* isolate) const {
  CHECK(Smi::IsValid(module_request));  // TODO(neis): Check earlier?
  return SourceTextModuleInfoEntry::New(
      isolate, ToStringOrUndefined(isolate, export_name),
      ToStringOrUndefined(isolate, local_name),
      ToStringOrUndefined(isolate, import_name), module_request, cell_index,
      location.beg_pos, location.end_pos);
}
template Handle<SourceTextModuleInfoEntry>
SourceTextModuleDescriptor::Entry::Serialize(Isolate* isolate) const;
template Handle<SourceTextModuleInfoEntry>
SourceTextModuleDescriptor::Entry::Serialize(LocalIsolate* isolate) const;

template <typename LocalIsolate>
Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
    LocalIsolate* isolate, Zone* zone) const {
  // We serialize regular exports in a way that lets us later iterate over their
  // local names and for each local name immediately access all its export
  // names.  (Regular exports have neither import name nor module request.)

  ZoneVector<Handle<Object>> data(
      SourceTextModuleInfo::kRegularExportLength * regular_exports_.size(),
      zone);
  int index = 0;

  for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
    // Find out how many export names this local name has.
    auto next = it;
    int count = 0;
    do {
      DCHECK_EQ(it->second->local_name, next->second->local_name);
      DCHECK_EQ(it->second->cell_index, next->second->cell_index);
      ++next;
      ++count;
    } while (next != regular_exports_.end() && next->first == it->first);

    Handle<FixedArray> export_names = isolate->factory()->NewFixedArray(count);
    data[index + SourceTextModuleInfo::kRegularExportLocalNameOffset] =
        it->second->local_name->string();
    data[index + SourceTextModuleInfo::kRegularExportCellIndexOffset] =
        handle(Smi::FromInt(it->second->cell_index), isolate);
    data[index + SourceTextModuleInfo::kRegularExportExportNamesOffset] =
        export_names;
    index += SourceTextModuleInfo::kRegularExportLength;

    // Collect the export names.
    int i = 0;
    for (; it != next; ++it) {
      export_names->set(i++, *it->second->export_name->string());
    }
    DCHECK_EQ(i, count);

    // Continue with the next distinct key.
    DCHECK(it == next);
  }
  DCHECK_LE(index, static_cast<int>(data.size()));
  data.resize(index);

  // We cannot create the FixedArray earlier because we only now know the
  // precise size.
  Handle<FixedArray> result = isolate->factory()->NewFixedArray(index);
  for (int i = 0; i < index; ++i) {
    result->set(i, *data[i]);
  }
  return result;
}
template Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
    Isolate* isolate, Zone* zone) const;
template Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
    LocalIsolate* isolate, Zone* zone) const;

void SourceTextModuleDescriptor::MakeIndirectExportsExplicit(Zone* zone) {
  for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
    Entry* entry = it->second;
    DCHECK_NOT_NULL(entry->local_name);
    auto import = regular_imports_.find(entry->local_name);
    if (import != regular_imports_.end()) {
      // Found an indirect export.  Patch export entry and move it from regular
      // to special.
      DCHECK_NULL(entry->import_name);
      DCHECK_LT(entry->module_request, 0);
      DCHECK_NOT_NULL(import->second->import_name);
      DCHECK_LE(0, import->second->module_request);
      DCHECK_LT(import->second->module_request,
                static_cast<int>(module_requests_.size()));
      entry->import_name = import->second->import_name;
      entry->module_request = import->second->module_request;
      // Hack: When the indirect export cannot be resolved, we want the error
      // message to point at the import statement, not at the export statement.
      // Therefore we overwrite [entry]'s location here.  Note that Validate()
      // has already checked for duplicate exports, so it's guaranteed that we
      // won't need to report any error pointing at the (now lost) export
      // location.
      entry->location = import->second->location;
      entry->local_name = nullptr;
      AddSpecialExport(entry, zone);
      it = regular_exports_.erase(it);
    } else {
      it++;
    }
  }
}

SourceTextModuleDescriptor::CellIndexKind
SourceTextModuleDescriptor::GetCellIndexKind(int cell_index) {
  if (cell_index > 0) return kExport;
  if (cell_index < 0) return kImport;
  return kInvalid;
}

void SourceTextModuleDescriptor::AssignCellIndices() {
  int export_index = 1;
  for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
    auto current_key = it->first;
    // This local name may be exported under multiple export names.  Assign the
    // same index to each such entry.
    do {
      Entry* entry = it->second;
      DCHECK_NOT_NULL(entry->local_name);
      DCHECK_NULL(entry->import_name);
      DCHECK_LT(entry->module_request, 0);
      DCHECK_EQ(entry->cell_index, 0);
      entry->cell_index = export_index;
      it++;
    } while (it != regular_exports_.end() && it->first == current_key);
    export_index++;
  }

  int import_index = -1;
  for (const auto& elem : regular_imports_) {
    Entry* entry = elem.second;
    DCHECK_NOT_NULL(entry->local_name);
    DCHECK_NOT_NULL(entry->import_name);
    DCHECK_LE(0, entry->module_request);
    DCHECK_EQ(entry->cell_index, 0);
    entry->cell_index = import_index;
    import_index--;
  }
}

namespace {

const SourceTextModuleDescriptor::Entry* BetterDuplicate(
    const SourceTextModuleDescriptor::Entry* candidate,
    ZoneMap<const AstRawString*, const SourceTextModuleDescriptor::Entry*>&
        export_names,
    const SourceTextModuleDescriptor::Entry* current_duplicate) {
  DCHECK_NOT_NULL(candidate->export_name);
  DCHECK(candidate->location.IsValid());
  auto insert_result =
      export_names.insert(std::make_pair(candidate->export_name, candidate));
  if (insert_result.second) return current_duplicate;
  if (current_duplicate == nullptr) {
    current_duplicate = insert_result.first->second;
  }
  return (candidate->location.beg_pos > current_duplicate->location.beg_pos)
             ? candidate
             : current_duplicate;
}

}  // namespace

const SourceTextModuleDescriptor::Entry*
SourceTextModuleDescriptor::FindDuplicateExport(Zone* zone) const {
  const SourceTextModuleDescriptor::Entry* duplicate = nullptr;
  ZoneMap<const AstRawString*, const SourceTextModuleDescriptor::Entry*>
      export_names(zone);
  for (const auto& elem : regular_exports_) {
    duplicate = BetterDuplicate(elem.second, export_names, duplicate);
  }
  for (auto entry : special_exports_) {
    if (entry->export_name == nullptr) continue;  // Star export.
    duplicate = BetterDuplicate(entry, export_names, duplicate);
  }
  return duplicate;
}

bool SourceTextModuleDescriptor::Validate(
    ModuleScope* module_scope, PendingCompilationErrorHandler* error_handler,
    Zone* zone) {
  DCHECK_EQ(this, module_scope->module());
  DCHECK_NOT_NULL(error_handler);

  // Report error iff there are duplicate exports.
  {
    const Entry* entry = FindDuplicateExport(zone);
    if (entry != nullptr) {
      error_handler->ReportMessageAt(
          entry->location.beg_pos, entry->location.end_pos,
          MessageTemplate::kDuplicateExport, entry->export_name);
      return false;
    }
  }

  // Report error iff there are exports of non-existent local names.
  for (const auto& elem : regular_exports_) {
    const Entry* entry = elem.second;
    DCHECK_NOT_NULL(entry->local_name);
    if (module_scope->LookupLocal(entry->local_name) == nullptr) {
      error_handler->ReportMessageAt(
          entry->location.beg_pos, entry->location.end_pos,
          MessageTemplate::kModuleExportUndefined, entry->local_name);
      return false;
    }
  }

  MakeIndirectExportsExplicit(zone);
  AssignCellIndices();
  return true;
}

}  // namespace internal
}  // namespace v8
