{"version":3,"file":"lithentDevHelper.cjs","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","compProps","compChild","ctor","previousCtor","replaceWDom","error","_c","createBoundary","onFailure","onApplied","disposed","active"],"mappings":"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"}