@@ -22,6 +22,72 @@ export const decorateComponentExportsWithProps = (
2222 return uid ;
2323 }
2424
25+ /**
26+ * Rewrite any re-exports for named components (`default Component`, `HydrateFallback`, `ErrorBoundary`)
27+ * into `export const <name> = <expr>` form in preparation for adding props HOCs in the next traversal.
28+ *
29+ * Case 1: `export { name, ... }` or `export { value as name, ... }`
30+ * -> Rename `name` to `uid` where `uid` is a new unique identifier
31+ * -> Insert `export const name = uid`
32+ *
33+ * Case 2: `export { name1, value as name 2, ... } from "source"`
34+ * -> Insert `import { name as uid }` where `uid` is a new unique identifier
35+ * -> Insert `export const name = uid`
36+ */
37+ traverse ( ast , {
38+ ExportNamedDeclaration ( path ) {
39+ if ( path . node . declaration ) return ;
40+ const { source } = path . node ;
41+
42+ const exports : Array < {
43+ uid : Babel . Identifier ;
44+ local : Babel . Identifier ;
45+ exported : Babel . Identifier ;
46+ } > = [ ] ;
47+ for ( const specifier of path . get ( "specifiers" ) ) {
48+ if ( specifier . isExportSpecifier ( ) ) {
49+ const { local, exported } = specifier . node ;
50+ const { name } = local ;
51+ if ( ! t . isIdentifier ( exported ) ) continue ;
52+ const uid = path . scope . generateUidIdentifier ( `_${ name } ` ) ;
53+ if ( exported . name === "default" || isNamedComponentExport ( name ) ) {
54+ exports . push ( { uid, local, exported } ) ;
55+ specifier . remove ( ) ;
56+ }
57+ }
58+ }
59+ if ( exports . length === 0 ) return ;
60+
61+ if ( source != null ) {
62+ // `import { local as uid } from "source"`
63+ path . insertAfter ( [
64+ t . importDeclaration (
65+ exports . map ( ( { local, uid } ) => t . importSpecifier ( uid , local ) ) ,
66+ source ,
67+ ) ,
68+ ] ) ;
69+ } else {
70+ for ( const { local, uid } of exports ) {
71+ path . scope . getBinding ( local . name ) ?. scope . rename ( uid . name ) ;
72+ }
73+ }
74+
75+ // `export const exported = uid`
76+ path . insertAfter (
77+ exports . map ( ( { uid, exported } ) => {
78+ if ( exported . name === "default" ) {
79+ return t . exportDefaultDeclaration ( uid ) ;
80+ }
81+ return t . exportNamedDeclaration (
82+ t . variableDeclaration ( "const" , [
83+ t . variableDeclarator ( exported , uid ) ,
84+ ] ) ,
85+ ) ;
86+ } ) ,
87+ ) ;
88+ } ,
89+ } ) ;
90+
2591 traverse ( ast , {
2692 ExportDeclaration ( path ) {
2793 if ( path . isExportDefaultDeclaration ( ) ) {
0 commit comments