@@ -11,7 +11,6 @@ pub struct ModuleRecordBuilder<'a> {
1111 allocator : & ' a Allocator ,
1212 module_record : ModuleRecord < ' a > ,
1313 export_entries : Vec < ExportEntry < ' a > > ,
14- export_default_duplicated : Vec < Span > ,
1514 exported_bindings_duplicated : Vec < NameSpan < ' a > > ,
1615}
1716
@@ -21,16 +20,16 @@ impl<'a> ModuleRecordBuilder<'a> {
2120 allocator,
2221 module_record : ModuleRecord :: new ( allocator) ,
2322 export_entries : vec ! [ ] ,
24- export_default_duplicated : vec ! [ ] ,
2523 exported_bindings_duplicated : vec ! [ ] ,
2624 }
2725 }
2826
29- pub fn build ( mut self ) -> ModuleRecord < ' a > {
27+ pub fn build ( mut self ) -> ( ModuleRecord < ' a > , Vec < OxcDiagnostic > ) {
3028 // The `ParseModule` algorithm requires `importedBoundNames` (import entries) to be
3129 // resolved before resolving export entries.
3230 self . resolve_export_entries ( ) ;
33- self . module_record
31+ let errors = self . errors ( ) ;
32+ ( self . module_record , errors)
3433 }
3534
3635 pub fn errors ( & self ) -> Vec < OxcDiagnostic > {
@@ -44,19 +43,25 @@ impl<'a> ModuleRecordBuilder<'a> {
4443 errors. push ( diagnostics:: duplicate_export ( & name_span. name , name_span. span , old_span) ) ;
4544 }
4645
47- for span in & self . export_default_duplicated {
48- let old_span = module_record. export_default . unwrap ( ) ;
49- errors. push ( diagnostics:: duplicate_export ( "default" , * span, old_span) ) ;
50- }
51-
52- // `export default x;`
53- // `export { y as default };`
54- if let ( Some ( span) , Some ( default_span) ) =
55- ( module_record. exported_bindings . get ( "default" ) , & module_record. export_default )
56- {
57- errors. push ( diagnostics:: duplicate_export ( "default" , * default_span, * span) ) ;
46+ // Multiple default exports
47+ // `export default foo`
48+ // `export { default }`
49+ let default_exports = module_record
50+ . local_export_entries
51+ . iter ( )
52+ . filter_map ( |export_entry| export_entry. export_name . default_export_span ( ) )
53+ . chain (
54+ module_record
55+ . indirect_export_entries
56+ . iter ( )
57+ . filter_map ( |export_entry| export_entry. export_name . default_export_span ( ) ) ,
58+ )
59+ . collect :: < Vec < _ > > ( ) ;
60+ if default_exports. len ( ) > 1 {
61+ errors. push (
62+ OxcDiagnostic :: error ( "Duplicated default export" ) . with_labels ( default_exports) ,
63+ ) ;
5864 }
59-
6065 errors
6166 }
6267
@@ -94,12 +99,6 @@ impl<'a> ModuleRecordBuilder<'a> {
9499 }
95100 }
96101
97- fn add_default_export ( & mut self , span : Span ) {
98- if let Some ( old_node) = self . module_record . export_default . replace ( span) {
99- self . export_default_duplicated . push ( old_node) ;
100- }
101- }
102-
103102 /// [ParseModule](https://tc39.es/ecma262/#sec-parsemodule)
104103 /// Step 10.
105104 fn resolve_export_entries ( & mut self ) {
@@ -264,8 +263,6 @@ impl<'a> ModuleRecordBuilder<'a> {
264263 return ;
265264 }
266265 let exported_name = & decl. exported ;
267- let exported_name_span = decl. exported . span ( ) ;
268- self . add_default_export ( exported_name_span) ;
269266
270267 let local_name = match & decl. declaration {
271268 ExportDefaultDeclarationKind :: Identifier ( ident) => {
0 commit comments