@@ -17,11 +17,16 @@ use utils::*;
1717mod utils;
1818
1919static SSG_EXPORTS : & [ & str ; 2 ] = & [ "getStaticProps" , "getServerSideProps" ] ;
20+ static INITIAL_PROPS : & str = "getInitialProps" ;
2021
2122// import { withSuperJSONProps as _withSuperJSONProps } from "next-superjson-plugin/tools";
2223static SUPERJSON_PROPS_IMPORTED : & str = "withSuperJSONProps" ;
2324static SUPERJSON_PROPS_LOCAL : & str = "_withSuperJSONProps" ;
2425
26+ // import { withSuperJSONInitProps as _withSuperJSONInitProps } from "next-superjson-plugin/tools";
27+ static SUPERJSON_INIT_PROPS_IMPORTED : & str = "withSuperJSONInitProps" ;
28+ static SUPERJSON_INIT_PROPS_LOCAL : & str = "_withSuperJSONInitProps" ;
29+
2530// import { withSuperJSONPage as _withSuperJSONPage } from "next-superjson-plugin/tools";
2631static SUPERJSON_PAGE_IMPORTED : & str = "withSuperJSONPage" ;
2732static SUPERJSON_PAGE_LOCAL : & str = "_withSuperJSONPage" ;
@@ -55,6 +60,9 @@ struct NextSuperJsonTransformer {
5560
5661 props : TransformTarget ,
5762 page : TransformTarget ,
63+
64+ has_init_props : bool ,
65+ use_init_props : bool ,
5866}
5967
6068#[ derive( Debug , Default , Clone , Deserialize ) ]
@@ -74,27 +82,36 @@ pub fn transform(config: Config) -> impl VisitMut {
7482
7583 props : Default :: default ( ) ,
7684 page : Default :: default ( ) ,
85+
86+ has_init_props : false ,
87+ use_init_props : false ,
7788 }
7889}
7990
8091impl Fold for NextSuperJsonTransformer { }
8192
8293impl VisitMut for NextSuperJsonTransformer {
8394 fn visit_mut_module_items ( & mut self , items : & mut Vec < ModuleItem > ) {
84- self . find_ssg_prop ( items) ;
95+ self . find_page ( items) ;
8596
86- if self . props . export . orig . is_none ( ) {
97+ if self . page . export . orig . is_none ( ) {
8798 return ;
8899 }
89100
90- self . find_page ( items) ;
101+ self . find_ssg_prop ( items) ;
91102
92- if self . page . export . orig . is_none ( ) {
93- return ;
103+ if self . props . export . orig . is_none ( ) {
104+ if !self . use_init_props {
105+ return ;
106+ }
107+
108+ self . props . skip = true ;
94109 }
95110
96111 let mut new_items = vec ! [ ] ;
97112
113+ let mut temp_page = None ;
114+
98115 for ( pos, item) in items. iter_mut ( ) . enumerate ( ) {
99116 if self . props . ident . orig . is_some ( )
100117 && pos == self . props . ident . orig . unwrap ( )
@@ -194,7 +211,7 @@ impl VisitMut for NextSuperJsonTransformer {
194211 _ => { }
195212 }
196213 } else {
197- if pos == self . props . export . orig . unwrap ( ) && ! self . props . skip {
214+ if ! self . props . skip && pos == self . props . export . orig . unwrap ( ) {
198215 match item {
199216 ModuleItem :: ModuleDecl ( ModuleDecl :: ExportDecl ( ExportDecl {
200217 decl : export_decl,
@@ -303,16 +320,20 @@ impl VisitMut for NextSuperJsonTransformer {
303320 }
304321 }
305322
323+ let mut keep_page = false ;
324+
306325 if pos == self . page . export . orig . unwrap ( ) && !self . page . skip {
307326 match item {
308327 ModuleItem :: ModuleDecl ( ModuleDecl :: ExportDefaultExpr (
309328 ExportDefaultExpr { expr, .. } ,
310329 ) ) => {
330+ keep_page = self . use_init_props ;
311331 * expr = expr. take ( ) . wrap_page ( ) ;
312332 }
313333 ModuleItem :: ModuleDecl ( ModuleDecl :: ExportDefaultDecl (
314334 ExportDefaultDecl { decl, .. } ,
315335 ) ) => {
336+ keep_page = self . use_init_props ;
316337 // TODO: remove duplicate code
317338 match decl {
318339 DefaultDecl :: Class ( class_expr) => {
@@ -390,7 +411,7 @@ impl VisitMut for NextSuperJsonTransformer {
390411 src,
391412 ) ) ;
392413
393- new_items . push ( ModuleItem :: ModuleDecl (
414+ let new_page = ModuleItem :: ModuleDecl (
394415 ModuleDecl :: ExportDefaultExpr ( ExportDefaultExpr {
395416 expr : Box :: new ( Expr :: Ident ( Ident :: new (
396417 NEXT_PAGE_LOCAL . into ( ) ,
@@ -399,19 +420,29 @@ impl VisitMut for NextSuperJsonTransformer {
399420 . wrap_page ( ) ,
400421 span : DUMMY_SP ,
401422 } ) ,
402- ) ) ;
423+ ) ;
424+ if !self . use_init_props {
425+ new_items. push ( new_page) ;
426+ } else {
427+ temp_page = Some ( new_page) ;
428+ }
403429
404430 // export { Page as default }
405431 // =>
406432 // export default wrap(Page, excluded)
407433 } else {
408434 if let ModuleExportName :: Ident ( id) = & s. orig {
409- new_items . push ( ModuleItem :: ModuleDecl (
435+ let new_page = ModuleItem :: ModuleDecl (
410436 ModuleDecl :: ExportDefaultExpr ( ExportDefaultExpr {
411437 expr : Box :: new ( Expr :: Ident ( id. clone ( ) ) ) . wrap_page ( ) ,
412438 span : DUMMY_SP ,
413439 } ) ,
414- ) )
440+ ) ;
441+ if !self . use_init_props {
442+ new_items. push ( new_page) ;
443+ } else {
444+ temp_page = Some ( new_page) ;
445+ }
415446 }
416447 }
417448
@@ -427,23 +458,41 @@ impl VisitMut for NextSuperJsonTransformer {
427458 ..
428459 } ) ) => {
429460 if !specifiers. is_empty ( ) {
430- new_items. push ( item. take ( ) ) ;
461+ if !keep_page {
462+ new_items. push ( item. take ( ) ) ;
463+ } else {
464+ temp_page = Some ( item. take ( ) ) ;
465+ }
431466 }
432467 }
433468 _ => {
434- new_items. push ( item. take ( ) ) ;
469+ if !keep_page {
470+ new_items. push ( item. take ( ) ) ;
471+ } else {
472+ temp_page = Some ( item. take ( ) ) ;
473+ }
435474 }
436475 }
437476 }
438477 }
439478
479+ if let Some ( tmp) = temp_page {
480+ new_items. push ( tmp) ;
481+ }
482+
440483 // TODO: these two stmts can be combined
441484 if !self . props . skip {
442485 prepend_stmt (
443486 & mut new_items,
444487 superjson_import_decl ( SUPERJSON_PROPS_IMPORTED ) ,
445488 ) ;
446489 }
490+ if self . use_init_props {
491+ prepend_stmt (
492+ & mut new_items,
493+ superjson_import_decl ( SUPERJSON_INIT_PROPS_IMPORTED ) ,
494+ ) ;
495+ }
447496 if !self . page . skip {
448497 prepend_stmt (
449498 & mut new_items,
@@ -453,6 +502,81 @@ impl VisitMut for NextSuperJsonTransformer {
453502
454503 * items = new_items;
455504 }
505+
506+ fn visit_mut_class_member ( & mut self , member : & mut ClassMember ) {
507+ member. visit_mut_children_with ( self ) ;
508+ match member {
509+ ClassMember :: ClassProp ( p) => {
510+ if let PropName :: Ident ( id) = & p. key {
511+ if & * id. sym == INITIAL_PROPS {
512+ if let Some ( expr) = & mut p. value {
513+ self . use_init_props = true ;
514+ p. value = Some ( expr. take ( ) . wrap_init_props ( self . excluded_expr ( ) ) ) ;
515+ }
516+ }
517+ }
518+ }
519+ ClassMember :: Method ( m) => {
520+ if let PropName :: Ident ( id) = & m. key {
521+ if & * id. sym == INITIAL_PROPS {
522+ self . use_init_props = true ;
523+ * member = ClassMember :: ClassProp ( ClassProp {
524+ accessibility : m. accessibility . take ( ) ,
525+ declare : false ,
526+ decorators : vec ! [ ] ,
527+ definite : false ,
528+ is_abstract : m. is_abstract ,
529+ is_optional : m. is_optional ,
530+ is_override : m. is_override ,
531+ is_static : m. is_static ,
532+ key : m. key . take ( ) ,
533+ readonly : false ,
534+ span : DUMMY_SP ,
535+ type_ann : None ,
536+ value : Some (
537+ Box :: new ( Expr :: Fn ( FnExpr {
538+ function : m. function . take ( ) ,
539+ ident : None ,
540+ } ) )
541+ . wrap_init_props ( self . excluded_expr ( ) ) ,
542+ ) ,
543+ } ) ;
544+ }
545+ }
546+ }
547+ _ => { }
548+ }
549+ }
550+
551+ fn visit_mut_assign_expr ( & mut self , a : & mut AssignExpr ) {
552+ a. visit_mut_children_with ( self ) ;
553+
554+ if a. left . is_expr ( ) {
555+ if let Some ( mut expr) = a. left . take ( ) . expr ( ) {
556+ if let Some ( MemberExpr { prop, .. } ) = expr. as_mut_member ( ) {
557+ prop. visit_mut_children_with ( self ) ;
558+ }
559+
560+ if self . has_init_props {
561+ a. right = a. right . take ( ) . wrap_init_props ( self . excluded_expr ( ) ) ;
562+ self . use_init_props = true ;
563+ self . has_init_props = false ;
564+ }
565+
566+ a. left = PatOrExpr :: Expr ( expr) ;
567+ }
568+ }
569+ }
570+
571+ fn visit_mut_member_prop ( & mut self , p : & mut MemberProp ) {
572+ p. visit_mut_children_with ( self ) ;
573+
574+ if let Some ( id) = p. as_ident ( ) {
575+ if & * id. sym == INITIAL_PROPS {
576+ self . has_init_props = true ;
577+ }
578+ }
579+ }
456580}
457581
458582impl NextSuperJsonTransformer {
@@ -482,52 +606,61 @@ impl NextSuperJsonTransformer {
482606 pub fn find_ssg_prop ( & mut self , items : & mut Vec < ModuleItem > ) {
483607 let mut ssg_prop_ident = None ;
484608
485- self . props . export . orig = items. iter ( ) . position ( |item| match item {
486- // check has ssg props
487- ModuleItem :: ModuleDecl ( ModuleDecl :: ExportDecl ( ExportDecl { decl, .. } ) ) => match decl {
488- Decl :: Fn ( fn_decl) => SSG_EXPORTS . contains ( & & * fn_decl. ident . sym ) ,
489- Decl :: Var ( var_decl) => {
490- self . props . export . decl = var_decl. decls . iter ( ) . position ( |decl| {
491- SSG_EXPORTS . contains ( & & * decl. name . as_ident ( ) . unwrap ( ) . sym )
492- } ) ;
609+ self . props . export . orig = items. iter_mut ( ) . position ( |item| {
610+ // check initial props
611+ item. visit_mut_children_with ( self ) ;
493612
494- self . props . export . decl . is_some ( )
495- }
496- _ => false ,
497- } ,
498- ModuleItem :: ModuleDecl ( ModuleDecl :: ExportNamed ( NamedExport {
499- specifiers,
500- src,
501- ..
502- } ) ) => {
503- self . props . export . spec = specifiers. iter ( ) . position ( |specifier| match specifier {
504- ExportSpecifier :: Named ( ExportNamedSpecifier {
505- orig : ModuleExportName :: Ident ( orig_id) ,
506- exported,
507- ..
508- } ) => {
509- let exported_as = match exported {
510- Some ( ModuleExportName :: Ident ( exported_id) ) => & exported_id. sym ,
511- _ => & orig_id. sym ,
512- } ;
513-
514- if SSG_EXPORTS . contains ( & & * * exported_as) {
515- self . props . skip = src. is_some ( )
516- && ( exported. is_none ( ) || ( & & * * exported_as == & & * orig_id. sym ) ) ;
517-
518- if !self . props . skip {
519- ssg_prop_ident = Some ( ( * orig_id. sym ) . to_string ( ) ) ;
520- }
521- return true ;
613+ match item {
614+ // check has ssg props
615+ ModuleItem :: ModuleDecl ( ModuleDecl :: ExportDecl ( ExportDecl { decl, .. } ) ) => {
616+ match decl {
617+ Decl :: Fn ( fn_decl) => SSG_EXPORTS . contains ( & & * fn_decl. ident . sym ) ,
618+ Decl :: Var ( var_decl) => {
619+ self . props . export . decl = var_decl. decls . iter ( ) . position ( |decl| {
620+ SSG_EXPORTS . contains ( & & * decl. name . as_ident ( ) . unwrap ( ) . sym )
621+ } ) ;
622+
623+ self . props . export . decl . is_some ( )
522624 }
523- false
625+ _ => false ,
524626 }
525- _ => false ,
526- } ) ;
627+ }
628+ ModuleItem :: ModuleDecl ( ModuleDecl :: ExportNamed ( NamedExport {
629+ specifiers,
630+ src,
631+ ..
632+ } ) ) => {
633+ self . props . export . spec =
634+ specifiers. iter ( ) . position ( |specifier| match specifier {
635+ ExportSpecifier :: Named ( ExportNamedSpecifier {
636+ orig : ModuleExportName :: Ident ( orig_id) ,
637+ exported,
638+ ..
639+ } ) => {
640+ let exported_as = match exported {
641+ Some ( ModuleExportName :: Ident ( exported_id) ) => & exported_id. sym ,
642+ _ => & orig_id. sym ,
643+ } ;
644+
645+ if SSG_EXPORTS . contains ( & & * * exported_as) {
646+ self . props . skip = src. is_some ( )
647+ && ( exported. is_none ( )
648+ || ( & & * * exported_as == & & * orig_id. sym ) ) ;
649+
650+ if !self . props . skip {
651+ ssg_prop_ident = Some ( ( * orig_id. sym ) . to_string ( ) ) ;
652+ }
653+ return true ;
654+ }
655+ false
656+ }
657+ _ => false ,
658+ } ) ;
527659
528- self . props . export . spec . is_some ( )
660+ self . props . export . spec . is_some ( )
661+ }
662+ _ => false ,
529663 }
530- _ => false ,
531664 } ) ;
532665
533666 if ssg_prop_ident. is_some ( ) && !self . props . skip {
0 commit comments