import { NullValue, Value } from '../value.mts'; import { OutOfRange, isArray } from '../utils/language.mts'; import type { ParseNode } from '../parser/ParseNode.mts'; import { StringValue, type ExportEntry, type ModuleRequestRecord } from './all.mts'; export function ExportEntriesForModule(node: ParseNode | readonly ParseNode[], module: ModuleRequestRecord | NullValue): ExportEntry[] { if (isArray(node)) { const specs: ExportEntry[] = []; node.forEach((n) => { specs.push(...ExportEntriesForModule(n, module)); }); return specs; } switch (node.type) { case 'ExportFromClause': if (node.ModuleExportName) { // 1. Let exportName be the StringValue of ModuleExportName. const exportName = StringValue(node.ModuleExportName); // 2. Let entry be the ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: ~namespace~, [[LocalName]]: null, [[ExportName]]: exportName }. // (proposal-deferred-reexports renamed ~all~ to ~namespace~ for star-as exports.) const entry: ExportEntry = { ModuleRequest: module, ImportName: 'namespace', LocalName: Value.null, ExportName: exportName, }; // 3. Return a new List containing entry. return [entry]; } else { // 1. Let entry be the ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: ~all-but-default~, [[LocalName]]: null, [[ExportName]]: null }. const entry: ExportEntry = { ModuleRequest: module, ImportName: 'all-but-default', LocalName: Value.null, ExportName: Value.null, }; // 2. Return a new List containing entry. return [entry]; } case 'ExportSpecifier': { const sourceName = StringValue(node.localName); const exportName = StringValue(node.exportName); let localName; let importName; if (module === Value.null) { localName = sourceName; importName = Value.null; } else { // 4. Else, localName = Value.null; importName = sourceName; } return [{ ModuleRequest: module, ImportName: importName, LocalName: localName, ExportName: exportName, }]; } case 'NamedExports': return ExportEntriesForModule(node.ExportsList, module); default: throw OutOfRange.nonExhaustive(node); } }