diff --git a/compiler/apps/playground/components/Editor/Output.tsx b/compiler/apps/playground/components/Editor/Output.tsx index 331aa66bcbeb4..dcc8dea5c83bf 100644 --- a/compiler/apps/playground/components/Editor/Output.tsx +++ b/compiler/apps/playground/components/Editor/Output.tsx @@ -19,12 +19,13 @@ import { import parserBabel from 'prettier/plugins/babel'; import * as prettierPluginEstree from 'prettier/plugins/estree'; import * as prettier from 'prettier/standalone'; -import {memo, ReactNode, useEffect, useState} from 'react'; import {type Store} from '../../lib/stores'; +import {memo, ReactNode, use, useState, Suspense} from 'react'; import AccordionWindow from '../AccordionWindow'; import TabbedWindow from '../TabbedWindow'; import {monacoOptions} from './monacoOptions'; import {BabelFileResult} from '@babel/core'; +import {LRUCache} from 'lru-cache'; const MemoizedOutput = memo(Output); @@ -32,6 +33,10 @@ export default MemoizedOutput; export const BASIC_OUTPUT_TAB_NAMES = ['Output', 'SourceMap']; +const tabifyCache = new LRUCache>>({ + max: 5, +}); + export type PrintedCompilerPipelineValue = | { kind: 'hir'; @@ -200,6 +205,25 @@ ${code} return reorderedTabs; } +function tabifyCached( + store: Store, + compilerOutput: CompilerOutput, +): Promise> { + const cached = tabifyCache.get(store); + if (cached) return cached; + const result = tabify(store.source, compilerOutput, store.showInternals); + tabifyCache.set(store, result); + return result; +} + +function Fallback(): JSX.Element { + return ( +
+ Loading... +
+ ); +} + function utf16ToUTF8(s: string): string { return unescape(encodeURIComponent(s)); } @@ -213,12 +237,17 @@ function getSourceMapUrl(code: string, map: string): string | null { } function Output({store, compilerOutput}: Props): JSX.Element { + return ( + }> + + + ); +} + +function OutputContent({store, compilerOutput}: Props): JSX.Element { const [tabsOpen, setTabsOpen] = useState>( () => new Set(['Output']), ); - const [tabs, setTabs] = useState>( - () => new Map(), - ); const [activeTab, setActiveTab] = useState('Output'); /* @@ -233,13 +262,6 @@ function Output({store, compilerOutput}: Props): JSX.Element { setTabsOpen(new Set(['Output'])); setActiveTab('Output'); } - - useEffect(() => { - tabify(store.source, compilerOutput, store.showInternals).then(tabs => { - setTabs(tabs); - }); - }, [store.source, compilerOutput, store.showInternals]); - const changedPasses: Set = new Set(['Output', 'HIR']); // Initial and final passes should always be bold let lastResult: string = ''; for (const [passName, results] of compilerOutput.results) { @@ -254,6 +276,7 @@ function Output({store, compilerOutput}: Props): JSX.Element { lastResult = currResult; } } + const tabs = use(tabifyCached(store, compilerOutput)); if (!store.showInternals) { return ( diff --git a/compiler/apps/playground/package.json b/compiler/apps/playground/package.json index 08aed45e0f33c..6d5757008a5bc 100644 --- a/compiler/apps/playground/package.json +++ b/compiler/apps/playground/package.json @@ -32,6 +32,7 @@ "hermes-eslint": "^0.25.0", "hermes-parser": "^0.25.0", "invariant": "^2.2.4", + "lru-cache": "^11.2.2", "lz-string": "^1.5.0", "monaco-editor": "^0.52.0", "next": "15.6.0-canary.7", diff --git a/compiler/apps/playground/yarn.lock b/compiler/apps/playground/yarn.lock index 53f0d24db706f..00b8a6950f93a 100644 --- a/compiler/apps/playground/yarn.lock +++ b/compiler/apps/playground/yarn.lock @@ -3104,6 +3104,11 @@ lru-cache@^10.2.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== +lru-cache@^11.2.2: + version "11.2.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.2.2.tgz#40fd37edffcfae4b2940379c0722dc6eeaa75f24" + integrity sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"