{"version":3,"file":"lithentDevHelper.mjs","sources":["../src/componentMapControl.ts","../src/createBoundary.ts"],"sourcesContent":["import type { CompKey } from 'lithent';\nimport { setComponentMapManualMode, disposeComponentEntry } from 'lithent';\n\nlet manualModeRefCount = 0;\n\nexport const enableComponentMapManualMode = (): void => {\n  manualModeRefCount += 1;\n  setComponentMapManualMode(true);\n};\n\nexport const disableComponentMapManualMode = (): void => {\n  manualModeRefCount = Math.max(0, manualModeRefCount - 1);\n  if (manualModeRefCount === 0) {\n    setComponentMapManualMode(false);\n  }\n};\n\nexport const removeComponentEntry = (compKey: CompKey): void => {\n  disposeComponentEntry(compKey);\n};\n","import type { CompKey, TagFunction, WDom } from 'lithent';\nimport { componentMap, replaceWDom } from 'lithent';\nimport {\n  disableComponentMapManualMode,\n  enableComponentMapManualMode,\n  removeComponentEntry,\n} from './componentMapControl';\n\nconst MAX_RETRY = 3;\n\ntype Registration = { callerCtor?: TagFunction };\n\ntype PendingUpdate = {\n  ctor: TagFunction;\n  instances: Map<CompKey, Registration>;\n  retryCount: number;\n  updated: boolean;\n};\n\ntype InstanceRegistry = {\n  instances: Set<CompKey>;\n  domMap: Map<CompKey, WDom>;\n  scheduled: boolean;\n  pendingUpdate?: PendingUpdate;\n  owners: number;\n  registrations: Map<CompKey, Registration>;\n  onFailure?: (reason: string) => void;\n  onApplied?: () => void;\n};\n\nconst boundaryRegistry = new Map<string, InstanceRegistry>();\n\nconst getRegistry = (moduleId: string): InstanceRegistry => {\n  let registry = boundaryRegistry.get(moduleId);\n\n  if (!registry) {\n    registry = {\n      instances: new Set(),\n      domMap: new Map(),\n      scheduled: false,\n      owners: 0,\n      registrations: new Map(),\n    };\n    boundaryRegistry.set(moduleId, registry);\n    enableComponentMapManualMode();\n  }\n\n  return registry;\n};\n\nexport type BoundaryController = {\n  register: (compKey: CompKey, callerCtor?: TagFunction) => () => void;\n  update: (nextCtor: TagFunction) => boolean;\n  dispose: () => void;\n};\n\nexport const registerBoundaryInstance = (\n  moduleId: string,\n  compKey: CompKey,\n  callerCtor?: TagFunction\n) => {\n  const registry = getRegistry(moduleId);\n\n  const registration = { callerCtor };\n  registry.registrations.set(compKey, registration);\n  registry.instances.add(compKey);\n\n  queueMicrotask(() => {\n    const entry = componentMap.get(compKey);\n    const currentWDom = entry?.vd?.value ?? null;\n\n    if (\n      currentWDom &&\n      boundaryRegistry.get(moduleId) === registry &&\n      registry.registrations.get(compKey) === registration\n    ) {\n      registry.domMap.set(compKey, currentWDom);\n    }\n  });\n\n  return () => {\n    const currentRegistry = boundaryRegistry.get(moduleId);\n    if (\n      currentRegistry !== registry ||\n      currentRegistry.registrations.get(compKey) !== registration\n    )\n      return;\n\n    currentRegistry.registrations.delete(compKey);\n    currentRegistry.instances.delete(compKey);\n    currentRegistry.domMap.delete(compKey);\n  };\n};\n\nexport const disposeBoundary = (moduleId: string) => {\n  const registry = boundaryRegistry.get(moduleId);\n\n  if (!registry) return;\n  boundaryRegistry.delete(moduleId);\n  for (const [compKey, registration] of Array.from(registry.registrations)) {\n    // A direct call observes its caller; it does not own that caller's lifetime.\n    if (!registration.callerCtor) removeComponentEntry(compKey);\n  }\n  registry.instances.clear();\n  registry.registrations.clear();\n  registry.domMap.clear();\n  disableComponentMapManualMode();\n};\n\nexport const applyBoundaryUpdate = (\n  moduleId: string,\n  nextCtor: TagFunction\n) => {\n  const registry = boundaryRegistry.get(moduleId);\n\n  if (!registry?.instances.size) return false;\n\n  registry.pendingUpdate = {\n    ctor: nextCtor,\n    instances: new Map(registry.registrations),\n    retryCount: 0,\n    updated: false,\n  };\n\n  if (!registry.scheduled) {\n    registry.scheduled = true;\n    queueMicrotask(() => flushBoundary(moduleId, registry));\n  }\n\n  return true;\n};\n\nconst flushBoundary = (moduleId: string, registry: InstanceRegistry) => {\n  if (boundaryRegistry.get(moduleId) !== registry) return;\n\n  registry.scheduled = false;\n\n  const update = registry.pendingUpdate;\n  if (!update) return;\n\n  registry.pendingUpdate = undefined;\n\n  let failed = false;\n\n  // Replacement can unregister old instances and register new descendants.\n  // Never consume additions made during this flush, or revisit retired nodes.\n  const instances = Array.from(update.instances, ([compKey, registration]) => ({\n    compKey,\n    wDom: componentMap.get(compKey)?.vd?.value || registry.domMap.get(compKey),\n    registration,\n  }));\n  update.instances.clear();\n  instances.forEach(({ compKey, wDom: currentWDom, registration }) => {\n    if (\n      boundaryRegistry.get(moduleId) !== registry ||\n      registry.registrations.get(compKey) !== registration ||\n      currentWDom?.il\n    )\n      return;\n\n    if (!currentWDom || !currentWDom.el) {\n      update.instances.set(compKey, registration);\n      return;\n    }\n\n    const { compProps, compChild } = currentWDom;\n\n    if (!compProps || !compChild) {\n      update.instances.set(compKey, registration);\n      return;\n    }\n\n    const ctor = registration.callerCtor || update.ctor;\n    const previousCtor = currentWDom.ctor;\n    // A stable HMR proxy has the same identity across versions. Force only this\n    // replacement to remount; the new WDom retains the proxy for later redraws.\n    if (!registration.callerCtor && previousCtor === ctor)\n      currentWDom.ctor = undefined;\n    try {\n      // A remount reuses the props/key. Release the old hooks before the core\n      // initializes its new hook state under that key.\n      if (!registration.callerCtor) removeComponentEntry(compKey);\n      replaceWDom(ctor, compProps, compChild, currentWDom);\n      update.updated = true;\n    } catch (error) {\n      failed = true;\n      console.warn(`[Lithent HMR] boundary update 실패: ${moduleId}`, error);\n    } finally {\n      currentWDom.ctor = previousCtor;\n    }\n  });\n\n  if (boundaryRegistry.get(moduleId) !== registry) return;\n  if (failed) registry.onFailure?.(`replacement failed: ${moduleId}`);\n  else if (update.updated && !update.instances.size) registry.onApplied?.();\n\n  // A newer update supersedes retries for the older implementation.\n  if (!registry.pendingUpdate && !failed && update.instances.size) {\n    update.retryCount += 1;\n\n    if (update.retryCount > MAX_RETRY) {\n      console.warn(\n        `[Lithent HMR] boundary update failed after ${update.retryCount} attempts; aborting: ${moduleId}`\n      );\n\n      registry.onFailure?.(\n        `missing DOM after ${update.retryCount} attempts: ${moduleId}`\n      );\n\n      return;\n    }\n    registry.pendingUpdate = update;\n  }\n\n  if (registry.pendingUpdate && !registry.scheduled) {\n    registry.scheduled = true;\n    setTimeout(() => flushBoundary(moduleId, registry), 0);\n  }\n};\n\nexport const createBoundary = (\n  moduleId: string,\n  onFailure?: (reason: string) => void,\n  onApplied?: () => void\n): BoundaryController => {\n  const registry = getRegistry(moduleId);\n  registry.owners += 1;\n  registry.onFailure = onFailure;\n  registry.onApplied = onApplied;\n\n  let disposed = false;\n  const active = () => !disposed && boundaryRegistry.get(moduleId) === registry;\n  return {\n    register: (compKey: CompKey, callerCtor?: TagFunction) =>\n      active()\n        ? registerBoundaryInstance(moduleId, compKey, callerCtor)\n        : () => {},\n    update: (nextCtor: TagFunction) =>\n      active() && applyBoundaryUpdate(moduleId, nextCtor),\n    dispose: () => {\n      if (!active()) return;\n      disposed = true;\n      registry.owners -= 1;\n      if (!registry.owners) disposeBoundary(moduleId);\n    },\n  };\n};\n"],"names":["manualModeRefCount","enableComponentMapManualMode","setComponentMapManualMode","disableComponentMapManualMode","removeComponentEntry","compKey","disposeComponentEntry","MAX_RETRY","boundaryRegistry","getRegistry","moduleId","registry","registerBoundaryInstance","callerCtor","registration","entry","componentMap","currentWDom","_a","currentRegistry","disposeBoundary","applyBoundaryUpdate","nextCtor","flushBoundary","update","failed","instances","_b","compProps","compChild","ctor","previousCtor","replaceWDom","error","_c","createBoundary","onFailure","onApplied","disposed","active"],"mappings":";AAGA,IAAIA,IAAqB;AAElB,MAAMC,IAA+B,MAAY;AAChC,EAAAD,KAAA,GACtBE,EAA0B,EAAI;AAChC,GAEaC,IAAgC,MAAY;AACvD,EAAAH,IAAqB,KAAK,IAAI,GAAGA,IAAqB,CAAC,GACnDA,MAAuB,KACzBE,EAA0B,EAAK;AAEnC,GAEaE,IAAuB,CAACC,MAA2B;AAC9D,EAAAC,EAAsBD,CAAO;AAC/B,GCXME,IAAY,GAsBZC,wBAAuB,OAEvBC,IAAc,CAACC,MAAuC;AACtD,MAAAC,IAAWH,EAAiB,IAAIE,CAAQ;AAE5C,SAAKC,MACQA,IAAA;AAAA,IACT,+BAAe,IAAI;AAAA,IACnB,4BAAY,IAAI;AAAA,IAChB,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,mCAAmB,IAAI;AAAA,EAAA,GAERH,EAAA,IAAIE,GAAUC,CAAQ,GACVV,MAGxBU;AACT,GAQaC,IAA2B,CACtCF,GACAL,GACAQ,MACG;AACG,QAAAF,IAAWF,EAAYC,CAAQ,GAE/BI,IAAe,EAAE,YAAAD;AACd,SAAAF,EAAA,cAAc,IAAIN,GAASS,CAAY,GACvCH,EAAA,UAAU,IAAIN,CAAO,GAE9B,eAAe,MAAM;;AACb,UAAAU,IAAQC,EAAa,IAAIX,CAAO,GAChCY,MAAcC,IAAAH,KAAA,gBAAAA,EAAO,OAAP,gBAAAG,EAAW,UAAS;AAGtC,IAAAD,KACAT,EAAiB,IAAIE,CAAQ,MAAMC,KACnCA,EAAS,cAAc,IAAIN,CAAO,MAAMS,KAE/BH,EAAA,OAAO,IAAIN,GAASY,CAAW;AAAA,EAC1C,CACD,GAEM,MAAM;AACL,UAAAE,IAAkBX,EAAiB,IAAIE,CAAQ;AACrD,IACES,MAAoBR,KACpBQ,EAAgB,cAAc,IAAId,CAAO,MAAMS,MAIjCK,EAAA,cAAc,OAAOd,CAAO,GAC5Bc,EAAA,UAAU,OAAOd,CAAO,GACxBc,EAAA,OAAO,OAAOd,CAAO;AAAA,EAAA;AAEzC,GAEae,IAAkB,CAACV,MAAqB;AAC7C,QAAAC,IAAWH,EAAiB,IAAIE,CAAQ;AAE9C,MAAKC,GACL;AAAA,IAAAH,EAAiB,OAAOE,CAAQ;AACrB,eAAA,CAACL,GAASS,CAAY,KAAK,MAAM,KAAKH,EAAS,aAAa;AAErE,MAAKG,EAAa,cAAYV,EAAqBC,CAAO;AAE5D,IAAAM,EAAS,UAAU,SACnBA,EAAS,cAAc,SACvBA,EAAS,OAAO,SACcR;;AAChC,GAEakB,IAAsB,CACjCX,GACAY,MACG;AACG,QAAAX,IAAWH,EAAiB,IAAIE,CAAQ;AAE9C,SAAKC,KAAA,QAAAA,EAAU,UAAU,QAEzBA,EAAS,gBAAgB;AAAA,IACvB,MAAMW;AAAA,IACN,WAAW,IAAI,IAAIX,EAAS,aAAa;AAAA,IACzC,YAAY;AAAA,IACZ,SAAS;AAAA,EAAA,GAGNA,EAAS,cACZA,EAAS,YAAY,IACrB,eAAe,MAAMY,EAAcb,GAAUC,CAAQ,CAAC,IAGjD,MAd+B;AAexC,GAEMY,IAAgB,CAACb,GAAkBC,MAA+B;;AACtE,MAAIH,EAAiB,IAAIE,CAAQ,MAAMC,EAAU;AAEjD,EAAAA,EAAS,YAAY;AAErB,QAAMa,IAASb,EAAS;AACxB,MAAI,CAACa,EAAQ;AAEb,EAAAb,EAAS,gBAAgB;AAEzB,MAAIc,IAAS;AAIP,QAAAC,IAAY,MAAM,KAAKF,EAAO,WAAW,CAAC,CAACnB,GAASS,CAAY,MAAO;;AAAA;AAAA,MAC3E,SAAAT;AAAA,MACA,QAAMsB,KAAAT,IAAAF,EAAa,IAAIX,CAAO,MAAxB,gBAAAa,EAA2B,OAA3B,gBAAAS,EAA+B,UAAShB,EAAS,OAAO,IAAIN,CAAO;AAAA,MACzE,cAAAS;AAAA,IACA;AAAA,GAAA;AA0CF,MAzCAU,EAAO,UAAU,SACjBE,EAAU,QAAQ,CAAC,EAAE,SAAArB,GAAS,MAAMY,GAAa,cAAAH,QAAmB;AAEhE,QAAAN,EAAiB,IAAIE,CAAQ,MAAMC,KACnCA,EAAS,cAAc,IAAIN,CAAO,MAAMS,KACxCG,KAAA,QAAAA,EAAa;AAEb;AAEF,QAAI,CAACA,KAAe,CAACA,EAAY,IAAI;AAC5B,MAAAO,EAAA,UAAU,IAAInB,GAASS,CAAY;AAC1C;AAAA,IACF;AAEM,UAAA,EAAE,WAAAc,GAAW,WAAAC,EAAc,IAAAZ;AAE7B,QAAA,CAACW,KAAa,CAACC,GAAW;AACrB,MAAAL,EAAA,UAAU,IAAInB,GAASS,CAAY;AAC1C;AAAA,IACF;AAEM,UAAAgB,IAAOhB,EAAa,cAAcU,EAAO,MACzCO,IAAed,EAAY;AAG7B,IAAA,CAACH,EAAa,cAAciB,MAAiBD,MAC/Cb,EAAY,OAAO;AACjB,QAAA;AAGF,MAAKH,EAAa,cAAYV,EAAqBC,CAAO,GAC9C2B,EAAAF,GAAMF,GAAWC,GAAWZ,CAAW,GACnDO,EAAO,UAAU;AAAA,aACVS,GAAO;AACL,MAAAR,IAAA,IACT,QAAQ,KAAK,qCAAqCf,CAAQ,IAAIuB,CAAK;AAAA,IAAA,UACnE;AACA,MAAAhB,EAAY,OAAOc;AAAA,IACrB;AAAA,EAAA,CACD,GAEGvB,EAAiB,IAAIE,CAAQ,MAAMC,GAKvC;AAAA,QAJIc,KAAQP,IAAAP,EAAS,cAAT,QAAAO,EAAA,KAAAP,GAAqB,uBAAuBD,CAAQ,MACvDc,EAAO,WAAW,CAACA,EAAO,UAAU,gBAAe,kCAGxD,CAACb,EAAS,iBAAiB,CAACc,KAAUD,EAAO,UAAU,MAAM;AAG3D,UAFJA,EAAO,cAAc,GAEjBA,EAAO,aAAajB,GAAW;AACzB,gBAAA;AAAA,UACN,8CAA8CiB,EAAO,UAAU,wBAAwBd,CAAQ;AAAA,QAAA,IAGxFwB,IAAAvB,EAAA,cAAA,QAAAuB,EAAA;AAAA,UAAAvB;AAAA,UACP,qBAAqBa,EAAO,UAAU,cAAcd,CAAQ;AAAA;AAG9D;AAAA,MACF;AACA,MAAAC,EAAS,gBAAgBa;AAAA,IAC3B;AAEA,IAAIb,EAAS,iBAAiB,CAACA,EAAS,cACtCA,EAAS,YAAY,IACrB,WAAW,MAAMY,EAAcb,GAAUC,CAAQ,GAAG,CAAC;AAAA;AAEzD,GAEawB,IAAiB,CAC5BzB,GACA0B,GACAC,MACuB;AACjB,QAAA1B,IAAWF,EAAYC,CAAQ;AACrC,EAAAC,EAAS,UAAU,GACnBA,EAAS,YAAYyB,GACrBzB,EAAS,YAAY0B;AAErB,MAAIC,IAAW;AACf,QAAMC,IAAS,MAAM,CAACD,KAAY9B,EAAiB,IAAIE,CAAQ,MAAMC;AAC9D,SAAA;AAAA,IACL,UAAU,CAACN,GAAkBQ,MAC3B0B,EAAA,IACI3B,EAAyBF,GAAUL,GAASQ,CAAU,IACtD,MAAM;AAAA,IAAC;AAAA,IACb,QAAQ,CAACS,MACPiB,EAAY,KAAAlB,EAAoBX,GAAUY,CAAQ;AAAA,IACpD,SAAS,MAAM;AACT,MAACiB,QACMD,IAAA,IACX3B,EAAS,UAAU,GACdA,EAAS,UAAQS,EAAgBV,CAAQ;AAAA,IAChD;AAAA,EAAA;AAEJ;"}