{"version":3,"sources":["../src/moduleCache.tsx"],"sourcesContent":["// based on: https://www.bbss.dev/posts/react-learn-suspense/#fetchcache-provider\n\nimport { createContext, ReactNode } from 'react';\nimport { EvaluationContext } from './sandboxTypes';\nimport { addListener } from './sandboxUtils';\nimport { COMPILE } from './generated/protocol';\n\nexport class ModuleCache {\n  nameResolutionPromises: Record<string, Promise<string>> = {};\n  evaluationContextPromises: Record<string, Promise<EvaluationContext>> = {};\n\n  constructor() {\n    // A compile-time cache reset, deliberately NOT performed. Resetting here\n    // replaced every <Include>'s module-evaluation-context promise with a new\n    // promise for the same value on EVERY compilation, including compilations that\n    // do not affect that module, so the component lost its state for nothing. The\n    // listener stays registered (and the reset stays here, disabled) because the\n    // fix is to scope the reset to the modules a compile actually changed, not to\n    // drop the seam.\n    addListener(COMPILE, () => {\n      // this.nameResolutionPromises = {};\n      // this.evaluationContextPromises = {};\n    });\n  }\n\n  // PROMISE-IDENTITY INVARIANT (the app-frame Suspense replay; pinned by\n  // src/boot.suspenseReplay.test.tsx): the promise returned by\n  // `getEvaluationContext` for a given key must be THE SAME promise for the\n  // whole realm boot. `Include` hands it straight to React's `use()` — a new\n  // identity for the same key mid-session re-suspends the boundary and REPLAYS\n  // every effect under it while the component instance, refs, DOM and\n  // in-flight promise chains survive (the Suspense hide/reveal signature). The\n  // invariant holds because the cache lives for the whole boot (one instance\n  // per `boot()` call), entries are never evicted (the compile seam above\n  // stays disabled), and the key — base-module filepath + module name — is\n  // stable for a stable URL. Any change that lets the same key answer a fresh\n  // promise (eviction, a scoped compile reset, a re-created cache) re-opens\n  // the replay, and the named test then fails loudly.\n\n  private getCacheKey(mod: EvaluationContext, moduleName: string): string {\n    return `${mod.evaluation.module.filepath}|${moduleName}`;\n  }\n\n  resolveModuleName(moduleName: string, baseModule?: EvaluationContext): Promise<string> {\n    // note: uses current module as base module if none specified by caller\n    // @ts-ignore\n    const mod = baseModule ?? (module as EvaluationContext);\n    const cacheKey = this.getCacheKey(mod, moduleName);\n    if (!(cacheKey in this.nameResolutionPromises)) {\n      this.nameResolutionPromises[cacheKey] = mod.resolve(moduleName);\n    }\n    return this.nameResolutionPromises[cacheKey];\n  }\n\n  getEvaluationContext(moduleName: string, baseModule?: EvaluationContext): Promise<EvaluationContext> {\n    // note: uses current module as base module if none specified by caller\n    // @ts-ignore\n    const mod = baseModule ?? (module as EvaluationContext);\n    const cacheKey = this.getCacheKey(mod, moduleName);\n    if (!(cacheKey in this.evaluationContextPromises)) {\n      this.evaluationContextPromises[cacheKey] = mod.getModuleEvaluationContext(moduleName);\n    }\n    return this.evaluationContextPromises[cacheKey];\n  }\n}\n\nexport const ModuleCacheContext = createContext<null | ModuleCache>(null);\n\nexport const ModuleCacheContextProvider = ({\n  children,\n  moduleCache,\n}: {\n  children: ReactNode;\n  moduleCache: ModuleCache;\n}) => {\n  return <ModuleCacheContext.Provider value={moduleCache}>{children}</ModuleCacheContext.Provider>;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2ES;AAzET,mBAAyC;AAEzC,0BAA4B;AAC5B,sBAAwB;AAEjB,MAAM,YAAY;AAAA,EAIvB,cAAc;AAHd,kCAA0D,CAAC;AAC3D,qCAAwE,CAAC;AAUvE,yCAAY,yBAAS,MAAM;AAAA,IAG3B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBQ,YAAY,KAAwB,YAA4B;AACtE,WAAO,GAAG,IAAI,WAAW,OAAO,QAAQ,IAAI,UAAU;AAAA,EACxD;AAAA,EAEA,kBAAkB,YAAoB,YAAiD;AAGrF,UAAM,MAAM,cAAe;AAC3B,UAAM,WAAW,KAAK,YAAY,KAAK,UAAU;AACjD,QAAI,EAAE,YAAY,KAAK,yBAAyB;AAC9C,WAAK,uBAAuB,QAAQ,IAAI,IAAI,QAAQ,UAAU;AAAA,IAChE;AACA,WAAO,KAAK,uBAAuB,QAAQ;AAAA,EAC7C;AAAA,EAEA,qBAAqB,YAAoB,YAA4D;AAGnG,UAAM,MAAM,cAAe;AAC3B,UAAM,WAAW,KAAK,YAAY,KAAK,UAAU;AACjD,QAAI,EAAE,YAAY,KAAK,4BAA4B;AACjD,WAAK,0BAA0B,QAAQ,IAAI,IAAI,2BAA2B,UAAU;AAAA,IACtF;AACA,WAAO,KAAK,0BAA0B,QAAQ;AAAA,EAChD;AACF;AAEO,MAAM,yBAAqB,4BAAkC,IAAI;AAEjE,MAAM,6BAA6B,CAAC;AAAA,EACzC;AAAA,EACA;AACF,MAGM;AACJ,SAAO,4CAAC,mBAAmB,UAAnB,EAA4B,OAAO,aAAc,UAAS;AACpE;","names":[]}