@@ -19,19 +19,24 @@ import {
1919import parserBabel from 'prettier/plugins/babel' ;
2020import * as prettierPluginEstree from 'prettier/plugins/estree' ;
2121import * as prettier from 'prettier/standalone' ;
22- import { memo , ReactNode , useEffect , useState } from 'react' ;
2322import { type Store } from '../../lib/stores' ;
23+ import { memo , ReactNode , use , useState , Suspense } from 'react' ;
2424import AccordionWindow from '../AccordionWindow' ;
2525import TabbedWindow from '../TabbedWindow' ;
2626import { monacoOptions } from './monacoOptions' ;
2727import { BabelFileResult } from '@babel/core' ;
28+ import { LRUCache } from 'lru-cache' ;
2829
2930const MemoizedOutput = memo ( Output ) ;
3031
3132export default MemoizedOutput ;
3233
3334export const BASIC_OUTPUT_TAB_NAMES = [ 'Output' , 'SourceMap' ] ;
3435
36+ const tabifyCache = new LRUCache < Store , Promise < Map < string , ReactNode > > > ( {
37+ max : 5 ,
38+ } ) ;
39+
3540export type PrintedCompilerPipelineValue =
3641 | {
3742 kind : 'hir' ;
@@ -200,6 +205,25 @@ ${code}
200205 return reorderedTabs ;
201206}
202207
208+ function tabifyCached (
209+ store : Store ,
210+ compilerOutput : CompilerOutput ,
211+ ) : Promise < Map < string , ReactNode > > {
212+ const cached = tabifyCache . get ( store ) ;
213+ if ( cached ) return cached ;
214+ const result = tabify ( store . source , compilerOutput , store . showInternals ) ;
215+ tabifyCache . set ( store , result ) ;
216+ return result ;
217+ }
218+
219+ function Fallback ( ) : JSX . Element {
220+ return (
221+ < div className = "w-full h-monaco_small sm:h-monaco flex items-center justify-center" >
222+ Loading...
223+ </ div >
224+ ) ;
225+ }
226+
203227function utf16ToUTF8 ( s : string ) : string {
204228 return unescape ( encodeURIComponent ( s ) ) ;
205229}
@@ -213,12 +237,17 @@ function getSourceMapUrl(code: string, map: string): string | null {
213237}
214238
215239function Output ( { store, compilerOutput} : Props ) : JSX . Element {
240+ return (
241+ < Suspense fallback = { < Fallback /> } >
242+ < OutputContent store = { store } compilerOutput = { compilerOutput } />
243+ </ Suspense >
244+ ) ;
245+ }
246+
247+ function OutputContent ( { store, compilerOutput} : Props ) : JSX . Element {
216248 const [ tabsOpen , setTabsOpen ] = useState < Set < string > > (
217249 ( ) => new Set ( [ 'Output' ] ) ,
218250 ) ;
219- const [ tabs , setTabs ] = useState < Map < string , React . ReactNode > > (
220- ( ) => new Map ( ) ,
221- ) ;
222251 const [ activeTab , setActiveTab ] = useState < string > ( 'Output' ) ;
223252
224253 /*
@@ -233,13 +262,6 @@ function Output({store, compilerOutput}: Props): JSX.Element {
233262 setTabsOpen ( new Set ( [ 'Output' ] ) ) ;
234263 setActiveTab ( 'Output' ) ;
235264 }
236-
237- useEffect ( ( ) => {
238- tabify ( store . source , compilerOutput , store . showInternals ) . then ( tabs => {
239- setTabs ( tabs ) ;
240- } ) ;
241- } , [ store . source , compilerOutput , store . showInternals ] ) ;
242-
243265 const changedPasses : Set < string > = new Set ( [ 'Output' , 'HIR' ] ) ; // Initial and final passes should always be bold
244266 let lastResult : string = '' ;
245267 for ( const [ passName , results ] of compilerOutput . results ) {
@@ -254,6 +276,7 @@ function Output({store, compilerOutput}: Props): JSX.Element {
254276 lastResult = currResult ;
255277 }
256278 }
279+ const tabs = use ( tabifyCached ( store , compilerOutput ) ) ;
257280
258281 if ( ! store . showInternals ) {
259282 return (
0 commit comments