// 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/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 {
  // 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();
  }
  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()) < 0;
}

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

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

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

void SourceTextModuleDescriptor::AddExport(const AstRawString* local_name,
                                           const AstRawString* export_name,
                                           Scanner::Location loc, Zone* zone) {
  Entry* entry = new (zone) 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 Scanner::Location loc,
    const Scanner::Location specifier_loc, Zone* zone) {
  DCHECK_NOT_NULL(import_name);
  DCHECK_NOT_NULL(export_name);
  Entry* entry = new (zone) Entry(loc);
  entry->export_name = export_name;
  entry->import_name = import_name;
  entry->module_request = AddModuleRequest(module_request, specifier_loc);
  AddSpecialExport(entry, zone);
}

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

namespace {
Handle<Object> ToStringOrUndefined(Isolate* isolate, const AstRawString* s) {
  return (s == nullptr)
             ? Handle<Object>::cast(isolate->factory()->undefined_value())
             : Handle<Object>::cast(s->string());
}
}  // namespace

Handle<SourceTextModuleInfoEntry> SourceTextModuleDescriptor::Entry::Serialize(
    Isolate* 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);
}

Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
    Isolate* 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;
}

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
