blob: 286a117b3f506791c5ce1c02cd1100e1532dfdbb [file] [log] [blame]
// 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"
namespace v8 {
namespace internal {
void ModuleDescriptor::AddImport(
const AstRawString* import_name, const AstRawString* local_name,
const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
DCHECK_NOT_NULL(import_name);
DCHECK_NOT_NULL(local_name);
DCHECK_NOT_NULL(module_request);
ModuleEntry* entry = new (zone) ModuleEntry(loc);
entry->local_name = local_name;
entry->import_name = import_name;
entry->module_request = module_request;
imports_.Add(entry, zone);
}
void ModuleDescriptor::AddStarImport(
const AstRawString* local_name, const AstRawString* module_request,
Scanner::Location loc, Zone* zone) {
DCHECK_NOT_NULL(local_name);
DCHECK_NOT_NULL(module_request);
ModuleEntry* entry = new (zone) ModuleEntry(loc);
entry->local_name = local_name;
entry->module_request = module_request;
imports_.Add(entry, zone);
}
void ModuleDescriptor::AddEmptyImport(
const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
DCHECK_NOT_NULL(module_request);
ModuleEntry* entry = new (zone) ModuleEntry(loc);
entry->module_request = module_request;
imports_.Add(entry, zone);
}
void ModuleDescriptor::AddExport(
const AstRawString* local_name, const AstRawString* export_name,
Scanner::Location loc, Zone* zone) {
DCHECK_NOT_NULL(local_name);
DCHECK_NOT_NULL(export_name);
ModuleEntry* entry = new (zone) ModuleEntry(loc);
entry->export_name = export_name;
entry->local_name = local_name;
exports_.Add(entry, zone);
}
void ModuleDescriptor::AddExport(
const AstRawString* import_name, const AstRawString* export_name,
const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
DCHECK_NOT_NULL(import_name);
DCHECK_NOT_NULL(export_name);
DCHECK_NOT_NULL(module_request);
ModuleEntry* entry = new (zone) ModuleEntry(loc);
entry->export_name = export_name;
entry->import_name = import_name;
entry->module_request = module_request;
exports_.Add(entry, zone);
}
void ModuleDescriptor::AddStarExport(
const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
DCHECK_NOT_NULL(module_request);
ModuleEntry* entry = new (zone) ModuleEntry(loc);
entry->module_request = module_request;
exports_.Add(entry, zone);
}
bool ModuleDescriptor::Validate(
Scope* module_scope, PendingCompilationErrorHandler* error_handler,
Zone* zone) const {
DCHECK(module_scope->is_module_scope());
DCHECK_EQ(this, module_scope->module());
DCHECK_NOT_NULL(error_handler);
// Report error iff there are duplicate exports.
{
ZoneAllocationPolicy allocator(zone);
ZoneHashMap* export_names = new (zone->New(sizeof(ZoneHashMap)))
ZoneHashMap(ZoneHashMap::PointersMatch,
ZoneHashMap::kDefaultHashMapCapacity, allocator);
for (auto entry : exports_) {
if (entry->export_name == nullptr) continue;
AstRawString* key = const_cast<AstRawString*>(entry->export_name);
ZoneHashMap::Entry* p =
export_names->LookupOrInsert(key, key->hash(), allocator);
DCHECK_NOT_NULL(p);
if (p->value != nullptr) {
error_handler->ReportMessageAt(
entry->location.beg_pos, entry->location.end_pos,
MessageTemplate::kDuplicateExport, entry->export_name);
return false;
}
p->value = key; // Anything but nullptr.
}
}
// Report error iff there are exports of non-existent local names.
for (auto entry : exports_) {
if (entry->local_name == nullptr) continue;
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;
}
}
return true;
}
} // namespace internal
} // namespace v8