@@ -43,13 +43,15 @@ export type CompilerPass = {
43
43
comments : Array < t . CommentBlock | t . CommentLine > ;
44
44
code : string | null ;
45
45
} ;
46
+ const OPT_IN_DIRECTIVES = new Set ( [ 'use forget' , 'use memo' ] ) ;
47
+ export const OPT_OUT_DIRECTIVES = new Set ( [ 'use no forget' , 'use no memo' ] ) ;
46
48
47
49
function findDirectiveEnablingMemoization (
48
50
directives : Array < t . Directive > ,
49
51
) : t . Directive | null {
50
52
for ( const directive of directives ) {
51
53
const directiveValue = directive . value . value ;
52
- if ( directiveValue === 'use forget' || directiveValue === 'use memo' ) {
54
+ if ( OPT_IN_DIRECTIVES . has ( directiveValue ) ) {
53
55
return directive ;
54
56
}
55
57
}
@@ -62,11 +64,7 @@ function findDirectiveDisablingMemoization(
62
64
) : t . Directive | null {
63
65
for ( const directive of directives ) {
64
66
const directiveValue = directive . value . value ;
65
- if (
66
- ( directiveValue === 'use no forget' ||
67
- directiveValue === 'use no memo' ) &&
68
- ! options . ignoreUseNoForget
69
- ) {
67
+ if ( OPT_OUT_DIRECTIVES . has ( directiveValue ) && ! options . ignoreUseNoForget ) {
70
68
return directive ;
71
69
}
72
70
}
@@ -338,6 +336,11 @@ export function compileProgram(
338
336
} > = [ ] ;
339
337
const compiledFns : Array < CompileResult > = [ ] ;
340
338
339
+ const useNoForget = findDirectiveDisablingMemoization (
340
+ program . node . directives ,
341
+ pass . opts ,
342
+ ) ;
343
+
341
344
const traverseFunction = ( fn : BabelFn , pass : CompilerPass ) : void => {
342
345
const fnType = getReactFunctionType ( fn , pass , environment ) ;
343
346
if ( fnType === null || ALREADY_COMPILED . has ( fn . node ) ) {
@@ -434,8 +437,20 @@ export function compileProgram(
434
437
handleError ( err , pass , fn . node . loc ?? null ) ;
435
438
return null ;
436
439
}
437
-
438
- if ( ! pass . opts . noEmit && ! hasCriticalError ) {
440
+ /**
441
+ * If 'use no forget/memo' is present, we still run the code through the compiler for validation
442
+ * but we don't mutate the babel AST. This allows us to flag if there is an unused
443
+ * 'use no forget/memo' directive.
444
+ */
445
+ if ( useNoForget != null ) {
446
+ pass . opts . logger ?. logEvent ( pass . filename , {
447
+ kind : 'CompileSkip' ,
448
+ fnLoc : fn . node . body . loc ?? null ,
449
+ reason : `Skipped due to '${ useNoForget . value } ' directive.` ,
450
+ loc : useNoForget . loc ?? null ,
451
+ } ) ;
452
+ return null ;
453
+ } else if ( ! pass . opts . noEmit && ! hasCriticalError ) {
439
454
return compiledFn ;
440
455
}
441
456
return null ;
@@ -596,24 +611,6 @@ function shouldSkipCompilation(
596
611
}
597
612
}
598
613
599
- // Top level "use no forget", skip this file entirely
600
- const useNoForget = findDirectiveDisablingMemoization (
601
- program . node . directives ,
602
- pass . opts ,
603
- ) ;
604
- if ( useNoForget != null ) {
605
- pass . opts . logger ?. logEvent ( pass . filename , {
606
- kind : 'CompileError' ,
607
- fnLoc : null ,
608
- detail : {
609
- severity : ErrorSeverity . Todo ,
610
- reason : 'Skipped due to "use no forget" directive.' ,
611
- loc : useNoForget . loc ?? null ,
612
- suggestions : null ,
613
- } ,
614
- } ) ;
615
- return true ;
616
- }
617
614
const moduleName = pass . opts . runtimeModule ?? 'react/compiler-runtime' ;
618
615
if ( hasMemoCacheFunctionImport ( program , moduleName ) ) {
619
616
return true ;
@@ -638,14 +635,10 @@ function getReactFunctionType(
638
635
) ;
639
636
if ( useNoForget != null ) {
640
637
pass . opts . logger ?. logEvent ( pass . filename , {
641
- kind : 'CompileError ' ,
638
+ kind : 'CompileSkip ' ,
642
639
fnLoc : fn . node . body . loc ?? null ,
643
- detail : {
644
- severity : ErrorSeverity . Todo ,
645
- reason : 'Skipped due to "use no forget" directive.' ,
646
- loc : useNoForget . loc ?? null ,
647
- suggestions : null ,
648
- } ,
640
+ reason : `Skipped due to '${ useNoForget . value } ' directive.` ,
641
+ loc : useNoForget . loc ?? null ,
649
642
} ) ;
650
643
return null ;
651
644
}
0 commit comments