swc-project/swc · error
codegen of `export default from 'foo';`
Error message
codegen of `export default from 'foo';`
What it means
swc's parser accepts the ESNext 'export default from' proposal syntax (`export default from './m';`, `export v from './m';`) and represents it as `ExportSpecifier::Default`. The code generator has no printer for that node — it is expected to be desugared by the `export_default_from` pass (swc_ecma_transforms_proposal) before printing; emitting it directly hits `unimplemented!`.
Source
Thrown at crates/swc_ecma_codegen/src/module_decls.rs:263
space!(emitter);
keyword!(emitter, "as");
space!(emitter);
}
emit!(self.local);
srcmap!(emitter, self, false);
Ok(())
}
}
#[node_impl]
impl MacroNode for ExportSpecifier {
fn emit(&mut self, emitter: &mut Macro) -> Result {
match self {
ExportSpecifier::Default(..) => {
unimplemented!("codegen of `export default from 'foo';`")
}
ExportSpecifier::Namespace(ref node) => emit!(node),
ExportSpecifier::Named(ref node) => emit!(node),
#[cfg(swc_ast_unknown)]
_ => return Err(unknown_error()),
}
Ok(())
}
}
#[node_impl]
impl MacroNode for ExportNamespaceSpecifier {
fn emit(&mut self, emitter: &mut Macro) -> Result {
emitter.emit_leading_comments_of_span(self.span(), false)?;
srcmap!(emitter, self, true);
View on GitHub (pinned to d7d7434666)
Solutions
- Add the `export_default_from` pass to the pass chain before codegen
- Replace the proposal syntax with standard re-export syntax in the source
- Disable export-default-from in the parser syntax config so the input is rejected early instead of panicking at print time
Example fix
// before
export default from './mod';
// after (standard ES2015 re-export)
export { default as default } from './mod'; Defensive patterns
Strategy: validation
Validate before calling
// Rust: before codegen, walk the module for ExportSpecifier::Default
fn uses_export_default_from(m: &Module) -> bool {
m.body.iter().any(|item| matches!(item, ModuleItem::ModuleDecl(ModuleDecl::ExportNamedDecl(d))
if d.specifiers.iter().any(|s| matches!(s, ExportSpecifier::Default(..)))))
} Type guard
fn is_printable_export(s: &ExportSpecifier) -> bool {
!matches!(s, ExportSpecifier::Default(..))
} Try / catch
// Rust: isolate third-party printing of untrusted ASTs
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| emitter.emit_module(&module)));
if result.is_err() { /* report and fall back to skipping re-print */ } Prevention
- Never enable a parser proposal flag without also adding its lowering pass to the chain
- For parse-and-print tools, reject inputs containing `export default from` / `export v from` upfront
When it happens
Trigger: Parse a module with export-default-from syntax enabled, then run the codegen without applying the `export_default_from` transform in between — custom pass pipelines, AST round-trippers, plugins that print raw AST.
Common situations: Hand-built pass lists that enable the parser syntax flag but omit the matching transform; formatters/pretty-printers that parse and print without lowering; pass sets that regress after an swc upgrade.
Related errors
- computed spread property
- Pattern {:?}
- emitting decorator metadata while using new proposal
- ClassMember::{:?}
- {message}; run `cargo codegen helpers` and commit the genera
AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16).
Data as JSON: /api/errors/b0dceeeaa11de852.
Report an issue: GitHub.