@wcstack/state 3.5.1 → 3.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"binder.js","sources":["../../../../../src/protocol/binder.ts","../../../../../src/mustache/convertMustacheToComments.ts","../../../../../src/structural/define.ts","../../../../../src/bindTextParser/parseFilterArgs.ts","../../../../../src/bindTextParser/utils.ts","../../../../../src/bindTextParser/parseFilters.ts","../../../../../src/bindTextParser/parsePropPart.ts","../../../../../src/bindTextParser/parseStatePart.ts","../../../../../src/bindTextParser/parseBindTextsForElement.ts","../../../../../src/bindings/parseCommentNode.ts","../../../../../src/bindTextParser/parseBindTextForEmbeddedNode.ts","../../../../../src/bindings/initializeBindingPromiseByNode.ts","../../../../../src/getCustomElement.ts","../../../../../src/platform/customElementRegistry.ts","../../../../../src/protocol/wcBindableReader.ts","../../../../../src/bindTextParser/expandSpread.ts","../../../../../src/structural/resolveNodePath.ts","../../../../../src/bindings/planFilters.ts","../../../../../src/bindings/getBindingsByNode.ts","../../../../../src/bindings/lightDomComponentScope.ts","../../../../../src/bindings/getSubscriberNodes.ts","../../../../../src/bindings/collectNodesAndBindingInfos.ts","../../../../../src/bindings/getBindingInfos.ts","../../../../../src/list/loopContextByNode.ts","../../../../../src/getUUID.ts","../../../../../src/list/createListIndex.ts","../../../../../src/updater/updateBatch.ts","../../../../../src/list/swapBaselineList.ts","../../../../../src/list/listIndexesByList.ts","../../../../../src/list/lastListValueByAbsoluteStateAddress.ts","../../../../../src/list/stateListBaseline.ts","../../../../../src/proxy/symbols.ts","../../../../../src/address/AbsoluteStateAddress.ts","../../../../../src/address/TreePath.ts","../../../../../src/address/liftAddress.ts","../../../../../src/apply/rootNodeByFragment.ts","../../../../../src/address/calcWildcardLen.ts","../../../../../src/list/wildcardLevel.ts","../../../../../src/list/getListIndexByBindingInfo.ts","../../../../../src/binding/getAbsoluteStateAddressByBinding.ts","../../../../../src/binding/getBindingSetByAbsoluteStateAddress.ts","../../../../../src/address/StateAddress.ts","../../../../../src/binding/getStateAddressByBindingInfo.ts","../../../../../src/event/handlerBindingRegistry.ts","../../../../../src/event/checkboxHandler.ts","../../../../../src/event/captureHandlerRejection.ts","../../../../../src/token/Token.ts","../../../../../src/event/EventToken.ts","../../../../../src/event/eventTokenRegistry.ts","../../../../../src/event/eventTokenHandler.ts","../../../../../src/command/CommandToken.ts","../../../../../src/event/handler.ts","../../../../../src/event/radioHandler.ts","../../../../../src/event/isPossibleTwoWay.ts","../../../../../src/propagation/propagation.ts","../../../../../src/proxy/occurrenceWrite.ts","../../../../../src/event/twowayHandler.ts","../../../../../src/bindings/observerSkip.ts","../../../../../src/bindings/DefinitionCoordinator.ts","../../../../../src/bindings/initialSync.ts","../../../../../src/bindings/BindingSession.ts","../../../../../src/bindings/replaceToReplaceNode.ts","../../../../../src/core/componentApplyHooks.ts","../../../../../src/apply/getFilteredValue.ts","../../../../../src/apply/applyChangeToCheckbox.ts","../../../../../src/createEmptyArray.ts","../../../../../src/apply/applyChangeToCommand.ts","../../../../../src/bindings/bindingsByContent.ts","../../../../../src/bindings/nodesByContent.ts","../../../../../src/bindings/bindLoopContextToContent.ts","../../../../../src/bindings/indexBindingsByContent.ts","../../../../../src/polyfills.ts","../../../../../src/cache/cacheEntryByAbsoluteStateAddress.ts","../../../../../src/protocol/transitionRunner.ts","../../../../../src/updater/updater.ts","../../../../../src/dependency/keyedDependency.ts","../../../../../src/list/createListDiff.ts","../../../../../src/list/stableListOrder.ts","../../../../../src/bindings/bindingSessionByContent.ts","../../../../../src/structural/planByContent.ts","../../../../../src/structural/activateContent.ts","../../../../../src/createEmptySet.ts","../../../../../src/structural/contentsByNode.ts","../../../../../src/structural/createContent.ts","../../../../../src/bindings/initializeBindings.ts","../../../../../src/structural/rowPlan.ts","../../../../../src/apply/viewTransitionNaming.ts","../../../../../src/apply/applyChangeToFor.ts","../../../../../src/apply/applyChangeToIf.ts","../../../../../src/apply/ssrPropertyStore.ts","../../../../../src/trustedTypes.ts","../../../../../src/apply/applyChangeToProperty.ts","../../../../../src/event/getInputAttributeMirror.ts","../../../../../src/apply/applyChangeToText.ts","../../../../../src/apply/applyChangeToWebComponent.ts","../../../../../src/apply/getValue.ts","../../../../../src/list/getIndexValueByLoopContext.ts","../../../../../src/apply/scheduleDeferredApply.ts","../../../../../src/apply/applyChange.ts","../../../../../src/apply/applyChangeToClass.ts","../../../../../src/apply/applyChangeToAttribute.ts","../../../../../src/apply/applyChangeToStyle.ts","../../../../../src/apply/applyChangeToRadio.ts","../../../../../src/apply/applyChangeFromBindings.ts","../../../../../src/waitForStateInitialize.ts","../../../../../src/buildBindings.ts","../../../../../src/core/featureEntries.ts","../../../../../src/core/ssrHooks.ts","../../../../../src/stateElementByName.ts","../../../../../src/structural/fragmentInfoByUUID.ts","../../../../../src/bindings/getParseBindTextResults.ts","../../../../../src/structural/createNotFilter.ts","../../../../../src/structural/expandShorthandPaths.ts","../../../../../src/structural/getNodePath.ts","../../../../../src/structural/getFragmentNodeInfos.ts","../../../../../src/structural/optimizeFragment.ts","../../../../../src/structural/collectStructuralFragments.ts","../../../../../src/bindings/binder.ts"],"sourcesContent":["// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/binder.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// binder protocol — how a package that inserts DOM hands those nodes to whoever\n// owns data bindings on the page.\n//\n// The dual of transition-runner: that one hands a *mutation* to whoever animates\n// it, this one hands *new nodes* to whoever binds them.\n//\n// A `data-wcs` binding exists only for nodes @wcstack/state walked when it built\n// its bindings. Nodes that arrive later — the content of a route that was not\n// active at that moment, a <wcs-head> child reflected into <head> — were never\n// walked, so their bindings silently do nothing, however often they are inserted.\n// @wcstack/router must not depend on @wcstack/state (zero runtime dependencies,\n// independently publishable), so state installs a binder on a well-known global\n// symbol and inserters look it up lazily.\n//\n// No binder installed means nothing happens — byte-for-byte the behavior these\n// packages had before the protocol existed.\n//\n// docs/binder-protocol-design.md is the normative description.\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/binder.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/binder.ts). Those copies are generated — do not edit them.\n\n/**\n * Global key the binder installs itself under. `Symbol.for` so independently\n * loaded copies of this file (two CDN bundles on one page) still agree.\n */\nexport const BINDER_KEY = Symbol.for(\"wcstack.binder\");\n\n/**\n * What the caller declares about a subtree it hands over (the second argument of `bind`; additive\n * since version 1 — a binder that predates it ignores it, and leaving it out keeps the old contract).\n */\nexport interface IWcsBindOptions {\n /**\n * The caller carries the range the subtree sits in: on removal it takes everything from its own\n * start mark up to its end mark along — what the binder rendered beside the subtree included, as\n * the rows a structural template handed over at the top of the content renders before its anchor —\n * and puts it all back on reinsertion. Only with this may a binder render such a template: without\n * it, what the binder rendered beside the subtree would be left behind. @wcstack/state 3.x ignores\n * the option and renders no structural template handed over itself, with or without it\n * (docs/binder-protocol-design.md §2, §9-5).\n */\n readonly range?: boolean;\n}\n\nexport interface IWcsBinder {\n readonly protocol: \"wcs-binder\";\n /** Integer protocol version. All versions >= 1 are participant-compatible. */\n readonly version: number;\n /**\n * Take a subtree that has just entered the document and bind whatever\n * declarations it carries.\n *\n * Contract (docs/binder-protocol-design.md §2):\n * - Synchronous. Initial values are applied before this returns, so the\n * caller never shows one frame of unbound markup.\n * - Idempotent. A subtree that is already bound is left alone, so a caller\n * may hand over the same nodes on every insertion without tracking which\n * ones are new.\n * - Binding survives later relocation, so this need not be called again when\n * the same nodes are moved (measured: design doc §8-3).\n * - Never throws for markup reasons; a subtree with no declarations is a\n * no-op.\n * - `options` (optional) is what the caller declares about the subtree\n * ({@link IWcsBindOptions}).\n */\n bind(subtree: Node, options?: IWcsBindOptions): void;\n}\n\n/**\n * The installed binder, or null when there is none or it speaks a version this\n * reader does not.\n *\n * Looked up on every call rather than cached, for the same reason\n * transition-runner does: the page's composition can change at any point, and a\n * stale cache would keep calling into a binder that is no longer there.\n */\nexport function getBinder(): IWcsBinder | null {\n const candidate = (globalThis as Record<symbol, unknown>)[BINDER_KEY] as IWcsBinder | undefined;\n if (candidate === undefined || candidate === null) return null;\n if (candidate.protocol !== \"wcs-binder\") return null;\n if (typeof candidate.version !== \"number\" || candidate.version < 1) return null;\n if (typeof candidate.bind !== \"function\") return null;\n return candidate;\n}\n\n/**\n * Subtrees offered before a binder existed, and the set of everything a binder\n * has taken. Both live on global symbols so that independently loaded copies of\n * this file — the router's and state's — share one queue.\n *\n * The queue is needed because of load order: the router's auto bundle runs\n * before state's, so `<wcs-head>` reflects its children into `<head>` while\n * there is still nothing to bind them. Offering them to a binder that arrives\n * later is the difference between working and silently blank.\n */\nconst PENDING_KEY = Symbol.for(\"wcstack.binder.pending\");\nconst TAKEN_KEY = Symbol.for(\"wcstack.binder.taken\");\n\nfunction pendingQueue(): Node[] {\n const globals = globalThis as Record<symbol, unknown>;\n let queue = globals[PENDING_KEY] as Node[] | undefined;\n if (queue === undefined) {\n queue = [];\n globals[PENDING_KEY] = queue;\n }\n return queue;\n}\n\nfunction takenSet(): WeakSet<Node> {\n const globals = globalThis as Record<symbol, unknown>;\n let taken = globals[TAKEN_KEY] as WeakSet<Node> | undefined;\n if (taken === undefined) {\n taken = new WeakSet<Node>();\n globals[TAKEN_KEY] = taken;\n }\n return taken;\n}\n\n/**\n * Hand `subtree` to the installed binder, or hold it for one that arrives later.\n *\n * Returns whether a binder took it *now*. A `false` does not yet mean the markup\n * is doomed — check {@link wasBoundBy} once module scripts have run.\n *\n * `options` goes to the binder with the subtree. A subtree held for a later binder\n * is handed over without it: that binder's first walk of the page binds what is\n * still in place there.\n */\nexport function bindSubtree(subtree: Node, options?: IWcsBindOptions): boolean {\n const binder = getBinder();\n if (binder === null) {\n pendingQueue().push(subtree);\n return false;\n }\n takenSet().add(subtree);\n binder.bind(subtree, options);\n return true;\n}\n\n/** Whether any binder has taken this subtree. */\nexport function wasBoundBy(subtree: Node): boolean {\n return takenSet().has(subtree);\n}\n\n/**\n * Bind everything offered before this binder existed. Called by the binder right\n * after it installs itself.\n */\nexport function flushPendingBinds(): void {\n const binder = getBinder();\n if (binder === null) return;\n const queue = pendingQueue();\n if (queue.length === 0) return;\n const pending = queue.splice(0, queue.length);\n const taken = takenSet();\n for (const subtree of pending) {\n taken.add(subtree);\n binder.bind(subtree);\n }\n}\n","import { config } from \"../config.js\";\nimport { SVG_NAMESPACE } from \"../define.js\";\n\nconst MUSTACHE_REGEX = /\\{\\{\\s*(.+?)\\s*\\}\\}/g;\nconst SKIP_TAGS = new Set([\"SCRIPT\", \"STYLE\"]);\n\nexport function convertMustacheToComments(root: Document | Element | DocumentFragment): void {\n if (!config.enableMustache) {\n return;\n }\n\n convertTextNodes(root);\n\n const templates = Array.from(root.querySelectorAll(\"template\"));\n\n for (const template of templates) {\n if (template.namespaceURI === SVG_NAMESPACE) {\n const newTemplate = document.createElement(\"template\");\n const childNodes = Array.from(template.childNodes);\n for(let i = 0; i < childNodes.length; i++) {\n const childNode = childNodes[i];\n newTemplate.content.appendChild(childNode);\n }\n for(const attr of template.attributes) {\n newTemplate.setAttribute(attr.name, attr.value);\n }\n template.replaceWith(newTemplate);\n convertMustacheToComments(newTemplate.content);\n } else {\n convertMustacheToComments(template.content);\n }\n }\n}\n\nfunction convertTextNodes(root: Document | Element | DocumentFragment): void {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n const textNodes: Text[] = [];\n\n while (walker.nextNode()) {\n textNodes.push(walker.currentNode as Text);\n }\n\n for (const textNode of textNodes) {\n if (textNode.parentElement && SKIP_TAGS.has(textNode.parentElement.tagName)) {\n continue;\n }\n replaceTextNode(textNode);\n }\n}\n\nfunction replaceTextNode(textNode: Text): void {\n const text = textNode.data;\n MUSTACHE_REGEX.lastIndex = 0;\n\n if (!MUSTACHE_REGEX.test(text)) {\n return;\n }\n\n MUSTACHE_REGEX.lastIndex = 0;\n const fragment = document.createDocumentFragment();\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = MUSTACHE_REGEX.exec(text)) !== null) {\n if (match.index > lastIndex) {\n fragment.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));\n }\n\n const bindText = match[1];\n fragment.appendChild(document.createComment(`@@: ${bindText}`));\n\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < text.length) {\n fragment.appendChild(document.createTextNode(text.slice(lastIndex)));\n }\n\n textNode.parentNode!.replaceChild(fragment, textNode);\n}\n","import { BindingType } from \"../types.js\";\n\nexport const STRUCTURAL_BINDING_TYPE_SET: Set<BindingType> = new Set([\n \"if\",\n \"elseif\",\n \"else\",\n \"for\",\n]);\n","/**\n * フィルタ引数リストのパース。`filter(a, b)` の `a, b` 部分を受け取る。\n *\n * トリムの規則は「**クォートの外側だけ**」。`fix( 2 )` のような書き癖を吸収するために\n * 素の引数は前後をトリムするが、クォートは「ここは literal」という宣言なので中身の\n * 空白は残す。両方まとめてトリムしていたため `pad(5, ' ')` が空文字パディング\n * (=無変化)に化けており、空白区切りの `join(' / ')` も指定できなかった。\n */\n\n/** 引数 1 つを確定する。クォート由来の文字が入った範囲より外側だけをトリムする。 */\nfunction finalizeArg(text: string, firstQuoteStart: number, lastQuoteEnd: number): string {\n // 先頭側: 最初のクォート文字より前だけが削れる(クォートが無ければ全体が対象)\n const startLimit = firstQuoteStart === -1 ? text.length : firstQuoteStart;\n let start = 0;\n while (start < startLimit && /\\s/.test(text[start])) {\n start++;\n }\n // 末尾側: 最後のクォート文字より後ろだけが削れる(クォートが無ければ全体が対象)\n const endLimit = lastQuoteEnd === -1 ? 0 : lastQuoteEnd;\n let end = text.length;\n while (end > endLimit && /\\s/.test(text[end - 1])) {\n end--;\n }\n return text.slice(start, end);\n}\n\nimport { LINT_HINT } from \"../errorGuidance\";\nimport { raiseError } from \"../raiseError\";\n\n/** 引用符の無い引数の型(要件 B9): true / false / null / 数値は型付き、それ以外は文字列 */\nconst NUMBER_LITERAL = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/;\nfunction toLiteral(text: string, quoted: boolean): unknown {\n if (quoted) return text;\n if (text === \"true\") return true;\n if (text === \"false\") return false;\n if (text === \"null\") return null;\n return NUMBER_LITERAL.test(text) ? Number(text) : text;\n}\n\n/**\n * 引数の原文と、その型付きの値(要件 B9)を一緒に返す。原文は引用符を外したもの。\n *\n * 末尾の空引数だけが落ちる(`\"a,\"` → 1 個、`\",a\"` → 2 個、`\",\"` → 1 個)。`filter()` を\n * 「引数 0 個」と読むための規則で、先頭・中間の空引数は位置を保つために残す。\n */\nexport function parseFilterArgsWithLiterals(argsText: string): { args: string[]; literals: unknown[] } {\n const args: string[] = [];\n const literals: unknown[] = [];\n let current = '';\n let inQuote: string | null = null;\n let hasQuote = false;\n let firstQuoteStart = -1;\n let lastQuoteEnd = -1;\n\n const flush = (): void => {\n const arg = finalizeArg(current, firstQuoteStart, lastQuoteEnd);\n args.push(arg);\n literals.push(toLiteral(arg, hasQuote));\n current = '';\n hasQuote = false;\n firstQuoteStart = -1;\n lastQuoteEnd = -1;\n };\n\n for (let i = 0; i < argsText.length; i++) {\n const char = argsText[i];\n\n if (inQuote) {\n if (char === inQuote) {\n inQuote = null;\n } else {\n if (firstQuoteStart === -1) {\n firstQuoteStart = current.length;\n }\n current += char;\n lastQuoteEnd = current.length;\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char;\n hasQuote = true;\n } else if (char === ',') {\n flush();\n } else {\n current += char;\n }\n }\n\n if (inQuote !== null) {\n // 閉じていない引用符は受理しない(要件 B2)。以前は黙って閉じたことにしていた\n raiseError(`[wcs/binding-syntax] unterminated ${inQuote} quote in the filter arguments \"(${argsText})\". Close the quote.${LINT_HINT}`);\n }\n const last = finalizeArg(current, firstQuoteStart, lastQuoteEnd);\n if (last || hasQuote) {\n args.push(last);\n literals.push(toLiteral(last, hasQuote));\n }\n\n return { args, literals };\n}\n","export const trimFn = (s: string): string => s.trim();\n\nconst isQuote = (c: string): boolean => c === \"'\" || c === '\"';\n\n/**\n * `text` の中で、引用符(`'` / `\"`)の外にある最初の `char` の位置。無ければ -1(要件 B1)。\n * 閉じていない引用符はそのまま末尾まで続く扱い — 不正な引用符はフィルタ引数の段で名指しで落ちる。\n */\nexport function indexOfOutsideQuotes(text: string, char: string): number {\n let quote: string | null = null;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quote !== null) {\n if (c === quote) quote = null;\n } else if (isQuote(c)) {\n quote = c;\n } else if (c === char) {\n return i;\n }\n }\n return -1;\n}\n\n/**\n * `text` の中で、引用符の外にある**最後の** `char` の位置。無ければ -1(要件 B1)。\n * 引用符は前からしか追えないので、前向きに走査して最後の一致を控える。\n * フィルタの閉じ括弧を探す用(`a|foo(')')` の引用符内の `)` を終端と誤認しないため)。\n */\nexport function lastIndexOfOutsideQuotes(text: string, char: string): number {\n let quote: string | null = null;\n let found = -1;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quote !== null) {\n if (c === quote) quote = null;\n } else if (isQuote(c)) {\n quote = c;\n } else if (c === char) {\n found = i;\n }\n }\n return found;\n}\n\n/**\n * `separator` で区切る。ただし引用符の中は区切らない(要件 B1): `join(';')` や `join('|')` の\n * 区切り文字は引数であって、バインディングやフィルタの区切りではない。\n */\nexport function splitOutsideQuotes(text: string, separator: string): string[] {\n const parts: string[] = [];\n let quote: string | null = null;\n let start = 0;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quote !== null) {\n if (c === quote) quote = null;\n } else if (isQuote(c)) {\n quote = c;\n } else if (c === separator) {\n parts.push(text.slice(start, i));\n start = i + 1;\n }\n }\n parts.push(text.slice(start));\n return parts;\n}\n","import { clearFilterResolutionCache } from \"../core/filterRegistry\";\nimport { MODIFIER_SEPARATOR } from \"../define\";\nimport { LINT_HINT } from \"../errorGuidance\";\nimport { FilterIOType } from \"../filters/types\";\nimport { raiseError } from \"../raiseError\";\nimport { IParsedFilter } from \"../types\";\nimport { parseFilterArgsWithLiterals } from \"./parseFilterArgs\";\nimport { indexOfOutsideQuotes, lastIndexOfOutsideQuotes } from \"./utils\";\n\n/** tooling 専用(parser.ts の clearParserCaches からのみ呼ぶ)。 */\nexport function clearFilterFnCacheForTooling(): void {\n clearFilterResolutionCache();\n}\n\n// format: filterName(arg1,arg2) or filterName\n\n/**\n * 文法の段(要件 D16): 名前と引数だけを読む。**実関数は引かない** — 束縛計画の段で\n * 登録簿から解決する(`core/filterRegistry.ts`・`bindings/getBindingInfos.ts`)。\n * 未知のフィルタもここでは落とさない: パーサだけを使う tooling は実装を持たないので、\n * 「知らない名前」を解析の段で判定できない。\n */\n/**\n * @param filterTextList 個々のフィルタの原文(`|` で切った後)\n * @param filterIOType 入力(左辺)/ 出力(右辺)。実関数は引かないが、助言の出し分けに使う\n * @param sourceText 診断に埋める原文。呼び出し側は**その辺の全文**(`propPart` / `statePart`)を\n * 渡すこと。`|` より後ろだけを渡すと、`textContent: a|` のように末尾が空の形で\n * 空文字になり、つなぎ直し(`filterTextList.join(\"|\")`)と同じで文脈が消える。\n * 省略時のつなぎ直しは、原文を持たない直接の呼び出し用のフォールバック\n */\nexport function parseFilters(filterTextList: string[], filterIOType: FilterIOType, sourceText?: string): IParsedFilter[] {\n const source = sourceText ?? filterTextList.join(\"|\");\n return filterTextList.map((filterText) => {\n // 括弧も引用符の外だけで探す(要件 B1)。素の `indexOf` / `lastIndexOf` だと\n // `foo(')')` の引用符内の `)` を終端に取り、「閉じ括弧が無い」ではなく\n // 「引用符が閉じていない」という見当違いの診断になっていた\n const openParenIndex = indexOfOutsideQuotes(filterText, '(');\n let closeParenIndex = lastIndexOfOutsideQuotes(filterText, ')');\n if (closeParenIndex === -1) {\n // 引用符の外に閉じ括弧が無い = 引用符が閉じていない形(`join('x)`)か、本当に無いか。\n // 前者で「閉じ括弧が無い」と言うのは見当違いなので素の探索へ落とし、引数の段の\n // `[wcs/binding-syntax] unterminated ' quote` に診断させる\n closeParenIndex = filterText.lastIndexOf(')');\n }\n // check parentheses\n if (openParenIndex !== -1 && closeParenIndex === -1) {\n raiseError(`[wcs/binding-syntax] Invalid filter format: missing closing parenthesis in \"${filterText}\".${LINT_HINT}`);\n }\n if (closeParenIndex !== -1 && openParenIndex === -1) {\n raiseError(`[wcs/binding-syntax] Invalid filter format: missing opening parenthesis in \"${filterText}\".${LINT_HINT}`);\n }\n if (closeParenIndex !== -1 && closeParenIndex < openParenIndex) {\n // `foo)1(` — 以前は `substring` が start > end で引数を入れ替えるため、フィルタ名\n // `foo)1` として受理されていた\n raiseError(`[wcs/binding-syntax] Invalid filter format: \")\" comes before \"(\" in \"${filterText}\".${LINT_HINT}`);\n }\n if (closeParenIndex !== -1 && filterText.slice(closeParenIndex + 1).trim().length > 0) {\n // 閉じ括弧の後ろの残余を**黙って捨てていた**。`n|fix(2)uc` は `uc` が消えて診断ゼロで\n // 通り、括弧の無い `n|ucuc` は `[wcs/filter-unknown]` で落ちる — 括弧の有無で非対称だった。\n // 実害は「`|` の打ち忘れでフィルタが 1 本消えても無診断」\n const trailing = filterText.slice(closeParenIndex + 1).trim();\n raiseError(\n `[wcs/binding-syntax] \"${filterText}\": unexpected \"${trailing}\" after the filter's closing \")\" — ` +\n `separate filters with \"|\" (write \"${filterText.slice(0, closeParenIndex + 1)}|${trailing}\").${LINT_HINT}`,\n );\n }\n const filterName = (openParenIndex === -1 ? filterText : filterText.substring(0, openParenIndex)).trim();\n if (filterName.length === 0) {\n // 空のフィルタ(`x|`・`x||y`・`x|(1)`)は文法の誤り。解析の段で名指しで落とす — 未知の\n // フィルタとは別物で、実関数の解決(束縛計画の段)まで持ち越すと tooling の解析が素通りする\n raiseError(`[wcs/binding-syntax] an empty filter in \"${source}\" — remove the extra \"|\" or name the filter.${LINT_HINT}`);\n }\n if (filterName.includes(MODIFIER_SEPARATOR)) {\n // フィルタ名に `#` が飲まれた形。`[wcs/filter-unknown] filter not found: trim#ro` だと\n // 診断が指す先が実際の誤りと違う(要件 B4 の並び)。\n // 助言は辺で分ける — **修飾子は左辺にしか存在しない**ので、右辺で「修飾子をフィルタより\n // 前に書け」と言うと成立しない直し方(`textContent#ro|trim: x`)を勧めることになる\n const [name, modifiers] = filterName.split(MODIFIER_SEPARATOR);\n raiseError(filterIOType === \"input\"\n ? `[wcs/binding-syntax] \"${filterName}\" is not a filter name: a modifier list ` +\n `\"${MODIFIER_SEPARATOR}${modifiers}\" comes before the input filters, not inside one — write ` +\n `\"<property>${MODIFIER_SEPARATOR}${modifiers}|${name}\".${LINT_HINT}`\n : `[wcs/binding-syntax] \"${filterName}\" is not a filter name: \"${MODIFIER_SEPARATOR}\" cannot appear ` +\n `in one. Modifiers belong on the left side of the binding, before the \":\" — write \"${name}\" ` +\n `here.${LINT_HINT}`);\n }\n if (openParenIndex === -1) {\n // no arguments\n return { filterName, args: [], literals: [] };\n }\n const argsText = filterText.substring(openParenIndex + 1, closeParenIndex);\n return { filterName, ...parseFilterArgsWithLiterals(argsText) };\n });\n}\n","import { DELIMITER, FILTER_SEPARATOR, MODIFIER_SEPARATOR } from \"../define\";\nimport { LINT_HINT } from \"../errorGuidance\";\nimport { raiseError } from \"../raiseError\";\nimport { IParsedBinding, IParsedFilter } from \"../types\";\nimport { parseFilters } from \"./parseFilters\";\nimport { indexOfOutsideQuotes, splitOutsideQuotes, trimFn } from \"./utils\";\n\n// 解析の段の形(フィルタは名前と引数だけ — 実関数は束縛計画の段で引く。要件 D16)\ntype PropPartParseResult = Pick<IParsedBinding, 'propName' | 'propSegments' | 'propModifiers' | 'inFilters'>;\n\nconst cacheFilterInfos = new Map<string, IParsedFilter[]>();\n\n/** tooling 専用(parser.ts の clearParserCaches からのみ呼ぶ)。 */\nexport function clearPropPartCacheForTooling(): void {\n cacheFilterInfos.clear();\n}\n\n// format: propName#moodifier1,modifier2\n// propName-format: path.to.property (e.g., textContent, style.color, not include :)\n// special path: \n// 'attr.attributeName' for attributes (e.g., attr.href, attr.data-id)\n// 'style.propertyName' for style properties (e.g., style.backgroundColor, style.fontSize)\n// 'class.className' for class names (e.g., class.active, class.hidden)\n// 'onclick', 'onchange' etc. for event listeners\n\nexport function parsePropPart(propPart: string): PropPartParseResult {\n const pos = indexOfOutsideQuotes(propPart, FILTER_SEPARATOR);\n let propText: string = '';\n let filterTexts: string[] = [];\n let filtersText = '';\n let filters: IParsedFilter[] = [];\n if (pos !== -1) {\n propText = propPart.slice(0, pos).trim();\n filtersText = propPart.slice(pos + 1).trim();\n if (cacheFilterInfos.has(filtersText)) {\n filters = cacheFilterInfos.get(filtersText)!;\n } else {\n filterTexts = splitOutsideQuotes(filtersText, FILTER_SEPARATOR).map(trimFn);\n // 診断に埋める原文は**左辺の全文**。`|` より後ろだけを渡すと `value|:` のように\n // 末尾が空の形で空文字になる(解析結果のキャッシュ鍵は従来どおり `filtersText`。\n // 落ちた解析はキャッシュに載らないので、原文を混ぜても鍵は汚れない)\n filters = parseFilters(filterTexts, \"input\", propPart);\n cacheFilterInfos.set(filtersText, filters);\n }\n } else {\n propText = propPart.trim();\n }\n\n // **不変条件**: ここから下の `split` は素で走らせてよい。`propText` は「引用符外の最初の `|`\n // より前」のスライスであり、引用符を含みうるのは入力フィルタの引数(`|` の後ろ)だけなので、\n // `#` も `,` も `.` も引用符の中に現れない。**修飾子の値に引用符を許す拡張(例\n // `value#fmt('a,b'): x`)を入れるなら、この 3 つも `splitOutsideQuotes` に替えること** —\n // 替え忘れると `structural/expandShorthandPaths.ts` で起きた「無言で 1 行も描画されない」\n // と同じ欠陥クラスが再発する。\n const modifierParts = propText.split(MODIFIER_SEPARATOR).map(trimFn);\n if (modifierParts.length > 2) {\n // 修飾子の並びは 1 つだけ(要件 B2)。`value#ro#wo` は以前 `ro` だけを残して黙って捨てていた\n raiseError(`[wcs/binding-syntax] \"${propText}\": a binding takes one modifier list after a single \"${MODIFIER_SEPARATOR}\" — write \"${modifierParts[0]}${MODIFIER_SEPARATOR}${modifierParts.slice(1).join(\",\")}\".${LINT_HINT}`);\n }\n const [propName, propModifiersText] = modifierParts;\n const propSegments = propName.split(DELIMITER).map(trimFn);\n // 明示のプロパティ形(`.name:` — 要件 B5 / D34)だけは先頭の空セグメントが正しい形。\n // それ以外で空のセグメントが残るのは書き間違い: 左辺が空(`\": x\"` / `\"#ro: x\"` / `\"|trim: x\"`)だと\n // `element[\"\"] = value` の expando ができて完全に沈黙し、末尾が空(`\"foo.: x\"`)だと適用の段で\n // 素の TypeError になる。どちらも解析の段で名指しで落とす(`.: x` 等は下の D34 の検査が受け持つ)\n const isExplicitProperty = propSegments.length > 1 && propSegments[0] === '';\n if (!isExplicitProperty && (propName.length === 0 || propSegments.some((segment) => segment.length === 0))) {\n raiseError(\n `[wcs/binding-syntax] \"${propPart}\": the left side of a binding must name a property — ` +\n `write \"<property>: <path>\" (modifiers and input filters come after the name).${LINT_HINT}`,\n );\n }\n const propModifiers = propModifiersText\n ? propModifiersText.split(',').map(trimFn)\n : [];\n return {\n propName,\n propSegments,\n propModifiers,\n inFilters: filters,\n };\n}","import { getPathInfo } from \"../address/PathInfo\";\nimport { raiseError } from \"../raiseError\";\nimport { DELIMITER, FILTER_SEPARATOR } from \"../define\";\nimport { LINT_HINT } from \"../errorGuidance\";\nimport { IParsedBinding, IParsedFilter } from \"../types\";\nimport { parseFilters } from \"./parseFilters\";\nimport { indexOfOutsideQuotes, splitOutsideQuotes, trimFn } from \"./utils\";\n\n// 解析の段の形(フィルタは名前と引数だけ — 実関数は束縛計画の段で引く。要件 D16)\ntype StatePartParseResult = Pick<IParsedBinding,\n 'statePathName' | 'statePathInfo' | 'outFilters'>;\n\nconst cacheFilterInfos = new Map<string, IParsedFilter[]>();\n\n/** tooling 専用(parser.ts の clearParserCaches からのみ呼ぶ)。 */\nexport function clearStatePartCacheForTooling(): void {\n cacheFilterInfos.clear();\n}\n\n// format: statePath|filter|filter\n// statePath-format: path.to.property (e.g., user.name.first, users.*.name, users.0.name, not include @)\n// filters-format: filterName or filterName(arg1,arg2)\nexport function parseStatePart(statePart: string): StatePartParseResult {\n // 引用符の中の `|` はフィルタの区切りではない(要件 B1 — `join('|')`)\n const pos = indexOfOutsideQuotes(statePart, FILTER_SEPARATOR);\n let stateAndPath: string = '';\n let filterTexts: string[] = [];\n let filtersText = '';\n let filters: IParsedFilter[] = [];\n if (pos !== -1) {\n stateAndPath = statePart.slice(0, pos).trim();\n filtersText = statePart.slice(pos + 1).trim();\n if (cacheFilterInfos.has(filtersText)) {\n filters = cacheFilterInfos.get(filtersText)!;\n } else {\n filterTexts = splitOutsideQuotes(filtersText, FILTER_SEPARATOR).map(trimFn);\n // 診断に埋める原文は**右辺の全文**(`parsePropPart` と同じ理由 — `a|` が空文字になる)\n filters = parseFilters(filterTexts, \"output\", statePart);\n cacheFilterInfos.set(filtersText, filters);\n }\n } else {\n stateAndPath = statePart.trim();\n }\n if (stateAndPath.indexOf(\"@\") !== -1) {\n // 名前次元は v2 で撤去(docs/state-mount-design.md D16 / §9)。パスは 1 本のツリー。\n raiseError(\n `\"${stateAndPath}\": the \"@name\" selector was removed in v2 — there is a single state tree. ` +\n `Mount the named state onto the tree (<wcs-state mount=\"...\">) and read it by its path prefix instead.`,\n );\n }\n const statePathName = stateAndPath;\n // 右辺も左辺(`parsePropPart`)と同じ規準で空セグメントを弾く(要件 B1)。放っておくと\n // `a.` / `a..b` は診断ゼロで `[\"a\",\"\",\"\"]` のまま intern され、`textContent:` /\n // `textContent: |uc` は適用の段で「`Path \"\"` が無い」というパス名が空の診断になる。\n //\n // **判定の前にループ相対の短縮形を正規化する。** `.` で始まる右辺は `for` 行の相対パスで\n // (`structural/expandShorthandPaths.ts` / `bindTextParser/expandSpread.ts` が生成し、正本の\n // パーサは展開前の原文も解析する)、先頭の空セグメント 1 つは正当。とくに **`.` 単独は\n // 「行そのもの」を指す正規の書き方**で、README と `examples/recursive-tree/index.html` の\n // `state: .` がそれ — 「先頭は許すが末尾は拒否」と素朴に書くと `\".\"` は\n // `[\"\", \"\"]` = 先頭かつ末尾なので落ちる。取り除いた残りが空でも通すこと\n const isLoopRelative = statePathName.startsWith(DELIMITER);\n const body = isLoopRelative ? statePathName.slice(DELIMITER.length) : statePathName;\n const hasEmptySegment = body.length > 0 && body.split(DELIMITER).some((segment) => segment.length === 0);\n if (hasEmptySegment || (!isLoopRelative && body.length === 0)) {\n raiseError(\n `[wcs/binding-syntax] \"${statePart}\": the right side of a binding must name a state path — ` +\n `write \"<property>: <path>\" (a path segment cannot be empty; \".\" alone and a leading \".\" are ` +\n `the loop-relative shorthand).${LINT_HINT}`,\n );\n }\n const pathInfo = getPathInfo(statePathName);\n return {\n statePathName,\n statePathInfo: pathInfo,\n outFilters: filters,\n };\n}\n","import { getPathInfo } from \"../address/PathInfo.js\";\nimport {\n ATTR_NAMESPACE,\n BINDING_SEPARATOR,\n DELIMITER,\n CLASS_NAMESPACE,\n COMMAND_NAMESPACE,\n ELSE_KEYWORD,\n STYLE_NAMESPACE,\n EVENT_PROP_PREFIX,\n FILTER_SEPARATOR,\n MODIFIER_SEPARATOR,\n EVENT_TOKEN_NAMESPACE,\n PROP_VALUE_SEPARATOR,\n SPREAD_PROP,\n VOLUME_INJECTION_PROP,\n} from \"../define.js\";\nimport { LINT_HINT } from \"../errorGuidance.js\";\nimport { raiseError } from \"../raiseError.js\";\nimport { STRUCTURAL_BINDING_TYPE_SET } from \"../structural/define.js\";\nimport { parsePropPart } from \"./parsePropPart.js\";\nimport { parseStatePart } from \"./parseStatePart.js\";\nimport { ParseBindTextResult } from \"./types.js\";\nimport { indexOfOutsideQuotes, splitOutsideQuotes, trimFn } from \"./utils.js\";\n\n// format: propPart:statePart; propPart:statePart; ...\n// special-propPart:\n// if: statePart (single binding for conditional rendering)\n// else: (single binding for conditional rendering, and statePart is ignored)\n// elseif: statePart only (single binding for conditional rendering)\n// for: statePart only (single binding for loop rendering)\n// onclick: statePart, onchange: statePart etc. (event listeners)\n// ...: statePart (spread — expand wcBindable properties+inputs of target object)\n\n/** 左辺に修飾子も入力フィルタも取らない束縛(構造ディレクティブと spread)— 付いていれば拒否する(要件 B4) */\nconst KEYWORDS_WITHOUT_MODIFIERS = new Set<string>([ELSE_KEYWORD, 'if', 'elseif', 'for', SPREAD_PROP]);\n\n/**\n * 明示のプロパティ形(`.name:`)の先頭に置けない語 — 名前空間として読まれる語(要件 B5)。\n * `state`(`VOLUME_INJECTION_PROP`)も含む: `<wcs-state mount>` 上の左辺 `state.<key>:` は\n * 注入の宣言(要件 B14③)なので、`.state.taxRate:` はプロパティか注入か曖昧になる。\n */\nconst EXPLICIT_PROPERTY_REJECTED_HEADS = new Set<string>([\n CLASS_NAMESPACE, ATTR_NAMESPACE, STYLE_NAMESPACE, COMMAND_NAMESPACE, EVENT_TOKEN_NAMESPACE,\n VOLUME_INJECTION_PROP,\n]);\n\n/**\n * `data-wcs` の値をバインディングごとに区切る(前後の空白は残す — tooling が位置を数えられるように)。\n * 引用符の中の `;` は区切りではない(要件 B1 — `join(';')`)。ランタイムと tooling(`@wcstack/state/parser`)で共有する\n */\nexport function splitBindTexts(bindText: string): string[] {\n return splitOutsideQuotes(bindText, BINDING_SEPARATOR);\n}\n\nexport function parseBindTextsForElement(bindText: string): ParseBindTextResult[] {\n const [ ...bindTexts ] = splitBindTexts(bindText).map(trimFn).filter(s => s.length > 0);\n const results = bindTexts.map((bindText): ParseBindTextResult => {\n // 左辺と右辺の区切りも引用符の外だけで探す(要件 B1)。`value|defaults(':'): path` の\n // 引数の中の `:` を区切りとして拾っていた\n const separatorIndex = indexOfOutsideQuotes(bindText, PROP_VALUE_SEPARATOR);\n if (separatorIndex === -1) {\n raiseError(`[wcs/binding-syntax] Invalid bindText: \"${bindText}\". Missing ':' separator between propPart and statePart.${LINT_HINT}`);\n }\n const propPart = bindText.slice(0, separatorIndex).trim();\n const statePart = bindText.slice(separatorIndex + 1).trim();\n // 種別は修飾子・入力フィルタより前の名前で決める(要件 B4)。以前は左辺全体との完全一致で\n // 判定していたので、`radio#ro:` が汎用プロパティに落ちていた。\n // **不変条件**: ここは素の `split` でよい — 取り出すのは最初の区切りより前の**先頭**片で、\n // 引用符を含みうるのは入力フィルタの引数(引用符外の最初の `|` より後ろ)だけなので、\n // `#` も `|` も引用符の中では出会わない。**修飾子の値に引用符を許す拡張を入れるなら\n // `indexOfOutsideQuotes` に替えること**(`parsePropPart.ts` の同じ注記と対)。\n const keyword = propPart.split(MODIFIER_SEPARATOR)[0].split(FILTER_SEPARATOR)[0].trim();\n if (keyword !== propPart && KEYWORDS_WITHOUT_MODIFIERS.has(keyword)) {\n raiseError(`[wcs/binding-syntax] \"${bindText}\": \"${keyword}\" takes no modifiers or filters on its left side — write \"${keyword}:\".${LINT_HINT}`);\n }\n if (propPart === ELSE_KEYWORD) {\n if (statePart.length > 0) {\n // else は値を取らない(要件 B2)。以前は右辺を黙って捨てていた\n raiseError(`[wcs/binding-syntax] \"${bindText}\": \"else\" takes no value — write \"else:\".${LINT_HINT}`);\n }\n const pathInfo = getPathInfo('#else');\n return {\n propName: ELSE_KEYWORD,\n propSegments: [ELSE_KEYWORD],\n propModifiers: [],\n statePathName: '#else',\n statePathInfo: pathInfo,\n inFilters: [],\n outFilters: [],\n bindingType: 'else',\n };\n } else if (propPart === SPREAD_PROP) {\n // 空の右辺は spread 専用の語彙で先に落とす。`parseStatePart` の一般の空パス診断\n // (「the right side of a binding must name a state path」)より、ここでは\n // 「spread target path is required」のほうが直し方を指している\n if (statePart.length === 0) {\n raiseError(`[wcs/binding-syntax] Invalid spread binding \"${bindText}\": spread target path is required.${LINT_HINT}`);\n }\n const stateResult = parseStatePart(statePart);\n if (stateResult.outFilters.length > 0) {\n raiseError(`[wcs/binding-syntax] Invalid spread binding \"${bindText}\": filters are not allowed on spread targets.${LINT_HINT}`);\n }\n return {\n propName: SPREAD_PROP,\n propSegments: [SPREAD_PROP],\n propModifiers: [],\n inFilters: [],\n ...stateResult,\n bindingType: 'spread',\n };\n } else if (propPart === 'if'\n || propPart === 'elseif'\n || propPart === 'for'\n ) {\n const stateResult = parseStatePart(statePart);\n return {\n propName: propPart,\n propSegments: [propPart],\n propModifiers: [],\n inFilters: [],\n ...stateResult,\n bindingType: propPart,\n };\n } else if (keyword === 'radio' || keyword === 'checkbox') {\n // 修飾子(`#ro`・`#onchange` …)と入力フィルタは radio / checkbox のハンドラが読む(要件 B4)\n const stateResult = parseStatePart(statePart);\n const propResult = parsePropPart(propPart);\n return {\n ...propResult,\n ...stateResult,\n bindingType: keyword,\n };\n } else {\n const stateResult = parseStatePart(statePart);\n const propResult = parsePropPart(propPart);\n // 左辺の先頭ドット(`.online:`)は明示のプロパティ形(要件 B5・3.x 計画 D34)。ドットの無い形と\n // 同じ束縛だが、`on` で始まってもイベントにはならない(`online:` は \"line\" イベントを待つ)。\n // 名前空間の語(`.class.x` / `.command.x` …)はプロパティか名前空間か曖昧なので受けない\n if (propResult.propSegments[0] === '' && propResult.propSegments.length > 1) {\n const propSegments = propResult.propSegments.slice(1);\n if (propSegments.includes('') || EXPLICIT_PROPERTY_REJECTED_HEADS.has(propSegments[0])) {\n raiseError(\n `[wcs/binding-syntax] \"${propPart}\": a leading \".\" binds an element property by name — ` +\n `write a non-empty property that is not a namespace (${[...EXPLICIT_PROPERTY_REJECTED_HEADS].join(\", \")}).${LINT_HINT}`,\n );\n }\n return {\n ...propResult,\n propName: propSegments.join(DELIMITER),\n propSegments,\n ...stateResult,\n bindingType: 'prop',\n };\n }\n // eventToken.<prop>: <name> は要素 dispatch を state へ流す pub/sub 配線。\n // 値適用ではないため bindingType 'event' として listener attach 経路に乗せる。\n if (propResult.propSegments[0] === EVENT_TOKEN_NAMESPACE) {\n return {\n ...propResult,\n ...stateResult,\n bindingType: 'event',\n };\n }\n if (propResult.propSegments[0].startsWith(EVENT_PROP_PREFIX)) {\n return {\n ...propResult,\n ...stateResult,\n bindingType: 'event',\n };\n } else {\n return {\n ...propResult,\n ...stateResult,\n bindingType: 'prop',\n };\n }\n }\n });\n // check for sigle binding for 'if', 'elseif', 'else', 'for'\n if (results.length > 1) {\n const isIncludeSingleBinding = results.some(r => STRUCTURAL_BINDING_TYPE_SET.has(r.bindingType));\n if (isIncludeSingleBinding) {\n // lint 側の単独バインディング検査(bindingValidator の structuralMustBeSingle)が\n // 同じケースを検出するため誘導を付ける(三面同語彙)。\n raiseError(`[wcs/template-syntax] Invalid bindText: \"${bindText}\". 'if', 'elseif', 'else', and 'for' bindings must be single binding. Put the structural binding alone in its own data-wcs (e.g. <template data-wcs=\"for: items\">).${LINT_HINT}`);\n }\n }\n return results;\n}\n\n","import { config } from \"../config\";\n\nconst bindTextByNode = new WeakMap<Node, string>();\n\n// format: <!--@@wcs-text:path-->\n// bind-stateはconfig.commentTextPrefixで変更可能\n// format: <!--@@wcs-for:UUID-->\n// bind-stateはconfig.commentForPrefixで変更可能\n// format: <!--@@wcs-if:UUID-->\n// bind-stateはconfig.commentIfPrefixで変更可能\n// format: <!--@@wcs-else:UUID-->\n// bind-stateはconfig.commentElsePrefixで変更可能\n// format: <!--@@wcs-elseif:UUID-->\n// bind-stateはconfig.commentElseIfPrefixで変更可能\nconst bindingTypeKeywordSet: Set<string> = new Set<string>([\n config.commentTextPrefix,\n config.commentForPrefix,\n config.commentIfPrefix,\n config.commentElseIfPrefix,\n config.commentElsePrefix,\n]);\n\n// format: <!--@@:path-->は<!--@@wcs-text:path-->と同義にする\nconst EMBEDDED_REGEX = /*#__PURE__*/ new RegExp(`^\\\\s*@@\\\\s*(.*?)\\\\s*:\\\\s*(.+?)\\\\s*$`);\n\nexport function parseCommentNode(node: Node): string | null {\n const savedText = bindTextByNode.get(node);\n if (typeof savedText === \"string\") {\n return savedText;\n }\n if (node.nodeType !== Node.COMMENT_NODE) {\n return null;\n }\n const commentNode = node as Comment;\n const text = commentNode.data.trim();\n const match = EMBEDDED_REGEX.exec(text);\n if (match === null) {\n return null;\n }\n // 空の場合は wcs-text として扱う\n const keyword = match[1] || config.commentTextPrefix;\n if (!bindingTypeKeywordSet.has(keyword)) {\n return null;\n }\n bindTextByNode.set(node, match[2]);\n return match[2];\n}\n\nexport function getCommentNodeBindText(node: Node): string | null {\n return bindTextByNode.get(node) || null;\n}","import { parseStatePart } from \"./parseStatePart.js\";\nimport { ParseBindTextResult } from \"./types.js\";\n\nexport function parseBindTextForEmbeddedNode(bindText: string): ParseBindTextResult {\n const stateResult = parseStatePart(bindText);\n return {\n propName: 'textContent',\n propSegments: ['textContent'],\n propModifiers: [],\n inFilters: [],\n ...stateResult,\n bindingType: 'text',\n }\n}","import { IInitializeBindingPromise } from \"./types\";\n\nconst bindingPromiseByNode = new WeakMap<Node, IInitializeBindingPromise>();\n// resolve 済みマーク。エントリ未生成のまま resolve されたノードは、後から\n// wait された時に「生成して即 resolve」で追いつく。\nconst resolvedNodes = new WeakSet<Node>();\n\nlet id = 0;\n\nexport function getInitializeBindingPromiseByNode(node: Node): IInitializeBindingPromise {\n let bindingPromise = bindingPromiseByNode.get(node) || null;\n if (bindingPromise !== null) {\n return bindingPromise;\n }\n let resolveFn = undefined;\n const promise = new Promise<void>((resolve) => {\n resolveFn = resolve;\n });\n bindingPromise = {\n id: ++id,\n promise,\n resolve: resolveFn!\n };\n bindingPromiseByNode.set(node, bindingPromise);\n if (resolvedNodes.has(node)) {\n bindingPromise.resolve();\n }\n return bindingPromise;\n}\n\nexport async function waitInitializeBinding(node: Node): Promise<void> {\n const bindingPromise = getInitializeBindingPromiseByNode(node);\n await bindingPromise.promise;\n}\n\nexport function resolveInitializedBinding(node: Node): void {\n // ホットパス: リスト行では全 subscriber ノードがここを通るが、await する消費者\n // (boundComponent / shadowRoot host)はほぼ居ない。既存エントリが無ければ\n // Promise+closure を生成せず resolve 済みマークだけ残す(15 万個級の割り当て削減)。\n const existing = bindingPromiseByNode.get(node);\n if (typeof existing !== \"undefined\") {\n existing.resolve();\n return;\n }\n resolvedNodes.add(node);\n}\n","\nconst cache = new WeakMap<Node, string | null>();\n\nexport function getCustomElement(node: Node): string | null {\n const cached = cache.get(node);\n if (cached !== undefined) {\n return cached;\n }\n let value: string | null = null;\n try {\n if (node.nodeType !== Node.ELEMENT_NODE) {\n return value;\n }\n const element = node as Element;\n const tagName = element.tagName.toLowerCase();\n if (tagName.includes(\"-\")) {\n return value = tagName;\n }\n if (element.hasAttribute(\"is\")) {\n const is = element.getAttribute(\"is\")!;\n if (is.includes(\"-\")) {\n return value = is;\n }\n }\n return value;\n } finally {\n cache.set(node, value);\n }\n}\n","export interface ICustomElementRegistryAdapter {\n get(name: string): CustomElementConstructor | undefined;\n whenDefined(name: string): Promise<CustomElementConstructor>;\n upgrade?(root: Node): void;\n define?(name: string, constructor: CustomElementConstructor): void;\n}\n\nexport interface ICustomElementRegistryOwner {\n /**\n * Scoped registry hook, as exposed by `Element` / `Document` / `ShadowRoot`.\n * `undefined` on platforms without scoped custom element registries; `null`\n * when the node deliberately carries a null registry (a declarative shadow\n * root with `shadowrootcustomelementregistry`, or a document from\n * `createHTMLDocument()`) and has not been handed to `registry.initialize()`.\n */\n readonly customElementRegistry?: unknown;\n /** Legacy owner form: a `Window`-like object carrying a registry. */\n readonly customElements?: unknown;\n}\n\nfunction toAdapter(registry: unknown): ICustomElementRegistryAdapter | null {\n if (typeof registry !== \"object\" || registry === null) return null;\n\n const candidate = registry as Partial<ICustomElementRegistryAdapter>;\n if (typeof candidate.get !== \"function\" || typeof candidate.whenDefined !== \"function\") {\n return null;\n }\n return candidate as ICustomElementRegistryAdapter;\n}\n\n/**\n * Resolve the registry that governs `owner` at operation time, so importing the\n * runtime stays safe when browser globals are absent.\n *\n * Pass the node the operation is about (the bound element, its shadow root):\n * with scoped custom element registries the same tag name can resolve to a\n * different constructor per tree, so \"is this tag defined?\" is only meaningful\n * relative to a node. Nodes on platforms without scoped registries report\n * `undefined` and fall back to the global registry, which keeps every existing\n * caller on today's behaviour.\n */\nexport function getCustomElementRegistry(\n owner: ICustomElementRegistryOwner | Node | null = null,\n): ICustomElementRegistryAdapter | null {\n if (owner !== null && typeof owner !== \"undefined\") {\n const { customElementRegistry: scoped, customElements: owned } =\n owner as ICustomElementRegistryOwner;\n // A node in a null-registry subtree resolves to no registry at all. Falling\n // back to the global one would report globally-defined tags as usable and\n // let us write own properties onto elements that are still un-upgraded --\n // exactly the accessor shadowing the deferred-apply path exists to avoid.\n if (scoped === null) return null;\n if (typeof scoped !== \"undefined\") return toAdapter(scoped);\n if (typeof owned !== \"undefined\") return toAdapter(owned);\n }\n return toAdapter((globalThis as { readonly customElements?: unknown }).customElements);\n}\n\nexport function upgradeCustomElement(\n registry: ICustomElementRegistryAdapter,\n root: Node,\n): void {\n registry.upgrade?.(root);\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/wc-bindable-reader.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\nimport type {\n IWcBindable,\n IWcBindableCommand,\n IWcBindableInput,\n IWcBindableProperty,\n} from \"./wcBindable.js\";\n\nexport const MIN_WC_BINDABLE_VERSION = 1;\n\nexport interface WcBindableElement {\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions,\n ): void;\n readonly constructor: {\n readonly wcBindable: IWcBindable;\n };\n}\n\nexport interface ReadBindableResult {\n readonly target: WcBindableElement;\n readonly liveDeclaration: IWcBindable;\n readonly knownProperties: ReadonlyMap<string, IWcBindableProperty>;\n readonly declaredInputs: ReadonlyMap<string, IWcBindableInput>;\n readonly declaredCommands: ReadonlyMap<string, IWcBindableCommand>;\n}\n\n/**\n * Repository-local conformance mirror of @wc-bindable/core's\n * getWcBindableDeclaration(). Discovery has one path only:\n * target.constructor.wcBindable.\n *\n * The declaration remains live. The maps are read-time indexes and are not a\n * clone, freeze, or normalized replacement for liveDeclaration.\n */\nexport function readBindableDeclaration(target: unknown): ReadBindableResult | null {\n try {\n if (target === null || (typeof target !== \"object\" && typeof target !== \"function\")) {\n return null;\n }\n\n const candidate = target as {\n readonly addEventListener?: unknown;\n readonly removeEventListener?: unknown;\n readonly constructor?: { readonly wcBindable?: IWcBindable };\n };\n const addEventListener = candidate.addEventListener;\n const removeEventListener = candidate.removeEventListener;\n const declaration = candidate.constructor?.wcBindable;\n\n if (typeof addEventListener !== \"function\" || typeof removeEventListener !== \"function\") {\n return null;\n }\n if (declaration?.protocol !== \"wc-bindable\") return null;\n if (!Number.isInteger(declaration.version) || declaration.version < MIN_WC_BINDABLE_VERSION) {\n return null;\n }\n\n const knownProperties = readNamedList(declaration.properties, isValidPropertyDescriptor);\n if (knownProperties === null) return null;\n\n const declaredInputs = declaration.inputs === undefined\n ? new Map<string, IWcBindableInput>()\n : readNamedList(declaration.inputs, isValidInputDescriptor);\n if (declaredInputs === null) return null;\n\n const declaredCommands = declaration.commands === undefined\n ? new Map<string, IWcBindableCommand>()\n : readNamedList(declaration.commands, isValidCommandDescriptor);\n if (declaredCommands === null) return null;\n\n return {\n target: target as WcBindableElement,\n liveDeclaration: declaration,\n knownProperties,\n declaredInputs,\n declaredCommands,\n };\n } catch {\n return null;\n }\n}\n\nfunction isValidPropertyDescriptor(value: unknown): value is IWcBindableProperty {\n if (typeof value !== \"object\" || value === null) return false;\n const descriptor = value as Partial<IWcBindableProperty>;\n if (typeof descriptor.name !== \"string\" || descriptor.name.length === 0) return false;\n if (typeof descriptor.event !== \"string\" || descriptor.event.length === 0) return false;\n return descriptor.getter === undefined || typeof descriptor.getter === \"function\";\n}\n\nfunction isValidInputDescriptor(value: unknown): value is IWcBindableInput {\n if (typeof value !== \"object\" || value === null) return false;\n const descriptor = value as Partial<IWcBindableInput>;\n if (typeof descriptor.name !== \"string\" || descriptor.name.length === 0) return false;\n return descriptor.attribute === undefined || typeof descriptor.attribute === \"string\";\n}\n\nfunction isValidCommandDescriptor(value: unknown): value is IWcBindableCommand {\n if (typeof value !== \"object\" || value === null) return false;\n const descriptor = value as Partial<IWcBindableCommand>;\n if (typeof descriptor.name !== \"string\" || descriptor.name.length === 0) return false;\n return descriptor.async === undefined || typeof descriptor.async === \"boolean\";\n}\n\nfunction readNamedList<T extends { readonly name: string }>(\n value: unknown,\n isValidEntry: (entry: unknown) => entry is T,\n): ReadonlyMap<string, T> | null {\n if (!Array.isArray(value)) return null;\n const entries = new Map<string, T>();\n for (const entry of value) {\n if (!isValidEntry(entry) || entries.has(entry.name)) return null;\n entries.set(entry.name, entry);\n }\n return entries;\n}\n","import { getPathInfo } from \"../address/PathInfo\";\nimport { config } from \"../config\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry, upgradeCustomElement } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\nimport { raiseError } from \"../raiseError\";\nimport { ParseBindTextResult } from \"./types\";\n\nfunction makeExpandedEntry(\n name: string,\n base: string,\n): ParseBindTextResult {\n // Dot-relative spread keeps the loop item root (`.`) without producing `..foo`.\n const expandedPath = base === \".\" ? `.${name}` : `${base}.${name}`;\n return {\n propName: name,\n propSegments: [name],\n propModifiers: [],\n statePathName: expandedPath,\n statePathInfo: getPathInfo(expandedPath),\n inFilters: [],\n outFilters: [],\n bindingType: 'prop',\n };\n}\n\nfunction dedupKey(r: ParseBindTextResult): string | null {\n switch (r.bindingType) {\n case 'prop':\n case 'event':\n case 'radio':\n case 'checkbox':\n return `${r.bindingType}::${r.propName}`;\n case 'spread':\n return null;\n default:\n return null;\n }\n}\n\nexport interface IExpandSpreadOptions {\n /**\n * When false, raise an error if the custom element class is not yet defined.\n * When true (default), leave the spread entry in place so the caller can\n * defer expansion via customElements.whenDefined.\n */\n readonly allowDeferred?: boolean;\n}\n\n/**\n * Expand spread bind-text entries (`...: target`) into per-prop entries\n * by enumerating wcBindable.properties + inputs of the element's class.\n *\n * Behavior:\n * - With `allowDeferred: true` (default): if class is not yet defined, the\n * spread entry stays so the caller can wait via customElements.whenDefined.\n * - With `allowDeferred: false`: raises if class is not defined.\n * - Duplicate propName: last-wins (explicit binding overrides spread).\n * - When config.debug, console.debug logs each override.\n * - Mid-`*` in target path is allowed (e.g. `...: stores.*.fetch`).\n *\n * Composite Profile (COMPOSITE.md / SPEC-extensions § 4) support:\n * - A composite shell exposes its synthesized declaration via the standard\n * `target.constructor.wcBindable` surface (§ 1 Discovery), so this function\n * handles it without any composite-specific code path.\n * - Composed property names use the `<sourceId>.<sourceName>` pattern\n * (e.g. \"s3.progress\"); we keep the dotted name as a single segment so\n * element member access stays flat (element[\"s3.progress\"], not nested).\n * - The expanded state path becomes `targetBase.s3.progress`, which resolves\n * as nested state access — author state as `{ s3: { progress: 0 } }` to\n * mirror the composed structure.\n * - Tier claim (Symbol.for(\"wc-bindable.composite.tiers\")) is not read here;\n * spread covers observation (T1) and writable inputs (T2) transparently\n * through normal property assignment, and commands stay out of spread by\n * design regardless of tier.\n */\nexport function expandSpread(\n node: Node,\n results: ParseBindTextResult[],\n options: IExpandSpreadOptions = {},\n): ParseBindTextResult[] {\n const allowDeferred = options.allowDeferred ?? true;\n if (!results.some(r => r.bindingType === 'spread')) {\n return results;\n }\n const expanded: ParseBindTextResult[] = [];\n const spreadOrigin = new WeakSet<ParseBindTextResult>();\n for (const result of results) {\n if (result.bindingType !== 'spread') {\n expanded.push(result);\n continue;\n }\n if (node.nodeType !== Node.ELEMENT_NODE) {\n raiseError(`Spread binding requires an element node.`);\n }\n const element = node as Element;\n const tagName = getCustomElement(element);\n if (tagName === null) {\n raiseError(`Spread binding \"${result.statePathName}\" requires a custom element with wcBindable, but <${element.tagName.toLowerCase()}> is not a custom element.`);\n }\n const registry = getCustomElementRegistry(element);\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${tagName}>.`);\n }\n const customClass = registry.get(tagName);\n if (typeof customClass === \"undefined\") {\n if (!allowDeferred) {\n raiseError(`Spread binding \"${result.statePathName}\" requires <${tagName}> to be registered. Define the custom element before initializing this binding.`);\n }\n // Deferred: keep spread entry intact; caller retries via whenDefined.\n expanded.push(result);\n continue;\n }\n upgradeCustomElement(registry, element);\n const bindable = readBindableDeclaration(element);\n if (bindable === null) {\n raiseError(`Spread binding \"${result.statePathName}\" requires <${tagName}> to expose a valid wcBindable declaration.`);\n }\n const targetBase = result.statePathName;\n const seen = new Set<string>();\n for (const name of bindable.knownProperties.keys()) {\n if (seen.has(name)) continue;\n seen.add(name);\n const entry = makeExpandedEntry(name, targetBase);\n spreadOrigin.add(entry);\n expanded.push(entry);\n }\n // properties win over inputs when the name overlaps because they carry the\n // full property contract (for example change events).\n for (const name of bindable.declaredInputs.keys()) {\n if (seen.has(name)) continue;\n seen.add(name);\n const entry = makeExpandedEntry(name, targetBase);\n spreadOrigin.add(entry);\n expanded.push(entry);\n }\n }\n // Last-wins de-duplication\n const lastIndexByKey = new Map<string, number>();\n for (let i = 0; i < expanded.length; i++) {\n const key = dedupKey(expanded[i]);\n if (key !== null) {\n lastIndexByKey.set(key, i);\n }\n }\n const final: ParseBindTextResult[] = [];\n for (let i = 0; i < expanded.length; i++) {\n const key = dedupKey(expanded[i]);\n if (key === null) {\n final.push(expanded[i]);\n continue;\n }\n if (lastIndexByKey.get(key) === i) {\n final.push(expanded[i]);\n } else if (config.debug && spreadOrigin.has(expanded[i])) {\n const overrider = expanded[lastIndexByKey.get(key)!];\n const tagText = node.nodeType === Node.ELEMENT_NODE\n ? `<${(node as Element).tagName.toLowerCase()}>`\n : 'node';\n console.debug(`[@wcstack/state] spread: prop \"${expanded[i].propName}\" of ${tagText} overridden by explicit binding (statePath: \"${overrider.statePathName}\").`);\n }\n }\n return final;\n}\n\nexport function hasUnresolvedSpread(results: ParseBindTextResult[]): boolean {\n return results.some(r => r.bindingType === 'spread');\n}\n","export function resolveNodePath(root: Node, path: number[]): Node | null {\n let currentNode: Node | null = root;\n // childNodes[i] ではなく兄弟ポインタで辿る。複製したばかりの行では、childNodes に触れた\n // ノードごとに NodeList(と NodeRareData)が作られ、行の寿命のあいだ残る。行テンプレートの\n // 子は数個なので、辿る歩数は添字の分だけで済む(設計 R5)。\n //\n // 負の添字は `childNodes[-1]`(= undefined → null)とは違い `firstChild` を返す。nodePath は\n // `getNodePath` が実 DOM を数えて作る内部の値で、負の数は生じない(範囲外は `null` で\n // `compileRowPlan` が不適格に倒す)ため、この差は観測されない。\n for (let i = 0; i < path.length; i++) {\n let remaining = path[i];\n currentNode = currentNode.firstChild;\n while (currentNode !== null && remaining > 0) {\n currentNode = currentNode.nextSibling;\n remaining--;\n }\n if (currentNode === null) break;\n }\n return currentNode;\n}\n","/**\n * bindings/planFilters.ts — 束縛計画の段でフィルタの実関数を引く(要件 D16)。\n *\n * 解析の段(`bindTextParser/parseFilters.ts`)は名前と引数しか作らない。実関数は\n * 登録簿(`core/filterRegistry.ts`)から**ここで**引く。未知のフィルタが名指しで落ちるのも\n * ここ — ページの構築時であって、最初の更新の最中ではない。\n *\n * 呼び出し点は 2 つ: 通常経路の `getBindingInfos`(ノードごと)と、行プラン\n * `structural/rowPlan.ts`(テンプレートごとに 1 回、行不変の解決として焼き込む)。\n */\nimport type { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { resolveFilterFn } from \"../core/filterRegistry\";\nimport type { FilterIOType } from \"../filters/types\";\nimport type { IBindingInfo, IFilterInfo, IParsedFilter } from \"../types\";\n\n/** node / replaceNode 以外が確定したバインディング(行プランのスロットが持つ形) */\nexport type IPlannedBinding = Omit<IBindingInfo, \"node\" | \"replaceNode\">;\n\nexport function planFilters(filters: IParsedFilter[], filterIOType: FilterIOType): IFilterInfo[] {\n if (filters.length === 0) {\n // 空配列は共有してよい(フィルタ無しの宣言が大多数)\n return filters as IFilterInfo[];\n }\n const planned: IFilterInfo[] = [];\n for (let i = 0; i < filters.length; i++) {\n const filter = filters[i];\n // `literals`(型付きの値・要件 B9)は**落とさずに持ち回す**。落とすと、これより後ろで\n // フィルタの並びを鍵にする側(`binding/filterKey.ts` — ハンドラ共有キー・束縛キー・\n // devtools の宣言キー)が原文 `args` しか見られず、`defaults(0)` と `defaults('0')` を\n // 取り違えてハンドラを共有してしまう\n const literals = filter.literals ?? filter.args;\n planned.push({\n filterName: filter.filterName,\n args: filter.args,\n literals,\n filterFn: resolveFilterFn(filter.filterName, filter.args, filterIOType, literals),\n });\n }\n return planned;\n}\n\nexport function planBinding(parsed: ParseBindTextResult): IPlannedBinding {\n return {\n ...parsed,\n inFilters: planFilters(parsed.inFilters, \"input\"),\n outFilters: planFilters(parsed.outFilters, \"output\"),\n };\n}\n","import { IBindingInfo } from \"../binding/types\";\n\nconst bindingsByNode = new WeakMap<Node, IBindingInfo[]>();\n\nexport function getBindingsByNode(node: Node): IBindingInfo[] | null {\n return bindingsByNode.get(node) || null;\n}\n\nexport function setBindingsByNode(node: Node, bindings: IBindingInfo[]): void {\n bindingsByNode.set(node, bindings);\n}\n\nexport function addBindingByNode(node: Node, binding: IBindingInfo): void {\n const bindings = getBindingsByNode(node);\n if (bindings === null) {\n setBindingsByNode(node, [binding]);\n } else {\n bindings.push(binding);\n }\n}","/**\n * bindings/lightDomComponentScope.ts — Light DOM の mapped `bind-component` を\n * 「ホストとは別のバインディングスコープ」として扱うための判定\n * (docs/architecture-hardening/15-state-component-mechanism-consistency.md §1.13)。\n *\n * Shadow DOM 形では、コンポーネントの `<wcs-state>` が**別 rootNode** にいることで\n * 2 つのことが同時に成立している。\n *\n * 1. ホスト root の `waitForStateInitialize` の走査集合に入らない\n * 2. 子スコープのバインディングがホストとは別の `buildBindings` パスで処理される\n *\n * Light DOM では両方が失われる。1 が失われると、\n * 「ホストの `waitForStateInitialize` が子 state を待つ →\n * 子 state は自分を束ねるホスト binding を待つ →\n * その binding を作る `initializeBindings` は `waitForStateInitialize` の後」\n * という循環になり、初期化が永久に解決しない。2 が失われると、子スコープの\n * `@name` 参照がホストと同じパスで解決されてしまい、子 state の名前登録より\n * 先に評価される。\n *\n * このモジュールはその 2 つを明示的に復元するための判定だけを持つ。\n *\n * **plain(ホストからバインドしない state 注入)の Light DOM は v2 で廃止**\n *(State._initializeBindWebComponent が raise する — 共有 rootNode に独立ツリーを\n * 置けないため。shadow を付ければ plain Shadow 形として従来どおり動く)。\n * ここの判定が「ホストからバインドされているか」を見るのはその名残ではなく、\n * マウント(配線あり)だけをスコープとして切り出すため。\n */\n\nimport { config } from \"../config\";\n\n/** `<wcs-state bind-component>` が Light DOM の mapped 形(=別スコープ扱い)か。 */\nexport function isLightDomMappedStateElement(stateElement: Element): boolean {\n if (!stateElement.hasAttribute(\"bind-component\")) {\n return false;\n }\n const parentNode = stateElement.parentNode;\n // Shadow DOM 形では parentNode が ShadowRoot になる(かつホスト root の\n // querySelectorAll にはそもそも出てこない)\n if (!(parentNode instanceof Element)) {\n return false;\n }\n // ホストからバインドされていなければ plain。従来どおりの扱いに任せる\n return parentNode.hasAttribute(config.bindAttributeName);\n}\n\n/**\n * `root` の内側にある Light DOM mapped コンポーネント要素を集める。\n *\n * `root` 自身は**含めない**。子スコープが自分のパスとして\n * `initializeBindings(componentElement)` を呼ぶとき、その要素自身まで prune すると\n * 何も初期化されなくなるため。\n */\nexport function findNestedLightDomComponents(root: Document | Element | DocumentFragment): Element[] {\n const components: Element[] = [];\n const stateElements = root.querySelectorAll(`${config.tagNames.state}[bind-component]`);\n for (const stateElement of stateElements) {\n if (!isLightDomMappedStateElement(stateElement)) {\n continue;\n }\n const component = stateElement.parentNode as Element;\n if (component === (root as unknown as Element)) {\n continue;\n }\n components.push(component);\n }\n return components;\n}\n\n/** `node` が、いずれかのコンポーネント要素の**真の**子孫か。 */\nexport function isInsideAnyComponent(node: Node, components: Element[]): boolean {\n for (let i = 0; i < components.length; i++) {\n const component = components[i];\n if (component !== node && component.contains(node)) {\n return true;\n }\n }\n return false;\n}\n","import { config } from \"../config\";\nimport { findNestedLightDomComponents, isInsideAnyComponent } from \"./lightDomComponentScope\";\nimport { parseCommentNode } from \"./parseCommentNode\";\n\n/**\n * data-wcs 属性または埋め込みノード<!--{{}}-->を持つノードをすべて取得する\n *\n * Light DOM の mapped コンポーネントの**内側**は除外する(§1.13)。そのサブツリーの\n * `@name` 参照は、コンポーネント側の state が名前登録を済ませてからでないと解決できず、\n * ホストと同じパスで拾うと登録前に評価されてしまう。除外したぶんは、その state が\n * 初期化を終えた時点で自分のスコープとして `initializeBindings(componentElement)` を\n * 呼び直す(Shadow DOM 形で rootNode ごとにパスが分かれるのと同じ形にする)。\n *\n * コンポーネント要素**自身**は除外しない。ホスト側の `data-wcs`(`state.msg: user.name`)\n * はホストのスコープに属し、それが張られることで子側の待ちが解ける。\n *\n * @param root\n * @returns\n */\n\nexport function getSubscriberNodes(root: Document | Element | DocumentFragment): Node[] {\n const subscriberNodes: Node[] = [];\n const nestedComponents = findNestedLightDomComponents(root);\n const walker = document.createTreeWalker(\n root, \n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT, \n {\n acceptNode(node: Node) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as Element;\n const hasBinding = element.hasAttribute(config.bindAttributeName);\n return hasBinding\n ? NodeFilter.FILTER_ACCEPT\n : NodeFilter.FILTER_SKIP;\n } else {\n // Comment node\n return parseCommentNode(node) !== null\n ? NodeFilter.FILTER_ACCEPT \n : NodeFilter.FILTER_SKIP;\n }\n }\n }\n );\n \n while (walker.nextNode()) {\n const node = walker.currentNode;\n // TreeWalker の acceptNode は「自分は拾うが子孫は辿らない」を表現できないため、\n // コンポーネント要素自身を拾ったうえで、その子孫をここで落とす。\n // nestedComponents が空(=圧倒的多数)のときは contains 走査ごと発生しない。\n if (nestedComponents.length > 0 && isInsideAnyComponent(node, nestedComponents)) {\n continue;\n }\n subscriberNodes.push(node);\n }\n return subscriberNodes;\n}","import { expandSpread, hasUnresolvedSpread } from \"../bindTextParser/expandSpread\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { raiseError } from \"../raiseError\";\nimport { resolveNodePath } from \"../structural/resolveNodePath\";\nimport { IFragmentNodeInfo } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\nimport { getBindingInfos } from \"./getBindingInfos\";\nimport { setBindingsByNode } from \"./getBindingsByNode\";\nimport { getParseBindTextResults } from \"./getParseBindTextResults\";\nimport { getSubscriberNodes } from \"./getSubscriberNodes\";\nimport { resolveInitializedBinding } from \"./initializeBindingPromiseByNode\";\n\nconst registeredNodeSet = new WeakSet<Node>();\n\n/**\n * パース結果の変換フック(Phase 2 のマウント — impl-plan §3-0 の 1)。\n * マウントされたスコープの収集は、これで各パース結果を親ツリーの絶対パスへ書き換える。\n * `uuid` を持つエントリ(構造フラグメントの参照)には掛けない — フラグメント側の\n * パース結果は登録時(collectStructuralFragments)に変換済みで、二重に掛けると\n * 接頭辞が二重になる。\n */\nexport type ParseResultTransform = (parsed: ParseBindTextResult, forPath?: string) => ParseBindTextResult;\n\nfunction applyTransform(\n parseResults: ParseBindTextResult[],\n transform: ParseResultTransform | undefined,\n): ParseBindTextResult[] {\n if (typeof transform === \"undefined\") {\n return parseResults;\n }\n return parseResults.map((parsed) => (parsed.uuid != null ? parsed : transform(parsed)));\n}\n\nexport interface IDeferredSpreadEntry {\n readonly node: Node;\n readonly tagName: string;\n readonly parseResults: ParseBindTextResult[];\n readonly transform?: ParseResultTransform;\n /** 予約中の定義待ちの取り消し(`scheduleDeferredSpreads` が持つ。行の活性化し直しで待ちを重ねない) */\n cancel?: () => void;\n}\n\nfunction processParseResultsForNode(\n node: Node,\n parseResults: ParseBindTextResult[],\n options: { allowDeferred: boolean },\n transform?: ParseResultTransform,\n): { bindings: IBindingInfo[], deferred: IDeferredSpreadEntry | null } {\n const expanded = expandSpread(node, parseResults, { allowDeferred: options.allowDeferred });\n if (hasUnresolvedSpread(expanded)) {\n const tagName = node.nodeType === Node.ELEMENT_NODE\n ? getCustomElement(node as Element)\n : null;\n if (tagName === null) {\n raiseError(`Spread binding deferred but element is not a custom element.`);\n }\n return { bindings: [], deferred: { node, tagName, parseResults, transform } };\n }\n registeredNodeSet.add(node);\n // 変換は spread 展開の**後**(展開されたプロパティごとのパスに掛かる)\n const bindings = getBindingInfos(node, applyTransform(expanded, transform));\n setBindingsByNode(node, bindings);\n resolveInitializedBinding(node);\n return { bindings, deferred: null };\n}\n\nexport function collectNodesAndBindingInfos(\n root: Document | Element | DocumentFragment,\n transform?: ParseResultTransform,\n): [ Node[], IBindingInfo[], IDeferredSpreadEntry[] ] {\n return collectNodesAndBindingInfosOf(getSubscriberNodes(root), transform);\n}\n\n/**\n * 購読ノードの列を受け取る版。SSR のハイドレーション(ssr/hydrateBindings.ts)が、生きている\n * ブロックのノード列を**動かさずに**集めるのに使う(根を要求する上の版に掛けるには一時的な\n * 要素へ移すしかなく、移すとブロックの中のカスタム要素が切断・再接続される — #258)。\n */\nexport function collectNodesAndBindingInfosOf(\n subscriberNodes: Node[],\n transform?: ParseResultTransform,\n): [ Node[], IBindingInfo[], IDeferredSpreadEntry[] ] {\n const allBindings: IBindingInfo[] = [];\n const deferredSpreads: IDeferredSpreadEntry[] = [];\n for(const node of subscriberNodes) {\n if (registeredNodeSet.has(node)) continue;\n const parseResults = getParseBindTextResults(node);\n const result = processParseResultsForNode(node, parseResults, { allowDeferred: true }, transform);\n if (result.deferred !== null) {\n deferredSpreads.push(result.deferred);\n continue;\n }\n allBindings.push(...result.bindings);\n }\n return [subscriberNodes, allBindings, deferredSpreads];\n}\n\nexport function collectNodesAndBindingInfosByFragment(\n root: DocumentFragment,\n nodeInfos: IFragmentNodeInfo[],\n): [ Node[], IBindingInfo[], IDeferredSpreadEntry[] ] {\n const nodes: Node[] = [];\n const allBindings: IBindingInfo[] = [];\n const deferredSpreads: IDeferredSpreadEntry[] = [];\n for(const nodeInfo of nodeInfos) {\n const node = resolveNodePath(root, nodeInfo.nodePath);\n if (node === null) {\n raiseError(`Node not found by path [${nodeInfo.nodePath.join(', ')}] in fragment.`);\n }\n if (registeredNodeSet.has(node)) continue;\n const result = processParseResultsForNode(node, nodeInfo.parseBindTextResults, { allowDeferred: true });\n // 未定義カスタム要素への spread は行の活性化が定義待ちへ予約する(#330。ルートと同じ約束)。\n // ノードは行のノードの列に入れる — 行のループ文脈はこの列に張られ、展開した束縛がそれを読む。\n // 行のノードとして台帳にも載せる — 祖先の走査し直し(binder)がルートの待ちとして二重に予約しない\n if (result.deferred !== null) {\n deferredSpreads.push(result.deferred);\n registeredNodeSet.add(node);\n }\n allBindings.push(...result.bindings);\n nodes.push(node);\n }\n return [nodes, allBindings, deferredSpreads];\n}\n\n/**\n * The nodes of the list not collected yet (`initializeBindings`, #414). A collected node is bound already\n * — by an earlier walk, or as a row's node — and its loop context is not to be touched again.\n */\nexport function uncollectedNodes(nodes: Node[]): Node[] {\n return nodes.filter((node) => !registeredNodeSet.has(node));\n}\n\nexport function unregisterNode(node: Node): void {\n registeredNodeSet.delete(node);\n}\n\n/**\n * RowPlan 経路(createContent のプラン実体化)用。パース・spread 展開を経ずに\n * binding を組み立てた subscriber ノードを二重処理防止台帳へ載せる\n * (後続の collectNodesAndBindingInfos による再スキャンから保護)。\n */\nexport function markNodeRegistered(node: Node): void {\n registeredNodeSet.add(node);\n}\n\n/**\n * Re-process a deferred spread entry once the custom element class is\n * registered. Expands the captured parseResults, installs bindings, and\n * returns them so the caller can attach handlers and apply state values.\n */\nexport function processDeferredNode(entry: IDeferredSpreadEntry): IBindingInfo[] {\n const { node, parseResults, transform } = entry;\n unregisterNode(node);\n const result = processParseResultsForNode(node, parseResults, { allowDeferred: false }, transform);\n return result.bindings;\n}\n","import { IBindingInfo } from \"../types\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\n// 束縛計画の段でフィルタの実関数を引く(要件 D16)。実装は `planFilters.ts` の 1 本だけ —\n// かつてこのファイルが逐語のコピーを持っていて、両方がバンドルに載っていた\nimport { planFilters } from \"./planFilters\";\n\nexport function getBindingInfos(node: Node, parseBindingTextResults: ParseBindTextResult[]): IBindingInfo[] {\n const bindingInfos: IBindingInfo[] = [];\n for (const parseBindingTextResult of parseBindingTextResults) {\n const inFilters = planFilters(parseBindingTextResult.inFilters, \"input\");\n const outFilters = planFilters(parseBindingTextResult.outFilters, \"output\");\n if (parseBindingTextResult.bindingType !== 'text') {\n bindingInfos.push({\n ...parseBindingTextResult,\n inFilters,\n outFilters,\n node: node,\n replaceNode: node,\n });\n } else {\n // フラグメント登録時に事前正規化済みの Text ノードはそのまま replaceNode に\n // 使う(node === replaceNode なら replaceToReplaceNode は no-op)。\n // 実 DOM 上の wcs-text コメント(非フラグメント経路)は従来どおり\n // 空 Text を生成して実行時に差し替える。\n const replaceNode = node.nodeType === Node.TEXT_NODE\n ? node\n : document.createTextNode('');\n bindingInfos.push({\n ...parseBindingTextResult,\n inFilters,\n outFilters,\n node: node,\n replaceNode: replaceNode,\n });\n }\n }\n return bindingInfos;\n}\n","import { ILoopContext } from \"./types\";\n\nconst loopContextByNode = new WeakMap<Node, ILoopContext>();\n\n// 親を持たない ShadowRoot で探索を続けるか。マウントされたスコープ根はホストへ抜ける\n// (webComponent/mount.ts が記録の登録時に注入する)。未注入なら従来どおり境界で止まる —\n// 走るのは探索が ShadowRoot に達した 1 回だけなので、大域の受け口でも hot path には載らない\nlet mountedScopeHost: ((root: ShadowRoot) => Node | null) | null = null;\n\nexport function setMountedScopeHost(resolver: (root: ShadowRoot) => Node | null): void {\n mountedScopeHost = resolver;\n}\n\nexport function getLoopContextByNode(node: Node): ILoopContext | null {\n let paramNode: Node | null = node;\n while (paramNode) {\n const loopContext = loopContextByNode.get(paramNode);\n if (loopContext) {\n return loopContext;\n }\n let next: Node | null = paramNode.parentNode;\n if (next === null && mountedScopeHost !== null && paramNode instanceof ShadowRoot) {\n // マウントされた ShadowRoot はホストのループ文脈を継承する(impl-plan §3-0 の 3)。\n // ホスト行の listIndex [i] が子スコープの `for` の親になり、内側の行は [i, j] を\n // 作る — 絶対パスのワイルドカード数 = listIndex 段数(設計書 §4-4)がこれで成立し、\n // v1 の crossBoundaryAddress / baseListIndex(Δ の帳簿)は要らなくなる。\n // マウントされていない ShadowRoot(plain コンポーネント・通常の Shadow ツリー)は\n // 従来どおり境界で止まる(resolver が null を返す)。\n next = mountedScopeHost(paramNode);\n }\n paramNode = next;\n }\n return null;\n}\n\nexport function setLoopContextByNode(node: Node, loopContext: ILoopContext | null): void {\n if (loopContext === null) {\n loopContextByNode.delete(node);\n return;\n }\n loopContextByNode.set(node, loopContext);\n}\n","\nlet count = 0;\nexport function getUUID(): string {\n return `u${(count++).toString(36)}`;\n}\n","import { getUUID } from \"../getUUID\";\nimport { IListIndex } from \"./types\";\n\nlet version = 0;\n/**\n * 親の付け替え(#256 の修理)の世代。`listIndexes` の WeakRef 連鎖は一度組んだら\n * 作り直されないので、祖先が付け替わったら子孫のキャッシュも無効にする必要がある。\n * `dirty`(version 比較)は `indexes` の再構築が消費してしまうため、連鎖専用の世代を持つ。\n */\nlet chainGeneration = 0;\n\n/** 値が一度も記録されていない行の印(`undefined` を持つ行と区別するため)。 */\nconst NO_VALUE = Symbol(\"wcs.listIndex.noValue\");\n\nclass ListIndex implements IListIndex {\n readonly uuid = getUUID();\n parentListIndex: IListIndex | null;\n readonly position: number;\n readonly length: number;\n\n private _index: number;\n private _version: number;\n private _indexes: number[] | undefined;\n private _listIndexes: WeakRef<IListIndex>[] | undefined;\n private _chainGeneration: number;\n /**\n * この行集合を最初に展開した親(`home`・#256)。付け替えても変わらない。退役した親から\n * 付け替えたあと、その親が戻ってきたら戻す先になる。1 組の行集合に home は 1 つ — 別の配列(写し)へ\n * 引き継いだ行集合は、引き継いだ親を home にする(`createListDiff` の rehomeListIndex・#394。前の home は\n * 新しい配列を持ったことが無い)。\n */\n private _homeParentListIndex: IListIndex | null;\n\n /**\n * この行が表しているリスト要素(#256)。差分が返すたびに付け直す。\n * 「同じ行が戻ってきた」を配列インスタンスをまたいで言えるのはこの値だけ ──\n * 行を戻す普通のやり方(新しい配列に同じ要素を並べ直す)は ListIndex を作り直すので、\n * 行オブジェクトの identity では判定できない。\n */\n private _value: unknown;\n\n /**\n * 行の下のキャッシュの印(#389)。行の下の値(`items.*.name`)のキャッシュは載せたときの印を持ち、\n * 印が進んだ行の項目は読みで外れる。行の要素・途中の値が変わったら、子のパスを 1 つずつ無効にする\n * 代わりに印を 1 つ進める(cache/cacheEntryByAbsoluteStateAddress.ts)。\n */\n cacheStamp = 0;\n\n /** 要素オブジェクトの索引が持つ、この行への弱い参照(rowsByElement・#393。載せたときに作る) */\n ref: WeakRef<ListIndex> | undefined;\n\n /**\n * Creates a new ListIndex instance.\n *\n * @param parentListIndex - Parent list index for nested loops, or null for top-level\n * @param index - Current index value in the loop\n * @param homeParentListIndex - Parent this row's set belongs to (#256)\n */\n constructor(parentListIndex: IListIndex | null, index: number, homeParentListIndex: IListIndex | null) {\n this.parentListIndex = parentListIndex;\n this.position = parentListIndex ? parentListIndex.position + 1 : 0;\n this.length = this.position + 1;\n this._homeParentListIndex = homeParentListIndex;\n this._value = NO_VALUE;\n this._index = index;\n this._version = version;\n this._chainGeneration = chainGeneration;\n }\n\n /**\n * Gets current index value.\n *\n * @returns Current index number\n */\n get index() {\n return this._index;\n }\n\n /**\n * Sets index value and updates version.\n *\n * @param value - New index value\n */\n set index(value: number) {\n this._index = value;\n this._version = ++version;\n this.indexes[this.position] = value;\n }\n\n /**\n * Gets current version number for change detection.\n *\n * @returns Version number\n */\n get version(): number {\n return this._version;\n }\n\n /** 行集合を最初に展開した親(付け替えても変わらない)。 */\n get homeParentListIndex(): IListIndex | null {\n return this._homeParentListIndex;\n }\n\n set homeParentListIndex(home: IListIndex | null) {\n this._homeParentListIndex = home;\n }\n\n /** この行が表しているリスト要素(未記録なら `NO_VALUE`)。 */\n get value(): unknown {\n return this._value;\n }\n\n set value(value: unknown) {\n this._value = value;\n }\n\n /**\n * Checks if parent indexes have changed since last access.\n *\n * @returns true if parent has newer version, false otherwise\n */\n get dirty(): boolean {\n if (this.parentListIndex === null) {\n return false;\n } else {\n return this.parentListIndex.dirty || this.parentListIndex.version > this._version;\n }\n }\n\n /**\n * Gets array of all index values from root to current level.\n * Rebuilds array if parent indexes have changed (dirty).\n *\n * @returns Array of index values\n */\n get indexes(): number[] {\n if (this.parentListIndex === null) {\n if (typeof this._indexes === \"undefined\") {\n this._indexes = [this._index];\n }\n } else {\n if (typeof this._indexes === \"undefined\" || this.dirty) {\n this._indexes = [...this.parentListIndex.indexes, this._index];\n this._version = version;\n }\n }\n return this._indexes;\n }\n\n /**\n * Gets array of WeakRef to all ListIndex instances from root to current level.\n *\n * @returns Array of WeakRef<IListIndex>\n */\n get listIndexes(): WeakRef<IListIndex>[] {\n if (this.parentListIndex === null) {\n if (typeof this._listIndexes === \"undefined\") {\n this._listIndexes = [new WeakRef(this)];\n }\n } else {\n if (typeof this._listIndexes === \"undefined\" || this._chainGeneration !== chainGeneration) {\n this._listIndexes = [...this.parentListIndex.listIndexes, new WeakRef(this)];\n this._chainGeneration = chainGeneration;\n }\n }\n return this._listIndexes;\n }\n\n /**\n * Gets variable name for this loop index ($1, $2, etc.).\n *\n * @returns Variable name string\n */\n get varName(): string {\n return `$${this.position + 1}`;\n }\n\n /**\n * Gets ListIndex at specified position in hierarchy.\n * Supports negative indexing from end.\n *\n * @param pos - Position index (0-based, negative for from end)\n * @returns ListIndex at position or null if not found/garbage collected\n */\n /**\n * 退役した親を、同じ深さの生きた親へ差し替える(#256)。**行の identity は保つ**ので、\n * 描画済み content も、その行に紐づくバインドしていない DOM の状態も残る。\n * 添字の値は親が変われば変わりうる(並べ替えを伴う置換)ため、`indexes` と WeakRef 連鎖を\n * 捨て、version を進めて子孫の `dirty` を立てる。`_homeParentListIndex` は動かさない\n * ── 外した行が戻ってきたときに持ち主を返す先だから。\n */\n reparent(parentListIndex: IListIndex | null): void {\n this.parentListIndex = parentListIndex;\n this._indexes = undefined;\n this._listIndexes = undefined;\n this._version = ++version;\n chainGeneration++;\n }\n\n at(pos: number): IListIndex | null {\n if (pos >= 0) {\n return this.listIndexes[pos]?.deref() || null;\n } else {\n return this.listIndexes[this.listIndexes.length + pos]?.deref() || null;\n }\n }\n}\n\n/**\n * Factory function to create ListIndex instance.\n *\n * @param parentListIndex - Parent list index for nested loops, or null for top-level\n * @param index - Current index value in the loop\n * @param homeParentListIndex - Row set this row joins (#256); defaults to the minting parent\n * @returns New IListIndex instance\n */\nexport function createListIndex(\n parentListIndex: IListIndex | null,\n index: number,\n homeParentListIndex: IListIndex | null = parentListIndex,\n): IListIndex {\n return new ListIndex(parentListIndex, index, homeParentListIndex);\n}\n\n/**\n * 台帳(`listIndexesByList`)専用の入口。行は必ずこのモジュールが鋳造した実体なので、\n * 到達不能な防御分岐を置かずに直接呼ぶ。\n */\nexport function reparentListIndex(listIndex: IListIndex, parentListIndex: IListIndex | null): void {\n (listIndex as ListIndex).reparent(parentListIndex);\n}\n\n/**\n * 台帳専用の入口その 2。行集合の home を読む(`IListIndex` を広げないための cast ──\n * この型は dist/index.d.ts に出るので、内部だけの都合で公開面を増やさない)。\n */\nexport function getHomeParentListIndex(listIndex: IListIndex): IListIndex | null {\n return (listIndex as ListIndex).homeParentListIndex;\n}\n\n/** 台帳専用の入口その 2'。行集合を別の配列へ引き継いだ親を home にする(createListDiff・#394) */\nexport function rehomeListIndex(listIndex: IListIndex, home: IListIndex | null): void {\n (listIndex as ListIndex).homeParentListIndex = home;\n}\n\n/**\n * キャッシュ専用の入口。行の下のキャッシュの印を読む(行の無いアドレスは undefined — #389)。\n * 載せるときと読むときの両方がこれで引くので、行の無いアドレスの項目は印の比較で外れない。\n */\nexport function getRowCacheStamp(listIndex: IListIndex | null): number | undefined {\n return (listIndex as ListIndex | null)?.cacheStamp;\n}\n\n/** キャッシュ専用の入口その 2。行の下のキャッシュをまとめて無効にする(#389) */\nexport function advanceRowCacheStamp(listIndex: IListIndex): void {\n (listIndex as ListIndex).cacheStamp++;\n}\n\n/**\n * 台帳専用の入口その 3。差分が返した行に、その行が表している要素を憶えさせる(#256)。\n * 要素の書き込みがその場で行の要素を替えたときも呼ぶ(setByAddress の _setByAddressWithSwap・#359)。\n * 前に憶えていた要素と違えば真を返す — 差分がこれを見て、行はそのままで要素だけが替わった行を\n * 描き直させる(createListDiff の syncListIndexes)。\n */\nexport function setListIndexValue(listIndex: IListIndex, value: unknown): boolean {\n const row = listIndex as ListIndex;\n const previous = row.value;\n const changed = previous !== NO_VALUE && !Object.is(previous, value);\n if (previous !== value) {\n rowsByElement.get(previous as object)?.delete(row.ref!);\n rememberRowOfElement(value, row);\n }\n row.value = value;\n return changed;\n}\n\n/**\n * 要素オブジェクト → それを表している入れ子のリストの行(#393)。同じ要素オブジェクトは別の行にも居る — 同じ配列の\n * 2 つの位置、共有された配列の写し(ほかの外側の行がまだ持つ配列の写しは、行を借りずに新しい行を作る — createListDiff)。\n * 行の下への書き込み(`groups.1.items.0.v`)は、同じ要素を表す別の行のアドレスにも知らせる(setByAddress の notifyWrite)。\n * 行は弱く持つ — 外側の行ごと外した行・捨てた state の行は差分を通らず退役の印も付かないので、強く持つと要素が生きている\n * 間ずっと残った(外側の行を不変更新するたびに内側の行の数だけ増えた)。集合は前に見直した大きさの倍に育ったときに、消えた\n * 行と、退役した行・退役した外側の行の下の行を外す — 消えた行だけを外すと、GC までの間、外側の行を消して戻すたびに集合が\n * 育った(500 回で 501)。ルート直下の行は載せない(別の行を引くのは入れ子の行の下への書き込みだけ)\n */\nconst rowsByElement = new WeakMap<object, Set<WeakRef<ListIndex>>>();\nconst pruneSizeByRows = new WeakMap<Set<WeakRef<ListIndex>>, number>();\n\nfunction rememberRowOfElement(element: unknown, row: ListIndex): void {\n if (typeof element !== \"object\" || element === null || row.parentListIndex === null) {\n return;\n }\n let held = rowsByElement.get(element);\n if (typeof held === \"undefined\") {\n held = new Set();\n rowsByElement.set(element, held);\n } else if (held.size >= (pruneSizeByRows.get(held) ?? 8)) {\n liveRowsOf(held, row, true);\n pruneSizeByRows.set(held, held.size * 2 + 8);\n }\n held.add(row.ref ??= new WeakRef(row));\n}\n\n/** 集合の生きている行のうち `row` でないもの(消えた行は外す。`stale` なら退役した行・その下の行も外す) */\nfunction liveRowsOf(held: Set<WeakRef<ListIndex>> | undefined, row: ListIndex, stale = false): ListIndex[] {\n const rows: ListIndex[] = [];\n held?.forEach((ref) => {\n const other = ref.deref();\n if (typeof other === \"undefined\" || (stale && isUnderRetiredRow(other))) {\n held.delete(ref);\n } else if (other !== row) {\n rows.push(other);\n }\n });\n return rows;\n}\n\n/** 同じ要素オブジェクトを表している別の行(台帳専用の入口その 4 — list/listIndexesByList.ts の getElementAliases) */\nexport function getRowsOfSameElement(listIndex: IListIndex): ListIndex[] {\n return liveRowsOf(rowsByElement.get((listIndex as ListIndex).value as object), listIndex as ListIndex);\n}\n\n/**\n * 差分で `newIndexes` から外れた行 = 消費者が画面から外した行(list/listIndexesByList.ts の retireListIndexes /\n * reviveListIndexes が付け外しする)。「生きた親集合に属さない」の判定材料。要素の索引の見直しも引くのでここに置く\n */\nexport const retiredListIndexes = new WeakSet<IListIndex>();\n\n/** 行か、その祖先の行が退役しているか */\nexport function isUnderRetiredRow(listIndex: IListIndex | null): boolean {\n for (let row = listIndex; row !== null; row = row.parentListIndex) {\n if (retiredListIndexes.has(row)) {\n return true;\n }\n }\n return false;\n}\n\n/** 行が表しているリスト要素(未記録なら undefined ではなく内部の印 — 台帳専用の入口その 5・list/listIndexesByList.ts の covers) */\nexport function getListIndexValue(listIndex: IListIndex): unknown {\n return (listIndex as ListIndex).value;\n}\n\n/**\n * 2 つの行が**同じリスト要素**を表しているか(#256)。\n * 差分を通っていない行(`hydrateBindings` / `setByAddress` が鋳造する行)は値を持たないので、\n * 未記録どうしは「同じ」と見なさない ── 値の無い行を取り違えて付け替えないため。\n * 行を書き換えない読むだけの判定なので、台帳の外からも使う: `$scan` の drain が、行のアドレスが\n * いまその位置の要素を表しているかを見る(scan/scanRuntime.ts の placementOf)。\n */\nexport function isSameListIndexValue(listIndex: IListIndex, other: IListIndex): boolean {\n const value = (listIndex as ListIndex).value;\n return value !== NO_VALUE && value === (other as ListIndex).value;\n}\n","/**\n * updater/updateBatch.ts\n *\n * 次に drain されるバッチの番号(updater が drain を始めるたびに進める)。書き込みが同じバッチのものかを\n * 見る側が読む — 要素書き込みの入れ替えの、揃う前の書き込み(proxy/methods/setByAddress.ts・#361)と、\n * 行はそのままで要素が替わった行の差分(list/createListDiff.ts・#359)。\n * updater は描画の適用を読み込むので、list/ から updater.ts を読むと循環する。番号だけを葉のモジュールに置く。\n */\nexport let updateBatch = 0;\n\n/** drain を始めた(updater 専用) */\nexport function advanceUpdateBatch(): void {\n updateBatch++;\n}\n","/**\n * 要素書き込みの入れ替えが揃ったとき、`for` の描画基準に据える「書き込む前の並びの写し」の印(#4)。\n *\n * `for` はこの写しとの差分でだけ、同じ位置で外す行と入る行の Content をその場で使い回す\n * (applyChangeToFor の collectInPlaceContents)。配列の置換の差分は、これまでどおり外した行の\n * Content をプールに通す。\n */\nconst swapBaselineLists = new WeakSet<object>();\n\nexport function markSwapBaselineList(list: readonly unknown[]): void {\n swapBaselineLists.add(list);\n}\n\nexport function isSwapBaselineList(list: unknown): boolean {\n return swapBaselineLists.has(list as object);\n}\n","/**\n * list/listIndexesByList.ts\n *\n * 行(`IListIndex`)の正本台帳。1 本の配列につき行集合は **1 組**。\n *\n * #256 が扱うのは「共有」ではなく「陳腐化」である。台帳はこの 2 つを分ける:\n *\n * - **生きた共有** ── 1 本の配列が 2 つの生きた親から到達できる形。行集合は 1 組のまま\n * 全員で共有する(どの親から読んでも同じ値が見える)。親ごとに私有の行集合を持たせると\n * 同じスロットに 2 本の絶対アドレスができ、片方へ書いた値がもう片方から**永久に**\n * 見えなくなる。共有そのものの帰結(親を読む getter が持ち主の行の文脈で評価される・\n * 1 スロットへ到達経路の数だけ書かれる)は残るが、それはデータが実際に共有されている\n * ことの帰結であって、**もう存在しない古い値**ではない。\n * - **陳腐化** ── 行オブジェクトだけを作り直す置換(`nodes.map(n => ({...n}))` は\n * `children` を参照ごと引き継ぐ)で、台帳の行がぶら下がる親が**退役した**形。読み手は\n * 新しい行の絶対アドレスを見るのに、書き手は行の親ポインタを遡って旧行の絶対アドレスを\n * dirty にするので、葉への書き込みが集計へ届かない(#256)。外側の行が内側のパスに別の値を書いて、前の配列を\n * **手放した**形も同じ(#394 — releaseListAtParent)。\n *\n * 判別は「台帳の行が持つ親が、生きた親集合に属するか」。属さないときだけ、**行の identity を\n * 保ったまま**新しい親へ付け替える(`reparentListIndex`)。作り直さないのは、消費者が\n * 描画済み content を行 ListIndex の identity で持っているため ── 作り直すと、著者が何も\n * 間違えていないページで行の DOM が丸ごと失われる(`<details>` の開閉のような、バインド\n * していない状態ごと)。\n *\n * 退役の signal は差分の `deleteIndexSet`(=エンジン自身が「この行はもう無い」と決めた\n * 集合)で、**復活の signal は同じ差分の `newIndexes`**。印は差分ごとに付け直され、\n * 消えない印は残らない(`retireListIndexes` / `reviveListIndexes` を `createListDiff` が\n * 対で呼ぶ)。\n *\n * 付け替えは**一方通行ではない**。行は自分の行集合を最初に展開した親(`home`)を憶えていて、\n * その home が**リストに戻ってきたら**持ち主を返す。これが無いと「行を削除して戻す」ページで\n * 持ち主が隣の行に移ったまま固定され、削除の履歴によって集計が凍る行が変わってしまう。\n *\n * 戻ってきたかどうかは **行オブジェクト(ListIndex)の identity ではなく、行が表している\n * リスト要素の identity** で判定する。同じ配列インスタンスを戻す綴りなら home そのものが\n * 生き返るが、行を戻す普通のやり方(新しい配列に同じ要素を並べ直す)では差分が ListIndex を\n * 作り直すので、ListIndex の identity で見ると home は永久に退役したままになる。\n * 要素そのものを作り直した行は**別の行**なので home には一致しない。生き残った行が\n * 1 つでもあればそちらへ戻るが、**全ての行を作り直す**綴り(`map(n => ({...n}))`)では\n * どの要素も一致せず、退役した親からの付け替えが位置に対して働く。\n */\nimport { createListIndex, getHomeParentListIndex, getListIndexValue, getRowsOfSameElement, isSameListIndexValue, isUnderRetiredRow, reparentListIndex, retiredListIndexes, setListIndexValue } from \"./createListIndex\";\nimport { IListIndex } from \"./types\";\nimport { updateBatch } from \"../updater/updateBatch\";\nimport { isSwapBaselineList, markSwapBaselineList } from \"./swapBaselineList\";\n\nconst listIndexesByList = new WeakMap<readonly unknown[], IListIndex[]>();\n\n/** 差分が捨てた行を退役として記録する(`createListDiff` が呼ぶ)。 */\nexport function retireListIndexes(listIndexes: Iterable<IListIndex>): void {\n for (const listIndex of listIndexes) {\n retiredListIndexes.add(listIndex);\n }\n}\n\n/**\n * 差分が「いま生きている」と返した行の退役印を落とす(`createListDiff` が呼ぶ)。\n * 同じ配列インスタンスを戻す・タブを切り替えて戻る等で、退役した行は実際に生き返る。\n */\nexport function reviveListIndexes(listIndexes: Iterable<IListIndex>): void {\n for (const listIndex of listIndexes) {\n retiredListIndexes.delete(listIndex);\n }\n}\n\n/**\n * 差分がリストから外し、まだ戻っていない行か。読むだけの判定で、`$scan` の drain が\n * 行のアドレスの指す行がもうリストに居ないかを見る(scan/scanRuntime.ts の placementOf)。\n */\nexport function isRetiredListIndex(listIndex: IListIndex): boolean {\n return retiredListIndexes.has(listIndex);\n}\n\n/**\n * 外側の行 → その行が内側のパスから手放した配列(#394)。外側の行の内側のパスへ別の配列を書くと(setByAddress)、\n * 前の配列の行がその外側の行を親に持っていても、その行はもうその配列を持たない。退役した親と同じく付け替えの元に\n * なり、戻り先(home)にもならない。同じ配列を書き戻したら外す(holdListAtParent)。\n */\nconst releasedListsByParent = new WeakMap<IListIndex, WeakSet<readonly unknown[]>>();\n\n/**\n * 外側の行 `parentListIndex` の内側のパス(`holder` の `key`)が、配列 `list` から別の値に替わった(setByAddress)。\n * 同じ要素の別のパスがまだその配列を持つ(`{ items: A, alt: A }` の `alt` だけを替えた)なら手放さず、真を返す —\n * 呼び手は、新しい配列に前の配列の行を貸させない(前の配列はまだ描かれている — createListDiff の keepPreviousList)\n */\nexport function releaseListAtParent(list: unknown, parentListIndex: IListIndex, holder: Record<string, unknown>, key: string): boolean {\n if (!listIndexesByList.has(list as readonly unknown[])) {\n return false;\n }\n let kept = false;\n for (const other in holder) {\n kept ||= other !== key && holder[other] === list;\n }\n if (!kept) {\n let released = releasedListsByParent.get(parentListIndex);\n if (typeof released === \"undefined\") {\n released = new WeakSet();\n releasedListsByParent.set(parentListIndex, released);\n }\n released.add(list as readonly unknown[]);\n }\n // 行集合の親がこの外側の行なら、配列をまだ持つ別の外側の行へいま付け替える。その外側の行が引くまで待つと、間に描き直した\n // 行の下のアドレスが手放した外側の行を経由し、その外側の行の新しい値(写し)を読み書きした(隠れた外側の行に知らせた\n // 更新で、別の外側の行が写しに替えた — f5/if/1242)。付け替え先は、手放したキーで配列を持つ外側の行。別のキーがまだ\n // 持つときも、このキーの分は手放すので付け替える — 残ったキーのアドレスは、憶えた親(この外側の行)を使い続ける\n // (address/StateAddress.ts・f6/dual/43)\n const rows = listIndexesByList.get(list as readonly unknown[])!;\n const moved = movedByList.get(list as readonly unknown[]);\n if (rows[0]?.parentListIndex === parentListIndex && !(kept && moved?.[0] === parentListIndex && moved[1] === updateBatch)) {\n for (const other of holdersByList.get(list as readonly unknown[]) ?? []) {\n if (other !== parentListIndex && other.position === parentListIndex.position && isHoldingParent(list as readonly unknown[], other) &&\n Object(getListIndexValue(other))[key] === list) {\n rows.forEach((row) => reparentListIndex(row, other));\n handedOverByList.set(list as readonly unknown[], [parentListIndex, updateBatch]);\n break;\n }\n }\n }\n return kept;\n}\n\n/**\n * 配列 → 手放したときに行集合を付け替えた元の外側の行と、そのバッチ。同じバッチでその外側の行が別のキーに同じ配列を書いたら\n * (`items` から `alt` へ移した)、行集合を戻す — 付け替えた先の外側の行は書いたキーで配列を持たないので、移した先のキーの\n * アドレスが付け替えた先の外側の行の別の配列を読んだ(6 つ目の修理の検証の y7)\n */\nconst handedOverByList = new WeakMap<readonly unknown[], [IListIndex, number]>();\n\n/**\n * 配列 → その配列を内側のパスに書いた外側の行と、そのバッチ。同じバッチで先に別のキーへ書いてから元のキーを替えた(`alt` へ\n * 移してから `items` を替えた)外側の行は、まだその配列を持つので付け替えない — 移した先のキーのアドレスはこれから作られ、\n * 付け替えた先の外側の行の別の配列を読んだ(6 つ目の修理の検証の y7)\n */\nconst movedByList = new WeakMap<readonly unknown[], [IListIndex, number]>();\n\n/** 外側の行 `parentListIndex` の内側のパスに、配列 `list` を書いた(手放した印を外す) */\nexport function holdListAtParent(list: unknown, parentListIndex: IListIndex): void {\n releasedListsByParent.get(parentListIndex)?.delete(list as readonly unknown[]);\n const rows = listIndexesByList.get(list as readonly unknown[]);\n if (typeof rows !== \"undefined\") {\n movedByList.set(list as readonly unknown[], [parentListIndex, updateBatch]);\n const handedOver = handedOverByList.get(list as readonly unknown[]);\n if (handedOver?.[0] === parentListIndex && handedOver[1] === updateBatch) {\n rows.forEach((row) => reparentListIndex(row, parentListIndex));\n }\n }\n}\n\n/** 外側の行 `parentListIndex` が配列 `list` を手放したか(applyChangeToFor・#393) */\nexport function hasReleasedList(list: readonly unknown[], parentListIndex: IListIndex): boolean {\n return releasedListsByParent.get(parentListIndex)?.has(list) === true;\n}\n\n/**\n * 外側の行が、もうその配列を持たないか(退役した・内側のパスから手放した)。祖先の行が退役した行も同じ — 3 段のリストの\n * 外側の行を作り直すと、真ん中の行は差分を通らないので退役の印が付かない(見なければ、真ん中の行を作り直した後の\n * 内側の配列の行が、退役した外側の行の下の真ん中の行に残り、2 つの行から引かれた配列と取り違える)\n */\nfunction isGoneParent(list: readonly unknown[], parentListIndex: IListIndex): boolean {\n return hasReleasedList(list, parentListIndex) || isUnderRetiredRow(parentListIndex);\n}\n\n/**\n * 要素書き込みの入れ替えの途中で、書いた要素を映している行 → 書いたバッチ(setByAddress の _setByAddressWithSwap)。\n * 揃うと行は値に付いて元の要素へ戻るので、その間にこの行の下で引いた配列の行を、この行へ付け替えない — 付け替えると、\n * 揃った後にその配列を持たない行が親として残り、書き込みが別の配列に着地した(#394 と同じ系統)\n */\nconst swapPendingBatchByRow = new WeakMap<IListIndex, number>();\n\nexport function markRowSwapPending(row: IListIndex): void {\n swapPendingBatchByRow.set(row, updateBatch);\n}\n\nexport function clearRowSwapPending(row: IListIndex): void {\n swapPendingBatchByRow.delete(row);\n}\n\n/**\n * 外側の行 `row` の要素が、`other` の要素が配列を持つどのキーでも同じ配列を持つか(直下のキーだけ)。行のアドレスは\n * 行の親から引き直すので、同じ配列を `items` と `alt` の 2 つのキーに持つ外側の行がいると、片方のキーにしか持たない外側の行を\n * 親にした行の、もう片方のキーのアドレスが別の配列に着地した(R1 — 例: `{ items: 写し, alt: A }` を親にした `groups.0.items.0`)\n */\nfunction covers(list: readonly unknown[], row: IListIndex, other: IListIndex): boolean {\n const element = Object(getListIndexValue(row)) as Record<string, unknown>;\n const held = getListIndexValue(other) as Record<string, unknown>;\n for (const key in held) {\n if (held[key] === list && element[key] !== list) {\n return false;\n }\n }\n return true;\n}\n\n/** 付け替え先にしてよい親か(配列を持っていて、入れ替えの途中で別の要素を映していない) */\nfunction isHoldingParent(list: readonly unknown[], parentListIndex: IListIndex): boolean {\n return !isGoneParent(list, parentListIndex) && swapPendingBatchByRow.get(parentListIndex) !== updateBatch;\n}\n\n/**\n * 2 つ以上の外側の行から引かれた配列 → 引いた外側の行(#393)。行の親は 1 つなので、もう片方の外側の行から引いた行も同じ\n * 親を持つ。その行を別の配列(写し)に貸すと、写しの要素の書き込みが行の親を経由して元の配列に着地し、元の配列を描く\n * 外側の行の添字も写しの位置へ振り直される。差分は、ほかにまだ持っている外側の行がある配列の行を貸さない(createListDiff)。\n * 持っているかはその都度見る(手放した・退役した外側の行は数えない)ので、共有をやめた配列の写しは行を借りて DOM を保つ。\n * もう持っていない外側の行は、見たときと、集合が前に見直した大きさの倍に育ったときに外す — 外した外側の行を持ち続けず、\n * 見直しの手間は足した数に比例する(9,000 行が同じ配列を持つページで、足すたびに全部を見直すと作り直しが 4 倍遅れた)\n */\nconst holdersByList = new WeakMap<readonly unknown[], Set<IListIndex>>();\nconst pruneSizeByList = new WeakMap<readonly unknown[], number>();\n\nfunction addHolders(list: readonly unknown[], holders: (IListIndex | null)[]): void {\n let held = holdersByList.get(list);\n if (typeof held === \"undefined\") {\n held = new Set();\n holdersByList.set(list, held);\n } else if (held.size >= (pruneSizeByList.get(list) ?? 8)) {\n held.forEach((holder) => {\n if (isGoneParent(list, holder)) {\n held!.delete(holder);\n }\n });\n pruneSizeByList.set(list, held.size * 2 + 8);\n }\n for (const holder of holders) {\n held.add(holder!);\n }\n}\n\n/** `requester` のほかに、配列をまだ持っている外側の行があるか(見た、もう持っていない外側の行は外す) */\nexport function isHeldElsewhere(list: readonly unknown[], requester: IListIndex): boolean {\n const held = holdersByList.get(list);\n for (const holder of held ?? []) {\n if (isGoneParent(list, holder)) {\n held!.delete(holder);\n } else if (holder !== requester) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * 行を写しに貸した配列(#393)。差分は、外側の行の内側のパスに書いた写しへ前の配列の行を貸す(DOM を保つため)。\n * 前の配列を別の外側の行がまだ持っていて(書いた外側の行はまだ引いていなかった — if で隠れていた等)後から引くと、\n * 台帳は行をその外側の行へ付け替えようとする — 付け替えると写しの行も動き、写しの要素の書き込みが前の配列に着地する。\n * 貸した配列には、付け替える代わりに新しい行集合を作る(resolveListIndexesByList)。\n */\nconst lentLists = new WeakSet<readonly unknown[]>();\n\nexport function markListLent(list: readonly unknown[]): void {\n lentLists.add(list);\n}\n\n/**\n * 同じ要素オブジェクトを表している、書いた配列の外の生きた行(createListIndex.ts の getRowsOfSameElement・#393)。退役した行・\n * 退役した外側の行の下の行(外側の行ごと外した行 — 差分を通らない)は数えない\n */\nexport function getElementAliases(row: IListIndex, readList: () => readonly unknown[]): readonly IListIndex[] {\n const others = getRowsOfSameElement(row);\n if (others.length === 0) {\n return others;\n }\n // 入れ子のリストの、書いた配列(`readList` — 別の行が居るときだけ読む)の外の行だけ — 深さの違う行は書いたパスの\n // アドレスにならず、同じ配列の 2 つの位置・ルート直下の写しは、同じオブジェクトを 2 つの行に置いた形の制約のまま(#365 / #362)\n const rows = new Set(listIndexesByList.get(readList()));\n return others.filter((other) => other.position === row.position && !rows.has(other) && !isUnderRetiredRow(other));\n}\n\n/**\n * 台帳の行がぶら下がる親(`oldParent`)を、いま要求している親(`newParent`)へ\n * 付け替えてよいか。**親がもうその配列を持たないとき(退役した・手放した)だけ**真 ──\n * 持っているなら共有であって陳腐化ではないので、main と同じく 1 組の行集合に合流させる。\n * 深さ(`position`)が変わる付け替えはしない。行の `position` / `length` は鋳造時に\n * 確定していて、そこがずれると絶対アドレスの段数が壊れる(bind-component が 1 本の\n * 配列を 2 つの深さから展開する形が実際にある)。\n */\nfunction canReparent(list: readonly unknown[], oldParent: IListIndex | null, newParent: IListIndex | null): boolean {\n if (oldParent === newParent) {\n // 自分が展開した行集合(ここが圧倒的多数)。ルート直下どうし(両方 null)もここ。\n return false;\n }\n if (oldParent === null || newParent === null) {\n return false;\n }\n if (oldParent.position !== newParent.position) {\n return false;\n }\n return isGoneParent(list, oldParent) && isHoldingParent(list, newParent);\n}\n\n/**\n * 要求している親(`newParent`)が、退役した `home` の**行そのもの**か。\n * 行を戻す普通のやり方(新しい配列に同じ要素を並べ直す)では差分が ListIndex を作り直すので、\n * home の ListIndex は二度と生き返らない。同じリスト要素を同じ深さで表している生きた行が\n * 現れたら、それが戻ってきた home である。\n */\nfunction isRestoredHome(\n list: readonly unknown[],\n home: IListIndex | null,\n oldParent: IListIndex | null,\n newParent: IListIndex | null,\n): boolean {\n if (home === null || newParent === null) {\n return false;\n }\n if (newParent === oldParent) {\n // すでにそこにある(=毎回 reparent して version を進めない)。\n return false;\n }\n if (!retiredListIndexes.has(home)) {\n // home が生きているなら「生き返った home」の分岐が扱う。\n return false;\n }\n if (!isHoldingParent(list, newParent) || newParent.position !== home.position) {\n return false;\n }\n // 手放した home の要素は、もうこの配列を持たない(#394)\n return !hasReleasedList(list, home) && isSameListIndexValue(newParent, home);\n}\n\n/**\n * 行集合の親をどこへ向けるか。`null` なら何もしない。\n * 優先順位は **「生き返った home」>「戻ってきた home の行」>「陳腐化した親の付け替え」**。\n */\nfunction getRepairTarget(list: readonly unknown[], first: IListIndex, parentListIndex: IListIndex | null): IListIndex | null {\n const home = getHomeParentListIndex(first);\n const oldParent = first.parentListIndex;\n if (home !== null && home !== oldParent && !isGoneParent(list, home) && covers(list, home, oldParent!)) {\n return home;\n }\n if (isRestoredHome(list, home, oldParent, parentListIndex)) {\n return parentListIndex;\n }\n return canReparent(list, oldParent, parentListIndex) ? parentListIndex : null;\n}\n\n/**\n * 台帳を**引き当てるだけ**。行の親ポインタには触らない。\n * 観測(テスト・世代の後始末・`$scan` の drain が行の置き換わりを見る判定)と存在判定はこちらを使う。\n */\nexport function getListIndexesByList(list: readonly unknown[]): IListIndex[] | null {\n const listIndexes = listIndexesByList.get(list);\n if (typeof listIndexes === \"undefined\") {\n return null;\n }\n return listIndexes;\n}\n\n/**\n * 台帳を引き当て、**必要なら親ポインタを修理して**返す(#256)。\n * 引き当てのついでに行を書き換えるので、観測目的では使わないこと ──\n * 修理が要るのは「その親の文脈で値を解決する」経路(差分・アドレス解決)だけ。\n */\nexport function resolveListIndexesByList(\n list: readonly unknown[],\n parentListIndex: IListIndex | null,\n): IListIndex[] | null {\n const listIndexes = listIndexesByList.get(list);\n if (typeof listIndexes === \"undefined\") {\n return null;\n }\n const first = listIndexes[0];\n // 描いた並びの写し(要素書き込みの入れ替えの前の並び — swapBaselineList.ts・下の貸した行の写し)は state に居ないので、\n // その台帳を引いても行を付け替えない — 写しを持つ外側の行の印(手放した・退役した)が無いので、行集合を手放した外側の行\n // (home)へ戻してしまう(#394)\n if (typeof first !== \"undefined\" && !isSwapBaselineList(list)) {\n // 行の親とは別の、配列を持っている外側の行から引いた。入れ替えの途中で別の要素を映している行が引いたのは共有ではない\n // (揃うと行は元の要素へ戻る)\n const other = parentListIndex !== null && first.parentListIndex !== parentListIndex &&\n swapPendingBatchByRow.get(parentListIndex) !== updateBatch;\n const target = getRepairTarget(list, first, parentListIndex);\n if (target !== null && lentLists.has(list)) {\n lentLists.delete(list);\n // この配列を描いた `for` が描いたのは貸した行。描いた並びを、貸した行の台帳を持つ写しへ移す(#320 の記録)\n const image = [...list];\n markSwapBaselineList(image);\n listIndexesByList.set(image, listIndexes);\n rebaseRenderedList(list, image);\n const rows = listIndexes.map((_row, i) => {\n const row = createListIndex(target, i);\n setListIndexValue(row, list[i]);\n return row;\n });\n listIndexesByList.set(list, rows);\n return rows;\n }\n if (target !== null) {\n // 1 組の行集合は 1 つの親のもとにある、を保つ(差分が別の親の行を混ぜて\n // 作った集合も、ここで揃える)。\n for (const listIndex of listIndexes) {\n reparentListIndex(listIndex, target);\n }\n } else if (other) {\n // 2 つの外側の行が持つ配列(holdersByList)。要求した外側の行が、いまの親より多くのキーで配列を持つなら、そちらを親に\n // する(上の covers — 片方のキーにしか持たない外側の行が先に引いた)\n addHolders(list, [first.parentListIndex, parentListIndex]);\n const parent = first.parentListIndex;\n if (parent !== null && parent.position === parentListIndex!.position && !covers(list, parent, parentListIndex!) &&\n covers(list, parentListIndex!, parent)) {\n for (const listIndex of listIndexes) {\n reparentListIndex(listIndex, parentListIndex);\n }\n }\n }\n }\n return listIndexes;\n}\n\n/**\n * 要素の書き込み(setByAddress の renewReplacedRow・#333)が写した台帳のうち、その配列の台帳としてしか\n * 参照されていないもの。次の要素の書き込みは写さずにその場で書き換えてよい(写すと、1 バッチで全要素を\n * 書く `$setAll(\"items.*\", …)` が O(n²) になる)。台帳の配列を別の持ち手が捕まえたら外す — 別の配列の\n * 台帳にする(下の setListIndexesByList)、差分が持つ(createListDiff)、入れ替えが持つ(swapInfo.ts)、\n * `$eqIndex` の監視が付く(dependency/keyedDependency.ts の registerIndexWatcher / moveIndexWatchers)。\n */\nconst ownedListIndexes = new WeakSet<IListIndex[]>();\n\nexport function isOwnedListIndexes(listIndexes: IListIndex[]): boolean {\n return ownedListIndexes.has(listIndexes);\n}\n\nexport function disownListIndexes(listIndexes: IListIndex[]): void {\n ownedListIndexes.delete(listIndexes);\n}\n\nexport function setListIndexesByList(list: readonly unknown[], listIndexes: IListIndex[] | null, owned = false): void {\n if (listIndexes === null) {\n listIndexesByList.delete(list);\n return;\n }\n if (owned) {\n ownedListIndexes.add(listIndexes);\n } else {\n disownListIndexes(listIndexes);\n }\n listIndexesByList.set(list, listIndexes);\n}\n\n/**\n * `for` が描いた並び(#320)。1 本の配列につき 1 つで、その配列を描いたどの `for` もこれを指す。\n *\n * 描画の基準(lastListValueByAbsoluteStateAddress.ts)はアドレスごとに 1 本なので、同じリストを描く `for` が複数あると、画面から外れていて\n * 描かなかった `for`(`if` で消された・DOM から外された)を待たずに進む。そうした `for` は自分が\n * 描いた並びとの差分を取る(applyChangeToFor)。その並びを配列そのもので覚えると、要素書き込みが\n * 配列をその場で書き換えて台帳を差し替えたときに「描いた並び」が失われるので、ここを 1 段挟む。\n * 要素書き込みの入れ替えが揃ったら、ここを書き込む前の並びの写しに差し替える(rebaseRenderedList)。\n */\nexport interface IRenderedList {\n value: readonly unknown[];\n}\n\nconst renderedListByList: WeakMap<readonly unknown[], IRenderedList> = new WeakMap();\n\nexport function getRenderedList(list: readonly unknown[]): IRenderedList {\n let rendered = renderedListByList.get(list);\n if (typeof rendered === \"undefined\") {\n rendered = { value: list };\n renderedListByList.set(list, rendered);\n }\n return rendered;\n}\n\n/** この配列を描いた `for` がいて、描いた後にまだ描画の基準を移していないか(setByAddress の renewReplacedRow) */\nexport function hasRenderedList(list: readonly unknown[]): boolean {\n return renderedListByList.has(list);\n}\n\n/**\n * 要素書き込みの入れ替えが揃った(setByAddress の notifySwappedList)。この配列をこれまでに描いた `for` が\n * 描いたのは、書き込む前の並び(`image` — 写しと台帳の写し)。以後この配列を描く `for` は新しい並びを指す。\n */\nexport function rebaseRenderedList(list: readonly unknown[], image: readonly unknown[]): void {\n const rendered = renderedListByList.get(list);\n if (typeof rendered !== \"undefined\") {\n rendered.value = image;\n renderedListByList.delete(list);\n }\n}\n","import { IAbsoluteStateAddress } from \"../address/types\";\nimport { IListIndex } from \"./types\";\nimport { getListIndexesByList, isRetiredListIndex } from \"./listIndexesByList\";\n\nconst lastListValueByAbsoluteStateAddress: WeakMap<IAbsoluteStateAddress, readonly unknown[]> = new WeakMap();\n\n/**\n * 上の記録の逆引き(#379): state 要素ごとに、配列 → その配列をいま描画の基準にしているアドレス。\n * 同じ配列を別のアドレスの `for` も描いている(2 つの外側の行が同じ内側の配列を持つ・同じ行の別パス)とき、\n * 要素書き込みの入れ替えが揃ったら、その `for` にも書き込む前の並びからの差分で描き直させる(setByAddress の\n * notifySwappedList → 下の markSwappedList)。state 要素ごとに分けるのは、別の state の `for` を描き直させず、\n * 捨てた state を配列から持ち続けないため。退役した行(リストから外した外側の行)とその下のアドレスは、集合が\n * 前に見直したときの 2 倍に育ったときに外す(行の数に比例する手間で、外した外側の行を持ち続けない)。\n */\nconst addressesByListByStateElement: WeakMap<object, WeakMap<readonly unknown[], Set<IAbsoluteStateAddress>>> = new WeakMap();\nconst NO_ADDRESSES: ReadonlySet<IAbsoluteStateAddress> = new Set<IAbsoluteStateAddress>();\n/** 逆引きの集合を次に見直す大きさ(退役した行の下のアドレスを外す — setLastListValueByAbsoluteStateAddress) */\nconst sweepAtByAddresses: WeakMap<Set<IAbsoluteStateAddress>, number> = new WeakMap();\nconst SWEEP_MIN = 8;\n\n/**\n * 同じ配列を描く別の `for` のアドレス → 要素書き込みの入れ替えが揃ったその配列(#379)。そのアドレスの `for`(同じ行を\n * 描く `for` が 2 つあれば両方)が描くときに見て(isSwappedList — applyChangeToFor)、描いた後の記録(上の set)で\n * 消える。まだその配列を描くなら、自分が描いた並び(入れ替えの前の写しへ移された #320 の記録)との差分を取る。\n * 基準そのもの(上の記録)は差し替えない — 同じバッチでその `for` のパスへ別の配列を書いていたら、いままでの基準との\n * 差分(#320 の突き合わせ)で描く。写しを基準にすると、差分が新しい配列の行を引き直し、その行が写しの行集合の\n * 持ち主の外側の行へ付け替わる(#256)。\n */\nconst swappedListByAddress: WeakMap<IAbsoluteStateAddress, readonly unknown[]> = new WeakMap();\n\nfunction addressesByListOf(address: IAbsoluteStateAddress): WeakMap<readonly unknown[], Set<IAbsoluteStateAddress>> {\n const stateElement = address.absolutePathInfo.stateElement;\n let addressesByList = addressesByListByStateElement.get(stateElement);\n if (typeof addressesByList === \"undefined\") {\n addressesByList = new WeakMap();\n addressesByListByStateElement.set(stateElement, addressesByList);\n }\n return addressesByList;\n}\n\nexport function getLastListValueByAbsoluteStateAddress(address: IAbsoluteStateAddress): readonly unknown[] {\n return lastListValueByAbsoluteStateAddress.get(address) ?? [];\n}\n\nexport function setLastListValueByAbsoluteStateAddress(address: IAbsoluteStateAddress, value: readonly unknown[]): void {\n const previous = lastListValueByAbsoluteStateAddress.get(address);\n lastListValueByAbsoluteStateAddress.set(address, value);\n swappedListByAddress.delete(address);\n const addressesByList = addressesByListOf(address);\n if (previous !== value && typeof previous !== \"undefined\") {\n addressesByList.get(previous)!.delete(address);\n }\n const addresses = addressesByList.get(value);\n if (typeof addresses === \"undefined\") {\n addressesByList.set(value, new Set([address]));\n } else if (!addresses.has(address)) {\n // 足すたびに全部を見ると、同じ配列を N 行が持つページの描画が N² になる。集合が前に見た後の 2 倍に育ったときだけ見る\n if (addresses.size >= (sweepAtByAddresses.get(addresses) ?? SWEEP_MIN)) {\n addresses.forEach((held) => {\n if (isUnderRetiredRow(held.listIndex)) {\n addresses.delete(held);\n }\n });\n sweepAtByAddresses.set(addresses, Math.max(SWEEP_MIN, addresses.size * 2));\n }\n addresses.add(address);\n }\n}\n\n/**\n * アドレスの行か、その祖先の行が退役しているか。外側の行をリストから外すと、その下の行(3 段なら中の行)は\n * 差分を通らないので退役の印が付かない — 祖先まで見ないと、作り直すたびに外したアドレスが残り続ける\n */\nfunction isUnderRetiredRow(listIndex: IListIndex | null): boolean {\n for (let row = listIndex; row !== null; row = row.parentListIndex) {\n if (isRetiredListIndex(row)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * この state 要素で、この配列をいま描画の基準にしているアドレス(`address` の state 要素で引く)。退役した行の下の\n * アドレスはここでも外す — 外側の行を減らした後の要素書き込みが、外した行の `for` を毎回数えないように\n */\nexport function getAddressesByLastListValue(address: IAbsoluteStateAddress, value: readonly unknown[]): ReadonlySet<IAbsoluteStateAddress> {\n const addresses = addressesByListOf(address).get(value);\n if (typeof addresses === \"undefined\") {\n return NO_ADDRESSES;\n }\n addresses.forEach((held) => {\n if (isUnderRetiredRow(held.listIndex)) {\n addresses.delete(held);\n }\n });\n return addresses;\n}\n\n/** 同じ配列を描く別の `for` に、その配列の入れ替えが揃ったことを知らせる(上の swappedListByAddress)。もう知らせてあれば偽 */\nexport function markSwappedList(address: IAbsoluteStateAddress, list: readonly unknown[]): boolean {\n if (swappedListByAddress.has(address)) {\n return false;\n }\n swappedListByAddress.set(address, list);\n return true;\n}\n\n/**\n * 入れ替えが揃ったと知らされていて、いま描く値がその配列か。同じ中身の写し(同じバッチで\n * `[...items]` を書いた)は元の配列の台帳をそのまま持つので、同じ配列として扱う\n */\nexport function isSwappedList(address: IAbsoluteStateAddress, value: unknown): boolean {\n const list = swappedListByAddress.get(address);\n return typeof list !== \"undefined\" && (list === value || getListIndexesByList(value as unknown[]) === getListIndexesByList(list));\n}\n\nexport function clearLastListValueByAbsoluteStateAddress(address: IAbsoluteStateAddress): void {\n const previous = lastListValueByAbsoluteStateAddress.get(address);\n lastListValueByAbsoluteStateAddress.delete(address);\n if (typeof previous !== \"undefined\") {\n addressesByListOf(address).get(previous)!.delete(address);\n }\n}\n\nexport function hasLastListValueByAbsoluteStateAddress(address: IAbsoluteStateAddress): boolean {\n return lastListValueByAbsoluteStateAddress.has(address);\n}\n\n// `for` が描いた並び(#320)の記録は、行の台帳と一緒に持つ(list/listIndexesByList.ts — 台帳を作り直すときに描いた並びを移す・#393)\nexport { getRenderedList, hasRenderedList, rebaseRenderedList } from \"./listIndexesByList\";\nexport type { IRenderedList } from \"./listIndexesByList\";\n","/**\n * list/stateListBaseline.ts\n *\n * state 側のリスト差分基準 — 「最後に **state 側が観測した** リスト値」。\n *\n * 描画側の基準([lastListValueByAbsoluteStateAddress](./lastListValueByAbsoluteStateAddress.ts))\n * とは別の問いに答える台帳である。あちらは「最後に**描画した**値」で、`applyChangeToFor` が\n * 「画面に対して何を足し引きするか」を決めるために使う。こちらは読み(`$getAll`)と\n * 依存ウォーク(`walkDependency`)が「**前回見た形からどう変わったか**」を決めるために使う。\n *\n * 統合してはならない。ウォークが描画側の基準を進めると、その後の `applyChangeToFor` が\n * 空の差分を見て描画を落とす。逆に描画側の基準だけに頼ると、`for` バインドの無いリストでは\n * 基準が永久に空のままになり、`createListDiff` の「旧リストが空」分岐が新しい配列に\n * **新しい ListIndex を鋳造**する。子リストの台帳は旧親 ListIndex を指したまま残るので\n * 親子の連鎖が切れ、集計が恒久的に stale になるか `ListIndexes not found` で恒久的に\n * throw する(docs/state-recursive-path-impl-plan.md §3-2 の E1)。\n *\n * 書き手は 5 系統ある。いずれも「観測した」という同じ意味を持つ。\n * - 読み: `collectWildcardIndexes`(`commitDiffBaseline: true` のときだけ。固定 arity の\n * `$setAll` は走査を借りるだけで動かさない — docs/state-set-all-design.md §6-2)\n * - 再帰の走査: `recursion/walk.ts`(合併形の `$getAll` と**再帰の `$setAll` の両方**が確定する。\n * cold な書き込みが ListIndex 世代を鋳造したまま基準を残すと、次の構造変更で深い子台帳が\n * 孤児になるため — docs/state-recursive-path-impl-plan.md §6)\n * - 描画: `applyChangeFromBindings` / `hydrateBindings`(描画側の基準と同時に書く)\n * - 依存ウォーク: `walkDependency`(ウォーク完了後にまとめて確定する)\n * - 添字から行を引く経路(直接添字・`$postUpdate`・`$resolve` / `$setAll` の行の引き直し —\n * proxy/methods/getListIndexesByAddress.ts): 台帳の無いリストに台帳を生やしたときだけ(#324)。\n * 生やした行を基準に載せないと、描いていないリストを写し替えたときに行が退役せず、子リストの\n * 台帳が古い行にぶら下がったまま残る\n *\n * キーは **絶対アドレス**。`IStateAddress` は listIndex が null のとき pathInfo だけで\n * intern されるため、同じパス形状のルートリストを持つ 2 つの state 要素がエントリを\n * 共有してしまう(`createStateAddress` の `_cacheNullListIndex`)。\n */\nimport { IAbsoluteStateAddress } from \"../address/types\";\n\nconst stateListBaselineByAbsoluteStateAddress: WeakMap<IAbsoluteStateAddress, readonly unknown[]> = new WeakMap();\n/**\n * 更新バッチ中の観測は**即座に確定しない**。バッチ内で同じリストへ 2 回構造書き込みすると、\n * 2 回目のウォークが「一度も描画されず直後に上書きされる中間値」を基準に diff を取り、\n * 中間値が落とした行の ListIndex が鋳造し直されて子リストの台帳が恒久的に切れるため。\n *\n * バッチが開いている間の観測はここに溜め、バッチ末尾(updater の drain 終了)でまとめて\n * 確定する。こうするとバッチ内のどのウォークも「バッチ開始時の値」と diff を取り、\n * これは描画側(applyChangeToFor が描画基準で取る diff)と一致する。\n *\n * 深さで数えるのは、drain の最中に $updatedCallback などが書いて新しいバッチが\n * 始まる形があるため。0 に戻ったバッチだけが確定する。\n */\nlet pendingBaselines: Map<IAbsoluteStateAddress, readonly unknown[]> | null = null;\nlet batchDepth = 0;\n\nexport function getStateListBaseline(address: IAbsoluteStateAddress): readonly unknown[] {\n // pending は意図的に見ない。バッチ中の読み手には「バッチ開始時の値」を返す。\n return stateListBaselineByAbsoluteStateAddress.get(address) ?? [];\n}\n\nexport function setStateListBaseline(address: IAbsoluteStateAddress, value: readonly unknown[]): void {\n if (pendingBaselines !== null) {\n pendingBaselines.set(address, value);\n return;\n }\n stateListBaselineByAbsoluteStateAddress.set(address, value);\n}\n\n/** 更新バッチの開始(updater が最初の enqueue で呼ぶ)。 */\nexport function beginStateListBaselineBatch(): void {\n batchDepth++;\n if (pendingBaselines === null) {\n pendingBaselines = new Map<IAbsoluteStateAddress, readonly unknown[]>();\n }\n}\n\n/** 更新バッチの終了(updater が drain の finally で呼ぶ)。入れ子が全部閉じたら確定する。 */\nexport function endStateListBaselineBatch(): void {\n if (batchDepth === 0) {\n // enqueue を経ない直接 drain(testApplyChange)。開いていないバッチは閉じない。\n return;\n }\n batchDepth--;\n if (batchDepth > 0 || pendingBaselines === null) {\n return;\n }\n for (const [address, value] of pendingBaselines) {\n stateListBaselineByAbsoluteStateAddress.set(address, value);\n }\n pendingBaselines = null;\n}\n\n/** 台帳から 1 件落とす(描画側の clearLastListValueByAbsoluteStateAddress と対にしておく)。 */\nexport function clearStateListBaseline(address: IAbsoluteStateAddress): void {\n pendingBaselines?.delete(address);\n stateListBaselineByAbsoluteStateAddress.delete(address);\n}\n\nexport function hasStateListBaseline(address: IAbsoluteStateAddress): boolean {\n return (pendingBaselines?.has(address) ?? false)\n || stateListBaselineByAbsoluteStateAddress.has(address);\n}\n","\nexport const setLoopContextSymbol: unique symbol = Symbol(\"$$setLoopContext\");\nexport const getByAddressSymbol: unique symbol = Symbol(\"$$getByAddress\");\nexport const hasByAddressSymbol: unique symbol = Symbol(\"$$hasByAddress\");\nexport const connectedCallbackSymbol: unique symbol = Symbol(\"$$connectedCallback\");\nexport const disconnectedCallbackSymbol: unique symbol = Symbol(\"$$disconnectedCallback\");\nexport const updatedCallbackSymbol: unique symbol = Symbol(\"$$updatedCallback\");\nexport const errorCallbackSymbol: unique symbol = Symbol(\"$$errorCallback\");\n","import { IListIndex } from \"../list/types\";\nimport { ITreePath, IAbsoluteStateAddress } from \"./types\";\n\nconst _cache: WeakMap<IListIndex, WeakMap<ITreePath, IAbsoluteStateAddress>> = new WeakMap();\nconst _cacheNullListIndex: WeakMap<ITreePath, IAbsoluteStateAddress> = new WeakMap();\n\nclass AbsoluteStateAddress implements IAbsoluteStateAddress {\n readonly absolutePathInfo: ITreePath;\n readonly listIndex: IListIndex | null;\n\n constructor(absolutePathInfo: ITreePath, listIndex: IListIndex | null) {\n this.absolutePathInfo = absolutePathInfo;\n this.listIndex = listIndex;\n }\n}\n\nexport function createAbsoluteStateAddress(absolutePathInfo: ITreePath, listIndex: IListIndex | null): IAbsoluteStateAddress {\n if (listIndex === null) {\n let cached = _cacheNullListIndex.get(absolutePathInfo);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n cached = new AbsoluteStateAddress(absolutePathInfo, null);\n _cacheNullListIndex.set(absolutePathInfo, cached);\n return cached;\n } else {\n let cacheByAbsolutePathInfo = _cache.get(listIndex);\n if (typeof cacheByAbsolutePathInfo === \"undefined\") {\n cacheByAbsolutePathInfo = new WeakMap<ITreePath, IAbsoluteStateAddress>();\n _cache.set(listIndex, cacheByAbsolutePathInfo);\n }\n let cached = cacheByAbsolutePathInfo.get(absolutePathInfo);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n cached = new AbsoluteStateAddress(absolutePathInfo, listIndex);\n cacheByAbsolutePathInfo.set(absolutePathInfo, cached);\n return cached;\n }\n}\n","import { IStateElement } from \"../components/types\";\nimport { ITreePath, IPathInfo } from \"./types\";\n\n/**\n * ツリー(`<wcs-state>` 要素)に固定したパス。絶対アドレスの intern の中間ノードであり、\n * 行バインディングのパターン台帳のキーでもある(docs/state-row-instantiation-redesign.md §3-3)。\n *\n * 表は「要素を弱キーにした WeakMap → PathInfo をキーにした Map」の 2 段。PathInfo はページの\n * 寿命だけ生きる(強参照の Map に載っている)ので内側は WeakMap である必要が無く、Map のほうが\n * 引きが速い。各段は get 1 回と undefined 比較で引く — has してから get する形は同じ表を\n * 2 回引いていた。読みのベンチ(e2e/bench/plain-read.mjs)では、キャッシュを引く読みが\n * getter で約 1ns、行の getter で 3〜5ns 速くなり、この関数を通らない素のパスの読みは変わらない\n * (docs/spikes/state-address-intern-placement/README.md の main-tp)。\n *\n * ノードへの強参照経路は要素の WeakMap エントリ(ephemeron)だけなので、要素が DOM から外れれば\n * ノードごと回収される(e2e/tests/state-address-gc.spec.ts)。\n */\nconst treePathsByElement: WeakMap<IStateElement, Map<IPathInfo, ITreePath>> = new WeakMap();\n\nexport function getTreePath(stateElement: IStateElement, pathInfo: IPathInfo): ITreePath {\n let table = treePathsByElement.get(stateElement);\n if (table === undefined) {\n table = new Map();\n treePathsByElement.set(stateElement, table);\n }\n let treePath = table.get(pathInfo);\n if (treePath === undefined) {\n treePath = Object.freeze(new TreePath(stateElement, pathInfo));\n table.set(pathInfo, treePath);\n }\n return treePath;\n}\n\nclass TreePath implements ITreePath {\n readonly pathInfo: IPathInfo;\n readonly stateElement: IStateElement;\n constructor(stateElement: IStateElement, pathInfo: IPathInfo) {\n this.pathInfo = pathInfo;\n this.stateElement = stateElement;\n }\n}\n","import { IStateElement } from \"../components/types\";\nimport { IListIndex } from \"../list/types\";\nimport { createAbsoluteStateAddress } from \"./AbsoluteStateAddress\";\nimport { getTreePath } from \"./TreePath\";\nimport { IAbsoluteStateAddress, IPathInfo, IStateAddress } from \"./types\";\n\n/**\n * ツリー非依存のアドレスを、`stateElement`(どのツリーか)まで確定した絶対アドレスへ持ち上げる。\n *\n * 恒久台帳(cache / bindings / baseline / updater の queue)はモジュール単一でツリーをまたぐので、\n * キーは必ずこちらを使う — `IStateAddress` をそのままキーにすると、同じパス形状や同じ配列を持つ\n * 2 つの `<wcs-state>` が混線する(__tests__/addressLedgerKeyGuard.test.ts が番人)。\n *\n * 持ち上げは選択の余地が無い決定的な変換で、以前は各呼び出し元が 2 行で手書きしていた。\n * ここに集めて、intern の関数(getTreePath / createAbsoluteStateAddress)を src/address/ の外から\n * 直接呼ばせない(__tests__/addressImportBoundary.test.ts が番人)。2 本の型を 1 本に畳む統合\n * (docs/state-address-unification-design.md)は、素のパスの読みを退行させることが実測で分かり、\n * 閉じた(同 §12)— この持ち上げは残る。\n */\nexport function liftAddress(stateElement: IStateElement, address: IStateAddress): IAbsoluteStateAddress {\n return createAbsoluteStateAddress(getTreePath(stateElement, address.pathInfo), address.listIndex);\n}\n\n/** `IStateAddress` を経ずに、構成要素から直接絶対アドレスを作る。 */\nexport function absoluteAddressOf(\n stateElement: IStateElement,\n pathInfo: IPathInfo,\n listIndex: IListIndex | null,\n): IAbsoluteStateAddress {\n return createAbsoluteStateAddress(getTreePath(stateElement, pathInfo), listIndex);\n}\n","\nconst rootNodeByFragment: WeakMap<DocumentFragment, Node> = new WeakMap();\n\nexport function setRootNodeByFragment(fragment: DocumentFragment, rootNode: Node | null): void {\n if (rootNode === null) {\n rootNodeByFragment.delete(fragment);\n } else {\n rootNodeByFragment.set(fragment, rootNode);\n }\n}\n\nexport function getRootNodeByFragment(fragment: DocumentFragment): Node | null {\n return rootNodeByFragment.get(fragment) || null;\n}\n","import { IPathInfo } from \"./types.js\";\n\nconst cacheCalcWildcardLen: Map<string, number> = new Map(); \n\nexport function calcWildcardLen(pathInfo: IPathInfo, targetPathInfo: IPathInfo): number {\n let path1: IPathInfo;\n let path2: IPathInfo;\n if (pathInfo.wildcardCount === 0 || targetPathInfo.wildcardCount === 0) {\n return 0;\n }\n if (pathInfo.wildcardCount === 1 \n && targetPathInfo.wildcardCount > 0 \n && targetPathInfo.wildcardPathSet.has(pathInfo.path)) {\n return 1;\n }\n if (pathInfo.id < targetPathInfo.id) {\n path1 = pathInfo;\n path2 = targetPathInfo;\n } else {\n path1 = targetPathInfo;\n path2 = pathInfo;\n }\n const key = `${path1.path}\\t${path2.path}`;\n let len = cacheCalcWildcardLen.get(key);\n if (typeof len !== \"undefined\") {\n return len;\n }\n const matchPath = path1.wildcardPathSet.intersection(path2.wildcardPathSet);\n len = matchPath.size;\n cacheCalcWildcardLen.set(key, len);\n return len;\n}\n\n","/**\n * list/wildcardLevel.ts\n *\n * 「パス上のワイルドカード位置」→「listIndex チェーン上の段」の変換を 1 箇所に集める。\n *\n * チェーンの長さは常に `Δ + W`(W = そのパスの wildcardCount、Δ = そのスコープの\n * base 深さ)である。通常の state スコープは Δ=0 なので「位置 i = 段 i」で済んでいたが、\n * `bind-component` の子スコープがホストの `for` の内側にいる場合は Δ>0 になる\n * (docs/state-bind-component-nested-for-design.md)。\n *\n * そこで**先頭ではなく末尾を基準に数える**。`IListIndex.at()` は負値を受けるので:\n *\n * at(i) → at(i - W) // listIndexes[(Δ+W) + (i-W)] = listIndexes[Δ+i]\n *\n * Δ=0 のときは両者が同じ要素を指すため、この書き換えは既存スコープに対して\n * 意味論を変えない。Δ の値を呼び出し側へ配管する必要も無い。\n */\n\nimport { IListIndex } from \"./types\";\n\n/**\n * ワイルドカード位置 `wildcardPos`(先頭から 0 始まり)に対応する listIndex を返す。\n * `wildcardCount` は `wildcardPos` が属するパスのワイルドカード総数。\n *\n * 範囲外(`wildcardPos >= wildcardCount`)は null。Δ=0 では `at(pos)` が\n * チェーン長を超えて null を返していたのと同じ結果になる。**このガードは必須**で、\n * 落とすと「1 段ループの中で `$2` を読む」が黙って `$1` を返す\n * (末尾起点では `at(1-1)=at(0)` に化けるため)。\n */\nexport function listIndexAtWildcard(\n listIndex: IListIndex,\n wildcardPos: number,\n wildcardCount: number,\n): IListIndex | null {\n if (wildcardPos < 0 || wildcardPos >= wildcardCount) {\n return null;\n }\n return listIndex.at(wildcardPos - wildcardCount);\n}\n\n/**\n * ユーザーランドへ渡すインデックス列。チェーンの先頭 Δ 段(base)を落とし、\n * **そのスコープ自身のループ分だけ**にする。\n *\n * コンポーネントの作者は、自分がリストの中に置かれるかどうかを知らずに書く。\n * `$1` や `onClick(event, index)` の意味が設置場所で変わってはいけないので、\n * Δ は境界の内側に閉じ込める。`$resolve(path, indexes)` は台帳の配列位置で\n * 引くため、ここで返した列がそのまま往復で使える。\n */\nexport function getScopedIndexes(listIndex: IListIndex, wildcardCount: number): number[] {\n // indexes は型上は必須だが、防御的フォールバックを既存挙動として持っている\n const indexes = listIndex.indexes ?? [];\n if (indexes.length === wildcardCount) {\n return indexes;\n }\n return indexes.slice(indexes.length - wildcardCount);\n}\n","import { calcWildcardLen } from \"../address/calcWildcardLen\";\nimport { IBindingInfo } from \"../types\";\nimport { getLoopContextByNode } from \"./loopContextByNode\";\nimport { IListIndex, ILoopContext } from \"./types\";\nimport { listIndexAtWildcard } from \"./wildcardLevel\";\n\nconst listIndexByBindingInfoByLoopContext: WeakMap<ILoopContext, WeakMap<IBindingInfo, IListIndex | null>> = new WeakMap();\n\nexport function getListIndexByBindingInfo(bindingInfo: IBindingInfo): IListIndex | null {\n const loopContext = getLoopContextByNode(bindingInfo.node);\n if (loopContext === null) {\n return null;\n }\n let listIndexByBindingInfo = listIndexByBindingInfoByLoopContext.get(loopContext);\n if (typeof listIndexByBindingInfo === \"undefined\") {\n listIndexByBindingInfo = new WeakMap<IBindingInfo, IListIndex | null>();\n listIndexByBindingInfoByLoopContext.set(loopContext, listIndexByBindingInfo);\n } else {\n const listIndex = listIndexByBindingInfo.get(bindingInfo);\n if (typeof listIndex !== \"undefined\") {\n return listIndex;\n }\n }\n\n let listIndex: IListIndex | null = null;\n try {\n const wildcardLen = calcWildcardLen(loopContext.pathInfo, bindingInfo.statePathInfo);\n if (wildcardLen > 0) {\n listIndex = listIndexAtWildcard(loopContext.listIndex, wildcardLen - 1, loopContext.pathInfo.wildcardCount);\n }\n return listIndex;\n } finally {\n listIndexByBindingInfo.set(bindingInfo, listIndex);\n }\n\n}\n","import { absoluteAddressOf } from \"../address/liftAddress\";\nimport { IAbsoluteStateAddress } from \"../address/types\";\nimport { getRootNodeByFragment } from \"../apply/rootNodeByFragment\";\nimport { getListIndexByBindingInfo } from \"../list/getListIndexByBindingInfo\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo } from \"./types\";\n\nconst absoluteStateAddressByBinding: WeakMap<IBindingInfo, IAbsoluteStateAddress> = new WeakMap();\n\n/**\n * binding の解決済み root を返す。knownRootNode があれば getRootNode() と\n * fragment フォールバックを省略する(リスト行活性化のホットパス)。\n */\nexport function resolveBindingRootNode(binding: IBindingInfo, knownRootNode?: Node | null): Node {\n if (knownRootNode != null) {\n return knownRootNode;\n }\n let rootNode: Node = binding.replaceNode.getRootNode() as Node;\n // binding.replaceNodeはisConnected=trueになっていることが前提、切断されている場合はraiseErrorを返す\n if (binding.replaceNode.isConnected === false) {\n // DocumentFragmentでバッファリングされている場合は、ルートノードをDocumentFragmentから実際のルートノードに切り替える\n const rootNodeByFragment = getRootNodeByFragment(rootNode as DocumentFragment);\n if (rootNodeByFragment === null) {\n raiseError(`Cannot get absolute state address for disconnected binding: ${binding.bindingType} ${binding.statePathName} on ${binding.node.nodeName}`);\n } else {\n rootNode = rootNodeByFragment;\n }\n }\n return rootNode;\n}\n\nexport function getAbsoluteStateAddressByBinding(binding: IBindingInfo, knownRootNode?: Node | null): IAbsoluteStateAddress {\n // 切断されていても、キャッシュされていれば絶対状態アドレスを返す。\n let absoluteStateAddress: IAbsoluteStateAddress | null = null;\n absoluteStateAddress = absoluteStateAddressByBinding.get(binding) || null;\n if (absoluteStateAddress !== null) {\n return absoluteStateAddress;\n }\n\n const rootNode: Node = resolveBindingRootNode(binding, knownRootNode);\n\n const listIndex = getListIndexByBindingInfo(binding);\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n absoluteStateAddress = absoluteAddressOf(stateElement, binding.statePathInfo, listIndex);\n absoluteStateAddressByBinding.set(binding, absoluteStateAddress);\n return absoluteStateAddress;\n}\n\nexport function clearAbsoluteStateAddressByBinding(binding: IBindingInfo) {\n absoluteStateAddressByBinding.delete(binding);\n}","import { createAbsoluteStateAddress } from \"../address/AbsoluteStateAddress\";\nimport { ITreePath, IAbsoluteStateAddress } from \"../address/types\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { IListIndex } from \"../list/types\";\nimport { IBindingInfo } from \"./types\";\n\n/**\n * 絶対アドレス → 登録 binding の台帳。\n *\n * リスト行の絶対アドレスは (absolutePathInfo, listIndex) の組ごとに一意で、\n * 登録される binding は通常 1 本しかない。アドレスごとに Set を確保すると\n * 行×binding の数だけ Set アロケーションが積み上がるため、単一値で持ち\n * 2 本目から Set に昇格する(interestedSessionsByNode と同じ前例)。\n */\nconst bindingsByAbsoluteStateAddress: WeakMap<IAbsoluteStateAddress, IBindingInfo | Set<IBindingInfo>> = new WeakMap();\n\n/**\n * 参照専用の取得。未登録アドレスにエントリを生成・キャッシュしない\n * (リスト置換の drain は大量のバインディング無しアドレスを照会するため、\n * 生成すると空エントリが溜まり続ける)。\n * 戻り値は単一 binding(登録 1 本)か Set(2 本以上)のどちらか。\n * 呼び出し側は Set を変異してはならない(instanceof で分岐できるよう\n * ReadonlySet でなく Set 型で返す)。\n */\nexport function peekBindingsByAbsoluteStateAddress(\n absoluteStateAddress: IAbsoluteStateAddress,\n): IBindingInfo | Set<IBindingInfo> | undefined {\n return bindingsByAbsoluteStateAddress.get(absoluteStateAddress);\n}\n\nexport function addBindingByAbsoluteStateAddress(absoluteStateAddress: IAbsoluteStateAddress, binding: IBindingInfo): void {\n const current = bindingsByAbsoluteStateAddress.get(absoluteStateAddress);\n if (typeof current === \"undefined\") {\n bindingsByAbsoluteStateAddress.set(absoluteStateAddress, binding);\n } else if (current instanceof Set) {\n current.add(binding);\n } else if (current !== binding) {\n bindingsByAbsoluteStateAddress.set(absoluteStateAddress, new Set([current, binding]));\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-added\", absoluteAddress: absoluteStateAddress, binding });\n }\n}\n\nexport function clearBindingSetByAbsoluteStateAddress(absoluteStateAddress: IAbsoluteStateAddress): void {\n bindingsByAbsoluteStateAddress.delete(absoluteStateAddress);\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-cleared\", absoluteAddress: absoluteStateAddress });\n }\n}\n\nexport function removeBindingByAbsoluteStateAddress(absoluteStateAddress: IAbsoluteStateAddress, binding: IBindingInfo): void {\n const current = bindingsByAbsoluteStateAddress.get(absoluteStateAddress);\n if (typeof current === \"undefined\") {\n return;\n }\n if (current instanceof Set) {\n current.delete(binding);\n } else if (current === binding) {\n bindingsByAbsoluteStateAddress.delete(absoluteStateAddress);\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-removed\", absoluteAddress: absoluteStateAddress, binding });\n }\n}\n\n/**\n * パターン索引台帳(リスト行バインディング専用・docs/state-row-instantiation-redesign.md §3-3)。\n *\n * 行バインディングは (absolutePathInfo, listIndex) の 2 段キーで登録し、登録側では\n * AbsoluteStateAddress の intern(アドレスオブジェクト割当 + listIndex ごとの\n * intern 用 WeakMap)を一切行わない。書き込み側(setByAddress → enqueue)は従来\n * どおり intern 済みアドレスを使うため、drain はアドレスの構成要素\n * (absolutePathInfo / listIndex — どちらもオブジェクト同一性が保証済み)で\n * このパターン台帳を引ける。リオーダーは listIndex 同一性キーの帰結として\n * 従来同様ゼロタッチ。wholesale destroy は従来同様削除ゼロ(listIndex ごと GC 崩壊)。\n *\n * devtools 計装(state:binding-added/removed)はプロトコル契約なので、sink 接続時に\n * 限りアドレスを intern してイベントを流す(フック未接続時のコストは分岐 1 個の規範を維持)。\n */\nconst patternLedger: WeakMap<ITreePath, WeakMap<IListIndex, IBindingInfo | Set<IBindingInfo>>> = new WeakMap();\n\nexport function addBindingByPattern(absolutePathInfo: ITreePath, listIndex: IListIndex, binding: IBindingInfo): void {\n let rowMap = patternLedger.get(absolutePathInfo);\n if (typeof rowMap === \"undefined\") {\n rowMap = new WeakMap();\n patternLedger.set(absolutePathInfo, rowMap);\n }\n const current = rowMap.get(listIndex);\n if (typeof current === \"undefined\") {\n rowMap.set(listIndex, binding);\n } else if (current instanceof Set) {\n current.add(binding);\n } else if (current !== binding) {\n rowMap.set(listIndex, new Set([current, binding]));\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-added\", absoluteAddress: createAbsoluteStateAddress(absolutePathInfo, listIndex), binding });\n }\n}\n\nexport function removeBindingByPattern(absolutePathInfo: ITreePath, listIndex: IListIndex, binding: IBindingInfo): void {\n const rowMap = patternLedger.get(absolutePathInfo);\n if (typeof rowMap === \"undefined\") {\n return;\n }\n const current = rowMap.get(listIndex);\n if (typeof current === \"undefined\") {\n return;\n }\n if (current instanceof Set) {\n current.delete(binding);\n } else if (current === binding) {\n rowMap.delete(listIndex);\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-removed\", absoluteAddress: createAbsoluteStateAddress(absolutePathInfo, listIndex), binding });\n }\n}\n\n/**\n * drain(updater)用の統合参照。従来台帳 → パターン台帳の順に引く。\n * 従来台帳を先に引くのは、listIndex 付きでも旧経路(SSR ハイドレーション等)で\n * アドレス台帳に登録される可能性を許容するため(取りこぼし防止)。\n */\nexport function peekBindingsForAddress(\n absoluteStateAddress: IAbsoluteStateAddress,\n): IBindingInfo | Set<IBindingInfo> | undefined {\n const entry = bindingsByAbsoluteStateAddress.get(absoluteStateAddress);\n if (typeof entry !== \"undefined\") {\n return entry;\n }\n if (absoluteStateAddress.listIndex === null) {\n return undefined;\n }\n return patternLedger.get(absoluteStateAddress.absolutePathInfo)?.get(absoluteStateAddress.listIndex);\n}\n","import { WILDCARD } from \"../define\";\nimport { IListIndex } from \"../list/types\";\nimport { getListIndexValue } from \"../list/createListIndex\";\nimport { getListIndexesByList } from \"../list/listIndexesByList\";\nimport { IPathInfo, IStateAddress } from \"./types\";\n\nconst _cache: WeakMap<IListIndex, WeakMap<IPathInfo, IStateAddress>> = new WeakMap();\nconst _cacheNullListIndex: WeakMap<IPathInfo, IStateAddress> = new WeakMap();\n\nclass StateAddress implements IStateAddress {\n readonly pathInfo: IPathInfo;\n readonly listIndex: IListIndex | null;\n private _parentAddress: IStateAddress | undefined;\n /** 行のアドレス(末尾がワイルドカードで行を持つ)。親のアドレスは行の親に付いて変わる */\n private readonly _rowAddress: boolean;\n\n constructor(pathInfo: IPathInfo, listIndex: IListIndex | null) {\n this.pathInfo = pathInfo;\n this.listIndex = listIndex;\n this._rowAddress = listIndex !== null && pathInfo.lastSegment === WILDCARD;\n }\n\n /**\n * 行のアドレス(末尾がワイルドカード)の親は、行の**いまの**親から引く。行の親は台帳が付け替える(外側の行を作り直した・\n * 外側の行が内側の配列を手放した — list/listIndexesByList.ts の #256 / #394)。憶えた親を使い続けると、付け替えの後の\n * 読み書きが、もうその配列を持たない外側の行を経由して別の配列に着地した(#393 / #394)。ただし、いまの親がこのアドレスの\n * キーではこの行の配列を持たず、憶えた親が持つなら、憶えた親を使う — 同じ配列を外側の行ごとに別のキー(`items` と `alt`)に\n * 持つと、行の親はどちらか一方のキーにしか合わない(R1・f6 dual)\n */\n get parentAddress(): IStateAddress | null {\n const cached = this._parentAddress;\n if (typeof cached !== 'undefined' && (!this._rowAddress || cached.listIndex === this.listIndex!.parentListIndex)) {\n return cached;\n }\n const parentPathInfo = this.pathInfo.parentPathInfo;\n if (parentPathInfo === null) {\n return null;\n }\n const lastSegment = this.pathInfo.segments[this.pathInfo.segments.length - 1];\n let parentListIndex: IListIndex | null = null;\n if (lastSegment === WILDCARD) {\n parentListIndex = this.listIndex?.parentListIndex ?? null;\n } else {\n parentListIndex = this.listIndex;\n }\n const next = createStateAddress(parentPathInfo, parentListIndex);\n if (typeof cached !== 'undefined' && !holdsRow(next, this.listIndex!) && holdsRow(cached, this.listIndex!)) {\n return cached;\n }\n return this._parentAddress = next;\n }\n}\n\n/** 外側の行のアドレス `address`(`groups.*.items`)の配列が、行 `row` をその位置に持つか(要素のオブジェクトを素で読む) */\nfunction holdsRow(address: IStateAddress, row: IListIndex): boolean {\n const pathInfo = address.pathInfo;\n let value = getListIndexValue(address.listIndex!);\n for (const segment of pathInfo.segments.slice(pathInfo.wildcardPositions[pathInfo.wildcardCount - 1] + 1)) {\n value = Object(value)[segment];\n }\n return getListIndexesByList(value as unknown[])?.[row.index] === row;\n}\n\nexport function createStateAddress(pathInfo: IPathInfo, listIndex: IListIndex | null): IStateAddress {\n if (listIndex === null) {\n let cached = _cacheNullListIndex.get(pathInfo);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n cached = new StateAddress(pathInfo, null);\n _cacheNullListIndex.set(pathInfo, cached);\n return cached;\n } else {\n let cacheByPathInfo = _cache.get(listIndex);\n if (typeof cacheByPathInfo === \"undefined\") {\n cacheByPathInfo = new WeakMap<IPathInfo, IStateAddress>();\n _cache.set(listIndex, cacheByPathInfo);\n }\n let cached = cacheByPathInfo.get(pathInfo);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n cached = new StateAddress(pathInfo, listIndex);\n cacheByPathInfo.set(pathInfo, cached);\n return cached;\n }\n}","import { createStateAddress } from \"../address/StateAddress\";\nimport { IStateAddress } from \"../address/types\";\nimport { getListIndexByBindingInfo } from \"../list/getListIndexByBindingInfo\";\nimport { raiseError } from \"../raiseError\";\nimport { IBindingInfo } from \"../types\";\n\nconst stateAddressByBindingInfo: WeakMap<IBindingInfo, IStateAddress> = new WeakMap();\n\nexport function getStateAddressByBindingInfo(bindingInfo: IBindingInfo) {\n let stateAddress: IStateAddress | null = null;\n stateAddress = stateAddressByBindingInfo.get(bindingInfo) || null;\n if (stateAddress !== null) {\n return stateAddress;\n }\n if (bindingInfo.statePathInfo.wildcardCount > 0) {\n const listIndex = getListIndexByBindingInfo(bindingInfo);\n if (listIndex === null) {\n raiseError(`Cannot resolve state address for binding with wildcard statePathName \"${bindingInfo.statePathName}\" because list index is null.`);\n }\n stateAddress = createStateAddress(bindingInfo.statePathInfo, listIndex);\n } else {\n stateAddress = createStateAddress(bindingInfo.statePathInfo, null);\n }\n stateAddressByBindingInfo.set(bindingInfo, stateAddress);\n return stateAddress;\n}\n\n// call for change loopContext\nexport function clearStateAddressByBindingInfo(bindingInfo: IBindingInfo) {\n stateAddressByBindingInfo.delete(bindingInfo);\n}","import { IBindingInfo } from \"../types\";\n\n/**\n * イベントハンドラ登録の台帳。\n *\n * 旧実装は Map<string, Set<IBindingInfo>>(文字列キーの強参照 Map)で binding を\n * 保持していたため、binding.node → 行 DOM サブツリー全体が解放不能だった\n * (detach 系はほぼ呼ばれないため、リスト削除後も全イベントバインディングが\n * 永久保持されるリーク。clear-10k 後に 10k 行分の detached DOM が残留していた)。\n *\n * WeakSet(帰属判定・冪等性)と件数カウンタ(「最後の 1 件が外れたらハンドラを\n * 掃除する」判定)に分離し、binding を強参照しない。GC で binding が消えた場合\n * カウンタは減らないが、残るのはキー文字列と数値のみで実害はない。\n */\nexport interface IHandlerBindingRegistry {\n /** binding を key に登録する。新規登録なら true を返す(既登録は冪等に false) */\n add(key: string, binding: IBindingInfo): boolean;\n /** binding を key から外す。key の登録件数が 0 になったら true を返す */\n remove(key: string, binding: IBindingInfo): boolean;\n has(key: string, binding: IBindingInfo): boolean;\n countOf(key: string): number;\n readonly keyCount: number;\n clear(): void;\n}\n\nexport function createHandlerBindingRegistry(): IHandlerBindingRegistry {\n const attachedByKey = new Map<string, WeakSet<IBindingInfo>>();\n const countByKey = new Map<string, number>();\n return {\n add(key: string, binding: IBindingInfo): boolean {\n let attached = attachedByKey.get(key);\n if (typeof attached === \"undefined\") {\n attached = new WeakSet<IBindingInfo>();\n attachedByKey.set(key, attached);\n }\n if (attached.has(binding)) {\n return false;\n }\n attached.add(binding);\n countByKey.set(key, (countByKey.get(key) ?? 0) + 1);\n return true;\n },\n remove(key: string, binding: IBindingInfo): boolean {\n const attached = attachedByKey.get(key);\n if (typeof attached === \"undefined\" || !attached.has(binding)) {\n return false;\n }\n attached.delete(binding);\n const next = (countByKey.get(key) ?? 1) - 1;\n if (next <= 0) {\n attachedByKey.delete(key);\n countByKey.delete(key);\n return true;\n }\n countByKey.set(key, next);\n return false;\n },\n has(key: string, binding: IBindingInfo): boolean {\n return attachedByKey.get(key)?.has(binding) ?? false;\n },\n countOf(key: string): number {\n return countByKey.get(key) ?? 0;\n },\n get keyCount(): number {\n return countByKey.size;\n },\n clear(): void {\n attachedByKey.clear();\n countByKey.clear();\n },\n };\n}\n","import { EVENT_PROP_PREFIX, MODIFIER_READONLY } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo, IFilterInfo } from \"../types\";\nimport { setLoopContextSymbol } from \"../proxy/symbols\";\nimport { filterListKey } from \"../binding/filterKey\";\nimport { createHandlerBindingRegistry } from \"./handlerBindingRegistry\";\n\nconst handlerByHandlerKey: Map<string, (event: Event) => any> = new Map();\n// binding を強参照しない台帳(handlerBindingRegistry.ts のリーク解説を参照)\nconst bindingRegistry = /*#__PURE__*/ createHandlerBindingRegistry();\n\nfunction getHandlerKey(binding: IBindingInfo, eventName: string): string {\n const filterKey = filterListKey(binding.inFilters);\n return `${binding.statePathName}::${eventName}::${filterKey}`;\n}\n\nfunction getEventName(binding: IBindingInfo): string {\n let eventName = 'input';\n for(const modifier of binding.propModifiers) {\n if (modifier.startsWith(EVENT_PROP_PREFIX)) {\n eventName = modifier.slice(EVENT_PROP_PREFIX.length);\n }\n }\n return eventName;\n}\n\nconst checkboxEventHandlerFunction = (\n statePathName: string,\n inFilters: IFilterInfo[],\n) => (event: Event): any => {\n const node = event.target as HTMLInputElement;\n if (node === null) {\n console.warn(`[@wcstack/state] event.target is null.`);\n return;\n }\n if (node.type !== 'checkbox') {\n console.warn(`[@wcstack/state] event.target is not a checkbox input element.`);\n return;\n }\n const checked = node.checked;\n const newValue = node.value;\n let filteredNewValue: unknown = newValue;\n for(const filter of inFilters) {\n filteredNewValue = filter.filterFn(filteredNewValue);\n }\n\n const rootNode = node.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for two-way binding.`);\n }\n\n const loopContext = getLoopContextByNode(node);\n stateElement.createState(\"writable\", (state) => {\n state[setLoopContextSymbol](loopContext, () => {\n let currentValue = state[statePathName];\n if (Array.isArray(currentValue)) {\n if (checked) {\n if (currentValue.indexOf(filteredNewValue) === -1) {\n state[statePathName] = currentValue.concat(filteredNewValue);\n }\n } else {\n const index = currentValue.indexOf(filteredNewValue);\n if (index !== -1) {\n state[statePathName] = currentValue.toSpliced(index, 1);\n }\n }\n } else {\n if (checked) {\n state[statePathName] = [filteredNewValue];\n } else {\n state[statePathName] = [];\n }\n }\n });\n });\n}\n\nexport function attachCheckboxEventHandler(binding: IBindingInfo): boolean {\n if (binding.bindingType === \"checkbox\" && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const key = getHandlerKey(binding, eventName);\n let checkboxEventHandler = handlerByHandlerKey.get(key);\n if (typeof checkboxEventHandler === \"undefined\") {\n checkboxEventHandler = checkboxEventHandlerFunction(\n binding.statePathName,\n binding.inFilters\n );\n handlerByHandlerKey.set(key, checkboxEventHandler);\n }\n (binding.node as Element).addEventListener(eventName, checkboxEventHandler);\n bindingRegistry.add(key, binding);\n return true;\n }\n return false;\n}\n\nexport function detachCheckboxEventHandler(binding: IBindingInfo): boolean {\n if (binding.bindingType === \"checkbox\" && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const key = getHandlerKey(binding, eventName);\n const checkboxEventHandler = handlerByHandlerKey.get(key);\n if (typeof checkboxEventHandler === \"undefined\") {\n return false;\n }\n (binding.node as Element).removeEventListener(eventName, checkboxEventHandler);\n\n if (bindingRegistry.countOf(key) === 0) {\n return false;\n }\n if (bindingRegistry.remove(key, binding)) {\n handlerByHandlerKey.delete(key);\n }\n return true;\n }\n return false;\n}\n\nexport const __private__ = {\n handlerByHandlerKey,\n bindingRegistry,\n getHandlerKey,\n getEventName,\n checkboxEventHandlerFunction,\n};\n","/**\n * captureHandlerRejection.ts\n *\n * state 側ハンドラ(`$on` の event-token subscriber、`onXxx:` の state メソッド、\n * DOM イベント起点の command-token emit)の戻り値を受け取り、Promise が混ざって\n * いれば reject を捕捉して報告する。\n *\n * なぜ必要か:\n * 発火経路はハンドラの完了を待たない。戻り値は `Token.emit` の結果配列にしか現れず、\n * 呼び出し側(eventTokenHandler / handler)はそれを捨てている。そのため **async\n * ハンドラが reject すると unhandled rejection になり**、しかも「どのハンドラで\n * 落ちたか」の手掛かりがスタックにしか残らない(特性化:\n * `__tests__/poc.asyncOnLoopContext.test.ts`)。\n *\n * 握り潰しではない:\n * 可視性は `console.error` で保たれ、state 名・ハンドラ名が付く分むしろ特定は容易に\n * なる。非同期の失敗を「例外の伝播」ではなく「診断可能な報告」に落とすのは\n * never-throw(async-io-node-guidelines.md §3.6)と同じ方針であり、I/O ノードが\n * `error` プロパティへ流すのと同じ位置づけの、state 側ハンドラ版にあたる。\n *\n * **同期 throw の扱いは発火経路で違う。** 同期に呼ぶ経路(twoway / radio / checkbox の\n * `createState`、state 側からの `Token.emit`)では従来どおり呼び出し元へ伝播する。\n * DOM イベント起点(`event/handler.ts`)は `createStateAsync` を使うので、ハンドラの同期 throw も\n * `async` 関数の中で reject に変わり、**呼び出し元(DOM のイベント配送)には届かない** —\n * 捨てると unhandled rejection になるだけなので、`reportHandlerError` で報告へ落とす。\n * プログラマエラーを loud に落とす `raiseError` の意図(見えること)はそれで保たれる。\n */\n\nfunction isThenable(value: unknown): value is PromiseLike<unknown> {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\n/**\n * @param result ハンドラ呼び出しの戻り値。`Token.emit` の結果配列(subscriber ごとの\n * 戻り値)と、単一ハンドラの戻り値の両方を受ける。\n * @param describe 報告に載せるハンドラの識別名(例: `$on.\"rowFailed\" of state \"default\"`)。\n */\n/**\n * ハンドラの失敗を報告する(発火経路が呼び出し元へ投げ返せないとき)。\n * 文言は `captureHandlerRejection` と同じ形にして、報告の出どころを 1 つに保つ。\n */\nexport function reportHandlerError(error: unknown, describe: string): void {\n console.error(`[wcstack/state] ${describe} rejected.`, error);\n}\n\nexport function captureHandlerRejection(result: unknown, describe: string): void {\n // emit は subscriber ごとの戻り値配列。単一ハンドラの戻り値はそのまま届く。\n const values = Array.isArray(result) ? result : [result];\n for (const value of values) {\n if (!isThenable(value)) {\n continue;\n }\n // Promise.resolve は native Promise をそのまま返すため、catch の登録によって\n // 元の Promise が handled になる(thenable は同値の Promise に包まれる)。\n Promise.resolve(value).catch((error: unknown) => reportHandlerError(error, describe));\n }\n}\n","// command-token / event-token が共有する pub/sub プリミティブ。\n// _subscribers は Set のため挿入順を保持する。\n// emit() は subscribe() された順に呼び出され、戻り値配列も同じ順序で返る。\n//\n// 「誰が subscribe し誰が emit するか」だけが command / event の違い:\n// - command-token: element が subscribe / state が emit\n// - event-token: state(`$on`) が subscribe / element(listener) が emit\n\nexport type TokenSubscriber = (...args: unknown[]) => unknown;\n\nexport interface IToken {\n readonly name: string;\n readonly size: number;\n subscribe(fn: TokenSubscriber): () => void;\n unsubscribe(fn: TokenSubscriber): boolean;\n emit(...args: unknown[]): unknown[];\n}\n\nexport class Token implements IToken {\n private _name: string;\n private _subscribers: Set<TokenSubscriber> = new Set();\n\n constructor(name: string) {\n this._name = name;\n }\n\n get name(): string {\n return this._name;\n }\n\n get size(): number {\n return this._subscribers.size;\n }\n\n subscribe(fn: TokenSubscriber): () => void {\n this._subscribers.add(fn);\n return () => {\n this._subscribers.delete(fn);\n };\n }\n\n unsubscribe(fn: TokenSubscriber): boolean {\n return this._subscribers.delete(fn);\n }\n\n /**\n * 全 subscriber へ配る。**1 つが throw しても残りへ配り続ける** — トークンはファンアウトの\n * 口で、購読者どうしは互いを知らない(README の「click fans the command out to every\n * subscriber」の例は、片方の要素が投げたらもう片方に届かない形では成り立たない)。\n * 投げた分は握り潰さず `console.error` に載せ、結果配列にはその位置を `undefined` で残す。\n *\n * 握り潰しでないことの根拠は `event/captureHandlerRejection.ts` と同じ: 発火経路は\n * ハンドラの完了を待たず、DOM イベント起点では例外を呼び出し元へ投げ返せない。\n * 「例外の伝播」ではなく「診断可能な報告」に落とすのが state 側ハンドラの方針。\n */\n emit(...args: unknown[]): unknown[] {\n const results: unknown[] = [];\n for (const fn of this._subscribers) {\n try {\n results.push(fn(...args));\n } catch (error) {\n results.push(undefined);\n console.error(`[wcstack/state] a subscriber of token \"${this.name}\" threw; the remaining subscribers still received it.`, error);\n }\n }\n return results;\n }\n}\n","import type { IStateElement } from \"../components/types\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { Token } from \"../token/Token\";\n\n// EventToken は共有 pub/sub プリミティブ Token の薄い特化(element→state 方向)。\n// instanceof による型判別を成立させるため独立クラスとして維持する。\nexport class EventToken extends Token {\n /**\n * 属する state 要素(devtools のツリー識別 — protocol v2 追補)。\n * registry(getOrCreateEventToken)経由の生成でのみ渡る optional 参照。\n * 寿命は registry 側の WeakMap が管理する(CommandToken と同じ位置づけ)。\n */\n private _stateElement: IStateElement | undefined;\n\n constructor(name: string, stateElement?: IStateElement) {\n super(name);\n this._stateElement = stateElement;\n }\n\n emit(...args: unknown[]): unknown[] {\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"state:token-emit\",\n kind: \"event\",\n tokenName: this.name,\n args,\n subscriberCount: this.size,\n stateElement: this._stateElement,\n });\n }\n return super.emit(...args);\n }\n}\n\nexport function isEventToken(value: unknown): value is EventToken {\n return value instanceof EventToken;\n}\n","import { IStateElement } from \"../components/types\";\nimport { EventToken } from \"./EventToken\";\n\nconst registryByStateElement: WeakMap<IStateElement, Map<string, EventToken>> = new WeakMap();\n\nexport function getOrCreateEventToken(stateElement: IStateElement, name: string): EventToken {\n let registry = registryByStateElement.get(stateElement);\n if (typeof registry === \"undefined\") {\n registry = new Map<string, EventToken>();\n registryByStateElement.set(stateElement, registry);\n }\n let token = registry.get(name);\n if (typeof token === \"undefined\") {\n // stateElement を渡すのは devtools のツリー識別(protocol v2 追補)のため\n token = new EventToken(name, stateElement);\n registry.set(name, token);\n }\n return token;\n}\n\nexport function clearEventTokenRegistry(stateElement: IStateElement): void {\n registryByStateElement.delete(stateElement);\n}\n\nexport const __private__ = {\n registryByStateElement,\n};\n","/**\n * eventToken.<propertyName>: <eventTokenName> バインディングの attach ハンドラ。\n *\n * command-token の双対(element→state)。要素が dispatch する CustomEvent を受けて\n * event-token を emit し、state 側の `$on` ハンドラ群へ pub/sub で配送する。\n *\n * 設計(MVP スコープ: wc-bindable カスタム要素のみ):\n * - キーは生イベント名ではなく **wcBindable property 名**。実 DOM イベント名は\n * wcBindable.properties[].event から解決する(command-token が wcBindable.commands で\n * 検証するのと対称。コロンを含む namespaced event 名と binding 構文の `:` 衝突も回避)。\n * - <prop> が wcBindable.properties に宣言されていることは attach 時に検証する\n * (要素クラス参照のみで DOM 接続に非依存。fail-fast / typo 耐性)。\n * - <eventTokenName> が $eventTokens に宣言されていることは **発火時** に検証する\n * (state 解決が必要なため。詳細は下記の fire-time 解決の注記を参照)。\n * - subscriber 引数規約は `(state, event, ...listIndexes)`。\n * - modifier `#prevent` / `#stop` は既存イベント binding と同等にサポート。\n *\n * token はイベント発火ごとに registry から解決する(getOrCreateEventToken)。これにより\n * state の再 set で registry が作り直されても最新の subscriber 群へ配送できる。\n *\n * state element の解決と `$eventTokens` 検証は **発火時** に行う(attach 時ではない)。\n * 構造ブロック(for/if)や SSR hydration では、binding 初期化時にノードが detached な\n * DocumentFragment / wrapper 上にあり、その時点では element.getRootNode() から state を\n * 解決できないため。onclick / two-way ハンドラと同じく fire-time 解決に揃えている。\n */\n\nimport { EVENT_TOKEN_NAMESPACE, MODIFIER_PREVENT, MODIFIER_STOP } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { setLoopContextSymbol } from \"../proxy/symbols\";\nimport { getScopedIndexes } from \"../list/wildcardLevel\";\nimport { didYouMean, LINT_HINT } from \"../errorGuidance\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration, ReadBindableResult } from \"../protocol/wcBindableReader\";\nimport { IBindingInfo } from \"../types\";\nimport { captureHandlerRejection } from \"./captureHandlerRejection\";\nimport { getOrCreateEventToken } from \"./eventTokenRegistry\";\n\ninterface IEventTokenListener {\n readonly eventName: string;\n readonly handler: (event: Event) => void;\n}\n\nconst listenerByBinding: WeakMap<IBindingInfo, IEventTokenListener> = new WeakMap();\n\nfunction getWcBindable(element: Element): ReadBindableResult | null {\n const customTagName = getCustomElement(element);\n if (customTagName === null) {\n return null;\n }\n // attach 側で未定義要素は whenDefined 後に再試行するため、ここに来る時点で customClass は定義済み。\n return readBindableDeclaration(element);\n}\n\nexport function attachEventTokenHandler(binding: IBindingInfo): boolean {\n if (binding.propSegments[0] !== EVENT_TOKEN_NAMESPACE) {\n return false;\n }\n const element = binding.node as Element;\n\n // カスタム要素が未定義なら定義後に再試行(wcBindable が必要なため)。\n const customTagName = getCustomElement(element);\n const registry = getCustomElementRegistry(element);\n if (customTagName !== null && registry?.get(customTagName) === undefined) {\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${customTagName}>.`);\n }\n return true;\n }\n\n // 再評価で二重 attach しない。\n if (listenerByBinding.has(binding)) {\n return true;\n }\n\n const propertyName = binding.propSegments[1];\n if (typeof propertyName !== \"string\" || propertyName.length === 0) {\n raiseError(`eventToken binding requires a property name (e.g., \"eventToken.error\").`);\n }\n\n const bindable = getWcBindable(element);\n if (bindable === null) {\n raiseError(`eventToken binding requires a wc-bindable custom element. <${element.tagName.toLowerCase()}> is not wc-bindable.`);\n }\n const propDesc = bindable.knownProperties.get(propertyName);\n if (typeof propDesc === \"undefined\") {\n raiseError(`Property \"${propertyName}\" is not declared in wcBindable.properties of <${element.tagName.toLowerCase()}>.${didYouMean(propertyName, bindable.knownProperties.keys())}`);\n }\n const eventName = propDesc.event;\n\n const tokenName = binding.statePathName;\n const modifiers = binding.propModifiers;\n const handler = (event: Event): void => {\n if (modifiers.includes(MODIFIER_PREVENT)) event.preventDefault();\n if (modifiers.includes(MODIFIER_STOP)) event.stopPropagation();\n\n // state は発火時の live root から解決する(attach 時は detached の可能性があるため)。\n const rootNode = element.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for eventToken handler.`);\n }\n if (!stateElement.eventTokenNames.has(tokenName)) {\n // lint も同じケースを wcs/token-undeclared で検出する(三面同語彙)。\n raiseError(`[wcs/token-undeclared] eventToken \"${tokenName}\" is not declared in $eventTokens.${didYouMean(tokenName, stateElement.eventTokenNames)}${LINT_HINT}`);\n }\n const loopContext = getLoopContextByNode(element);\n stateElement.createStateAsync(\"writable\", async (state) => {\n const results = state[setLoopContextSymbol](loopContext, () => {\n const indexes = loopContext !== null\n ? getScopedIndexes(loopContext.listIndex, loopContext.pathInfo.wildcardCount) : [];\n const token = getOrCreateEventToken(stateElement, tokenName);\n return token.emit(state, event, ...indexes);\n });\n // この経路はハンドラの完了を待たない(emit の戻り値はここでしか見えない)。\n // async な $on ハンドラの reject を unhandled にせず報告へ落とす。\n captureHandlerRejection(results, `$on.\"${tokenName}\"`);\n });\n };\n\n element.addEventListener(eventName, handler);\n listenerByBinding.set(binding, { eventName, handler });\n return true;\n}\n\nexport function detachEventTokenHandler(binding: IBindingInfo): boolean {\n if (binding.propSegments[0] !== EVENT_TOKEN_NAMESPACE) {\n return false;\n }\n const listener = listenerByBinding.get(binding);\n if (typeof listener === \"undefined\") {\n return false;\n }\n (binding.node as Element).removeEventListener(listener.eventName, listener.handler);\n listenerByBinding.delete(binding);\n return true;\n}\n\nexport const __private__ = {\n listenerByBinding,\n};\n","import type { IStateElement } from \"../components/types\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { Token } from \"../token/Token\";\nimport { ICommandToken } from \"./types\";\n\n// CommandToken は共有 pub/sub プリミティブ Token の薄い特化。\n// instanceof による型判別を成立させるため独立クラスとして維持する。\n//\nexport class CommandToken extends Token implements ICommandToken {\n /**\n * 属する state 要素(devtools のツリー識別 — protocol v2 追補)。\n * registry(getOrCreateCommandToken)経由の生成でのみ渡る optional 参照で、\n * token の寿命は registry 側の WeakMap が state 要素に紐づけている(ここが\n * 寿命を延ばす新しい経路にはならない)。emit の payload にだけ載せる。\n */\n private _stateElement: IStateElement | undefined;\n\n constructor(name: string, stateElement?: IStateElement) {\n super(name);\n this._stateElement = stateElement;\n }\n\n emit(...args: unknown[]): unknown[] {\n if (devtoolsSink !== null) {\n // subscriberCount 0 の emit(空撃ち)もそのまま流す — whenDefined 前の\n // command 空撃ちレース類をタイムラインで可視化するため\n devtoolsSink({\n type: \"state:token-emit\",\n kind: \"command\",\n tokenName: this.name,\n args,\n subscriberCount: this.size,\n stateElement: this._stateElement,\n });\n }\n return super.emit(...args);\n }\n}\n\nexport function isCommandToken(value: unknown): value is ICommandToken {\n return value instanceof CommandToken;\n}\n","import { createStateAddress } from \"../address/StateAddress\";\nimport { IPathInfo } from \"../address/types\";\nimport { isCommandToken } from \"../command/CommandToken\";\nimport { ICommandToken } from \"../command/types\";\nimport { EVENT_PROP_PREFIX, MODIFIER_PREVENT, MODIFIER_STOP, STATE_COMMAND_NAMESPACE_NAME } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { getByAddressSymbol, setLoopContextSymbol } from \"../proxy/symbols\";\nimport { getScopedIndexes } from \"../list/wildcardLevel\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo } from \"../types\";\nimport { captureHandlerRejection, reportHandlerError } from \"./captureHandlerRejection\";\nimport { createHandlerBindingRegistry } from \"./handlerBindingRegistry\";\n\n// onclick: $command.<name> のように、DOM イベントから command token を直接 emit する形式かを判定する。\n// 右辺が $command 名前空間配下のパス($command.<token>)のときに true。\nfunction isCommandTokenPath(statePathName: string): boolean {\n return statePathName.startsWith(STATE_COMMAND_NAMESPACE_NAME + \".\");\n}\n\nconst handlerByHandlerKey: Map<string, (event: Event) => any> = new Map();\n// binding を強参照しない台帳(handlerBindingRegistry.ts のリーク解説を参照)\n// 純粋な割り当て(Map 2 個)。バンドラが未使用時に落とせるよう明示する(ヘルパーだけの import に残さない)\nconst bindingRegistry = /*#__PURE__*/ createHandlerBindingRegistry();\n\nfunction getHandlerKey(binding: IBindingInfo): string {\n const modifierKey = binding.propModifiers.filter(m => m === MODIFIER_PREVENT || m === MODIFIER_STOP).sort().join(',');\n return `${binding.statePathName}::${modifierKey}`;\n}\n\nconst stateEventHandlerFunction = (\n handlerName: string,\n modifiers: string[],\n statePathInfo: IPathInfo\n) => (event: Event): any => {\n if (modifiers.includes(MODIFIER_PREVENT)) event.preventDefault();\n if (modifiers.includes(MODIFIER_STOP)) event.stopPropagation();\n\n const node = event.target as Element;\n const rootNode = node.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for event handler.`);\n }\n\n const loopContext = getLoopContextByNode(node);\n const isCommand = isCommandTokenPath(handlerName);\n // `createStateAsync` の戻り Promise を捨てると、ハンドラの**同期 throw**(未宣言の\n // command token・state に無いハンドラ名・作者のメソッドが投げた例外)が `async` 関数の中で\n // reject に変わり、そのまま unhandled rejection に沈む。DOM のイベント配送には投げ返せない\n // 経路なので、少なくとも報告へ落とす(captureHandlerRejection.ts の方針と同じ)\n stateElement.createStateAsync(\"writable\", async (state) => {\n const results = state[setLoopContextSymbol](loopContext, () => {\n // マウントされたスコープ(v2): 作者のハンドラが受ける添字は自スコープの\n // ループ分だけ(§4-4 / P2-9)。翻訳で増えたワイルドカード数を落とす。\n // 翻訳された for の台帳に無いループ文脈は外側スコープのもの(境界ホップで\n // 借りた行)なので、作者から見える添字は 0 本。\n // 記録の解決はノードから(findMountRecordForNode)— Shadow 形は rootNode\n // (shadowRoot)で直に引け、Light DOM 形はスコープ根がコンポーネント要素\n // 自身なので祖先走査が要る(rootNode だけ見ると Light DOM で外側の添字が漏れる)\n let scopedWildcardCount = loopContext !== null ? loopContext.pathInfo.wildcardCount : 0;\n if (loopContext !== null) {\n // 添字の段数はスコープ機能の handlerScope hook(webComponent/addressHooks.ts)が決める。\n // hook の無い state は判定 1 個で抜ける\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const scopes = hooks.handlerScope;\n for (let i = 0; i < scopes.length; i++) {\n scopedWildcardCount = scopes[i](stateElement, node, rootNode, loopContext, scopedWildcardCount);\n }\n }\n }\n const indexes = loopContext !== null\n ? getScopedIndexes(loopContext.listIndex, scopedWildcardCount) : [];\n if (isCommand) {\n // command token を解決して emit。引数はハンドラ呼び出しと同じく (event, ...listIndexes) を透過する。\n const token = state[getByAddressSymbol](createStateAddress(statePathInfo, null));\n if (!isCommandToken(token)) {\n raiseError(`Event binding \"${handlerName}\" did not resolve to a CommandToken. Declare the name in $commandTokens and reference it as $command.<name>.`);\n }\n return (token as ICommandToken).emit(event, ...indexes);\n }\n const handler = state[handlerName];\n if (typeof handler !== \"function\") {\n raiseError(`Handler \"${handlerName}\" is not a function on the state tree.`);\n }\n return Reflect.apply(handler, state, [event, ...indexes]);\n });\n // eventTokenHandler と同じく、この経路もハンドラの完了を待たない。async な\n // state メソッド / command subscriber の reject を unhandled にせず報告へ落とす。\n captureHandlerRejection(results, `\"${handlerName}\"`);\n }).catch((error: unknown) => reportHandlerError(error, `\"${handlerName}\"`));\n}\n\n/**\n * DOM イベントリスナを張る束縛かを判定する(要件 B5 / D34)。\n *\n * 名前の綴り(`on` で始まるか)だけでは足りない: 明示のプロパティ形 `.online:` は\n * `propName` が `\"online\"` でも **プロパティ束縛**(`bindingType: 'prop'`)であって\n * `\"line\"` イベントの購読ではない。`spread` で配線される `once`(`<wcs-timer>` /\n * `<wcs-raf>` …)も同じ形。種別で判定することで、`for` 行の内(`structural/rowPlan.ts`\n * の `isEvent`)と外で同じ束縛が同じ意味になる。\n *\n * `eventToken.<prop>:` も `bindingType: 'event'` だが DOM イベントではない(pub/sub 配線)\n * ので、`on` 接頭辞の検査も併せて残す。\n */\nfunction isDomEventBinding(binding: IBindingInfo): boolean {\n return binding.bindingType === 'event' && binding.propName.startsWith(EVENT_PROP_PREFIX);\n}\n\nexport function attachEventHandler(binding: IBindingInfo): boolean {\n if (!isDomEventBinding(binding)) {\n return false;\n }\n const key = getHandlerKey(binding);\n let stateEventHandler = handlerByHandlerKey.get(key);\n if (typeof stateEventHandler === \"undefined\") {\n stateEventHandler = stateEventHandlerFunction(binding.statePathName, binding.propModifiers, binding.statePathInfo);\n handlerByHandlerKey.set(key, stateEventHandler);\n }\n\n const eventName = binding.propName.slice(2);\n (binding.node as Element).addEventListener(eventName, stateEventHandler);\n\n bindingRegistry.add(key, binding);\n return true;\n}\n\nexport function detachEventHandler(binding: IBindingInfo): boolean {\n if (!isDomEventBinding(binding)) {\n return false;\n }\n const key = getHandlerKey(binding);\n const stateEventHandler = handlerByHandlerKey.get(key);\n if (typeof stateEventHandler === \"undefined\") {\n return false;\n }\n const eventName = binding.propName.slice(2);\n (binding.node as Element).removeEventListener(eventName, stateEventHandler);\n\n if (bindingRegistry.countOf(key) === 0) {\n return false;\n }\n if (bindingRegistry.remove(key, binding)) {\n handlerByHandlerKey.delete(key);\n }\n return true;\n}\n\nexport const __private__ = {\n handlerByHandlerKey,\n bindingRegistry,\n getHandlerKey,\n};\n\n","import { EVENT_PROP_PREFIX, MODIFIER_READONLY } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo, IFilterInfo } from \"../types\";\nimport { setLoopContextSymbol } from \"../proxy/symbols\";\nimport { filterListKey } from \"../binding/filterKey\";\nimport { createHandlerBindingRegistry } from \"./handlerBindingRegistry\";\n\nconst handlerByHandlerKey: Map<string, (event: Event) => any> = new Map();\n// binding を強参照しない台帳(handlerBindingRegistry.ts のリーク解説を参照)\nconst bindingRegistry = /*#__PURE__*/ createHandlerBindingRegistry();\n\nfunction getHandlerKey(binding: IBindingInfo, eventName: string): string {\n const filterKey = filterListKey(binding.inFilters);\n return `${binding.statePathName}::${eventName}::${filterKey}`;\n}\n\nfunction getEventName(binding: IBindingInfo): string {\n let eventName = 'input';\n for(const modifier of binding.propModifiers) {\n if (modifier.startsWith(EVENT_PROP_PREFIX)) {\n eventName = modifier.slice(EVENT_PROP_PREFIX.length);\n }\n }\n return eventName;\n}\n\nconst radioEventHandlerFunction = (\n statePathName: string,\n inFilters: IFilterInfo[],\n) => (event: Event): any => {\n const node = event.target as HTMLInputElement;\n if (node === null) {\n console.warn(`[@wcstack/state] event.target is null.`);\n return;\n }\n if (node.type !== 'radio') {\n console.warn(`[@wcstack/state] event.target is not a radio input element.`);\n return;\n }\n if (node.checked === false) {\n return;\n }\n const newValue = node.value;\n let filteredNewValue: unknown = newValue;\n for(const filter of inFilters) {\n filteredNewValue = filter.filterFn(filteredNewValue);\n }\n\n const rootNode = node.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for two-way binding.`);\n }\n\n const loopContext = getLoopContextByNode(node);\n stateElement.createState(\"writable\", (state) => {\n state[setLoopContextSymbol](loopContext, () => {\n state[statePathName] = filteredNewValue;\n });\n });\n}\n\nexport function attachRadioEventHandler(binding: IBindingInfo): boolean {\n if (binding.bindingType === \"radio\" && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const key = getHandlerKey(binding, eventName);\n let radioEventHandler = handlerByHandlerKey.get(key);\n if (typeof radioEventHandler === \"undefined\") {\n radioEventHandler = radioEventHandlerFunction(\n binding.statePathName,\n binding.inFilters\n );\n handlerByHandlerKey.set(key, radioEventHandler);\n }\n (binding.node as Element).addEventListener(eventName, radioEventHandler);\n bindingRegistry.add(key, binding);\n return true;\n }\n return false;\n}\n\nexport function detachRadioEventHandler(binding: IBindingInfo): boolean {\n if (binding.bindingType === \"radio\" && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const key = getHandlerKey(binding, eventName);\n const radioEventHandler = handlerByHandlerKey.get(key);\n if (typeof radioEventHandler === \"undefined\") {\n return false;\n }\n (binding.node as Element).removeEventListener(eventName, radioEventHandler);\n\n if (bindingRegistry.countOf(key) === 0) {\n return false;\n }\n if (bindingRegistry.remove(key, binding)) {\n handlerByHandlerKey.delete(key);\n }\n return true;\n }\n return false;\n}\n\nexport const __private__ = {\n handlerByHandlerKey,\n bindingRegistry,\n getHandlerKey,\n getEventName,\n radioEventHandlerFunction,\n};\n","import { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\nimport { raiseError } from \"../raiseError\";\n\nconst CHECK_TYPES = new Set([ 'radio', 'checkbox' ]);\nconst DEFAULT_VALUE_PROP_NAMES = new Set([ 'value', 'valueAsNumber', 'valueAsDate' ]);\n\nexport function isPossibleTwoWay(node: Node, propName: string): boolean {\n if (node.nodeType !== Node.ELEMENT_NODE) {\n return false;\n }\n const element = node as Element;\n const tagName = element.tagName.toLowerCase();\n if (tagName === 'input') {\n const inputType = (element.getAttribute('type') || 'text').toLowerCase();\n if (inputType === 'button') {\n return false;\n }\n if (CHECK_TYPES.has(inputType) && propName === 'checked') {\n return true;\n }\n if (DEFAULT_VALUE_PROP_NAMES.has(propName)) {\n return true;\n }\n }\n if (tagName === 'select' && propName === 'value') {\n return true;\n }\n if (tagName === 'textarea' && propName === 'value') {\n return true;\n }\n const customTagName = getCustomElement(element);\n if (customTagName !== null) {\n const customClass = getCustomElementRegistry(element)?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n raiseError(`Custom element <${customTagName}> is not defined. Cannot determine if property \"${propName}\" is suitable for two-way binding.`);\n }\n const bindable = readBindableDeclaration(element);\n if (bindable?.knownProperties.has(propName)) {\n return true;\n }\n }\n return false;\n}\n","/**\n * propagation/propagation.ts\n *\n * Phase 3 の因果伝播コア(feature flag `enablePropagationContext` 下)。\n * 依存は types のみの葉モジュールとし、twowayHandler / applyChangeToProperty /\n * setByAddress / updater の計装点から循環 import なしで参照できるようにする。\n *\n * wire 識別は (node × member × statePathName) で行う。設計書の\n * WriteReceipt は bindingId + generation を持つが、twoway handler は共有\n * handler(handlerByHandlerKey)で binding インスタンスに到達できないため、\n * runtime の edge / receipt 照合キーは wire 単位とする。BindingSession\n * generation との統合(再 attach 後の edge ID 非再利用)は session 側の\n * 計装が揃う段階で bindingGeneration に反映する。\n */\n\nimport { IPropagationContext, IWriteReceipt } from \"./types\";\n\nexport type PropagationEdgeDirection = \"to-element\" | \"to-state\";\n\nlet nextWireId = 1;\nlet nextTransactionId = 1;\nlet nextSynchronousScopeId = 1;\n\n// node を強参照しない wire 台帳。inner key = `${statePathName}::${member}`\nconst wireIdsByNode = new WeakMap<Node, Map<string, number>>();\n\nfunction wireKey(member: string, statePathName: string): string {\n return `${statePathName}::${member}`;\n}\n\n/**\n * wire(配線)の安定 ID を返す。edge ID の基底と receipt の bindingId に使う。\n */\nexport function getWireId(\n node: Node,\n member: string,\n statePathName: string,\n): number {\n let byKey = wireIdsByNode.get(node);\n if (typeof byKey === \"undefined\") {\n byKey = new Map();\n wireIdsByNode.set(node, byKey);\n }\n const key = wireKey(member, statePathName);\n let wireId = byKey.get(key);\n if (typeof wireId === \"undefined\") {\n wireId = nextWireId++;\n byKey.set(key, wireId);\n }\n return wireId;\n}\n\n/** wire × 方向 → edge ID。方向を含めるため再利用されない */\nexport function getEdgeId(wireId: number, direction: PropagationEdgeDirection): number {\n return direction === \"to-element\" ? wireId * 2 : wireId * 2 + 1;\n}\n\nconst EMPTY_EDGES: ReadonlySet<number> = new Set<number>();\n\n/** 外部 event / API update ごとの transaction 開始。current context は変更しない */\nexport function beginPropagationTransaction(originBindingId: number): IPropagationContext {\n return {\n transactionId: nextTransactionId++,\n originBindingId,\n visitedEdges: EMPTY_EDGES,\n hop: 0,\n };\n}\n\n/** edge を 1 つ通過した新しい context を返す(visitedEdges 追加・hop+1) */\nexport function extendPropagationContext(\n context: IPropagationContext,\n edgeId: number,\n): IPropagationContext {\n const visitedEdges = new Set(context.visitedEdges);\n visitedEdges.add(edgeId);\n return {\n transactionId: context.transactionId,\n originBindingId: context.originBindingId,\n visitedEdges,\n hop: context.hop + 1,\n };\n}\n\n// 同期 dynamic scope の current context(updater drain / element 書き込み中に設定)\nlet currentContext: IPropagationContext | null = null;\n\nexport function getCurrentPropagationContext(): IPropagationContext | null {\n return currentContext;\n}\n\nexport function runWithPropagationContext<T>(\n context: IPropagationContext | null,\n callback: () => T,\n): T {\n const previous = currentContext;\n currentContext = context;\n try {\n return callback();\n } finally {\n currentContext = previous;\n }\n}\n\n// WriteReceipt: 同期 scope 限定のスタック。scope 終了時に必ず破棄される\ninterface IActiveWriteReceipt {\n readonly receipt: IWriteReceipt;\n readonly node: Node;\n}\n\nconst receiptStack: IActiveWriteReceipt[] = [];\n\n/**\n * state → element 書き込みを receipt scope で包んで実行する。\n * setter が同期 dispatch する event は matchWriteReceipt でこの receipt を観測できる。\n */\nexport function runWithWriteReceipt<T>(\n node: Node,\n member: string,\n writtenValue: unknown,\n bindingId: number,\n transactionId: number,\n callback: () => T,\n): T {\n const receipt: IWriteReceipt = {\n bindingId,\n bindingGeneration: 0,\n member,\n transactionId,\n synchronousScopeId: nextSynchronousScopeId++,\n writtenValue,\n };\n receiptStack.push({ receipt, node });\n try {\n return callback();\n } finally {\n receiptStack.pop();\n }\n}\n\n/**\n * (node, member) に対する最も内側の active receipt を返す。\n * confirmation / normalization の判定(writtenValue との Object.is 比較)は\n * 呼び出し側が行う。scope 外(非同期に届いた event)では null。\n */\nexport function matchWriteReceipt(node: Node, member: string): IWriteReceipt | null {\n for (let i = receiptStack.length - 1; i >= 0; i--) {\n const active = receiptStack[i];\n if (active.node === node && active.receipt.member === member) {\n return active.receipt;\n }\n }\n return null;\n}\n\n// テスト用\nexport const __private__ = {\n receiptStack,\n};\n","/**\n * occurrenceWrite.ts\n *\n * 要素(wc-bindable の出力・双方向バインドの要素)から届いた値を state へ書き込む 1 write に、\n * その出どころを伝える one-shot トークン。\n *\n * 1. occurrence(wc-bindable の `semantics: \"event\"`)は same-value guard(`config.sameValueGuard`・\n * 既定 ON)を 1 回分だけ飛ばす。\n * same-value guard は primitive が `Object.is` 同値なら set / enqueue / 依存伝播 / DOM 適用 /\n * `$updatedCallback` をまるごとスキップする。current value(state)にとっては正しい最適化だが、\n * occurrence(同じ payload でも「もう一度起きた」ことに意味がある)へ適用すると発生を取りこぼす。\n * どちらであるかは producer の declaration が `semantics` で宣言する\n * (docs/architecture-hardening/12-wc-bindable-observable-inventory.md)。\n * 2. 要素から来た書き込みはどれも、リストの要素(`for` の行そのもの — `status: .`)へ書いても入れ替え\n * (#4 の同一性モデル)として扱わない。要素が自分の行へ出す値は「その行の値の更新」で、別の行との\n * 入れ替えではない。入れ替えとして扱うと、同じ値から進む行が別の行と入れ替わり、以後の出力が別の行に\n * 届いた(#337)。\n *\n * one-shot にしている理由:\n * フラグを書き込みの呼び出しスタック全体へ張ると、その内側で走る `$updatedCallback` や\n * 依存伝播が行う無関係な書き込みまで巻き込む。`setByAddress` が最初のガード評価で\n * トークンを消費するため、影響は目的の 1 write に閉じる。\n */\n\nimport type { IStateElement } from \"../components/types\";\nimport type { ILoopContext } from \"../list/types\";\nimport { setLoopContextSymbol } from \"./symbols\";\n\nlet pending = 0;\n\n/**\n * 要素から届いた値を、その要素の行の文脈で state へ書く(双方向バインドの commit と初期同期)。\n * `occurrence` なら同値ガードも飛ばす。書き込みが setByAddress へ届かなくても、トークンはここで破棄する。\n */\nexport function commitElementValue(\n stateElement: IStateElement,\n loopContext: ILoopContext | null,\n statePathName: string,\n value: unknown,\n occurrence = false,\n): void {\n pending = occurrence ? 2 : 1;\n try {\n stateElement.createState(\"writable\", (state) => {\n state[setLoopContextSymbol](loopContext, () => {\n state[statePathName] = value;\n });\n });\n } finally {\n pending = 0;\n }\n}\n\n/**\n * ガード評価側が呼ぶ。0 = 要素から来ていない、1 = 要素から来た、2 = 要素から来た occurrence。\n * トークンは呼んだ時点で消費される。\n */\nexport function consumeElementWrite(): number {\n const consumed = pending;\n pending = 0;\n return consumed;\n}\n","import { isPossibleTwoWay } from \"./isPossibleTwoWay\";\nimport { EVENT_PROP_PREFIX, MODIFIER_READONLY } from \"../define\";\nimport { config } from \"../config\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { beginPropagationTransaction, extendPropagationContext, getCurrentPropagationContext, getEdgeId, getWireId, matchWriteReceipt, runWithPropagationContext } from \"../propagation/propagation\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo, IFilterInfo } from \"../types\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\nimport { filterListKey } from \"../binding/filterKey\";\nimport { createHandlerBindingRegistry } from \"./handlerBindingRegistry\";\nimport { commitElementValue } from \"../proxy/occurrenceWrite\";\n\nconst handlerByHandlerKey: Map<string, (event: Event) => any> = new Map();\n// binding を強参照しない台帳(handlerBindingRegistry.ts のリーク解説を参照)\nconst bindingRegistry = /*#__PURE__*/ createHandlerBindingRegistry();\nconst producerValueObserversByNode = new WeakMap<Node, Map<string, Set<(value: unknown) => void>>>();\n\nconst DEFAULT_GETTER = (e: Event) => (e as CustomEvent).detail;\n\n/**\n * 既定 getter(`(e) => e.detail`)が要素の宣言と噛み合っていない典型 2 形を、\n * 要素 × プロパティごとに 1 回だけ警告する(README「What the element writes back」)。\n *\n * (a) detail が undefined なのに `element[propName]` には値がある —\n * CustomEvent でない Event を dispatch している / `detail` を付け忘れている\n * (b) detail が `{ <propName>: … }` の形のラッパーで、`element[propName]` はオブジェクトでない —\n * `getter: (e) => e.detail.<propName>` が要る\n *\n * どちらも state には黙って undefined / ラッパーが書かれ、例外も lint 診断も出ない\n * (payload の形は静的に見えない)。挙動は変えない — 書き込みはそのまま行う。\n * occurrence(`semantics: \"event\"`)は payload が任意なので対象外(呼び出し側で除外)。\n */\nconst warnedDefaultGetter = new WeakMap<Element, Set<string>>();\nfunction warnDefaultGetterMismatch(node: Element, propName: string, detail: unknown): void {\n const propValue = (node as any)[propName];\n let reason: string | null = null;\n if (typeof detail === \"undefined\") {\n if (typeof propValue !== \"undefined\") {\n reason = `the event carried no detail (undefined) while element.${propName} is ${typeof propValue}`;\n }\n } else if (\n detail !== null && typeof detail === \"object\" && Object.prototype.hasOwnProperty.call(detail, propName)\n && (propValue === null || typeof propValue !== \"object\")\n ) {\n reason = `the event's detail is an object with a \"${propName}\" key while element.${propName} is ${typeof propValue}`;\n }\n if (reason === null) return;\n let props = warnedDefaultGetter.get(node);\n if (typeof props === \"undefined\") {\n props = new Set();\n warnedDefaultGetter.set(node, props);\n }\n if (props.has(propName)) return;\n props.add(propName);\n console.warn(\n `[@wcstack/state] [wcs/default-getter-mismatch] <${node.tagName.toLowerCase()}> \"${propName}\": ${reason}. ` +\n `With no getter, state receives e.detail as-is. Dispatch the value itself as detail, or declare ` +\n `getter (e.g. (e) => e.detail.${propName}, or (e) => e.target.${propName}) on that wcBindable property.`\n );\n}\n\n/**\n * getter 関数ごとの安定した識別子。\n *\n * ハンドラのクロージャは `valueGetter` の**実体**を捕捉するのに、鍵は「getter があるか」の\n * 真偽しか持っていなかった。propName / イベント名 / state パス / フィルタ列が同じで getter だけ\n * 違う 2 つの wc-bindable タグを同じパスに繋ぐと、後から配線した方が**先のタグの getter で\n * 畳んだ値**を state に書く。`filterListKey` を入れて塞いだのと同じ不完全さが getter に残っていた。\n */\nconst getterIds = new WeakMap<object, number>();\nlet nextGetterId = 0;\nfunction getterIdOf(valueGetter: ((event: Event) => any) | null): string {\n if (valueGetter === null) {\n return \"n\";\n }\n let id = getterIds.get(valueGetter);\n if (typeof id === \"undefined\") {\n getterIds.set(valueGetter, id = ++nextGetterId);\n }\n return `g${id}`;\n}\n\n/**\n * attach 時に控えた「何を、どのイベント名で付けたか」。**detach はここだけを見る。**\n *\n * `wcBindable` の宣言は live と規定されている(`protocol/wcBindableReader.ts`)ので、attach と\n * detach の間に差し替わりうる(composite shell は `target.constructor.wcBindable` で synthesized\n * 宣言を出すので絵空事ではない)。detach 側で作り直すと、宣言に依存する 3 つ — 二方向かの判定\n * (`isPossibleTwoWay`)、イベント名(`getEventName`)、ハンドラの鍵(`getHandlerKey`)— が\n * すべてずれうる。判定がずれれば門で早戻りしてリスナが残り、イベント名や鍵がずれれば\n * `removeEventListener` が空振りしてリスナが残る。**控えがあるかどうかが「attach したか」\n * そのもの**なので、detach は宣言を一切読み直さない。\n */\ninterface IAttachedTwoway {\n readonly key: string;\n readonly eventName: string;\n}\nconst attachedByBinding = new WeakMap<IBindingInfo, IAttachedTwoway>();\n\nfunction getHandlerKey(binding: IBindingInfo, eventName: string, valueGetter: ((event: Event) => any) | null, isOccurrence: boolean): string {\n const filterKey = filterListKey(binding.inFilters);\n return `${binding.propName}::${binding.statePathName}::${eventName}::${filterKey}::${getterIdOf(valueGetter)}::${isOccurrence ? 'o' : 's'}`;\n}\n\nfunction getEventName(binding: IBindingInfo): string {\n const tagName = (binding.node as Element).tagName.toLowerCase();\n // 1.default event name\n let eventName = (tagName === 'select') ? 'change' : 'input';\n // 2.wcBindable protocol\n const customTagName = getCustomElement(binding.node as Element);\n if (customTagName !== null) {\n const customClass = getCustomElementRegistry(binding.node)?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n raiseError(`Custom element <${customTagName}> is not defined. Cannot determine event name for two-way binding.`);\n }\n const propDesc = readBindableDeclaration(binding.node)?.knownProperties.get(binding.propName);\n if (propDesc) {\n eventName = propDesc.event;\n }\n }\n // 3.modifier(`#onchange` 等 — `on` + イベント名の修飾子形。README「Modifiers」参照)\n for(const modifier of binding.propModifiers) {\n if (modifier.startsWith(EVENT_PROP_PREFIX)) {\n eventName = modifier.slice(EVENT_PROP_PREFIX.length);\n }\n }\n return eventName;\n}\n\nfunction getValueGetter(binding: IBindingInfo): ((event: Event) => any) | null {\n const customTagName = getCustomElement(binding.node as Element);\n if (customTagName !== null) {\n const propDesc = readBindableDeclaration(binding.node)?.knownProperties.get(binding.propName);\n if (propDesc) {\n return propDesc.getter ?? DEFAULT_GETTER;\n }\n }\n return null;\n}\n\n/**\n * producer が `semantics: \"event\"` を宣言した property か。occurrence は同じ payload でも\n * 「もう一度起きた」ことに意味があるため、state への書き込みで same-value guard を通さない\n * (docs/async-io-node-guidelines.md §3.3.1 の `event`)。宣言が無い property は従来どおり\n * — 未指定は「未指定」であって state ではないので、挙動は変えない。\n */\nfunction isOccurrenceProperty(binding: IBindingInfo): boolean {\n const customTagName = getCustomElement(binding.node as Element);\n if (customTagName === null) return false;\n const propDesc = readBindableDeclaration(binding.node)?.knownProperties.get(binding.propName);\n return propDesc?.semantics === \"event\";\n}\n\nconst twowayEventHandlerFunction = (\n propName: string,\n statePathName: string,\n inFilters: IFilterInfo[],\n valueGetter: ((event: Event) => any) | null,\n isOccurrence: boolean,\n) => (event: Event): any => {\n const node = event.target as Element;\n if (node === null) {\n console.warn(`[@wcstack/state] event.target is null.`);\n return;\n }\n let newValue: any;\n if (valueGetter !== null) {\n newValue = valueGetter(event);\n if (valueGetter === DEFAULT_GETTER && !isOccurrence) {\n warnDefaultGetterMismatch(node, propName, newValue);\n }\n } else {\n if (!(propName in node)) {\n console.warn(`[@wcstack/state] Property \"${propName}\" does not exist on target element.`);\n return;\n }\n newValue = (node as any)[propName];\n }\n let filteredNewValue = newValue;\n for(const filter of inFilters) {\n filteredNewValue = filter.filterFn(filteredNewValue);\n }\n const producerObservers = producerValueObserversByNode.get(node)?.get(propName);\n if (typeof producerObservers !== \"undefined\") {\n for (const observer of producerObservers) observer(filteredNewValue);\n }\n\n let propagationContext: ReturnType<typeof getCurrentPropagationContext> = null;\n if (config.enablePropagationContext) {\n // Phase 3: element → state edge の因果判定(設計書 §4)。\n const wireId = getWireId(node, propName, statePathName);\n const receipt = matchWriteReceipt(node, propName);\n if (receipt !== null && Object.is(receipt.writtenValue, newValue)) {\n // 規則 4: 同じ setter call stack 内で同じ member から Object.is 同値の\n // 通知が戻った場合だけ confirmation として再伝播を抑止する。\n // shadow diagnostic(§8): primitive なら same-value guard も同じ結論に\n // なるため、provenance だけが守っている非 primitive の echo を可視化する。\n if (config.debug) {\n console.debug(`[@wcstack/state] propagation: write confirmation suppressed echo.`, {\n node,\n propName,\n statePathName,\n transactionId: receipt.transactionId,\n coveredBySameValueGuard: config.sameValueGuard\n && (filteredNewValue === null || typeof filteredNewValue !== \"object\"),\n });\n }\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"propagation:suppressed\",\n reason: \"confirmation\",\n transactionId: receipt.transactionId,\n edgeId: getEdgeId(wireId, \"to-state\"),\n node,\n member: propName,\n });\n }\n return;\n }\n // receipt があるが値が異なる場合は正規化差分: element の確定値として受理し、\n // 新しい edge を通る変更として継続する(規則 5・decision gate)。\n const toStateEdgeId = getEdgeId(wireId, \"to-state\");\n const baseContext = getCurrentPropagationContext();\n if (baseContext !== null && baseContext.visitedEdges.has(toStateEdgeId)) {\n // 規則 2: 同じ transaction が同じ edge を再度通ろうとした場合だけ抑止\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"propagation:suppressed\",\n reason: \"visited-edge\",\n transactionId: baseContext.transactionId,\n edgeId: toStateEdgeId,\n node,\n member: propName,\n });\n }\n return;\n }\n // 規則 1: 外部 event(受け皿の context が無い)なら新しい transaction を開始\n propagationContext = extendPropagationContext(\n baseContext ?? beginPropagationTransaction(wireId),\n toStateEdgeId,\n );\n }\n\n const rootNode = node.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for two-way binding.`);\n }\n\n const loopContext = getLoopContextByNode(node);\n // 要素から来た書き込み: 行そのものへ書いても入れ替えにしない(#337)。occurrence は同値でも\n // 取りこぼしてはならない(§3.3.1 `event`)。トークンは setByAddress の最初のガード評価で\n // 消費されるため、この write 1 回だけに効く(proxy/occurrenceWrite.ts)。\n const commitToState = (): void => commitElementValue(stateElement, loopContext, statePathName, filteredNewValue, isOccurrence);\n if (propagationContext !== null) {\n runWithPropagationContext(propagationContext, commitToState);\n } else {\n commitToState();\n }\n}\n\nexport function addTwowayValueObserver(\n node: Node,\n propName: string,\n observer: (value: unknown) => void,\n): () => void {\n let byProperty = producerValueObserversByNode.get(node);\n if (typeof byProperty === \"undefined\") {\n byProperty = new Map();\n producerValueObserversByNode.set(node, byProperty);\n }\n let observers = byProperty.get(propName);\n if (typeof observers === \"undefined\") {\n observers = new Set();\n byProperty.set(propName, observers);\n }\n observers.add(observer);\n return () => {\n observers?.delete(observer);\n if (observers?.size === 0) byProperty?.delete(propName);\n if (byProperty?.size === 0) producerValueObserversByNode.delete(node);\n };\n}\n\nexport function attachTwowayEventHandler(binding: IBindingInfo): void {\n const customTagName = getCustomElement(binding.node as Element);\n if (customTagName !== null) {\n const registry = getCustomElementRegistry(binding.node);\n const customClass = registry?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${customTagName}>.`);\n }\n return;\n }\n }\n\n if (isPossibleTwoWay(binding.node, binding.propName) && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const valueGetter = getValueGetter(binding);\n const isOccurrence = isOccurrenceProperty(binding);\n const key = getHandlerKey(binding, eventName, valueGetter, isOccurrence);\n attachedByBinding.set(binding, { key, eventName });\n let twowayEventHandler = handlerByHandlerKey.get(key);\n if (typeof twowayEventHandler === \"undefined\") {\n twowayEventHandler = twowayEventHandlerFunction(\n binding.propName,\n binding.statePathName,\n binding.inFilters,\n valueGetter,\n isOccurrence\n );\n handlerByHandlerKey.set(key, twowayEventHandler);\n }\n (binding.node as Element).addEventListener(eventName, twowayEventHandler);\n bindingRegistry.add(key, binding);\n }\n}\n\nexport function detachTwowayEventHandler(binding: IBindingInfo): void {\n // 控えが無い = attach していない(未定義のカスタム要素、二方向でないプロパティ、`#ro`)。\n // ここで `wcBindable` を読み直さないのが要点 — 理由は `attachedByBinding` の注記\n const attached = attachedByBinding.get(binding);\n if (typeof attached === \"undefined\") {\n return;\n }\n attachedByBinding.delete(binding);\n const twowayEventHandler = handlerByHandlerKey.get(attached.key);\n if (typeof twowayEventHandler === \"undefined\") {\n return;\n }\n (binding.node as Element).removeEventListener(attached.eventName, twowayEventHandler);\n\n if (bindingRegistry.remove(attached.key, binding)) {\n handlerByHandlerKey.delete(attached.key);\n }\n}\n\nexport const __private__ = {\n handlerByHandlerKey,\n bindingRegistry,\n producerValueObserversByNode,\n getHandlerKey,\n getEventName,\n getValueGetter,\n twowayEventHandlerFunction,\n DEFAULT_GETTER,\n};\n","// framework 自身が detach し明示的に解体(deactivate/unmount)したノード。\n// BindingOwner の MutationObserver は削除サブツリー走査でこれらをスキップする。\n//\n// 根拠: 削除時の handleRemovedNode は binding を dispose するだけ(DOM 構造変更も\n// connect-snapshot 依存も無い)で、framework が unmount 経路で既に dispose 済みの\n// content に対しては純粋な冗長走査(forEachInclusive で削除サブツリー全体を歩く)に\n// なる。create(追加)経路は two-way の connect-time snapshot を observer に依存する\n// ため対象外だが、削除は依存が無いため安全に飛ばせる。\n//\n// マークは observer が削除を配送した時点で消費(削除)する。マーク〜配送の間隔は\n// 単一 microtask であり、その間に外部 DOM 変異は割り込めない(framework の drain は\n// 同期)ため、マークは framework 由来の削除にしか一致しない。\nconst observerSkipNodes = new WeakSet<Node>();\n\nexport function markObserverSkipOnRemove(node: Node): void {\n observerSkipNodes.add(node);\n}\n\n// マーク済みなら true を返しつつマークを消費する。未マークなら false。\nexport function consumeObserverSkipOnRemove(node: Node): boolean {\n if (!observerSkipNodes.has(node)) {\n return false;\n }\n observerSkipNodes.delete(node);\n return true;\n}\n\n// framework 自身がマウント(Content.appendTo / mountAfter)したノード。\n// 追加サブツリー走査の実質の仕事は connect-snapshot 待ち(observationPending)の\n// record への配送だけで、record 自体は同期マウント(activateContent → start)で\n// observer flush より先に active 済み。よって待ちがグローバルに 1 つも無ければ\n// 追加側走査も冗長であり丸ごとスキップできる(削除側スキップの対称形)。\n// マーク〜配送が単一 microtask で外部変異が割り込めない前提も削除側と同じ。\n// framework の削除を親ごとの件数で数える(1 つの mutation record がその件数の子をまとめて消したとき、\n// 削除ノードごとの WeakSet 印の代わりに 1 回の判定で飛ばせる)\nconst skipRemovedChildrenByParent = new WeakMap<Node, number>();\n\nexport function markObserverSkipRemovedChildren(parent: Node, count: number): void {\n skipRemovedChildrenByParent.set(parent, (skipRemovedChildrenByParent.get(parent) ?? 0) + count);\n}\n\n/** Consumes `count` framework removals of `parent`; false (and nothing consumed) when the count does not cover them. */\nexport function consumeObserverSkipRemovedChildren(parent: Node, count: number): boolean {\n const pending = skipRemovedChildrenByParent.get(parent);\n if (typeof pending === \"undefined\" || pending < count) {\n return false;\n }\n if (pending === count) {\n skipRemovedChildrenByParent.delete(parent);\n } else {\n skipRemovedChildrenByParent.set(parent, pending - count);\n }\n return true;\n}\n\nconst observerSkipAddedNodes = new WeakSet<Node>();\n\nexport function markObserverSkipOnAdd(node: Node): void {\n observerSkipAddedNodes.add(node);\n}\n\n// マーク済みなら true を返しつつマークを消費する(削除側と同じ one-shot 契約)。\nexport function consumeObserverSkipOnAdd(node: Node): boolean {\n if (!observerSkipAddedNodes.has(node)) {\n return false;\n }\n observerSkipAddedNodes.delete(node);\n return true;\n}\n\n// connect-snapshot 待ち(two-way sync=connect で未接続のまま activate された record)の\n// グローバル件数。> 0 の間は追加側スキップを無効化して従来走査に戻す。\n// increment は settleInitialRecord、decrement は readProducerSnapshot(消化時)と\n// runTeardowns(未消化のまま終端した record のリーク防止)が担う。\nlet pendingObservationCount = 0;\n\nexport function incrementPendingObservation(): void {\n pendingObservationCount++;\n}\n\nexport function decrementPendingObservation(): void {\n pendingObservationCount--;\n}\n\nexport function hasPendingObservation(): boolean {\n return pendingObservationCount > 0;\n}\n","import { ICustomElementRegistryAdapter } from \"../platform/customElementRegistry\";\n\ninterface IDefinitionWaiter {\n active: boolean;\n readonly resolve: () => void;\n readonly reject: (error: unknown) => void;\n}\n\ninterface IDefinitionEntry {\n readonly waiters: Set<IDefinitionWaiter>;\n}\n\n/**\n * Shares one CustomElementRegistry.whenDefined() continuation per registry/tag.\n * Waiters can be removed independently, so a never-defined tag does not retain\n * binding records or their DOM nodes after teardown.\n */\nexport class DefinitionCoordinator {\n private readonly entries = new Map<string, IDefinitionEntry>();\n\n constructor(private readonly registry: ICustomElementRegistryAdapter) {}\n\n wait(\n tagName: string,\n resolve: () => void,\n reject: (error: unknown) => void = () => undefined,\n ): () => void {\n const normalizedTagName = tagName.toLowerCase();\n let entry = this.entries.get(normalizedTagName);\n if (typeof entry === \"undefined\") {\n entry = { waiters: new Set() };\n this.entries.set(normalizedTagName, entry);\n this.registry.whenDefined(normalizedTagName).then(\n () => this.settle(normalizedTagName, null),\n (error: unknown) => this.settle(normalizedTagName, error),\n );\n }\n\n const waiter: IDefinitionWaiter = { active: true, resolve, reject };\n entry.waiters.add(waiter);\n return () => {\n if (!waiter.active) return;\n waiter.active = false;\n entry?.waiters.delete(waiter);\n };\n }\n\n pendingCount(tagName: string): number {\n return this.entries.get(tagName.toLowerCase())?.waiters.size ?? 0;\n }\n\n private settle(tagName: string, error: unknown): void {\n const entry = this.entries.get(tagName);\n if (typeof entry === \"undefined\") return;\n this.entries.delete(tagName);\n const waiters = Array.from(entry.waiters);\n entry.waiters.clear();\n for (const waiter of waiters) {\n if (!waiter.active) continue;\n waiter.active = false;\n if (error === null) waiter.resolve();\n else waiter.reject(error);\n }\n }\n}\n\nconst coordinatorByRegistry = new WeakMap<ICustomElementRegistryAdapter, DefinitionCoordinator>();\n\nexport function getDefinitionCoordinator(\n registry: ICustomElementRegistryAdapter,\n): DefinitionCoordinator {\n let coordinator = coordinatorByRegistry.get(registry);\n if (typeof coordinator === \"undefined\") {\n coordinator = new DefinitionCoordinator(registry);\n coordinatorByRegistry.set(registry, coordinator);\n }\n return coordinator;\n}\n","import { getRootNodeByFragment } from \"../apply/rootNodeByFragment\";\nimport { getStateAddressByBindingInfo } from \"../binding/getStateAddressByBindingInfo\";\nimport { IStateElement } from \"../components/types\";\nimport { config } from \"../config\";\nimport { ATTR_NAMESPACE, CLASS_NAMESPACE, COMMAND_NAMESPACE, MODIFIER_KEY_INIT, MODIFIER_KEY_SYNC, STYLE_NAMESPACE } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { hasByAddressSymbol } from \"../proxy/symbols\";\nimport { commitElementValue } from \"../proxy/occurrenceWrite\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo } from \"../types\";\n\n/**\n * 左辺の先頭セグメントが名前空間になる束縛 — `apply/applyChange.ts` の\n * `applyChangeByFirstSegment` と**同じ集合**。\n *\n * ここが 1 つでも欠けると、欠けた名前空間が下の wcBindable プロパティ検証に落ちて\n * `Property \"class.on\" is not declared by wcBindable.` が飛び、**そのルートの束縛が\n * 1 つも立たなくなる**(`class.` / `attr.` / `style.` が実際にそうなっていた。\n * `command.` だけが除外されていた)。\n *\n * 集合の一致は `__tests__/bindings.initialSync.namespaces.test.ts` が apply 層の\n * ディスパッチ表と突き合わせて固定する(`manifest.test.ts` の drift 検出と同じ手)。\n */\nconst LEFT_HAND_NAMESPACES: ReadonlySet<string> = new Set<string>([\n CLASS_NAMESPACE, ATTR_NAMESPACE, STYLE_NAMESPACE, COMMAND_NAMESPACE,\n]);\n\nexport type InitialAuthority = \"state\" | \"element\" | \"auto\" | \"none\";\nexport type ResolvedInitialAuthority = Exclude<InitialAuthority, \"auto\">;\nexport type InitialSyncOn = \"call\" | \"connect\";\n\nexport interface IInitialSyncPolicy {\n readonly authority: InitialAuthority;\n readonly syncOn: InitialSyncOn;\n readonly observable: boolean;\n /**\n * wcBindable 宣言が properties のみ(output-only member)であること。\n * authority は初期同期のみを支配する(docs/architecture-hardening/09 §3.6)が、\n * output-only member への state→element 書き込みは初期に限らず契約として\n * 恒久ブロックする。その判定を authority と分離してここに持つ。\n */\n readonly outputOnly: boolean;\n}\n\nfunction readOption(\n binding: IBindingInfo,\n key: \"init\" | \"sync\",\n): string | null {\n let result: string | null = null;\n for (const modifier of binding.propModifiers) {\n const separator = modifier.indexOf(\"=\");\n if (separator < 0) continue;\n const modifierKey = modifier.slice(0, separator).trim();\n const value = modifier.slice(separator + 1).trim();\n if (modifierKey !== MODIFIER_KEY_INIT && modifierKey !== MODIFIER_KEY_SYNC) {\n raiseError(`Unknown binding modifier \"${modifierKey}\" in \"${modifier}\".`);\n }\n if (modifierKey !== key) continue;\n if (result !== null) {\n raiseError(`Binding modifier \"${key}\" may only be specified once.`);\n }\n result = value;\n }\n return result;\n}\n\nfunction parseAuthority(value: string | null): InitialAuthority | null {\n if (value === null) return null;\n if (value === \"state\" || value === \"element\" || value === \"auto\" || value === \"none\") {\n return value;\n }\n return raiseError(`Invalid init modifier value \"${value}\".`);\n}\n\nfunction parseSyncOn(value: string | null): InitialSyncOn {\n if (value === null || value === \"call\") return \"call\";\n if (value === \"connect\") return \"connect\";\n return raiseError(`Invalid sync modifier value \"${value}\".`);\n}\n\nexport function hasInitialSyncModifier(binding: IBindingInfo): boolean {\n return binding.propModifiers.some((modifier) => modifier.includes(\"=\"));\n}\n\n// 頻出ポリシー(修飾子なしの通常バインディング)の凍結シングルトン。リスト行では\n// binding ごとに resolveInitialSyncPolicy が走るため、毎回のオブジェクト割り当てを\n// 避ける(record.initialPolicy は読み取り専用でしか使われない)。\nconst STATE_CALL_POLICY: IInitialSyncPolicy = Object.freeze({ authority: \"state\", syncOn: \"call\", observable: false, outputOnly: false });\nconst NONE_CALL_POLICY: IInitialSyncPolicy = Object.freeze({ authority: \"none\", syncOn: \"call\", observable: false, outputOnly: false });\n\nfunction statePolicy(authority: InitialAuthority, syncOn: IInitialSyncPolicy[\"syncOn\"]): IInitialSyncPolicy {\n if (authority === \"state\" && syncOn === \"call\") return STATE_CALL_POLICY;\n return { authority, syncOn, observable: false, outputOnly: false };\n}\n\nexport function resolveInitialSyncPolicy(binding: IBindingInfo): IInitialSyncPolicy {\n if (!config.enableDirectionalInitialSync) {\n if (hasInitialSyncModifier(binding)) {\n raiseError(\"init=/sync= modifiers require enableDirectionalInitialSync.\");\n }\n return STATE_CALL_POLICY;\n }\n\n const explicitAuthority = parseAuthority(readOption(binding, MODIFIER_KEY_INIT));\n const syncOn = parseSyncOn(readOption(binding, MODIFIER_KEY_SYNC));\n if (binding.bindingType === \"event\") {\n if (explicitAuthority !== null && explicitAuthority !== \"none\") {\n raiseError(\"Event bindings only allow init=none.\");\n }\n return syncOn === \"call\" ? NONE_CALL_POLICY : { authority: \"none\", syncOn, observable: false, outputOnly: false };\n }\n // 左辺の名前空間(`class.` / `attr.` / `style.` / `command.`)は bindingType こそ \"prop\" だが、\n // `propName` は wcBindable の property **ではない**。下の property authority 検証\n // (未宣言なら raiseError)に掛けてはならず、掛けると wc-bindable 要素に `class.on: flag` と\n // 書いただけで `Property \"class.on\" is not declared by wcBindable.` が飛び、\n // **そのルートの束縛が 1 つも立たなくなる**(`getBindingsReady` ごと reject)。\n // 値の初期同期を持たない配線なので、現行互換の \"state\" authority を返す\n // (command token は従来どおり初期 apply で配線される)。\n if (LEFT_HAND_NAMESPACES.has(binding.propSegments[0])) {\n return statePolicy(\"state\", syncOn);\n }\n if (binding.bindingType !== \"prop\") {\n if (explicitAuthority !== null && explicitAuthority !== \"state\" && explicitAuthority !== \"none\") {\n raiseError(`Binding type \"${binding.bindingType}\" does not support init=${explicitAuthority}.`);\n }\n return statePolicy(explicitAuthority ?? \"state\", syncOn);\n }\n\n const declaration = readBindableDeclaration(binding.node);\n if (declaration === null) {\n return statePolicy(explicitAuthority ?? \"state\", syncOn);\n }\n const hasOutput = declaration.knownProperties.has(binding.propName);\n const hasInput = declaration.declaredInputs.has(binding.propName);\n if (!hasOutput && !hasInput) {\n raiseError(`Property \"${binding.propName}\" is not declared by wcBindable.`);\n }\n\n const allowed = hasOutput && hasInput\n ? new Set<InitialAuthority>([\"state\", \"element\", \"auto\", \"none\"])\n : hasOutput\n ? new Set<InitialAuthority>([\"element\", \"none\"])\n : new Set<InitialAuthority>([\"state\", \"none\"]);\n const defaultAuthority: InitialAuthority = hasOutput && !hasInput ? \"element\" : \"state\";\n const authority = explicitAuthority ?? defaultAuthority;\n if (!allowed.has(authority)) {\n raiseError(`init=${authority} is incompatible with wcBindable member \"${binding.propName}\".`);\n }\n if (syncOn === \"connect\" && !hasOutput) {\n raiseError(`sync=connect requires observable property \"${binding.propName}\".`);\n }\n return { authority, syncOn, observable: hasOutput, outputOnly: hasOutput && !hasInput };\n}\n\n/**\n * 初期同期が読み書きする state 要素を引く。`for:` の行は文書へ挿入する前のバッチ\n * fragment の上で活性化される(`apply/applyChangeToFor.ts`)ので、その間の\n * `getRootNode()` は fragment 自身を返す。fragment → 実ルートの台帳\n * (`setRootNodeByFragment`)で引き直す — `applyChange` と同じ手順。\n * 引き直さないと、クラス定義済みの要素を `for:` の行に置いたとき初期同期が投げ、\n * 一覧の反映ごと失敗していた(#319)。\n */\nfunction getSyncStateElement(node: Node): IStateElement | null {\n let rootNode: Node | null = node.getRootNode();\n if (rootNode instanceof DocumentFragment && !(rootNode instanceof ShadowRoot)) {\n rootNode = getRootNodeByFragment(rootNode);\n }\n return rootNode === null ? null : getStateElement(rootNode);\n}\n\nexport function isBindingStateInitialized(binding: IBindingInfo): boolean {\n const stateElement = getSyncStateElement(binding.replaceNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n const address = getStateAddressByBindingInfo(binding);\n let initialized = false;\n stateElement.createState(\"readonly\", (state) => {\n initialized = state[hasByAddressSymbol](address);\n });\n return initialized;\n}\n\nexport function resolveInitialAuthority(\n binding: IBindingInfo,\n authority: InitialAuthority,\n): ResolvedInitialAuthority {\n if (authority !== \"auto\") return authority;\n return isBindingStateInitialized(binding) ? \"state\" : \"element\";\n}\n\nexport function commitProducerValue(binding: IBindingInfo, value: unknown): void {\n let filteredValue = value;\n for (const filter of binding.inFilters) {\n filteredValue = filter.filterFn(filteredValue);\n }\n const stateElement = getSyncStateElement(binding.node);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for initial binding sync.`);\n }\n // 要素から来た書き込み: 行そのものへ書いても入れ替えにしない(proxy/occurrenceWrite.ts・#337)\n commitElementValue(stateElement, getLoopContextByNode(binding.node), binding.statePathName, filteredValue);\n}\n","import { applyChangeFromBindings } from \"../apply/applyChangeFromBindings\";\nimport { EVENT_TOKEN_NAMESPACE, MODIFIER_READONLY } from \"../define\";\nimport { IAbsoluteStateAddress } from \"../address/types\";\nimport { getTreePath } from \"../address/TreePath\";\nimport { ITreePath } from \"../address/types\";\nimport { clearAbsoluteStateAddressByBinding, getAbsoluteStateAddressByBinding, resolveBindingRootNode } from \"../binding/getAbsoluteStateAddressByBinding\";\nimport { addBindingByAbsoluteStateAddress, addBindingByPattern, removeBindingByAbsoluteStateAddress, removeBindingByPattern } from \"../binding/getBindingSetByAbsoluteStateAddress\";\nimport { getListIndexByBindingInfo } from \"../list/getListIndexByBindingInfo\";\nimport { getLastListValueByAbsoluteStateAddress, hasLastListValueByAbsoluteStateAddress, setLastListValueByAbsoluteStateAddress } from \"../list/lastListValueByAbsoluteStateAddress\";\nimport { getStateListBaseline, hasStateListBaseline, setStateListBaseline } from \"../list/stateListBaseline\";\nimport { IListIndex } from \"../list/types\";\nimport { clearStateAddressByBindingInfo } from \"../binding/getStateAddressByBindingInfo\";\nimport { config } from \"../config\";\nimport { filterListKey } from \"../binding/filterKey\";\nimport { detachCheckboxEventHandler, attachCheckboxEventHandler } from \"../event/checkboxHandler\";\nimport { detachEventTokenHandler, attachEventTokenHandler } from \"../event/eventTokenHandler\";\nimport { detachEventHandler, attachEventHandler } from \"../event/handler\";\nimport { detachRadioEventHandler, attachRadioEventHandler } from \"../event/radioHandler\";\nimport { detachTwowayEventHandler, attachTwowayEventHandler, addTwowayValueObserver } from \"../event/twowayHandler\";\nimport { isPossibleTwoWay } from \"../event/isPossibleTwoWay\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry, upgradeCustomElement } from \"../platform/customElementRegistry\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo } from \"../types\";\nimport { consumeObserverSkipOnAdd, consumeObserverSkipOnRemove, consumeObserverSkipRemovedChildren, decrementPendingObservation, hasPendingObservation, incrementPendingObservation } from \"./observerSkip\";\nimport { getDefinitionCoordinator } from \"./DefinitionCoordinator\";\nimport { commitProducerValue, hasInitialSyncModifier, IInitialSyncPolicy, ResolvedInitialAuthority, resolveInitialAuthority, resolveInitialSyncPolicy } from \"./initialSync\";\nimport { replaceToReplaceNode } from \"./replaceToReplaceNode\";\nimport type { IRowPlan } from \"../structural/types\";\n\nexport type BindingPhase =\n | \"discovered\"\n | \"waiting-definition\"\n | \"ready-to-attach\"\n | \"attaching\"\n | \"synchronizing\"\n | \"active\"\n | \"failed\"\n | \"disposed\";\n\nexport interface IBindingRecord {\n readonly id: number;\n readonly info: IBindingInfo;\n readonly generation: number;\n phase: BindingPhase;\n /**\n * 追加の後始末クロージャ(radio/checkbox/observer/定義キャンセル等の希少ケース)。\n * 頻出の後始末(イベント detach・双方向 detach・アドレス台帳解除)はクロージャで\n * なく record のフラグ/フィールドから runTeardowns がデータ駆動で実行するため、\n * 大多数の record では null のまま(行あたり Set×5 + クロージャ×10 の割当を排除)。\n */\n teardowns: Set<() => void> | null;\n}\n\ninterface IBindingOptions {\n registerAddress: boolean;\n registerPathInfo: boolean;\n applyOnReconnect: boolean;\n}\n\ninterface IInternalBindingRecord extends IBindingRecord {\n /**\n * generation はプラン行のプール再利用(record オブジェクト再利用)で更新するため\n * 内部表現では書き込み可能にする(IBindingRecord 公開面は readonly のまま)\n */\n generation: number;\n readonly session: BindingSession;\n readonly anchor: Node;\n readonly options: IBindingOptions;\n address: IAbsoluteStateAddress | null;\n /**\n * パターン索引台帳((absolutePathInfo, listIndex) 2 段キー)への登録。リスト行の\n * binding は address を intern せずこちらに登録する。address とは排他。\n */\n patternPathInfo: ITreePath | null;\n patternListIndex: IListIndex | null;\n pendingDefinitions: number;\n initialPolicy: IInitialSyncPolicy | null;\n resolvedAuthority: ResolvedInitialAuthority | null;\n initialSettled: boolean;\n /**\n * 最初の shouldApplyState 相談(= 初期 state sweep / 初回 render の選別)を\n * 消費済みか。authority は初期同期のみを支配する(09 §3.6)ため、初回相談は\n * authority で答え、以降の定常 apply は output-only 契約と connect-snapshot\n * 未解決だけをブロックする。\n */\n initialApplyDone: boolean;\n /** initialPolicy.outputOnly のミラー(settle 時確定・定常ゲートの分岐を総域にする) */\n outputOnlyMember: boolean;\n observationPending: boolean;\n eventSequence: number;\n hasProducerValue: boolean;\n producerValue: unknown;\n /** attachEventHandler 済み(dispose 時に detachEventHandler をデータ駆動実行) */\n eventAttached: boolean;\n /** attachTwowayEventHandler 済み(dispose 時に detachTwowayEventHandler をデータ駆動実行) */\n twowayAttached: boolean;\n}\n\ninterface IDeferredDefinition {\n readonly node: Node;\n /** 登録した世代(session の disposedAt と比べる) */\n readonly born: number;\n /** 張っている registry の待ちの取り消し。null はまだ張っていない(fragment の中)か、外れて下ろした */\n cancel: (() => void) | null;\n /** ノードが今属する registry で待ちを張る(張り済み・session が手放した待ちは何もしない) */\n arm: () => void;\n}\n\ninterface IObservableRoot extends Node {\n contains(other: Node | null): boolean;\n}\n\nlet nextRecordId = 0;\n// 次の microtask にまとめて張る定義待ち(全 session で 1 本・登録順)。null は並んでいる待ちが無い\nlet armQueue: IDeferredDefinition[] | null = null;\nlet nextGeneration = 0;\n\n// プラン行の帳簿は束縛ごとの record ではなく行に 1 つの record(slot 配列)で持つ\n// (行ランタイム設計 R3)。phase は slot ごとの SLOT_*、フラグは FLAG_* のビット。\nconst SLOT_ACTIVE = 0;\nconst SLOT_DISPOSED = 1;\nconst SLOT_FAILED = 2;\nconst FLAG_INITIAL_APPLY_DONE = 1;\nconst FLAG_EVENT_ATTACHED = 2;\nconst SLOT_PHASE_NAMES: readonly BindingPhase[] = [\"active\", \"disposed\", \"failed\"];\ninterface IRowRecord {\n readonly id: number;\n /** この行を持つ共有 session(行 → session の逆引き。設計 R3) */\n readonly session: BindingSession;\n generation: number;\n readonly plan: IRowPlan;\n readonly bindings: readonly IBindingInfo[];\n /** activate が address 登録を昇格したか(従来の record.options.registerAddress に相当、行で共有) */\n registered: boolean;\n /** SLOT_* per slot */\n readonly phases: number[];\n /** FLAG_* bits per slot */\n readonly flags: number[];\n readonly addresses: (IAbsoluteStateAddress | null)[];\n readonly patternPathInfos: (ITreePath | null)[];\n readonly patternListIndexes: (IListIndex | null)[];\n}\n// 束縛 → その行の record(record が共有 session を知っている。設計 R3)\nconst rowByBinding = new WeakMap<IBindingInfo, IRowRecord>();\n// 行 slot に振った record id(`getRecord` — 検査・テスト専用の経路でしか作られない)\nconst rowSlotIds = new WeakMap<IRowRecord, number[]>();\n\nconst recordByBinding = new WeakMap<IBindingInfo, IInternalBindingRecord>();\nconst sessionByRoot = new WeakMap<Node, BindingSession>();\n\n// binding の構造キーは不変フィールドのみから決まる。リスト行の初期化では同一 binding に\n// 対し remember() が2回呼ばれる(createContent 内 initializeBindingsByFragment と\n// activateContent の registerAddress 目的の initialize)ため、2度目の文字列生成を避けるべく\n// binding 単位でメモ化する。プロファイル上 bindingKey は create-10k の JS 自己時間で上位。\nconst bindingKeyByBinding = new WeakMap<IBindingInfo, string>();\n\n// node → その node に関心を持つ session(anchor として binding を覚えている、\n// または定義待ちタスクを抱えている)。BindingOwner は mutation で増減した\n// サブツリーを1回だけ走査し、ここに登録された session だけへ per-node 配送する。\n// 全 session ブロードキャストだと、リスト行の逐次 append などで\n// 「session 数 × 変異ノード数」の O(n²) ファンアウトになるため、その正本台帳。\n// 大多数の node は関心 session が1つなので単一値で持ち、2つ目から Set に昇格する。\nconst interestedSessionsByNode = new WeakMap<Node, BindingSession | Set<BindingSession>>();\n\nfunction addInterestedSession(node: Node, session: BindingSession): void {\n const current = interestedSessionsByNode.get(node);\n if (typeof current === \"undefined\") {\n interestedSessionsByNode.set(node, session);\n return;\n }\n if (current === session) return;\n if (current instanceof Set) {\n current.add(session);\n return;\n }\n interestedSessionsByNode.set(node, new Set([current, session]));\n}\n\n/**\n * このノードに既にバインドが張られているか。\n *\n * binder プロトコル(`bind()`)の冪等判定に使う。`remember` が binding ごとに\n * `addInterestedSession(binding.replaceNode, …)` を呼ぶので、バインド済みノードは\n * 必ずこの台帳に載っている。新しい台帳を足さずに済むぶん、二重管理の齟齬が無い。\n */\nexport function hasInterestedSession(node: Node): boolean {\n return interestedSessionsByNode.has(node);\n}\n\nfunction forEachInterestedSession(node: Node, callback: (session: BindingSession) => void): void {\n const current = interestedSessionsByNode.get(node);\n if (typeof current === \"undefined\") return;\n if (current instanceof Set) {\n for (const session of Array.from(current)) callback(session);\n return;\n }\n callback(current);\n}\n\nfunction forEachInclusive(root: Node, callback: (node: Node) => void): void {\n callback(root);\n // 葉ノード(fragment 一括挿入時のテキスト・空セル等が大多数)では\n // Array.from(childNodes) の空配列アロケーションを避ける。callback が子を\n // 追加しうるため firstChild は callback 後に判定する(従来と同一意味論)。\n if (root.firstChild === null) return;\n for (const child of Array.from(root.childNodes)) {\n forEachInclusive(child, callback);\n }\n}\n\nfunction isObservableRoot(value: unknown): value is IObservableRoot {\n if (typeof value !== \"object\" || value === null) return false;\n const node = value as Node;\n return node.nodeType === 9 || (node.nodeType === 11 && \"host\" in (node as object));\n}\n\nfunction observableRootFor(node: Node): IObservableRoot | null {\n const root = node.getRootNode();\n return isObservableRoot(root) ? root : null;\n}\n\nclass BindingOwner {\n private readonly observer: MutationObserver | null;\n\n constructor(readonly root: IObservableRoot) {\n const Observer = (globalThis as { MutationObserver?: typeof MutationObserver }).MutationObserver;\n this.observer = typeof Observer === \"function\"\n ? new Observer((mutations) => this.handleMutations(mutations))\n : null;\n this.observer?.observe(root, { childList: true, subtree: true });\n }\n\n private handleMutations(mutations: MutationRecord[]): void {\n const removed: Node[] = [];\n const added: Node[] = [];\n for (let m = 0; m < mutations.length; m++) {\n const mutation = mutations[m];\n const removedNodes = mutation.removedNodes;\n // 削除された子がすべて framework の削除(消去が親に件数で印を付けた)なら record ごと飛ばし、\n // ノードごとの印には触れない\n if (removedNodes.length === 0 || !consumeObserverSkipRemovedChildren(mutation.target, removedNodes.length)) {\n for (let i = 0; i < removedNodes.length; i++) removed.push(removedNodes[i]);\n }\n const addedNodes = mutation.addedNodes;\n for (let i = 0; i < addedNodes.length; i++) added.push(addedNodes[i]);\n }\n // 走査は owner が1回だけ行い、関心 session が居る node だけを配送・contains\n // 検査へ進める。contains は O(木の深さ) なので、関心の無い node で呼ばない。\n const reconnected: IBindingInfo[] = [];\n for (const subtree of removed) {\n // framework が unmount した削除サブツリーは binding を明示 dispose 済みなので\n // observer 側の冗長走査(forEachInclusive で全 node を歩き handleRemovedNode を\n // 呼ぶ)を丸ごとスキップする。clear/大量 delete のホットスポット短縮。\n if (consumeObserverSkipOnRemove(subtree)) continue;\n forEachInclusive(subtree, (node) => {\n forEachInterestedSession(node, (session) => {\n if (this.root.contains(node)) return;\n session.handleRemovedNode(node);\n });\n });\n }\n for (const subtree of added) {\n // framework がマウントしたサブツリーは record が同期 activate 済みで、追加側\n // 走査の実質の仕事は connect-snapshot 待ちへの配送だけ。待ちがグローバルに\n // 無ければ丸ごとスキップする(待ちがあればマークだけ消費して従来走査に戻す)。\n if (consumeObserverSkipOnAdd(subtree) && !hasPendingObservation()) continue;\n forEachInclusive(subtree, (node) => {\n forEachInterestedSession(node, (session) => {\n if (!this.root.contains(node)) return;\n session.handleAddedNode(node, reconnected);\n });\n });\n }\n if (reconnected.length > 0) applyChangeFromBindings(reconnected);\n }\n}\n\nconst ownerByRoot = new WeakMap<IObservableRoot, BindingOwner>();\n\nfunction getBindingOwner(root: IObservableRoot): BindingOwner {\n let owner = ownerByRoot.get(root);\n if (typeof owner === \"undefined\") {\n owner = new BindingOwner(root);\n ownerByRoot.set(root, owner);\n }\n return owner;\n}\n\nfunction bindingKey(binding: IBindingInfo): string {\n // 引数は型付きの値で書き出す(要件 B9)— `defaults(0)` と `defaults('0')` を取り違えない\n const inFilters = filterListKey(binding.inFilters);\n const outFilters = filterListKey(binding.outFilters);\n return [\n binding.bindingType,\n binding.propName,\n binding.propModifiers.join(\",\"),\n binding.statePathName,\n inFilters,\n outFilters,\n binding.uuid ?? \"\",\n ].join(\"\\u0000\");\n}\n\n/*\n * 束縛が状態の台帳へ出入りする経路(行ランタイム設計 R4)。行 slot(registerRowSlot /\n * unregisterRowSlot)と record(registerAddress / runTeardowns / rebindAddresses)が同じ登録・\n * 解除をそれぞれ書き写していたのを 1 箇所にした。登録した形(アドレスか、パターンの\n * pathInfo + listIndex か)は呼び出し側の器(行の slot 配列 / record のフィールド)へ書く —\n * ここで値の組を返すと行ごとに割り当てが増えるため、器は呼び出し側に残す。\n */\n\n/** リスト行: (absolutePathInfo, listIndex) のパターン台帳へ入れる(AbsoluteStateAddress の intern を省く) */\nfunction registerPattern(binding: IBindingInfo, listIndex: IListIndex, knownRoot?: Node | null): ITreePath {\n const stateElement = getStateElement(resolveBindingRootNode(binding, knownRoot));\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n const absolutePathInfo = getTreePath(stateElement, binding.statePathInfo);\n addBindingByPattern(absolutePathInfo, listIndex, binding);\n return absolutePathInfo;\n}\n\n/** リスト行でない束縛: 絶対アドレスの台帳へ入れる */\nfunction registerAbsoluteAddress(binding: IBindingInfo, knownRoot?: Node | null): IAbsoluteStateAddress {\n const address = getAbsoluteStateAddressByBinding(binding, knownRoot);\n addBindingByAbsoluteStateAddress(address, binding);\n return address;\n}\n\n/**\n * 台帳から外す。`address` が null ならパターン登録(`pathInfo` + `listIndex`)。相対アドレス\n * (getValue)と絶対アドレス(applyChangeToFor / updatedCallback 経由の遅延 intern)のメモは\n * パターン登録でも作られうるので、どちらでも対称にクリアする。\n */\nfunction unregisterFromLedger(\n binding: IBindingInfo,\n address: IAbsoluteStateAddress | null,\n pathInfo: ITreePath | null,\n listIndex: IListIndex | null,\n): void {\n if (address !== null) {\n removeBindingByAbsoluteStateAddress(address, binding);\n } else {\n removeBindingByPattern(pathInfo!, listIndex!, binding);\n }\n clearStateAddressByBindingInfo(binding);\n clearAbsoluteStateAddressByBinding(binding);\n}\n\nfunction addRecordTeardown(record: IInternalBindingRecord, teardown: () => void): void {\n if (record.teardowns === null) {\n record.teardowns = new Set();\n }\n record.teardowns.add(teardown);\n}\n\nexport class BindingSession {\n private readonly records = new Set<IInternalBindingRecord>();\n /**\n * initializeRow で設定される行プラン。非 null のとき activate は\n * スロット整列の高速経路(activatePlanRows)を使う。\n */\n private rowPlan: IRowPlan | null = null;\n /** この session が持つ生きている行(`for` 束縛 1 つにつき session 1 つ、行は複数。設計 R3) */\n private readonly rows = new Set<IRowRecord>();\n // anchor ノードが持つ binding は大多数が 1 本なので単一値で持ち、2 本目から\n // Map(remember 経路のキー照合用)に昇格する(台帳・興味 session と同じ前例)\n private readonly knownBindingsByNode = new WeakMap<Node, IBindingInfo | Map<string, IBindingInfo>>();\n private readonly optionsByBinding = new WeakMap<IBindingInfo, IBindingOptions>();\n private readonly deferredByNode = new WeakMap<Node, Set<IDeferredDefinition>>();\n private readonly deferred = new Set<IDeferredDefinition>();\n /**\n * 最後に session ごと解体した(dispose / destroyRecords — 行の Content が消えた・プールに入った)時点の\n * 世代。これより前に生まれた record・定義待ちは、外れて戻ってきても張り直さない・適用し直さない(#352)\n */\n private disposedAt = 0;\n\n constructor(root: Node | null = null) {\n if (root !== null) this.observe(root);\n }\n\n /**\n * knownRoot: 呼び出し側が root を確定済みのときの per-binding observe 省略。\n * - undefined: 従来どおり binding ごとに anchor から root を導出して observe\n * - null: detached fragment 上(createContent)の初期化。observableRootFor が\n * 必ず null を返す状況なので observe(= getRootNode)を丸ごと省略する\n * - Node: 呼び出し側で owner 保証済み(activate 経由のみ。initialize へは未使用)\n */\n initialize(\n bindings: readonly IBindingInfo[],\n options: Partial<IBindingOptions> = {},\n knownRoot?: Node | null,\n ): IBindingInfo[] {\n const registerAddress = options.registerAddress ?? true;\n const resolvedOptions: IBindingOptions = {\n registerAddress,\n registerPathInfo: options.registerPathInfo ?? registerAddress,\n applyOnReconnect: options.applyOnReconnect ?? true,\n };\n const initialized: IBindingInfo[] = [];\n for (const candidate of bindings) {\n const binding = this.remember(candidate, resolvedOptions);\n const rowRecord = this.rowOf(binding);\n const rowSlot = rowRecord === null ? -1 : rowRecord.bindings.indexOf(binding);\n if (rowRecord !== null && rowRecord.phases[rowSlot] === SLOT_ACTIVE) {\n const row = rowRecord;\n this.observe(binding.replaceNode);\n if (resolvedOptions.registerAddress && row.addresses[rowSlot] === null && row.patternPathInfos[rowSlot] === null) {\n row.registered = true;\n this.registerRowSlot(row, rowSlot);\n }\n continue;\n }\n const existing = recordByBinding.get(binding);\n if (typeof existing !== \"undefined\" && existing.phase !== \"disposed\" && existing.phase !== \"failed\") {\n this.observe(existing.anchor);\n if (resolvedOptions.registerAddress && existing.address === null && existing.patternListIndex === null) {\n existing.options.registerAddress = true;\n this.registerAddress(existing);\n }\n if (existing.phase === \"active\") this.settleInitialRecord(existing);\n this.settleConnectedSnapshot(existing);\n continue;\n }\n this.start(binding, resolvedOptions, knownRoot);\n initialized.push(binding);\n }\n return initialized.filter((binding) => this.shouldApplyState(binding));\n }\n\n /**\n * activateContent 専用の再活性化パス。createContent 側の initialize で\n * remember 済みの binding 配列(bindingsByContent がそのまま保持する同一オブジェクト)\n * にだけ使える前提で、remember の再実行(キー照合・options マージ・興味登録)を省き、\n * 必要な仕事だけ行う: 初回活性化はアドレス登録+初期同期、pool 再利用(disposed)は\n * start による再構築、未知の binding は防御的に従来 initialize へ倒す。\n *\n * knownRoot は呼び出し側(applyChangeToFor / applyChangeToIf の apply context)が\n * 確定済みの root。owner(root ごとの MutationObserver)の保証を呼び出しあたり\n * 1 回に集約し、binding ごとの observe(= getRootNode)とアドレス解決の\n * getRootNode を丸ごと省略する。\n */\n activate(bindings: readonly IBindingInfo[], knownRoot: Node): void {\n if (isObservableRoot(knownRoot)) getBindingOwner(knownRoot);\n if (this.rowPlan !== null) {\n this.activatePlanRows(this.rowPlan, bindings, knownRoot);\n return;\n }\n for (const binding of bindings) {\n const record = recordByBinding.get(binding);\n if (typeof record !== \"undefined\" && record.session === this\n && record.phase !== \"disposed\" && record.phase !== \"failed\") {\n if (record.address === null && record.patternListIndex === null) {\n // 初回活性化(owner は冒頭で保証済み)\n record.options.registerAddress = true;\n this.registerAddress(record, knownRoot);\n }\n if (record.phase === \"active\") this.settleInitialRecord(record);\n this.settleConnectedSnapshot(record);\n continue;\n }\n const options = this.optionsByBinding.get(binding);\n if (typeof options === \"undefined\") {\n // この session で remember されていない binding(防御): 従来経路\n this.initialize([binding], { registerAddress: true, registerPathInfo: false, applyOnReconnect: false });\n continue;\n }\n // pool 再利用: record は disposed。活性化要件(アドレス登録)を昇格して再構築\n options.registerAddress = true;\n this.start(binding, options, knownRoot);\n }\n }\n\n shouldApplyState(binding: IBindingInfo): boolean {\n if (!config.enableDirectionalInitialSync) {\n if (hasInitialSyncModifier(binding)) resolveInitialSyncPolicy(binding);\n return true;\n }\n const row = this.rowOf(binding);\n if (row !== null) {\n const slot = row.bindings.indexOf(binding);\n if (slot >= 0) {\n if (!row.registered) return true;\n if (row.phases[slot] === SLOT_FAILED) return false;\n const planSlot = row.plan.slots[slot];\n if ((row.flags[slot] & FLAG_INITIAL_APPLY_DONE) === 0) {\n row.flags[slot] |= FLAG_INITIAL_APPLY_DONE;\n return planSlot.authority === \"state\";\n }\n if (planSlot.authority === \"state\") return true;\n return !planSlot.policy.outputOnly;\n }\n }\n const record = recordByBinding.get(binding);\n if (typeof record === \"undefined\" || record.session !== this) return true;\n if (!record.options.registerAddress || record.phase === \"waiting-definition\") return true;\n if (record.phase === \"failed\") return false;\n if (record.phase === \"active\") this.settleInitialRecord(record);\n // authority は初期同期のみを支配する(09 §3.6: init=element は「snapshot を\n // state へ入れる」、init=none は「次の変更から扱う」)。settle 後の最初の相談\n // = 初期 state sweep / 初回 render / deferred initial apply の選別なので\n // authority で答え、ここで初期適用を消費する。\n if (!record.initialApplyDone) {\n record.initialApplyDone = true;\n return record.resolvedAuthority === \"state\";\n }\n if (record.resolvedAuthority === \"state\") return true;\n // 定常: two-way / input member は authority と無関係に state→element を流す。\n // 恒久ブロックは (1) output-only member の契約(書き込み無意味・DCC/router の\n // conformance が依存)と (2) sync=connect の接続 snapshot が未解決の間\n //(初期競合が未決着のうちは state push が element 初期値を潰しうる)だけ。\n return !record.outputOnlyMember && !record.observationPending;\n }\n\n /**\n * **検査・テスト専用**(本番の呼び出し元は無い)。行の slot には record オブジェクトが\n * 無いので、呼ぶたびに読み取り専用の合成オブジェクトを作る — ホットパスでは使わないこと。\n *\n * `id` は record の id と同じ通し番号から取る。かつて `row.id * 64 + slot` で合成していたが、\n * 1 行が 64 スロットを超えると別の行の id と衝突した(`row.id` 自身も同じ通し番号なので、\n * 素の record の id とも衝突しうる)。台帳は WeakMap なので本番経路の割り当ては増えない。\n */\n getRecord(binding: IBindingInfo): IBindingRecord | null {\n const row = this.rowOf(binding);\n const slot = row === null ? -1 : row.bindings.indexOf(binding);\n if (row !== null && slot >= 0) {\n let ids = rowSlotIds.get(row);\n if (typeof ids === \"undefined\") {\n rowSlotIds.set(row, ids = []);\n }\n const id = ids[slot] ?? (ids[slot] = ++nextRecordId);\n return { id, info: binding, generation: row.generation, phase: SLOT_PHASE_NAMES[row.phases[slot]], teardowns: null };\n }\n const record = recordByBinding.get(binding);\n return record?.session === this ? record : null;\n }\n\n /**\n * teardown を足せるのは record を持つ束縛だけ(設計 R3)。唯一の呼び出し元は\n * `scheduleDeferredApply`(未定義カスタム要素への遅延適用)で、プラン行はカスタム要素を\n * 含み得ないため行 slot には来ない。\n */\n addTeardown(binding: IBindingInfo, teardown: () => void): boolean {\n const record = recordByBinding.get(binding);\n if (typeof record === \"undefined\" || !this.isAlive(record, record.generation)) {\n return false;\n }\n addRecordTeardown(record, teardown);\n return true;\n }\n\n deferUntilDefined(\n node: Node,\n tagName: string,\n callback: () => void,\n reject: (error: unknown) => void = () => undefined,\n ): () => void {\n const tasks = this.deferredByNode.get(node) ?? new Set<IDeferredDefinition>();\n // 済ませる(一度きり)。済んだ・取り消した task はどちらの台帳にも居ない\n const finish = (): boolean => tasks.delete(task) && this.deferred.delete(task);\n const wait = (): void => {\n const registry = getCustomElementRegistry(node);\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${tagName}>.`);\n }\n task.cancel = getDefinitionCoordinator(registry).wait(\n tagName,\n () => {\n if (!finish()) return;\n try {\n upgradeCustomElement(registry, node);\n callback();\n } catch (error) {\n reject(error);\n }\n },\n (error) => {\n if (!finish()) return;\n reject(error);\n },\n );\n };\n const task: IDeferredDefinition = {\n node,\n born: ++nextGeneration,\n cancel: null,\n arm: () => {\n // 張り済み(cancel あり)か、session の手を離れた(済んだ・取り消した・外れて下ろした)待ちは張らない\n if (task.cancel !== null || !this.deferred.has(task)) return;\n try {\n wait();\n } catch (error) {\n // 後から張る待ちの失敗は呼び出し元へ返せない\n finish();\n reject(error);\n }\n },\n };\n const root = node.getRootNode();\n // まだ DocumentFragment の中(行を fragment で組んで活性化してから差し込む経路)。fragment の中の要素は\n // 行き先の registry にまだ結び付いていない — Chromium は global registry を返し、スコープ付き registry の\n // shadow root へ差し込むとそちらに付け替わる(#357)。差し込みは同じ同期処理のうちに済むので、待つ先は\n // その後で引く。\n // 並んでいる待ちがあれば、その後ろに並ぶ(ノードごとの登録順を保つ)。two-way・イベントを\n // 付ける待ち(createContent の fragment の中で登録)より先に値の遅延適用(差し込んだ後の活性化で登録)が\n // 走ると、初期同期の前に state の値が要素へ書かれる — `#init=element` の要素の値が消える。\n // 並べた待ちは microtask 1 回でまとめて、登録順に張る\n if (armQueue !== null || root.nodeType === 11 && !isObservableRoot(root)) {\n if (armQueue === null) {\n const queue: IDeferredDefinition[] = armQueue = [];\n queueMicrotask(() => {\n armQueue = null;\n for (let i = 0; i < queue.length; i++) queue[i].arm();\n });\n }\n armQueue.push(task);\n } else {\n wait();\n }\n if (isObservableRoot(root)) getBindingOwner(root);\n addInterestedSession(node, this);\n this.deferredByNode.set(node, tasks.add(task));\n this.deferred.add(task);\n return () => {\n finish();\n task.cancel?.();\n };\n }\n\n disposeBinding(binding: IBindingInfo): void {\n const row = this.rowOf(binding);\n if (row !== null) {\n const slot = row.bindings.indexOf(binding);\n if (slot >= 0) {\n this.disposeRowSlot(row, slot);\n return;\n }\n }\n const record = recordByBinding.get(binding);\n if (typeof record === \"undefined\" || record.session !== this) return;\n this.disposeRecord(record);\n }\n\n /** 行の session か(`for` 束縛ごとに 1 つを全行で共有する形。設計 R3) */\n get isRowSession(): boolean {\n return this.rowPlan !== null;\n }\n\n get currentRowPlan(): IRowPlan | null {\n return this.rowPlan;\n }\n\n /**\n * 共有 session の行単位の解体(設計 R3)。この content の行だけを解体する。\n *\n * 生きている行が 1 つも無くなったら、行ごと session だった頃の `dispose()` と同じく\n * 残っている定義待ち(`deferUntilDefined`)を取り消す。プラン行そのものは未定義要素を\n * 持てない(`compileRowPlan` がカスタム要素のテンプレートを不適格にする)が、\n * この session に注入された待ちが残ると閉包が強参照で残り続ける。\n */\n disposeBindings(bindings: readonly IBindingInfo[]): void {\n for (let i = 0; i < bindings.length; i++) {\n this.disposeBinding(bindings[i]);\n }\n if (this.rows.size > 0) {\n return;\n }\n for (const task of Array.from(this.deferred)) {\n task.cancel?.();\n this.deferred.delete(task);\n this.deferredByNode.get(task.node)?.delete(task);\n }\n }\n\n /** 行単位の wholesale destroy(設計 R3)。行を持たない session は従来どおり全部を捨てる */\n destroyRow(bindings: readonly IBindingInfo[]): void {\n const row = bindings.length > 0 ? this.rowOf(bindings[0]) : null;\n if (row === null) {\n this.destroyRecords();\n return;\n }\n this.destroyRowRecord(row);\n this.rows.delete(row);\n }\n\n private destroyRowRecord(row: IRowRecord): void {\n for (let i = 0; i < row.bindings.length; i++) {\n const address = row.addresses[i];\n if (address !== null) {\n removeBindingByAbsoluteStateAddress(address, row.bindings[i]);\n row.addresses[i] = null;\n }\n row.phases[i] = SLOT_DISPOSED;\n }\n }\n\n dispose(): void {\n this.disposedAt = nextGeneration;\n for (const row of Array.from(this.rows)) {\n for (let i = 0; i < row.bindings.length; i++) this.disposeRowSlot(row, i);\n }\n for (const record of Array.from(this.records)) this.disposeRecord(record);\n for (const task of Array.from(this.deferred)) {\n task.cancel?.();\n this.deferred.delete(task);\n this.deferredByNode.get(task.node)?.delete(task);\n }\n }\n\n /**\n * wholesale destroy(全行クリアで teardown を GC に任せる高速経路)を適用して\n * よいか。定義待ち(DefinitionCoordinator の waiter / deferred spread タスク)は\n * 強参照 Map に閉包が残り、connect-snapshot 待ちは pending カウンタが戻らなく\n * なるため、1 つでもあれば従来経路(teardown 実行)に倒す。\n */\n canWholesaleDestroy(): boolean {\n if (this.deferred.size > 0) return false;\n if (this.records.size === 0) return true; // 空の Set の反復も割り当てるので先に抜ける\n for (const record of this.records) {\n if (record.pendingDefinitions > 0 || record.observationPending) return false;\n }\n return true;\n }\n\n /**\n * 全 record を teardown を走らせずに終端化する(canWholesaleDestroy が true の\n * content 専用)。イベント listener・loopContext・パターン台帳(listIndex キー)は\n * ノード/binding もろとも GC で崩壊する(recordByBinding 以下は全て弱参照)。\n * 例外は null-listIndex の従来台帳(record.address): キーの intern 済み\n * AbsoluteStateAddress が PathInfo キャッシュ経由で生涯生存するため GC で\n * 崩壊せず、共有エントリに残った binding が binding.node 経由で行 DOM 全体を\n * 永久リークする。ここだけ明示除去する(行イベント binding が典型で行あたり\n * 高々数件・Set.delete のみなので wholesale の速度特性は保たれる)。\n * handlerBindingRegistry のカウンタは減らないが、残るのはキー文字列と数値のみで\n * 実害はない設計(handlerBindingRegistry.ts の弱参照化コメント参照)。\n */\n destroyRecords(): void {\n this.disposedAt = nextGeneration;\n for (const row of this.rows) this.destroyRowRecord(row);\n this.rows.clear();\n for (const record of this.records) {\n if (record.address !== null) {\n removeBindingByAbsoluteStateAddress(record.address, record.info);\n record.address = null;\n }\n record.phase = \"disposed\";\n record.teardowns = null;\n }\n this.records.clear();\n }\n\n /**\n * マウントスコープ専用(Phase 2・webComponent/mountScope.ts): 全 record の台帳登録を\n * **現在のループ文脈の listIndex** で張り直す。行 content のプール再利用でコンポーネント\n * 要素が別の行に付け替わると、スコープの binding は旧行の listIndex で台帳に載ったままに\n * なる — その 1 点だけを直す(listener・record・依存グラフは張り直し不要)。\n *\n * `for` binding は lastListValue(差分の基準)を旧アドレスから新アドレスへ引き継ぐ。\n * 引き継がないと再適用が全行 add と誤認し、旧行の DOM が残ったまま新行を重ねて\n * マウントする。戻り値は再適用すべき binding(呼び出し側が applyChangeFromBindings する)。\n */\n /**\n * マウントスコープ再接続専用: アクティブな record の binding ノード(text は差し替え前の\n * comment — ループ文脈の直接エントリはこのノードに載る)を列挙する。\n * remountScopeBindings が現在の行の文脈へ張り替えるために使う。\n */\n forEachActiveBindingNode(callback: (node: Node) => void): void {\n for (const row of this.rows) {\n for (let i = 0; i < row.bindings.length; i++) {\n if (row.phases[i] === SLOT_ACTIVE) callback(row.bindings[i].node);\n }\n }\n for (const record of this.records) {\n if (record.phase !== \"active\") continue;\n callback(record.info.node);\n }\n }\n\n rebindAddresses(): IBindingInfo[] {\n const rebound: IBindingInfo[] = [];\n for (const row of this.rows) {\n for (let i = 0; i < row.bindings.length; i++) {\n if (row.phases[i] !== SLOT_ACTIVE) continue;\n if (row.addresses[i] === null && row.patternPathInfos[i] === null) continue;\n const binding = row.bindings[i];\n this.unregisterRowSlot(row, i);\n this.registerRowSlot(row, i);\n if (this.shouldApplyState(binding)) rebound.push(binding);\n }\n }\n for (const record of this.records) {\n if (record.phase !== \"active\") continue;\n const binding = record.info;\n if (record.address === null && record.patternListIndex === null) continue;\n const oldAbs = binding.bindingType === \"for\" ? getAbsoluteStateAddressByBinding(binding) : null;\n unregisterFromLedger(binding, record.address, record.patternPathInfo, record.patternListIndex);\n record.address = null;\n record.patternPathInfo = null;\n record.patternListIndex = null;\n this.registerAddress(record);\n if (oldAbs !== null) {\n const newAbs = getAbsoluteStateAddressByBinding(binding);\n // 記録の有無は has で見る(get は未記録でも `[]` を返すため、!= null 判定は\n // 常に真 — 未記録の旧アドレスから空配列を持ち込んで、新アドレスに残っていた\n // 正当な記録を潰しうる)\n if (newAbs !== oldAbs && hasLastListValueByAbsoluteStateAddress(oldAbs)) {\n setLastListValueByAbsoluteStateAddress(newAbs, getLastListValueByAbsoluteStateAddress(oldAbs));\n }\n // state 側の基準(E1)も同じ理由で引き継ぐ。記録の有無は has で見る(同上)\n if (newAbs !== oldAbs && hasStateListBaseline(oldAbs)) {\n setStateListBaseline(newAbs, getStateListBaseline(oldAbs));\n }\n }\n if (this.shouldApplyState(binding)) {\n rebound.push(binding);\n }\n }\n return rebound;\n }\n\n observe(node: Node): void {\n const root = observableRootFor(node);\n if (root === null) return;\n // owner(root ごとの MutationObserver)の存在だけ保証する。session の配送先\n // 登録は node 単位(interestedSessionsByNode)で行い、owner は session を\n // 直接は保持しない。\n getBindingOwner(root);\n }\n\n handleMutations(root: IObservableRoot, removed: readonly Node[], added: readonly Node[]): void {\n for (const subtree of removed) {\n forEachInclusive(subtree, (node) => {\n if (root.contains(node)) return;\n this.handleRemovedNode(node);\n });\n }\n const reconnected: IBindingInfo[] = [];\n for (const subtree of added) {\n forEachInclusive(subtree, (node) => {\n if (!root.contains(node)) return;\n this.handleAddedNode(node, reconnected);\n });\n }\n if (reconnected.length > 0) applyChangeFromBindings(reconnected);\n }\n\n handleRemovedNode(node: Node): void {\n const known = this.knownBindingsByNode.get(node);\n if (typeof known !== \"undefined\") {\n if (known instanceof Map) {\n for (const binding of known.values()) this.disposeBinding(binding);\n } else {\n this.disposeBinding(known);\n }\n }\n // 外れている間は registry の待ちを下ろす(戻らない要素を掴み続けない)。task はノードの台帳(弱参照)\n // にだけ残し、戻ったら handleAddedNode が張り直す(#352)\n this.deferredByNode.get(node)?.forEach((task) => {\n task.cancel?.();\n task.cancel = null;\n this.deferred.delete(task);\n });\n }\n\n handleAddedNode(node: Node, reconnected: IBindingInfo[]): void {\n // 外れたときに下ろした定義待ちを、今属する registry で張り直す(#352)。外れている間に session ごと\n // 解体された(行が消えた・プールに入った)待ちは張り直さない — 消えた行の文脈で展開しない\n this.deferredByNode.get(node)?.forEach((task) => {\n if (task.born <= this.disposedAt) return;\n this.deferred.add(task);\n task.arm();\n });\n const known = this.knownBindingsByNode.get(node);\n if (typeof known === \"undefined\") return;\n const bindings = known instanceof Map ? known.values() : [known];\n for (const binding of bindings) {\n const record = recordByBinding.get(binding);\n if (record?.phase === \"active\") {\n this.settleConnectedSnapshot(record);\n continue;\n }\n if (record?.phase !== \"disposed\") continue;\n const options = this.optionsByBinding.get(binding);\n if (typeof options === \"undefined\") continue;\n try {\n this.start(binding, options);\n // 要素の定義を待っていた束縛の遅延適用は、外れたときに解体と一緒に取り消された — 再接続で適用し直さない\n // 束縛(行)でも、その行が生きていれば(外れている間に session ごと解体されていなければ)適用し直し、\n // 待ちを予約し直す(#352)\n if ((options.applyOnReconnect || record.pendingDefinitions > 0 && record.generation > this.disposedAt)\n && this.shouldApplyState(binding)) reconnected.push(binding);\n } catch {\n // Mutation delivery cannot surface initialization errors to a caller.\n }\n }\n }\n\n /**\n * anchor の known 台帳を Map 形へ正規化して返す(remember のキー照合用)。\n * 単一値(プラン行 or 既存単独 binding)は実キーを引いて昇格する。\n */\n private knownMapFor(anchor: Node): Map<string, IBindingInfo> {\n const current = this.knownBindingsByNode.get(anchor);\n if (current instanceof Map) {\n return current;\n }\n const map = new Map<string, IBindingInfo>();\n if (typeof current !== \"undefined\") {\n let key = bindingKeyByBinding.get(current);\n if (typeof key === \"undefined\") {\n key = bindingKey(current);\n bindingKeyByBinding.set(current, key);\n }\n map.set(key, current);\n }\n this.knownBindingsByNode.set(anchor, map);\n return map;\n }\n\n private remember(binding: IBindingInfo, options: IBindingOptions): IBindingInfo {\n const anchor = binding.replaceNode;\n // detached fragment 上でも登録しておく(node 単位の台帳なので root 非依存)。\n // fragment 一括マウントで後から接続された行にも mutation 配送が届くようにする。\n addInterestedSession(anchor, this);\n const known = this.knownMapFor(anchor);\n let key = bindingKeyByBinding.get(binding);\n if (typeof key === \"undefined\") {\n key = bindingKey(binding);\n bindingKeyByBinding.set(binding, key);\n }\n const remembered = known.get(key);\n if (typeof remembered !== \"undefined\") {\n const rememberedOptions = this.optionsByBinding.get(remembered);\n if (typeof rememberedOptions !== \"undefined\") {\n rememberedOptions.registerAddress ||= options.registerAddress;\n rememberedOptions.registerPathInfo ||= options.registerPathInfo;\n rememberedOptions.applyOnReconnect ||= options.applyOnReconnect;\n }\n return remembered;\n }\n known.set(key, binding);\n this.optionsByBinding.set(binding, { ...options });\n return binding;\n }\n\n /**\n * RowPlan 経路の一括初期化(createContent 専用・docs/state-row-instantiation-redesign.md §3-2)。\n * プラン行の binding はこの呼び出しでのみ生成されるため remember(キー照合・\n * options マージ)を丸ごと省略し、policy/authority はテンプレート時に解決済みの\n * 値を焼き込む。options は行内共有の 1 オブジェクト(activate が\n * registerAddress を昇格するとき行内全 binding が同時に昇格する — 従来も\n * activate は全 binding を同順で昇格するため観測可能な差はない)。\n */\n initializeRow(plan: IRowPlan, bindings: readonly IBindingInfo[]): void {\n this.rowPlan = plan;\n const slots = plan.slots;\n const n = bindings.length;\n const row: IRowRecord = {\n id: ++nextRecordId,\n session: this,\n generation: ++nextGeneration,\n plan,\n bindings,\n registered: false,\n // 素の配列(Smi)。型付き配列は本体と backing store で 1 本あたり 100 B を超え、cold の\n // 生成では行ごとの割り当ての上位に出た(設計 R5)\n phases: new Array<number>(n).fill(SLOT_ACTIVE),\n flags: new Array<number>(n).fill(0),\n addresses: new Array<IAbsoluteStateAddress | null>(n).fill(null),\n patternPathInfos: new Array<ITreePath | null>(n).fill(null),\n patternListIndexes: new Array<IListIndex | null>(n).fill(null),\n };\n this.rows.add(row);\n for (let i = 0; i < n; i++) {\n const binding = bindings[i];\n const anchor = binding.replaceNode;\n addInterestedSession(anchor, this);\n this.addKnownRowBinding(anchor, binding, i);\n rowByBinding.set(binding, row);\n if (slots[i].isEvent) {\n // 印は `attachEventHandler` の**戻り値**で立てる。今は `structural/rowPlan.ts` の\n // 名前空間除外によって `slot.isEvent` ⟺ `isDomEventBinding` が成り立っているが、\n // そこが緩んだ瞬間に「張っていないのに張った印」が立ち、detach が空振りする\n let attached = false;\n try {\n attached = attachEventHandler(binding);\n } catch (error) {\n row.phases[i] = SLOT_FAILED;\n throw error;\n }\n if (attached) row.flags[i] |= FLAG_EVENT_ATTACHED;\n }\n // 非 event スロットはプラン適格性により双方向不能・radio/checkbox 不能・\n // token 配線不能が確定しているため attach 系を一切呼ばない\n }\n }\n\n /**\n * プラン行の活性化(activate の高速経路)。bindings は initializeRow と同一の\n * スロット整列配列(bindingsByContent がそのまま保持)である前提。\n * プラン行の record は policy/authority 解決済み・observable なし・\n * connect-snapshot なしが構造的に保証されているため、settleInitialRecord /\n * settleConnectedSnapshot の呼び出し自体を省略できる。\n * プール再利用(disposed/failed)では record オブジェクトを再利用し、\n * 世代だけ進めて listener attach とアドレス登録をやり直す(record 再割当なし)。\n */\n private activatePlanRows(plan: IRowPlan, bindings: readonly IBindingInfo[], knownRoot: Node): void {\n const row = bindings.length > 0 ? this.rowOf(bindings[0]) : null;\n if (row === null || row.bindings !== bindings) {\n // この session の行でない binding 配列(防御): 従来経路\n for (const binding of bindings) {\n this.initialize([binding], { registerAddress: true, registerPathInfo: false, applyOnReconnect: false });\n }\n return;\n }\n row.registered = true;\n const slots = plan.slots;\n let revived = false;\n for (let i = 0; i < bindings.length; i++) {\n if (row.phases[i] !== SLOT_ACTIVE) {\n // pool 再利用: 世代だけ進めて listener attach とアドレス登録をやり直す\n if (!revived) {\n row.generation = ++nextGeneration;\n revived = true;\n this.rows.add(row);\n }\n row.phases[i] = SLOT_ACTIVE;\n row.flags[i] = 0;\n if (slots[i].isEvent) {\n let attached = false;\n try {\n attached = attachEventHandler(bindings[i]);\n } catch (error) {\n row.phases[i] = SLOT_FAILED;\n this.runRowSlotTeardowns(row, i);\n throw error;\n }\n if (attached) row.flags[i] |= FLAG_EVENT_ATTACHED;\n }\n this.registerRowSlot(row, i, knownRoot);\n continue;\n }\n if (row.addresses[i] === null && row.patternPathInfos[i] === null) {\n // 初回活性化\n this.registerRowSlot(row, i, knownRoot);\n }\n }\n }\n\n private rowOf(binding: IBindingInfo): IRowRecord | null {\n const row = rowByBinding.get(binding);\n return typeof row !== \"undefined\" && row.session === this ? row : null;\n }\n\n private registerRowSlot(row: IRowRecord, slot: number, knownRoot?: Node | null): void {\n if (row.addresses[slot] !== null || row.patternPathInfos[slot] !== null) return;\n const binding = row.bindings[slot];\n const listIndex = getListIndexByBindingInfo(binding);\n if (listIndex !== null) {\n row.patternPathInfos[slot] = registerPattern(binding, listIndex, knownRoot);\n row.patternListIndexes[slot] = listIndex;\n } else {\n row.addresses[slot] = registerAbsoluteAddress(binding, knownRoot);\n }\n // registerPathInfo は行オプションで常に false\n }\n\n private unregisterRowSlot(row: IRowRecord, slot: number): void {\n const address = row.addresses[slot];\n const pathInfo = row.patternPathInfos[slot];\n if (address === null && pathInfo === null) return;\n // 外せなかった(台帳の throw)ときは器を残す: 後で生き返った行が登録し直さないように\n unregisterFromLedger(row.bindings[slot], address, pathInfo, row.patternListIndexes[slot]);\n row.addresses[slot] = null;\n row.patternPathInfos[slot] = null;\n row.patternListIndexes[slot] = null;\n }\n\n private disposeRowSlot(row: IRowRecord, slot: number): void {\n if (row.phases[slot] === SLOT_DISPOSED) return;\n row.phases[slot] = SLOT_DISPOSED;\n this.runRowSlotTeardowns(row, slot);\n for (let i = 0; i < row.phases.length; i++) {\n if (row.phases[i] === SLOT_ACTIVE) return;\n }\n this.rows.delete(row);\n }\n\n private runRowSlotTeardowns(row: IRowRecord, slot: number): void {\n try {\n this.unregisterRowSlot(row, slot);\n } catch {\n // Cleanup is best-effort; one faulty resource must not retain the rest.\n }\n if ((row.flags[slot] & FLAG_EVENT_ATTACHED) !== 0) {\n row.flags[slot] &= ~FLAG_EVENT_ATTACHED;\n try {\n detachEventHandler(row.bindings[slot]);\n } catch {\n // Cleanup is best-effort.\n }\n }\n }\n\n private addKnownRowBinding(anchor: Node, binding: IBindingInfo, slotIndex: number): void {\n const current = this.knownBindingsByNode.get(anchor);\n if (typeof current === \"undefined\") {\n this.knownBindingsByNode.set(anchor, binding);\n return;\n }\n // 同一 anchor に複数スロット(複数エントリの data-wcs): Map へ昇格。\n // プラン行はキー照合されないため添字ベースの合成キーで一意性だけ担保する\n if (current instanceof Map) {\n current.set(\"@plan:\" + slotIndex, binding);\n return;\n }\n const map = new Map<string, IBindingInfo>();\n map.set(\"@plan:first\", current);\n map.set(\"@plan:\" + slotIndex, binding);\n this.knownBindingsByNode.set(anchor, map);\n }\n\n private start(binding: IBindingInfo, options: IBindingOptions, knownRoot?: Node | null): void {\n replaceToReplaceNode(binding);\n const recordOptions = this.optionsByBinding.get(binding) ?? { ...options };\n const record: IInternalBindingRecord = {\n id: ++nextRecordId,\n info: binding,\n generation: ++nextGeneration,\n phase: \"discovered\",\n teardowns: null,\n session: this,\n anchor: binding.replaceNode,\n options: recordOptions,\n address: null,\n patternPathInfo: null,\n patternListIndex: null,\n pendingDefinitions: 0,\n initialPolicy: null,\n resolvedAuthority: null,\n initialSettled: false,\n initialApplyDone: false,\n outputOnlyMember: false,\n observationPending: false,\n eventSequence: 0,\n hasProducerValue: false,\n producerValue: undefined,\n eventAttached: false,\n twowayAttached: false,\n };\n recordByBinding.set(binding, record);\n this.records.add(record);\n // knownRoot が渡されたときは observe を省略する(null = detached fragment 上で\n // observableRootFor が必ず null、Node = activate 冒頭で owner 保証済み)\n if (typeof knownRoot === \"undefined\") this.observe(record.anchor);\n\n try {\n record.phase = \"attaching\";\n this.attachListeners(record);\n if (record.options.registerAddress) this.registerAddress(record, knownRoot);\n if (record.pendingDefinitions === 0) record.phase = \"active\";\n } catch (error) {\n record.phase = \"failed\";\n this.runTeardowns(record);\n this.records.delete(record);\n throw error;\n }\n }\n\n private attachListeners(record: IInternalBindingRecord): void {\n const binding = record.info;\n if (attachEventHandler(binding)) {\n record.eventAttached = true;\n return;\n }\n\n if (binding.propSegments[0] === EVENT_TOKEN_NAMESPACE) {\n this.attachAfterDefinition(record, () => {\n if (attachEventTokenHandler(binding)) {\n addRecordTeardown(record, () => detachEventTokenHandler(binding));\n }\n });\n return;\n }\n\n if (attachRadioEventHandler(binding)) {\n addRecordTeardown(record, () => detachRadioEventHandler(binding));\n }\n if (attachCheckboxEventHandler(binding)) {\n addRecordTeardown(record, () => detachCheckboxEventHandler(binding));\n }\n this.attachAfterDefinition(record, () => {\n // directional initial sync の producer-value observer は twowayEventHandlerFunction\n // からのみ呼ばれる(唯一の consumer)。その handler が attach されるのは\n // isPossibleTwoWay かつ非 ro の binding だけ(attachTwowayEventHandler と同条件)\n // なので、one-way / event / eventToken / radio(非value) 等では observer は決して\n // fire しない。以前は attachListeners 冒頭で全 binding に無条件登録していたが、\n // fire しえない大多数の binding に対する setup 死荷重だった。ここへ移すことで\n // 「twoway handler が付く binding のみ observer 登録」を構造的に保証する\n // (undefined custom element は attachAfterDefinition が定義後まで遅延するので\n // isPossibleTwoWay の未定義 CE raiseError も踏まない)。\n if (\n config.enableDirectionalInitialSync\n && isPossibleTwoWay(binding.node, binding.propName)\n && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1\n ) {\n const removeObserver = addTwowayValueObserver(binding.node, binding.propName, (value) => {\n if (!this.isAlive(record, record.generation)) return;\n record.eventSequence += 1;\n record.hasProducerValue = true;\n record.producerValue = value;\n });\n addRecordTeardown(record, removeObserver);\n }\n attachTwowayEventHandler(binding);\n record.twowayAttached = true;\n });\n }\n\n private attachAfterDefinition(record: IInternalBindingRecord, attach: () => void): void {\n const tagName = getCustomElement(record.info.node);\n if (tagName === null) {\n attach();\n return;\n }\n const registry = getCustomElementRegistry(record.info.node);\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${tagName}>.`);\n }\n if (typeof registry.get(tagName) !== \"undefined\") {\n attach();\n return;\n }\n\n record.phase = \"waiting-definition\";\n record.pendingDefinitions += 1;\n const generation = record.generation;\n // 待つ先の registry は deferUntilDefined が引く — 行の中身(createContent の fragment の中)は\n // 差し込んだ後の木の registry で待つ(#357)\n addRecordTeardown(record, this.deferUntilDefined(record.info.node, tagName, () => {\n if (!this.isAlive(record, generation)) return;\n attach();\n record.pendingDefinitions -= 1;\n if (record.pendingDefinitions === 0) {\n record.phase = \"active\";\n this.settleInitialRecord(record);\n }\n }, () => {\n if (!this.isAlive(record, generation)) return;\n record.phase = \"failed\";\n this.runTeardowns(record);\n this.records.delete(record);\n }));\n }\n\n private settleInitialRecord(record: IInternalBindingRecord): void {\n if (!config.enableDirectionalInitialSync || record.initialSettled || !record.options.registerAddress) return;\n record.phase = \"synchronizing\";\n try {\n const policy = resolveInitialSyncPolicy(record.info);\n const authority = resolveInitialAuthority(record.info, policy.authority);\n record.initialPolicy = policy;\n record.resolvedAuthority = authority;\n record.initialSettled = true;\n record.outputOnlyMember = policy.outputOnly;\n record.phase = \"active\";\n if (!policy.observable) return;\n if (\n policy.syncOn === \"connect\"\n && record.info.node instanceof HTMLElement\n && !record.info.node.isConnected\n ) {\n record.observationPending = true;\n // 待ちが 1 件でもある間は追加側 observer スキップを無効化する\n incrementPendingObservation();\n return;\n }\n this.readProducerSnapshot(record, policy.syncOn === \"call\");\n } catch (error) {\n record.phase = \"failed\";\n this.runTeardowns(record);\n this.records.delete(record);\n throw error;\n }\n }\n\n private readProducerSnapshot(record: IInternalBindingRecord, eventWins: boolean): void {\n if (!this.isAlive(record, record.generation)) return;\n const target = record.info.node as Node & Record<string, unknown>;\n const name = record.info.propName;\n if (!(name in target)) return;\n const sequence = record.eventSequence;\n const value = target[name];\n if (record.observationPending) {\n record.observationPending = false;\n decrementPendingObservation();\n }\n if (eventWins && record.eventSequence !== sequence) return;\n record.hasProducerValue = true;\n record.producerValue = value;\n if (record.resolvedAuthority === \"element\") {\n commitProducerValue(record.info, value);\n }\n }\n\n private settleConnectedSnapshot(record: IInternalBindingRecord): void {\n if (\n !config.enableDirectionalInitialSync\n || !record.observationPending\n || !(record.info.node instanceof HTMLElement)\n || !record.info.node.isConnected\n ) return;\n try {\n this.readProducerSnapshot(record, false);\n } catch {\n record.phase = \"failed\";\n this.runTeardowns(record);\n this.records.delete(record);\n }\n }\n\n private registerAddress(record: IInternalBindingRecord, knownRoot?: Node | null): void {\n if (record.address !== null || record.patternListIndex !== null) return;\n const binding = record.info;\n const listIndex = getListIndexByBindingInfo(binding);\n if (listIndex !== null) {\n record.patternPathInfo = registerPattern(binding, listIndex, knownRoot);\n record.patternListIndex = listIndex;\n } else {\n record.address = registerAbsoluteAddress(binding, knownRoot);\n }\n // 台帳解除は runTeardowns が record.address / pattern フィールドから\n // データ駆動で行う(クロージャ不要)\n if (!record.options.registerPathInfo) return;\n const rootNode = binding.replaceNode.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n if (binding.bindingType !== \"event\") {\n stateElement.setPathInfo(binding.statePathName, binding.bindingType);\n }\n }\n\n private isAlive(record: IInternalBindingRecord, generation: number): boolean {\n return record.generation === generation\n && recordByBinding.get(record.info) === record\n && record.phase !== \"disposed\"\n && record.phase !== \"failed\";\n }\n\n private disposeRecord(record: IInternalBindingRecord): void {\n if (record.phase === \"disposed\") return;\n record.phase = \"disposed\";\n this.runTeardowns(record);\n this.records.delete(record);\n }\n\n private runTeardowns(record: IInternalBindingRecord): void {\n // runTeardowns は record の終端(disposed / failed)でのみ呼ばれる。未消化の\n // connect-snapshot 待ちが残っていれば必ずカウンタを戻す(スキップ再有効化)。\n if (record.observationPending) {\n record.observationPending = false;\n decrementPendingObservation();\n }\n const binding = record.info;\n // データ駆動の後始末(従来はクロージャで積んでいた頻出3種)。実行順は従来の\n // 逆順実行と同じ: アドレス台帳解除(最後に積まれていた)→ 双方向 detach →\n // 希少クロージャ群(逆順)→ イベント detach。各 detach は互いに独立した資源を\n // 対象とするため、この順序で意味論は変わらない。\n if (record.address !== null || record.patternListIndex !== null) {\n try {\n unregisterFromLedger(binding, record.address, record.patternPathInfo, record.patternListIndex);\n record.address = null;\n record.patternPathInfo = null;\n record.patternListIndex = null;\n } catch {\n // Cleanup is best-effort; one faulty resource must not retain the rest.\n }\n }\n if (record.twowayAttached) {\n record.twowayAttached = false;\n try {\n detachTwowayEventHandler(binding);\n } catch {\n // Cleanup is best-effort.\n }\n }\n if (record.teardowns !== null) {\n const teardowns = Array.from(record.teardowns).reverse();\n record.teardowns = null;\n for (const teardown of teardowns) {\n try {\n teardown();\n } catch {\n // Cleanup is best-effort; one faulty resource must not retain the rest.\n }\n }\n }\n if (record.eventAttached) {\n record.eventAttached = false;\n try {\n detachEventHandler(binding);\n } catch {\n // Cleanup is best-effort.\n }\n }\n }\n}\n\nexport function getOrCreateBindingSession(root: Node): BindingSession {\n let session = sessionByRoot.get(root);\n if (typeof session === \"undefined\") {\n session = new BindingSession(root);\n sessionByRoot.set(root, session);\n }\n return session;\n}\n\nexport function getBindingSession(binding: IBindingInfo): BindingSession | null {\n return recordByBinding.get(binding)?.session ?? rowByBinding.get(binding)?.session ?? null;\n}\n\n/**\n * 要素の定義を待って、まだ two-way・イベントを付けていない(初期同期もしていない)束縛か。\n * `applyChange` はこの間、要素がもう定義済みに見えても値を直接書かず、定義待ちの後ろへ回す(#357)。\n */\nexport function isWaitingDefinition(binding: IBindingInfo): boolean {\n return recordByBinding.get(binding)?.phase === \"waiting-definition\";\n}\n","import { IBindingInfo } from \"../types.js\";\n\nexport function replaceToReplaceNode(bindingInfo: IBindingInfo): void {\n const node = bindingInfo.node;\n const replaceNode = bindingInfo.replaceNode;\n if (node === replaceNode) {\n return;\n }\n if (node.parentNode === null) {\n // already replaced\n return;\n }\n node.parentNode.replaceChild(replaceNode, node);\n}\n","/**\n * core/componentApplyHooks.ts — カスタム要素のプロパティ束縛の受け口(設計案 S5)。\n *\n * `bind-component` の機能(webComponent/bindComponentLifecycle.ts)が install で置く。apply 側\n * (apply/applyChange.ts・apply/applyChangeToProperty.ts)は、置かれていなければカスタム要素への\n * 束縛も素のプロパティ書き込みとして扱い、何も控えない — 控えの読み手は bind-component の中にしか居ない。\n */\n\nexport interface IComponentApplyHooks {\n /** `bind-component` の配線が完了した (要素, state プロパティ)。値を運ばない通知チャネルへ切り替える */\n isComplete(element: Element, stateProp: string): boolean;\n /** 宣言済み・未完了。完了前の初期適用は書かない */\n isDeclared(element: Element, stateProp: string): boolean;\n /** 完了前の丸ごと書き込み(`state: user`)が置き換える作者のオブジェクトを控える */\n rememberOverwrittenObject(element: Element, prop: string, previous: object): void;\n /** 完了前の部分書き込み(`state.theme: theme`)が作者のオブジェクトに作ったキーを控える */\n recordInjectedKey(element: Element, prop: string, key: string): void;\n /** 完了前の部分書き込みが上書きする作者の既存キーの値を控える */\n rememberOverwrittenValue(element: Element, prop: string, key: string, previous: unknown): void;\n}\n\n/** 置かれていなければ null(apply 側は判定 1 回で素の書き込みに倒す) */\nexport let componentApplyHooks: IComponentApplyHooks | null = null;\n\n/** 機能の install が呼ぶ(冪等 — 置き換え) */\nexport function setComponentApplyHooks(hooks: IComponentApplyHooks | null): void {\n componentApplyHooks = hooks;\n}\n","import { IFilterInfo } from \"../binding/types.js\";\n\nexport function getFilteredValue(value: any, filters: IFilterInfo[]) {\n let filteredValue = value;\n for(const filter of filters) {\n filteredValue = filter.filterFn(filteredValue);\n }\n return filteredValue;\n}\n","import { createEmptyArray } from \"../createEmptyArray\";\nimport { IBindingInfo } from \"../types\";\nimport { getFilteredValue } from \"./getFilteredValue\";\nimport { IApplyContext } from \"./types\";\n\nconst EMPTY_ARRAY = createEmptyArray<unknown>();\n\nexport function applyChangeToCheckbox(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const element = binding.node as HTMLInputElement;\n const elementValue = element.value;\n const elementFilteredValue = getFilteredValue(elementValue, binding.inFilters);\n const normalizedNewValue = Array.isArray(newValue) ? newValue : EMPTY_ARRAY;\n element.checked = normalizedNewValue.includes(elementFilteredValue);\n}\n","\nexport function createEmptyArray<T>(): Readonly<Array<T>> {\n return Object.freeze<Array<T>>([]);\n}\n","/**\n * command.<methodName>: <commandToken-path> バインディングの適用ハンドラ。\n *\n * subscribe lifecycle:\n * - 同一 binding に同じ token が再評価された場合は no-op。\n * - 異なる token が来た場合は古い subscription を解除し、新しい token に subscribe し直す。\n * 旧解除は新しい binding 妥当性検証(methodName・wcBindable.commands チェック)を\n * 通過した後に行うため、再評価が validation で失敗しても旧購読は温存される(fail-fast)。\n * - element は WeakRef で保持し、subscriber 経由で element を強参照しないようにする。\n * これにより、element が DOM から消えた後に subscriber が token._subscribers に\n * 残っていても element 本体は GC 可能。\n * - emit 時に下記いずれかなら自動で subscription を破棄する(lazy purge):\n * - WeakRef.deref() が undefined(element が既に GC 済み)\n * - element.isConnected が false(DOM から取り外されている)\n *\n * 既知の制約:\n * - emit が来なければ stale subscriber は token に残り続ける(要素が GC されても subscriber 関数自体は残る)。\n * registry は state 要素をキーにした WeakMap なので、state 要素ごと GC されたときに解放される。\n * 切断では registry を捨てない — 捨てると、ルート <wcs-state> を付け直した後の emit が\n * 購読者の居ない新しい token に届き、命令が無言で止まる(#273)。\n * element ライフサイクルに直接フックする手段が現状の binding 機構に無いため、能動的な purge は将来課題。\n */\n\nimport { isCommandToken } from \"../command/CommandToken\";\nimport { ICommandToken } from \"../command/types\";\nimport { didYouMean } from \"../errorGuidance\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration, ReadBindableResult } from \"../protocol/wcBindableReader\";\nimport { raiseError } from \"../raiseError\";\nimport { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\ninterface ICommandSubscription {\n readonly token: ICommandToken;\n readonly unsubscribe: () => void;\n readonly elementRef: WeakRef<Element>;\n}\n\nconst subscribedBindings: WeakMap<IBindingInfo, ICommandSubscription> = new WeakMap();\n\nfunction getWcBindable(element: Element): ReadBindableResult | null {\n const customTagName = getCustomElement(element);\n if (customTagName === null) {\n return null;\n }\n const customClass = getCustomElementRegistry(element)?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n raiseError(`Custom element <${customTagName}> is not defined for command binding.`);\n }\n return readBindableDeclaration(element);\n}\n\nexport function applyChangeToCommand(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n if (!isCommandToken(newValue)) {\n raiseError(`command binding requires a CommandToken value (use $command.<tokenName> with a name declared in $commandTokens).`);\n }\n const token = newValue as ICommandToken;\n\n const existing = subscribedBindings.get(binding);\n if (existing && existing.token === token) {\n return;\n }\n\n // 新しい binding 妥当性検証は、旧 subscription を解除する前に通す(fail-fast)。\n const element = binding.node as Element;\n const methodName = binding.propSegments[1];\n if (typeof methodName !== \"string\" || methodName.length === 0) {\n raiseError(`command binding requires a method name (e.g., \"command.fetch\").`);\n }\n\n const bindable = getWcBindable(element);\n if (bindable === null) {\n raiseError(`command binding requires a wc-bindable custom element. <${element.tagName.toLowerCase()}> is not wc-bindable.`);\n }\n if (!bindable.declaredCommands.has(methodName)) {\n // eventTokenHandler の property 検証と対双の did-you-mean(設計 §3)。\n raiseError(`Command \"${methodName}\" is not declared in wcBindable.commands of <${element.tagName.toLowerCase()}>.${didYouMean(methodName, bindable.declaredCommands.keys())}`);\n }\n\n // ここまで来たら旧解除して新 subscribe に切り替える。\n if (existing) {\n existing.unsubscribe();\n subscribedBindings.delete(binding);\n }\n\n const elementRef = new WeakRef(element);\n let unsubscribe: (() => void) | null = null;\n const subscriber = (...args: unknown[]): unknown => {\n const el = elementRef.deref();\n if (!el || !el.isConnected) {\n unsubscribe?.();\n subscribedBindings.delete(binding);\n return undefined;\n }\n const method = (el as unknown as Record<string, unknown>)[methodName];\n if (typeof method !== \"function\") {\n raiseError(`Method \"${methodName}\" is not a function on <${el.tagName.toLowerCase()}>.`);\n }\n return Reflect.apply(method as (...a: unknown[]) => unknown, el, args);\n };\n unsubscribe = token.subscribe(subscriber);\n subscribedBindings.set(binding, { token, unsubscribe, elementRef });\n}\n\nexport const __private__ = {\n subscribedBindings,\n};\n","import { IContent } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\n\nconst bindingsByContent: WeakMap<IContent, IBindingInfo[]> = new WeakMap();\n\nexport function getBindingsByContent(content: IContent): IBindingInfo[] {\n return bindingsByContent.get(content) ?? [];\n}\n\nexport function setBindingsByContent(content: IContent, bindings: IBindingInfo[]): void {\n bindingsByContent.set(content, bindings);\n}\n","import { IContent } from \"../structural/types\";\n\nconst nodesByContent: WeakMap<IContent, Node[]> = new WeakMap();\n\nexport function getNodesByContent(content: IContent): Node[] {\n return nodesByContent.get(content) ?? [];\n}\n\nexport function setNodesByContent(content: IContent, nodes: Node[]): void {\n nodesByContent.set(content, nodes);\n}\n","import { setLoopContextByNode } from \"../list/loopContextByNode\";\nimport { ILoopContext } from \"../list/types\";\nimport { IContent } from \"../structural/types\";\nimport { getNodesByContent } from \"./nodesByContent\";\n\nexport function bindLoopContextToContent(content: IContent, loopContext: ILoopContext | null): void {\n const nodes = getNodesByContent(content);\n for(const node of nodes) {\n setLoopContextByNode(node, loopContext);\n }\n}\n\nexport function unbindLoopContextToContent(content: IContent): void {\n const nodes = getNodesByContent(content);\n for (let i = 0; i < nodes.length; i++) { // 添字ループ(消去の窓に反復子のごみを残さない)\n setLoopContextByNode(nodes[i], null);\n }\n}\n","import { IContent } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\n\nconst indexBindingsByContent: WeakMap<IContent, IBindingInfo[]> = new WeakMap();\n\nexport function getIndexBindingsByContent(content: IContent): IBindingInfo[] {\n return indexBindingsByContent.get(content) ?? [];\n}\n\nexport function setIndexBindingsByContent(content: IContent, bindings: IBindingInfo[]): void {\n indexBindingsByContent.set(content, bindings);\n}\n","/* v8 ignore file */\nexport {};\n\ndeclare global {\n interface Set<T> {\n difference(other: Set<T>): Set<T>;\n intersection(other: Set<T>): Set<T>;\n }\n}\n\nif (!Set.prototype.difference) {\n Set.prototype.difference = function <T>(this: Set<T>, other: Set<T>): Set<T> {\n const result = new Set(this);\n for (const elem of other) {\n result.delete(elem);\n }\n return result;\n };\n}\n\nif (!Set.prototype.intersection) {\n Set.prototype.intersection = function <T>(this: Set<T>, other: Set<T>): Set<T> {\n const result = new Set<T>();\n for (const elem of other) {\n if (this.has(elem)) {\n result.add(elem);\n }\n }\n return result;\n };\n}\n","import { IAbsoluteStateAddress, IPathInfo } from \"../address/types\";\nimport { advanceRowCacheStamp } from \"../list/createListIndex\";\nimport { ICacheEntry } from \"./types\";\n\nconst cacheEntryByAbsoluteStateAddress: WeakMap<IAbsoluteStateAddress, ICacheEntry> = new WeakMap();\n\n/**\n * 同じ行の下に子孫のパスがキャッシュに載ったことのあるパス(`items.*.m.k0` を載せると `items.*.m` と\n * `items.*`)。このパスの値を無効にすると、行の印を進めて子孫の項目をまとめて外す(#389)。\n * パスの単位で state を問わない — 別の state が載せた分で印を進めても、読み直しが増えるだけ。\n */\nconst rowCacheParents: WeakSet<IPathInfo> = new WeakSet();\n\nexport function getCacheEntryByAbsoluteStateAddress(\n address: IAbsoluteStateAddress\n): ICacheEntry | null {\n return cacheEntryByAbsoluteStateAddress.get(address) ?? null;\n}\n\nexport function setCacheEntryByAbsoluteStateAddress(\n address: IAbsoluteStateAddress,\n cacheEntry: ICacheEntry | null\n): void {\n if (cacheEntry === null) {\n cacheEntryByAbsoluteStateAddress.delete(address);\n } else {\n cacheEntryByAbsoluteStateAddress.set(address, cacheEntry);\n // 行の値(ワイルドカードを含むパス)は行ごとに載る。要素の書き込み・`$postUpdate` が子のパスのキャッシュに\n // 届くように(#364):\n // - 行の下で同じ行の親になるパスに印を付ける。そのパスの値を無効にすると行の印が進み、子のパスの項目は\n // 読みで外れる(dirtyCacheEntryByAbsoluteStateAddress)。子のパスを要素パスからの静的な辺に載せると、\n // 要素の書き込みの依存ウォークの費用が行の下で読んだパスの数に比例した(#389 — 動的なキー 1 万個で\n // 1 回 約 5 ms)。\n // - 静的な辺に載せるのはリストの連なり(`items → items.*`)だけ。`for` で描いていないリストでも、リストへの\n // 代入・`$postUpdate(\"items\")` の依存ウォークが行へ届く。\n // 子のパスを読む getter へは、依存の辺が同じ行の親からも張られる(State.addDynamicDependency)。\n // 2 回目からは印の判定と登録済みのパスの判定(State.setPathInfo)1 回ずつで抜ける\n const { stateElement, pathInfo } = address.absolutePathInfo;\n if (pathInfo.wildcardCount > 0) {\n for (let parent = pathInfo.parentPathInfo;\n parent !== null && parent.wildcardCount === pathInfo.wildcardCount && !rowCacheParents.has(parent);\n parent = parent.parentPathInfo) {\n rowCacheParents.add(parent);\n }\n stateElement.setPathInfo(pathInfo.lastWildcardPath!, \"prop\", \"internal\");\n }\n }\n}\n\nexport function dirtyCacheEntryByAbsoluteStateAddress(\n address: IAbsoluteStateAddress\n): void {\n const cacheEntry = cacheEntryByAbsoluteStateAddress.get(address);\n if (cacheEntry) {\n cacheEntry.dirty = true;\n }\n // 同じ行の下に載った子孫のパスの項目もまとめて外す(#389)。無効にするのは値が変わりうるときで、その下の\n // 値も変わりうる\n if (address.listIndex !== null && rowCacheParents.has(address.absolutePathInfo.pathInfo)) {\n advanceRowCacheStamp(address.listIndex);\n }\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/transition-runner.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// transition-runner protocol — how a package that mutates the DOM hands that\n// mutation to whoever is arbitrating view transitions on the page.\n//\n// @wcstack/state and @wcstack/router must not depend on @wcstack/view-transition\n// (zero runtime dependencies, independently publishable), so the arbiter installs\n// itself on a well-known global symbol and the participants look it up lazily.\n// No arbiter installed means the mutation is invoked directly, synchronously —\n// byte-for-byte the behavior these packages had before the protocol existed.\n//\n// docs/view-transition-design.md §4 is the normative description.\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/transition-runner.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/transitionRunner.ts). Those copies are generated — do not edit them.\n\n/**\n * Global key the arbiter installs itself under. `Symbol.for` so independently\n * loaded copies of this file (two CDN bundles on one page) still agree.\n */\nexport const TRANSITION_RUNNER_KEY = Symbol.for(\"wcstack.transition-runner\");\n\n/** Who is asking. Backs the arbiter's `for=` participant gate. */\nexport type TransitionSource = \"router\" | \"state\";\n\n/** `view-transition-name` assignment policy the arbiter declares for participants. */\nexport type TransitionNaming = \"manual\" | \"auto\";\n\nexport interface IWcsTransitionRunOptions {\n /** Participant id, for the `for=` gate and for diagnostics. */\n readonly source?: string;\n /** Transition types, where the environment supports `startViewTransition({ types })`. */\n readonly types?: readonly string[];\n}\n\nexport interface IWcsTransitionRunner {\n readonly protocol: \"wcs-transition-runner\";\n /** Integer protocol version. All versions >= 1 are participant-compatible. */\n readonly version: number;\n /** `\"auto\"` licenses a participant to assign `view-transition-name` itself. */\n readonly naming: TransitionNaming;\n /** Upper bound on auto-assigned names; past it a participant stops naming. */\n readonly namingLimit: number;\n /** Whether this participant animates at all. */\n accepts(source: string): boolean;\n /**\n * Invoke `mutate` inside a view transition when one is possible.\n *\n * Contract (docs/view-transition-design.md §4):\n * - `mutate` is invoked exactly once, whatever happens to the transition.\n * - The promise resolves once `mutate` has run — never waits for the animation.\n * - When no transition is started, `mutate` runs synchronously inside `run()`.\n * - It rejects only if `mutate` threw.\n */\n run(mutate: () => void, options?: IWcsTransitionRunOptions): Promise<void>;\n}\n\n/**\n * The installed arbiter, or null when there is none, it speaks a version this\n * reader does not, or it does not accept this participant.\n *\n * Looked up on every call rather than cached: the tag can be added, removed, or\n * reconfigured at any point in a page's life, and a stale cache would either\n * animate what the author just switched off or miss what they switched on.\n */\nexport function getTransitionRunner(source: string): IWcsTransitionRunner | null {\n const candidate = (globalThis as Record<symbol, unknown>)[TRANSITION_RUNNER_KEY] as\n | IWcsTransitionRunner\n | undefined;\n if (candidate === undefined || candidate === null) return null;\n if (candidate.protocol !== \"wcs-transition-runner\") return null;\n if (typeof candidate.version !== \"number\" || candidate.version < 1) return null;\n if (typeof candidate.run !== \"function\") return null;\n if (typeof candidate.accepts !== \"function\" || !candidate.accepts(source)) return null;\n return candidate;\n}\n\n/**\n * Run `mutate` under the installed arbiter, or directly when there is none.\n *\n * Returns `undefined` in the no-arbiter case instead of a resolved promise: the\n * state drain calls this on every batch, and awaiting is a caller's choice, not\n * an allocation the common path should pay for. `await` accepts both.\n */\nexport function runTransition(\n source: string,\n mutate: () => void,\n types?: readonly string[],\n): Promise<void> | undefined {\n const runner = getTransitionRunner(source);\n if (runner === null) {\n mutate();\n return undefined;\n }\n return runner.run(mutate, { source, types });\n}\n","import { IAbsoluteStateAddress } from \"../address/types\";\nimport type { IStateElement } from \"../components/types\";\nimport { beginStateListBaselineBatch, endStateListBaselineBatch } from \"../list/stateListBaseline\";\nimport { advanceUpdateBatch } from \"./updateBatch\";\nimport { applyChangeFromBindings } from \"../apply/applyChangeFromBindings\";\nimport { peekBindingsForAddress } from \"../binding/getBindingSetByAbsoluteStateAddress\";\nimport { inSsr } from \"../config\";\nimport { MAX_PROPAGATION_HOPS, MAX_RENDER_CHAIN_DEPTH } from \"../define\";\nimport { runTransition } from \"../protocol/transitionRunner\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { IPropagationContext } from \"../propagation/types\";\nimport { IBindingInfo } from \"../types\";\n\n/**\n * drain(_applyChange)終了通知のリスナー(docs/state-streams-design.md §3-2)。\n * バッチ内の更新アドレス(AbsoluteStateAddress のインスタンス同一性で\n * dedup 済みの Set)を受け取る。stream runtime の依存駆動 restart が\n * この通知を交差判定の入力にする。\n */\nexport type UpdateBatchListener = (batch: ReadonlySet<IAbsoluteStateAddress>) => void;\n\ninterface IRegisteredBatchListener {\n readonly listener: UpdateBatchListener;\n readonly priority: number;\n}\n\nconst updateBatchListeners: IRegisteredBatchListener[] = [];\n\n/**\n * 書き込みの enqueue を見る機能(設計案 H2 の enqueue 側)。`$watch` の連鎖深さ(watch/chainDepth.ts)と\n * `on` scan の保留 reset(scan/eventReset.ts)が install で登録する。互いに独立なので順序契約は無い。\n * 登録が無ければ enqueue は配列長 0 の判定 1 回で抜ける。\n */\nexport type EnqueueListener = (absoluteAddress: IAbsoluteStateAddress) => void;\n\nconst enqueueListeners: EnqueueListener[] = [];\n\n/**\n * 描画起点の書き込み連鎖の深さ(#338・MAX_RENDER_CHAIN_DEPTH)。書き込みは enqueue の時点で 3 通りに分かれる。\n * - binding の適用(下の applyBindings)の最中: 「次のバッチはこの連鎖の続き」と印を付ける\n * (行を作るときの要素の初期同期・binding が設定したその場で要素が同期に出したイベント・`$renderedCallback` など)\n * - drain の外(作者の操作・非同期に届く I/O ノードのイベント・`$stream` の値・ハイドレーション): 次のバッチを深さ 0 から\n * 数え直す。microtask で刻む書き手(`await` の続き・待ちの無い `$stream`)が描画の書き戻しと同じバッチに\n * 乗り続けても、連鎖を伸ばさない\n * - drain 終了リスナー(`$scan` / `$watch` / `$streams` restart)の中: 伸ばしも数え直させもせず、今のバッチの\n * 深さを次のバッチへ引き継ぐ。`$watch` は自分の連鎖上限を持つので重ねて数えない。引き継がないと、描画の\n * 書き戻しを `$watch` / `$scan` が受けて書く循環(要素が `x` へ書き、`$watch` が `x` から一覧の読むキーへ書く)で、\n * リスナーの書き込みだけが載った次のバッチが深さ 0 に戻り、上限に掛からずに回り続けていた(#353)\n * 適用が書かなかったバッチの次は深さ 0 なので、一度で収まる書き戻し(行の初期同期など)は伸びない。\n */\n/** 適用中のバッチの深さ + 1。drain 終了リスナーの最中はバッチの深さ、drain の外なら -1 */\nlet applyingDepth = -1;\n/** 次に drain されるバッチの深さ */\nlet pendingDepth = 0;\n/** 次のバッチに drain の外からの書き込みがある(深さ 0 から数え直す) */\nlet pendingExternal = false;\n\n/** 機能の install が呼ぶ(冪等 — 同じ listener は 1 回だけ) */\nexport function registerEnqueueListener(listener: EnqueueListener): void {\n if (!enqueueListeners.includes(listener)) {\n enqueueListeners.push(listener);\n }\n}\n\n/**\n * drain 終了リスナーを登録する。\n *\n * `priority` の昇順に呼ばれる(同値は登録順)。機構間の実行順序\n * (`$scan` → `$watch` → `$streams` restart。前の 2 つは同じ watch リスナーの中の順序で、\n * `$scan` は畳んで書いてから `$watch` を発火する —\n * docs/state-watch-hook-design.md §3-2 層 1・docs/state-scan-design.md D11)は\n * この優先度で固定する — import 順に順序を持たせると、無関係な import 整理で\n * 静かに壊れるため。定数は define.ts の `*_LISTENER_PRIORITY` を使うこと。\n */\nexport function registerUpdateBatchListener(listener: UpdateBatchListener, priority = 0): void {\n // 挿入ソート: 同値優先度の中では登録順を保つ(find は最初の「より大きい」要素を指す)\n const index = updateBatchListeners.findIndex((registered) => registered.priority > priority);\n const entry = { listener, priority };\n if (index === -1) {\n updateBatchListeners.push(entry);\n } else {\n updateBatchListeners.splice(index, 0, entry);\n }\n}\n\n/**\n * drain 終了リスナーを解除する(テスト間の分離用)。\n */\nexport function unregisterUpdateBatchListener(listener: UpdateBatchListener): void {\n const index = updateBatchListeners.findIndex((registered) => registered.listener === listener);\n if (index !== -1) {\n updateBatchListeners.splice(index, 1);\n }\n}\n\n/**\n * 全リスナーに drain のバッチを優先度順で通知する。\n * リスナーの throw は握りつぶさない(内部バグの隠蔽防止)。\n * stream / watch 側リスナーが entry ごとに自前で try/catch する契約(設計書 §3-2)。\n */\nfunction notifyUpdateBatchListeners(batch: ReadonlySet<IAbsoluteStateAddress>): void {\n // 反復中の register / unregister(ハンドラ内の切断・再 set)に耐えるためコピーする\n for (const registered of updateBatchListeners.slice()) {\n registered.listener(batch);\n }\n}\n\n/**\n * 遷移越しの適用が失敗したときの報告。\n *\n * 遷移の中では例外を同期的に呼び出し元へ投げ返せない。今日の drain は\n * queueMicrotask の中で throw する = uncaught として観測されるので、それと同じ\n * 「loud に出す」挙動へ揃える。握り潰すと `$updatedCallback` の throw が黙って\n * 消える(README の 3 層表が定める伝播の契約が破れる)。\n */\nexport function reportDeferredApplyFailure(error: unknown): void {\n queueMicrotask(() => { throw error; });\n}\n\n/** queue に積まれる update record(address + 書き込み時点の因果 context) */\ninterface IQueuedUpdateRecord {\n readonly absoluteAddress: IAbsoluteStateAddress;\n readonly context: IPropagationContext | null;\n}\n\nclass Updater {\n private _queueUpdateRecords: IQueuedUpdateRecord[] = [];\n /**\n * 描画だけをやり直すアドレス(`enqueueRenderOnlyAddress`)。書き込みの record とは別に持つ —\n * drain 終了リスナーへ渡すバッチにも、`hasQueuedPath`(`on` scan の保留 reset の判定)にも混ぜない。\n */\n private _queueRenderOnlyAddresses: IAbsoluteStateAddress[] = [];\n constructor() {\n }\n\n enqueueAbsoluteAddress(\n absoluteAddress: IAbsoluteStateAddress,\n context: IPropagationContext | null = null,\n ): void {\n // 書き込みの時点を見る機能(`$watch` の連鎖のマーク・`on` scan の `resetOn` の保留)。\n // install されていなければ配列長 0 の判定 1 回\n for (let i = 0; i < enqueueListeners.length; i++) {\n enqueueListeners[i](absoluteAddress);\n }\n // 描画連鎖の印(上の applyingDepth の説明)\n if (applyingDepth > pendingDepth) {\n pendingDepth = applyingDepth;\n }\n if (applyingDepth < 0) {\n pendingExternal = true;\n }\n const requireStartProcess = this._isQueueEmpty();\n this._queueUpdateRecords.push({ absoluteAddress, context });\n if (requireStartProcess) {\n this._scheduleDrain();\n }\n }\n\n /**\n * 描画だけをやり直させる(#4)。値を書いたわけではないので、書き込みの着地としては扱わない —\n * binding の適用には載せるが、drain 終了リスナー(`$scan` / `$watch` / `$streams` restart)へ渡す\n * バッチに入れず、`$watch` の連鎖や `on` scan の reset の印も付けない。同じバッチで同じアドレスが\n * 書き込みとしても積まれていれば、そちらが着地になる。\n * 呼び手は要素書き込みの入れ替えの完了(proxy/methods/setByAddress.ts の notifySwappedList)。\n */\n enqueueRenderOnlyAddress(absoluteAddress: IAbsoluteStateAddress): void {\n const requireStartProcess = this._isQueueEmpty();\n this._queueRenderOnlyAddresses.push(absoluteAddress);\n if (requireStartProcess) {\n this._scheduleDrain();\n }\n }\n\n private _isQueueEmpty(): boolean {\n return this._queueUpdateRecords.length === 0 && this._queueRenderOnlyAddresses.length === 0;\n }\n\n private _scheduleDrain(): void {\n // このバッチのあいだ、依存ウォークと読みが観測したリスト値は保留にする。\n // 確定は drain の finally(list/stateListBaseline.ts の頭のコメント)。\n beginStateListBaselineBatch();\n queueMicrotask(() => {\n const updateRecords = this._queueUpdateRecords;\n const renderOnlyAddresses = this._queueRenderOnlyAddresses;\n this._queueUpdateRecords = [];\n this._queueRenderOnlyAddresses = [];\n advanceUpdateBatch();\n this._applyChange(updateRecords, renderOnlyAddresses);\n });\n }\n\n /**\n * まだ drain されていない書き込み(次のバッチ)に、この state のこのパスがあるか。\n * drain の最中のキューは次のバッチの分だけになっている(_applyChange の前に差し替える)。\n * `on` scan の保留 reset を、発火しない drain で捨ててよいかの判定に使う(scan/eventReset.ts)。\n */\n hasQueuedPath(stateElement: IStateElement, path: string): boolean {\n return this._queueUpdateRecords.some((record) =>\n record.absoluteAddress.absolutePathInfo.stateElement === stateElement\n && record.absoluteAddress.absolutePathInfo.pathInfo.path === path);\n }\n\n // テスト用に公開\n testApplyChange(\n absoluteAddresses: IAbsoluteStateAddress[],\n contexts?: readonly (IPropagationContext | null)[],\n ): void {\n this._applyChange(absoluteAddresses.map((absoluteAddress, index) => ({\n absoluteAddress,\n context: contexts?.[index] ?? null,\n })));\n }\n\n private _applyChange(\n updateRecords: IQueuedUpdateRecord[],\n renderOnlyAddresses: readonly IAbsoluteStateAddress[] = [],\n ): void {\n // Note: AbsoluteStateAddress はキャッシュされているため、\n // 同一の (stateElement, address) は同じインスタンスとなり、\n // Map / Set による重複排除が正しく機能する。\n // coalescing は last-write-wins: 同じ address は最後の update の\n // (値は state 側が既に保持) context をそのまま採用する(設計書 §4.1)。\n // visitedEdges の合成や synthetic transaction への置換は行わない。\n //\n // このメソッドの反復は for...of を使わない(添字ループと Map#forEach)。drain は 1 バッチに 1 回しか\n // 呼ばれないので最適化段に上がらず、for...of は反復ごとに結果オブジェクト(Map なら [key, value] の\n // 配列も)を割り当てる。cold の 1,000 行生成では行ごとに数件の依存アドレスが積まれ、その分が\n // 生成の割り当ての 1 割近くを占めていた(設計 R5)。\n //\n // このバッチの描画連鎖の深さを消費する(キューはもう次のバッチの分なので、ここから先の印は次のバッチのもの)\n let depth = pendingExternal ? 0 : pendingDepth;\n pendingDepth = 0;\n pendingExternal = false;\n const contextByAbsoluteAddress = new Map<IAbsoluteStateAddress, IPropagationContext | null>();\n // drain 終了リスナーへ渡すのは書き込みの着地だけ。描画だけのアドレスは、この後で適用の対象に足す\n // (同じアドレスの書き込みがあれば、その context のまま着地として残る)。Map の鍵から作り直さず\n // ここで積む(鍵の iterator は反復ごとに割り当てる。順序は同じ = 最初に現れた順)\n const landedAddresses = new Set<IAbsoluteStateAddress>();\n for (let i = 0; i < updateRecords.length; i++) {\n const record = updateRecords[i];\n const previous = contextByAbsoluteAddress.get(record.absoluteAddress);\n if (\n devtoolsSink !== null\n && typeof previous !== \"undefined\" && previous !== null\n && record.context !== null\n && previous.transactionId !== record.context.transactionId\n ) {\n devtoolsSink({\n type: \"propagation:coalesced\",\n absoluteAddress: record.absoluteAddress,\n droppedTransactionId: previous.transactionId,\n winnerTransactionId: record.context.transactionId,\n });\n }\n contextByAbsoluteAddress.set(record.absoluteAddress, record.context);\n landedAddresses.add(record.absoluteAddress);\n }\n for (let i = 0; i < renderOnlyAddresses.length; i++) {\n const absoluteAddress = renderOnlyAddresses[i];\n if (!contextByAbsoluteAddress.has(absoluteAddress)) {\n contextByAbsoluteAddress.set(absoluteAddress, null);\n }\n }\n const processBindings: IBindingInfo[] = [];\n const propagationContextByBinding = new Map<IBindingInfo, IPropagationContext | null>();\n contextByAbsoluteAddress.forEach((context, absoluteAddress) => {\n if (context !== null && context.hop >= MAX_PROPAGATION_HOPS) {\n // hop 上限超過: この transaction の未処理 record だけを quarantine する。\n // 既に適用した値は戻さず、updater から例外は投げない(設計書 §4 規則 6)。\n console.error(`[@wcstack/state] propagation hop limit exceeded; update record quarantined.`, {\n path: absoluteAddress.absolutePathInfo.pathInfo.path,\n transactionId: context.transactionId,\n hop: context.hop,\n maxHops: MAX_PROPAGATION_HOPS,\n });\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"propagation:hop-limit\",\n absoluteAddress,\n transactionId: context.transactionId,\n hop: context.hop,\n });\n }\n return;\n }\n // peek: バインディングの無いアドレス(リスト置換で enqueue される中間\n // アドレス等)に空エントリを生成・蓄積しない。エントリは単一 binding\n // (通常ケース)か Set(同一アドレスに 2 本以上)のどちらか。\n // 従来台帳 → パターン台帳(リスト行)の順で引く。\n const entry = peekBindingsForAddress(absoluteAddress);\n if (entry === undefined) {\n return;\n }\n if (entry instanceof Set) {\n for(const binding of entry) {\n if (binding.replaceNode.isConnected === false) {\n // 切断されているバインディングは無視\n continue;\n }\n processBindings.push(binding);\n if (context !== null) {\n propagationContextByBinding.set(binding, context);\n }\n }\n } else if (entry.replaceNode.isConnected !== false) {\n processBindings.push(entry);\n if (context !== null) {\n propagationContextByBinding.set(entry, context);\n }\n }\n });\n // drain 終了フック: binding 適用後に dedup 済みバッチを通知する(設計書 §3-2)。\n // testApplyChange も同じ _applyChange を通るため、テストから同期に駆動できる。\n // quarantine された address も state 値は適用済みのため通知対象に含める。\n //\n // try/finally なのは、適用側が throw しても `$watch` / `$streams` restart を\n // 落とさないため。binding 1 本の失敗は applyChangeFromBindings が隔離するので\n // ここへ来るのは $updatedCallback の throw(契約どおり loud に伝播させる)等に\n // 限られるが、そのとき drain フックまで道連れにすると「機構間の順序は固定」\n // (README の 3 層表)が黙って破れる。例外は握らない = 伝播は維持する。\n try {\n const applyBindings = (): void => {\n // 遷移越しに後で走っても、このバッチの深さで印を付ける(閉包で持つ)。throw しても必ず下ろす —\n // 下ろし忘れると、以後の無関係な書き込みが全部この連鎖の続きに数えられる\n applyingDepth = depth + 1;\n try {\n // context が無い場合は従来どおり 1 引数で呼ぶ(呼び出し契約の互換維持)\n if (propagationContextByBinding.size > 0) {\n applyChangeFromBindings(processBindings, propagationContextByBinding);\n } else {\n applyChangeFromBindings(processBindings);\n }\n } finally {\n applyingDepth = -1;\n }\n };\n // View transition 参加点(docs/view-transition-design.md §7.2)。arbiter が\n // 居なければ runTransition はその場で applyBindings を呼び、undefined を返す\n // = 従来と完全に同じ同期適用。SSR では遷移そのものを持たない(G5)。\n //\n // 適用する binding が 0 本のバッチは arbiter へ渡さない。書き込みはバインドの\n // 有無に関わらず enqueue される(setByAddress)ため、headless なパス\n // (`$watch` 専用・`$streams` の内部状態・リスト置換の中間アドレス)への\n // 書き込みだけでもここへ到達する。それでページ全体をスナップショットするのは\n // 無駄なだけでなく、既定の mode=\"latest\" では「アニメーションすべき DOM 変更が\n // 無い遷移」が実行中の本物の遷移をスキップしてしまう(ルート遷移が毎回途中で\n // 切れる/active が空撃ちで振動する)。\n if (depth > MAX_RENDER_CHAIN_DEPTH && processBindings.length > 0) {\n // 描画起点の連鎖の打ち切り(#338): このバッチの binding を適用しない = 適用が書かないので連鎖が\n // 止まる。値は巻き戻さず、drain 終了リスナーには通常どおり通知する(hop 上限の quarantine と同じ\n // 姿勢)。適用するものが無いバッチは連鎖がそこで自然に終わるので報告しない — hop 上限が全部を\n // quarantine したバッチもここへは来ない(報告は 1 つの機構から 1 回)。\n // `$watch` / `$scan` を挟む循環(#353)は、適用を止めてもリスナーの書き込みが深さを引き継いで次のバッチを\n // 作る。報告は連鎖が初めて越えたバッチ(深さは 1 バッチに 1 段までしか伸びないので上限 + 1)だけにし、\n // 引き継ぐ深さを 1 つ進めて、続くバッチは報告せずに適用しない\n if (depth++ === MAX_RENDER_CHAIN_DEPTH + 1) {\n // パスで畳む(行ごとのアドレスが同じパスで並ぶと、循環しているパスが読み取りにくい)\n const paths = [...new Set(Array.from(landedAddresses, (absAddress) => absAddress.absolutePathInfo.pathInfo.path))];\n console.error(\n `[@wcstack/state] render chain depth limit exceeded; bindings for this batch were not applied.`,\n { maxDepth: MAX_RENDER_CHAIN_DEPTH, paths },\n );\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:render-chain-limit\", maxDepth: MAX_RENDER_CHAIN_DEPTH, paths });\n }\n }\n } else if (inSsr() || processBindings.length === 0) {\n applyBindings();\n } else {\n const pending = runTransition(\"state\", applyBindings);\n if (pending !== undefined) {\n pending.catch(reportDeferredApplyFailure);\n }\n }\n } finally {\n // バッチ中に溜めたリスト差分基準を確定する。notifyUpdateBatchListeners より先に\n // 置くのは、リスナー($watch / $streams restart)の中で走る書き込みが\n // 「このバッチの結果」を基準として見るべきだから。\n endStateListBaselineBatch();\n // リスナーの書き込みは描画連鎖を伸ばしも数え直させもせず、このバッチの深さを引き継ぐ(applyingDepth の\n // 説明)。リスナーは throw しない契約(内部バグだけ)なので finally で包まない — 残っても次の drain が戻す\n applyingDepth = depth;\n notifyUpdateBatchListeners(landedAddresses);\n applyingDepth = -1;\n }\n }\n\n}\n\n// コンストラクタは空でフィールド初期化だけ(純粋な割り当て)。バンドラが未使用時に落とせるよう\n// 明示する: ヘルパーだけの import(defineState / 型 / version)にランタイムを残さない\nconst updater = /*#__PURE__*/ new Updater();\n\nexport function getUpdater(): Updater {\n return updater;\n}\n\n// テスト用にprivateメソッドを公開\nexport const __private__ = {\n Updater,\n reportDeferredApplyFailure,\n};\n","/**\n * keyedDependency.ts — 鍵付き購読(`$eq(path, key)` / `$eqPath(path, keyPath)` / `$eqIndex(path, level)`)。\n *\n * 「`path` の値が鍵に等しいか」だけを知りたい getter は、`path` のパターン辺ではなく\n * その鍵の下に自分の行アドレスを登録する。`path` への書き込みは、旧値と新値の鍵に\n * 登録された行だけを dirty 化して enqueue する(パターン辺なら全行に展開されるところを\n * 高々 2 行に抑える。docs/state-next-major-tech-survey.md §10.1・§10.10、要件 N6 / D7)。\n *\n * - 行の購読は、差分がその行の listIndex を退役させた時点で落とす\n * (`dropKeyedSubscriptionsByListIndex`、list/createListDiff.ts が呼ぶ)。差分が行を\n * 復活させたときは、getter の再評価が購読を張り直す。\n * - `$eqIndex` は行の index を鍵にする(getter を index 依存には記録しない)。段によって 2 通り:\n * - 最内段(getter 自身の行の段)は行ごとの購読を持たず、リスト(listIndex 配列)単位の\n * 監視を 1 つ置く(`registerIndexWatcher`)。書き込みは `indexes[旧値]` と `indexes[新値]`\n * の行を、差分は配列が変わったとき(`moveIndexWatchers`)「最後の値の位置にいた行と来た行」\n * だけを enqueue する。移動行ごとの処理も退役時の解除も無い。\n * - 外側の段は行ごとに index を鍵にして購読し、差分が index を付け替えるとき\n * (syncListIndexes → `rekeyIndexSubscriptions`)に鍵も付け替える。移動した行は\n * 「`path` の最後の値が旧 index か新 index に等しい」ときだけ enqueue する。\n * どちらも 1 行削除で再評価されるのは高々 2 行。\n * - `path` の最後の値は登録時と書き込み時に控える(差分側の判定に使う)。書き込みが旧値を\n * 読めなかったとき(オブジェクトの書き込みは同値ガードを通らない)は、これを旧い鍵として使う\n * — 読めないまま新しい鍵の行だけを再評価すると、前に選ばれていた行が真のまま残る。\n * - `path` の祖先への書き込み(`$eq(\"sel.id\")` に対する `sel = {…}`)は `path` への書き込みを\n * 経ないので、祖先 → 配下の鍵付きパスの逆引きを持ち、旧い親と新しい親から鍵を辿って知らせる\n * (`keyedDescendantDependents`)。\n *\n * 不変条件: 同じ (アドレス, path) の購読は 1 つ。`keyByPathByAddress` が現在の鍵の正本で、\n * 台帳(`byPath`)とは常に一致する。退役した行のエントリは台帳・逆引きの両方から同時に消える。\n * 制約: Map の鍵比較は SameValueZero(`-0` と `+0` は同じ鍵、`NaN` 同士は同じ鍵)。\n */\nimport { IAbsoluteStateAddress, IPathInfo } from \"../address/types\";\nimport { getPathInfo } from \"../address/PathInfo\";\nimport { WILDCARD } from \"../define\";\nimport { createStateAddress } from \"../address/StateAddress\";\nimport { liftAddress } from \"../address/liftAddress\";\nimport { disownListIndexes, isRetiredListIndex } from \"../list/listIndexesByList\";\nimport { dirtyCacheEntryByAbsoluteStateAddress } from \"../cache/cacheEntryByAbsoluteStateAddress\";\nimport { IStateElement } from \"../components/types\";\nimport { IListIndex } from \"../list/types\";\nimport { getUpdater } from \"../updater/updater\";\n\ntype KeyMap = Map<unknown, Set<IAbsoluteStateAddress>>;\ninterface IElementLedger {\n readonly byPath: Map<string, KeyMap>;\n /** `path` の最後に見た値(登録時か書き込み時)。差分側の鍵付け替えが読む */\n readonly lastValue: Map<string, unknown>;\n /** 祖先の逆引きに載せ終えた path */\n readonly recorded: Set<string>;\n /**\n * getter の評価中に呼ばれたが、`path` が getter かその下にあるので鍵付きで購読できず、追跡付きの\n * 読みに落ちた path。台帳の動作には使わず、DevTools の要約(要件 D17)だけが読む\n */\n readonly tracked: Set<string>;\n}\ninterface IEntry {\n readonly stateElement: IStateElement;\n readonly path: string;\n readonly absAddress: IAbsoluteStateAddress;\n /** `$eqIndex` のとき、index を鍵にしている段の listIndex(それ以外は null) */\n readonly levelListIndex: IListIndex | null;\n}\nconst ledgerByElement = new WeakMap<IStateElement, IElementLedger>();\n// アドレス → (path → 現在の鍵)。再評価した getter が購読を新しい鍵へ移すための逆引き\nconst keyByPathByAddress = new WeakMap<IAbsoluteStateAddress, Map<string, unknown>>();\n// 行の listIndex にぶら下がる購読(退役時に落とす)\nconst entriesByListIndex = new WeakMap<IListIndex, IEntry[]>();\n// index を鍵にしている購読を、その index の段の listIndex から引く(付け替え用)\nconst indexKeyedByListIndex = new WeakMap<IListIndex, IEntry[]>();\n// 一度も登録が無ければ差分側のフックは Map 参照すら行わない\nlet anyRegistered = false;\n\n/**\n * リスト差分が enqueue した鍵付き購読者のアドレス。**依存ウォークの起点として使う分**。\n *\n * 書き込み起点の通知(`setByAddress` の `notifyKeyed`)は購読者から `walkDependency` を回して\n * 派生先まで届けるが(`walkKeyedDependents`)、差分起点の 2 経路(`moveIndexWatchers` /\n * `rekeyIndexSubscriptions`)は `createListDiff` から呼ばれ、そこには state proxy が無い\n * (ウォークはリスト展開で値を読む)。そこで**積むだけ**にして、proxy を持つ地点\n * (`walkDependency` の末尾)が引き取って回す。積む側は引き取り手を知らない。\n *\n * ツリー別に分ける理由が 2 つある。\n * - 引き取り手は自分のツリーしか辿れない(`walkDependency` は 1 ツリーの依存表と proxy で回る)。\n * 1 本の配列にすると、別ツリーのウォークが来たときに他人の分を取り出して**捨ててしまう**。\n * - 集合(Set)にしてあるので、引き取り手が来ないまま差分が続いても、溜まるのは\n * 「そのツリーの相異なる購読者アドレス」止まり(アドレスは intern 済み)。台帳が既に持っている\n * 分を超えない。\n *\n * `WeakMap` なので、ツリーが捨てられれば取り残しごと回収される。鍵付き購読を使わないページは\n * 積む側が `anyRegistered` で先に抜けるため、引き取り手の負担は `WeakMap#get` 1 回だけ。\n */\nconst pendingKeyedWalk = new WeakMap<IStateElement, Set<IAbsoluteStateAddress>>();\n\nfunction pushPendingKeyedWalk(absAddress: IAbsoluteStateAddress): void {\n const stateElement = absAddress.absolutePathInfo.stateElement;\n let pending = pendingKeyedWalk.get(stateElement);\n if (typeof pending === \"undefined\") {\n pendingKeyedWalk.set(stateElement, pending = new Set());\n }\n pending.add(absAddress);\n}\n\n/** このツリーに積まれた起点を取り出す(無ければ null)。引き取り手は proxy を持っている地点だけ */\nexport function takePendingKeyedWalk(stateElement: IStateElement): Set<IAbsoluteStateAddress> | null {\n const pending = pendingKeyedWalk.get(stateElement);\n if (typeof pending === \"undefined\") {\n return null;\n }\n pendingKeyedWalk.delete(stateElement);\n return pending;\n}\n\n/**\n * リスト単位の index 監視(`$eqIndex` の最内段)。行ごとの購読を持たず、書き込みは\n * `indexes[旧値]` と `indexes[新値]` の行を、差分は「最後の値の位置にいた行と来た行」だけを\n * enqueue する。差分がリストの listIndex 配列を作り直したら監視を新しい配列へ移す。\n */\ninterface IIndexWatcher {\n readonly stateElement: IStateElement;\n readonly path: string;\n /** 監視中のリストの listIndex 配列(差分で付け替わる) */\n indexes: IListIndex[];\n /** この監視を張った getter のパス(同じリストの複数 getter を 1 監視で扱う) */\n readonly getters: Set<IPathInfo>;\n}\nconst watchersByElement = new WeakMap<IStateElement, Map<string, Set<IIndexWatcher>>>();\nconst watchersByIndexes = new WeakMap<IListIndex[], IIndexWatcher[]>();\n/**\n * 祖先の listIndex → その配下で購読を持つ行の listIndex。\n *\n * 入れ子リストの**親行**が退役しても、子のリスト(`groups.*.rows`)には差分が来ない — 配列ごと\n * 捨てられるだけなので `dropKeyedSubscriptionsByListIndex` が子には呼ばれず、台帳の強参照\n * (`ledger.byPath` の `Set<IAbsoluteStateAddress>`)が残る。`IListIndex` は `parentListIndex`\n * (上向き)しか持たないので、登録の時点で祖先の側に自分を載せて逆引きを作る。\n *\n * 集合の中身は強参照だが、**祖先が生きている間だけ**(WeakMap)で、行が落ちるときは\n * `unlinkAncestors` で外れる。祖先自身が回収されれば集合ごと消える。\n */\nconst descendantRowsByAncestor = new WeakMap<IListIndex, Set<IListIndex>>();\n/** `$eqIndex` 最内段の監視 → それが載っているリストの親行(親の退役で監視ごと落とす) */\nconst watchersByOwnerListIndex = new WeakMap<IListIndex, Set<IIndexWatcher>>();\n// 祖先パス → その配下の鍵付きパス(祖先への書き込みを配下の鍵付き購読へ届ける)\nconst descendantsByElement = new WeakMap<IStateElement, Map<string, Set<string>>>();\nconst EMPTY: IAbsoluteStateAddress[] = [];\n\n/** `path` の祖先を逆引きに載せる(同じ path は 1 回だけ)。祖先の無いトップレベルの path は載せない */\nfunction recordAncestors(stateElement: IStateElement, path: string): void {\n const ledger = ledgerOf(stateElement);\n if (ledger.recorded.has(path)) {\n return;\n }\n ledger.recorded.add(path);\n const cumulativePaths = getPathInfo(path).cumulativePaths;\n if (cumulativePaths.length < 2) {\n return;\n }\n let byAncestor = descendantsByElement.get(stateElement);\n if (typeof byAncestor === \"undefined\") {\n descendantsByElement.set(stateElement, byAncestor = new Map());\n }\n for (let i = 0; i < cumulativePaths.length - 1; i++) {\n let descendants = byAncestor.get(cumulativePaths[i]);\n if (typeof descendants === \"undefined\") {\n byAncestor.set(cumulativePaths[i], descendants = new Set());\n }\n descendants.add(path);\n }\n}\n\nfunction ledgerOf(stateElement: IStateElement): IElementLedger {\n let ledger = ledgerByElement.get(stateElement);\n if (typeof ledger === \"undefined\") {\n ledgerByElement.set(stateElement, ledger = { byPath: new Map(), lastValue: new Map(), recorded: new Set(), tracked: new Set() });\n }\n return ledger;\n}\n\nfunction keyMapOf(ledger: IElementLedger, path: string): KeyMap {\n let keyMap = ledger.byPath.get(path);\n if (typeof keyMap === \"undefined\") {\n ledger.byPath.set(path, keyMap = new Map());\n }\n return keyMap;\n}\n\nfunction addToKey(keyMap: KeyMap, key: unknown, absAddress: IAbsoluteStateAddress): void {\n let set = keyMap.get(key);\n if (typeof set === \"undefined\") {\n keyMap.set(key, set = new Set());\n }\n set.add(absAddress);\n}\n\n/** 鍵から行を外し、空になった鍵は Map から消す(オブジェクトの鍵を行の退役後まで握らない) */\nfunction removeFromKey(keyMap: KeyMap, key: unknown, absAddress: IAbsoluteStateAddress): void {\n const set = keyMap.get(key)!;\n set.delete(absAddress);\n if (set.size === 0) {\n keyMap.delete(key);\n }\n}\n\n/** 台帳へ登録する。既に同じ (アドレス, path) が登録済みなら鍵を移すだけで、false を返す */\nfunction subscribe(ledger: IElementLedger, path: string, key: unknown, absAddress: IAbsoluteStateAddress): boolean {\n const keyMap = keyMapOf(ledger, path);\n let previous = keyByPathByAddress.get(absAddress);\n if (typeof previous === \"undefined\") {\n keyByPathByAddress.set(absAddress, previous = new Map());\n }\n if (previous.has(path)) {\n const oldKey = previous.get(path);\n if (!Object.is(oldKey, key)) {\n removeFromKey(keyMap, oldKey, absAddress);\n previous.set(path, key);\n addToKey(keyMap, key, absAddress);\n }\n return false;\n }\n previous.set(path, key);\n addToKey(keyMap, key, absAddress);\n return true;\n}\n\n/** 追加して「この listIndex の最初のエントリだったか」を返す(祖先への登録は行ごとに 1 回でよい) */\nfunction pushEntry(map: WeakMap<IListIndex, IEntry[]>, listIndex: IListIndex, entry: IEntry): boolean {\n const entries = map.get(listIndex);\n if (typeof entries === \"undefined\") {\n map.set(listIndex, [entry]);\n return true;\n }\n entries.push(entry);\n return false;\n}\n\n/**\n * 行を祖先の逆引きへ載せる / から外す。深さぶんのループで、鍵付き購読を持つ行の登録と退役でしか\n * 走らない(`$eq` 系を使わないページは 1 回も通らない)。\n *\n * 祖先は `listIndexes`(WeakRef 配列)ではなく `parentListIndex` を辿る。`parentListIndex` は\n * 強参照なので、自分が生きていれば祖先も生きている = `deref()` の空振りを考えなくてよく、\n * `listIndexes` getter の再構築(`reparent` の世代が変わると配列を作り直す)も踏まない。\n *\n * **不変条件: 購読を持つ行は、生きたまま別の親へ付け替えられない。** チェーンを記録するのは\n * 「その行の最初の購読」の 1 回だけで、外すのは行が落ちるときだけなので、途中で\n * `reparentListIndex`(`list/listIndexesByList.ts` の `getRepairTarget`。第 1 分岐は**旧親が\n * 退役していなくても** `home` へ付け替えうる)が走ると逆引きは古い親を指したまま残る。\n * 破れると 2 方向に壊れる:\n * (a) 旧親の退役が、**生きている**行の購読を落とす(選択が効かなくなる)\n * (b) 実親の退役が子を落とし損ねる(=この逆引きが塞いだリークの再発)\n * 破れていないことは `__tests__/dependency.keyedAncestorIndex.test.ts` が検査している\n * (記録した祖先が今も `parentListIndex` チェーン上に居るかの突き合わせ)。付け替えを\n * 許す必要が出たら、`reparentListIndex` から `unlinkAncestors` → `linkAncestors` を\n * 張り直す形にするのが構造的に強い。\n */\nfunction linkAncestors(listIndex: IListIndex): void {\n for (let ancestor = listIndex.parentListIndex; ancestor !== null; ancestor = ancestor.parentListIndex) {\n let rows = descendantRowsByAncestor.get(ancestor);\n if (typeof rows === \"undefined\") {\n descendantRowsByAncestor.set(ancestor, rows = new Set());\n }\n rows.add(listIndex);\n }\n}\n\nfunction unlinkAncestors(listIndex: IListIndex): void {\n for (let ancestor = listIndex.parentListIndex; ancestor !== null; ancestor = ancestor.parentListIndex) {\n const rows = descendantRowsByAncestor.get(ancestor);\n // 祖先ごと退役した場合は、`dropKeyedSubscriptionsByListIndex` が先に集合を外している\n if (typeof rows === \"undefined\") {\n continue;\n }\n rows.delete(listIndex);\n if (rows.size === 0) {\n descendantRowsByAncestor.delete(ancestor);\n }\n }\n}\n\nfunction record(ledger: IElementLedger, path: string, current: unknown, absAddress: IAbsoluteStateAddress, isNew: boolean, entry: IEntry): void {\n ledger.lastValue.set(path, current);\n if (!isNew) {\n return;\n }\n // 行の外(トップレベルの getter)からの登録は listIndex を持たず、退役で落ちることもない\n if (absAddress.listIndex !== null) {\n if (pushEntry(entriesByListIndex, absAddress.listIndex, entry)) {\n // この行の最初の購読。祖先の逆引きへ 1 回だけ載せる\n linkAncestors(absAddress.listIndex);\n }\n }\n if (entry.levelListIndex !== null) {\n pushEntry(indexKeyedByListIndex, entry.levelListIndex, entry);\n }\n}\n\n/** `$eq` / `$eqPath`: 評価中の getter のアドレスを `key` の下に登録する。`current` は今読んだ `path` の値 */\nexport function registerKeyedDependency(\n stateElement: IStateElement,\n path: string,\n key: unknown,\n absAddress: IAbsoluteStateAddress,\n current: unknown,\n): void {\n anyRegistered = true;\n const ledger = ledgerOf(stateElement);\n recordAncestors(stateElement, path);\n const isNew = subscribe(ledger, path, key, absAddress);\n record(ledger, path, current, absAddress, isNew, { stateElement, path, absAddress, levelListIndex: null });\n}\n\n/** `$eqIndex`: `levelListIndex.index` を鍵にして登録する。差分が index を変えたとき鍵も付け替える */\nexport function registerIndexKeyedDependency(\n stateElement: IStateElement,\n path: string,\n levelListIndex: IListIndex,\n absAddress: IAbsoluteStateAddress,\n current: unknown,\n): void {\n anyRegistered = true;\n const ledger = ledgerOf(stateElement);\n recordAncestors(stateElement, path);\n const isNew = subscribe(ledger, path, levelListIndex.index, absAddress);\n record(ledger, path, current, absAddress, isNew, { stateElement, path, absAddress, levelListIndex });\n}\n\n/** getter の評価中の `$eq` / `$eqPath` / `$eqIndex` が、`path` が getter 由来のため追跡付きの読みに落ちた */\nexport function recordTrackedKeyedPath(stateElement: IStateElement, path: string): void {\n ledgerOf(stateElement).tracked.add(path);\n}\n\n/** DevTools の要約(devtools/keyedSubscriptions.ts)が読む、この state の台帳。読むだけで変えない */\nexport interface IKeyedLedgerView {\n readonly byPath: ReadonlyMap<string, ReadonlyMap<unknown, ReadonlySet<IAbsoluteStateAddress>>>;\n readonly lastValue: ReadonlyMap<string, unknown>;\n readonly tracked: ReadonlySet<string>;\n /** `$eqIndex` の最内段のリスト単位の監視(path → 監視) */\n readonly watchers: ReadonlyMap<string, ReadonlySet<unknown>> | undefined;\n}\n\nexport function getKeyedLedgerView(stateElement: IStateElement): IKeyedLedgerView | null {\n const ledger = ledgerByElement.get(stateElement);\n if (typeof ledger === \"undefined\") {\n return null;\n }\n return { byPath: ledger.byPath, lastValue: ledger.lastValue, tracked: ledger.tracked, watchers: watchersByElement.get(stateElement) };\n}\n\nexport function hasKeyedDependents(stateElement: IStateElement, path: string): boolean {\n return ledgerByElement.get(stateElement)?.byPath.has(path) === true\n || watchersByElement.get(stateElement)?.has(path) === true;\n}\n\n/** `$eqIndex` の最内段: リスト(listIndex 配列)単位の監視を 1 つ登録し、getter のパスを足す */\nexport function registerIndexWatcher(\n stateElement: IStateElement,\n path: string,\n getterPathInfo: IPathInfo,\n indexes: IListIndex[],\n current: unknown,\n): void {\n anyRegistered = true;\n ledgerOf(stateElement).lastValue.set(path, current);\n recordAncestors(stateElement, path);\n let byPath = watchersByElement.get(stateElement);\n if (typeof byPath === \"undefined\") {\n watchersByElement.set(stateElement, byPath = new Map());\n }\n let watchers = byPath.get(path);\n if (typeof watchers === \"undefined\") {\n byPath.set(path, watchers = new Set());\n }\n let byList = watchersByIndexes.get(indexes);\n let watcher: IIndexWatcher | undefined;\n if (typeof byList === \"undefined\") {\n watchersByIndexes.set(indexes, byList = []);\n // 監視は配列に付くので、要素の書き込みはもうその場で書き換えない(listIndexesByList.ts)\n disownListIndexes(indexes);\n } else {\n watcher = byList.find((w) => w.stateElement === stateElement && w.path === path);\n }\n if (typeof watcher === \"undefined\") {\n watcher = { stateElement, path, indexes, getters: new Set() };\n byList.push(watcher);\n watchers.add(watcher);\n // 入れ子リストの監視は、そのリストを抱える**親行**に紐づける。親が退役すると\n // この配列には差分が来ない(配列ごと捨てられる)ので、ここで持ち主を控えておかないと\n // `watchersByElement` に死んだ監視が積み上がる。トップレベルのリスト(親が null)は\n // 孤児にならないので紐づけない\n const owner = indexes[0]?.parentListIndex ?? null;\n if (owner !== null) {\n let owned = watchersByOwnerListIndex.get(owner);\n if (typeof owned === \"undefined\") {\n watchersByOwnerListIndex.set(owner, owned = new Set());\n }\n owned.add(watcher);\n }\n }\n watcher.getters.add(getterPathInfo);\n}\n\nfunction watchedRowsAt(watcher: IIndexWatcher, key: unknown, out: IAbsoluteStateAddress[]): void {\n if (typeof key !== \"number\") {\n return;\n }\n const listIndex = watcher.indexes[key];\n if (typeof listIndex === \"undefined\") {\n return;\n }\n for (const getterPathInfo of watcher.getters) {\n out.push(liftAddress(watcher.stateElement, createStateAddress(getterPathInfo, listIndex)));\n }\n}\n\n/**\n * 差分がリストの listIndex 配列を `oldIndexes` → `newIndexes` に付け替えた: 監視を新しい配列へ移し、\n * `path` の最後の値の位置にいた行と来た行(違うときだけ)を dirty 化して enqueue する。\n * 同じ差分の 2 回目の呼び出し(キャッシュ命中)は旧配列に監視が無いので何もしない。\n */\nexport function moveIndexWatchers(oldIndexes: IListIndex[], newIndexes: IListIndex[]): void {\n if (!anyRegistered || oldIndexes === newIndexes) {\n return;\n }\n const watchers = watchersByIndexes.get(oldIndexes);\n if (typeof watchers === \"undefined\") {\n return;\n }\n watchersByIndexes.delete(oldIndexes);\n const existing = watchersByIndexes.get(newIndexes);\n watchersByIndexes.set(newIndexes, typeof existing === \"undefined\" ? watchers : existing.concat(watchers));\n disownListIndexes(newIndexes);\n for (const watcher of watchers) {\n watcher.indexes = newIndexes;\n const last = ledgerOf(watcher.stateElement).lastValue.get(watcher.path);\n if (typeof last !== \"number\") {\n continue;\n }\n const before = oldIndexes[last];\n const after = newIndexes[last];\n if (before === after) {\n continue;\n }\n for (const listIndex of [before, after]) {\n if (typeof listIndex === \"undefined\" || isRetiredListIndex(listIndex)) {\n continue;\n }\n for (const getterPathInfo of watcher.getters) {\n const absAddress = liftAddress(watcher.stateElement, createStateAddress(getterPathInfo, listIndex));\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n getUpdater().enqueueAbsoluteAddress(absAddress, null);\n pushPendingKeyedWalk(absAddress);\n }\n }\n }\n}\n\nfunction collect(set: Set<IAbsoluteStateAddress> | undefined, out: IAbsoluteStateAddress[]): void {\n if (typeof set === \"undefined\") {\n return;\n }\n for (const address of set) {\n out.push(address);\n }\n}\n\n/**\n * `path` への書き込み: 旧値(同値ガードが読めたとき)と新値の鍵に登録された行アドレス。\n * 控えていた最後の値が旧値と違う(旧値を読めなかった)ときは、その鍵の行も加える。\n * 新値を `path` の最後の値として控える。呼び出し側は hasKeyedDependents で門を通す。\n */\nexport function keyedDependents(\n stateElement: IStateElement,\n path: string,\n hasOldKey: boolean,\n oldKey: unknown,\n newKey: unknown,\n): IAbsoluteStateAddress[] {\n const ledger = ledgerByElement.get(stateElement);\n const keyMap = ledger?.byPath.get(path);\n const watchers = watchersByElement.get(stateElement)?.get(path);\n if (typeof ledger === \"undefined\" || (typeof keyMap === \"undefined\" && typeof watchers === \"undefined\")) {\n return EMPTY;\n }\n const hasLast = ledger.lastValue.has(path);\n const last = ledger.lastValue.get(path);\n ledger.lastValue.set(path, newKey);\n const out: IAbsoluteStateAddress[] = [];\n const newDiffers = !hasOldKey || !Object.is(oldKey, newKey);\n // 行が最後に見た値。旧値を読めなかったときに真のまま残る行はここにいる\n const lastDiffers = hasLast && (!hasOldKey || !Object.is(last, oldKey)) && !Object.is(last, newKey);\n if (typeof keyMap !== \"undefined\") {\n if (hasOldKey) {\n collect(keyMap.get(oldKey), out);\n }\n if (lastDiffers) {\n collect(keyMap.get(last), out);\n }\n if (newDiffers) {\n collect(keyMap.get(newKey), out);\n }\n }\n if (typeof watchers !== \"undefined\") {\n for (const watcher of watchers) {\n if (hasOldKey) {\n watchedRowsAt(watcher, oldKey, out);\n }\n if (lastDiffers) {\n watchedRowsAt(watcher, last, out);\n }\n if (newDiffers) {\n watchedRowsAt(watcher, newKey, out);\n }\n }\n }\n return out;\n}\n\nexport function hasKeyedDescendants(stateElement: IStateElement, path: string): boolean {\n return descendantsByElement.get(stateElement)?.has(path) === true;\n}\n\n/** `value` から `segments` を辿った値(途中がオブジェクトでなければ undefined) */\nfunction valueAt(value: unknown, segments: readonly string[]): unknown {\n let current = value;\n for (const segment of segments) {\n if (typeof current !== \"object\" || current === null) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[segment];\n }\n return current;\n}\n\n/**\n * `path`(鍵付きパスの祖先)への書き込み: 配下の鍵付きパスごとに、旧い親と新しい親から鍵を辿り、\n * その鍵の行を返す(`keyedDependents` と同じ扱い)。残りのパスにワイルドカードがあると行ごとの鍵が\n * 辿れないので、そのパスに購読している行をすべて返す。呼び出し側は hasKeyedDescendants で門を通す。\n */\nexport function keyedDescendantDependents(\n stateElement: IStateElement,\n path: string,\n oldValue: unknown,\n newValue: unknown,\n hasOldValue: boolean = true,\n): IAbsoluteStateAddress[] {\n const depth = getPathInfo(path).segments.length;\n const out: IAbsoluteStateAddress[] = [];\n for (const descendant of descendantsByElement.get(stateElement)!.get(path)!) {\n const rest = getPathInfo(descendant).segments.slice(depth);\n if (rest.includes(WILDCARD)) {\n allDependents(stateElement, descendant, out);\n continue;\n }\n // `hasOldValue` が偽なのは `$postUpdate`(in-place 変異の通知 — 旧い親がどこにも無い)。\n // 旧い鍵は台帳の `lastValue` から引かせる(`keyedDependents` の lastDiffers 経路)\n const oldKey = hasOldValue ? valueAt(oldValue, rest) : undefined;\n for (const address of keyedDependents(stateElement, descendant, hasOldValue, oldKey, valueAt(newValue, rest))) {\n out.push(address);\n }\n }\n return out;\n}\n\n/** `path` に鍵付きで購読しているすべての行 */\nfunction allDependents(stateElement: IStateElement, path: string, out: IAbsoluteStateAddress[]): void {\n const keyMap = ledgerByElement.get(stateElement)!.byPath.get(path);\n if (typeof keyMap !== \"undefined\") {\n for (const set of keyMap.values()) {\n collect(set, out);\n }\n }\n const watchers = watchersByElement.get(stateElement)?.get(path);\n if (typeof watchers !== \"undefined\") {\n for (const watcher of watchers) {\n for (let index = 0; index < watcher.indexes.length; index++) {\n watchedRowsAt(watcher, index, out);\n }\n }\n }\n}\n\nfunction removeIndexEntry(entry: IEntry): void {\n const entries = indexKeyedByListIndex.get(entry.levelListIndex!)!;\n const at = entries.indexOf(entry);\n entries.splice(at, 1);\n}\n\n/** 1 行ぶんの購読を台帳と逆引きから落とす */\nfunction dropRowSubscriptions(listIndex: IListIndex): void {\n const entries = entriesByListIndex.get(listIndex);\n if (typeof entries === \"undefined\") {\n return;\n }\n entriesByListIndex.delete(listIndex);\n // 生きている親の下で行が出入りする形(単層リストの削除)でも、祖先の集合に死んだ行を\n // 残さない\n unlinkAncestors(listIndex);\n for (const entry of entries) {\n const { stateElement, path, absAddress } = entry;\n const keys = keyByPathByAddress.get(absAddress)!;\n const key = keys.get(path);\n keys.delete(path);\n removeFromKey(ledgerByElement.get(stateElement)!.byPath.get(path)!, key, absAddress);\n if (entry.levelListIndex !== null) {\n removeIndexEntry(entry);\n }\n }\n}\n\n/** `listIndex` が親として抱えていたリストの `$eqIndex` 監視を落とす */\nfunction dropWatchersOwnedBy(listIndex: IListIndex): void {\n const owned = watchersByOwnerListIndex.get(listIndex);\n if (typeof owned === \"undefined\") {\n return;\n }\n watchersByOwnerListIndex.delete(listIndex);\n for (const watcher of owned) {\n // 台帳の不変条件で必ず引ける: 監視を入れるのは `registerIndexWatcher` だけで両方へ同時に入れ、\n // 抜くのはここと `moveIndexWatchers`(`watcher.indexes` と `watchersByIndexes` を同時に\n // 付け替える)だけ。`dropRowSubscriptions` 側と同じく `!` で不変条件を宣言する\n const byPath = watchersByElement.get(watcher.stateElement)!;\n const watchers = byPath.get(watcher.path)!;\n watchers.delete(watcher);\n if (watchers.size === 0) {\n byPath.delete(watcher.path);\n }\n const byList = watchersByIndexes.get(watcher.indexes)!;\n byList.splice(byList.indexOf(watcher), 1);\n if (byList.length === 0) {\n watchersByIndexes.delete(watcher.indexes);\n }\n }\n}\n\n/**\n * 差分が `listIndex` を退役させた: その行にぶら下がる購読を台帳と逆引きから落とす\n * (復活した行は再評価で張り直す)。\n *\n * **入れ子リストの子孫も一緒に落とす。** 親が退役しても子のリストには差分が来ない\n * (配列ごと捨てられる)ので、ここで辿らないと子行の購読が台帳に残り続ける —\n * 描画は正しい(updater が dead アドレスを弾く)が、強参照のリークであり、D17 の\n * pull API が「4 行のページで rows 20」という嘘を返す。\n * 逆引きは**全段の祖先**に載せてあるので、再帰せずここで一度に落とせる。\n */\nexport function dropKeyedSubscriptionsByListIndex(listIndex: IListIndex): void {\n if (!anyRegistered) {\n return;\n }\n dropRowSubscriptions(listIndex);\n dropWatchersOwnedBy(listIndex);\n const descendants = descendantRowsByAncestor.get(listIndex);\n if (typeof descendants === \"undefined\") {\n return;\n }\n // `unlinkAncestors` が回している間に同じ集合を触るので、先に切り離す\n descendantRowsByAncestor.delete(listIndex);\n for (const descendant of descendants) {\n dropRowSubscriptions(descendant);\n dropWatchersOwnedBy(descendant);\n descendantRowsByAncestor.delete(descendant);\n }\n}\n\n/**\n * 差分が `listIndex` の index を `oldIndex` → `newIndex` に変えた: その段を鍵にする `$eqIndex` の購読を\n * 新しい鍵へ移し、`path` の最後の値が旧 index か新 index に等しい行だけを dirty 化して enqueue する\n * (それ以外の移動行では `$eqIndex` の答えは変わらない)。syncListIndexes から、drain が差分を\n * 適用する前に呼ばれる。\n */\nexport function rekeyIndexSubscriptions(listIndex: IListIndex, oldIndex: number, newIndex: number): void {\n if (!anyRegistered) {\n return;\n }\n const entries = indexKeyedByListIndex.get(listIndex);\n if (typeof entries === \"undefined\") {\n return;\n }\n for (const { stateElement, path, absAddress } of entries) {\n const ledger = ledgerByElement.get(stateElement)!;\n const keyMap = ledger.byPath.get(path)!;\n removeFromKey(keyMap, oldIndex, absAddress);\n addToKey(keyMap, newIndex, absAddress);\n keyByPathByAddress.get(absAddress)!.set(path, newIndex);\n const last = ledger.lastValue.get(path);\n if (Object.is(last, oldIndex) || Object.is(last, newIndex)) {\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n getUpdater().enqueueAbsoluteAddress(absAddress, null);\n pushPendingKeyedWalk(absAddress);\n }\n }\n}\n\n/** テスト用: この state で `path` の下に購読されている行アドレスの数 */\nexport function countKeyedSubscriptions(stateElement: IStateElement, path: string): number {\n const keyMap = ledgerByElement.get(stateElement)?.byPath.get(path);\n if (typeof keyMap === \"undefined\") {\n return 0;\n }\n let n = 0;\n for (const set of keyMap.values()) {\n n += set.size;\n }\n return n;\n}\n","import \"../polyfills\";\nimport { createListIndex, rehomeListIndex, setListIndexValue } from \"./createListIndex\";\nimport { disownListIndexes, isHeldElsewhere, markListLent, resolveListIndexesByList, retireListIndexes, reviveListIndexes, setListIndexesByList } from \"./listIndexesByList\";\nimport { IListDiff, IListIndex } from \"./types\";\nimport { dropKeyedSubscriptionsByListIndex, moveIndexWatchers, rekeyIndexSubscriptions } from \"../dependency/keyedDependency\";\nimport { updateBatch } from \"../updater/updateBatch\";\n\nconst listDiffByOldListByNewList = new WeakMap<readonly unknown[], WeakMap<readonly unknown[], IListDiff>>();\n\nconst EMPTY_LIST = Object.freeze([]);\nconst EMPTY_SET = new Set<IListIndex>();\n/** 行はそのままで要素が替わった行(syncListIndexes・#359)。新しい配列ごとに、拾ったバッチの番号と一緒に持つ */\nconst valueChangesByList = new WeakMap<readonly unknown[], [number, IListIndex[]]>();\n\n/**\n * 新しい配列 → まだ state に居る前の配列(#362)。配列をそのまま返していた getter が写しを返すようになった\n * (TodoMVC の絞り込み all → done)ときに、getter の評価が控える(proxy/methods/getByAddress.ts)。\n * 差分は前の配列の行を新しい配列へ貸さない — 貸すと行の添字が写しの位置へ振り直され、前の配列(`todos`)の\n * 数値添字の読み書きが別の要素に着地した。前の配列は生きているので、その行を退役させもしない。\n * 前の配列は弱く持つ — 強く持つと、写しを書き直すたびに写しの鎖(とそれぞれの行)が残った(同じ外側の行の 2 つのキーに\n * 写しを書き直す 300 回で happy-dom のヒープが 58 MB → 594 MB)。state から消えた前の配列は、もう生きていない\n */\nconst livePreviousLists = new WeakMap<object, WeakRef<object>>();\n\nexport function keepPreviousList(list: object, previous: unknown): void {\n livePreviousLists.set(list, new WeakRef(Object(previous)));\n}\n\nfunction previousOf(list: object): unknown {\n return livePreviousLists.get(list)?.deref();\n}\n\nfunction getListDiff(rawOldList: readonly unknown[], rawNewList: readonly unknown[]): IListDiff | null {\n const oldList = (Array.isArray(rawOldList) && rawOldList.length > 0) ? rawOldList : EMPTY_LIST;\n const newList = (Array.isArray(rawNewList) && rawNewList.length > 0) ? rawNewList : EMPTY_LIST;\n let diffByNewList = listDiffByOldListByNewList.get(oldList);\n if (!diffByNewList) {\n return null;\n }\n return diffByNewList.get(newList) || null;\n}\n\nfunction setListDiff(oldList: readonly unknown[], newList: readonly unknown[], diff: IListDiff): void {\n let diffByNewList = listDiffByOldListByNewList.get(oldList);\n if (!diffByNewList) {\n diffByNewList = new WeakMap<readonly unknown[], IListDiff>();\n listDiffByOldListByNewList.set(oldList, diffByNewList);\n }\n diffByNewList.set(newList, diff);\n}\n/**\n * Checks if two lists are identical by comparing length and each element.\n * @param oldList - Previous list to compare\n * @param newList - New list to compare\n * @returns True if lists are identical, false otherwise\n */\nexport function isSameList(oldList: readonly unknown[], newList: readonly unknown[]): boolean {\n if (oldList.length !== newList.length) {\n return false;\n }\n\n for (let i = 0; i < oldList.length; i++) {\n if (oldList[i] !== newList[i]) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Aligns each list index's .index with its position in the new list.\n * A diff only becomes the rendered state once the updater applies it: an\n * earlier diff in the same batch (two replacements in one microtask) may have\n * moved shared indexes toward a list that never got applied, and a cache hit\n * skips recomputation entirely — so every createListDiff return re-aligns.\n * 同じ走査で、行が表している要素も憶えさせる(#256)。行を戻す普通のやり方は\n * 配列を作り直すので ListIndex も作り直される ── 「同じ行が戻ってきた」と言えるのは\n * 行オブジェクトの identity ではなく、この値だけ。\n * 憶えていた要素と違う行は、行の同一性だけを突き合わせる差分(両方の配列に台帳がある)が「変わらない」と\n * 見る行で、要素だけが替わっている(#359 — 要素の書き込みがその場で行の要素を替えた配列から、その行の元の\n * 要素を持つ前の配列へ戻した)。`valueChangeIndexes` に集め、依存ウォークに行ごと描き直させる。\n * 拾えるのは最初の呼び出しだけ(憶えた要素をここで付け直す)なので、同じバッチの間は、同じ配列への差分を\n * 取り直した呼び出しにも前の呼び出しが拾った行を渡す(`valueChangesByList`)— 同じ配列を別のパスが描く\n * (配列をそのまま返す getter の `for`)と、そのパスのリストの展開は同じ配列への差分を取り直す。\n */\nfunction syncListIndexes(diff: IListDiff, newList: readonly unknown[]): void {\n const newIndexes = diff.newIndexes;\n let changed: IListIndex[] | undefined;\n for (let i = 0; i < newIndexes.length; i++) {\n if (newIndexes[i].index !== i) {\n const oldIndex = newIndexes[i].index;\n newIndexes[i].index = i;\n // `$eqIndex` の購読は差分側で鍵を付け替える(dependency/keyedDependency.ts)\n rekeyIndexSubscriptions(newIndexes[i], oldIndex, i);\n }\n if (setListIndexValue(newIndexes[i], newList[i])) {\n (changed ??= []).push(newIndexes[i]);\n }\n }\n const kept = valueChangesByList.get(newList);\n if (kept?.[0] === updateBatch) {\n changed = changed ? kept[1].concat(changed) : kept[1];\n }\n if (changed) {\n valueChangesByList.set(newList, [updateBatch, changed]);\n }\n diff.valueChangeIndexes = changed;\n}\n\n/**\n * 行を退役させ、その行の鍵付き購読(`$eq` 系)を行と一緒に落とす。差分が捨てた行と、\n * 要素の書き込みが別の要素に差し替えた行(setByAddress の renewReplacedRow・#333)が使う。\n */\nexport function retireRows(rows: Iterable<IListIndex>): void {\n retireListIndexes(rows);\n for (const retired of rows) {\n dropKeyedSubscriptionsByListIndex(retired);\n }\n}\n\n/**\n * Creates or updates list indexes by comparing old and new lists.\n * Optimizes by reusing existing list indexes when values match.\n * @param parentListIndex - Parent list index for nested lists, or null for top-level\n * @param oldList - Previous list (will be normalized to array)\n * @param newList - New list (will be normalized to array)\n * @param oldIndexes - Array of existing list indexes to potentially reuse\n * @returns Array of list indexes for the new list\n */\nexport function createListDiff(\n parentListIndex: IListIndex | null,\n rawOldList: unknown,\n rawNewList: unknown,\n): IListDiff {\n const diff = computeListDiff(parentListIndex, rawOldList, rawNewList);\n syncListIndexes(\n diff,\n (Array.isArray(rawNewList) && rawNewList.length > 0) ? rawNewList : EMPTY_LIST,\n );\n // 捨てた行を退役、返した行を復活として記録する。台帳はこれを見て「共有」と「陳腐化」を\n // 分ける(#256)。両方を毎回の差分で付け直すので、消えない印は残らない。\n // deleteIndexSet と newIndexes は構造上交わらない。\n reviveListIndexes(diff.newIndexes);\n // 前の配列がまだ state に居る(livePreviousLists)なら、その行も `$eqIndex` の監視も前の配列のまま\n if (previousOf(rawNewList as object) !== rawOldList) {\n retireRows(diff.deleteIndexSet);\n // `$eqIndex` の最内段の監視は listIndex 配列に付く: 配列が変わったら移し、最後の値の位置の行を enqueue\n moveIndexWatchers(diff.oldIndexes, diff.newIndexes);\n }\n return diff;\n}\n\n/**\n * 前の配列の行を新しい配列へ貸した(#393 — listIndexesByList.ts の markListLent)。行集合は新しい配列を持つ親のものに\n * なるので、home もそこへ移す(#394。前の home は新しい配列を持ったことが無く、手放してもいないので、戻すと別の外側の行の\n * 配列を引いた)\n */\nfunction lendRows(oldList: readonly unknown[], rows: IListIndex[], parentListIndex: IListIndex | null): void {\n markListLent(oldList);\n if (parentListIndex !== null) {\n for (const row of rows) {\n rehomeListIndex(row, parentListIndex);\n }\n }\n}\n\nfunction computeListDiff(\n parentListIndex: IListIndex | null,\n rawOldList: unknown,\n rawNewList: unknown,\n): IListDiff {\n // Normalize inputs to arrays (handles null/undefined)\n const oldList: readonly unknown[] = (Array.isArray(rawOldList) && rawOldList.length > 0) ? rawOldList : EMPTY_LIST;\n const newList: readonly unknown[] = (Array.isArray(rawNewList) && rawNewList.length > 0) ? rawNewList : EMPTY_LIST;\n const cachedDiff = getListDiff(oldList, newList);\n // 差分を取った後で新しい配列の台帳が差し替わった(同じバッチの要素書き込みの入れ替えが揃った —\n // #335)なら、キャッシュした差分の行は古い。台帳どうしで取り直す。台帳はキャッシュが当たっても引き直す —\n // 行の親が退役した・配列を手放した外側の行のままだと、行の下の読みが別の外側の行の配列を引く(#256 / #394)\n if (cachedDiff && cachedDiff.newIndexes === resolveListIndexesByList(newList, parentListIndex)) {\n return cachedDiff;\n }\n // 台帳は 1 本の配列につき行集合 1 組(listIndexesByList.ts)。親は「行がぶら下がる親が\n // 退役していたら、この親へ付け替える」ための差し替え先として渡す(#256)。\n const oldIndexes = resolveListIndexesByList(oldList, parentListIndex) || [];\n // 新しく鋳造する行の home は鋳造した親(createListIndex の既定)。前の行集合を引き継ぐ行も、引き継いだ親を home に\n // する(lendRows)— 1 組の行集合に home は 1 つ(#256)\n let retValue: IListDiff | undefined;\n try {\n // Early return for empty list\n if (newList.length === 0) {\n return retValue = {\n oldIndexes: oldIndexes,\n newIndexes: [] as IListIndex[],\n changeIndexSet: EMPTY_SET,\n deleteIndexSet: new Set<IListIndex>(oldIndexes),\n addIndexSet: EMPTY_SET,\n };\n }\n // If old list was empty, create all new indexes\n // 前の配列がまだ state に居る(livePreviousLists)なら、その行を貸さずに新しい行を作る(#362)\n let newIndexes: IListIndex[] | null = resolveListIndexesByList(newList, parentListIndex);\n // ほかの外側の行もまだ持っている配列の行は、写しに貸さない(#393 — listIndexesByList.ts の holdersByList)。元の配列は\n // その外側の行にまだ居るので、行を退役させもしない\n if (newIndexes === null && parentListIndex !== null && isHeldElsewhere(oldList, parentListIndex)) {\n keepPreviousList(newList, oldList);\n }\n if (oldList.length === 0 || (newIndexes === null && previousOf(newList) === oldList)) {\n if (newIndexes === null) {\n newIndexes = [];\n for(let i = 0; i < newList.length; i++) {\n const newListIndex = createListIndex(parentListIndex, i);\n newIndexes.push(newListIndex);\n }\n }\n return retValue = {\n oldIndexes: oldIndexes,\n newIndexes: newIndexes,\n changeIndexSet: EMPTY_SET,\n deleteIndexSet: new Set<IListIndex>(oldIndexes),\n addIndexSet: new Set<IListIndex>(newIndexes),\n };\n }\n // If lists are identical, return existing indexes unchanged (optimization)\n // 新しい配列が別の行集合を持つなら下で行どうしを突き合わせる — 要素の書き込みは位置を新しい行にするので\n // (別の要素を書いてから元の要素へ戻す — #333)、同じ中身の配列でも行が違い、前の配列の行(退役した行を\n // 含む)を被せると、新しい配列を描いた `for` に無い行が台帳に戻る\n if (isSameList(oldList, newList) && (newIndexes ?? oldIndexes) === oldIndexes) {\n if (oldList !== newList) {\n lendRows(oldList, oldIndexes, parentListIndex);\n }\n return retValue = {\n oldIndexes: oldIndexes,\n newIndexes: oldIndexes,\n changeIndexSet: EMPTY_SET,\n deleteIndexSet: EMPTY_SET,\n addIndexSet: EMPTY_SET,\n };\n }\n if (newIndexes !== null) {\n return calcDiffIndexes(oldIndexes, newIndexes);\n }\n newIndexes = [];\n\n // Use index-based map for efficiency\n // Supports duplicate values by storing array of indexes\n const indexByValue = new Map<unknown, number[]>();\n for(let i = 0; i < oldList.length; i++) {\n const val = oldList[i];\n let indexes = indexByValue.get(val);\n if (!indexes) {\n indexes = [];\n indexByValue.set(val, indexes);\n }\n indexes.push(i);\n }\n\n // Build new indexes array by matching values with old list\n const changeIndexSet: Set<IListIndex> = new Set();\n const addIndexSet: Set<IListIndex> = new Set();\n // 前の配列の行を 1 つでも新しい配列へ貸したか(listIndexesByList.ts の markListLent・#393)\n let lent = false;\n for(let i = 0; i < newList.length; i++) {\n const newValue = newList[i];\n const existingIndexes = indexByValue.get(newValue);\n const oldIndex = existingIndexes && existingIndexes.length > 0 ? existingIndexes.shift() : undefined;\n \n if (typeof oldIndex === \"undefined\") {\n // New element\n const newListIndex = createListIndex(parentListIndex, i);\n newIndexes.push(newListIndex);\n addIndexSet.add(newListIndex);\n } else {\n // Reuse existing element\n const existingListIndex = oldIndexes[oldIndex];\n lent = true;\n // Judge position change against the old list's order (oldIndexes array\n // order), not the mutable .index — an earlier diff in the same batch\n // may have already moved .index toward a list that was never applied.\n // The .index itself is re-aligned by syncListIndexes on return.\n if (oldIndex !== i) {\n changeIndexSet.add(existingListIndex);\n }\n newIndexes.push(existingListIndex);\n }\n }\n \n if (lent) {\n lendRows(oldList, newIndexes, parentListIndex);\n }\n const deleteIndexSet: Set<IListIndex> = (new Set(oldIndexes)).difference(new Set(newIndexes));\n return retValue = {\n oldIndexes: oldIndexes,\n newIndexes: newIndexes,\n changeIndexSet: changeIndexSet,\n deleteIndexSet: deleteIndexSet,\n addIndexSet: addIndexSet,\n };\n } finally {\n if (typeof retValue !== \"undefined\") {\n setListDiff(oldList, newList, retValue);\n // 差分が両方の台帳の配列を持つので、要素の書き込みはもうその場で書き換えない(listIndexesByList.ts)\n disownListIndexes(oldIndexes);\n setListIndexesByList(newList, retValue.newIndexes);\n }\n }\n}\n\n/**\n * Diff between two lists whose listIndex ledgers both already exist.\n * Rows are joined by listIndex identity — the same key applyChangeToFor and\n * walkDependency consume the result sets with. A value-based join could mark\n * oldIndexes-side objects that are absent from newIndexes (ledgers built along\n * unconnected diff chains hold different objects for the same value); such\n * orphan markers never match the consumers' has() lookups and only pollute\n * the dirty set. Rows without shared identity are represented as add+delete.\n * 台帳に書かず・キャッシュもしない純粋な突き合わせなので、共有の記録から外れていた `for` が\n * 自分の描いた行と今の行を突き合わせるのにも使う(applyChangeToFor、#320)。\n */\nexport function calcDiffIndexes(\n oldIndexes: IListIndex[],\n newIndexes: IListIndex[],\n): IListDiff {\n const newIndexSet: Set<IListIndex> = new Set(newIndexes);\n const oldIndexSet: Set<IListIndex> = new Set(oldIndexes);\n const changeIndexSet: Set<IListIndex> = new Set();\n const addIndexSet: Set<IListIndex> = newIndexSet.difference(oldIndexSet);\n const deleteIndexSet: Set<IListIndex> = oldIndexSet.difference(newIndexSet);\n // Old positions come from the oldIndexes array order (.index may have been\n // mutated by an unapplied diff in the same batch).\n const oldPosByIndex = new Map<IListIndex, number>();\n for (let i = 0; i < oldIndexes.length; i++) {\n oldPosByIndex.set(oldIndexes[i], i);\n }\n for (let i = 0; i < newIndexes.length; i++) {\n const index = newIndexes[i];\n if (addIndexSet.has(index)) {\n continue;\n }\n if (oldPosByIndex.get(index) !== i) {\n // 位置が違うことだけを記録\n changeIndexSet.add(index);\n }\n }\n return {\n oldIndexes: oldIndexes,\n newIndexes: newIndexes,\n changeIndexSet: changeIndexSet,\n deleteIndexSet: deleteIndexSet,\n addIndexSet: addIndexSet,\n };\n}","import { IListDiff, IListIndex } from \"./types\";\n\n/**\n * Indices into `seq` whose values form a longest strictly-increasing\n * subsequence, returned in ascending order. Classic patience-sorting\n * LIS in O(n log n). `seq` values are assumed distinct (old list\n * positions are unique).\n */\nexport function longestIncreasingSubsequence(seq: number[]): number[] {\n const n = seq.length;\n // tails[k] = index into seq of the smallest tail of an increasing\n // subsequence of length k+1; prev[i] = predecessor index to rebuild the chain.\n const tails: number[] = [];\n const prev: number[] = new Array(n).fill(-1);\n for (let i = 0; i < n; i++) {\n const value = seq[i];\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (seq[tails[mid]] < value) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n if (lo > 0) {\n prev[i] = tails[lo - 1];\n }\n tails[lo] = i;\n }\n const result: number[] = [];\n let k = tails.length > 0 ? tails[tails.length - 1] : -1;\n while (k >= 0) {\n result.push(k);\n k = prev[k];\n }\n result.reverse();\n return result;\n}\n\n/**\n * Determines which reused list indexes can stay where they are when the DOM\n * is brought into the new list order.\n *\n * Returns null when the reused indexes already appear in their old relative\n * order (no inversions) — the caller's existing position guard then performs\n * no moves, so nothing extra is needed. When inversions exist, returns the\n * set of indexes forming a longest increasing subsequence of old positions:\n * leaving exactly those in place and moving every other content yields the\n * correct final order with the fewest content moves (the naive forward walk\n * otherwise cascades: a single swap of rows 2/999 in 1000 rows moves ~997\n * contents instead of 2).\n *\n * Note: IListIndex.index is already mutated to the NEW position by\n * createListDiff, so old positions must come from the oldIndexes array order.\n */\nexport function computeStableIndexSet(diff: IListDiff): ReadonlySet<IListIndex> | null {\n // No reused index changed position, or nothing was reused: relative order\n // is already correct and the walk performs no moves.\n if (diff.changeIndexSet.size === 0 || diff.addIndexSet.size === diff.newIndexes.length) {\n return null;\n }\n const oldPosByIndex = new Map<IListIndex, number>();\n for (let i = 0; i < diff.oldIndexes.length; i++) {\n oldPosByIndex.set(diff.oldIndexes[i], i);\n }\n const reused: IListIndex[] = [];\n const seq: number[] = [];\n let prevPos = -1;\n let sorted = true;\n for (const index of diff.newIndexes) {\n if (diff.addIndexSet.has(index)) {\n continue;\n }\n const pos = oldPosByIndex.get(index);\n if (pos === undefined) {\n // Invariant break (a reused index missing from oldIndexes): fall back\n // to the settle walk rather than compute a stable set from bad data.\n return null;\n }\n if (pos < prevPos) {\n sorted = false;\n }\n prevPos = pos;\n reused.push(index);\n seq.push(pos);\n }\n if (sorted) {\n return null;\n }\n const lis = longestIncreasingSubsequence(seq);\n const stable = new Set<IListIndex>();\n for (const seqIndex of lis) {\n stable.add(reused[seqIndex]);\n }\n return stable;\n}\n","import { IContent } from \"../structural/types\";\nimport type { BindingSession } from \"./BindingSession\";\n\nconst bindingSessionByContent = new WeakMap<IContent, BindingSession>();\n\nexport function getBindingSessionByContent(content: IContent): BindingSession | null {\n return bindingSessionByContent.get(content) ?? null;\n}\n\nexport function setBindingSessionByContent(content: IContent, session: BindingSession): void {\n bindingSessionByContent.set(content, session);\n}\n","import type { IContent, IRowPlan } from \"./types\";\n\n/**\n * structural/planByContent.ts — 行プランから実体化した content の逆引き(行ランタイム設計 R2)。\n *\n * プラン経路で作られた content だけがここに載る。活性化のとき、その行が「プラン行か」を\n * 1 回の WeakMap 引きで判定するためのもの(プラン初期描画の門)。\n */\nconst planByContent = new WeakMap<IContent, IRowPlan>();\n\nexport function setPlanByContent(content: IContent, plan: IRowPlan): void {\n planByContent.set(content, plan);\n}\n\nexport function getPlanByContent(content: IContent): IRowPlan | null {\n return planByContent.get(content) ?? null;\n}\n","import { applyChange, applyValueToBinding } from \"../apply/applyChange\";\nimport { IApplyContext } from \"../apply/types\";\nimport { getAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding\";\nimport { addBindingByAbsoluteStateAddress, removeBindingByAbsoluteStateAddress } from \"../binding/getBindingSetByAbsoluteStateAddress\";\nimport { getBindingsByContent } from \"../bindings/bindingsByContent\";\nimport { getBindingSessionByContent } from \"../bindings/bindingSessionByContent\";\nimport { getIndexBindingsByContent } from \"../bindings/indexBindingsByContent\";\nimport type { BindingSession } from \"../bindings/BindingSession\";\nimport { bindLoopContextToContent, unbindLoopContextToContent } from \"../bindings/bindLoopContextToContent\";\nimport { scheduleDeferredSpreads } from \"../bindings/initializeBindings\";\nimport { ILoopContext } from \"../list/types\";\nimport { getByAddressSymbol } from \"../proxy/symbols\";\nimport type { IBindingInfo } from \"../types\";\nimport { getPlanByContent } from \"./planByContent\";\nimport { IContent, IRowPlan } from \"./types\";\n\n/**\n * プラン初期描画(行ランタイム設計 R2)の下ごしらえ。\n *\n * 行の下の**素の葉**(どの接頭辞も getter でなく、tail にワイルドカードが無く、event /\n * index 束縛でもない)の slot は、行オブジェクトを proxy で 1 回読めば値が取れる。その\n * 「行のパスからの残り」をプランと行パスの組ごとに 1 回だけ作って持つ(行不変)。\n * null は「この slot はプラン初期描画に載せない」。\n */\ninterface ISlotTail {\n /** 行オブジェクトからの残りのセグメント */\n readonly tail: string[];\n /** getter 判定のための、行パスからの累積パス */\n readonly prefixes: string[];\n}\n\nconst tailsByPlan = new WeakMap<IRowPlan, Map<string, (ISlotTail | null)[]>>();\n\nfunction slotTails(plan: IRowPlan, bindings: readonly IBindingInfo[], rowPath: string): (ISlotTail | null)[] {\n let byRowPath = tailsByPlan.get(plan);\n if (typeof byRowPath === \"undefined\") {\n tailsByPlan.set(plan, byRowPath = new Map());\n }\n const cached = byRowPath.get(rowPath);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n const prefix = rowPath + \".\";\n const tails = bindings.map((binding, i) => {\n const slot = plan.slots[i];\n if (slot.isEvent || slot.isIndexBinding) {\n return null;\n }\n const path = binding.statePathInfo.path;\n if (!path.startsWith(prefix)) {\n return null;\n }\n const tail = path.slice(prefix.length).split(\".\");\n const prefixes: string[] = [];\n let accumulated = rowPath;\n for (const segment of tail) {\n if (segment === \"*\") {\n // 行より下のワイルドカード(入れ子リスト)は行オブジェクトの素の読みでは解けない\n return null;\n }\n accumulated += \".\" + segment;\n prefixes.push(accumulated);\n }\n return { tail, prefixes };\n });\n byRowPath.set(rowPath, tails);\n return tails;\n}\n\n/**\n * getter は state ごとの集合で、`_state` の再セットで作り直される。行ごとに引き直す\n * (プラン側にキャッシュすると、再セット後も古い判定を使ってしまう)。\n */\nfunction hasGetterOnPrefix(prefixes: string[], getterPaths: ReadonlySet<string>): boolean {\n for (let k = 0; k < prefixes.length; k++) {\n if (getterPaths.has(prefixes[k])) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * プラン行の初期描画。行オブジェクトを proxy で 1 回読み、素の葉の slot にはその生の値を\n * そのまま渡す(読み 7 → 4・適用 3 → 1 回/行。調査 §10.13)。getter の slot と、\n * 載せられない slot は従来どおり `applyChange` を通る。\n */\nfunction applyPlanRow(\n plan: IRowPlan,\n bindings: readonly IBindingInfo[],\n session: BindingSession,\n loopContext: ILoopContext,\n context: IApplyContext,\n): void {\n const tails = slotTails(plan, bindings, loopContext.pathInfo.path);\n const getterPaths = context.stateElement.getterPaths;\n // 素の葉読みは `getByAddress` の readMissing hook(マウントの公開 getter の dispatch —\n // webComponent/exportIndex.ts)を迂回する。公開キー `P.k` は **`getterPaths` に載らない**\n // ので `hasGetterOnPrefix` にも掛からず、素の葉として undefined に落ちていた。\n // hook を持たない state(スコープ機能を入れていないページ)は真偽値 1 個で抜ける。\n //\n // 追加コスト(Chromium 149・10,000 行 × 7 スロット × 1 段 = 70,000 回の走査、中央値 60 本):\n // 素の走査 0.10 ms → hook 無し 0.20 ms → hook 有り 0.40 ms。create-10k の実測(v3 cold 中央値\n // 302.3 ms・docs/research/state-next/a3-v251-vs-3.0.json)に対して最悪 +0.3 ms ≒ 0.1 % で、\n // 同ベンチのサンプル分散(272.9〜450.3 ms)に埋もれる。R2 の改善幅(2.5.1 比 −18.7 %)は保たれる。\n const hasReadMissing = (context.stateElement.addressHooks?.readMissing.length ?? 0) !== 0;\n let rowValue: any;\n let rowRead = false;\n for (let i = 0; i < bindings.length; i++) {\n const binding = bindings[i];\n if (!session.shouldApplyState(binding)) {\n continue;\n }\n const slotTail = tails[i];\n if (slotTail === null || hasGetterOnPrefix(slotTail.prefixes, getterPaths)) {\n applyChange(binding, context);\n continue;\n }\n if (context.appliedBindingSet.has(binding)) {\n continue;\n }\n if (!rowRead) {\n rowValue = (context.state as any)[getByAddressSymbol](loopContext);\n rowRead = true;\n }\n const tail = slotTail.tail;\n let value: any = rowValue;\n let missingKey = false;\n for (let k = 0; k < tail.length; k++) {\n if (value === null || typeof value === \"undefined\") {\n value = undefined;\n break;\n }\n // 「ツリーにそのキーが無い」= readMissing hook が答える形(getByAddress と同じ判定)。\n // この slot だけ従来経路へ倒し、hook に聞かせる\n if (hasReadMissing && !(tail[k] in Object(value))) {\n missingKey = true;\n break;\n }\n value = value[tail[k]];\n }\n if (missingKey) {\n applyChange(binding, context);\n continue;\n }\n context.appliedBindingSet.add(binding);\n applyValueToBinding(binding, context, value);\n }\n}\n\nexport function activateContent(\n content: IContent,\n loopContext: ILoopContext | null,\n context: IApplyContext,\n): void {\n bindLoopContextToContent(content, loopContext);\n const bindings = getBindingsByContent(content);\n const session = getBindingSessionByContent(content);\n if (session !== null) {\n // createContent 側の initialize で remember 済みの同一 binding 配列なので、\n // remember を再実行しない専用パスで活性化する(リスト行生成のホットパス)。\n // context.rootNode は applyChangeFromBindings が確定済みの root(fragment\n // バッファ中は setRootNodeByFragment の対応先と同一)で、binding ごとの\n // getRootNode を省略できる\n session.activate(bindings, context.rootNode);\n // プラン初期描画(設計 R2)。載せないのは 2 つ:\n // `$updatedCallback` を持つ state — 束縛ごとのアドレス集計が要る\n // `**` を持つ state — 展開形の getter が `getterPaths` に無いので素の葉と見分けられない\n if (loopContext !== null\n && context.stateElement.hasUpdatedCallback === false\n && context.stateElement.hasRecursion !== true) {\n const plan = getPlanByContent(content);\n if (plan !== null) {\n applyPlanRow(plan, bindings, session, loopContext, context);\n return;\n }\n }\n }\n for (const binding of bindings) {\n if (session === null) {\n const absoluteStateAddress = getAbsoluteStateAddressByBinding(binding);\n addBindingByAbsoluteStateAddress(absoluteStateAddress, binding);\n }\n if (session !== null && !session.shouldApplyState(binding)) {\n continue;\n }\n applyChange(binding, context);\n }\n // 未定義カスタム要素への spread(#330)は行が生きている間だけ定義を待つ。解体(session の dispose)が\n // 待ちを取り消すので、使い回す行・再表示する枝はここで予約し直す。持つのは createContent の行だけ\n //(session あり・プラン行はカスタム要素を持てない)\n if (content.spreads) scheduleDeferredSpreads(content.spreads, loopContext, session!, bindings, getIndexBindingsByContent(content));\n}\n\nexport function deactivateContent(\n content: IContent,\n): void {\n if (!content.mounted) {\n return;\n }\n const bindings = getBindingsByContent(content);\n const session = getBindingSessionByContent(content);\n for (let i = 0; i < bindings.length; i++) { // 添字ループ(消去の窓に反復子のごみを残さない)\n const binding = bindings[i];\n if (session !== null) {\n session.disposeBinding(binding);\n } else {\n const absoluteStateAddress = getAbsoluteStateAddressByBinding(binding);\n removeBindingByAbsoluteStateAddress(absoluteStateAddress, binding);\n }\n }\n unbindLoopContextToContent(content);\n}\n","\nexport function createEmptySet<T>(): Readonly<Set<T>> {\n return Object.freeze(new Set<T>());\n}\n","import { createEmptySet } from \"../createEmptySet\";\nimport { IContent } from \"./types\";\n\nconst contentSetByNode = new WeakMap<Node, Set<IContent>>();\n\nconst EMPTY_SET = /*#__PURE__*/ createEmptySet<IContent>();\n\nexport function setContentByNode(node: Node, content: IContent): void {\n const contents = contentSetByNode.get(node);\n if (contents) {\n contents.add(content);\n } else {\n contentSetByNode.set(node, new Set([content]));\n }\n}\n\nexport function getContentSetByNode(node: Node): Readonly<Set<IContent>> {\n const contents = contentSetByNode.get(node);\n if (typeof contents !== \"undefined\") {\n return contents;\n }\n return EMPTY_SET;\n}\n\nexport function deleteContentByNode(node: Node, content: IContent): void {\n const contents = contentSetByNode.get(node);\n if (contents) {\n contents.delete(content);\n if (contents.size === 0) {\n contentSetByNode.delete(node);\n }\n }\n}","import { clearAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding.js\";\nimport { clearStateAddressByBindingInfo } from \"../binding/getStateAddressByBindingInfo.js\";\nimport { getBindingsByContent, setBindingsByContent } from \"../bindings/bindingsByContent.js\";\nimport { getBindingSessionByContent, setBindingSessionByContent } from \"../bindings/bindingSessionByContent.js\";\nimport { IDeferredSpreadEntry, markNodeRegistered } from \"../bindings/collectNodesAndBindingInfos.js\";\nimport { setIndexBindingsByContent } from \"../bindings/indexBindingsByContent.js\";\nimport { initializeBindingsByFragment, initializeRowBindings } from \"../bindings/initializeBindings.js\";\nimport { resolveInitializedBinding } from \"../bindings/initializeBindingPromiseByNode.js\";\nimport { setNodesByContent } from \"../bindings/nodesByContent.js\";\nimport { markObserverSkipOnAdd, markObserverSkipOnRemove } from \"../bindings/observerSkip.js\";\nimport { config, inSsr } from \"../config.js\";\nimport { INDEX_BY_INDEX_NAME } from \"../define.js\";\nimport { raiseError } from \"../raiseError.js\";\nimport { IBindingInfo } from \"../types.js\";\nimport { getContentSetByNode, setContentByNode } from \"./contentsByNode.js\";\nimport { getFragmentInfoByUUID } from \"./fragmentInfoByUUID.js\";\nimport { resolveNodePath } from \"./resolveNodePath.js\";\nimport { compileRowPlan } from \"./rowPlan.js\";\nimport { setPlanByContent } from \"./planByContent.js\";\nimport { IContent, IFragmentInfo, IRowPlan } from \"./types.js\";\n\nconst recursiveBindingTypes = new Set(['if', 'elseif', 'else', 'for']);\n\nclass Content implements IContent {\n private _content: DocumentFragment;\n private _childNodeArray: Node[] = [];\n private _firstNode: Node | null = null;\n private _lastNode: Node | null = null;\n private _mounted: boolean = false;\n /**\n * 範囲モード。トップレベルに構造ディレクティブを持つ content でのみ true。\n * この content の実レンジは自分の childNodeArray より広い(ネストした\n * if/for が自分のアンカー直後に実ノードを挿すため)ので、移動は\n * firstNode..lastNode の DOM レンジで行う。\n */\n private _ranged: boolean = false;\n // 出力しない宣言(持つ行だけに後から付ける — 全行にフィールドを足さない)\n declare spreads?: IDeferredSpreadEntry[];\n constructor(content: DocumentFragment, ranged: boolean = false) {\n this._content = content;\n this._ranged = ranged;\n // childNodes(NodeList)と Array.from の iterator を作らずに兄弟ポインタで集める。複製した\n // ばかりの fragment ではここが childNodes に触れる最初の場所になる(resolveNodePath と同じ理由、設計 R5)\n const childNodeArray: Node[] = [];\n for (let node = content.firstChild; node !== null; node = node.nextSibling) {\n childNodeArray.push(node);\n }\n this._childNodeArray = childNodeArray;\n this._firstNode = this._childNodeArray.length > 0 ? this._childNodeArray[0] : null;\n this._lastNode = this._childNodeArray.length > 0 ? this._childNodeArray[this._childNodeArray.length - 1] : null;\n }\n\n get firstNode(): Node | null {\n return this._firstNode;\n }\n\n get lastNode(): Node | null {\n return this._lastNode;\n }\n\n get mounted(): boolean {\n return this._mounted;\n }\n\n appendTo(targetNode: Node): void {\n const childNodes = this._childNodeArray;\n for (let i = 0; i < childNodes.length; i++) {\n const node = childNodes[i];\n // framework 起点のマウントを observer に伝える。中間 fragment へ append する\n // 経路でも、後続の一括 insertBefore(fragment) の mutation record には\n // この top-level node が addedNodes として現れるため、ここでのマークが届く。\n markObserverSkipOnAdd(node);\n targetNode.appendChild(node);\n }\n this._mounted = true;\n }\n\n /**\n * 移動対象ノード列。通常は自分のトップレベルノードそのもの(同一参照を返すので\n * 追加アロケーション無し)。範囲モードでマウント中のときだけ、ネストした構造\n * ディレクティブが挿した実ノードを含む DOM レンジを収集する。\n */\n private _movableNodes(): Node[] {\n if (!this._ranged || !this._mounted) {\n return this._childNodeArray;\n }\n const first = this._firstNode;\n const last = this._lastNode;\n if (first === null || last === null || first.parentNode === null) {\n return this._childNodeArray;\n }\n // 移動でsiblingが変わるため、先に列を確定させてから動かす\n const nodes: Node[] = [];\n for (let node: Node | null = first; node !== null; node = node.nextSibling) {\n nodes.push(node);\n if (node === last) {\n return nodes;\n }\n }\n // last へ到達しない(想定外の不連続)→ 従来どおり自分のノードだけ動かす\n return this._childNodeArray;\n }\n\n mountAfter(targetNode: Node): void {\n const parentNode = targetNode.parentNode;\n if (parentNode) {\n // マウント済み content にも再突入する(if の true→true 再適用・SSR\n // ハイドレーション産 content 等)。固定の nextSibling へ一括 insertBefore\n // すると、マウント済みでは nextSibling が自分の先頭ノードを指すため\n // 先頭ノードが末尾へ回転する。anchor を進めながら位置一致ノードを\n // スキップすることで冪等にする(mutation record も発生させない)。\n let anchor: Node = targetNode;\n for(const node of this._movableNodes()) {\n if (anchor.nextSibling !== node) {\n // moveBefore も childList mutation record を出すため、マークは両分岐の前\n markObserverSkipOnAdd(node);\n // moveBefore は取り外しを伴わない移動 — 接続済み行の reorder で\n // フォーカス・iframe・アニメーション状態を保存する(docs/a11y-design.md §4-1)。\n // この 1 文は 4 つのノード状態を共有する: (a) 接続済み reorder、\n // (b) clone フラグメント由来(root 違い)、(c) プール/unmount 済み(親なし)、\n // (d) バッチフラグメント内。moveBefore は「同一ツリー・親あり」を要求し\n // (b)(c)(d) では HierarchyRequestError を投げるため、same-parent ガード\n // (同 root かつ親が非 null の同時証明 = フォーカス保存が意味を持つ (a) と\n // 正確に一致)は外せない。ガードを外す「簡略化」をしてはならない。\n const mover = parentNode as Node & {\n moveBefore?: (node: Node, child: Node | null) => void;\n };\n if (node.parentNode === parentNode && typeof mover.moveBefore === \"function\") {\n mover.moveBefore(node, anchor.nextSibling);\n } else {\n parentNode.insertBefore(node, anchor.nextSibling);\n }\n }\n anchor = node;\n }\n }\n this._mounted = true;\n }\n\n tryDestroy(): boolean {\n const session = getBindingSessionByContent(this);\n // session 無し(SSR ハイドレーション産)や、定義待ち・connect-snapshot 待ちを\n // 抱える content は teardown 省略でリークするため従来経路に倒す。\n if (session === null || !session.canWholesaleDestroy()) {\n return false;\n }\n session.destroyRow(getBindingsByContent(this));\n // 添字ループ: for...of の反復子オブジェクトを行ごとに割り当てない(消去の scavenge を窓から外す)\n const childNodes = this._childNodeArray;\n for (let i = 0; i < childNodes.length; i++) {\n const node = childNodes[i];\n // unmount と同じ理由の observer 向け削除マーク(clear の一括削除でも\n // top-level node が mutation record の root に現れる)\n // この content が自分でノードを外すときだけ印を付ける(親の一括削除は親側で件数を数える)\n if (node.parentNode !== null) {\n markObserverSkipOnRemove(node);\n node.parentNode.removeChild(node);\n }\n }\n const bindings = getBindingsByContent(this);\n for (let i = 0; i < bindings.length; i++) {\n const binding = bindings[i];\n if (recursiveBindingTypes.has(binding.bindingType)) {\n getContentSetByNode(binding.node).forEach((content) => {\n if (!content.tryDestroy()) {\n content.unmount();\n }\n });\n }\n }\n this._mounted = false;\n return true;\n }\n\n /**\n * 自分のノードを DOM に残したまま、unmount と同じ解体をする(#4)。\n *\n * 行の置き換えで `for` が同じ位置の Content を新しい行に使い回すとき、入力中の欄を DOM から\n * 外さないための経路。解体そのものは省けない — 中の構造ディレクティブ(ネストした for / if)が\n * 持つ Content を古い行のまま残すと、新しい行として活性化したときに内側の行が二重に描かれ、\n * `if` の中身は古い行のアドレスに紐づいたまま取り残される。\n */\n unmountInPlace(): void {\n {\n // 共有 session(`for` 束縛ごとに 1 つ)ではこの content の行だけを解体する(設計 R3)。\n // session ごと dispose すると同じリストの生きている行まで巻き込む\n const session = getBindingSessionByContent(this);\n if (session !== null) {\n if (session.isRowSession) session.disposeBindings(getBindingsByContent(this));\n else session.dispose();\n }\n }\n this._teardownBindings();\n }\n\n /** binding ごとの解体(ネストした構造ディレクティブの Content・アドレス台帳) */\n private _teardownBindings(): void {\n const bindings = getBindingsByContent(this);\n for (let i = 0; i < bindings.length; i++) {\n const binding = bindings[i];\n if (recursiveBindingTypes.has(binding.bindingType)) {\n getContentSetByNode(binding.node).forEach((content) => { content.unmount(); });\n }\n clearStateAddressByBindingInfo(binding);\n clearAbsoluteStateAddressByBinding(binding);\n }\n }\n\n unmount(): void {\n {\n // 共有 session(`for` 束縛ごとに 1 つ)ではこの content の行だけを解体する(設計 R3)。\n // session ごと dispose すると同じリストの生きている行まで巻き込む\n const session = getBindingSessionByContent(this);\n if (session !== null) {\n if (session.isRowSession) session.disposeBindings(getBindingsByContent(this));\n else session.dispose();\n }\n }\n for(const node of this._childNodeArray) {\n // framework 起点の削除であることを observer に伝える。clear の\n // parentNode.textContent='' 一括削除でも、この top-level node が\n // 削除サブツリーの root として mutation record に現れるため、ここで\n // マークしておけば observer の冗長走査をスキップできる。マークは\n // 同期実行中に立ち、observer は次 microtask で読むので順序は保証される。\n if (node.parentNode !== null) {\n markObserverSkipOnRemove(node);\n node.parentNode.removeChild(node);\n }\n }\n const bindings = getBindingsByContent(this);\n for (let i = 0; i < bindings.length; i++) {\n const binding = bindings[i];\n if (recursiveBindingTypes.has(binding.bindingType)) {\n getContentSetByNode(binding.node).forEach((content) => { content.unmount(); });\n }\n clearStateAddressByBindingInfo(binding);\n clearAbsoluteStateAddressByBinding(binding);\n }\n this._mounted = false;\n }\n}\n\n/**\n * トップレベルに構造ディレクティブのプレースホルダを持つか。\n *\n * これを持つ content は、ネストした if/for が「自分のアンカー直後」に実ノードを\n * 挿すため、自分の childNodeArray が実レンジより狭くなる。その状態だと\n * (1) 呼び出し側の位置追跡(applyChangeToFor の lastNode)が実ノードの手前で\n * 止まり後続行が割り込む、(2) 移動時にネスト分を置き去りにする、の 2 つが起きる。\n * 該当テンプレートにだけ終端マーカーを持たせて実レンジを閉じる。\n */\nfunction hasTopLevelStructural(fragment: DocumentFragment): boolean {\n // config は setConfig で差し替わりうるので都度組む。テンプレート単位に一度しか\n // 走らない判定なので、この生成コストが行あたりに乗ることはない。\n const structural = new RegExp(\n `^@@(?:${config.commentForPrefix}|${config.commentIfPrefix}`\n + `|${config.commentElseIfPrefix}|${config.commentElsePrefix}):`,\n );\n for (let node = fragment.firstChild; node !== null; node = node.nextSibling) {\n if (node.nodeType !== Node.COMMENT_NODE) {\n continue;\n }\n // Comment の data は常に文字列(textContent の null 分岐を持ち込まない)\n if (structural.test((node as Comment).data)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * 範囲モードの要否をテンプレート単位で一度だけ判定してキャッシュする。\n * 大多数のテンプレート(トップレベルが素の要素)は false を引くだけで、\n * 行ごとの追加コストはゼロ。\n */\nfunction resolveRanged(fragmentInfo: IFragmentInfo): boolean {\n let ranged = fragmentInfo.topLevelStructural;\n if (typeof ranged === 'undefined') {\n ranged = fragmentInfo.topLevelStructural = hasTopLevelStructural(fragmentInfo.fragment);\n }\n return ranged;\n}\n\n/**\n * 添字 `$N`(`INDEX_BY_INDEX_NAME` の位置 pos = N - 1)のビット。32 段目より奥の添字は最上位のビットに\n * まとめる(まとめた添字どうしは区別されず、多めに辿るだけ — 取りこぼしはしない)。\n */\nexport function indexBit(pos: number): number {\n return 1 << Math.min(pos, 31);\n}\n\n/** `$1` … `$depth` のビット集合(32 段以上は全部) */\nfunction indexBitsUpTo(depth: number): number {\n return 2 ** Math.min(depth, 32) - 1;\n}\n\n/** 段で絞らない(if の枝・SSR の行) */\nexport const ALL_INDEX_BITS = -1;\n\n/**\n * テンプレートの中(入れ子のテンプレートも含む)で使う添字(`$1` …)のビット集合。テンプレート単位に一度だけ\n * 求めてキャッシュする(resolveRanged と同じ門)。入れ子の構造ディレクティブの条件(`if: $1|lt(2)`)は、\n * 置き場の解析結果として外側のテンプレートの中身に居る。\n */\nfunction indexBitsOfFragment(fragmentInfo: IFragmentInfo): number {\n let bits = fragmentInfo.indexBits;\n if (typeof bits === 'undefined') {\n bits = 0;\n for (const nodeInfo of fragmentInfo.nodeInfos) {\n for (const result of nodeInfo.parseBindTextResults) {\n if (result.statePathName in INDEX_BY_INDEX_NAME) {\n bits |= indexBit(INDEX_BY_INDEX_NAME[result.statePathName]);\n }\n if (typeof result.uuid === 'string') {\n bits |= indexBitsOfFragment(getFragmentInfoByUUID(result.uuid)!);\n }\n }\n }\n fragmentInfo.indexBits = bits;\n }\n return bits;\n}\n\n/** 構造ディレクティブの束縛の中(入れ子の奥も含む)で使う添字のビット集合 */\nexport function getIndexBitsByBinding(binding: IBindingInfo): number {\n return indexBitsOfFragment(getFragmentInfoByUUID(binding.uuid as string)!);\n}\n\n/**\n * 行の位置が変わったときに当て直す列(indexBindingsByContent)に入れる束縛か: 添字の束縛(`$1` …)と、\n * 中に `depthBits` の添字の束縛を持つ入れ子の構造ディレクティブ(内側の for の行・if の枝の添字の束縛へ辿る\n * 入口 — applyChangeToFor.ts の applyIndexBindings・#360)。for の行の位置が変わって値の変わる添字は、その for の\n * 段の `$d` だけ — 行を動かしうるのはその for と外側の for なので、`depthBits` は `$1` … `$d`。中にそれ以外の添字\n * しか無い入れ子(内側の行が自分の番号 `$2` だけを描く形など)まで入れると、位置の変わった行ごとに、当て直す\n * もの無しに入れ子の行を全部辿る(#390)。SSR の行(ssr/hydrateBindings.ts)も同じ振り分け。\n */\nexport function isIndexBinding(binding: IBindingInfo, depthBits: number): boolean {\n return binding.statePathName in INDEX_BY_INDEX_NAME\n || (recursiveBindingTypes.has(binding.bindingType) && (getIndexBitsByBinding(binding) & depthBits) !== 0);\n}\n\nconst ROW_END_PREFIX = 'wcs-row-end';\n\n/**\n * 終端マーカーの付与。バインディング初期化の後に足すので nodePath 解決には影響しない\n * (末尾追加なので既存 index もずれない)。SSR 描画中は付けない — SSR は行ごとに\n * `@@wcs-for-start/end` を出力しており、そちらがレンジの正本かつハイドレーション\n * が読む対象なので、余計なコメントを混ぜない。\n */\nfunction appendRowEndMarker(cloneFragment: DocumentFragment, uuid: string): void {\n cloneFragment.appendChild(document.createComment(`${ROW_END_PREFIX}:${uuid}`));\n}\n\n/**\n * SSR ハイドレーション用: 既存の DOM ノード配列から Content を生成する。\n * テンプレートからの clone ではなく、SSR で描画済みのノードをそのまま使う。\n * `ranged` は createContent と同じ範囲モード(終端マーカーは呼び出し側が `nodes` の末尾に置く)。\n */\nexport function createContentFromNodes(\n nodes: Node[],\n ranged?: boolean,\n): IContent {\n const fragment = document.createDocumentFragment();\n // ノードを fragment に移動せず、参照だけ持つ Content を作る\n const content = new Content(fragment, ranged);\n // Content の内部状態を直接設定\n (content as any)._childNodeArray = nodes;\n (content as any)._firstNode = nodes.length > 0 ? nodes[0] : null;\n (content as any)._lastNode = nodes.length > 0 ? nodes[nodes.length - 1] : null;\n (content as any)._mounted = true; // SSR で既にマウント済み\n return content;\n}\n\n/**\n * RowPlan 経路の実体化: clone → nodePath 解決 → スロットから薄い binding を複製 →\n * initializeRowBindings。パース再生(spread 展開・remember・キー文字列・options\n * オブジェクト・policy 再解決)を行ごとに繰り返さない\n * (docs/state-row-instantiation-redesign.md §3-1/§3-2)。\n */\nfunction createPlanContent(\n bindingInfo: IBindingInfo,\n fragmentInfo: IFragmentInfo,\n plan: IRowPlan,\n): IContent {\n const cloneFragment = document.importNode(fragmentInfo.fragment, true);\n const nodeInfos = fragmentInfo.nodeInfos;\n const nodes: Node[] = new Array(nodeInfos.length);\n for (let i = 0; i < nodeInfos.length; i++) {\n const node = resolveNodePath(cloneFragment, nodeInfos[i].nodePath);\n if (node === null) {\n raiseError(`Node not found by path [${nodeInfos[i].nodePath.join(', ')}] in fragment.`);\n }\n // 再スキャン防止と初期化完了マークは従来経路と同じ台帳に載せる\n markNodeRegistered(node);\n resolveInitializedBinding(node);\n nodes[i] = node;\n }\n const slots = plan.slots;\n const bindings: IBindingInfo[] = new Array(slots.length);\n const indexBindings: IBindingInfo[] = [];\n for (let k = 0; k < slots.length; k++) {\n const slot = slots[k];\n const node = nodes[slot.nodeIndex];\n // text スロットは事前正規化済みの Text がそのまま replaceNode(従来経路の\n // getBindingInfos と同じ帰結)。prop/event は node === replaceNode\n const binding: IBindingInfo = { ...slot.template, node, replaceNode: node };\n bindings[k] = binding;\n if (slot.isIndexBinding) {\n indexBindings.push(binding);\n }\n }\n const session = initializeRowBindings(plan, bindings, bindingInfo.node);\n // プラン経路の content は範囲モードにならない: compileRowPlan は bindingType が\n // text / prop / event のもの以外(= for / if / elseif / else)を含む時点で不適格に\n // するため、プラン適格なフラグメントはトップレベル構造アンカーを持ち得ない。\n const content = new Content(cloneFragment);\n setBindingSessionByContent(content, session);\n setBindingsByContent(content, bindings);\n // 活性化がこの行をプラン初期描画に載せてよいか判定するための逆引き(設計 R2)\n setPlanByContent(content, plan);\n setIndexBindingsByContent(content, indexBindings);\n setNodesByContent(content, nodes);\n setContentByNode(bindingInfo.node, content);\n return content;\n}\n\nexport function createContent(\n bindingInfo: IBindingInfo,\n): IContent {\n if (typeof bindingInfo.uuid === 'undefined' || bindingInfo.uuid === null) {\n raiseError(`BindingInfo.uuid is null.`);\n }\n const fragmentInfo = getFragmentInfoByUUID(bindingInfo.uuid);\n if (!fragmentInfo) {\n raiseError(`Fragment with UUID \"${bindingInfo.uuid}\" not found.`);\n }\n // SSR 描画中は行ごとの @@wcs-for-start/end がレンジの正本なので終端マーカーは付けない\n const ranged = !inSsr() && resolveRanged(fragmentInfo);\n let plan = fragmentInfo.rowPlan;\n if (typeof plan === 'undefined' || (plan !== null && plan.directional !== config.enableDirectionalInitialSync)) {\n // 初回 or config(directional)が変わったときだけコンパイル。不適格は null を\n // キャッシュして以後は従来経路へ直行する\n plan = fragmentInfo.rowPlan = compileRowPlan(fragmentInfo);\n }\n if (plan !== null) {\n return createPlanContent(bindingInfo, fragmentInfo, plan);\n }\n const cloneFragment = document.importNode(fragmentInfo.fragment, true);\n const initialInfo = initializeBindingsByFragment(cloneFragment, fragmentInfo.nodeInfos);\n if (ranged) {\n // uuid は冒頭のガードで非 null が確定している(raiseError は never を返す)\n appendRowEndMarker(cloneFragment, bindingInfo.uuid);\n }\n const content = new Content(cloneFragment, ranged);\n if (initialInfo.spreads.length > 0) content.spreads = initialInfo.spreads;\n setBindingSessionByContent(content, initialInfo.bindingSession);\n setBindingsByContent(content, initialInfo.bindingInfos);\n // 行の位置が変わったときに当て直す列(isIndexBinding)。for の行の段は、その for のリストのパスの\n // ワイルドカードの数 + 1。if の枝は自分の段を持たないので絞らない(辿るときに applyIndexBindings が絞る)\n const depthBits = bindingInfo.bindingType === 'for'\n ? indexBitsUpTo(bindingInfo.statePathInfo.wildcardCount + 1)\n : ALL_INDEX_BITS;\n const indexBindings: IBindingInfo[] = [];\n for(const binding of initialInfo.bindingInfos) {\n if (isIndexBinding(binding, depthBits)) {\n indexBindings.push(binding);\n }\n }\n setIndexBindingsByContent(content, indexBindings);\n setNodesByContent(content, initialInfo.nodes);\n setContentByNode(bindingInfo.node, content);\n return content;\n}\n","import { ILoopContext } from \"../list/types\";\nimport { IBindingInfo } from \"../types\";\nimport { INDEX_BY_INDEX_NAME } from \"../define\";\nimport {\n collectNodesAndBindingInfosOf,\n collectNodesAndBindingInfosByFragment,\n IDeferredSpreadEntry,\n ParseResultTransform,\n processDeferredNode,\n uncollectedNodes,\n} from \"./collectNodesAndBindingInfos\";\nimport { getSubscriberNodes } from \"./getSubscriberNodes\";\nimport { IFragmentNodeInfo, IRowPlan } from \"../structural/types\";\nimport { setLoopContextByNode } from \"../list/loopContextByNode\";\nimport { applyChangeFromBindings } from \"../apply/applyChangeFromBindings\";\nimport { IInitialBindingInfo } from \"./types\";\nimport { BindingSession, getOrCreateBindingSession } from \"./BindingSession\";\n\n/**\n * 未定義カスタム要素への `...: path` を `whenDefined` 後の配線として予約する。\n * ハイドレーション経路(`ssr/hydrateBindings.ts`)も同じ手順を通すため export している —\n * あちらは `collectNodesAndBindingInfos` の 3 要素目を捨てていて、SSR したページでだけ\n * spread が永久に配線されなかった。\n *\n * `contentBindings` は構造テンプレートの行(Content)の束縛の列(#330。`activateContent` が渡す)。\n * 行の待ちは行の解体(session の dispose)が取り消し、次の活性化(プールからの使い回し・`if:` の\n * 再表示)が予約し直す。定義されたら展開した束縛をこの列に足して行の束縛にし(以後の解体・活性化は\n * 他の束縛と同じ)、`deferredSpreads` から外す — 展開は一度きり。添字の束縛(`$1`)は `indexBindings`\n * (行の添字が変わったときに当て直す列)にも足す — createContent の振り分けと同じ。\n */\nexport function scheduleDeferredSpreads(\n deferredSpreads: IDeferredSpreadEntry[],\n parentLoopContext: ILoopContext | null,\n session: BindingSession,\n contentBindings?: IBindingInfo[],\n indexBindings?: IBindingInfo[],\n): void {\n for (const entry of deferredSpreads) {\n // 生きている行の活性化し直し(`if:` の真→真)で待ちを重ねない(取り消し済み・発火済みなら何もしない)\n entry.cancel?.();\n entry.cancel = session.deferUntilDefined(entry.node, entry.tagName, () => {\n const bindings = processDeferredNode(entry);\n if (contentBindings) {\n deferredSpreads.splice(deferredSpreads.indexOf(entry), 1);\n contentBindings.push(...bindings);\n indexBindings!.push(...bindings.filter((binding) => binding.statePathName in INDEX_BY_INDEX_NAME));\n }\n if (bindings.length === 0) return;\n setLoopContextByNode(entry.node, parentLoopContext);\n // 行の束縛は行と同じ選択肢で(createContent の初期化 → activate の昇格と同じ結果)\n const initialized = session.initialize(bindings, contentBindings && { registerPathInfo: false, applyOnReconnect: false });\n applyChangeFromBindings(initialized);\n }, (error: unknown) => {\n console.error(`[@wcstack/state] deferred spread failed for <${entry.tagName}>.`, error);\n });\n }\n}\n\nexport function initializeBindings(\n root: Document | DocumentFragment | Element,\n parentLoopContext: ILoopContext | null,\n transform?: ParseResultTransform,\n // The subscriber nodes to bind. The binder passes its own: the walk never returns `root` itself (binder.ts)\n nodes: Node[] = getSubscriberNodes(root),\n // The binder passes a session of its own: one keyed by its subtree could be a mount scope's (binder.ts)\n session: BindingSession = getOrCreateBindingSession(root),\n): void {\n // Only the nodes not collected yet (#414). A collected node is bound already — by an earlier walk, or\n // as a row's node — and keeps the loop context it was given: a subtree handed over again (the router\n // hands a route's content over on every entry) reset its rows' nodes to `parentLoopContext`, and a\n // row's `if:` failed on its next toggle.\n const [subscriberNodes, allBindings, deferredSpreads] = collectNodesAndBindingInfosOf(uncollectedNodes(nodes), transform);\n for (const node of subscriberNodes) {\n setLoopContextByNode(node, parentLoopContext);\n }\n const initialized = session.initialize(allBindings);\n applyChangeFromBindings(initialized);\n scheduleDeferredSpreads(deferredSpreads, parentLoopContext, session);\n}\n\nexport function initializeBindingsByFragment(\n root: DocumentFragment,\n nodeInfos: IFragmentNodeInfo[],\n): IInitialBindingInfo {\n const [subscriberNodes, allBindings, spreads] = collectNodesAndBindingInfosByFragment(root, nodeInfos);\n const session = new BindingSession();\n // knownRoot=null: detached fragment 上の初期化。observableRootFor が必ず null を\n // 返す(observe は no-op)ため、binding ごとの getRootNode を省略する\n const initialized = session.initialize(allBindings, {\n registerAddress: false,\n applyOnReconnect: false,\n }, null);\n return {\n nodes: subscriberNodes,\n bindingInfos: initialized,\n bindingSession: session,\n spreads,\n };\n}\n\n/**\n * RowPlan 経路の行初期化(createContent 専用)。remember / spread 展開 /\n * shouldApplyState フィルタを経ず、プランのスロットから直接 record を構築する。\n * 返す session は従来経路と同じ活性化(activate)・破棄(dispose/wholesale)\n * インターフェースを持つ。\n */\n// `for` 束縛(そのノード)ごとに 1 つの session を全行で共有する(設計 R3)。\n// プランが差し替わったら(再セット・方向性初期同期の設定変更)新しい session に切り替える。\nconst rowSessionByForNode = new WeakMap<Node, BindingSession>();\nexport function initializeRowBindings(plan: IRowPlan, bindings: IBindingInfo[], forNode: Node): BindingSession {\n let session = rowSessionByForNode.get(forNode);\n if (typeof session === \"undefined\" || session.currentRowPlan !== plan) {\n session = new BindingSession();\n rowSessionByForNode.set(forNode, session);\n }\n session.initializeRow(plan, bindings);\n return session;\n}\n","import { IInitialSyncPolicy, resolveInitialSyncPolicy } from \"../bindings/initialSync\";\nimport { planBinding } from \"../bindings/planFilters\";\nimport { config } from \"../config\";\nimport { COMMAND_NAMESPACE, EVENT_TOKEN_NAMESPACE, INDEX_BY_INDEX_NAME } from \"../define\";\nimport { isPossibleTwoWay } from \"../event/isPossibleTwoWay\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { IBindingInfo } from \"../types\";\nimport { resolveNodePath } from \"./resolveNodePath\";\nimport { IFragmentInfo, IRowPlan, IRowPlanSlot } from \"./types\";\n\n/**\n * rowPlan.ts — 行実体化プランのコンパイル(docs/state-row-instantiation-redesign.md §3-1)。\n *\n * テンプレート(fragmentInfo)を初回行生成時に一度だけ検査し、全スロットが\n * 「行不変の判定をテンプレート時に確定できる」種別のときだけプランを返す。\n * 1 スロットでも確定できなければ null(テンプレート丸ごと従来経路 = 部分適用しない。\n * 経路混在のデバッグ困難を避ける設計判断・同 §5)。\n *\n * プラン適格の条件(すべて満たすこと):\n * - bindingType が text / prop / event のみ(構造 for/if・radio/checkbox・spread は不適格)\n * - バインディング先ノードがカスタム要素でない(定義待ち・wcBindable 検証が不要)\n * - prop が command / eventToken 名前空間でない(token 配線 teardown が要るため)\n * - prop が双方向可能(isPossibleTwoWay)でない(connect-snapshot / observer 配線が要るため)\n * - initial-sync policy が観測不要(observable=false)かつ authority が \"auto\" でない\n * - text スロットは事前正規化済みの Text ノードである\n */\nexport function compileRowPlan(fragmentInfo: IFragmentInfo): IRowPlan | null {\n const directional = config.enableDirectionalInitialSync;\n const slots: IRowPlanSlot[] = [];\n const nodeInfos = fragmentInfo.nodeInfos;\n for (let nodeIndex = 0; nodeIndex < nodeInfos.length; nodeIndex++) {\n const nodeInfo = nodeInfos[nodeIndex];\n const node = resolveNodePath(fragmentInfo.fragment, nodeInfo.nodePath);\n if (node === null) {\n return null;\n }\n for (const template of nodeInfo.parseBindTextResults) {\n const bindingType = template.bindingType;\n if (bindingType !== \"text\" && bindingType !== \"prop\" && bindingType !== \"event\") {\n return null;\n }\n // command.<name>(prop 扱い)と eventToken.<prop>(event 扱い)は token 配線の\n // teardown / attach 分岐が要るため不適格\n const namespace = template.propSegments[0];\n if (namespace === COMMAND_NAMESPACE || namespace === EVENT_TOKEN_NAMESPACE) {\n return null;\n }\n if (bindingType === \"text\") {\n if (node.nodeType !== Node.TEXT_NODE) {\n return null;\n }\n } else if (getCustomElement(node) !== null) {\n return null;\n }\n if (bindingType === \"prop\" && isPossibleTwoWay(node, template.propName)) {\n return null;\n }\n // フィルタの実関数は行不変なので、テンプレートごとに 1 回だけ引く(要件 D16。\n // 未知のフィルタはここで名指しで落ちる — 不適格として倒さない。従来経路へ倒しても\n // 同じ診断が出るだけで、行の生成まで遅れる)\n const planned = planBinding(template);\n let policy: IInitialSyncPolicy;\n try {\n // 判定はテンプレートのノードで行う(policy は node の宣言と行不変フィールドの\n // 純関数)。修飾子エラー等の throw は不適格として従来経路に倒し、従来経路が\n // 同じエラーを同じタイミング(初回行生成)で報告する。\n const probe: IBindingInfo = { ...planned, node, replaceNode: node };\n policy = resolveInitialSyncPolicy(probe);\n } catch {\n return null;\n }\n if (policy.observable || policy.authority === \"auto\") {\n return null;\n }\n slots.push({\n nodeIndex,\n template: planned,\n isEvent: bindingType === \"event\",\n isIndexBinding: template.statePathName in INDEX_BY_INDEX_NAME,\n policy,\n authority: policy.authority,\n });\n }\n }\n if (slots.length === 0) {\n // 束縛を 1 つも持たないテンプレート(静的な行)はプランに載せない(設計 R3)。\n // 行の帳簿(`session.rows`)の出入りは「スロットの binding」を鍵に回るので、0 スロットだと\n // 登録した行を解放する手掛かりが無く、`destroyRow([])` も共有 session の全行破棄へ倒れる。\n // 静的な行に最適化する余地は無い(適用も購読も無い)ので、従来経路に任せる方が安い\n return null;\n }\n return { directional, slots };\n}\n","import { getTransitionRunner } from \"../protocol/transitionRunner\";\nimport { IContent } from \"../structural/types\";\n\n/**\n * Automatic `view-transition-name` assignment (docs/view-transition-design.md §6).\n *\n * A name has to be on the element *before* the browser snapshots the old state,\n * so it cannot be assigned inside the transition's update callback — \"name only\n * what changed\" is impossible. The names are therefore assigned as structural\n * content mounts, and only when the page's arbiter declares `naming=\"auto\"`.\n *\n * The name follows the *content*, not the row's data: a pooled content reused for\n * another item keeps its name, which is exactly what the DOM does, so the\n * transition morphs the element that really was reused.\n */\nexport interface IAutoNaming {\n readonly limit: number;\n}\n\nexport type TransitionNameKind = \"row\" | \"branch\";\n\n/** Elements that already carry a generated name (never renamed). */\nconst namedElements = new WeakSet<Element>();\n\n/**\n * The generated-name ledger is per *document*, not per module instance.\n *\n * `view-transition-name` has to be unique across the whole document: the moment\n * two elements share one, the browser aborts the transition outright. A\n * module-scope counter breaks that as soon as `@wcstack/state` is loaded twice on\n * one page (two CDN bundles), because both copies would start minting\n * `wcs-row-1`. The transition-runner key is a `Symbol.for` for exactly this\n * reason, and the counter needs the same protection.\n *\n * Sharing the cap is right for the same reason: the cost a cap exists to bound —\n * one snapshot group per named element — is a document-wide cost, not a\n * per-bundle one.\n */\nconst NAMING_LEDGER_KEY = Symbol.for(\"wcstack.state.view-transition-naming\");\n\ninterface INamingLedger {\n counter: number;\n assigned: number;\n warned: boolean;\n}\n\nfunction getLedger(): INamingLedger {\n const slot = globalThis as Record<symbol, INamingLedger | undefined>;\n return (slot[NAMING_LEDGER_KEY] ??= { counter: 0, assigned: 0, warned: false });\n}\n\n// テスト用: ドキュメント単位の命名台帳を初期化する\nexport function __test_resetTransitionNaming(): void {\n const ledger = getLedger();\n ledger.counter = 0;\n ledger.assigned = 0;\n ledger.warned = false;\n}\n\n/**\n * The active auto-naming policy, or null when names are the author's business\n * (the default) — one arbiter lookup per structural apply, not per row.\n */\nexport function getAutoNaming(): IAutoNaming | null {\n const runner = getTransitionRunner(\"state\");\n if (runner === null || runner.naming !== \"auto\") {\n return null;\n }\n return { limit: runner.namingLimit };\n}\n\nfunction firstElementOf(content: IContent): Element | null {\n const first = content.firstNode;\n if (first === null) {\n return null;\n }\n const last = content.lastNode;\n for (let node: Node | null = first; node !== null; node = node.nextSibling) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n return node as Element;\n }\n if (node === last) {\n break;\n }\n }\n return null;\n}\n\n/**\n * Give this content's first element a unique name plus a class for group\n * styling, unless it already has one or the cap has been reached.\n *\n * The cap exists because every named element becomes its own snapshot group; a\n * few hundred of them make a transition visibly slow. Past it naming stops and\n * says so once — silently degrading would leave the author wondering why only\n * the first part of a list animates.\n */\nexport function applyTransitionName(\n content: IContent,\n kind: TransitionNameKind,\n naming: IAutoNaming,\n): void {\n const element = firstElementOf(content);\n if (element === null || namedElements.has(element)) {\n return;\n }\n // A node without `style` (anything outside HTMLElement / SVGElement) cannot\n // carry a name. Bail before touching the ledger: consuming the cap and marking\n // the element as named would burn a slot for a name that was never written,\n // and leave that element permanently ineligible.\n const style = (element as HTMLElement).style;\n if (style === undefined) {\n return;\n }\n const ledger = getLedger();\n if (ledger.assigned >= naming.limit) {\n if (!ledger.warned) {\n ledger.warned = true;\n console.warn(\n `[@wcstack/state] auto view-transition-name limit (${naming.limit}) reached; ` +\n \"further elements are left unnamed. Raise naming-limit on <wcs-view-transition>, \" +\n 'or switch to naming=\"manual\" and name only what should morph.',\n );\n }\n return;\n }\n namedElements.add(element);\n ledger.assigned += 1;\n ledger.counter += 1;\n style.setProperty(\"view-transition-name\", `wcs-${kind}-${ledger.counter}`);\n // Group handle for CSS (`::view-transition-group(*.wcs-row)`). Ignored by\n // engines that predate view-transition-class, which costs nothing.\n style.setProperty(\"view-transition-class\", `wcs-${kind}`);\n}\n","import { getPathInfo } from \"../address/PathInfo\";\nimport { createStateAddress } from \"../address/StateAddress\";\nimport { getAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding\";\nimport { getBindingsByContent } from \"../bindings/bindingsByContent\";\nimport { bindLoopContextToContent } from \"../bindings/bindLoopContextToContent\";\nimport { markObserverSkipRemovedChildren } from \"../bindings/observerSkip\";\nimport { getIndexBindingsByContent } from \"../bindings/indexBindingsByContent\";\nimport { inSsr, ssrBlockRemoval } from \"../config\";\nimport { INDEX_BY_INDEX_NAME, WILDCARD } from \"../define\";\nimport { calcDiffIndexes, createListDiff } from \"../list/createListDiff\";\nimport { getListIndexByBindingInfo } from \"../list/getListIndexByBindingInfo\";\nimport { getLastListValueByAbsoluteStateAddress, getRenderedList, IRenderedList, isSwappedList } from \"../list/lastListValueByAbsoluteStateAddress\";\nimport { getListIndexesByList, hasReleasedList, isRetiredListIndex } from \"../list/listIndexesByList\";\nimport { computeStableIndexSet } from \"../list/stableListOrder\";\nimport { isSwapBaselineList } from \"../list/swapBaselineList\";\nimport { IListDiff, IListIndex } from \"../list/types\";\nimport { raiseError } from \"../raiseError\";\nimport { activateContent, deactivateContent } from \"../structural/activateContent\";\nimport { deleteContentByNode, getContentSetByNode } from \"../structural/contentsByNode\";\nimport { createContent, getIndexBitsByBinding, indexBit } from \"../structural/createContent\";\nimport { IContent } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\nimport { applyChange } from \"./applyChange\";\nimport { setRootNodeByFragment } from \"./rootNodeByFragment\";\nimport { IApplyContext } from \"./types\";\nimport { applyTransitionName, getAutoNaming } from \"./viewTransitionNaming\";\n\nconst lastNodeByNode: WeakMap<Node, Node> = new WeakMap();\nconst contentByListIndexByNode: WeakMap<Node, WeakMap<IListIndex, IContent>> = new WeakMap();\nconst pooledContentsByNode: WeakMap<Node, IContent[]> = new WeakMap();\nconst isOnlyNodeInParentContentByNode: WeakMap<Node, boolean> = new WeakMap();\n// この for(アンカー)が最後に描いた並び(#320。lastListValueByAbsoluteStateAddress.ts の IRenderedList)\nconst renderedListByNode: WeakMap<Node, IRenderedList> = new WeakMap();\n// SSR 描画中の行の境界コメント [`@@wcs-for-start`, `@@wcs-for-end`](#334)\nconst ssrBoundsByContent: WeakMap<IContent, Comment[]> = new WeakMap();\n\n/**\n * SSR 描画中: 行を境界コメントで挟んで `parent` の `prev` の直後(null なら末尾)に置き、終端コメントを返す\n * (次の行はその後ろ)。境界は行の Content の範囲の外なので、Content だけを動かすと境界が置き去りになる\n * (#334 — 描いてある行の中身が自分の境界の前へ出て、足した行の境界が入れ子になった)。描いてある行は\n * 境界ごと(中の if / for が描いたノードも含めて)動かす。ラベルの添字は今の位置に付け直す(ハイドレーション\n * は添字で行を組む)。\n */\nfunction placeSsrRow(content: IContent, parent: Node, prev: Node | null, label: string): Comment {\n let bounds = ssrBoundsByContent.get(content);\n if (typeof bounds === 'undefined') {\n bounds = [document.createComment(''), document.createComment('')];\n ssrBoundsByContent.set(content, bounds);\n }\n const [start, end] = bounds;\n start.data = `@@wcs-for-start:${label}`;\n end.data = `@@wcs-for-end:${label}`;\n if (!content.mounted) {\n // 祖先の unmount(if の非表示)で外れた行は、中身だけが外れて境界が残る。外してから置き直す\n start.remove();\n end.remove();\n }\n const ref = prev === null ? null : prev.nextSibling;\n if (start.parentNode === null) {\n // 新しい行・プールから戻す行・祖先の unmount で外れた行・その場で使い回す行(外すときに境界を外した):\n // 境界を置いてから中身を挟む(中の if / for は、この後の活性化が境界の内側へ描く)\n parent.insertBefore(start, ref);\n parent.insertBefore(end, ref);\n content.mountAfter(start);\n } else if (ref !== start) {\n let node: Node = start;\n while (node !== end) {\n const next = node.nextSibling as Node;\n parent.insertBefore(node, ref);\n node = next;\n }\n parent.insertBefore(end, ref);\n }\n return end;\n}\n\n// テスト用ヘルパー(内部状態の操作)\nexport function __test_setContentByListIndex(node: Node, index: IListIndex, content: IContent | null): void {\n setContent(node, index, content);\n}\n\nexport function __test_deleteLastNodeByNode(node: Node): void {\n lastNodeByNode.delete(node);\n}\n\n// SSR ハイドレーション用: Content を ListIndex に登録する\nexport function hydrateSetContent(node: Node, index: IListIndex, content: IContent): void {\n setContent(node, index, content);\n}\n\nexport function hydrateSetLastNode(node: Node, lastNode: Node): void {\n lastNodeByNode.set(node, lastNode);\n}\n\n// SSR ハイドレーション用: サーバーが描いた並びを、この for が描いた並びとして記録する(クライアントで描いた\n// for と同じく、要素の書き込みが描画の基準を書き込む前の写しへ移せるように — #351)\nexport function hydrateSetRenderedList(node: Node, list: readonly unknown[]): void {\n renderedListByNode.set(node, getRenderedList(list));\n}\n\nexport function __test_deleteContentByNode(node: Node): void {\n contentByListIndexByNode.delete(node);\n}\n\nfunction getPooledContents(bindingInfo: IBindingInfo): IContent[] {\n return pooledContentsByNode.get(bindingInfo.node) || [];\n}\n\n// プールの上限(アンカーごと)。プールはアンカー(文書に永続するコメントノード)\n// から content とその DOM サブツリー・バインディング群を強参照するため、無制限だと\n// 大きなリストのクリア後もメモリが解放されない(10k 行で 10MB 級)。上限超過分は\n// contentSetByNode の台帳からも外して GC 可能にする。再追加時は createContent で\n// 作り直すコストと引き換えになる。\nconst MAX_POOLED_CONTENTS = 1000;\nlet maxPooledContents = MAX_POOLED_CONTENTS;\n\n// テスト用: プール上限の変更と現在のプールサイズ取得\nexport function __test_setMaxPooledContents(limit: number): number {\n const prev = maxPooledContents;\n maxPooledContents = limit;\n return prev;\n}\n\nexport function __test_getPooledContentsCount(node: Node): number {\n return (pooledContentsByNode.get(node) || []).length;\n}\n\nfunction setPooledContent(bindingInfo: IBindingInfo, content: IContent): void {\n let contents = pooledContentsByNode.get(bindingInfo.node);\n if (typeof contents === 'undefined') {\n contents = [];\n pooledContentsByNode.set(bindingInfo.node, contents);\n }\n if (contents.length < maxPooledContents) {\n contents.push(content);\n } else {\n // 上限超過: content を完全に手放す。contentSetByNode は createContent 時に\n // 追加されたきり解放経路が無いため、ここで外さないと GC できない。\n deleteContentByNode(bindingInfo.node, content);\n }\n}\n\n/**\n * 親の中身を一括で捨てて良いか(全行削除の近道)の判定に数えるノードか。要素・空白でないテキストの\n * ほかに、**構造ディレクティブのアンカー(コメント)** も数える(#4)。数えないと、同じ親に居る `if` の\n * アンカーまで textContent='' で消え、その `if` は以後何も描けない — 行の中が `if` だけの形では、\n * 行の器ごと壊れる(行を描き直さない main では表に出ないが、消えているのは同じ)。\n */\nfunction countsAsParentContent(node: Node): boolean {\n if (node.nodeType === Node.ELEMENT_NODE) {\n return true;\n }\n if (node.nodeType === Node.TEXT_NODE) {\n return (node.textContent?.trim() ?? '') !== '';\n }\n return node.nodeType === Node.COMMENT_NODE && (node as Comment).data.startsWith('@@wcs-');\n}\n\nfunction isOnlyNodeInParentContent(firstNode: Node, lastNode: Node): boolean {\n let prevCheckNode = firstNode.previousSibling;\n let nextCheckNode = lastNode.nextSibling;\n let onlyNode = true;\n while(prevCheckNode !== null) {\n if (countsAsParentContent(prevCheckNode)) {\n onlyNode = false;\n break;\n }\n prevCheckNode = prevCheckNode.previousSibling;\n }\n while(nextCheckNode !== null) {\n if (countsAsParentContent(nextCheckNode)) {\n onlyNode = false;\n break;\n }\n nextCheckNode = nextCheckNode.nextSibling;\n }\n return onlyNode;\n}\n\n// A stable content may be left in place only when its first node verifiably\n// follows the settled walk position in the same tree: the listIndexes ledger\n// can lag the physical DOM (element-write swaps reorder listIndexes without\n// moving nodes; hidden regions unmount contents that stay registered). Empty\n// contents (null firstNode) always take the settle walk so their mount\n// bookkeeping matches the pre-LIS behavior.\nfunction isPhysicallyAfter(lastNode: Node, firstNode: Node | null): boolean {\n if (firstNode === null) {\n return false;\n }\n if (lastNode.nextSibling === firstNode) {\n return true;\n }\n const position = lastNode.compareDocumentPosition(firstNode);\n return (position & Node.DOCUMENT_POSITION_FOLLOWING) !== 0\n && (position & Node.DOCUMENT_POSITION_DISCONNECTED) === 0;\n}\n\ninterface IInPlaceContents {\n /** 入る行の listIndex → その場で使い回す Content */\n readonly byAddedIndex: Map<IListIndex, IContent>;\n readonly reused: Set<IContent>;\n}\n\n/**\n * 要素書き込みの入れ替えを描き直す差分(基準が「書き込む前の並びの写し」— swapBaselineList.ts)で、\n * 同じ位置の「外す行」と「入る行」を組にし、外す行の Content を入る行にその場で使い回す(#4)。\n * 行の置き換え(リストに無かった値の書き込み)はその位置の行が新しい行に替わるだけなので、プールを通して\n * ブロックを DOM から外す必要が無い — 外すと、双方向バインドの入力で打鍵ごとにフォーカスが失われる。\n * 配列の置換の差分は対象にしない(外した行の Content はこれまでどおりプールを通す)。\n */\nfunction collectInPlaceContents(\n contentMap: WeakMap<IListIndex, IContent>,\n lastValue: unknown,\n diff: IListDiff,\n): IInPlaceContents | null {\n if (!isSwapBaselineList(lastValue)) {\n return null;\n }\n let inPlace: IInPlaceContents | null = null;\n for (let position = 0; position < diff.newIndexes.length; position++) {\n const added = diff.newIndexes[position];\n const removed = diff.oldIndexes[position];\n const content = diff.addIndexSet.has(added) && diff.deleteIndexSet.has(removed)\n ? contentMap.get(removed)\n : undefined;\n if (typeof content === \"undefined\") {\n continue;\n }\n inPlace ??= { byAddedIndex: new Map(), reused: new Set() };\n inPlace.byAddedIndex.set(added, content);\n inPlace.reused.add(content);\n }\n return inPlace;\n}\n\nconst STRUCTURAL_BINDING_TYPES = new Set(['if', 'elseif', 'else', 'for']);\n\n/**\n * 使い回す Content の「適用済み」の印を落とす。入れ子の構造ディレクティブが持つ Content も辿る —\n * `if` の中の `for` や、`elseif` / `else` のアンカーは行の Content ではなく**内側の** Content に\n * 属するので、行の binding だけ落としても新しい行として適用し直されない(印が残ったまま\n * activateContent の applyChange に飛ばされ、解体した内側が描き直されないまま空になる)。\n */\nfunction clearAppliedMarks(content: IContent, context: IApplyContext): void {\n for (const binding of getBindingsByContent(content)) {\n context.appliedBindingSet.delete(binding);\n if (!STRUCTURAL_BINDING_TYPES.has(binding.bindingType)) {\n continue;\n }\n for (const nested of getContentSetByNode(binding.node)) {\n clearAppliedMarks(nested, context);\n }\n }\n}\n\n/**\n * 位置が変わった行の添字の束縛(`$1` …)を当て直す。行の中の入れ子の構造ディレクティブ(createContent が\n * 同じ列に入れる)の Content — 内側の for の行・if の枝、その奥 — も辿る(#360)。内側の for は同じ配列を\n * 描き続けるので差分が出ず、if は条件が変わらないので、ここで辿らないと外側の軸の添字が古いまま残る。\n * 辿るのは、中(入れ子の奥も含む)で動いた行の段の添字(`movedBit` — `for: rows` の行なら `$1`)を使う入れ子\n * だけ。それ以外の添字(外側の行の番号・入れ子の行の自分の番号)は動いても変わらない(#390)。\n * 添字を条件に持つ構造ディレクティブ(`if: $1|lt(2)`)は当て直してから辿る(真のままなら枝は描き直されない)。\n * 外れている Content(プールの行・偽の if の枝)は辿らない(戻すときの活性化が全部の束縛を当てる)。\n */\nfunction applyIndexBindings(content: IContent, context: IApplyContext, movedBit: number): void {\n for (const binding of getIndexBindingsByContent(content)) {\n if (!STRUCTURAL_BINDING_TYPES.has(binding.bindingType)) {\n applyChange(binding, context);\n continue;\n }\n if (binding.statePathName in INDEX_BY_INDEX_NAME) {\n applyChange(binding, context);\n }\n if ((getIndexBitsByBinding(binding) & movedBit) === 0) {\n continue;\n }\n for (const nested of getContentSetByNode(binding.node)) {\n if (nested.mounted) {\n applyIndexBindings(nested, context, movedBit);\n }\n }\n }\n}\n\n/**\n * 入れ子の `for` が持つ Content を解体して台帳から外す(#4)。その場で使い回す行の中身は新しい行として\n * 作り直されるので、外した Content をアンカーの content 台帳(contentSetByNode)に残すと、置き換えの\n * たびに伸び続ける。プールへ返さないのは、返すと次の適用で内側の `for` が「全行削除」の近道\n * (親の textContent を空にする)に入り、囲む `if` のアンカーごと行を壊すため。`if` の Content は\n * アンカーごとに 1 つを使い回すので外さない。\n */\nfunction dropNestedContents(content: IContent): void {\n for (const binding of getBindingsByContent(content)) {\n if (!STRUCTURAL_BINDING_TYPES.has(binding.bindingType)) {\n continue;\n }\n const dropped = binding.bindingType === 'for';\n for (const nested of getContentSetByNode(binding.node)) {\n dropNestedContents(nested);\n if (!dropped || !nested.mounted) {\n continue;\n }\n deactivateContent(nested);\n nested.unmount();\n deleteContentByNode(binding.node, nested);\n // 描いた行を捨てたので、その for が描いた並びも捨てて白紙から描かせる(#320。残すと次の適用が、\n // 捨てた行を自分の行として差分の旧側に数え、台帳から外した Content をプールへ戻してしまう)。行の Content の\n // 台帳も捨てる — 残すと、同じ行を別の外側の行の for も描いている(2 つの外側の行が同じ配列を持つ — #393)とき、\n // その for がアドレスに残した描画の基準を自分の描いた並びと取り違え、描いていない行を探して落ちた\n renderedListByNode.delete(binding.node);\n contentByListIndexByNode.delete(binding.node);\n }\n }\n}\n\nfunction setContent(node: Node, listIndex: IListIndex, content: IContent | null): void {\n let contentByListIndex = contentByListIndexByNode.get(node);\n if (typeof contentByListIndex === 'undefined') {\n if (content === null) {\n return;\n }\n contentByListIndex = new WeakMap<IListIndex, IContent>();\n contentByListIndexByNode.set(node, contentByListIndex);\n }\n if (content === null) {\n contentByListIndex.delete(listIndex);\n } else {\n contentByListIndex.set(listIndex, content);\n }\n}\n\nexport function applyChangeToFor(\n bindingInfo: IBindingInfo, \n context: IApplyContext,\n newValue: unknown, \n): void {\n const listPathInfo = bindingInfo.statePathInfo;\n const listIndex = getListIndexByBindingInfo(bindingInfo);\n const absAddress = getAbsoluteStateAddressByBinding(bindingInfo);\n const recordedLastValue = getLastListValueByAbsoluteStateAddress(absAddress);\n const rendered = renderedListByNode.get(bindingInfo.node);\n let lastValue: readonly unknown[];\n let diff: IListDiff;\n // 共有の記録が、この for の描いた並びを置いて進んだ(#320)。同じリストを描く別の for だけが描いた —\n // この for は `if` で消されていた・DOM から外されていた — か、行の Content の使い回しでこの for が\n // 別の行に付け替わった。行の台帳(どの値がどの行か)は共有の差分で進め、描き替えは自分が描いた行と\n // 今の行を行の同一性で突き合わせて決める。描いた並びが空なら台帳は無い(全行 add)。\n // 今の行の親がこの配列を手放した外側の行(台帳の食い違い)なら突き合わせに使わない — 別の行の値を描き、その後の\n // 書き込みを別の行へ着地させる。従来の差分(行を付け替える)に戻す。行の親が、この配列をまだ持つ別の外側の行なのは\n // 食い違いではない(2 つの外側の行が同じ配列を持つ — #393)\n // 同じ配列を描く別の `for` で要素書き込みの入れ替えが揃い、この for はまだその配列を描く(setByAddress の\n // notifySwappedList・#379)。自分が描いた並び(入れ替えの前の写しへ移された記録)といまの台帳を、行の同一性だけで\n // 突き合わせる。差分(createListDiff)は通さない — 台帳の行の親を、書いていない外側の行へ付け替えてしまう(#256)\n const swapped = typeof rendered !== 'undefined' && isSwappedList(absAddress, newValue);\n const shared = !swapped && typeof rendered !== 'undefined' && rendered.value !== recordedLastValue\n ? createListDiff(listIndex, recordedLastValue, newValue)\n : null;\n if (swapped) {\n lastValue = rendered!.value;\n diff = calcDiffIndexes(getListIndexesByList(lastValue)!, getListIndexesByList(newValue as unknown[])!);\n } else if (shared !== null && shared.newIndexes.every((row) => row.parentListIndex === listIndex || isRetiredListIndex(row.parentListIndex!) || !hasReleasedList(newValue as unknown[], row.parentListIndex!))) {\n lastValue = rendered!.value;\n diff = calcDiffIndexes(getListIndexesByList(lastValue) ?? [], shared.newIndexes);\n } else {\n // lastListValue はアドレスキーの共有台帳。まだ何も描いていない binding ノード\n //(content 台帳が空)が、既に描画済みのアドレスに後から参加する形 — マウント\n // スコープの再初期化(コンポーネントが connectedCallback で shadow を張り直す)や\n // 後着ノードの binder 適用 — では、共有の記録で差分を取ると「既存 content の\n // 再利用・維持」を指示され、この binding には無いので落ちる。自分の台帳が空なら\n // 白紙から全行 add で描く(同じアドレスの他の binding の差分には影響しない)\n lastValue = recordedLastValue.length > 0 && !contentByListIndexByNode.has(bindingInfo.node)\n ? []\n : recordedLastValue;\n diff = createListDiff(listIndex, lastValue, newValue);\n }\n const newListValue = Array.isArray(newValue) ? newValue : [];\n context.newListValueByAbsAddress.set(absAddress, newListValue);\n renderedListByNode.set(bindingInfo.node, getRenderedList(newListValue));\n\n let contentMap = contentByListIndexByNode.get(bindingInfo.node);\n // 要素書き込みの入れ替えを描き直す差分では、同じ位置で外す行の Content を入る行がその場で使い回す(#4)\n const inPlaceContents = typeof contentMap !== 'undefined' ? collectInPlaceContents(contentMap, lastValue, diff) : null;\n const fullDelete = Array.isArray(lastValue)\n && lastValue.length === diff.deleteIndexSet.size\n && diff.deleteIndexSet.size > 0;\n // その場で使い回す Content があるときは、親を空にする近道を取らない(使い回す行の DOM も消える)\n if (fullDelete && inPlaceContents === null && bindingInfo.node.parentNode !== null) {\n let isOnlyNode = isOnlyNodeInParentContentByNode.get(bindingInfo.node);\n if (typeof isOnlyNode === 'undefined') {\n const lastNode = lastNodeByNode.get(bindingInfo.node) || bindingInfo.node;\n // 描いた行が祖先の unmount(`if` の非表示・プールに入った行)で既に外れているなら、アンカーから数える。\n // 外れた末尾には後ろの兄弟が無いので、同じ親に居る兄弟の `for` / `if` を見落として「この for だけ」と\n // 覚え、親を空にする近道がそのアンカーごと消す(プールから戻した行で内側の for が描いていた行を外す形)\n isOnlyNode = isOnlyNodeInParentContent(bindingInfo.node, lastNode.parentNode === bindingInfo.node.parentNode ? lastNode : bindingInfo.node);\n isOnlyNodeInParentContentByNode.set(bindingInfo.node, isOnlyNode);\n }\n if (isOnlyNode) {\n const parentNode = bindingInfo.node.parentNode;\n // 全行は 1 つの mutation record で消えるので、親に「framework の削除がこの件数」と 1 回書けば\n // observer はその record を丸ごと飛ばせる(行ごとの印を消費しない。bindings/observerSkip.ts)\n markObserverSkipRemovedChildren(parentNode, parentNode.childNodes.length);\n parentNode.textContent = '';\n parentNode.appendChild(bindingInfo.node);\n }\n }\n // 全削除時、プールに収まらない content は再利用されないため、per-binding の\n // teardown(listener 解除・アドレス台帳・loopContext 掃除)を丸ごと省略して\n // ノードごと GC に任せる(tryDestroy)。プール行きの分だけ従来どおり解体する\n // (プール行は binding が生存し続けるため address キャッシュのクリアが必須)。\n // content 台帳の WeakMap ビルトインは V8 プロファイルで本関数の self に計上される\n // ホットスポット: 外側の node→map 解決はループ外に持ち上げ、fullDelete(旧全行が\n // deleteIndexSet に載る=台帳の全エントリが消える)では per-index delete を廃して\n // 台帳ごと 1 回で手放す。\n let poolBudget = fullDelete\n ? maxPooledContents - getPooledContents(bindingInfo).length\n : Number.POSITIVE_INFINITY;\n const ssrMode = inSsr();\n if (typeof contentMap !== 'undefined') {\n // Set の for...of は行ごとに反復子の結果オブジェクトを割り当てる(消去の scavenge の引き金)ので forEach で回す\n const map = contentMap;\n diff.deleteIndexSet.forEach((deleteIndex) => {\n const content = map.get(deleteIndex);\n if (typeof content !== 'undefined') {\n if (ssrMode) {\n // 外す行の境界も外す(#334。その場で使い回す行は、足す行として境界を置き直す)。SSR の外で\n // 描いた行(同じ文書で後から SSR が始まった)は境界を持たない\n ssrBoundsByContent.get(content)?.forEach((bound) => bound.remove());\n ssrBlockRemoval.seen = true;\n }\n if (inPlaceContents !== null && inPlaceContents.reused.has(content)) {\n // 同じ位置に入る行がその場で使い回す。自分のノードは DOM に残し、プールにも入れないが、\n // 解体は unmount と同じ(ネストした for / if の Content とアドレス台帳を落とす)\n deactivateContent(content);\n dropNestedContents(content);\n content.unmountInPlace();\n } else if (poolBudget <= 0 && content.tryDestroy()) {\n deleteContentByNode(bindingInfo.node, content);\n } else {\n deactivateContent(content);\n content.unmount();\n setPooledContent(bindingInfo, content);\n poolBudget -= 1;\n }\n if (!fullDelete) {\n map.delete(deleteIndex);\n }\n }\n });\n if (fullDelete) {\n contentByListIndexByNode.delete(bindingInfo.node);\n contentMap = undefined;\n }\n }\n\n let lastNode = bindingInfo.node;\n const elementPathInfo = getPathInfo(listPathInfo.path + '.' + WILDCARD);\n const loopContextStack = context.stateElement.loopContextStack;\n // When the new order contains inversions, contents in the stable set (an LIS\n // of old positions) keep their relative order and must not be moved; moving\n // only the rest avoids the cascade where one swap relocates every row in\n // between. null = no inversions; the position guard below then does no moves.\n const stableIndexSet = computeStableIndexSet(diff);\n let fragment: DocumentFragment | null = null;\n if (diff.newIndexes.length == diff.addIndexSet.size \n && diff.newIndexes.length > 0\n && lastNode.isConnected\n && inPlaceContents === null\n ) {\n // 全部追加の場合はまとめて処理\n fragment = document.createDocumentFragment();\n setRootNodeByFragment(fragment, context.rootNode);\n }\n // SSR の境界コメントのラベル(`<uuid>:<path>:` + 行の添字)\n const ssrLabel = ssrMode ? `${bindingInfo.uuid}:${listPathInfo.path}:` : '';\n // 自動命名ポリシーは行ごとではなく apply ごとに 1 回だけ引く\n // (docs/view-transition-design.md §6)。既定の manual では null で、\n // 以降の行ループは分岐 1 つ分しか増えない。\n const autoNaming = getAutoNaming();\n // 追加行ごとの WeakMap 解決を避けるためプール配列も 1 回だけ引く(プールの配列\n // 実体は setPooledContent が一度作ったら不変なので、delete ループ後の参照で安定)\n const pooledContents = pooledContentsByNode.get(bindingInfo.node);\n for(const index of diff.newIndexes) {\n let content: IContent | undefined;\n // add\n if (diff.addIndexSet.has(index)) {\n const stateAddress = createStateAddress(elementPathInfo, index);\n loopContextStack.createLoopContext(stateAddress, (loopContext) => {\n content = inPlaceContents?.byAddedIndex.get(index)\n ?? (typeof pooledContents !== 'undefined' ? pooledContents.pop() : undefined);\n if (typeof content === 'undefined') {\n content = createContent(bindingInfo);\n } else {\n // プール(か同じ位置)から使い回す Content の binding は、同じバッチで**外した行として**適用済みのことがある。\n // 外した行のアドレスへの書き込み(行の葉・要素の置き換え)で enqueue された binding が、この `for`\n // より先に適用された形。印が残ると activateContent の applyChange が飛ばし、新しい行に外した行の\n // 値が残る(表示と state が食い違う)。新しい行として適用し直す\n clearAppliedMarks(content, context);\n // DOM に戻す前に新しい行のループ文脈を張る。戻した瞬間に中のマウント済みコンポーネントの\n // 再接続(`$connectedCallback`)が同期で走り、要素の行を引く(#368)\n bindLoopContextToContent(content, loopContext);\n }\n // コンテント活性化の前にDOMツリーに追加しておく必要がある\n if (ssrMode) {\n lastNode = fragment !== null\n ? placeSsrRow(content, fragment, null, ssrLabel + index.index)\n : placeSsrRow(content, lastNode.parentNode!, lastNode, ssrLabel + index.index);\n } else if (fragment !== null) {\n content.appendTo(fragment);\n } else if (lastNode.nextSibling !== content.firstNode) {\n // Ensure content is in correct position (e.g. if previous siblings were deleted/moved)\n content.mountAfter(lastNode);\n }\n // コンテントを活性化\n activateContent(content, loopContext, context);\n if (autoNaming !== null) {\n applyTransitionName(content, \"row\", autoNaming);\n }\n });\n if (typeof content === 'undefined') {\n raiseError(`Content not found for ListIndex: ${index.index} at path \"${listPathInfo.path}\"`);\n }\n if (inPlaceContents !== null && inPlaceContents.reused.has(content)) {\n // その場で使い回した行の中のコンポーネントは DOM から外れない = 付け替えを知らせる\n // connectedCallback が来ないので、マウントスコープを新しい行の listIndex へ張り直す(#4)。\n // スコープ機能の rowReused hook(webComponent/addressHooks.ts)。hook の無い state は判定 1 個で抜ける\n const hooks = context.stateElement.addressHooks;\n if (hooks) {\n const reused = hooks.rowReused;\n for (let i = 0; i < reused.length; i++) {\n reused[i](context.stateElement, content);\n }\n }\n }\n } else {\n // getContent 相当(undefined→null 正規化は後段の raiseError 判定が null 比較のため維持)\n content = (typeof contentMap !== 'undefined' ? contentMap.get(index) ?? null : null)!;\n if (diff.changeIndexSet.has(index)) {\n // change(値の変わる添字は、この for の段の `$d` — d はリストのパスのワイルドカードの数 + 1)\n applyIndexBindings(content, context, indexBit(listPathInfo.wildcardCount));\n }\n // Update lastNode for next iteration to ensure correct order\n // Ensure content is in correct position (e.g. if previous siblings were deleted/moved)\n if (content === null) {\n raiseError(`Content not found for ListIndex: ${index.index} at path \"${listPathInfo.path}\"`);\n }\n // 祖先の unmount(if の非表示など)で解体された行は、ここで物理的に\n // 戻されるだけでは binding が dispose 済みのまま復活しない。位置合わせの\n // 前に判定しておき(mountAfter が mounted を立てる)、戻した後に再活性化する。\n const unmountedByAncestor = !content.mounted;\n if (ssrMode) {\n lastNode = placeSsrRow(content, lastNode.parentNode!, lastNode, ssrLabel + index.index);\n } else if (!(stableIndexSet !== null && stableIndexSet.has(index) && isPhysicallyAfter(lastNode, content.firstNode))\n && lastNode.nextSibling !== content.firstNode) {\n // Stable contents are already in correct relative order — but only\n // trust that after physical verification (see isPhysicallyAfter).\n // Contents out of order (and everything unverifiable) settle via the\n // self-healing mountAfter walk.\n content.mountAfter(lastNode);\n }\n if (unmountedByAncestor) {\n // 再活性化しないと、行の同一性が保たれる更新が以後すべて無視される\n // (docs/state-deactivated-content-stale-update.md)。activate は\n // disposed record の再構築を含むので、プール再利用と同じ経路で戻る。\n const revivedContent = content;\n const stateAddress = createStateAddress(elementPathInfo, index);\n loopContextStack.createLoopContext(stateAddress, (loopContext) => {\n activateContent(revivedContent, loopContext, context);\n });\n }\n }\n if (!ssrMode) {\n // SSR では行の終端コメント(placeSsrRow が返す)のまま\n lastNode = content.lastNode || lastNode;\n }\n if (typeof contentMap === 'undefined') {\n contentMap = new WeakMap<IListIndex, IContent>();\n contentByListIndexByNode.set(bindingInfo.node, contentMap);\n }\n contentMap.set(index, content);\n }\n lastNodeByNode.set(bindingInfo.node, lastNode);\n if (fragment !== null) {\n // Mount all at once\n bindingInfo.node.parentNode!.insertBefore(fragment, bindingInfo.node.nextSibling);\n setRootNodeByFragment(fragment, null);\n }\n}\n","import { bindLoopContextToContent } from \"../bindings/bindLoopContextToContent\";\nimport { config, inSsr, ssrBlockRemoval } from \"../config\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { activateContent, deactivateContent } from \"../structural/activateContent\";\nimport { getContentSetByNode } from \"../structural/contentsByNode\";\nimport { createContent } from \"../structural/createContent\";\nimport { IContent } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\nimport { applyTransitionName, getAutoNaming } from \"./viewTransitionNaming\";\n\nfunction bindingInfoText(bindingInfo: IBindingInfo): string {\n return `${bindingInfo.bindingType} ${bindingInfo.statePathName} ${bindingInfo.outFilters.map(f => f.filterName).join('|')} ${bindingInfo.node.isConnected ? '(connected)' : '(disconnected)'}`;\n}\n\nexport function applyChangeToIf(\n bindingInfo: IBindingInfo,\n context: IApplyContext,\n rawNewValue: unknown,\n): void {\n const newValue = Boolean(rawNewValue);\n let content: IContent | undefined;\n const contents = getContentSetByNode(bindingInfo.node);\n if (contents.size === 0) {\n content = createContent(bindingInfo);\n } else {\n content = contents.values().next().value!;\n }\n const ssrMode = inSsr();\n const uuid = bindingInfo.uuid ?? '';\n const keyword = bindingInfo.bindingType; // if, elseif, else\n if (!newValue) {\n if (config.debug) {\n console.log(`unmount if content : ${bindingInfoText(bindingInfo)}`);\n }\n if (ssrMode && content.mounted) ssrBlockRemoval.seen = true;\n deactivateContent(content);\n content.unmount();\n }\n if (newValue) {\n if (config.debug) {\n console.log(`mount if content : ${bindingInfoText(bindingInfo)}`);\n }\n // DOM に戻す前にループ文脈を張る。再表示で戻した瞬間に中のマウント済みコンポーネントの\n // 再接続(`$connectedCallback`)が同期で走り、要素の行を引く(#368)\n const loopContext = getLoopContextByNode(bindingInfo.node);\n bindLoopContextToContent(content, loopContext);\n if (ssrMode) {\n // 描いてある枝(真のままの描き直し)は境界の組ごとその場に残す(#356)。組を置き直すと枝の\n // トップレベルのノードだけが新しい組へ移り、先に描いた入れ子の枝・行は古い組の中に残った\n if (!content.mounted) {\n const startComment = document.createComment(`@@wcs-${keyword}-start:${uuid}:${bindingInfo.statePathName}`);\n bindingInfo.node.parentNode!.insertBefore(startComment, bindingInfo.node.nextSibling);\n content.mountAfter(startComment);\n const endComment = document.createComment(`@@wcs-${keyword}-end:${uuid}:${bindingInfo.statePathName}`);\n const afterNode = content.lastNode ?? startComment;\n afterNode.parentNode!.insertBefore(endComment, afterNode.nextSibling);\n }\n } else {\n content.mountAfter(bindingInfo.node);\n }\n activateContent(content, loopContext, context);\n // 自動命名(docs/view-transition-design.md §6)。manual(既定)では null。\n const autoNaming = getAutoNaming();\n if (autoNaming !== null) {\n applyTransitionName(content, \"branch\", autoNaming);\n }\n }\n}\n\n","/**\n * SSR 時に HTML 属性で表現できないプロパティバインディングを蓄積するストア。\n * ハイドレーション時にクライアント側で復元する。\n */\n\nexport interface ISsrPropertyEntry {\n propName: string;\n value: unknown;\n}\n\n// node → プロパティエントリのリスト\nconst store: WeakMap<Node, ISsrPropertyEntry[]> = new WeakMap();\n\nexport function addSsrProperty(node: Node, propName: string, value: unknown): void {\n let entries = store.get(node);\n if (!entries) {\n entries = [];\n store.set(node, entries);\n }\n // 同じプロパティの既存エントリは上書き\n const existing = entries.find(e => e.propName === propName);\n if (existing) {\n existing.value = value;\n } else {\n entries.push({ propName, value });\n }\n}\n\nexport function getSsrProperties(node: Node): ISsrPropertyEntry[] {\n return store.get(node) ?? [];\n}\n\nexport function getAllSsrPropertyNodes(): Node[] {\n // WeakMap は列挙不可なので、別途トラッキングが必要\n return Array.from(trackedNodes);\n}\n\nconst trackedNodes: Set<Node> = new Set();\n\nexport function trackSsrPropertyNode(node: Node): void {\n trackedNodes.add(node);\n}\n\nexport function clearSsrPropertyStore(): void {\n trackedNodes.clear();\n}\n","/**\n * Trusted Types (`require-trusted-types-for 'script'`) 対応。正本は docs/csp.md §7。\n *\n * state が HTML sink に流すのは **状態の値**(`innerHTML: path` などのプロパティ\n * バインド)で、ユーザー入力が混ざり得る文字列そのもの。ここに identity policy を\n * 噛ませて通すのは TT の無効化と同義なので、state は自前の policy を作らない。\n * 利用側が sanitizer を持つ policy を注入したときだけ通し、無ければ従来どおり\n * ブラウザに弾かせる(ただし何を設定すれば直るかは必ず言う)。\n *\n * 注入口は全 @wcstack パッケージ共通のグローバルスロット。buildless(CDN 一発)でも\n * inline script 1 本で差し込める:\n *\n * ```js\n * globalThis[Symbol.for(\"wcstack.trustedTypes.policy\")] =\n * trustedTypes.createPolicy(\"my-app\", { createHTML: (s) => DOMPurify.sanitize(s) });\n * ```\n *\n * バンドラ経由なら `setTrustedTypesPolicy()` を使う。値は毎回スロットから読むので\n * 後から差し替えても効く(identity policy を作る router / worker 側だけは\n * `createPolicy` の重複を避けるため生成結果をシングルトンで保持する)。\n */\n\nexport interface IWcsTrustedTypesPolicy {\n createHTML?(input: string): unknown;\n createScriptURL?(input: string): unknown;\n}\n\n/** 利用側が policy を差し込むグローバルスロット(全 @wcstack パッケージ共通)。 */\nexport const TRUSTED_TYPES_POLICY_SLOT = Symbol.for(\"wcstack.trustedTypes.policy\");\n\ntype SymbolSlotHolder = { [key: symbol]: unknown };\n\n/**\n * 利用側が注入した policy を返す。state はここに identity policy をフォールバック\n * させない(それをやると TT を無効化することになる)。\n */\nexport function getTrustedTypesPolicy(): IWcsTrustedTypesPolicy | null {\n const value = (globalThis as SymbolSlotHolder)[TRUSTED_TYPES_POLICY_SLOT];\n if (value === null || typeof value !== \"object\") return null;\n return value as IWcsTrustedTypesPolicy;\n}\n\n/** 利用側 policy を設定する(`null` で解除)。最初のバインド適用前に呼ぶこと。 */\nexport function setTrustedTypesPolicy(policy: IWcsTrustedTypesPolicy | null): void {\n (globalThis as SymbolSlotHolder)[TRUSTED_TYPES_POLICY_SLOT] = policy;\n}\n\n/**\n * TrustedHTML が要求されるプロパティか。`textContent` などの安全な sink は含めない。\n * ホットパス(全プロパティ書き込み)から呼ばれるので文字列比較だけで済ませる。\n */\nexport function isHtmlSinkProp(prop: string): boolean {\n return prop === \"innerHTML\" || prop === \"outerHTML\" || prop === \"srcdoc\";\n}\n\n/**\n * HTML sink へ書く値を利用側 policy に通す。policy が無ければ値をそのまま返す\n * = TT 有効下ではブラウザが弾く(意図どおり)。policy がある場合は TT 非対応\n * ブラウザでも通す: sanitizer は Chromium だけで効いても意味がないため。\n */\nexport function trustHtmlValue(value: unknown): unknown {\n if (typeof value !== \"string\") return value;\n const policy = getTrustedTypesPolicy();\n const createHTML = policy?.createHTML;\n if (typeof createHTML !== \"function\") return value;\n return createHTML.call(policy, value);\n}\n\nlet _enforced: boolean | undefined = undefined;\n\n/**\n * TT が実際に強制されているかを実測する。エラーメッセージの文言に依存しないよう、\n * 使い捨ての要素へ実際に書いて確かめる。`default` policy がある場合は書き込みが\n * 通る=我々の書き込みも通るので、正しく false になる。\n *\n * cold path(書き込みが失敗した後)でしか呼ばれない。\n */\nexport function isTrustedTypesEnforced(): boolean {\n if (_enforced !== undefined) return _enforced;\n if (!(\"trustedTypes\" in globalThis)) {\n _enforced = false;\n return _enforced;\n }\n try {\n document.createElement(\"div\").innerHTML = \"<i></i>\";\n _enforced = false;\n } catch {\n _enforced = true;\n }\n return _enforced;\n}\n\nlet _reported = false;\n\n/** テスト用: 実測キャッシュと一度きりの診断をリセットする。 */\nexport function _resetTrustedTypesDiagnostics(): void {\n _enforced = undefined;\n _reported = false;\n}\n\n/**\n * HTML sink への書き込み失敗を診断する。applyChangeToProperty の catch は\n * `config.debug` 時しか warn しないため、TT が原因のときは黙って壊れていた。\n * 原因と直し方が分かる形で一度だけ報告する。\n */\nexport function reportTrustedTypesBlock(element: Element, prop: string): void {\n if (_reported) return;\n if (!isTrustedTypesEnforced()) return;\n _reported = true;\n const hasPolicy = typeof getTrustedTypesPolicy()?.createHTML === \"function\";\n const cause = hasPolicy\n ? \"The injected policy's createHTML() did not return a TrustedHTML.\"\n : \"No sanitizing policy is installed, and @wcstack/state deliberately does not \"\n + \"pass state values through an identity policy — that would defeat the CSP.\";\n console.error(\n `[@wcstack/state] Writing to \"${prop}\" was blocked by Trusted Types `\n + `(require-trusted-types-for 'script'). ${cause}\\n`\n + `Install a sanitizing policy before the first binding is applied:\\n`\n + ` globalThis[Symbol.for(\"wcstack.trustedTypes.policy\")] =\\n`\n + ` trustedTypes.createPolicy(\"my-app\", { createHTML: (s) => DOMPurify.sanitize(s) });\\n`\n + `Or bind the value as text instead of HTML. See docs/csp.md section 7.`,\n { element, property: prop },\n );\n}\n","import { config, inSsr } from \"../config\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { applyMirrorAttribute, getInputAttributeMirror } from \"../event/getInputAttributeMirror\";\nimport { beginPropagationTransaction, extendPropagationContext, getCurrentPropagationContext, getEdgeId, getWireId, runWithPropagationContext, runWithWriteReceipt } from \"../propagation/propagation\";\nimport { isPossibleTwoWay } from \"../event/isPossibleTwoWay\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { IBindingInfo } from \"../types\";\nimport { componentApplyHooks } from \"../core/componentApplyHooks\";\nimport { IApplyContext } from \"./types\";\nimport { addSsrProperty, trackSsrPropertyNode } from \"./ssrPropertyStore\";\nimport { isHtmlSinkProp, reportTrustedTypesBlock, trustHtmlValue } from \"../trustedTypes\";\n\n// SSR 時に HTML 属性で代替可能なプロパティ\n// これら以外のプロパティは ssrPropertyStore に蓄積してハイドレーション時に復元\nconst SSR_ATTR_PROPS: Record<string, (element: Element, value: unknown) => void> = {\n value(element, value) {\n if (element.tagName === 'TEXTAREA') {\n element.textContent = String(value ?? '');\n } else {\n element.setAttribute('value', String(value ?? ''));\n }\n },\n checked(element, value) {\n if (value) element.setAttribute('checked', '');\n else element.removeAttribute('checked');\n },\n selected(element, value) {\n if (value) element.setAttribute('selected', '');\n else element.removeAttribute('selected');\n },\n disabled(element, value) {\n if (value) element.setAttribute('disabled', '');\n else element.removeAttribute('disabled');\n },\n selectedIndex(element, value) {\n const options = element.querySelectorAll('option');\n const idx = Number(value);\n for (let i = 0; i < options.length; i++) {\n if (i === idx) options[i].setAttribute('selected', '');\n else options[i].removeAttribute('selected');\n }\n },\n};\n\n/**\n * 表示のプロパティは `textContent` / `innerText` / `innerHTML` の 3 つ(要件 B8)。ここへの\n * undefined は「値が無い」ので空にする — 要素の入力と違って生かすべき既定値が無く、\n * スキップすると、使い回した行に前の行の表示が残る。\n *\n * `outerHTML` は **入れない**。`trustedTypes.isHtmlSinkProp` は HTML sink として認めるが、\n * `element.outerHTML = \"\"` は要素そのものを DOM から外すので、「空にする」では済まず束縛先の\n * ノードごと失われる(以降の更新が届かない)。値が無いときはスキップして前の描画を残す方が\n * まだ壊れ方が小さい。`outerHTML:` を表示面として正しく畳むには「置換のやり直し」の設計が要る。\n */\nexport function applyChangeToProperty(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n if (binding.propSegments.length === 1) {\n const displayProp = binding.propSegments[0];\n if (displayProp === \"textContent\" || displayProp === \"innerText\") {\n // テキストの表示プロパティは IDL 側で文字列化される — `textContent` は nullable DOMString\n // (null は空文字)、`innerText` は [LegacyNullToEmptyString]。ブラウザでは生値を代入しても\n // 同じ結果になるが、SSR(happy-dom)の setter は**非文字列の falsy を落とす**ので\n // `textContent: count` が 0 のとき、サーバ HTML だけが空になっていた(ハイドレーション用\n // props には正しい値が載るのでクライアントでは戻る= no-JS / SEO / 初回描画だけが壊れる)。\n // IDL と同じ規則にここで自分で寄せる。副次的に、比較(下の current !== newValue)も\n // 文字列同士になり、数値を束ねた表示が毎回書き直されなくなる。\n // `== null` は null と undefined の両方(意図的な緩い比較)\n newValue = newValue == null ? \"\" : String(newValue);\n } else if (typeof newValue === \"undefined\" && displayProp === \"innerHTML\") {\n // `innerHTML` を上の文字列化に含めない理由: TrustedHTML を String() で潰すと Trusted Types の\n // 強制下で書き込みが拒否される(trustedTypes.trustHtmlValue は非文字列を素通しする)。\n // 値が無いときに空にする規則だけは表示面として共通(要件 B8)\n newValue = \"\";\n }\n }\n // 要素の入力への undefined は「状態が値を持たない=無意見」であり、書き込み自体をスキップして\n // 要素側の既定値を生かす。書き込んでしまうと setter の文字列化で\n // \"undefined\" 属性や removeAttribute が走り要素が壊れる (spread で未初期化\n // slot を配線したときに顕在化)。明示的なクリアは null で表現する。\n // mirror 属性 (applyMirrorAttribute) の「undefined → 属性削除」と同じ語彙。\n if (typeof newValue === \"undefined\") {\n if (config.debug) {\n console.debug(`Skipped property write: state value is undefined.`, {\n element: binding.node,\n propSegments: binding.propSegments,\n statePathName: binding.statePathName,\n });\n }\n return;\n }\n const element = binding.node as Element;\n const propSegments = binding.propSegments;\n if (propSegments.length === 1) {\n const firstSegment = propSegments[0];\n\n const current = (element as any)[firstSegment];\n if (current !== newValue) {\n // 完了前の丸ごとマウント(`state: user`)は、作者の state オブジェクトを親の\n // オブジェクトで置き換えてしまう。あとで戻せるように置き換え前を控える\n // (webComponent/preCompletionWrites.ts — bind-component の機能が core/componentApplyHooks.ts に置く。\n // 置かれていなければ判定 1 回で抜ける)。オブジェクト → オブジェクトの書き込みで\n // 相手がカスタム要素のときだけ台帳に触る(通常の書き込みは typeof 判定で抜ける)。\n if (componentApplyHooks !== null && current !== null && typeof current === 'object'\n && newValue !== null && typeof newValue === 'object'\n && getCustomElement(element) !== null) {\n componentApplyHooks.rememberOverwrittenObject(element, firstSegment, current);\n }\n // Trusted Types: HTML sink (`innerHTML` 等) への書き込みだけ、利用側が注入した\n // sanitizer 付き policy を通す。state が identity policy を作って素通しさせるのは\n // TT の無効化と同義なので採らない(docs/csp.md §7)。sink 以外は文字列比較 3 回で\n // 抜けるので、ホットパスの実コストはほぼ無い。\n const isHtmlSink = isHtmlSinkProp(firstSegment);\n\n const performWrite = (): void => {\n let propertyWriteSucceeded = false;\n try {\n (element as any)[firstSegment] = isHtmlSink ? trustHtmlValue(newValue) : newValue;\n propertyWriteSucceeded = true;\n } catch (error) {\n // TT が原因のときは config.debug に関係なく報告する。ここを黙って握り潰すと\n // 「バインドを書いたのに何も起きない」という最悪の壊れ方をする。\n if (isHtmlSink) {\n reportTrustedTypesBlock(element, firstSegment);\n }\n if (config.debug) {\n console.warn(`Failed to set property '${firstSegment}' on element.`, {\n element,\n newValue,\n error\n });\n }\n }\n // wc-bindable inputs[].attribute ミラー。プロパティ書き込みが成功したときだけ\n // 属性へ反映する。setter が値を拒否した場合に属性だけ進んでしまうと\n // property と attribute が乖離し、attributeChangedCallback や CSS セレクタが\n // 実際のプロパティ値と矛盾した状態で発火するため、ここでガードする。\n if (propertyWriteSucceeded) {\n const mirrorAttr = getInputAttributeMirror(element, firstSegment);\n if (mirrorAttr !== null) {\n try {\n applyMirrorAttribute(element, mirrorAttr, newValue);\n } catch (error) {\n if (config.debug) {\n console.warn(`Failed to mirror attribute '${mirrorAttr}' on element.`, {\n element,\n newValue,\n error\n });\n }\n }\n }\n }\n };\n // Zero-cost fast path (§4 最適化): the propagation edge / WriteReceipt\n // machinery only matters when the element write can *echo* — i.e. the setter\n // may synchronously dispatch an event a two-way wire feeds back to state.\n // `isPossibleTwoWay` is the same conservative check the two-way listener\n // registration uses, and it is cheap for the common one-way case (textContent\n // / class / style on plain elements return false fast). One-way bindings can\n // never re-traverse an edge, so skipping the context/receipt is safe and\n // avoids a per-apply Set copy + receipt allocation. Diamond / coalescing are\n // unaffected — those ride the write-transaction context threaded through the\n // updater, not the element edge.\n if (config.enablePropagationContext && isPossibleTwoWay(element, firstSegment)) {\n // Phase 3: state → element edge の通過を記録し、同じ transaction が\n // 同じ edge を再度通ろうとした場合だけ抑止する(設計書 §4 規則 2)。\n // 書き込みは WriteReceipt scope で包み、setter が同期 dispatch する\n // event が confirmation / 正規化を判定できるようにする(規則 3)。\n const wireId = getWireId(element, firstSegment, binding.statePathName);\n const edgeId = getEdgeId(wireId, \"to-element\");\n const baseContext = _context?.propagationContextByBinding?.get(binding)\n ?? getCurrentPropagationContext()\n ?? beginPropagationTransaction(wireId);\n if (baseContext.visitedEdges.has(edgeId)) {\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"propagation:suppressed\",\n reason: \"visited-edge\",\n transactionId: baseContext.transactionId,\n edgeId,\n node: element,\n member: firstSegment,\n });\n }\n } else {\n const extendedContext = extendPropagationContext(baseContext, edgeId);\n runWithPropagationContext(extendedContext, () =>\n runWithWriteReceipt(element, firstSegment, newValue, wireId, extendedContext.transactionId, performWrite));\n }\n } else {\n performWrite();\n }\n }\n if (inSsr()) {\n const attrHandler = SSR_ATTR_PROPS[firstSegment];\n if (attrHandler) {\n // 属性で代替可能 → HTML 属性に反映\n attrHandler(element, newValue);\n } else {\n // 属性で代替不可 → ハイドレーション用ストアに蓄積\n addSsrProperty(element, firstSegment, newValue);\n trackSsrPropertyNode(element);\n }\n }\n return;\n }\n const firstSegment = propSegments[0];\n let subObject = (element as any)[firstSegment];\n for (let i = 1; i < propSegments.length - 1; i++) {\n const segment = propSegments[i];\n if (subObject == null) {\n return;\n }\n subObject = subObject[segment];\n }\n const lastSegment = propSegments[propSegments.length - 1];\n const oldValue = subObject[lastSegment];\n if (oldValue !== newValue) {\n if (Object.isFrozen(subObject)) {\n if (config.debug) {\n console.warn(`Attempting to set property on frozen object.`, {\n element,\n propSegments,\n oldValue,\n newValue\n });\n }\n return;\n }\n // 完了前の部分マウント(`state.theme: theme`)が、作者の state オブジェクトに無かった\n // キーを作る(積み)ことを控える。R1 の衝突報告はこのキーを作者のものとして扱わない\n // (webComponent/preCompletionWrites.ts — core/componentApplyHooks.ts 越し)\n if (componentApplyHooks !== null && propSegments.length === 2 && typeof subObject === 'object' && subObject !== null\n && getCustomElement(element) !== null) {\n if (!(lastSegment in subObject)) {\n componentApplyHooks.recordInjectedKey(element, firstSegment, lastSegment);\n } else {\n // 既存キーの上書き: 作者の値を控える(v2 の厳格 R1 が snapshot 前に復元する)。\n // 完了後の (element, stateProp) への適用はここへルーティングされない\n //(applyChangeToWebComponent の no-op へ行く — apply/applyChange.ts)ので、\n // ここに来る上書きは常に完了前=控えの対象で良い\n componentApplyHooks.rememberOverwrittenValue(element, firstSegment, lastSegment, subObject[lastSegment]);\n }\n }\n try {\n subObject[lastSegment] = newValue;\n } catch (error) {\n if (config.debug) {\n console.warn(`Failed to set property on sub-object.`, {\n element,\n propSegments,\n oldValue,\n newValue,\n error\n });\n }\n }\n }\n // サブオブジェクトプロパティ (e.g. style.xxx) は属性に反映済みなのでストア不要\n}\n","import { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\n\n/**\n * 要素 `element` の `propName` プロパティ書き込みに対して、\n * wc-bindable inputs の `attribute` ミラー先属性名を返す。\n *\n * - wc-bindable でないネイティブ要素や、inputs 未宣言、attribute フィールド無しは null\n * - inputs に同名宣言があっても `attribute` を持たないものはミラー対象外\n *\n * 戻り値の string がそのまま `setAttribute(name, value)` の name となる。\n */\nexport function getInputAttributeMirror(element: Element, propName: string): string | null {\n const customTagName = getCustomElement(element);\n if (customTagName === null) {\n return null;\n }\n const customClass = getCustomElementRegistry(element)?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n return null;\n }\n const input = readBindableDeclaration(element)?.declaredInputs.get(propName);\n if (typeof input?.attribute === \"string\" && input.attribute.length > 0) {\n return input.attribute;\n }\n return null;\n}\n\n/**\n * mirror 属性値の表現を決める。\n * - null / undefined → 属性削除\n * - object / array → JSON.stringify (失敗時は String(value))\n * - その他 (string / number / boolean / bigint) → String(value)\n */\nexport function applyMirrorAttribute(element: Element, attributeName: string, value: unknown): void {\n if (value === null || typeof value === \"undefined\") {\n element.removeAttribute(attributeName);\n return;\n }\n let formatted: string;\n if (typeof value === \"object\") {\n try {\n formatted = JSON.stringify(value);\n } catch {\n formatted = String(value);\n }\n } else {\n formatted = String(value);\n }\n element.setAttribute(attributeName, formatted);\n}\n","import { inSsr } from \"../config\";\nimport { IBindingInfo } from \"../binding/types\";\nimport { IApplyContext } from \"./types\";\n\nconst ssrWrappedNodes: WeakSet<Node> = new WeakSet();\n\nexport function applyChangeToText(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n // nodeValue は nullable DOMString(実ブラウザでは null / undefined とも空文字に\n // 正規化される)ため、比較前に同じ規則で文字列化する。生値のまま比較すると\n // 数値など非文字列値は常に不一致になり、同値でも毎回 DOM 書き込みが走る。\n // 注: happy-dom は undefined を \"undefined\" にする非準拠実装なので String() に\n // 頼らず明示的に \"\" へ正規化する。\n const text = newValue === null || newValue === undefined ? \"\" : String(newValue);\n if (binding.replaceNode.nodeValue !== text) {\n binding.replaceNode.nodeValue = text;\n }\n // SSR モード時: テキストノードの前後にコメントを挿入して境界を明示\n if (inSsr() && !ssrWrappedNodes.has(binding.replaceNode)) {\n ssrWrappedNodes.add(binding.replaceNode);\n const parentNode = binding.replaceNode.parentNode;\n if (parentNode) {\n const path = binding.statePathName;\n const startComment = document.createComment(`@@wcs-text-start:${path}`);\n const endComment = document.createComment(`@@wcs-text-end:${path}`);\n parentNode.insertBefore(startComment, binding.replaceNode);\n parentNode.insertBefore(endComment, binding.replaceNode.nextSibling);\n }\n }\n}\n","import { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\n/**\n * カスタム要素の state プロパティバインディング(`state[.sub]: path`)に対する\n * 適用のルート先(apply/applyChange.ts の resolveCustomElementApply)。\n *\n * v2 では state プロパティのバインディングは全てマウント(webComponent/mountScope.ts)で、\n * 配送は「翻訳されたバインディング+単一台帳+静的依存」が担う — 親→子の再読込\n * 通知チャネル(v1 の innerState への $postUpdate)はこの経路では何も運ぶものが無い。\n * 完了済みの (element, stateProp) への適用は意図的な no-op。\n *\n * 未完了(宣言前)の適用はここへ来ない(applyChangeToProperty の積み、または\n * skipPendingMountWrite — apply/applyChange.ts)。\n */\nexport function applyChangeToWebComponent(_binding: IBindingInfo, _context: IApplyContext, _newValue: unknown): void {\n // no-op(上記)\n return;\n}\n","import { getStateAddressByBindingInfo } from \"../binding/getStateAddressByBindingInfo\";\nimport { IBindingInfo } from \"../binding/types\";\nimport { INDEX_BY_INDEX_NAME } from \"../define\";\nimport { getIndexValueByLoopContext } from \"../list/getIndexValueByLoopContext\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { getByAddressSymbol } from \"../proxy/symbols\";\nimport { IStateProxy } from \"../proxy/types\";\nimport { raiseError } from \"../raiseError\";\n\nexport function getValue(state: IStateProxy, binding: IBindingInfo): any {\n const stateAddress = getStateAddressByBindingInfo(binding);\n if (stateAddress.pathInfo.path in INDEX_BY_INDEX_NAME) {\n const loopContext = getLoopContextByNode(binding.node);\n if (loopContext === null) {\n raiseError(`ListIndex not found for binding: ${binding.statePathName}`);\n }\n return getIndexValueByLoopContext(loopContext, stateAddress.pathInfo.path);\n } else {\n return state[getByAddressSymbol](stateAddress);\n }\n}\n","import { INDEX_BY_INDEX_NAME } from \"../define\";\nimport { wildcardScopeMessage } from \"../pathDiagnostics\";\nimport { raiseError } from \"../raiseError\";\nimport { ILoopContext } from \"./types\";\nimport { listIndexAtWildcard } from \"./wildcardLevel\";\n\n// indexName ... $1, $2, ...\nexport function getIndexValueByLoopContext(loopContext: ILoopContext, indexName: string): number | null {\n if (loopContext.listIndex === null) {\n raiseError(`ListIndex not found for loopContext:`);\n }\n const indexPos = INDEX_BY_INDEX_NAME[indexName];\n if (typeof indexPos === \"undefined\") {\n raiseError(`Invalid index name: ${indexName}`);\n }\n const listIndex = listIndexAtWildcard(loopContext.listIndex, indexPos, loopContext.pathInfo.wildcardCount);\n if (listIndex === null) {\n // 位置が範囲外 = `$2` を 1 段のループの中で読んだ、という取り違え。\n // 元の文面(`Index not found at position 1 for loopContext:`)は内部の言葉で、\n // 何段必要で何段あるのかが書かれていなかった。\n raiseError(wildcardScopeMessage(`\"${indexName}\"`, indexPos + 1, loopContext.pathInfo.wildcardCount));\n }\n return listIndex.index;\n}","import { getBindingSession } from \"../bindings/BindingSession.js\";\nimport { getDefinitionCoordinator } from \"../bindings/DefinitionCoordinator.js\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry.js\";\nimport { IBindingInfo } from \"../types.js\";\nimport { applyChangeFromBindings } from \"./applyChangeFromBindings.js\";\n\nconst scheduledBindings = new WeakSet<IBindingInfo>();\n\nfunction reportFailure(tagName: string, error: unknown): void {\n console.error(`[@wcstack/state] deferred apply failed for <${tagName}>.`, error);\n}\n\nexport function scheduleDeferredApply(binding: IBindingInfo, tagName: string): void {\n if (scheduledBindings.has(binding)) return;\n scheduledBindings.add(binding);\n\n const applyLatest = (): void => {\n scheduledBindings.delete(binding);\n const currentSession = getBindingSession(binding);\n if (currentSession !== null && !currentSession.shouldApplyState(binding)) {\n return;\n }\n applyChangeFromBindings([binding]);\n };\n const reject = (error: unknown): void => {\n scheduledBindings.delete(binding);\n reportFailure(tagName, error);\n };\n\n const session = getBindingSession(binding);\n if (session !== null) {\n const cancel = session.deferUntilDefined(binding.replaceNode, tagName, applyLatest, reject);\n if (!session.addTeardown(binding, () => {\n scheduledBindings.delete(binding);\n cancel();\n })) {\n scheduledBindings.delete(binding);\n cancel();\n }\n return;\n }\n\n // Compatibility fallback for direct applyChange() callers outside a session.\n const registry = getCustomElementRegistry(binding.replaceNode);\n if (registry === null) {\n scheduledBindings.delete(binding);\n reportFailure(tagName, new Error(\"CustomElementRegistry is unavailable.\"));\n return;\n }\n getDefinitionCoordinator(registry).wait(tagName, () => {\n if (!binding.replaceNode.isConnected) {\n scheduledBindings.delete(binding);\n return;\n }\n applyLatest();\n }, reject);\n}\n","import { getAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding.js\";\nimport { ATTR_NAMESPACE, CLASS_NAMESPACE, COMMAND_NAMESPACE, STYLE_NAMESPACE } from \"../define.js\";\nimport { getBindingSession, isWaitingDefinition } from \"../bindings/BindingSession.js\";\nimport { getCustomElement } from \"../getCustomElement.js\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry.js\";\nimport { raiseError } from \"../raiseError.js\";\nimport { getStateElement } from \"../stateElementByName.js\";\nimport { IBindingInfo } from \"../types.js\";\nimport { componentApplyHooks } from \"../core/componentApplyHooks.js\";\nimport { applyChangeToAttribute } from \"./applyChangeToAttribute.js\";\nimport { applyChangeToCheckbox } from \"./applyChangeToCheckbox.js\";\nimport { applyChangeToClass } from \"./applyChangeToClass.js\";\nimport { applyChangeToCommand } from \"./applyChangeToCommand.js\";\nimport { applyChangeToFor } from \"./applyChangeToFor.js\";\nimport { applyChangeToIf } from \"./applyChangeToIf.js\";\nimport { applyChangeToProperty } from \"./applyChangeToProperty.js\";\nimport { applyChangeToRadio } from \"./applyChangeToRadio.js\";\nimport { applyChangeToStyle } from \"./applyChangeToStyle.js\";\nimport { applyChangeToText } from \"./applyChangeToText.js\";\nimport { applyChangeToWebComponent } from \"./applyChangeToWebComponent.js\";\nimport { getFilteredValue } from \"./getFilteredValue.js\";\nimport { getValue } from \"./getValue.js\";\nimport { getRootNodeByFragment } from \"./rootNodeByFragment.js\";\nimport { scheduleDeferredApply } from \"./scheduleDeferredApply.js\";\nimport { ApplyChangeFn, IApplyContext } from \"./types.js\";\n\n// キーは define.ts の namespace 語彙定数(manifest.syntax.bindingTypes.propNamespaces と\n// 同一の正本)。集合の一致は __tests__/manifest.test.ts の drift テストが強制するため\n// export する(manifest エントリは DOM 非依存でこのファイルを import できない)。\nexport const applyChangeByFirstSegment: { readonly [key: string]: ApplyChangeFn } = Object.freeze({\n [CLASS_NAMESPACE]: applyChangeToClass,\n [ATTR_NAMESPACE]: applyChangeToAttribute,\n [STYLE_NAMESPACE]: applyChangeToStyle,\n [COMMAND_NAMESPACE]: applyChangeToCommand,\n});\n\nconst applyChangeByBindingType: { [key: string]: ApplyChangeFn } = {\n \"text\": applyChangeToText,\n \"for\": applyChangeToFor,\n \"if\": applyChangeToIf,\n \"else\": applyChangeToIf,\n \"elseif\": applyChangeToIf,\n \"radio\": applyChangeToRadio,\n \"checkbox\": applyChangeToCheckbox,\n};\n\nconst fnByBinding: WeakMap<IBindingInfo, ApplyChangeFn> = new WeakMap();\nconst deferredSelectBindingByBinding: WeakMap<IBindingInfo, boolean> = new WeakMap();\n\n// 未 define カスタム要素チェックの確定メモ。customTag が無い、または define 済みを\n// 一度確認したら以後は不変(define は不可逆)なので apply 毎の getCustomElement /\n// registry 照会を省略できる。scoped registry を導入する場合はこの不可逆前提を再検討。\nconst definedApplyVerifiedByBinding: WeakMap<IBindingInfo, boolean> = new WeakMap();\n\n/**\n * 宣言済みマウントの完了前の初期適用は書かない。子が完了すればマウント経由で\n * ライブに読むので、ここで親の値を書く意味は無い(書くと害がある —\n * webComponent/completeWebComponent.ts の宣言台帳を参照 — core/componentApplyHooks.ts 越しに引く)。v2 では部分規則\n *(`state.name: user.name`)にも同じ原則を適用する: 積みの上書きが作者の既定値を\n * 汚すと、厳格 R1(作者の own data key は私有・D19)の privateSnapshot が親の値で\n * 汚染される。積みが要るのは**未宣言**(`<wcs-state bind-component>` がまだ来ていない\n * 非同期定義や、そもそも bind-component の無い素のプロパティパス配線)だけ。\n */\nfunction skipPendingMountWrite(): void {}\n\n/**\n * カスタム要素へのプロパティバインディングの適用関数を決める。\n *\n * - 完了済み(bindWebComponent が公開プロパティを差し替え終えた)→ 値を運ばない\n * 再読込通知(applyChangeToWebComponent)。1 セグメント(`state: user`)も含む —\n * 残余が空なら「子の登録済みパス全部を読み直せ」の意味(ルート規則。\n * docs/state-mount-design.md §3-2 / impl-plan P1-2)\n * - 未完了だが `<wcs-state bind-component>` が宣言済み → 今回は\n * 書かない(skipPendingMountWrite — 部分規則も含む、上記)\n * - それ以外(未宣言)→ 素のプロパティ書き込み(積み)\n *\n * 以前は 1 セグメントを通知チャネルから除いていた(残余が空だと applyChangeToWebComponent\n * が raiseError し、updater の drain が捕まえないので同じバッチの無関係な更新まで\n * 巻き添えにした)。残余空がルート規則の意味を持った今、その除外は要らない。\n */\nfunction resolveCustomElementApply(binding: IBindingInfo): ApplyChangeFn {\n // 完了・宣言の台帳は bind-component の機能が受け口に置く。置かれていなければ素の書き込み\n const hooks = componentApplyHooks;\n if (hooks !== null) {\n const element = binding.replaceNode as Element;\n const stateProp = binding.propSegments[0];\n if (hooks.isComplete(element, stateProp)) {\n return applyChangeToWebComponent;\n }\n if (hooks.isDeclared(element, stateProp)) {\n return skipPendingMountWrite;\n }\n }\n return applyChangeToProperty;\n}\n\nfunction _applyChange(binding: IBindingInfo, context: IApplyContext): void {\n applyValueToBinding(binding, context, getValue(context.state, binding));\n}\n\n/**\n * 値が既に手元にあるときの `_applyChange` の後半(フィルタ適用 → DOM 書き込み)。\n * プラン初期描画(structural/activateContent.ts、設計 R2)が、行オブジェクトから直に\n * 読んだ素の値を渡すために使う。値の出どころ以外は通常の適用と同じ経路。\n */\nexport function applyValueToBinding(binding: IBindingInfo, context: IApplyContext, value: unknown): void {\n const filteredValue = getFilteredValue(value, binding.outFilters);\n\n if (deferredSelectBindingByBinding.get(binding) === true) {\n context.deferredSelectBindings.push({ binding, value: filteredValue, stateElement: context.stateElement });\n return;\n }\n let fn = fnByBinding.get(binding);\n if (typeof fn !== 'undefined') {\n fn(binding, context, filteredValue);\n return;\n }\n if (fnByBinding.has(binding)) {\n fn = resolveCustomElementApply(binding);\n if (fn === applyChangeToWebComponent) {\n fnByBinding.set(binding, fn); // 確定したのでキャッシュ\n }\n fn(binding, context, filteredValue);\n return;\n }\n\n fn = applyChangeByBindingType[binding.bindingType];\n if (typeof fn === 'undefined') {\n const firstSegment = binding.propSegments[0];\n fn = applyChangeByFirstSegment[firstSegment];\n fnByBinding.set(binding, fn);\n if (typeof fn === 'undefined') {\n const customTag = getCustomElement(binding.replaceNode);\n if (customTag) {\n fn = resolveCustomElementApply(binding);\n if (fn === applyChangeToWebComponent) {\n fnByBinding.set(binding, fn); // 確定したのでキャッシュ\n }\n } else {\n fn = applyChangeToProperty;\n fnByBinding.set(binding, fn);\n }\n }\n }\n if (fn === applyChangeToProperty) {\n const element = binding.node as Element;\n if (element.tagName === 'SELECT') {\n const propName = binding.propSegments[0];\n if (propName === 'value' || propName === 'selectedIndex') {\n context.deferredSelectBindings.push({ binding, value: filteredValue, stateElement: context.stateElement });\n deferredSelectBindingByBinding.set(binding, true);\n return;\n }\n }\n }\n fn(binding, context, filteredValue);\n}\n\nexport function applyChange(binding: IBindingInfo, context: IApplyContext): void {\n if (context.appliedBindingSet.has(binding)) {\n return;\n }\n context.appliedBindingSet.add(binding);\n // $updatedCallback が定義されていない state では、更新アドレスの集計自体が\n // 不要(drain 終端の呼び出しごと省略される)。大量バインディング適用時の\n // Set 蓄積を避ける。undefined(テスト用モック等)は従来通り集計する。\n if (context.stateElement.hasUpdatedCallback !== false) {\n const absAddress = getAbsoluteStateAddressByBinding(binding);\n if (context.updatedAbsAddressSetByStateElement.has(context.stateElement)) {\n const addressSet = context.updatedAbsAddressSetByStateElement.get(context.stateElement)!;\n addressSet.add(absAddress);\n } else {\n context.updatedAbsAddressSetByStateElement.set(context.stateElement, new Set([\n absAddress\n ]));\n }\n }\n const bindingSession = getBindingSession(binding);\n if (bindingSession !== null && !bindingSession.shouldApplyState(binding)) {\n return;\n }\n if (binding.bindingType === \"event\") {\n return;\n }\n if (definedApplyVerifiedByBinding.get(binding) !== true) {\n const customTag = getCustomElement(binding.replaceNode);\n if (customTag) {\n // 定義済みに見えても、束縛がまだ定義を待っている(two-way・イベントも初期同期もまだ)なら同じく待つ —\n // 行の中身は fragment の中で「未定義」と判断して待ちを並べ、スコープ付き registry の木へ差し込んだ\n // 時点で upgrade される。ここで書くと初期同期より先に state の値が要素へ入る(#357)\n if (getCustomElementRegistry(binding.replaceNode)?.get(customTag) === undefined || isWaitingDefinition(binding)) {\n // 未 define のカスタム要素へは今は適用できない(accessor 未確立の要素に\n // 素の own property を書くと upgrade 後に class accessor を隠してしまう)。\n // whenDefined 後に最新 state 値で再適用する(two-way attach / deferred\n // spread と対称。docs/state-binding-init-races.md §2)。\n scheduleDeferredApply(binding, customTag);\n return;\n }\n }\n // customTag 無し or define 済み確定 → 以後この検査を省略(不可逆)\n definedApplyVerifiedByBinding.set(binding, true);\n }\n // applyChangeFromBindings のグループ化ループが解決済みルートの一致を検証済みの\n // 場合、getRootNode の再解決(native 呼び出し)を省略できる。activateContent 経由\n // (フラグメント内の新規 content)も、フラグメントは setRootNodeByFragment で\n // context.rootNode に解決されるため同じ不変条件が成り立つ。\n if (context.sameRootVerified === true) {\n _applyChange(binding, context);\n return;\n }\n let rootNode: Node | null = binding.replaceNode.getRootNode() as Node;\n if (rootNode instanceof DocumentFragment && !(rootNode instanceof ShadowRoot)) {\n rootNode = getRootNodeByFragment(rootNode);\n if (rootNode === null) {\n raiseError(`Root node for fragment not found for binding.`);\n }\n }\n if (rootNode !== context.rootNode) {\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n stateElement.createState(\"readonly\", (targetState) => {\n const newContext = {\n rootNode: rootNode,\n stateElement: stateElement,\n state: targetState,\n appliedBindingSet: context.appliedBindingSet,\n newListValueByAbsAddress: context.newListValueByAbsAddress,\n updatedAbsAddressSetByStateElement: context.updatedAbsAddressSetByStateElement,\n deferredSelectBindings: context.deferredSelectBindings,\n }\n _applyChange(binding, newContext);\n });\n } else {\n _applyChange(binding, context);\n }\n}\n","import { raiseError } from \"../raiseError\";\nimport { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\nexport function applyChangeToClass(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const element = binding.node as Element;\n const className = binding.propSegments[1];\n // 「値が無い」(undefined / null)はクラスを外す — 要件 B8 の `attr.` と同じ語彙。\n // throw にしていると、使い回した行に値の無い行オブジェクトが来たときに**行ごと**描かれなかった\n // (`attr.title:` は属性が消えるだけで済んでいた)\n if (newValue === undefined || newValue === null) {\n element.classList.toggle(className, false);\n return;\n }\n // truthy な非 boolean(`class.on: label` に文字列が来る等)は今も throw する。クラスの束縛は\n // 真偽の切り替えなので、truthy な文字列は意図より書き間違いである方がずっと多い。ただし\n // **行の中で throw すると行ごと描かれない**という失敗モードは残るので、この取り違えは\n // 静的検出(`@wcstack/lint` / VS Code 拡張のパス型推論)で前に倒す方針。\n // 作者が truthy 扱いを意図しているなら `class.on: flag|truthy` と書く(README の B8 節)。\n if (typeof newValue !== 'boolean') {\n raiseError(`Invalid value for class application: expected boolean, got ${typeof newValue}. Write \"|truthy\" if you mean to coerce.`);\n }\n element.classList.toggle(className, newValue as boolean);\n}","import { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\nexport function applyChangeToAttribute(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const element = binding.node as Element;\n const attrName = binding.propSegments[1];\n // 値が無い(undefined / null)属性は削除する(要件 B8)。以前は文字列 \"undefined\" / \"null\" を書いていた\n if (newValue === undefined || newValue === null) {\n if (element.hasAttribute(attrName)) {\n element.removeAttribute(attrName);\n }\n return;\n }\n // 属性の値は常に文字列なので、比較の前に同じ規則で文字列化する(`applyChangeToText` と同じ)。\n // 生値のまま比べると数値・真偽値を束ねた属性は同値でも毎回 setAttribute が走っていた\n const text = String(newValue);\n if (element.getAttribute(attrName) !== text) {\n element.setAttribute(attrName, text);\n }\n}\n","import { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\nexport function applyChangeToStyle(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const styleName = binding.propSegments[1];\n const style = (binding.node as HTMLElement).style;\n // 値が無い(undefined / null)スタイルは消す(要件 B8)\n if (newValue === undefined || newValue === null) {\n newValue = \"\";\n }\n const currentValue = (style as any)[styleName];\n if (currentValue !== newValue) {\n (style as any)[styleName] = newValue;\n }\n}\n","import { IBindingInfo } from \"../types\";\nimport { getFilteredValue } from \"./getFilteredValue\";\nimport { IApplyContext } from \"./types\";\n\nexport function applyChangeToRadio(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const element = binding.node as HTMLInputElement;\n const elementValue = element.value;\n const elementFilteredValue = getFilteredValue(elementValue, binding.inFilters);\n element.checked = newValue === elementFilteredValue;\n}\n","import { IAbsoluteStateAddress } from \"../address/types\";\nimport { IStateElement } from \"../components/types\";\nimport { config } from \"../config\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { setLastListValueByAbsoluteStateAddress } from \"../list/lastListValueByAbsoluteStateAddress\";\nimport { setStateListBaseline } from \"../list/stateListBaseline\";\nimport { errorCallbackSymbol, updatedCallbackSymbol } from \"../proxy/symbols\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IPropagationContext } from \"../propagation/types\";\nimport { IBindingErrorInfo, IBindingInfo } from \"../types\";\nimport { applyChange } from \"./applyChange\";\nimport { applyChangeToProperty } from \"./applyChangeToProperty\";\nimport { getRootNodeByFragment } from \"./rootNodeByFragment\";\nimport { IApplyContext, IDeferredSelectBinding } from \"./types\";\n\n/** $errorCallback へ配送する失敗 1 件(drain 末尾でまとめて配送する) */\ninterface IBindingFailure {\n readonly error: unknown;\n readonly info: IBindingErrorInfo;\n}\n\n/**\n * バインディング 1 本の適用失敗を報告する(握り潰しではない)。\n *\n * `console.error` だけだと devtools からは「静かに握られた失敗」が見えないため、\n * 同じ地点から sink にも流す(`state:watch-error` と同じ位置づけ)。\n * 値と DOM は巻き戻さない — 伝播 hop 上限超過・watch 連鎖打ち切りと同じ姿勢。\n *\n * state が `$errorCallback` を宣言していれば、console.error の代わりにそこへ配送する\n * (作者が報告を引き取った。ページ内で受けるための口)。配送は batch の末尾 —\n * $updatedCallback と同じ位置 — にまとめる。devtools sink へは宣言の有無に関わらず流す。\n */\nfunction reportBindingApplyError(\n binding: IBindingInfo,\n error: unknown,\n stateElement: IStateElement | null,\n failuresByStateElement: Map<IStateElement, IBindingFailure[]>,\n): void {\n const handled = stateElement !== null && stateElement.hasErrorCallback === true;\n if (handled) {\n const info: IBindingErrorInfo = {\n path: binding.statePathName,\n bindingType: binding.bindingType,\n node: binding.node,\n };\n const failures = failuresByStateElement.get(stateElement);\n if (failures === undefined) {\n failuresByStateElement.set(stateElement, [{ error, info }]);\n } else {\n failures.push({ error, info });\n }\n } else {\n console.error(\n `[@wcstack/state] binding \"${binding.bindingType}: ${binding.statePathName}\" failed to apply; ` +\n `the rest of this batch continues.`,\n { node: binding.node, error },\n );\n }\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"state:binding-apply-error\",\n path: binding.statePathName,\n bindingType: binding.bindingType,\n error,\n });\n }\n}\n\n/**\n * バインディング情報の配列を処理し、各バインディングに対して状態の変更を適用する。\n *\n * 2フェーズで処理:\n * Phase 1: 構造的更新(for/if) + 値更新(select以外) — select.value/selectedIndex は遅延収集\n * Phase 2: 遅延されたselect.value/selectedIndex を適用(option要素の生成後)\n *\n * 最適化のため、以下のグループ化を行う:\n * 同じ rootNode を持つバインディングをグループ化 → createState の呼び出しを削減\n *\n * `options.updatedCallback === false` は `$updatedCallback` を呼ばない。唯一の呼び手は再セットの\n * 再適用(apply/reapplyStateBindings.ts)で、再セットは書き込みではないため。`$errorCallback` は\n * 適用の失敗の報告なので、どの経路でも配送する。\n */\nexport function applyChangeFromBindings(\n bindings: IBindingInfo[],\n propagationContextByBinding?: ReadonlyMap<IBindingInfo, IPropagationContext | null>,\n options?: { readonly updatedCallback?: boolean },\n): void {\n let bindingIndex = 0;\n const appliedBindingSet: Set<IBindingInfo> = new Set();\n const newListValueByAbsAddress: Map<IAbsoluteStateAddress, readonly unknown[]> = new Map();\n const updatedAbsAddressSetByStateElement: Map<IStateElement, Set<IAbsoluteStateAddress>> = new Map();\n const deferredSelectBindings: IDeferredSelectBinding[] = [];\n const failuresByStateElement: Map<IStateElement, IBindingFailure[]> = new Map();\n\n // Phase 1: 構造的更新 + 値更新(select.value/selectedIndex は遅延)\n while(bindingIndex < bindings.length) {\n let binding = bindings[bindingIndex];\n if (binding.replaceNode.isConnected === false) {\n // 切断されているバインディングは無視、本来は事前に除去されているはず\n if (config.debug) {\n console.log(`applyChangeFromBindings: skip disconnected binding: ${binding.bindingType} ${binding.statePathName} on ${binding.node.nodeName}`, binding);\n }\n bindingIndex++;\n continue;\n }\n let rootNode: Node | null = binding.replaceNode.getRootNode() as Node;\n if (rootNode instanceof DocumentFragment && !(rootNode instanceof ShadowRoot)) {\n rootNode = getRootNodeByFragment(rootNode);\n if (rootNode === null) {\n raiseError(`Root node for fragment not found for binding.`);\n }\n }\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n\n stateElement.createState(\"readonly\", (state) => {\n const context: IApplyContext = {\n rootNode: rootNode,\n stateElement: stateElement,\n state: state,\n appliedBindingSet: appliedBindingSet,\n newListValueByAbsAddress: newListValueByAbsAddress,\n updatedAbsAddressSetByStateElement: updatedAbsAddressSetByStateElement,\n deferredSelectBindings: deferredSelectBindings,\n // グループ内の binding は下の do/while が「解決済みルート === rootNode」を\n // 検証してから applyChange に渡す(applyChange 側の getRootNode 省略の根拠)\n sameRootVerified: true,\n propagationContextByBinding: propagationContextByBinding,\n };\n\n do {\n // 1 本の失敗を 1 本に閉じ込める(§ エラー隔離)。隔離しないと、stale な\n // アドレスを読んだ 1 本の throw がバッチの残り・$updatedCallback・drain\n // リスナー($watch / $streams restart)まで道連れにし、「値は新しいのに\n // DOM は途中まで」という再現困難な半端状態を作る。\n try {\n applyChange(binding, context);\n } catch (error) {\n reportBindingApplyError(binding, error, stateElement, failuresByStateElement);\n }\n bindingIndex++;\n\n const nextBindingInfo: IBindingInfo | undefined = bindings[bindingIndex];\n if (!nextBindingInfo) break; // 終端に到達\n const nextRootNode = nextBindingInfo.replaceNode.getRootNode() as Node;\n if (nextRootNode !== context.rootNode) break; // ルートが変わった\n binding = nextBindingInfo;\n } while(true); // eslint-disable-line no-constant-condition\n });\n }\n // Phase 2: 遅延されたselect.value/selectedIndex を適用\n // applyChangeToProperty は propagationContextByBinding 以外の context を\n // 参照しないため、遅延分は最小 context を渡す\n for (const { binding, value, stateElement } of deferredSelectBindings) {\n try {\n applyChangeToProperty(binding, { propagationContextByBinding } as unknown as IApplyContext, value);\n } catch (error) {\n reportBindingApplyError(binding, error, stateElement ?? null, failuresByStateElement);\n }\n }\n\n for(const [ absAddress, newListValue ] of newListValueByAbsAddress.entries()) {\n setLastListValueByAbsoluteStateAddress(absAddress, newListValue);\n // 描画の基準とは別に、state 側の基準(読み・依存ウォークの共有正本)も進める。\n // 初回描画はどの書き込みも経ていないので、ここで観測しておかないと最初の構造\n // 書き込みで基準が空のまま ListIndex を鋳造してしまう(E1)。\n setStateListBaseline(absAddress, newListValue);\n }\n if (options?.updatedCallback !== false) {\n for(const [ stateElement, absAddressSet ] of updatedAbsAddressSetByStateElement.entries()) {\n stateElement.createState(\"writable\", (state) => {\n state[updatedCallbackSymbol](Array.from(absAddressSet));\n });\n }\n }\n // $errorCallback の配送。$updatedCallback の後・失敗した本数ぶん・this は writable proxy。\n // callback 自身の throw は隔離する — 1 件の報告失敗が残りの報告と drain を道連れにしない\n for (const [ stateElement, failures ] of failuresByStateElement.entries()) {\n stateElement.createState(\"writable\", (state) => {\n for (const { error, info } of failures) {\n try {\n state[errorCallbackSymbol](error, info);\n } catch (callbackError) {\n console.error(\n `[@wcstack/state] $errorCallback threw while handling the failure of binding \"${info.bindingType}: ${info.path}\".`,\n { error: callbackError, original: error, node: info.node },\n );\n }\n }\n });\n }\n}\n","import { isLightDomMappedStateElement } from \"./bindings/lightDomComponentScope\";\nimport { State } from \"./components/State\";\nimport { IStateElement } from \"./components/types\";\nimport { config } from \"./config\";\nimport { getCustomElementRegistry } from \"./platform/customElementRegistry\";\nimport { raiseError } from \"./raiseError\";\n\nexport async function waitForStateInitialize(root: Document | Element | DocumentFragment): Promise<void> {\n const elements = root.querySelectorAll(config.tagNames.state);\n const promises: Promise<void>[] = [];\n const registry = getCustomElementRegistry(root);\n if (registry === null) {\n // null レジストリのサブツリーでは <wcs-state> が upgrade されないので\n // initializePromise が生えず、待っても永久に初期化されない。\n raiseError(`CustomElementRegistry is unavailable for <${config.tagNames.state}>.`);\n }\n await registry.whenDefined(config.tagNames.state);\n for(const element of elements) {\n // Light DOM の mapped コンポーネントの state は待たない。それはこの root の\n // バインディングが張られてからでないと初期化できず(自分を束ねるホスト binding を\n // 待つ)、ここで待つと循環する(§1.13)。Shadow DOM 形では別 rootNode にいるので\n // そもそもこの集合に現れず、plain 形は循環しないので従来どおり待つ。\n if (isLightDomMappedStateElement(element)) {\n continue;\n }\n const stateElement = element as State as IStateElement;\n promises.push(stateElement.initializePromise);\n }\n await Promise.all(promises);\n}\n","import { waitInitializeBinding } from \"./bindings/initializeBindingPromiseByNode\";\nimport { initializeBindings } from \"./bindings/initializeBindings\";\nimport { config } from \"./config\";\nimport { convertMustacheToComments } from \"./mustache/convertMustacheToComments\";\nimport { collectStructuralFragments } from \"./structural/collectStructuralFragments\";\nimport { waitForStateInitialize } from \"./waitForStateInitialize\";\n\nexport async function buildBindings(root: Document | ShadowRoot): Promise<void> {\n if (root === document) {\n // document配下のwcs-stateの初期化(connectedCallbackの完了)を待機する\n await waitForStateInitialize(document);\n // baindingを取得して、初期値をセットする\n convertMustacheToComments(document);\n collectStructuralFragments(document, document);\n initializeBindings(document.body, null);\n } else {\n const shadowRoot = root as ShadowRoot;\n if (shadowRoot.host.hasAttribute(config.bindAttributeName)) {\n // data-wcsを持つWebComponentは、WebComponentのbindingが完了するまで待機する。\n await waitInitializeBinding(shadowRoot.host);\n }\n // shadowRoot配下のwcs-stateの初期化(connectedCallbackの完了)を待機する\n await waitForStateInitialize(shadowRoot);\n // baindingを取得して、初期値をセットする\n convertMustacheToComments(shadowRoot);\n collectStructuralFragments(shadowRoot, shadowRoot);\n initializeBindings(shadowRoot, null);\n }\n}\n","/**\n * core/featureEntries.ts — 受け口の機能名 → 利用者が入れるエントリ(設計案 §3 H5・§4)。\n *\n * barrier に当たったページが要るのは「どの import を足すか」であって内部の機能名ではない。\n * 内部では別々の機能(watch / scan / stream)が 1 つのエントリ(temporal)に載るので、\n * 対応表は 1 箇所に置き、3 つの barrier(addressHooks・lifecycleHooks・ssrHooks)が共有する。\n */\n/**\n * 鍵は `registerFeatureHooks` / `registerDeclarationHooks` / `requireLifecycleFeature` が使う\n * **実際の機能名**でなければならない(`__tests__/core.featureEntries.test.ts` が固定する)。\n * かつて `stream` と書かれていたが登録名は `streams` で、`@wcstack/state/features/streams`\n * という存在しないエントリを案内していた。\n */\nconst ENTRY_BY_FEATURE: Record<string, string> = {\n watch: \"temporal\",\n scan: \"temporal\",\n streams: \"temporal\",\n scopes: \"scopes\",\n dcc: \"scopes\",\n recursion: \"recursion\",\n ssr: \"ssr\",\n devtools: \"devtools\",\n};\n\n/** 未 install の機能を宣言が要求したときの文言(readiness barrier、H5 / D13) */\nexport function featureNotInstalledMessage(feature: string, declaration: string): string {\n const entry = ENTRY_BY_FEATURE[feature] ?? feature;\n return `[wcs/feature-not-installed] ${declaration} needs the \"${feature}\" feature: ` +\n `install it with installFeatures([...]) from \"@wcstack/state/features/${entry}\" before the state is defined.`;\n}\n","/**\n * core/ssrHooks.ts — SSR(サーバー描画とハイドレーション)の受け口(設計案 H8、S5)。\n *\n * core が持つのは SSR **モード**(config の `inSsr()` と apply 側が書く `@@wcs-*` コメント)と\n * `enable-ssr` 属性の判定だけ。`<wcs-ssr>` の読み書きとハイドレーションの実装は ssr 機能\n * (src/ssr/)が install で置く。core から機能への辺はこの 1 本の受け口に畳まれている。\n *\n * 受け口(core 側の呼び出し点):\n * hydrate ルート登録(stateElementByName)で、`enable-ssr` のクライアント側\n * loadState `_initialize` の冒頭で、`<wcs-ssr>` に載った state データを読む\n * emitSnapshot サーバー側の `connectedCallback` の末尾で `<wcs-ssr>` を書き出す\n */\nimport { raiseError } from \"../raiseError\";\nimport { featureNotInstalledMessage } from \"./featureEntries\";\n\nexport interface ISsrHooks {\n /** クライアント: SSR 出力からバインディングを起こす。偽なら core が通常の構築へ倒す */\n hydrate(root: Document): Promise<boolean>;\n /** クライアント: この要素の前に置かれた `<wcs-ssr>` の state データ(無ければ null) */\n loadState(element: Element): Record<string, any> | null;\n /** サーバー: バインディング完了後に `<wcs-ssr>` を書き出す */\n emitSnapshot(element: Element): Promise<void>;\n}\n\n/** 置かれていなければ null。`enable-ssr` の無いページはここを一度も見ない */\nexport let ssrHooks: ISsrHooks | null = null;\n\n/** 機能の install が呼ぶ(冪等 — 置き換え) */\nexport function setSsrHooks(hooks: ISsrHooks | null): void {\n ssrHooks = hooks;\n}\n\n/**\n * `enable-ssr` が SSR 機能を要求した: 未 install なら名指しで throw する(readiness barrier、H5 / D13)。\n * full / auto は `bootstrapState()` が install するので起きない。\n */\nexport function requireSsrHooks(declaration: string): ISsrHooks {\n if (ssrHooks === null) {\n raiseError(featureNotInstalledMessage(\"ssr\", declaration));\n }\n return ssrHooks;\n}\n","import { buildBindings } from \"./buildBindings\";\nimport { requireSsrHooks } from \"./core/ssrHooks\";\nimport { IStateElement } from \"./components/types\";\nimport { config, inSsr } from \"./config\";\nimport { raiseError } from \"./raiseError\";\nimport { devtoolsSink } from \"./platform/devtoolsSink\";\nimport { drainPendingBinds } from \"./bindings/binder\";\n\n// v2: 1 rootNode 1 ツリー(P3-6)。名前次元は無い — 追加の state はマウント(mount= / bind-component)で載る。\nconst stateElementByNode: WeakMap<Node, IStateElement> = new WeakMap();\nconst bindingsReadyByNode: WeakMap<Node, Promise<void>> = new WeakMap();\n\n// devtools 用の列挙可能な登録簿(protocol §4.1 — 唯一の常時 ON 台帳)。\n// サイズは <wcs-state> 要素数に拘束され、unregister(disconnectedCallback)で\n// 必ず削除されるためリークしない。\nconst liveStateElements: Set<IStateElement> = new Set();\n\n// ルートの登録を待つ機能(先に接続されたボリュームの引き取り — webComponent/volume.ts)の受け口。\n// 登録は 1 ルートにつき 1 回なので大域の listener 列で足りる(hot path には載らない)\ntype StateElementRegisteredListener = (rootNode: Node, element: IStateElement) => void;\nconst registeredListeners: StateElementRegisteredListener[] = [];\n\nexport function onStateElementRegistered(listener: StateElementRegisteredListener): void {\n if (!registeredListeners.includes(listener)) {\n registeredListeners.push(listener);\n }\n}\n\nexport function getLiveStateElements(): ReadonlySet<IStateElement> {\n return liveStateElements;\n}\n\nexport function getStateElement(rootNode: Node): IStateElement | null {\n return stateElementByNode.get(rootNode) ?? null;\n}\n\n/**\n * 指定された rootNode のバインディング初期化が完了するまで待機する Promise を返す。\n */\nexport function getBindingsReady(rootNode: Node): Promise<void> {\n return bindingsReadyByNode.get(rootNode) ?? Promise.resolve();\n}\n\n/**\n * この rootNode ではバインド構築が起きない、と確定する(#257)。\n *\n * ルートの state 要素が初期化に失敗すると `setStateElement` に到達しないので、\n * 台帳はエントリが無いまま残る。上の既定(未登録 = 即時解決)は「まだ登録されて\n * いない」と「バインドを張り終えた」を区別しないため、@wcstack/server の\n * `waitForReady` は**バインディングが 1 本も無いページ**を ready と報告してしまう。\n * 失敗した rootNode には reject 済みの ready を置き、待ち手へ同じ診断を届ける。\n *\n * 呼び手は State の `_failInitializeLoudly` ただ 1 つで、そちらが「この rootNode に\n * 生きたルートが居ない」ことを確かめてから呼ぶ(2 本目の `<wcs-state>` が落ちても\n * 1 本目の ready は壊さない)。\n */\nexport function markBindingsUnavailable(rootNode: Node, error: unknown): void {\n const failed = Promise.reject(error);\n // reject と同じティックで handled を立てる(getBindingsReady を誰も呼ばない\n // ページで unhandled rejection にしないため)。await した側は従来どおり受け取る\n failed.catch(() => undefined);\n bindingsReadyByNode.set(rootNode, failed);\n}\n\nconst bindingsBuiltRoots: WeakSet<Node> = new WeakSet();\n\n/**\n * マウントされたスコープ(コンポーネントの ShadowRoot)に、**親の** state element を\n * 別名として載せる(Phase 2・impl-plan §3-0 の 2)。\n *\n * `getRootNode()` で state element を解決する全てのサイト\n * (getAbsoluteStateAddressByBinding / applyChange / applyChangeFromBindings /\n * fragmentInfoByUUID)が、この 1 エントリで無改造のまま親ツリーに到達する。\n * `setStateElement` と違い、初回登録の副作用(buildBindings の起動・\n * liveStateElements・devtools イベント)は持たない — マウントスコープの構築は\n * webComponent/mountScope.ts が自前で行う。\n */\nexport function setStateElementAlias(rootNode: Node, element: IStateElement): void {\n const existing = stateElementByNode.get(rootNode);\n if (typeof existing !== \"undefined\") {\n // 再初期化(connectedCallback で shadow を張り直すコンポーネントの再接続)は\n // 同じ親を指し直すだけなので冪等。別要素への付け替えは設定ミス\n if (existing === element) {\n return;\n }\n raiseError(`A state tree is already registered on this root.`);\n }\n stateElementByNode.set(rootNode, element);\n}\n\n/**\n * マウントされたスコープの ready を登録する(`getBindingsReady(childShadow)` の互換面)。\n * 完了で binder の `areBindingsBuilt` も真にする。\n */\nexport function setBindingsReadyForScope(rootNode: Node, ready: Promise<void>): void {\n bindingsReadyByNode.set(rootNode, ready);\n ready.then(() => markBindingsBuilt(rootNode), () => undefined);\n}\n\n/**\n * この rootNode の初期バインド構築が完了しているか。\n *\n * binder プロトコル(`bind()`)が使う。router の `<wcs-head>` はクローンを\n * `connectedCallback` の中で head へ入れるので、**state が最初の走査を終える前**に\n * bind を求めてくる。そこで同期に束ねても state 要素の初期化が済んでおらず、\n * 結果は空のままになる。完了までは binder 側で保留する。\n *\n * 「まだ登録も済んでいない」と「もう構築が終わった」を取り違えないよう、判定は\n * 完了の側で持つ。<wcs-state> の登録は connectedCallback の await より後に起きるので、\n * 「エントリの有無」で進行中かを測ると読み込み順によって逆の答えを返す。\n */\nexport function areBindingsBuilt(rootNode: Node): boolean {\n return bindingsBuiltRoots.has(rootNode);\n}\n\nfunction markBindingsBuilt(rootNode: Node): void {\n bindingsBuiltRoots.add(rootNode);\n}\n\nexport function setStateElement(rootNode: Node, element: IStateElement | null): void {\n\n const existing = stateElementByNode.get(rootNode);\n\n if (element === null) {\n // 削除の場合、登録が無ければ何もしない\n if (existing === undefined) {\n return;\n }\n stateElementByNode.delete(rootNode);\n liveStateElements.delete(existing);\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:element-unregistered\", rootNode, element: existing });\n }\n if (config.debug) {\n console.debug(`State element unregistered`);\n }\n } else {\n // 登録の場合\n if (existing === element) {\n // 同じ要素の再登録は冪等(setStateElementAlias と同じ規範)。ロード完了前の\n // remove → append(DOM の移動・行プールの張り直し・shadow の組み直し)は\n // `_initialize` を 2 本同時に走らせるので、後から登録に来たほうが**自分自身**を\n // 「2 本目の <wcs-state>」と誤診する。DOM の移動は正常な操作であり、拒否すると\n // 健全なページの connectedCallbackPromise が reject される(#257)。\n // 切断時に登録を解除する案では直らない — 実測で、切断の時点ではまだ何も\n // 登録されていない(登録は進行中の `_initialize` の続きで起きる)。\n return;\n }\n if (existing === undefined) {\n // 初めてルートノードに登録する場合\n // enable-ssr 属性があり、サーバーサイドでない場合はハイドレーション\n const enableSsr = !inSsr() && (element as unknown as Element).hasAttribute?.('enable-ssr');\n // instanceof ではなく constructor.name で判定するのは意図的。SSR では\n // @wcstack/server の installGlobals が happy-dom の一部だけを globalThis に載せるが、\n // そのリスト(GLOBALS_KEYS)に `Document` は入っていない。Node にも `Document` は\n // 無いので `rootNode instanceof Document` は ReferenceError になる。\n // `ShadowRoot` はリストに含まれるため他所では instanceof を使っている\n // (docs/architecture-hardening/15-state-component-mechanism-consistency.md §3.3)。\n // reject を配管しないと、バインディング初期化中の例外は unhandled rejection として\n // 漏れるだけで ready が永久に未解決のまま残り、await getBindingsReady() の先が\n // 無言でハングする(docs/state-bind-component-nested-for-design.md §8.2)。\n if (rootNode.constructor.name === 'HTMLDocument' || rootNode.constructor.name === 'Document') {\n const ready = new Promise<void>((resolve, reject) => {\n queueMicrotask(async () => {\n try {\n if (enableSsr) {\n // ハイドレーションは SSR 機能(ssr/hydrateBindings.ts)。未 install なら名指しで落とす(H5 / D13)\n const success = await requireSsrHooks(`the \"enable-ssr\" attribute`).hydrate(rootNode as Document);\n if (!success) {\n await buildBindings(rootNode as Document);\n }\n } else {\n await buildBindings(rootNode as Document);\n }\n markBindingsBuilt(rootNode);\n // binder が居ない時点で差し出されたサブツリーを引き取る。ここが\n // 「state が確実に居る」最初の瞬間で、router の auto バンドルが\n // state のそれより先に走る順序を吸収できる唯一の場所である。\n drainPendingBinds();\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n });\n bindingsReadyByNode.set(rootNode, ready);\n } else if (rootNode.constructor.name === 'ShadowRoot') {\n const ready = new Promise<void>((resolve, reject) => {\n queueMicrotask(async () => {\n try {\n await buildBindings(rootNode as ShadowRoot);\n markBindingsBuilt(rootNode);\n // binder が居ない時点で差し出されたサブツリーを引き取る。ここが\n // 「state が確実に居る」最初の瞬間で、router の auto バンドルが\n // state のそれより先に走る順序を吸収できる唯一の場所である。\n drainPendingBinds();\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n });\n bindingsReadyByNode.set(rootNode, ready);\n }\n }\n if (existing !== undefined) {\n // v2 は 1 rootNode 1 ツリー。2 つ目の <wcs-state> は設定エラー — 追加の状態は\n // マウント(mount= / ホスト配線の bind-component)でツリーに載せる\n // 文言は実測のゾンビの姿に合わせる(#257 第 3 ラウンド): 2 本目は state を\n // 組み上げたまま**登録されない**。データもトークンも $on の購読も生きているのに\n // 誰もバインドしておらず、_initialized が false なので切断時の後始末も走らない\n raiseError(\n `A state tree is already registered on this root — one <wcs-state> per root in v2. ` +\n `This second element stays unregistered: it keeps the state it loaded and its ` +\n `declarations stay live, but nothing binds to it and disconnecting it runs no ` +\n `cleanup — remove it. Mount additional states onto the tree instead: ` +\n `<wcs-state mount=\"...\">.`,\n );\n }\n stateElementByNode.set(rootNode, element);\n liveStateElements.add(element);\n // ルートの登録を待っていた機能へ(先に接続されて保留中のボリュームの引き取り — ロード順に依存しない、V5)\n for (let i = 0; i < registeredListeners.length; i++) {\n registeredListeners[i](rootNode, element);\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:element-registered\", rootNode, element });\n }\n if (config.debug) {\n console.debug(`State element registered`, element);\n }\n }\n}\n","import { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IFragmentInfo } from \"./types\";\n\nconst fragmentInfoByUUID = new Map<string, IFragmentInfo>();\n\nexport function setFragmentInfoByUUID(uuid: string, rootNode: Node, fragmentInfo: IFragmentInfo | null): void {\n if (fragmentInfo === null) {\n fragmentInfoByUUID.delete(uuid);\n } else {\n fragmentInfoByUUID.set(uuid, fragmentInfo);\n // v2: ルートに 1 ツリーなので参照は 1 回でよい(名前ごとの再解決は名前次元と一緒に消えた)\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for fragment info.`);\n }\n const bindingPartial = fragmentInfo.parseBindTextResult;\n stateElement.setPathInfo(bindingPartial.statePathName, bindingPartial.bindingType);\n for(const nodeInfo of fragmentInfo.nodeInfos) {\n for(const nodeBindingPartial of nodeInfo.parseBindTextResults) {\n stateElement.setPathInfo(nodeBindingPartial.statePathName, nodeBindingPartial.bindingType);\n }\n }\n }\n}\n\nexport function getFragmentInfoByUUID(uuid: string): IFragmentInfo | null {\n return fragmentInfoByUUID.get(uuid) || null;\n}\n\nexport function getAllFragmentUUIDs(): string[] {\n return Array.from(fragmentInfoByUUID.keys());\n}\n\n/**\n * 台帳を空にする。**サーバーのレンダリング 1 回分の後始末専用**(`ssr/buildSsrDocument.ts` の\n * `resetSsrRenderState`)。\n *\n * この台帳はモジュール寿命で削除の口が無く、`renderToString` が同じプロセスで別のドキュメントを\n * 描いても前のドキュメントのテンプレートが残り続ける。出力への混入そのものは直列化側の\n * 到達可能性フィルタ(`Ssr.buildContent`)で閉じてあるので、ここは**メモリ**の口である。\n * ブラウザでは呼ばない — 台帳は生きているページの構造テンプレートの正本。\n */\nexport function clearFragmentInfos(): void {\n fragmentInfoByUUID.clear();\n}","import { config } from \"../config\";\nimport { VOLUME_INJECTION_PROP } from \"../define\";\nimport { raiseError } from \"../raiseError\";\nimport { parseBindTextsForElement } from \"../bindTextParser/parseBindTextsForElement\";\nimport { parseCommentNode } from \"./parseCommentNode\";\nimport { parseBindTextForEmbeddedNode } from \"../bindTextParser/parseBindTextForEmbeddedNode\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { getFragmentInfoByUUID } from \"../structural/fragmentInfoByUUID\";\n\nexport function getParseBindTextResults(node: Node): ParseBindTextResult[] {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as Element;\n const bindText = element.getAttribute(config.bindAttributeName) || '';\n const results = parseBindTextsForElement(bindText);\n // ボリューム要素の `state.<key>: path` は注入口の宣言で、束縛ではない(B14③)。ボリュームが\n // 接ぎ木の時に自分で読む — ここで束縛にすると、無い `state` プロパティへの書き込みとして適用に失敗する\n if (element.localName === config.tagNames.state) {\n if (element.hasAttribute(\"mount\")) {\n return results.filter((result) => result.propSegments[0] !== VOLUME_INJECTION_PROP);\n }\n // `mount=` の無い `<wcs-state>` の左辺 `state…` は、誰も読まないまま束縛として残り、\n // 存在しない `state` プロパティへの書き込みとして適用の段で落ちていた。書いた場所を名指しする。\n // 1 段(`state: x`)と 2 段以上(`state.<key>: x`)で助言が違う — 前者に `mount=` を足しても\n // 今度は `inject one key at a time` になるので、助言が回らないように分ける\n const injection = results.find((result) => result.propSegments[0] === VOLUME_INJECTION_PROP);\n if (typeof injection !== \"undefined\") {\n const where =\n `on a volume element — a <${config.tagNames.state}> with a \"mount\" attribute`;\n raiseError(injection.propSegments.length === 1\n ? `[wcs/mount-path-invalid] \"${injection.propName}\" is the reserved namespace for volume injection, ` +\n `so it cannot be bound as an element property. Write one key at a time ` +\n `(\"${VOLUME_INJECTION_PROP}.<key>: <path>\") ${where}.`\n : `[wcs/mount-path-invalid] \"${injection.propName}: ${injection.statePathName}\" is a volume injection ` +\n `declaration, and it can only be written ${where}. Add mount=\"<path>\", or bind an element ` +\n `property instead.`);\n }\n }\n return results;\n } else if (node.nodeType === Node.COMMENT_NODE) {\n const bindTextOrUUID = parseCommentNode(node);\n if (bindTextOrUUID === null) {\n raiseError(`Comment node binding text not found.`);\n }\n const fragmentInfo = getFragmentInfoByUUID(bindTextOrUUID);\n let parseBindingTextResult = fragmentInfo?.parseBindTextResult ?? null;\n let uuid: string | null = null;\n if (parseBindingTextResult === null) {\n // It is not a structural fragment UUID, so treat it as bindText\n parseBindingTextResult = parseBindTextForEmbeddedNode(bindTextOrUUID);\n uuid = null;\n } else {\n uuid = bindTextOrUUID;\n }\n return [{\n ...parseBindingTextResult,\n uuid: uuid,\n }]\n }\n return [];\n}","import { IParsedFilter } from \"../types\";\n\n/**\n * `if` / `else` の反転として、エンジン自身がパース結果へ足すフィルタ(解析の段の形 —\n * 名前と引数だけ。要件 D16)。実関数は束縛計画の段で登録簿から引かれる。\n *\n * `not` は core(`core/filterRegistry.ts` の `CORE_FILTERS`)と `features/formats`\n * (`formats/builtinFilters.ts`)が**同じ実装**(`!value`)を持つので、formats を入れない\n * 分割 core のページでも、入れたページでも同じ答えになる。ここが食い違うと\n * `if: 0` に対する `else:` がどちらの枝も描かれない(`applyChangeToIf` は `Boolean()` で\n * 寄せるのに `not` が非 boolean で throw していた)。\n */\nlet _notFilterInfo: IParsedFilter | undefined = undefined;\n\nexport function createNotFilter(): IParsedFilter {\n return _notFilterInfo ??= { filterName: \"not\", args: [] };\n}\n","import { indexOfOutsideQuotes, splitOutsideQuotes } from \"../bindTextParser/utils.js\";\nimport { config } from \"../config.js\";\nimport { DELIMITER, WILDCARD } from \"../define.js\";\n\nconst COMMENT_REGEX = /^(\\s*@@\\s*(?:.*?)\\s*:\\s*)(.+?)(\\s*)$/;\n\n/**\n * 右辺の短縮パス(`.name` / `.`)を展開する。\n *\n * ここの `|` 走査は、**現在の文法では素の `indexOf` と結果が変わらない** — 右辺で引用符が\n * 現れるのはフィルタ引数、つまり最初の `|` より後ろだけなので、「引用符の中の `|` が\n * 最初に来る」形が作れない(ゆえに変異テストでも差が出ない)。それでも正本のヘルパで\n * 走らせているのは、下の `expandBindAttribute` の `;` / `:` と規準を 1 つに揃えるため。\n * **パスそのものに引用符を許す拡張が入れば、ここだけが素の走査だと即座に破れる。**\n */\nfunction expandShorthandInStatePart(statePart: string, forPath: string): string {\n const prefix = forPath + DELIMITER + WILDCARD;\n const pipeIndex = indexOfOutsideQuotes(statePart, '|');\n let pathPart: string;\n let suffix: string;\n if (pipeIndex !== -1) {\n pathPart = statePart.slice(0, pipeIndex).trim();\n suffix = statePart.slice(pipeIndex);\n } else {\n pathPart = statePart.trim();\n suffix = '';\n }\n if (pathPart === '.') {\n pathPart = prefix;\n } else if (pathPart.startsWith('.')) {\n pathPart = prefix + DELIMITER + pathPart.slice(1);\n } else {\n return statePart;\n }\n if (suffix.length > 0) {\n return pathPart + suffix;\n }\n return pathPart;\n}\n\nfunction expandCommentData(data: string, forPath: string): string {\n const match = COMMENT_REGEX.exec(data);\n if (match === null) {\n return data;\n }\n const commentPrefix = match[1];\n const bindText = match[2];\n const commentSuffix = match[3];\n const expanded = expandShorthandInStatePart(bindText, forPath);\n return commentPrefix + expanded + commentSuffix;\n}\n\n/**\n * `for` 行の短縮パス(`.name` / `.`)を `items.*.name` へ展開する。\n *\n * 区切りの走査は**引用符の外だけ**(要件 B1)。`splitBindTexts` と同じ正本のヘルパを使う:\n * ここで素の `split(';')` / `indexOf(':')` / `indexOf('|')` を使うと、\n * `value|defaults('00:00'): .startTime` のようなごく普通のフィルタ引数で `statePart` が\n * `00'): .startTime` になり、短縮展開が起きず `.startTime` のまま残って\n * `[wcs/binding-path-missing]` が出る — しかも `getBindingsReady` は reject しないので\n * **行が 1 つも描画されないまま無言で終わる**。lint と拡張は正しく展開するので気づけない。\n */\nfunction expandBindAttribute(attrValue: string, forPath: string): string {\n const parts = splitOutsideQuotes(attrValue, ';');\n let changed = false;\n const result = parts.map(part => {\n const trimmed = part.trim();\n if (trimmed.length === 0) return part;\n const colonIndex = indexOfOutsideQuotes(trimmed, ':');\n if (colonIndex === -1) return part;\n const propPart = trimmed.slice(0, colonIndex).trim();\n const statePart = trimmed.slice(colonIndex + 1).trim();\n const expanded = expandShorthandInStatePart(statePart, forPath);\n if (expanded !== statePart) {\n changed = true;\n return `${propPart}: ${expanded}`;\n }\n return part;\n });\n if (!changed) return attrValue;\n return result.join(';');\n}\n\nexport function expandShorthandInBindAttribute(attrValue: string, forPath: string): string {\n return expandBindAttribute(attrValue, forPath);\n}\n\nexport function expandShorthandPaths(root: DocumentFragment, forPath: string): void {\n const bindAttr = config.bindAttributeName;\n const walker = document.createTreeWalker(\n root,\n NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT,\n );\n\n while (walker.nextNode()) {\n const node = walker.currentNode;\n if (node.nodeType === Node.COMMENT_NODE) {\n const comment = node as Comment;\n comment.data = expandCommentData(comment.data, forPath);\n continue;\n }\n const element = node as Element;\n if (element instanceof HTMLTemplateElement) {\n continue;\n }\n const attr = element.getAttribute(bindAttr);\n if (attr !== null) {\n const expanded = expandBindAttribute(attr, forPath);\n if (expanded !== attr) {\n element.setAttribute(bindAttr, expanded);\n }\n }\n }\n}\n","\nexport function getNodePath(node: Node): number[] {\n let currentNode: Node | null = node;\n const path: number[] = [];\n while(currentNode.parentNode !== null) {\n const nodes: Node[] = Array.from(currentNode.parentNode.childNodes);\n const index = nodes.indexOf(currentNode);\n path.unshift(index);\n currentNode = currentNode.parentNode;\n }\n return path;\n}\n","import { getParseBindTextResults } from \"../bindings/getParseBindTextResults\";\nimport { getSubscriberNodes } from \"../bindings/getSubscriberNodes\";\nimport { getNodePath } from \"./getNodePath\";\nimport { IFragmentNodeInfo } from \"./types\";\n\n/**\n * 正規化で捨てたコメントの原文(テキスト束縛だけ)。空 Text からは元の\n * `<!--@@: path|filter-->` を復元できないが、SSR のスナップショットはこの fragment を\n * **マークアップとして**直列化するので、原文が無いと `for` / `if` テンプレートの中の\n * `{{ }}` がスナップショットから丸ごと消える(ハイドレーション後に恒久的に空になる)。\n * 直列化の直前に原文へ戻すための控え。`Ssr.buildContent` だけが読む。\n */\nconst textCommentDataByNode = new WeakMap<Node, string>();\n\n/**\n * 正規化前のコメント原文(テキスト束縛の空 Text に対して)。無ければ null。\n * `null`(nodePath の解決に失敗)も受ける — `WeakMap.get` は弱く保持できないキーに\n * `undefined` を返すので、呼び手が解決失敗を分岐で捌かずに済む。\n */\nexport function getNormalizedTextCommentData(node: Node | null): string | null {\n return textCommentDataByNode.get(node as Node) ?? null;\n}\n\nexport function getFragmentNodeInfos(fragment: DocumentFragment): IFragmentNodeInfo[] {\n const fragmnentNodeInfos: IFragmentNodeInfo[] = [];\n const subscriberNodes = getSubscriberNodes(fragment);\n for(const subscriberNode of subscriberNodes) {\n const parseBindingTextResults = getParseBindTextResults(subscriberNode);\n let node = subscriberNode;\n // テンプレート登録時の事前正規化: text 専用の wcs-text コメントは、この時点で\n // 空 Text に置き換えておく。行 clone は最初から Text を持ち、getBindingInfos が\n // その Text を replaceNode に使うため、行ごとの createTextNode と start() 時の\n // replaceChild(コメント→Text 差し替え)が丸ごと不要になる。\n // 置換は同じ位置なので nodePath は不変。wcs-for/if 等の構造コメントは\n // アンカーとしてコメントのまま維持する(bindingType で判別)。\n // 非フラグメント経路(実 DOM 上のコメント)は従来どおり実行時に差し替える。\n if (\n subscriberNode.nodeType === Node.COMMENT_NODE\n && parseBindingTextResults.length === 1\n && parseBindingTextResults[0].bindingType === \"text\"\n && subscriberNode.parentNode !== null\n ) {\n const textNode = document.createTextNode(\"\");\n // 原文を控えてから捨てる(SSR の直列化が戻す — textCommentDataByNode を参照)\n textCommentDataByNode.set(textNode, (subscriberNode as Comment).data);\n subscriberNode.parentNode.replaceChild(textNode, subscriberNode);\n node = textNode;\n }\n fragmnentNodeInfos.push({\n nodePath: getNodePath(node),\n parseBindTextResults: parseBindingTextResults,\n });\n }\n return fragmnentNodeInfos;\n}","\nexport function optimizeFragment(fragment: DocumentFragment): void {\n const childNodes = Array.from(fragment.childNodes);\n for(const childNode of childNodes) {\n if (childNode.nodeType === Node.TEXT_NODE) {\n const textContent = childNode.textContent || '';\n if (textContent.trim() === '') {\n // Remove empty text nodes\n fragment.removeChild(childNode);\n }\n }\n }\n}\n","import { getParseBindTextResults } from \"../bindings/getParseBindTextResults\";\nimport { findNestedLightDomComponents } from \"../bindings/lightDomComponentScope\";\nimport { parseBindTextsForElement } from \"../bindTextParser/parseBindTextsForElement\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { config } from \"../config\";\nimport { getUUID } from \"../getUUID\";\nimport { raiseError } from \"../raiseError\";\nimport { BindingType } from \"../types\";\nimport { createNotFilter } from \"./createNotFilter\";\nimport { expandShorthandInBindAttribute, expandShorthandPaths } from \"./expandShorthandPaths\";\nimport { setFragmentInfoByUUID } from \"./fragmentInfoByUUID\";\nimport { getFragmentNodeInfos } from \"./getFragmentNodeInfos\";\nimport { getNodePath } from \"./getNodePath\";\nimport { optimizeFragment } from \"./optimizeFragment\";\nimport { IFragmentInfo } from \"./types\";\n\nconst keywordByBindingType: Map<BindingType, string> = new Map<BindingType, string>([\n [\"for\", config.commentForPrefix],\n [\"if\", config.commentIfPrefix],\n [\"elseif\", config.commentElseIfPrefix],\n [\"else\", config.commentElsePrefix],\n]);\n\nconst notFilter = /*#__PURE__*/ createNotFilter();\n\nfunction cloneNotParseBindTextResult(\n bindingType: BindingType,\n parseBindTextResult: ParseBindTextResult\n): ParseBindTextResult {\n const filters = parseBindTextResult.outFilters;\n return {\n ...parseBindTextResult,\n outFilters: [...filters, notFilter],\n bindingType: bindingType,\n };\n}\n\n/**\n * パース結果の変換フック(Phase 2 のマウント — impl-plan §3-0 の 1)。\n *\n * マウントされたスコープでは、フラグメントのパース結果(テンプレート自身の for/if と\n * nodeInfos の中身)を**登録時にここで**親ツリーの絶対パスへ書き換える。行の実体化\n * (collectNodesAndBindingInfosByFragment)は変換済みの nodeInfos をそのまま使うので、\n * 行生成のホットパスに変換コストは載らない。\n *\n * shorthand 展開(`.name` → `<forPath>.*.name`)は**変換前の**内側パスで行う —\n * 変換後のパスを forPath に使うと、展開結果が絶対パスになり二重変換の判別が\n * つかなくなるため。したがって入れ子のフラグメントも常に「スコープ相対のパース結果 →\n * 変換」の順を保ち、変換は各レベルで一度だけ掛かる。\n *\n * `uuid` を持つ nodeInfo エントリ(入れ子フラグメントの参照 — 再帰で変換済み)には\n * 掛けない(collectNodesAndBindingInfos.applyTransform と同じ規則)。\n */\nexport type FragmentParseTransform = (parsed: ParseBindTextResult, forPath?: string) => ParseBindTextResult;\n\nfunction transformNodeInfos(\n nodeInfos: IFragmentInfo[\"nodeInfos\"],\n transform: FragmentParseTransform,\n forPath: string | undefined,\n): void {\n for (const nodeInfo of nodeInfos) {\n for (let i = 0; i < nodeInfo.parseBindTextResults.length; i++) {\n const parsed = nodeInfo.parseBindTextResults[i];\n if (parsed.uuid != null) continue;\n // forPath はこのフラグメントの中身を囲む for のスコープ相対パス(`$n` のシフト量の根拠)\n nodeInfo.parseBindTextResults[i] = transform(parsed, forPath);\n }\n }\n}\n\nfunction _getFragmentInfo(\n rootNode: Node,\n fragment: DocumentFragment,\n parseBindingTextResult: ParseBindTextResult,\n forPath?: string,\n transform?: FragmentParseTransform,\n // else 節はテンプレート自身の結果を if の**変換済み**結果から clone するため、\n // そこだけ再変換しない(nodeInfos は通常どおり変換する)\n transformOwnResult: boolean = true,\n): IFragmentInfo {\n optimizeFragment(fragment);\n if (typeof forPath === \"string\") {\n expandShorthandPaths(fragment, forPath);\n }\n collectStructuralFragments(rootNode, fragment, forPath, transform);\n // after replacing and collect node infos on child fragment\n const fragmentInfo = {\n fragment: fragment,\n // own result(テンプレート自身の for/if/elseif)にも forPath を渡す — `$n` の\n // シフト量は囲む for の翻訳が根拠(translateParsedForMount)で、渡し漏れると\n // record.delta に落ち、翻訳がワイルドカードを増やす部分マウント内の for の\n // `if: $n` / `elseif: $n` が誤った添字に解決される(transformNodeInfos と対称)。\n // if/elseif の forPath(呼び手の childForPath)は外側 forPath そのもの。\n // for テンプレートの own path は `$n` になり得ず、非 `$n` パスの変換は forPath を\n // 読まないため、for に自パスが渡っても無害\n parseBindTextResult: typeof transform === \"undefined\" || !transformOwnResult\n ? parseBindingTextResult\n : transform(parseBindingTextResult, forPath),\n nodeInfos: getFragmentNodeInfos(fragment),\n }\n if (typeof transform !== \"undefined\") {\n transformNodeInfos(fragmentInfo.nodeInfos, transform, forPath);\n }\n return fragmentInfo;\n}\n\n\nexport function collectStructuralFragments(rootNode: Node, walkRoot: Document | Element | DocumentFragment, forPath?: string, transform?: FragmentParseTransform): void {\n const elseKeyword = config.commentElsePrefix;\n // Light DOM の mapped コンポーネントの内側は、その子スコープが自分で処理する(§1.13)。\n // fragment info は rootNode + state 名で登録されるため、ホストのパスでここを拾うと\n // コンポーネント側の state がまだ名前登録を済ませておらず解決に失敗する。\n // コンポーネント要素自身は template ではないので、REJECT でサブツリーごと落として問題ない。\n const nestedComponents = findNestedLightDomComponents(walkRoot);\n const walker = document.createTreeWalker(\n walkRoot,\n NodeFilter.SHOW_ELEMENT,\n {\n acceptNode(node: Node) {\n const element = node as Element;\n if (nestedComponents.length > 0 && nestedComponents.indexOf(element) !== -1) {\n return NodeFilter.FILTER_REJECT;\n }\n if (element.tagName.toLowerCase() === 'template') {\n const bindText = element.getAttribute(config.bindAttributeName) || '';\n if (bindText.length > 0) {\n return NodeFilter.FILTER_ACCEPT;\n }\n }\n return NodeFilter.FILTER_SKIP;\n }\n }\n );\n let lastIfFragmentInfo: IFragmentInfo | null = null; // for elseif chaining\n const elseFragmentInfos: IFragmentInfo[] = []; // for elseif chaining\n const templates: HTMLTemplateElement[] = [];\n while (walker.nextNode()) {\n const template = walker.currentNode as HTMLTemplateElement;\n templates.push(template);\n }\n\n for(const template of templates) {\n let bindText = template.getAttribute(config.bindAttributeName) || '';\n if (typeof forPath === \"string\") {\n bindText = expandShorthandInBindAttribute(bindText, forPath);\n }\n const parseBindTextResults = parseBindTextsForElement(bindText);\n let parseBindTextResult = parseBindTextResults[0];\n const keyword = keywordByBindingType.get(parseBindTextResult.bindingType);\n if (typeof keyword === 'undefined') {\n continue;\n }\n\n const bindingType = parseBindTextResult.bindingType;\n const fragment = template.content;\n const uuid = getUUID();\n let fragmentInfo: IFragmentInfo | null = null;\n\n // Determine childForPath for shorthand expansion\n const childForPath = bindingType === \"for\"\n ? parseBindTextResult.statePathName\n : forPath;\n\n if (bindingType === \"else\") {\n // check last 'if' or 'elseif' fragment info\n if (lastIfFragmentInfo === null) {\n raiseError(`'else' binding found without preceding 'if' or 'elseif' binding.`);\n }\n // else condition(if の変換済み結果の clone なので自身の再変換はしない)\n parseBindTextResult = cloneNotParseBindTextResult(\"else\", lastIfFragmentInfo.parseBindTextResult);\n fragmentInfo = _getFragmentInfo(rootNode, fragment, parseBindTextResult, childForPath, transform, false);\n setFragmentInfoByUUID(uuid, rootNode, fragmentInfo);\n\n const lastElseFragmentInfo = elseFragmentInfos.at(-1);\n const placeHolder = document.createComment(`@@${keyword}:${uuid}`);\n if (typeof lastElseFragmentInfo !== \"undefined\") {\n template.remove();\n lastElseFragmentInfo.fragment.appendChild(placeHolder);\n lastElseFragmentInfo.nodeInfos.push({\n nodePath: getNodePath(placeHolder),\n parseBindTextResults: getParseBindTextResults(placeHolder),\n });\n } else {\n template.replaceWith(placeHolder);\n }\n } else if (bindingType === \"elseif\") {\n // check last 'if' or 'elseif' fragment info\n if (lastIfFragmentInfo === null) {\n raiseError(`'elseif' binding found without preceding 'if' or 'elseif' binding.`);\n }\n\n fragmentInfo = _getFragmentInfo(rootNode, fragment, parseBindTextResult, childForPath, transform);\n setFragmentInfoByUUID(uuid, rootNode, fragmentInfo);\n const placeHolder = document.createComment(`@@${keyword}:${uuid}`);\n\n // create else fragment\n const elseUUID = getUUID();\n const elseFragmentInfo: IFragmentInfo = {\n fragment: document.createDocumentFragment(),\n parseBindTextResult: cloneNotParseBindTextResult(\"else\", lastIfFragmentInfo.parseBindTextResult),\n nodeInfos: [],\n };\n elseFragmentInfo.fragment.appendChild(placeHolder);\n elseFragmentInfo.nodeInfos.push({\n nodePath: getNodePath(placeHolder),\n parseBindTextResults: getParseBindTextResults(placeHolder),\n });\n setFragmentInfoByUUID(elseUUID, rootNode, elseFragmentInfo);\n const lastElseFragmentInfo = elseFragmentInfos.at(-1);\n elseFragmentInfos.push(elseFragmentInfo);\n const elsePlaceHolder = document.createComment(`@@${elseKeyword}:${elseUUID}`);\n\n if (typeof lastElseFragmentInfo !== \"undefined\") {\n template.remove();\n lastElseFragmentInfo.fragment.appendChild(elsePlaceHolder);\n lastElseFragmentInfo.nodeInfos.push({\n nodePath: getNodePath(elsePlaceHolder),\n parseBindTextResults: getParseBindTextResults(elsePlaceHolder),\n });\n } else {\n template.replaceWith(elsePlaceHolder);\n }\n\n } else {\n fragmentInfo = _getFragmentInfo(rootNode, fragment, parseBindTextResult, childForPath, transform);\n setFragmentInfoByUUID(uuid, rootNode, fragmentInfo);\n const placeHolder = document.createComment(`@@${keyword}:${uuid}`);\n template.replaceWith(placeHolder);\n }\n\n // Update lastIfFragmentInfo for if/elseif/else chaining\n if (bindingType === \"if\") {\n elseFragmentInfos.length = 0; // start new if chain\n lastIfFragmentInfo = fragmentInfo;\n } else if (bindingType === \"elseif\") {\n lastIfFragmentInfo = fragmentInfo;\n } else if (bindingType === \"else\") {\n lastIfFragmentInfo = null;\n elseFragmentInfos.length = 0; // end if chain\n }\n }\n}\n","import { BINDER_KEY, IWcsBinder, flushPendingBinds } from \"../protocol/binder\";\nimport { config } from \"../config\";\nimport { convertMustacheToComments } from \"../mustache/convertMustacheToComments\";\nimport { collectStructuralFragments } from \"../structural/collectStructuralFragments\";\nimport { BindingSession, hasInterestedSession } from \"./BindingSession\";\nimport { areBindingsBuilt } from \"../stateElementByName\";\nimport { initializeBindings } from \"./initializeBindings\";\nimport { getSubscriberNodes } from \"./getSubscriberNodes\";\nimport { isLightDomMappedStateElement } from \"./lightDomComponentScope\";\n\n/**\n * binder プロトコルの提供側(docs/binder-protocol-design.md)。\n *\n * `buildBindings` は起動時に `document.body` を 1 回走査するだけなので、そのとき\n * document に居なかったノードのバインドは存在しない。router が後から差し込む\n * ルート内容や `<wcs-head>` のクローンがこれに当たり、書いたバインドが黙って\n * 何もしない状態になっていた。`bind()` はその取りこぼしを 1 サブツリー分だけ\n * 埋める。\n *\n * **走査を勝手に広げない。** MutationObserver が見た全追加ノードを走査する形に\n * すると、バインドを 1 個も持たない挿入(大多数)にコストが乗り、さらに\n * `innerHTML` で入れた外部由来の DOM が `data-wcs` を発火させることになる。\n * ここで束ねるのは**明示的に渡されたものだけ**である。\n */\nconst BIND_ATTRIBUTE_SELECTOR = (): string => `[${config.bindAttributeName}]`;\n\n/**\n * このサブツリーは既にバインド済みか。\n *\n * ルート内容は「起動時に active だったので全部バインド済み」か「一度も走査されて\n * いないので全部未バインド」のどちらかで、途中の状態を取らない。したがって\n * **宣言を持つ最初のノード 1 個**を見れば足りる。全ノードを走査して判定するのは\n * 同じ結論により高いコストを払うだけになる。\n */\nfunction alreadyBound(subtree: Node): boolean {\n if (hasInterestedSession(subtree)) {\n return true;\n }\n if (!isElement(subtree)) {\n return false;\n }\n if (subtree.hasAttribute(config.bindAttributeName)) {\n // 属性を持つのに台帳に居ない = 未バインド\n return false;\n }\n const first = subtree.querySelector(BIND_ATTRIBUTE_SELECTOR());\n return first !== null && hasInterestedSession(first);\n}\n\nfunction isElement(node: Node): node is Element {\n return node.nodeType === 1;\n}\n\nfunction bindNow(subtree: Element): void {\n // A subtree no longer in the document is left alone: one held until the first build may have\n // left it since (the build's own walk replaces a structural template handed over with its anchor).\n if (!subtree.isConnected || alreadyBound(subtree)) {\n return;\n }\n // Bind inside the subtree only, its root included (#409). `getSubscriberNodes`'s TreeWalker never\n // returns its root, and roots that declare on themselves do come here (`<wcs-head>`'s\n // `<title data-wcs=\"…\">`, a route's content handed over node by node), so the root is taken in by\n // hand — the shape SSR's hydration uses. This used to walk from the parent instead, which also\n // reached the root's siblings: a later sibling's structural template, not collected yet, was\n // registered as a plain binding, failed to apply and was never rendered, and siblings nobody\n // handed over were bound.\n const nodes: Node[] = subtree.hasAttribute(config.bindAttributeName) ? [subtree] : [];\n // A Light DOM mount (wired from the host, its `<wcs-state bind-component>` right under it): the\n // root's declarations belong to the host, and what is inside to the component's scope, which\n // collects it once wired (§1.13 — `getSubscriberNodes` prunes a nested one, never its walk root).\n if (!Array.from(subtree.children).some(\n (child) => child.localName === config.tagNames.state && isLightDomMappedStateElement(child))) {\n convertMustacheToComments(subtree);\n collectStructuralFragments(subtree.getRootNode(), subtree);\n nodes.push(...getSubscriberNodes(subtree));\n }\n // A session of its own, keyed by nothing. A session found by its root is what a scope disposes as a\n // whole: keyed by `subtree`, a Light DOM mount's host bindings joined the mount scope's session\n // (keyed by the component), and its re-initialization tore them down.\n initializeBindings(subtree, null, undefined, nodes, new BindingSession());\n}\n\n/**\n * 初期バインド構築より前に差し出されたサブツリー。\n *\n * `<wcs-head>` は `connectedCallback` の中でクローンを head へ入れるので、\n * state / router のどちらを先に読み込んでも「まだ構築が終わっていない」時点で\n * bind を求めてくる。そこで同期に束ねても `<wcs-state>` の登録が済んでおらず、\n * バインドは state を見つけられない。**構築の完了を唯一の合図にする。**\n */\nconst beforeFirstBuild: Element[] = [];\n\nfunction bind(subtree: Node): void {\n // Nothing to bind in a subtree not in a document (held, it would wait for a build that never comes)\n if (!isElement(subtree) || !subtree.isConnected || alreadyBound(subtree)) {\n return;\n }\n if (!areBindingsBuilt(subtree.getRootNode())) {\n beforeFirstBuild.push(subtree);\n return;\n }\n bindNow(subtree);\n}\n\n/**\n * 初期バインド構築の完了時に呼ぶ(stateElementByName.ts)。binder が居ない時点で\n * 差し出された分(プロトコルの保留キュー)と、居たが早すぎた分をまとめて束ねる。\n */\nexport function drainPendingBinds(): void {\n const pending = beforeFirstBuild.splice(0, beforeFirstBuild.length);\n for (const subtree of pending) {\n bindNow(subtree);\n }\n flushPendingBinds();\n}\n\nconst binder: IWcsBinder = {\n protocol: \"wcs-binder\",\n version: 1,\n bind,\n};\n\n/**\n * グローバル symbol へ自分を載せる。`bootstrapState` から呼ぶ。\n *\n * 既に別のコピーが載っているなら譲る。1 ページに 2 つの state バンドルが載る構成\n * (CDN の取り違え)で、後から読まれた側が先客を追い出すと、先客がバインドした\n * ノードの台帳と食い違う。\n */\nexport function registerBinder(): void {\n const globals = globalThis as Record<symbol, unknown>;\n if (globals[BINDER_KEY] === undefined) {\n globals[BINDER_KEY] = binder;\n }\n // ここでは引き取らない。`<wcs-state>` の登録は connectedCallback の await より\n // 後なので、この時点ではまだ state が居ない。保留分は初期バインド構築の完了時に\n // 流す(stateElementByName.ts)。そこが「state が確実に居る」最初の瞬間である。\n}\n\n/** テスト用: 登録を外す */\nexport function _unregisterBinder(): void {\n const globals = globalThis as Record<symbol, unknown>;\n if (globals[BINDER_KEY] === binder) {\n delete globals[BINDER_KEY];\n }\n}\n"],"names":["BINDER_KEY","Symbol","for","PENDING_KEY","TAKEN_KEY","flushPendingBinds","binder","candidate","globalThis","protocol","version","bind","getBinder","queue","globals","undefined","pendingQueue","length","pending","splice","taken","WeakSet","takenSet","subtree","add","MUSTACHE_REGEX","SKIP_TAGS","Set","convertMustacheToComments","root","config","enableMustache","walker","document","createTreeWalker","NodeFilter","SHOW_TEXT","textNodes","nextNode","push","currentNode","textNode","parentElement","has","tagName","replaceTextNode","convertTextNodes","templates","Array","from","querySelectorAll","template","namespaceURI","SVG_NAMESPACE","newTemplate","createElement","childNodes","i","childNode","content","appendChild","attr","attributes","setAttribute","name","value","replaceWith","text","data","lastIndex","test","fragment","createDocumentFragment","match","exec","index","createTextNode","slice","bindText","createComment","parentNode","replaceChild","STRUCTURAL_BINDING_TYPE_SET","finalizeArg","firstQuoteStart","lastQuoteEnd","startLimit","start","endLimit","end","NUMBER_LITERAL","toLiteral","quoted","Number","parseFilterArgsWithLiterals","argsText","args","literals","current","inQuote","hasQuote","flush","arg","char","raiseError","LINT_HINT","last","trimFn","s","trim","isQuote","c","indexOfOutsideQuotes","quote","splitOutsideQuotes","separator","parts","parseFilters","filterTextList","filterIOType","sourceText","source","join","map","filterText","openParenIndex","closeParenIndex","found","lastIndexOfOutsideQuotes","lastIndexOf","trailing","filterName","substring","includes","MODIFIER_SEPARATOR","modifiers","split","cacheFilterInfos","Map","parsePropPart","propPart","pos","FILTER_SEPARATOR","propText","filterTexts","filtersText","filters","get","set","modifierParts","propName","propModifiersText","propSegments","DELIMITER","some","segment","propModifiers","inFilters","parseStatePart","statePart","stateAndPath","indexOf","statePathName","isLoopRelative","startsWith","body","statePathInfo","getPathInfo","outFilters","KEYWORDS_WITHOUT_MODIFIERS","ELSE_KEYWORD","SPREAD_PROP","EXPLICIT_PROPERTY_REJECTED_HEADS","CLASS_NAMESPACE","ATTR_NAMESPACE","STYLE_NAMESPACE","COMMAND_NAMESPACE","EVENT_TOKEN_NAMESPACE","VOLUME_INJECTION_PROP","parseBindTextsForElement","bindTexts","BINDING_SEPARATOR","splitBindTexts","filter","results","separatorIndex","PROP_VALUE_SEPARATOR","keyword","pathInfo","bindingType","stateResult","propResult","EVENT_PROP_PREFIX","r","bindTextByNode","WeakMap","bindingTypeKeywordSet","commentTextPrefix","commentForPrefix","commentIfPrefix","commentElseIfPrefix","commentElsePrefix","EMBEDDED_REGEX","RegExp","parseCommentNode","node","savedText","nodeType","Node","COMMENT_NODE","parseBindTextForEmbeddedNode","bindingPromiseByNode","resolvedNodes","id","async","waitInitializeBinding","bindingPromise","resolveFn","promise","Promise","resolve","getInitializeBindingPromiseByNode","resolveInitializedBinding","existing","cache","getCustomElement","cached","ELEMENT_NODE","element","toLowerCase","hasAttribute","is","getAttribute","toAdapter","registry","whenDefined","getCustomElementRegistry","owner","customElementRegistry","scoped","customElements","owned","upgradeCustomElement","upgrade","readBindableDeclaration","target","addEventListener","removeEventListener","declaration","constructor","wcBindable","isInteger","knownProperties","readNamedList","properties","isValidPropertyDescriptor","declaredInputs","inputs","isValidInputDescriptor","declaredCommands","commands","isValidCommandDescriptor","liveDeclaration","descriptor","event","getter","attribute","isValidEntry","isArray","entries","entry","makeExpandedEntry","base","expandedPath","dedupKey","expandSpread","options","allowDeferred","expanded","spreadOrigin","result","bindable","targetBase","seen","keys","lastIndexByKey","key","final","debug","overrider","tagText","console","resolveNodePath","path","remaining","firstChild","nextSibling","planFilters","planned","filterFn","resolveFilterFn","planBinding","parsed","bindingsByNode","getBindingsByNode","isLightDomMappedStateElement","stateElement","Element","bindAttributeName","findNestedLightDomComponents","components","stateElements","tagNames","state","component","isInsideAnyComponent","contains","getSubscriberNodes","subscriberNodes","nestedComponents","SHOW_ELEMENT","SHOW_COMMENT","acceptNode","FILTER_ACCEPT","FILTER_SKIP","registeredNodeSet","processParseResultsForNode","parseResults","transform","bindings","deferred","parseBindingTextResults","bindingInfos","parseBindingTextResult","replaceNode","TEXT_NODE","getBindingInfos","uuid","applyTransform","setBindingsByNode","collectNodesAndBindingInfos","collectNodesAndBindingInfosOf","allBindings","deferredSpreads","getParseBindTextResults","markNodeRegistered","processDeferredNode","delete","unregisterNode","loopContextByNode","mountedScopeHost","setMountedScopeHost","resolver","getLoopContextByNode","paramNode","loopContext","next","ShadowRoot","setLoopContextByNode","count","getUUID","toString","chainGeneration","NO_VALUE","ListIndex","parentListIndex","position","_index","_version","_indexes","_listIndexes","_chainGeneration","_homeParentListIndex","_value","cacheStamp","ref","homeParentListIndex","this","indexes","home","dirty","listIndexes","WeakRef","varName","reparent","at","deref","createListIndex","reparentListIndex","listIndex","getHomeParentListIndex","rehomeListIndex","getRowCacheStamp","setListIndexValue","row","previous","changed","Object","rowsByElement","held","size","pruneSizeByRows","liveRowsOf","rememberRowOfElement","stale","rows","forEach","other","isUnderRetiredRow","retiredListIndexes","getListIndexValue","isSameListIndexValue","updateBatch","swapBaselineLists","markSwapBaselineList","list","isSwapBaselineList","listIndexesByList","isRetiredListIndex","releasedListsByParent","releaseListAtParent","holder","kept","released","moved","movedByList","holdersByList","isHoldingParent","handedOverByList","holdListAtParent","handedOver","hasReleasedList","isGoneParent","swapPendingBatchByRow","markRowSwapPending","clearRowSwapPending","covers","pruneSizeByList","lentLists","getElementAliases","readList","others","getRepairTarget","first","oldParent","newParent","isRestoredHome","canReparent","getListIndexesByList","resolveListIndexesByList","image","rebaseRenderedList","_row","holders","addHolders","parent","ownedListIndexes","isOwnedListIndexes","disownListIndexes","setListIndexesByList","renderedListByList","getRenderedList","rendered","hasRenderedList","lastListValueByAbsoluteStateAddress","addressesByListByStateElement","NO_ADDRESSES","sweepAtByAddresses","swappedListByAddress","addressesByListOf","address","absolutePathInfo","addressesByList","getLastListValueByAbsoluteStateAddress","setLastListValueByAbsoluteStateAddress","addresses","Math","max","getAddressesByLastListValue","markSwappedList","hasLastListValueByAbsoluteStateAddress","stateListBaselineByAbsoluteStateAddress","pendingBaselines","batchDepth","getStateListBaseline","setStateListBaseline","beginStateListBaselineBatch","endStateListBaselineBatch","hasStateListBaseline","setLoopContextSymbol","getByAddressSymbol","hasByAddressSymbol","connectedCallbackSymbol","disconnectedCallbackSymbol","updatedCallbackSymbol","errorCallbackSymbol","_cache","_cacheNullListIndex","AbsoluteStateAddress","createAbsoluteStateAddress","cacheByAbsolutePathInfo","treePathsByElement","getTreePath","table","treePath","freeze","TreePath","liftAddress","absoluteAddressOf","rootNodeByFragment","setRootNodeByFragment","rootNode","getRootNodeByFragment","cacheCalcWildcardLen","calcWildcardLen","targetPathInfo","path1","path2","wildcardCount","wildcardPathSet","len","intersection","listIndexAtWildcard","wildcardPos","getScopedIndexes","listIndexByBindingInfoByLoopContext","getListIndexByBindingInfo","bindingInfo","listIndexByBindingInfo","wildcardLen","absoluteStateAddressByBinding","resolveBindingRootNode","binding","knownRootNode","getRootNode","isConnected","nodeName","getAbsoluteStateAddressByBinding","absoluteStateAddress","getStateElement","clearAbsoluteStateAddressByBinding","bindingsByAbsoluteStateAddress","addBindingByAbsoluteStateAddress","devtoolsSink","type","absoluteAddress","removeBindingByAbsoluteStateAddress","patternLedger","peekBindingsForAddress","StateAddress","_parentAddress","_rowAddress","lastSegment","WILDCARD","parentAddress","parentPathInfo","segments","createStateAddress","holdsRow","wildcardPositions","cacheByPathInfo","stateAddressByBindingInfo","getStateAddressByBindingInfo","stateAddress","clearStateAddressByBindingInfo","createHandlerBindingRegistry","attachedByKey","countByKey","attached","remove","countOf","keyCount","clear","handlerByHandlerKey","bindingRegistry","getHandlerKey","eventName","filterKey","filterListKey","getEventName","modifier","attachCheckboxEventHandler","MODIFIER_READONLY","checkboxEventHandler","warn","checked","filteredNewValue","createState","currentValue","concat","toSpliced","isThenable","then","reportHandlerError","error","describe","captureHandlerRejection","values","catch","Token","_name","_subscribers","subscribe","fn","unsubscribe","emit","EventToken","_stateElement","super","kind","tokenName","subscriberCount","registryByStateElement","getOrCreateEventToken","token","clearEventTokenRegistry","listenerByBinding","attachEventTokenHandler","customTagName","propertyName","getWcBindable","propDesc","didYouMean","handler","MODIFIER_PREVENT","preventDefault","MODIFIER_STOP","stopPropagation","eventTokenNames","createStateAsync","CommandToken","isCommandToken","modifierKey","m","sort","stateEventHandlerFunction","handlerName","isCommand","STATE_COMMAND_NAMESPACE_NAME","scopedWildcardCount","hooks","addressHooks","scopes","handlerScope","Reflect","apply","isDomEventBinding","attachEventHandler","stateEventHandler","detachEventHandler","attachRadioEventHandler","radioEventHandler","CHECK_TYPES","DEFAULT_VALUE_PROP_NAMES","isPossibleTwoWay","inputType","customClass","nextWireId","nextTransactionId","nextSynchronousScopeId","wireIdsByNode","getWireId","member","byKey","wireKey","wireId","getEdgeId","direction","EMPTY_EDGES","beginPropagationTransaction","originBindingId","transactionId","visitedEdges","hop","extendPropagationContext","context","edgeId","currentContext","getCurrentPropagationContext","runWithPropagationContext","callback","receiptStack","commitElementValue","occurrence","consumeElementWrite","consumed","producerValueObserversByNode","DEFAULT_GETTER","e","detail","warnedDefaultGetter","getterIds","nextGetterId","attachedByBinding","valueGetter","isOccurrence","getterIdOf","twowayEventHandlerFunction","newValue","propValue","reason","prototype","hasOwnProperty","call","props","warnDefaultGetterMismatch","producerObservers","observer","propagationContext","enablePropagationContext","receipt","active","matchWriteReceipt","writtenValue","coveredBySameValueGuard","sameValueGuard","toStateEdgeId","baseContext","commitToState","attachTwowayEventHandler","getValueGetter","semantics","isOccurrenceProperty","twowayEventHandler","observerSkipNodes","markObserverSkipOnRemove","consumeObserverSkipOnRemove","skipRemovedChildrenByParent","consumeObserverSkipRemovedChildren","observerSkipAddedNodes","markObserverSkipOnAdd","consumeObserverSkipOnAdd","pendingObservationCount","decrementPendingObservation","hasPendingObservation","DefinitionCoordinator","wait","reject","normalizedTagName","waiters","settle","waiter","pendingCount","coordinatorByRegistry","getDefinitionCoordinator","coordinator","LEFT_HAND_NAMESPACES","readOption","MODIFIER_KEY_INIT","MODIFIER_KEY_SYNC","hasInitialSyncModifier","STATE_CALL_POLICY","authority","syncOn","observable","outputOnly","NONE_CALL_POLICY","statePolicy","resolveInitialSyncPolicy","enableDirectionalInitialSync","explicitAuthority","parseSyncOn","hasOutput","hasInput","getSyncStateElement","DocumentFragment","resolveInitialAuthority","initialized","isBindingStateInitialized","nextRecordId","armQueue","nextGeneration","SLOT_PHASE_NAMES","rowByBinding","rowSlotIds","recordByBinding","sessionByRoot","bindingKeyByBinding","interestedSessionsByNode","addInterestedSession","session","hasInterestedSession","forEachInterestedSession","forEachInclusive","child","isObservableRoot","BindingOwner","Observer","MutationObserver","mutations","handleMutations","observe","childList","removed","added","mutation","removedNodes","addedNodes","reconnected","handleRemovedNode","handleAddedNode","applyChangeFromBindings","ownerByRoot","getBindingOwner","bindingKey","registerPattern","knownRoot","rowMap","addBindingByPattern","registerAbsoluteAddress","unregisterFromLedger","removeBindingByPattern","addRecordTeardown","record","teardown","teardowns","BindingSession","records","rowPlan","knownBindingsByNode","optionsByBinding","deferredByNode","disposedAt","initialize","registerAddress","resolvedOptions","registerPathInfo","applyOnReconnect","remember","rowRecord","rowOf","rowSlot","phases","patternPathInfos","registered","registerRowSlot","phase","anchor","patternListIndex","settleInitialRecord","settleConnectedSnapshot","shouldApplyState","activate","activatePlanRows","slot","planSlot","plan","slots","flags","policy","initialApplyDone","resolvedAuthority","outputOnlyMember","observationPending","getRecord","ids","info","generation","addTeardown","isAlive","deferUntilDefined","tasks","finish","task","cancel","born","arm","queueMicrotask","disposeBinding","disposeRowSlot","disposeRecord","isRowSession","currentRowPlan","disposeBindings","destroyRow","destroyRowRecord","destroyRecords","dispose","canWholesaleDestroy","pendingDefinitions","forEachActiveBindingNode","rebindAddresses","rebound","unregisterRowSlot","oldAbs","patternPathInfo","newAbs","observableRootFor","known","knownMapFor","remembered","rememberedOptions","initializeRow","n","fill","patternListIndexes","addKnownRowBinding","isEvent","revived","runRowSlotTeardowns","slotIndex","replaceToReplaceNode","recordOptions","initialPolicy","initialSettled","eventSequence","hasProducerValue","producerValue","eventAttached","twowayAttached","attachListeners","runTeardowns","detachRadioEventHandler","detachCheckboxEventHandler","attachAfterDefinition","removeObserver","byProperty","observers","addTwowayValueObserver","listener","detachEventTokenHandler","attach","HTMLElement","readProducerSnapshot","eventWins","sequence","filteredValue","commitProducerValue","setPathInfo","detachTwowayEventHandler","reverse","getOrCreateBindingSession","getBindingSession","componentApplyHooks","setComponentApplyHooks","getFilteredValue","EMPTY_ARRAY","subscribedBindings","bindingsByContent","getBindingsByContent","setBindingsByContent","nodesByContent","getNodesByContent","setNodesByContent","nodes","bindLoopContextToContent","indexBindingsByContent","getIndexBindingsByContent","setIndexBindingsByContent","difference","elem","cacheEntryByAbsoluteStateAddress","rowCacheParents","getCacheEntryByAbsoluteStateAddress","setCacheEntryByAbsoluteStateAddress","cacheEntry","lastWildcardPath","dirtyCacheEntryByAbsoluteStateAddress","TRANSITION_RUNNER_KEY","getTransitionRunner","run","accepts","runTransition","mutate","types","runner","updateBatchListeners","enqueueListeners","applyingDepth","pendingDepth","pendingExternal","registerEnqueueListener","registerUpdateBatchListener","priority","findIndex","unregisterUpdateBatchListener","reportDeferredApplyFailure","Updater","_queueUpdateRecords","_queueRenderOnlyAddresses","enqueueAbsoluteAddress","requireStartProcess","_isQueueEmpty","_scheduleDrain","enqueueRenderOnlyAddress","updateRecords","renderOnlyAddresses","_applyChange","hasQueuedPath","testApplyChange","absoluteAddresses","contexts","depth","contextByAbsoluteAddress","landedAddresses","droppedTransactionId","winnerTransactionId","processBindings","propagationContextByBinding","MAX_PROPAGATION_HOPS","maxHops","applyBindings","MAX_RENDER_CHAIN_DEPTH","paths","absAddress","maxDepth","inSsr","batch","notifyUpdateBatchListeners","updater","getUpdater","ledgerByElement","keyByPathByAddress","entriesByListIndex","indexKeyedByListIndex","anyRegistered","pendingKeyedWalk","pushPendingKeyedWalk","takePendingKeyedWalk","watchersByElement","watchersByIndexes","descendantRowsByAncestor","watchersByOwnerListIndex","descendantsByElement","EMPTY","recordAncestors","ledger","ledgerOf","recorded","cumulativePaths","byAncestor","descendants","byPath","lastValue","tracked","addToKey","keyMap","removeFromKey","keyMapOf","oldKey","pushEntry","isNew","ancestor","linkAncestors","levelListIndex","registerKeyedDependency","registerIndexKeyedDependency","recordTrackedKeyedPath","getKeyedLedgerView","watchers","hasKeyedDependents","registerIndexWatcher","getterPathInfo","watcher","byList","find","w","getters","watchedRowsAt","out","moveIndexWatchers","oldIndexes","newIndexes","before","after","collect","keyedDependents","hasOldKey","newKey","hasLast","newDiffers","lastDiffers","hasKeyedDescendants","valueAt","keyedDescendantDependents","oldValue","hasOldValue","descendant","rest","allDependents","removeIndexEntry","dropRowSubscriptions","unlinkAncestors","dropWatchersOwnedBy","dropKeyedSubscriptionsByListIndex","rekeyIndexSubscriptions","oldIndex","newIndex","listDiffByOldListByNewList","EMPTY_LIST","EMPTY_SET","valueChangesByList","livePreviousLists","keepPreviousList","previousOf","isSameList","oldList","newList","retireRows","retireListIndexes","retired","createListDiff","rawOldList","rawNewList","diff","cachedDiff","diffByNewList","getListDiff","retValue","changeIndexSet","deleteIndexSet","addIndexSet","requester","isHeldElsewhere","newListIndex","lendRows","calcDiffIndexes","indexByValue","val","lent","existingIndexes","shift","existingListIndex","setListDiff","computeListDiff","valueChangeIndexes","syncListIndexes","reviveListIndexes","newIndexSet","oldIndexSet","oldPosByIndex","computeStableIndexSet","reused","seq","prevPos","sorted","lis","tails","prev","lo","hi","mid","k","longestIncreasingSubsequence","stable","seqIndex","bindingSessionByContent","getBindingSessionByContent","setBindingSessionByContent","planByContent","tailsByPlan","hasGetterOnPrefix","prefixes","getterPaths","applyPlanRow","rowPath","byRowPath","prefix","isIndexBinding","tail","accumulated","slotTails","hasReadMissing","readMissing","rowValue","rowRead","slotTail","applyChange","appliedBindingSet","missingKey","applyValueToBinding","activateContent","hasUpdatedCallback","hasRecursion","getPlanByContent","spreads","scheduleDeferredSpreads","deactivateContent","mounted","unbindLoopContextToContent","createEmptySet","contentSetByNode","setContentByNode","contents","getContentSetByNode","deleteContentByNode","recursiveBindingTypes","Content","_content","_childNodeArray","_firstNode","_lastNode","_mounted","_ranged","ranged","childNodeArray","firstNode","lastNode","appendTo","targetNode","_movableNodes","mountAfter","mover","moveBefore","insertBefore","tryDestroy","removeChild","unmount","unmountInPlace","_teardownBindings","resolveRanged","fragmentInfo","topLevelStructural","structural","hasTopLevelStructural","indexBit","min","ALL_INDEX_BITS","indexBitsOfFragment","bits","indexBits","nodeInfo","nodeInfos","parseBindTextResults","INDEX_BY_INDEX_NAME","getFragmentInfoByUUID","getIndexBitsByBinding","depthBits","createContentFromNodes","createPlanContent","cloneFragment","importNode","nodePath","indexBindings","nodeIndex","forNode","rowSessionByForNode","initializeRowBindings","setPlanByContent","createContent","directional","namespace","compileRowPlan","initialInfo","collectNodesAndBindingInfosByFragment","bindingSession","initializeBindingsByFragment","appendRowEndMarker","namedElements","NAMING_LEDGER_KEY","getAutoNaming","naming","limit","namingLimit","applyTransitionName","firstElementOf","style","counter","assigned","warned","getLedger","setProperty","lastNodeByNode","contentByListIndexByNode","pooledContentsByNode","isOnlyNodeInParentContentByNode","renderedListByNode","ssrBoundsByContent","placeSsrRow","label","bounds","hydrateSetContent","contentByListIndex","setContent","hydrateSetLastNode","hydrateSetRenderedList","countsAsParentContent","textContent","isPhysicallyAfter","compareDocumentPosition","DOCUMENT_POSITION_FOLLOWING","DOCUMENT_POSITION_DISCONNECTED","STRUCTURAL_BINDING_TYPES","clearAppliedMarks","nested","applyIndexBindings","movedBit","dropNestedContents","dropped","bindingInfoText","f","applyChangeToIf","rawNewValue","Boolean","ssrMode","log","ssrBlockRemoval","startComment","endComment","afterNode","autoNaming","store","getSsrProperties","getAllSsrPropertyNodes","trackedNodes","clearSsrPropertyStore","TRUSTED_TYPES_POLICY_SLOT","getTrustedTypesPolicy","setTrustedTypesPolicy","_enforced","_reported","reportTrustedTypesBlock","prop","innerHTML","isTrustedTypesEnforced","cause","createHTML","property","SSR_ATTR_PROPS","String","removeAttribute","selected","disabled","selectedIndex","idx","applyChangeToProperty","_context","displayProp","firstSegment","rememberOverwrittenObject","isHtmlSink","performWrite","propertyWriteSucceeded","trustHtmlValue","mirrorAttr","input","getInputAttributeMirror","attributeName","formatted","JSON","stringify","applyMirrorAttribute","extendedContext","bindingId","bindingGeneration","synchronousScopeId","pop","runWithWriteReceipt","attrHandler","addSsrProperty","subObject","isFrozen","rememberOverwrittenValue","recordInjectedKey","ssrWrappedNodes","applyChangeToWebComponent","_binding","_newValue","getValue","indexName","indexPos","wildcardScopeMessage","getIndexValueByLoopContext","scheduledBindings","reportFailure","applyChangeByFirstSegment","className","classList","toggle","attrName","styleName","methodName","elementRef","el","method","applyChangeByBindingType","nodeValue","listPathInfo","recordedLastValue","swapped","isSwappedList","shared","every","newListValue","newListValueByAbsAddress","contentMap","inPlaceContents","inPlace","byAddedIndex","collectInPlaceContents","fullDelete","isOnlyNode","prevCheckNode","previousSibling","nextCheckNode","onlyNode","isOnlyNodeInParentContent","markObserverSkipRemovedChildren","poolBudget","getPooledContents","POSITIVE_INFINITY","deleteIndex","bound","setPooledContent","elementPathInfo","loopContextStack","stableIndexSet","ssrLabel","pooledContents","createLoopContext","rowReused","unmountedByAncestor","revivedContent","if","else","elseif","radio","elementFilteredValue","checkbox","normalizedNewValue","fnByBinding","deferredSelectBindingByBinding","definedApplyVerifiedByBinding","skipPendingMountWrite","resolveCustomElementApply","stateProp","isComplete","isDeclared","deferredSelectBindings","updatedAbsAddressSetByStateElement","customTag","isWaitingDefinition","applyLatest","currentSession","Error","scheduleDeferredApply","sameRootVerified","targetState","newContext","reportBindingApplyError","failuresByStateElement","hasErrorCallback","failures","bindingIndex","nextBindingInfo","updatedCallback","absAddressSet","callbackError","original","parentLoopContext","contentBindings","initializeBindings","uncollectedNodes","waitForStateInitialize","elements","promises","initializePromise","all","buildBindings","collectStructuralFragments","shadowRoot","host","ENTRY_BY_FEATURE","watch","scan","streams","dcc","recursion","ssr","devtools","featureNotInstalledMessage","feature","ssrHooks","setSsrHooks","requireSsrHooks","stateElementByNode","bindingsReadyByNode","liveStateElements","registeredListeners","onStateElementRegistered","getLiveStateElements","getBindingsReady","markBindingsUnavailable","failed","bindingsBuiltRoots","setStateElementAlias","setBindingsReadyForScope","ready","markBindingsBuilt","setStateElement","enableSsr","hydrate","drainPendingBinds","fragmentInfoByUUID","setFragmentInfoByUUID","bindingPartial","parseBindTextResult","nodeBindingPartial","clearFragmentInfos","localName","injection","where","bindTextOrUUID","_notFilterInfo","createNotFilter","COMMENT_REGEX","expandShorthandInStatePart","forPath","pipeIndex","pathPart","suffix","expandCommentData","commentPrefix","commentSuffix","expandBindAttribute","attrValue","part","trimmed","colonIndex","expandShorthandInBindAttribute","expandShorthandPaths","bindAttr","comment","HTMLTemplateElement","getNodePath","unshift","textCommentDataByNode","getNormalizedTextCommentData","getFragmentNodeInfos","fragmnentNodeInfos","subscriberNode","optimizeFragment","keywordByBindingType","notFilter","cloneNotParseBindTextResult","_getFragmentInfo","transformOwnResult","transformNodeInfos","walkRoot","elseKeyword","FILTER_REJECT","lastIfFragmentInfo","elseFragmentInfos","childForPath","lastElseFragmentInfo","placeHolder","elseUUID","elseFragmentInfo","elsePlaceHolder","BIND_ATTRIBUTE_SELECTOR","alreadyBound","isElement","querySelector","bindNow","children","beforeFirstBuild","registerBinder"],"mappings":"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"}
1
+ {"version":3,"file":"binder.js","sources":["../../../../../src/protocol/binder.ts","../../../../../src/mustache/convertMustacheToComments.ts","../../../../../src/structural/define.ts","../../../../../src/bindTextParser/parseFilterArgs.ts","../../../../../src/bindTextParser/utils.ts","../../../../../src/bindTextParser/parseFilters.ts","../../../../../src/bindTextParser/parsePropPart.ts","../../../../../src/bindTextParser/parseStatePart.ts","../../../../../src/bindTextParser/parseBindTextsForElement.ts","../../../../../src/bindings/parseCommentNode.ts","../../../../../src/bindTextParser/parseBindTextForEmbeddedNode.ts","../../../../../src/bindings/initializeBindingPromiseByNode.ts","../../../../../src/getCustomElement.ts","../../../../../src/platform/customElementRegistry.ts","../../../../../src/protocol/wcBindableReader.ts","../../../../../src/bindTextParser/expandSpread.ts","../../../../../src/structural/resolveNodePath.ts","../../../../../src/bindings/planFilters.ts","../../../../../src/bindings/getBindingsByNode.ts","../../../../../src/bindings/lightDomComponentScope.ts","../../../../../src/bindings/getSubscriberNodes.ts","../../../../../src/bindings/collectNodesAndBindingInfos.ts","../../../../../src/bindings/getBindingInfos.ts","../../../../../src/list/loopContextByNode.ts","../../../../../src/getUUID.ts","../../../../../src/list/createListIndex.ts","../../../../../src/updater/updateBatch.ts","../../../../../src/list/swapBaselineList.ts","../../../../../src/list/listIndexesByList.ts","../../../../../src/list/lastListValueByAbsoluteStateAddress.ts","../../../../../src/list/stateListBaseline.ts","../../../../../src/proxy/symbols.ts","../../../../../src/address/AbsoluteStateAddress.ts","../../../../../src/address/TreePath.ts","../../../../../src/address/liftAddress.ts","../../../../../src/apply/rootNodeByFragment.ts","../../../../../src/address/calcWildcardLen.ts","../../../../../src/list/wildcardLevel.ts","../../../../../src/list/getListIndexByBindingInfo.ts","../../../../../src/binding/getAbsoluteStateAddressByBinding.ts","../../../../../src/binding/getBindingSetByAbsoluteStateAddress.ts","../../../../../src/address/StateAddress.ts","../../../../../src/binding/getStateAddressByBindingInfo.ts","../../../../../src/event/handlerBindingRegistry.ts","../../../../../src/event/checkboxHandler.ts","../../../../../src/event/captureHandlerRejection.ts","../../../../../src/token/Token.ts","../../../../../src/event/EventToken.ts","../../../../../src/event/eventTokenRegistry.ts","../../../../../src/event/eventTokenHandler.ts","../../../../../src/command/CommandToken.ts","../../../../../src/event/handler.ts","../../../../../src/event/radioHandler.ts","../../../../../src/event/isPossibleTwoWay.ts","../../../../../src/propagation/propagation.ts","../../../../../src/proxy/occurrenceWrite.ts","../../../../../src/event/twowayHandler.ts","../../../../../src/bindings/observerSkip.ts","../../../../../src/bindings/DefinitionCoordinator.ts","../../../../../src/bindings/initialSync.ts","../../../../../src/bindings/BindingSession.ts","../../../../../src/bindings/replaceToReplaceNode.ts","../../../../../src/core/componentApplyHooks.ts","../../../../../src/apply/getFilteredValue.ts","../../../../../src/apply/applyChangeToCheckbox.ts","../../../../../src/createEmptyArray.ts","../../../../../src/apply/applyChangeToCommand.ts","../../../../../src/bindings/bindingsByContent.ts","../../../../../src/bindings/nodesByContent.ts","../../../../../src/bindings/bindLoopContextToContent.ts","../../../../../src/bindings/indexBindingsByContent.ts","../../../../../src/polyfills.ts","../../../../../src/cache/cacheEntryByAbsoluteStateAddress.ts","../../../../../src/protocol/transitionRunner.ts","../../../../../src/updater/updater.ts","../../../../../src/dependency/keyedDependency.ts","../../../../../src/list/createListDiff.ts","../../../../../src/list/stableListOrder.ts","../../../../../src/bindings/bindingSessionByContent.ts","../../../../../src/structural/planByContent.ts","../../../../../src/structural/activateContent.ts","../../../../../src/createEmptySet.ts","../../../../../src/structural/contentsByNode.ts","../../../../../src/structural/createContent.ts","../../../../../src/bindings/initializeBindings.ts","../../../../../src/structural/rowPlan.ts","../../../../../src/apply/viewTransitionNaming.ts","../../../../../src/apply/applyChangeToFor.ts","../../../../../src/apply/applyChangeToIf.ts","../../../../../src/apply/ssrPropertyStore.ts","../../../../../src/trustedTypes.ts","../../../../../src/apply/applyChangeToProperty.ts","../../../../../src/event/getInputAttributeMirror.ts","../../../../../src/apply/applyChangeToText.ts","../../../../../src/apply/applyChangeToWebComponent.ts","../../../../../src/apply/getValue.ts","../../../../../src/list/getIndexValueByLoopContext.ts","../../../../../src/apply/scheduleDeferredApply.ts","../../../../../src/apply/applyChange.ts","../../../../../src/apply/applyChangeToClass.ts","../../../../../src/apply/applyChangeToAttribute.ts","../../../../../src/apply/applyChangeToStyle.ts","../../../../../src/apply/applyChangeToRadio.ts","../../../../../src/apply/applyChangeFromBindings.ts","../../../../../src/waitForStateInitialize.ts","../../../../../src/buildBindings.ts","../../../../../src/core/featureEntries.ts","../../../../../src/core/ssrHooks.ts","../../../../../src/stateElementByName.ts","../../../../../src/structural/fragmentInfoByUUID.ts","../../../../../src/bindings/getParseBindTextResults.ts","../../../../../src/structural/createNotFilter.ts","../../../../../src/structural/expandShorthandPaths.ts","../../../../../src/structural/getNodePath.ts","../../../../../src/structural/getFragmentNodeInfos.ts","../../../../../src/structural/optimizeFragment.ts","../../../../../src/structural/collectStructuralFragments.ts","../../../../../src/bindings/binder.ts"],"sourcesContent":["// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/binder.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// binder protocol — how a package that inserts DOM hands those nodes to whoever\n// owns data bindings on the page.\n//\n// The dual of transition-runner: that one hands a *mutation* to whoever animates\n// it, this one hands *new nodes* to whoever binds them.\n//\n// A `data-wcs` binding exists only for nodes @wcstack/state walked when it built\n// its bindings. Nodes that arrive later — the content of a route that was not\n// active at that moment, a <wcs-head> child reflected into <head> — were never\n// walked, so their bindings silently do nothing, however often they are inserted.\n// @wcstack/router must not depend on @wcstack/state (zero runtime dependencies,\n// independently publishable), so state installs a binder on a well-known global\n// symbol and inserters look it up lazily.\n//\n// No binder installed means nothing happens — byte-for-byte the behavior these\n// packages had before the protocol existed.\n//\n// docs/binder-protocol-design.md is the normative description.\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/binder.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/binder.ts). Those copies are generated — do not edit them.\n\n/**\n * Global key the binder installs itself under. `Symbol.for` so independently\n * loaded copies of this file (two CDN bundles on one page) still agree.\n */\nexport const BINDER_KEY = Symbol.for(\"wcstack.binder\");\n\n/**\n * What the caller declares about a subtree it hands over (the second argument of `bind`; additive\n * since version 1 — a binder that predates it ignores it, and leaving it out keeps the old contract).\n */\nexport interface IWcsBindOptions {\n /**\n * The caller carries the range the subtree sits in: on removal it takes everything from its own\n * start mark up to its end mark along — what the binder rendered beside the subtree included, as\n * the rows a structural template handed over at the top of the content renders before its anchor —\n * and puts it all back on reinsertion. Only with this may a binder render such a template: without\n * it, what the binder rendered beside the subtree would be left behind. @wcstack/state 3.x ignores\n * the option and renders no structural template handed over itself, with or without it\n * (docs/binder-protocol-design.md §2, §9-5).\n */\n readonly range?: boolean;\n}\n\nexport interface IWcsBinder {\n readonly protocol: \"wcs-binder\";\n /** Integer protocol version. All versions >= 1 are participant-compatible. */\n readonly version: number;\n /**\n * Take a subtree that has just entered the document and bind whatever\n * declarations it carries.\n *\n * Contract (docs/binder-protocol-design.md §2):\n * - Synchronous. Initial values are applied before this returns, so the\n * caller never shows one frame of unbound markup.\n * - Idempotent. A subtree that is already bound is left alone, so a caller\n * may hand over the same nodes on every insertion without tracking which\n * ones are new.\n * - Binding survives later relocation, so this need not be called again when\n * the same nodes are moved (measured: design doc §8-3).\n * - Never throws for markup reasons; a subtree with no declarations is a\n * no-op.\n * - `options` (optional) is what the caller declares about the subtree\n * ({@link IWcsBindOptions}).\n */\n bind(subtree: Node, options?: IWcsBindOptions): void;\n}\n\n/**\n * The installed binder, or null when there is none or it speaks a version this\n * reader does not.\n *\n * Looked up on every call rather than cached, for the same reason\n * transition-runner does: the page's composition can change at any point, and a\n * stale cache would keep calling into a binder that is no longer there.\n */\nexport function getBinder(): IWcsBinder | null {\n const candidate = (globalThis as Record<symbol, unknown>)[BINDER_KEY] as IWcsBinder | undefined;\n if (candidate === undefined || candidate === null) return null;\n if (candidate.protocol !== \"wcs-binder\") return null;\n if (typeof candidate.version !== \"number\" || candidate.version < 1) return null;\n if (typeof candidate.bind !== \"function\") return null;\n return candidate;\n}\n\n/**\n * Subtrees offered before a binder existed, and the set of everything a binder\n * has taken. Both live on global symbols so that independently loaded copies of\n * this file — the router's and state's — share one queue.\n *\n * The queue is needed because of load order: the router's auto bundle runs\n * before state's, so `<wcs-head>` reflects its children into `<head>` while\n * there is still nothing to bind them. Offering them to a binder that arrives\n * later is the difference between working and silently blank.\n */\nconst PENDING_KEY = Symbol.for(\"wcstack.binder.pending\");\nconst TAKEN_KEY = Symbol.for(\"wcstack.binder.taken\");\n\nfunction pendingQueue(): Node[] {\n const globals = globalThis as Record<symbol, unknown>;\n let queue = globals[PENDING_KEY] as Node[] | undefined;\n if (queue === undefined) {\n queue = [];\n globals[PENDING_KEY] = queue;\n }\n return queue;\n}\n\nfunction takenSet(): WeakSet<Node> {\n const globals = globalThis as Record<symbol, unknown>;\n let taken = globals[TAKEN_KEY] as WeakSet<Node> | undefined;\n if (taken === undefined) {\n taken = new WeakSet<Node>();\n globals[TAKEN_KEY] = taken;\n }\n return taken;\n}\n\n/**\n * Hand `subtree` to the installed binder, or hold it for one that arrives later.\n *\n * Returns whether a binder took it *now*. A `false` does not yet mean the markup\n * is doomed — check {@link wasBoundBy} once module scripts have run.\n *\n * `options` goes to the binder with the subtree. A subtree held for a later binder\n * is handed over without it: that binder's first walk of the page binds what is\n * still in place there.\n */\nexport function bindSubtree(subtree: Node, options?: IWcsBindOptions): boolean {\n const binder = getBinder();\n if (binder === null) {\n pendingQueue().push(subtree);\n return false;\n }\n takenSet().add(subtree);\n binder.bind(subtree, options);\n return true;\n}\n\n/** Whether any binder has taken this subtree. */\nexport function wasBoundBy(subtree: Node): boolean {\n return takenSet().has(subtree);\n}\n\n/**\n * Bind everything offered before this binder existed. Called by the binder right\n * after it installs itself.\n */\nexport function flushPendingBinds(): void {\n const binder = getBinder();\n if (binder === null) return;\n const queue = pendingQueue();\n if (queue.length === 0) return;\n const pending = queue.splice(0, queue.length);\n const taken = takenSet();\n for (const subtree of pending) {\n taken.add(subtree);\n binder.bind(subtree);\n }\n}\n","import { config } from \"../config.js\";\nimport { SVG_NAMESPACE } from \"../define.js\";\n\nconst MUSTACHE_REGEX = /\\{\\{\\s*(.+?)\\s*\\}\\}/g;\nconst SKIP_TAGS = new Set([\"SCRIPT\", \"STYLE\"]);\n\n/**\n * `skip` keeps a text node with a `{{ … }}` as it is — a mount scope initialized again on the same DOM\n * passes the text its bindings rendered, which is data (webComponent/mountScope.ts).\n */\nexport function convertMustacheToComments(\n root: Document | Element | DocumentFragment,\n skip?: (textNode: Text) => boolean,\n): void {\n if (!config.enableMustache) {\n return;\n }\n\n convertTextNodes(root, skip);\n\n const templates = Array.from(root.querySelectorAll(\"template\"));\n\n for (const template of templates) {\n if (template.namespaceURI === SVG_NAMESPACE) {\n const newTemplate = document.createElement(\"template\");\n const childNodes = Array.from(template.childNodes);\n for(let i = 0; i < childNodes.length; i++) {\n const childNode = childNodes[i];\n newTemplate.content.appendChild(childNode);\n }\n for(const attr of template.attributes) {\n newTemplate.setAttribute(attr.name, attr.value);\n }\n template.replaceWith(newTemplate);\n convertMustacheToComments(newTemplate.content);\n } else {\n convertMustacheToComments(template.content);\n }\n }\n}\n\nfunction convertTextNodes(root: Document | Element | DocumentFragment, skip?: (textNode: Text) => boolean): void {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n const textNodes: Text[] = [];\n\n while (walker.nextNode()) {\n textNodes.push(walker.currentNode as Text);\n }\n\n for (const textNode of textNodes) {\n if (textNode.parentElement && SKIP_TAGS.has(textNode.parentElement.tagName)) {\n continue;\n }\n replaceTextNode(textNode, skip);\n }\n}\n\nfunction replaceTextNode(textNode: Text, skip?: (textNode: Text) => boolean): void {\n const text = textNode.data;\n MUSTACHE_REGEX.lastIndex = 0;\n\n if (!MUSTACHE_REGEX.test(text) || skip?.(textNode)) {\n return;\n }\n\n MUSTACHE_REGEX.lastIndex = 0;\n const fragment = document.createDocumentFragment();\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = MUSTACHE_REGEX.exec(text)) !== null) {\n if (match.index > lastIndex) {\n fragment.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));\n }\n\n const bindText = match[1];\n fragment.appendChild(document.createComment(`@@: ${bindText}`));\n\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < text.length) {\n fragment.appendChild(document.createTextNode(text.slice(lastIndex)));\n }\n\n textNode.parentNode!.replaceChild(fragment, textNode);\n}\n","import { BindingType } from \"../types.js\";\n\nexport const STRUCTURAL_BINDING_TYPE_SET: Set<BindingType> = new Set([\n \"if\",\n \"elseif\",\n \"else\",\n \"for\",\n]);\n","/**\n * フィルタ引数リストのパース。`filter(a, b)` の `a, b` 部分を受け取る。\n *\n * トリムの規則は「**クォートの外側だけ**」。`fix( 2 )` のような書き癖を吸収するために\n * 素の引数は前後をトリムするが、クォートは「ここは literal」という宣言なので中身の\n * 空白は残す。両方まとめてトリムしていたため `pad(5, ' ')` が空文字パディング\n * (=無変化)に化けており、空白区切りの `join(' / ')` も指定できなかった。\n */\n\n/** 引数 1 つを確定する。クォート由来の文字が入った範囲より外側だけをトリムする。 */\nfunction finalizeArg(text: string, firstQuoteStart: number, lastQuoteEnd: number): string {\n // 先頭側: 最初のクォート文字より前だけが削れる(クォートが無ければ全体が対象)\n const startLimit = firstQuoteStart === -1 ? text.length : firstQuoteStart;\n let start = 0;\n while (start < startLimit && /\\s/.test(text[start])) {\n start++;\n }\n // 末尾側: 最後のクォート文字より後ろだけが削れる(クォートが無ければ全体が対象)\n const endLimit = lastQuoteEnd === -1 ? 0 : lastQuoteEnd;\n let end = text.length;\n while (end > endLimit && /\\s/.test(text[end - 1])) {\n end--;\n }\n return text.slice(start, end);\n}\n\nimport { LINT_HINT } from \"../errorGuidance\";\nimport { raiseError } from \"../raiseError\";\n\n/** 引用符の無い引数の型(要件 B9): true / false / null / 数値は型付き、それ以外は文字列 */\nconst NUMBER_LITERAL = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/;\nfunction toLiteral(text: string, quoted: boolean): unknown {\n if (quoted) return text;\n if (text === \"true\") return true;\n if (text === \"false\") return false;\n if (text === \"null\") return null;\n return NUMBER_LITERAL.test(text) ? Number(text) : text;\n}\n\n/**\n * 引数の原文と、その型付きの値(要件 B9)を一緒に返す。原文は引用符を外したもの。\n *\n * 末尾の空引数だけが落ちる(`\"a,\"` → 1 個、`\",a\"` → 2 個、`\",\"` → 1 個)。`filter()` を\n * 「引数 0 個」と読むための規則で、先頭・中間の空引数は位置を保つために残す。\n */\nexport function parseFilterArgsWithLiterals(argsText: string): { args: string[]; literals: unknown[] } {\n const args: string[] = [];\n const literals: unknown[] = [];\n let current = '';\n let inQuote: string | null = null;\n let hasQuote = false;\n let firstQuoteStart = -1;\n let lastQuoteEnd = -1;\n\n const flush = (): void => {\n const arg = finalizeArg(current, firstQuoteStart, lastQuoteEnd);\n args.push(arg);\n literals.push(toLiteral(arg, hasQuote));\n current = '';\n hasQuote = false;\n firstQuoteStart = -1;\n lastQuoteEnd = -1;\n };\n\n for (let i = 0; i < argsText.length; i++) {\n const char = argsText[i];\n\n if (inQuote) {\n if (char === inQuote) {\n inQuote = null;\n } else {\n if (firstQuoteStart === -1) {\n firstQuoteStart = current.length;\n }\n current += char;\n lastQuoteEnd = current.length;\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char;\n hasQuote = true;\n } else if (char === ',') {\n flush();\n } else {\n current += char;\n }\n }\n\n if (inQuote !== null) {\n // 閉じていない引用符は受理しない(要件 B2)。以前は黙って閉じたことにしていた\n raiseError(`[wcs/binding-syntax] unterminated ${inQuote} quote in the filter arguments \"(${argsText})\". Close the quote.${LINT_HINT}`);\n }\n const last = finalizeArg(current, firstQuoteStart, lastQuoteEnd);\n if (last || hasQuote) {\n args.push(last);\n literals.push(toLiteral(last, hasQuote));\n }\n\n return { args, literals };\n}\n","export const trimFn = (s: string): string => s.trim();\n\nconst isQuote = (c: string): boolean => c === \"'\" || c === '\"';\n\n/**\n * `text` の中で、引用符(`'` / `\"`)の外にある最初の `char` の位置。無ければ -1(要件 B1)。\n * 閉じていない引用符はそのまま末尾まで続く扱い — 不正な引用符はフィルタ引数の段で名指しで落ちる。\n */\nexport function indexOfOutsideQuotes(text: string, char: string): number {\n let quote: string | null = null;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quote !== null) {\n if (c === quote) quote = null;\n } else if (isQuote(c)) {\n quote = c;\n } else if (c === char) {\n return i;\n }\n }\n return -1;\n}\n\n/**\n * `text` の中で、引用符の外にある**最後の** `char` の位置。無ければ -1(要件 B1)。\n * 引用符は前からしか追えないので、前向きに走査して最後の一致を控える。\n * フィルタの閉じ括弧を探す用(`a|foo(')')` の引用符内の `)` を終端と誤認しないため)。\n */\nexport function lastIndexOfOutsideQuotes(text: string, char: string): number {\n let quote: string | null = null;\n let found = -1;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quote !== null) {\n if (c === quote) quote = null;\n } else if (isQuote(c)) {\n quote = c;\n } else if (c === char) {\n found = i;\n }\n }\n return found;\n}\n\n/**\n * `separator` で区切る。ただし引用符の中は区切らない(要件 B1): `join(';')` や `join('|')` の\n * 区切り文字は引数であって、バインディングやフィルタの区切りではない。\n */\nexport function splitOutsideQuotes(text: string, separator: string): string[] {\n const parts: string[] = [];\n let quote: string | null = null;\n let start = 0;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quote !== null) {\n if (c === quote) quote = null;\n } else if (isQuote(c)) {\n quote = c;\n } else if (c === separator) {\n parts.push(text.slice(start, i));\n start = i + 1;\n }\n }\n parts.push(text.slice(start));\n return parts;\n}\n","import { clearFilterResolutionCache } from \"../core/filterRegistry\";\nimport { MODIFIER_SEPARATOR } from \"../define\";\nimport { LINT_HINT } from \"../errorGuidance\";\nimport { FilterIOType } from \"../filters/types\";\nimport { raiseError } from \"../raiseError\";\nimport { IParsedFilter } from \"../types\";\nimport { parseFilterArgsWithLiterals } from \"./parseFilterArgs\";\nimport { indexOfOutsideQuotes, lastIndexOfOutsideQuotes } from \"./utils\";\n\n/** tooling 専用(parser.ts の clearParserCaches からのみ呼ぶ)。 */\nexport function clearFilterFnCacheForTooling(): void {\n clearFilterResolutionCache();\n}\n\n// format: filterName(arg1,arg2) or filterName\n\n/**\n * 文法の段(要件 D16): 名前と引数だけを読む。**実関数は引かない** — 束縛計画の段で\n * 登録簿から解決する(`core/filterRegistry.ts`・`bindings/getBindingInfos.ts`)。\n * 未知のフィルタもここでは落とさない: パーサだけを使う tooling は実装を持たないので、\n * 「知らない名前」を解析の段で判定できない。\n */\n/**\n * @param filterTextList 個々のフィルタの原文(`|` で切った後)\n * @param filterIOType 入力(左辺)/ 出力(右辺)。実関数は引かないが、助言の出し分けに使う\n * @param sourceText 診断に埋める原文。呼び出し側は**その辺の全文**(`propPart` / `statePart`)を\n * 渡すこと。`|` より後ろだけを渡すと、`textContent: a|` のように末尾が空の形で\n * 空文字になり、つなぎ直し(`filterTextList.join(\"|\")`)と同じで文脈が消える。\n * 省略時のつなぎ直しは、原文を持たない直接の呼び出し用のフォールバック\n */\nexport function parseFilters(filterTextList: string[], filterIOType: FilterIOType, sourceText?: string): IParsedFilter[] {\n const source = sourceText ?? filterTextList.join(\"|\");\n return filterTextList.map((filterText) => {\n // 括弧も引用符の外だけで探す(要件 B1)。素の `indexOf` / `lastIndexOf` だと\n // `foo(')')` の引用符内の `)` を終端に取り、「閉じ括弧が無い」ではなく\n // 「引用符が閉じていない」という見当違いの診断になっていた\n const openParenIndex = indexOfOutsideQuotes(filterText, '(');\n let closeParenIndex = lastIndexOfOutsideQuotes(filterText, ')');\n if (closeParenIndex === -1) {\n // 引用符の外に閉じ括弧が無い = 引用符が閉じていない形(`join('x)`)か、本当に無いか。\n // 前者で「閉じ括弧が無い」と言うのは見当違いなので素の探索へ落とし、引数の段の\n // `[wcs/binding-syntax] unterminated ' quote` に診断させる\n closeParenIndex = filterText.lastIndexOf(')');\n }\n // check parentheses\n if (openParenIndex !== -1 && closeParenIndex === -1) {\n raiseError(`[wcs/binding-syntax] Invalid filter format: missing closing parenthesis in \"${filterText}\".${LINT_HINT}`);\n }\n if (closeParenIndex !== -1 && openParenIndex === -1) {\n raiseError(`[wcs/binding-syntax] Invalid filter format: missing opening parenthesis in \"${filterText}\".${LINT_HINT}`);\n }\n if (closeParenIndex !== -1 && closeParenIndex < openParenIndex) {\n // `foo)1(` — 以前は `substring` が start > end で引数を入れ替えるため、フィルタ名\n // `foo)1` として受理されていた\n raiseError(`[wcs/binding-syntax] Invalid filter format: \")\" comes before \"(\" in \"${filterText}\".${LINT_HINT}`);\n }\n if (closeParenIndex !== -1 && filterText.slice(closeParenIndex + 1).trim().length > 0) {\n // 閉じ括弧の後ろの残余を**黙って捨てていた**。`n|fix(2)uc` は `uc` が消えて診断ゼロで\n // 通り、括弧の無い `n|ucuc` は `[wcs/filter-unknown]` で落ちる — 括弧の有無で非対称だった。\n // 実害は「`|` の打ち忘れでフィルタが 1 本消えても無診断」\n const trailing = filterText.slice(closeParenIndex + 1).trim();\n raiseError(\n `[wcs/binding-syntax] \"${filterText}\": unexpected \"${trailing}\" after the filter's closing \")\" — ` +\n `separate filters with \"|\" (write \"${filterText.slice(0, closeParenIndex + 1)}|${trailing}\").${LINT_HINT}`,\n );\n }\n const filterName = (openParenIndex === -1 ? filterText : filterText.substring(0, openParenIndex)).trim();\n if (filterName.length === 0) {\n // 空のフィルタ(`x|`・`x||y`・`x|(1)`)は文法の誤り。解析の段で名指しで落とす — 未知の\n // フィルタとは別物で、実関数の解決(束縛計画の段)まで持ち越すと tooling の解析が素通りする\n raiseError(`[wcs/binding-syntax] an empty filter in \"${source}\" — remove the extra \"|\" or name the filter.${LINT_HINT}`);\n }\n if (filterName.includes(MODIFIER_SEPARATOR)) {\n // フィルタ名に `#` が飲まれた形。`[wcs/filter-unknown] filter not found: trim#ro` だと\n // 診断が指す先が実際の誤りと違う(要件 B4 の並び)。\n // 助言は辺で分ける — **修飾子は左辺にしか存在しない**ので、右辺で「修飾子をフィルタより\n // 前に書け」と言うと成立しない直し方(`textContent#ro|trim: x`)を勧めることになる\n const [name, modifiers] = filterName.split(MODIFIER_SEPARATOR);\n raiseError(filterIOType === \"input\"\n ? `[wcs/binding-syntax] \"${filterName}\" is not a filter name: a modifier list ` +\n `\"${MODIFIER_SEPARATOR}${modifiers}\" comes before the input filters, not inside one — write ` +\n `\"<property>${MODIFIER_SEPARATOR}${modifiers}|${name}\".${LINT_HINT}`\n : `[wcs/binding-syntax] \"${filterName}\" is not a filter name: \"${MODIFIER_SEPARATOR}\" cannot appear ` +\n `in one. Modifiers belong on the left side of the binding, before the \":\" — write \"${name}\" ` +\n `here.${LINT_HINT}`);\n }\n if (openParenIndex === -1) {\n // no arguments\n return { filterName, args: [], literals: [] };\n }\n const argsText = filterText.substring(openParenIndex + 1, closeParenIndex);\n return { filterName, ...parseFilterArgsWithLiterals(argsText) };\n });\n}\n","import { DELIMITER, FILTER_SEPARATOR, MODIFIER_SEPARATOR } from \"../define\";\nimport { LINT_HINT } from \"../errorGuidance\";\nimport { raiseError } from \"../raiseError\";\nimport { IParsedBinding, IParsedFilter } from \"../types\";\nimport { parseFilters } from \"./parseFilters\";\nimport { indexOfOutsideQuotes, splitOutsideQuotes, trimFn } from \"./utils\";\n\n// 解析の段の形(フィルタは名前と引数だけ — 実関数は束縛計画の段で引く。要件 D16)\ntype PropPartParseResult = Pick<IParsedBinding, 'propName' | 'propSegments' | 'propModifiers' | 'inFilters'>;\n\nconst cacheFilterInfos = new Map<string, IParsedFilter[]>();\n\n/** tooling 専用(parser.ts の clearParserCaches からのみ呼ぶ)。 */\nexport function clearPropPartCacheForTooling(): void {\n cacheFilterInfos.clear();\n}\n\n// format: propName#moodifier1,modifier2\n// propName-format: path.to.property (e.g., textContent, style.color, not include :)\n// special path: \n// 'attr.attributeName' for attributes (e.g., attr.href, attr.data-id)\n// 'style.propertyName' for style properties (e.g., style.backgroundColor, style.fontSize)\n// 'class.className' for class names (e.g., class.active, class.hidden)\n// 'onclick', 'onchange' etc. for event listeners\n\nexport function parsePropPart(propPart: string): PropPartParseResult {\n const pos = indexOfOutsideQuotes(propPart, FILTER_SEPARATOR);\n let propText: string = '';\n let filterTexts: string[] = [];\n let filtersText = '';\n let filters: IParsedFilter[] = [];\n if (pos !== -1) {\n propText = propPart.slice(0, pos).trim();\n filtersText = propPart.slice(pos + 1).trim();\n if (cacheFilterInfos.has(filtersText)) {\n filters = cacheFilterInfos.get(filtersText)!;\n } else {\n filterTexts = splitOutsideQuotes(filtersText, FILTER_SEPARATOR).map(trimFn);\n // 診断に埋める原文は**左辺の全文**。`|` より後ろだけを渡すと `value|:` のように\n // 末尾が空の形で空文字になる(解析結果のキャッシュ鍵は従来どおり `filtersText`。\n // 落ちた解析はキャッシュに載らないので、原文を混ぜても鍵は汚れない)\n filters = parseFilters(filterTexts, \"input\", propPart);\n cacheFilterInfos.set(filtersText, filters);\n }\n } else {\n propText = propPart.trim();\n }\n\n // **不変条件**: ここから下の `split` は素で走らせてよい。`propText` は「引用符外の最初の `|`\n // より前」のスライスであり、引用符を含みうるのは入力フィルタの引数(`|` の後ろ)だけなので、\n // `#` も `,` も `.` も引用符の中に現れない。**修飾子の値に引用符を許す拡張(例\n // `value#fmt('a,b'): x`)を入れるなら、この 3 つも `splitOutsideQuotes` に替えること** —\n // 替え忘れると `structural/expandShorthandPaths.ts` で起きた「無言で 1 行も描画されない」\n // と同じ欠陥クラスが再発する。\n const modifierParts = propText.split(MODIFIER_SEPARATOR).map(trimFn);\n if (modifierParts.length > 2) {\n // 修飾子の並びは 1 つだけ(要件 B2)。`value#ro#wo` は以前 `ro` だけを残して黙って捨てていた\n raiseError(`[wcs/binding-syntax] \"${propText}\": a binding takes one modifier list after a single \"${MODIFIER_SEPARATOR}\" — write \"${modifierParts[0]}${MODIFIER_SEPARATOR}${modifierParts.slice(1).join(\",\")}\".${LINT_HINT}`);\n }\n const [propName, propModifiersText] = modifierParts;\n const propSegments = propName.split(DELIMITER).map(trimFn);\n // 明示のプロパティ形(`.name:` — 要件 B5 / D34)だけは先頭の空セグメントが正しい形。\n // それ以外で空のセグメントが残るのは書き間違い: 左辺が空(`\": x\"` / `\"#ro: x\"` / `\"|trim: x\"`)だと\n // `element[\"\"] = value` の expando ができて完全に沈黙し、末尾が空(`\"foo.: x\"`)だと適用の段で\n // 素の TypeError になる。どちらも解析の段で名指しで落とす(`.: x` 等は下の D34 の検査が受け持つ)\n const isExplicitProperty = propSegments.length > 1 && propSegments[0] === '';\n if (!isExplicitProperty && (propName.length === 0 || propSegments.some((segment) => segment.length === 0))) {\n raiseError(\n `[wcs/binding-syntax] \"${propPart}\": the left side of a binding must name a property — ` +\n `write \"<property>: <path>\" (modifiers and input filters come after the name).${LINT_HINT}`,\n );\n }\n const propModifiers = propModifiersText\n ? propModifiersText.split(',').map(trimFn)\n : [];\n return {\n propName,\n propSegments,\n propModifiers,\n inFilters: filters,\n };\n}","import { getPathInfo } from \"../address/PathInfo\";\nimport { raiseError } from \"../raiseError\";\nimport { DELIMITER, FILTER_SEPARATOR } from \"../define\";\nimport { LINT_HINT } from \"../errorGuidance\";\nimport { IParsedBinding, IParsedFilter } from \"../types\";\nimport { parseFilters } from \"./parseFilters\";\nimport { indexOfOutsideQuotes, splitOutsideQuotes, trimFn } from \"./utils\";\n\n// 解析の段の形(フィルタは名前と引数だけ — 実関数は束縛計画の段で引く。要件 D16)\ntype StatePartParseResult = Pick<IParsedBinding,\n 'statePathName' | 'statePathInfo' | 'outFilters'>;\n\nconst cacheFilterInfos = new Map<string, IParsedFilter[]>();\n\n/** tooling 専用(parser.ts の clearParserCaches からのみ呼ぶ)。 */\nexport function clearStatePartCacheForTooling(): void {\n cacheFilterInfos.clear();\n}\n\n// format: statePath|filter|filter\n// statePath-format: path.to.property (e.g., user.name.first, users.*.name, users.0.name, not include @)\n// filters-format: filterName or filterName(arg1,arg2)\nexport function parseStatePart(statePart: string): StatePartParseResult {\n // 引用符の中の `|` はフィルタの区切りではない(要件 B1 — `join('|')`)\n const pos = indexOfOutsideQuotes(statePart, FILTER_SEPARATOR);\n let stateAndPath: string = '';\n let filterTexts: string[] = [];\n let filtersText = '';\n let filters: IParsedFilter[] = [];\n if (pos !== -1) {\n stateAndPath = statePart.slice(0, pos).trim();\n filtersText = statePart.slice(pos + 1).trim();\n if (cacheFilterInfos.has(filtersText)) {\n filters = cacheFilterInfos.get(filtersText)!;\n } else {\n filterTexts = splitOutsideQuotes(filtersText, FILTER_SEPARATOR).map(trimFn);\n // 診断に埋める原文は**右辺の全文**(`parsePropPart` と同じ理由 — `a|` が空文字になる)\n filters = parseFilters(filterTexts, \"output\", statePart);\n cacheFilterInfos.set(filtersText, filters);\n }\n } else {\n stateAndPath = statePart.trim();\n }\n if (stateAndPath.indexOf(\"@\") !== -1) {\n // 名前次元は v2 で撤去(docs/state-mount-design.md D16 / §9)。パスは 1 本のツリー。\n raiseError(\n `\"${stateAndPath}\": the \"@name\" selector was removed in v2 — there is a single state tree. ` +\n `Mount the named state onto the tree (<wcs-state mount=\"...\">) and read it by its path prefix instead.`,\n );\n }\n const statePathName = stateAndPath;\n // 右辺も左辺(`parsePropPart`)と同じ規準で空セグメントを弾く(要件 B1)。放っておくと\n // `a.` / `a..b` は診断ゼロで `[\"a\",\"\",\"\"]` のまま intern され、`textContent:` /\n // `textContent: |uc` は適用の段で「`Path \"\"` が無い」というパス名が空の診断になる。\n //\n // **判定の前にループ相対の短縮形を正規化する。** `.` で始まる右辺は `for` 行の相対パスで\n // (`structural/expandShorthandPaths.ts` / `bindTextParser/expandSpread.ts` が生成し、正本の\n // パーサは展開前の原文も解析する)、先頭の空セグメント 1 つは正当。とくに **`.` 単独は\n // 「行そのもの」を指す正規の書き方**で、README と `examples/recursive-tree/index.html` の\n // `state: .` がそれ — 「先頭は許すが末尾は拒否」と素朴に書くと `\".\"` は\n // `[\"\", \"\"]` = 先頭かつ末尾なので落ちる。取り除いた残りが空でも通すこと\n const isLoopRelative = statePathName.startsWith(DELIMITER);\n const body = isLoopRelative ? statePathName.slice(DELIMITER.length) : statePathName;\n const hasEmptySegment = body.length > 0 && body.split(DELIMITER).some((segment) => segment.length === 0);\n if (hasEmptySegment || (!isLoopRelative && body.length === 0)) {\n raiseError(\n `[wcs/binding-syntax] \"${statePart}\": the right side of a binding must name a state path — ` +\n `write \"<property>: <path>\" (a path segment cannot be empty; \".\" alone and a leading \".\" are ` +\n `the loop-relative shorthand).${LINT_HINT}`,\n );\n }\n const pathInfo = getPathInfo(statePathName);\n return {\n statePathName,\n statePathInfo: pathInfo,\n outFilters: filters,\n };\n}\n","import { getPathInfo } from \"../address/PathInfo.js\";\nimport {\n ATTR_NAMESPACE,\n BINDING_SEPARATOR,\n DELIMITER,\n CLASS_NAMESPACE,\n COMMAND_NAMESPACE,\n ELSE_KEYWORD,\n STYLE_NAMESPACE,\n EVENT_PROP_PREFIX,\n FILTER_SEPARATOR,\n MODIFIER_SEPARATOR,\n EVENT_TOKEN_NAMESPACE,\n PROP_VALUE_SEPARATOR,\n SPREAD_PROP,\n VOLUME_INJECTION_PROP,\n} from \"../define.js\";\nimport { LINT_HINT } from \"../errorGuidance.js\";\nimport { raiseError } from \"../raiseError.js\";\nimport { STRUCTURAL_BINDING_TYPE_SET } from \"../structural/define.js\";\nimport { parsePropPart } from \"./parsePropPart.js\";\nimport { parseStatePart } from \"./parseStatePart.js\";\nimport { ParseBindTextResult } from \"./types.js\";\nimport { indexOfOutsideQuotes, splitOutsideQuotes, trimFn } from \"./utils.js\";\n\n// format: propPart:statePart; propPart:statePart; ...\n// special-propPart:\n// if: statePart (single binding for conditional rendering)\n// else: (single binding for conditional rendering, and statePart is ignored)\n// elseif: statePart only (single binding for conditional rendering)\n// for: statePart only (single binding for loop rendering)\n// onclick: statePart, onchange: statePart etc. (event listeners)\n// ...: statePart (spread — expand wcBindable properties+inputs of target object)\n\n/** 左辺に修飾子も入力フィルタも取らない束縛(構造ディレクティブと spread)— 付いていれば拒否する(要件 B4) */\nconst KEYWORDS_WITHOUT_MODIFIERS = new Set<string>([ELSE_KEYWORD, 'if', 'elseif', 'for', SPREAD_PROP]);\n\n/**\n * 明示のプロパティ形(`.name:`)の先頭に置けない語 — 名前空間として読まれる語(要件 B5)。\n * `state`(`VOLUME_INJECTION_PROP`)も含む: `<wcs-state mount>` 上の左辺 `state.<key>:` は\n * 注入の宣言(要件 B14③)なので、`.state.taxRate:` はプロパティか注入か曖昧になる。\n */\nconst EXPLICIT_PROPERTY_REJECTED_HEADS = new Set<string>([\n CLASS_NAMESPACE, ATTR_NAMESPACE, STYLE_NAMESPACE, COMMAND_NAMESPACE, EVENT_TOKEN_NAMESPACE,\n VOLUME_INJECTION_PROP,\n]);\n\n/**\n * `data-wcs` の値をバインディングごとに区切る(前後の空白は残す — tooling が位置を数えられるように)。\n * 引用符の中の `;` は区切りではない(要件 B1 — `join(';')`)。ランタイムと tooling(`@wcstack/state/parser`)で共有する\n */\nexport function splitBindTexts(bindText: string): string[] {\n return splitOutsideQuotes(bindText, BINDING_SEPARATOR);\n}\n\nexport function parseBindTextsForElement(bindText: string): ParseBindTextResult[] {\n const [ ...bindTexts ] = splitBindTexts(bindText).map(trimFn).filter(s => s.length > 0);\n const results = bindTexts.map((bindText): ParseBindTextResult => {\n // 左辺と右辺の区切りも引用符の外だけで探す(要件 B1)。`value|defaults(':'): path` の\n // 引数の中の `:` を区切りとして拾っていた\n const separatorIndex = indexOfOutsideQuotes(bindText, PROP_VALUE_SEPARATOR);\n if (separatorIndex === -1) {\n raiseError(`[wcs/binding-syntax] Invalid bindText: \"${bindText}\". Missing ':' separator between propPart and statePart.${LINT_HINT}`);\n }\n const propPart = bindText.slice(0, separatorIndex).trim();\n const statePart = bindText.slice(separatorIndex + 1).trim();\n // 種別は修飾子・入力フィルタより前の名前で決める(要件 B4)。以前は左辺全体との完全一致で\n // 判定していたので、`radio#ro:` が汎用プロパティに落ちていた。\n // **不変条件**: ここは素の `split` でよい — 取り出すのは最初の区切りより前の**先頭**片で、\n // 引用符を含みうるのは入力フィルタの引数(引用符外の最初の `|` より後ろ)だけなので、\n // `#` も `|` も引用符の中では出会わない。**修飾子の値に引用符を許す拡張を入れるなら\n // `indexOfOutsideQuotes` に替えること**(`parsePropPart.ts` の同じ注記と対)。\n const keyword = propPart.split(MODIFIER_SEPARATOR)[0].split(FILTER_SEPARATOR)[0].trim();\n if (keyword !== propPart && KEYWORDS_WITHOUT_MODIFIERS.has(keyword)) {\n raiseError(`[wcs/binding-syntax] \"${bindText}\": \"${keyword}\" takes no modifiers or filters on its left side — write \"${keyword}:\".${LINT_HINT}`);\n }\n if (propPart === ELSE_KEYWORD) {\n if (statePart.length > 0) {\n // else は値を取らない(要件 B2)。以前は右辺を黙って捨てていた\n raiseError(`[wcs/binding-syntax] \"${bindText}\": \"else\" takes no value — write \"else:\".${LINT_HINT}`);\n }\n const pathInfo = getPathInfo('#else');\n return {\n propName: ELSE_KEYWORD,\n propSegments: [ELSE_KEYWORD],\n propModifiers: [],\n statePathName: '#else',\n statePathInfo: pathInfo,\n inFilters: [],\n outFilters: [],\n bindingType: 'else',\n };\n } else if (propPart === SPREAD_PROP) {\n // 空の右辺は spread 専用の語彙で先に落とす。`parseStatePart` の一般の空パス診断\n // (「the right side of a binding must name a state path」)より、ここでは\n // 「spread target path is required」のほうが直し方を指している\n if (statePart.length === 0) {\n raiseError(`[wcs/binding-syntax] Invalid spread binding \"${bindText}\": spread target path is required.${LINT_HINT}`);\n }\n const stateResult = parseStatePart(statePart);\n if (stateResult.outFilters.length > 0) {\n raiseError(`[wcs/binding-syntax] Invalid spread binding \"${bindText}\": filters are not allowed on spread targets.${LINT_HINT}`);\n }\n return {\n propName: SPREAD_PROP,\n propSegments: [SPREAD_PROP],\n propModifiers: [],\n inFilters: [],\n ...stateResult,\n bindingType: 'spread',\n };\n } else if (propPart === 'if'\n || propPart === 'elseif'\n || propPart === 'for'\n ) {\n const stateResult = parseStatePart(statePart);\n return {\n propName: propPart,\n propSegments: [propPart],\n propModifiers: [],\n inFilters: [],\n ...stateResult,\n bindingType: propPart,\n };\n } else if (keyword === 'radio' || keyword === 'checkbox') {\n // 修飾子(`#ro`・`#onchange` …)と入力フィルタは radio / checkbox のハンドラが読む(要件 B4)\n const stateResult = parseStatePart(statePart);\n const propResult = parsePropPart(propPart);\n return {\n ...propResult,\n ...stateResult,\n bindingType: keyword,\n };\n } else {\n const stateResult = parseStatePart(statePart);\n const propResult = parsePropPart(propPart);\n // 左辺の先頭ドット(`.online:`)は明示のプロパティ形(要件 B5・3.x 計画 D34)。ドットの無い形と\n // 同じ束縛だが、`on` で始まってもイベントにはならない(`online:` は \"line\" イベントを待つ)。\n // 名前空間の語(`.class.x` / `.command.x` …)はプロパティか名前空間か曖昧なので受けない\n if (propResult.propSegments[0] === '' && propResult.propSegments.length > 1) {\n const propSegments = propResult.propSegments.slice(1);\n if (propSegments.includes('') || EXPLICIT_PROPERTY_REJECTED_HEADS.has(propSegments[0])) {\n raiseError(\n `[wcs/binding-syntax] \"${propPart}\": a leading \".\" binds an element property by name — ` +\n `write a non-empty property that is not a namespace (${[...EXPLICIT_PROPERTY_REJECTED_HEADS].join(\", \")}).${LINT_HINT}`,\n );\n }\n return {\n ...propResult,\n propName: propSegments.join(DELIMITER),\n propSegments,\n ...stateResult,\n bindingType: 'prop',\n };\n }\n // eventToken.<prop>: <name> は要素 dispatch を state へ流す pub/sub 配線。\n // 値適用ではないため bindingType 'event' として listener attach 経路に乗せる。\n if (propResult.propSegments[0] === EVENT_TOKEN_NAMESPACE) {\n return {\n ...propResult,\n ...stateResult,\n bindingType: 'event',\n };\n }\n if (propResult.propSegments[0].startsWith(EVENT_PROP_PREFIX)) {\n return {\n ...propResult,\n ...stateResult,\n bindingType: 'event',\n };\n } else {\n return {\n ...propResult,\n ...stateResult,\n bindingType: 'prop',\n };\n }\n }\n });\n // check for sigle binding for 'if', 'elseif', 'else', 'for'\n if (results.length > 1) {\n const isIncludeSingleBinding = results.some(r => STRUCTURAL_BINDING_TYPE_SET.has(r.bindingType));\n if (isIncludeSingleBinding) {\n // lint 側の単独バインディング検査(bindingValidator の structuralMustBeSingle)が\n // 同じケースを検出するため誘導を付ける(三面同語彙)。\n raiseError(`[wcs/template-syntax] Invalid bindText: \"${bindText}\". 'if', 'elseif', 'else', and 'for' bindings must be single binding. Put the structural binding alone in its own data-wcs (e.g. <template data-wcs=\"for: items\">).${LINT_HINT}`);\n }\n }\n return results;\n}\n\n","import { config } from \"../config\";\n\nconst bindTextByNode = new WeakMap<Node, string>();\n\n// format: <!--@@wcs-text:path-->\n// bind-stateはconfig.commentTextPrefixで変更可能\n// format: <!--@@wcs-for:UUID-->\n// bind-stateはconfig.commentForPrefixで変更可能\n// format: <!--@@wcs-if:UUID-->\n// bind-stateはconfig.commentIfPrefixで変更可能\n// format: <!--@@wcs-else:UUID-->\n// bind-stateはconfig.commentElsePrefixで変更可能\n// format: <!--@@wcs-elseif:UUID-->\n// bind-stateはconfig.commentElseIfPrefixで変更可能\nconst bindingTypeKeywordSet: Set<string> = new Set<string>([\n config.commentTextPrefix,\n config.commentForPrefix,\n config.commentIfPrefix,\n config.commentElseIfPrefix,\n config.commentElsePrefix,\n]);\n\n// format: <!--@@:path-->は<!--@@wcs-text:path-->と同義にする\nconst EMBEDDED_REGEX = /*#__PURE__*/ new RegExp(`^\\\\s*@@\\\\s*(.*?)\\\\s*:\\\\s*(.+?)\\\\s*$`);\n\nexport function parseCommentNode(node: Node): string | null {\n const savedText = bindTextByNode.get(node);\n if (typeof savedText === \"string\") {\n return savedText;\n }\n if (node.nodeType !== Node.COMMENT_NODE) {\n return null;\n }\n const commentNode = node as Comment;\n const text = commentNode.data.trim();\n const match = EMBEDDED_REGEX.exec(text);\n if (match === null) {\n return null;\n }\n // 空の場合は wcs-text として扱う\n const keyword = match[1] || config.commentTextPrefix;\n if (!bindingTypeKeywordSet.has(keyword)) {\n return null;\n }\n bindTextByNode.set(node, match[2]);\n return match[2];\n}\n\nexport function getCommentNodeBindText(node: Node): string | null {\n return bindTextByNode.get(node) || null;\n}","import { parseStatePart } from \"./parseStatePart.js\";\nimport { ParseBindTextResult } from \"./types.js\";\n\nexport function parseBindTextForEmbeddedNode(bindText: string): ParseBindTextResult {\n const stateResult = parseStatePart(bindText);\n return {\n propName: 'textContent',\n propSegments: ['textContent'],\n propModifiers: [],\n inFilters: [],\n ...stateResult,\n bindingType: 'text',\n }\n}","import { IInitializeBindingPromise } from \"./types\";\n\nconst bindingPromiseByNode = new WeakMap<Node, IInitializeBindingPromise>();\n// resolve 済みマーク。エントリ未生成のまま resolve されたノードは、後から\n// wait された時に「生成して即 resolve」で追いつく。\nconst resolvedNodes = new WeakSet<Node>();\n\nlet id = 0;\n\nexport function getInitializeBindingPromiseByNode(node: Node): IInitializeBindingPromise {\n let bindingPromise = bindingPromiseByNode.get(node) || null;\n if (bindingPromise !== null) {\n return bindingPromise;\n }\n let resolveFn = undefined;\n const promise = new Promise<void>((resolve) => {\n resolveFn = resolve;\n });\n bindingPromise = {\n id: ++id,\n promise,\n resolve: resolveFn!\n };\n bindingPromiseByNode.set(node, bindingPromise);\n if (resolvedNodes.has(node)) {\n bindingPromise.resolve();\n }\n return bindingPromise;\n}\n\nexport async function waitInitializeBinding(node: Node): Promise<void> {\n const bindingPromise = getInitializeBindingPromiseByNode(node);\n await bindingPromise.promise;\n}\n\nexport function resolveInitializedBinding(node: Node): void {\n // ホットパス: リスト行では全 subscriber ノードがここを通るが、await する消費者\n // (boundComponent / shadowRoot host)はほぼ居ない。既存エントリが無ければ\n // Promise+closure を生成せず resolve 済みマークだけ残す(15 万個級の割り当て削減)。\n const existing = bindingPromiseByNode.get(node);\n if (typeof existing !== \"undefined\") {\n existing.resolve();\n return;\n }\n resolvedNodes.add(node);\n}\n","\nconst cache = new WeakMap<Node, string | null>();\n\nexport function getCustomElement(node: Node): string | null {\n const cached = cache.get(node);\n if (cached !== undefined) {\n return cached;\n }\n let value: string | null = null;\n try {\n if (node.nodeType !== Node.ELEMENT_NODE) {\n return value;\n }\n const element = node as Element;\n const tagName = element.tagName.toLowerCase();\n if (tagName.includes(\"-\")) {\n return value = tagName;\n }\n if (element.hasAttribute(\"is\")) {\n const is = element.getAttribute(\"is\")!;\n if (is.includes(\"-\")) {\n return value = is;\n }\n }\n return value;\n } finally {\n cache.set(node, value);\n }\n}\n","export interface ICustomElementRegistryAdapter {\n get(name: string): CustomElementConstructor | undefined;\n whenDefined(name: string): Promise<CustomElementConstructor>;\n upgrade?(root: Node): void;\n define?(name: string, constructor: CustomElementConstructor): void;\n}\n\nexport interface ICustomElementRegistryOwner {\n /**\n * Scoped registry hook, as exposed by `Element` / `Document` / `ShadowRoot`.\n * `undefined` on platforms without scoped custom element registries; `null`\n * when the node deliberately carries a null registry (a declarative shadow\n * root with `shadowrootcustomelementregistry`, or a document from\n * `createHTMLDocument()`) and has not been handed to `registry.initialize()`.\n */\n readonly customElementRegistry?: unknown;\n /** Legacy owner form: a `Window`-like object carrying a registry. */\n readonly customElements?: unknown;\n}\n\nfunction toAdapter(registry: unknown): ICustomElementRegistryAdapter | null {\n if (typeof registry !== \"object\" || registry === null) return null;\n\n const candidate = registry as Partial<ICustomElementRegistryAdapter>;\n if (typeof candidate.get !== \"function\" || typeof candidate.whenDefined !== \"function\") {\n return null;\n }\n return candidate as ICustomElementRegistryAdapter;\n}\n\n/**\n * Resolve the registry that governs `owner` at operation time, so importing the\n * runtime stays safe when browser globals are absent.\n *\n * Pass the node the operation is about (the bound element, its shadow root):\n * with scoped custom element registries the same tag name can resolve to a\n * different constructor per tree, so \"is this tag defined?\" is only meaningful\n * relative to a node. Nodes on platforms without scoped registries report\n * `undefined` and fall back to the global registry, which keeps every existing\n * caller on today's behaviour.\n */\nexport function getCustomElementRegistry(\n owner: ICustomElementRegistryOwner | Node | null = null,\n): ICustomElementRegistryAdapter | null {\n if (owner !== null && typeof owner !== \"undefined\") {\n const { customElementRegistry: scoped, customElements: owned } =\n owner as ICustomElementRegistryOwner;\n // A node in a null-registry subtree resolves to no registry at all. Falling\n // back to the global one would report globally-defined tags as usable and\n // let us write own properties onto elements that are still un-upgraded --\n // exactly the accessor shadowing the deferred-apply path exists to avoid.\n if (scoped === null) return null;\n if (typeof scoped !== \"undefined\") return toAdapter(scoped);\n if (typeof owned !== \"undefined\") return toAdapter(owned);\n }\n return toAdapter((globalThis as { readonly customElements?: unknown }).customElements);\n}\n\nexport function upgradeCustomElement(\n registry: ICustomElementRegistryAdapter,\n root: Node,\n): void {\n registry.upgrade?.(root);\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/wc-bindable-reader.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\nimport type {\n IWcBindable,\n IWcBindableCommand,\n IWcBindableInput,\n IWcBindableProperty,\n} from \"./wcBindable.js\";\n\nexport const MIN_WC_BINDABLE_VERSION = 1;\n\nexport interface WcBindableElement {\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions,\n ): void;\n readonly constructor: {\n readonly wcBindable: IWcBindable;\n };\n}\n\nexport interface ReadBindableResult {\n readonly target: WcBindableElement;\n readonly liveDeclaration: IWcBindable;\n readonly knownProperties: ReadonlyMap<string, IWcBindableProperty>;\n readonly declaredInputs: ReadonlyMap<string, IWcBindableInput>;\n readonly declaredCommands: ReadonlyMap<string, IWcBindableCommand>;\n}\n\n/**\n * Repository-local conformance mirror of @wc-bindable/core's\n * getWcBindableDeclaration(). Discovery has one path only:\n * target.constructor.wcBindable.\n *\n * The declaration remains live. The maps are read-time indexes and are not a\n * clone, freeze, or normalized replacement for liveDeclaration.\n */\nexport function readBindableDeclaration(target: unknown): ReadBindableResult | null {\n try {\n if (target === null || (typeof target !== \"object\" && typeof target !== \"function\")) {\n return null;\n }\n\n const candidate = target as {\n readonly addEventListener?: unknown;\n readonly removeEventListener?: unknown;\n readonly constructor?: { readonly wcBindable?: IWcBindable };\n };\n const addEventListener = candidate.addEventListener;\n const removeEventListener = candidate.removeEventListener;\n const declaration = candidate.constructor?.wcBindable;\n\n if (typeof addEventListener !== \"function\" || typeof removeEventListener !== \"function\") {\n return null;\n }\n if (declaration?.protocol !== \"wc-bindable\") return null;\n if (!Number.isInteger(declaration.version) || declaration.version < MIN_WC_BINDABLE_VERSION) {\n return null;\n }\n\n const knownProperties = readNamedList(declaration.properties, isValidPropertyDescriptor);\n if (knownProperties === null) return null;\n\n const declaredInputs = declaration.inputs === undefined\n ? new Map<string, IWcBindableInput>()\n : readNamedList(declaration.inputs, isValidInputDescriptor);\n if (declaredInputs === null) return null;\n\n const declaredCommands = declaration.commands === undefined\n ? new Map<string, IWcBindableCommand>()\n : readNamedList(declaration.commands, isValidCommandDescriptor);\n if (declaredCommands === null) return null;\n\n return {\n target: target as WcBindableElement,\n liveDeclaration: declaration,\n knownProperties,\n declaredInputs,\n declaredCommands,\n };\n } catch {\n return null;\n }\n}\n\nfunction isValidPropertyDescriptor(value: unknown): value is IWcBindableProperty {\n if (typeof value !== \"object\" || value === null) return false;\n const descriptor = value as Partial<IWcBindableProperty>;\n if (typeof descriptor.name !== \"string\" || descriptor.name.length === 0) return false;\n if (typeof descriptor.event !== \"string\" || descriptor.event.length === 0) return false;\n return descriptor.getter === undefined || typeof descriptor.getter === \"function\";\n}\n\nfunction isValidInputDescriptor(value: unknown): value is IWcBindableInput {\n if (typeof value !== \"object\" || value === null) return false;\n const descriptor = value as Partial<IWcBindableInput>;\n if (typeof descriptor.name !== \"string\" || descriptor.name.length === 0) return false;\n return descriptor.attribute === undefined || typeof descriptor.attribute === \"string\";\n}\n\nfunction isValidCommandDescriptor(value: unknown): value is IWcBindableCommand {\n if (typeof value !== \"object\" || value === null) return false;\n const descriptor = value as Partial<IWcBindableCommand>;\n if (typeof descriptor.name !== \"string\" || descriptor.name.length === 0) return false;\n return descriptor.async === undefined || typeof descriptor.async === \"boolean\";\n}\n\nfunction readNamedList<T extends { readonly name: string }>(\n value: unknown,\n isValidEntry: (entry: unknown) => entry is T,\n): ReadonlyMap<string, T> | null {\n if (!Array.isArray(value)) return null;\n const entries = new Map<string, T>();\n for (const entry of value) {\n if (!isValidEntry(entry) || entries.has(entry.name)) return null;\n entries.set(entry.name, entry);\n }\n return entries;\n}\n","import { getPathInfo } from \"../address/PathInfo\";\nimport { config } from \"../config\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry, upgradeCustomElement } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\nimport { raiseError } from \"../raiseError\";\nimport { ParseBindTextResult } from \"./types\";\n\nfunction makeExpandedEntry(\n name: string,\n base: string,\n): ParseBindTextResult {\n // Dot-relative spread keeps the loop item root (`.`) without producing `..foo`.\n const expandedPath = base === \".\" ? `.${name}` : `${base}.${name}`;\n return {\n propName: name,\n propSegments: [name],\n propModifiers: [],\n statePathName: expandedPath,\n statePathInfo: getPathInfo(expandedPath),\n inFilters: [],\n outFilters: [],\n bindingType: 'prop',\n };\n}\n\nfunction dedupKey(r: ParseBindTextResult): string | null {\n switch (r.bindingType) {\n case 'prop':\n case 'event':\n case 'radio':\n case 'checkbox':\n return `${r.bindingType}::${r.propName}`;\n case 'spread':\n return null;\n default:\n return null;\n }\n}\n\nexport interface IExpandSpreadOptions {\n /**\n * When false, raise an error if the custom element class is not yet defined.\n * When true (default), leave the spread entry in place so the caller can\n * defer expansion via customElements.whenDefined.\n */\n readonly allowDeferred?: boolean;\n}\n\n/**\n * Expand spread bind-text entries (`...: target`) into per-prop entries\n * by enumerating wcBindable.properties + inputs of the element's class.\n *\n * Behavior:\n * - With `allowDeferred: true` (default): if class is not yet defined, the\n * spread entry stays so the caller can wait via customElements.whenDefined.\n * - With `allowDeferred: false`: raises if class is not defined.\n * - Duplicate propName: last-wins (explicit binding overrides spread).\n * - When config.debug, console.debug logs each override.\n * - Mid-`*` in target path is allowed (e.g. `...: stores.*.fetch`).\n *\n * Composite Profile (COMPOSITE.md / SPEC-extensions § 4) support:\n * - A composite shell exposes its synthesized declaration via the standard\n * `target.constructor.wcBindable` surface (§ 1 Discovery), so this function\n * handles it without any composite-specific code path.\n * - Composed property names use the `<sourceId>.<sourceName>` pattern\n * (e.g. \"s3.progress\"); we keep the dotted name as a single segment so\n * element member access stays flat (element[\"s3.progress\"], not nested).\n * - The expanded state path becomes `targetBase.s3.progress`, which resolves\n * as nested state access — author state as `{ s3: { progress: 0 } }` to\n * mirror the composed structure.\n * - Tier claim (Symbol.for(\"wc-bindable.composite.tiers\")) is not read here;\n * spread covers observation (T1) and writable inputs (T2) transparently\n * through normal property assignment, and commands stay out of spread by\n * design regardless of tier.\n */\nexport function expandSpread(\n node: Node,\n results: ParseBindTextResult[],\n options: IExpandSpreadOptions = {},\n): ParseBindTextResult[] {\n const allowDeferred = options.allowDeferred ?? true;\n if (!results.some(r => r.bindingType === 'spread')) {\n return results;\n }\n const expanded: ParseBindTextResult[] = [];\n const spreadOrigin = new WeakSet<ParseBindTextResult>();\n for (const result of results) {\n if (result.bindingType !== 'spread') {\n expanded.push(result);\n continue;\n }\n if (node.nodeType !== Node.ELEMENT_NODE) {\n raiseError(`Spread binding requires an element node.`);\n }\n const element = node as Element;\n const tagName = getCustomElement(element);\n if (tagName === null) {\n raiseError(`Spread binding \"${result.statePathName}\" requires a custom element with wcBindable, but <${element.tagName.toLowerCase()}> is not a custom element.`);\n }\n const registry = getCustomElementRegistry(element);\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${tagName}>.`);\n }\n const customClass = registry.get(tagName);\n if (typeof customClass === \"undefined\") {\n if (!allowDeferred) {\n raiseError(`Spread binding \"${result.statePathName}\" requires <${tagName}> to be registered. Define the custom element before initializing this binding.`);\n }\n // Deferred: keep spread entry intact; caller retries via whenDefined.\n expanded.push(result);\n continue;\n }\n upgradeCustomElement(registry, element);\n const bindable = readBindableDeclaration(element);\n if (bindable === null) {\n raiseError(`Spread binding \"${result.statePathName}\" requires <${tagName}> to expose a valid wcBindable declaration.`);\n }\n const targetBase = result.statePathName;\n const seen = new Set<string>();\n for (const name of bindable.knownProperties.keys()) {\n if (seen.has(name)) continue;\n seen.add(name);\n const entry = makeExpandedEntry(name, targetBase);\n spreadOrigin.add(entry);\n expanded.push(entry);\n }\n // properties win over inputs when the name overlaps because they carry the\n // full property contract (for example change events).\n for (const name of bindable.declaredInputs.keys()) {\n if (seen.has(name)) continue;\n seen.add(name);\n const entry = makeExpandedEntry(name, targetBase);\n spreadOrigin.add(entry);\n expanded.push(entry);\n }\n }\n // Last-wins de-duplication\n const lastIndexByKey = new Map<string, number>();\n for (let i = 0; i < expanded.length; i++) {\n const key = dedupKey(expanded[i]);\n if (key !== null) {\n lastIndexByKey.set(key, i);\n }\n }\n const final: ParseBindTextResult[] = [];\n for (let i = 0; i < expanded.length; i++) {\n const key = dedupKey(expanded[i]);\n if (key === null) {\n final.push(expanded[i]);\n continue;\n }\n if (lastIndexByKey.get(key) === i) {\n final.push(expanded[i]);\n } else if (config.debug && spreadOrigin.has(expanded[i])) {\n const overrider = expanded[lastIndexByKey.get(key)!];\n const tagText = node.nodeType === Node.ELEMENT_NODE\n ? `<${(node as Element).tagName.toLowerCase()}>`\n : 'node';\n console.debug(`[@wcstack/state] spread: prop \"${expanded[i].propName}\" of ${tagText} overridden by explicit binding (statePath: \"${overrider.statePathName}\").`);\n }\n }\n return final;\n}\n\nexport function hasUnresolvedSpread(results: ParseBindTextResult[]): boolean {\n return results.some(r => r.bindingType === 'spread');\n}\n","export function resolveNodePath(root: Node, path: number[]): Node | null {\n let currentNode: Node | null = root;\n // childNodes[i] ではなく兄弟ポインタで辿る。複製したばかりの行では、childNodes に触れた\n // ノードごとに NodeList(と NodeRareData)が作られ、行の寿命のあいだ残る。行テンプレートの\n // 子は数個なので、辿る歩数は添字の分だけで済む(設計 R5)。\n //\n // 負の添字は `childNodes[-1]`(= undefined → null)とは違い `firstChild` を返す。nodePath は\n // `getNodePath` が実 DOM を数えて作る内部の値で、負の数は生じない(範囲外は `null` で\n // `compileRowPlan` が不適格に倒す)ため、この差は観測されない。\n for (let i = 0; i < path.length; i++) {\n let remaining = path[i];\n currentNode = currentNode.firstChild;\n while (currentNode !== null && remaining > 0) {\n currentNode = currentNode.nextSibling;\n remaining--;\n }\n if (currentNode === null) break;\n }\n return currentNode;\n}\n","/**\n * bindings/planFilters.ts — 束縛計画の段でフィルタの実関数を引く(要件 D16)。\n *\n * 解析の段(`bindTextParser/parseFilters.ts`)は名前と引数しか作らない。実関数は\n * 登録簿(`core/filterRegistry.ts`)から**ここで**引く。未知のフィルタが名指しで落ちるのも\n * ここ — ページの構築時であって、最初の更新の最中ではない。\n *\n * 呼び出し点は 2 つ: 通常経路の `getBindingInfos`(ノードごと)と、行プラン\n * `structural/rowPlan.ts`(テンプレートごとに 1 回、行不変の解決として焼き込む)。\n */\nimport type { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { resolveFilterFn } from \"../core/filterRegistry\";\nimport type { FilterIOType } from \"../filters/types\";\nimport type { IBindingInfo, IFilterInfo, IParsedFilter } from \"../types\";\n\n/** node / replaceNode 以外が確定したバインディング(行プランのスロットが持つ形) */\nexport type IPlannedBinding = Omit<IBindingInfo, \"node\" | \"replaceNode\">;\n\nexport function planFilters(filters: IParsedFilter[], filterIOType: FilterIOType): IFilterInfo[] {\n if (filters.length === 0) {\n // 空配列は共有してよい(フィルタ無しの宣言が大多数)\n return filters as IFilterInfo[];\n }\n const planned: IFilterInfo[] = [];\n for (let i = 0; i < filters.length; i++) {\n const filter = filters[i];\n // `literals`(型付きの値・要件 B9)は**落とさずに持ち回す**。落とすと、これより後ろで\n // フィルタの並びを鍵にする側(`binding/filterKey.ts` — ハンドラ共有キー・束縛キー・\n // devtools の宣言キー)が原文 `args` しか見られず、`defaults(0)` と `defaults('0')` を\n // 取り違えてハンドラを共有してしまう\n const literals = filter.literals ?? filter.args;\n planned.push({\n filterName: filter.filterName,\n args: filter.args,\n literals,\n filterFn: resolveFilterFn(filter.filterName, filter.args, filterIOType, literals),\n });\n }\n return planned;\n}\n\nexport function planBinding(parsed: ParseBindTextResult): IPlannedBinding {\n return {\n ...parsed,\n inFilters: planFilters(parsed.inFilters, \"input\"),\n outFilters: planFilters(parsed.outFilters, \"output\"),\n };\n}\n","import { IBindingInfo } from \"../binding/types\";\n\nconst bindingsByNode = new WeakMap<Node, IBindingInfo[]>();\n\nexport function getBindingsByNode(node: Node): IBindingInfo[] | null {\n return bindingsByNode.get(node) || null;\n}\n\nexport function setBindingsByNode(node: Node, bindings: IBindingInfo[]): void {\n bindingsByNode.set(node, bindings);\n}\n\nexport function addBindingByNode(node: Node, binding: IBindingInfo): void {\n const bindings = getBindingsByNode(node);\n if (bindings === null) {\n setBindingsByNode(node, [binding]);\n } else {\n bindings.push(binding);\n }\n}","/**\n * bindings/lightDomComponentScope.ts — Light DOM の mapped `bind-component` を\n * 「ホストとは別のバインディングスコープ」として扱うための判定\n * (docs/architecture-hardening/15-state-component-mechanism-consistency.md §1.13)。\n *\n * Shadow DOM 形では、コンポーネントの `<wcs-state>` が**別 rootNode** にいることで\n * 2 つのことが同時に成立している。\n *\n * 1. ホスト root の `waitForStateInitialize` の走査集合に入らない\n * 2. 子スコープのバインディングがホストとは別の `buildBindings` パスで処理される\n *\n * Light DOM では両方が失われる。1 が失われると、\n * 「ホストの `waitForStateInitialize` が子 state を待つ →\n * 子 state は自分を束ねるホスト binding を待つ →\n * その binding を作る `initializeBindings` は `waitForStateInitialize` の後」\n * という循環になり、初期化が永久に解決しない。2 が失われると、子スコープの\n * `@name` 参照がホストと同じパスで解決されてしまい、子 state の名前登録より\n * 先に評価される。\n *\n * このモジュールはその 2 つを明示的に復元するための判定だけを持つ。\n *\n * **plain(ホストからバインドしない state 注入)の Light DOM は v2 で廃止**\n *(State._initializeBindWebComponent が raise する — 共有 rootNode に独立ツリーを\n * 置けないため。shadow を付ければ plain Shadow 形として従来どおり動く)。\n * ここの判定が「ホストからバインドされているか」を見るのはその名残ではなく、\n * マウント(配線あり)だけをスコープとして切り出すため。\n */\n\nimport { config } from \"../config\";\n\n/** `<wcs-state bind-component>` が Light DOM の mapped 形(=別スコープ扱い)か。 */\nexport function isLightDomMappedStateElement(stateElement: Element): boolean {\n if (!stateElement.hasAttribute(\"bind-component\")) {\n return false;\n }\n const parentNode = stateElement.parentNode;\n // Shadow DOM 形では parentNode が ShadowRoot になる(かつホスト root の\n // querySelectorAll にはそもそも出てこない)\n if (!(parentNode instanceof Element)) {\n return false;\n }\n // ホストからバインドされていなければ plain。従来どおりの扱いに任せる\n return parentNode.hasAttribute(config.bindAttributeName);\n}\n\n/**\n * `root` の内側にある Light DOM mapped コンポーネント要素を集める。\n *\n * `root` 自身は**含めない**。子スコープが自分のパスとして\n * `initializeBindings(componentElement)` を呼ぶとき、その要素自身まで prune すると\n * 何も初期化されなくなるため。\n */\nexport function findNestedLightDomComponents(root: Document | Element | DocumentFragment): Element[] {\n const components: Element[] = [];\n const stateElements = root.querySelectorAll(`${config.tagNames.state}[bind-component]`);\n for (const stateElement of stateElements) {\n if (!isLightDomMappedStateElement(stateElement)) {\n continue;\n }\n const component = stateElement.parentNode as Element;\n if (component === (root as unknown as Element)) {\n continue;\n }\n components.push(component);\n }\n return components;\n}\n\n/** `node` が、いずれかのコンポーネント要素の**真の**子孫か。 */\nexport function isInsideAnyComponent(node: Node, components: Element[]): boolean {\n for (let i = 0; i < components.length; i++) {\n const component = components[i];\n if (component !== node && component.contains(node)) {\n return true;\n }\n }\n return false;\n}\n","import { config } from \"../config\";\nimport { findNestedLightDomComponents, isInsideAnyComponent } from \"./lightDomComponentScope\";\nimport { parseCommentNode } from \"./parseCommentNode\";\n\n/**\n * data-wcs 属性または埋め込みノード<!--{{}}-->を持つノードをすべて取得する\n *\n * Light DOM の mapped コンポーネントの**内側**は除外する(§1.13)。そのサブツリーの\n * `@name` 参照は、コンポーネント側の state が名前登録を済ませてからでないと解決できず、\n * ホストと同じパスで拾うと登録前に評価されてしまう。除外したぶんは、その state が\n * 初期化を終えた時点で自分のスコープとして `initializeBindings(componentElement)` を\n * 呼び直す(Shadow DOM 形で rootNode ごとにパスが分かれるのと同じ形にする)。\n *\n * コンポーネント要素**自身**は除外しない。ホスト側の `data-wcs`(`state.msg: user.name`)\n * はホストのスコープに属し、それが張られることで子側の待ちが解ける。\n *\n * @param root\n * @returns\n */\n\nexport function getSubscriberNodes(root: Document | Element | DocumentFragment): Node[] {\n const subscriberNodes: Node[] = [];\n const nestedComponents = findNestedLightDomComponents(root);\n const walker = document.createTreeWalker(\n root, \n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT, \n {\n acceptNode(node: Node) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as Element;\n const hasBinding = element.hasAttribute(config.bindAttributeName);\n return hasBinding\n ? NodeFilter.FILTER_ACCEPT\n : NodeFilter.FILTER_SKIP;\n } else {\n // Comment node\n return parseCommentNode(node) !== null\n ? NodeFilter.FILTER_ACCEPT \n : NodeFilter.FILTER_SKIP;\n }\n }\n }\n );\n \n while (walker.nextNode()) {\n const node = walker.currentNode;\n // TreeWalker の acceptNode は「自分は拾うが子孫は辿らない」を表現できないため、\n // コンポーネント要素自身を拾ったうえで、その子孫をここで落とす。\n // nestedComponents が空(=圧倒的多数)のときは contains 走査ごと発生しない。\n if (nestedComponents.length > 0 && isInsideAnyComponent(node, nestedComponents)) {\n continue;\n }\n subscriberNodes.push(node);\n }\n return subscriberNodes;\n}","import { expandSpread, hasUnresolvedSpread } from \"../bindTextParser/expandSpread\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { raiseError } from \"../raiseError\";\nimport { resolveNodePath } from \"../structural/resolveNodePath\";\nimport { IFragmentNodeInfo } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\nimport { getBindingInfos } from \"./getBindingInfos\";\nimport { setBindingsByNode } from \"./getBindingsByNode\";\nimport { getParseBindTextResults } from \"./getParseBindTextResults\";\nimport { getSubscriberNodes } from \"./getSubscriberNodes\";\nimport { resolveInitializedBinding } from \"./initializeBindingPromiseByNode\";\n\nconst registeredNodeSet = new WeakSet<Node>();\n\n/**\n * パース結果の変換フック(Phase 2 のマウント — impl-plan §3-0 の 1)。\n * マウントされたスコープの収集は、これで各パース結果を親ツリーの絶対パスへ書き換える。\n * `uuid` を持つエントリ(構造フラグメントの参照)には掛けない — フラグメント側の\n * パース結果は登録時(collectStructuralFragments)に変換済みで、二重に掛けると\n * 接頭辞が二重になる。\n */\nexport type ParseResultTransform = (parsed: ParseBindTextResult, forPath?: string) => ParseBindTextResult;\n\nfunction applyTransform(\n parseResults: ParseBindTextResult[],\n transform: ParseResultTransform | undefined,\n): ParseBindTextResult[] {\n if (typeof transform === \"undefined\") {\n return parseResults;\n }\n return parseResults.map((parsed) => (parsed.uuid != null ? parsed : transform(parsed)));\n}\n\nexport interface IDeferredSpreadEntry {\n readonly node: Node;\n readonly tagName: string;\n readonly parseResults: ParseBindTextResult[];\n readonly transform?: ParseResultTransform;\n /** 予約中の定義待ちの取り消し(`scheduleDeferredSpreads` が持つ。行の活性化し直しで待ちを重ねない) */\n cancel?: () => void;\n}\n\nfunction processParseResultsForNode(\n node: Node,\n parseResults: ParseBindTextResult[],\n options: { allowDeferred: boolean },\n transform?: ParseResultTransform,\n): { bindings: IBindingInfo[], deferred: IDeferredSpreadEntry | null } {\n const expanded = expandSpread(node, parseResults, { allowDeferred: options.allowDeferred });\n if (hasUnresolvedSpread(expanded)) {\n const tagName = node.nodeType === Node.ELEMENT_NODE\n ? getCustomElement(node as Element)\n : null;\n if (tagName === null) {\n raiseError(`Spread binding deferred but element is not a custom element.`);\n }\n return { bindings: [], deferred: { node, tagName, parseResults, transform } };\n }\n registeredNodeSet.add(node);\n // 変換は spread 展開の**後**(展開されたプロパティごとのパスに掛かる)\n const bindings = getBindingInfos(node, applyTransform(expanded, transform));\n setBindingsByNode(node, bindings);\n resolveInitializedBinding(node);\n return { bindings, deferred: null };\n}\n\nexport function collectNodesAndBindingInfos(\n root: Document | Element | DocumentFragment,\n transform?: ParseResultTransform,\n): [ Node[], IBindingInfo[], IDeferredSpreadEntry[] ] {\n return collectNodesAndBindingInfosOf(getSubscriberNodes(root), transform);\n}\n\n/**\n * 購読ノードの列を受け取る版。SSR のハイドレーション(ssr/hydrateBindings.ts)が、生きている\n * ブロックのノード列を**動かさずに**集めるのに使う(根を要求する上の版に掛けるには一時的な\n * 要素へ移すしかなく、移すとブロックの中のカスタム要素が切断・再接続される — #258)。\n */\nexport function collectNodesAndBindingInfosOf(\n subscriberNodes: Node[],\n transform?: ParseResultTransform,\n): [ Node[], IBindingInfo[], IDeferredSpreadEntry[] ] {\n const allBindings: IBindingInfo[] = [];\n const deferredSpreads: IDeferredSpreadEntry[] = [];\n for(const node of subscriberNodes) {\n if (registeredNodeSet.has(node)) continue;\n const parseResults = getParseBindTextResults(node);\n const result = processParseResultsForNode(node, parseResults, { allowDeferred: true }, transform);\n if (result.deferred !== null) {\n deferredSpreads.push(result.deferred);\n continue;\n }\n allBindings.push(...result.bindings);\n }\n return [subscriberNodes, allBindings, deferredSpreads];\n}\n\nexport function collectNodesAndBindingInfosByFragment(\n root: DocumentFragment,\n nodeInfos: IFragmentNodeInfo[],\n): [ Node[], IBindingInfo[], IDeferredSpreadEntry[] ] {\n const nodes: Node[] = [];\n const allBindings: IBindingInfo[] = [];\n const deferredSpreads: IDeferredSpreadEntry[] = [];\n for(const nodeInfo of nodeInfos) {\n const node = resolveNodePath(root, nodeInfo.nodePath);\n if (node === null) {\n raiseError(`Node not found by path [${nodeInfo.nodePath.join(', ')}] in fragment.`);\n }\n if (registeredNodeSet.has(node)) continue;\n const result = processParseResultsForNode(node, nodeInfo.parseBindTextResults, { allowDeferred: true });\n // 未定義カスタム要素への spread は行の活性化が定義待ちへ予約する(#330。ルートと同じ約束)。\n // ノードは行のノードの列に入れる — 行のループ文脈はこの列に張られ、展開した束縛がそれを読む。\n // 行のノードとして台帳にも載せる — 祖先の走査し直し(binder)がルートの待ちとして二重に予約しない\n if (result.deferred !== null) {\n deferredSpreads.push(result.deferred);\n registeredNodeSet.add(node);\n }\n allBindings.push(...result.bindings);\n nodes.push(node);\n }\n return [nodes, allBindings, deferredSpreads];\n}\n\n/**\n * The nodes of the list not collected yet (`initializeBindings`, #414). A collected node is bound already\n * — by an earlier walk, or as a row's node — and its loop context is not to be touched again.\n */\nexport function uncollectedNodes(nodes: Node[]): Node[] {\n return nodes.filter((node) => !registeredNodeSet.has(node));\n}\n\nexport function unregisterNode(node: Node): void {\n registeredNodeSet.delete(node);\n}\n\n/**\n * RowPlan 経路(createContent のプラン実体化)用。パース・spread 展開を経ずに\n * binding を組み立てた subscriber ノードを二重処理防止台帳へ載せる\n * (後続の collectNodesAndBindingInfos による再スキャンから保護)。\n */\nexport function markNodeRegistered(node: Node): void {\n registeredNodeSet.add(node);\n}\n\n/**\n * Re-process a deferred spread entry once the custom element class is\n * registered. Expands the captured parseResults, installs bindings, and\n * returns them so the caller can attach handlers and apply state values.\n */\nexport function processDeferredNode(entry: IDeferredSpreadEntry): IBindingInfo[] {\n const { node, parseResults, transform } = entry;\n unregisterNode(node);\n const result = processParseResultsForNode(node, parseResults, { allowDeferred: false }, transform);\n return result.bindings;\n}\n","import { IBindingInfo } from \"../types\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\n// 束縛計画の段でフィルタの実関数を引く(要件 D16)。実装は `planFilters.ts` の 1 本だけ —\n// かつてこのファイルが逐語のコピーを持っていて、両方がバンドルに載っていた\nimport { planFilters } from \"./planFilters\";\n\nexport function getBindingInfos(node: Node, parseBindingTextResults: ParseBindTextResult[]): IBindingInfo[] {\n const bindingInfos: IBindingInfo[] = [];\n for (const parseBindingTextResult of parseBindingTextResults) {\n const inFilters = planFilters(parseBindingTextResult.inFilters, \"input\");\n const outFilters = planFilters(parseBindingTextResult.outFilters, \"output\");\n if (parseBindingTextResult.bindingType !== 'text') {\n bindingInfos.push({\n ...parseBindingTextResult,\n inFilters,\n outFilters,\n node: node,\n replaceNode: node,\n });\n } else {\n // フラグメント登録時に事前正規化済みの Text ノードはそのまま replaceNode に\n // 使う(node === replaceNode なら replaceToReplaceNode は no-op)。\n // 実 DOM 上の wcs-text コメント(非フラグメント経路)は従来どおり\n // 空 Text を生成して実行時に差し替える。\n const replaceNode = node.nodeType === Node.TEXT_NODE\n ? node\n : document.createTextNode('');\n bindingInfos.push({\n ...parseBindingTextResult,\n inFilters,\n outFilters,\n node: node,\n replaceNode: replaceNode,\n });\n }\n }\n return bindingInfos;\n}\n","import { ILoopContext } from \"./types\";\n\nconst loopContextByNode = new WeakMap<Node, ILoopContext>();\n\n// 親を持たない ShadowRoot で探索を続けるか。マウントされたスコープ根はホストへ抜ける\n// (webComponent/mount.ts が記録の登録時に注入する)。未注入なら従来どおり境界で止まる —\n// 走るのは探索が ShadowRoot に達した 1 回だけなので、大域の受け口でも hot path には載らない\nlet mountedScopeHost: ((root: ShadowRoot) => Node | null) | null = null;\n\nexport function setMountedScopeHost(resolver: (root: ShadowRoot) => Node | null): void {\n mountedScopeHost = resolver;\n}\n\nexport function getLoopContextByNode(node: Node): ILoopContext | null {\n let paramNode: Node | null = node;\n while (paramNode) {\n const loopContext = loopContextByNode.get(paramNode);\n if (loopContext) {\n return loopContext;\n }\n let next: Node | null = paramNode.parentNode;\n if (next === null && mountedScopeHost !== null && paramNode instanceof ShadowRoot) {\n // マウントされた ShadowRoot はホストのループ文脈を継承する(impl-plan §3-0 の 3)。\n // ホスト行の listIndex [i] が子スコープの `for` の親になり、内側の行は [i, j] を\n // 作る — 絶対パスのワイルドカード数 = listIndex 段数(設計書 §4-4)がこれで成立し、\n // v1 の crossBoundaryAddress / baseListIndex(Δ の帳簿)は要らなくなる。\n // マウントされていない ShadowRoot(plain コンポーネント・通常の Shadow ツリー)は\n // 従来どおり境界で止まる(resolver が null を返す)。\n next = mountedScopeHost(paramNode);\n }\n paramNode = next;\n }\n return null;\n}\n\nexport function setLoopContextByNode(node: Node, loopContext: ILoopContext | null): void {\n if (loopContext === null) {\n loopContextByNode.delete(node);\n return;\n }\n loopContextByNode.set(node, loopContext);\n}\n","\nlet count = 0;\nexport function getUUID(): string {\n return `u${(count++).toString(36)}`;\n}\n","import { getUUID } from \"../getUUID\";\nimport { IListIndex } from \"./types\";\n\nlet version = 0;\n/**\n * 親の付け替え(#256 の修理)の世代。`listIndexes` の WeakRef 連鎖は一度組んだら\n * 作り直されないので、祖先が付け替わったら子孫のキャッシュも無効にする必要がある。\n * `dirty`(version 比較)は `indexes` の再構築が消費してしまうため、連鎖専用の世代を持つ。\n */\nlet chainGeneration = 0;\n\n/** 値が一度も記録されていない行の印(`undefined` を持つ行と区別するため)。 */\nconst NO_VALUE = Symbol(\"wcs.listIndex.noValue\");\n\nclass ListIndex implements IListIndex {\n readonly uuid = getUUID();\n parentListIndex: IListIndex | null;\n readonly position: number;\n readonly length: number;\n\n private _index: number;\n private _version: number;\n private _indexes: number[] | undefined;\n private _listIndexes: WeakRef<IListIndex>[] | undefined;\n private _chainGeneration: number;\n /**\n * この行集合を最初に展開した親(`home`・#256)。付け替えても変わらない。退役した親から\n * 付け替えたあと、その親が戻ってきたら戻す先になる。1 組の行集合に home は 1 つ — 別の配列(写し)へ\n * 引き継いだ行集合は、引き継いだ親を home にする(`createListDiff` の rehomeListIndex・#394。前の home は\n * 新しい配列を持ったことが無い)。\n */\n private _homeParentListIndex: IListIndex | null;\n\n /**\n * この行が表しているリスト要素(#256)。差分が返すたびに付け直す。\n * 「同じ行が戻ってきた」を配列インスタンスをまたいで言えるのはこの値だけ ──\n * 行を戻す普通のやり方(新しい配列に同じ要素を並べ直す)は ListIndex を作り直すので、\n * 行オブジェクトの identity では判定できない。\n */\n private _value: unknown;\n\n /**\n * 行の下のキャッシュの印(#389)。行の下の値(`items.*.name`)のキャッシュは載せたときの印を持ち、\n * 印が進んだ行の項目は読みで外れる。行の要素・途中の値が変わったら、子のパスを 1 つずつ無効にする\n * 代わりに印を 1 つ進める(cache/cacheEntryByAbsoluteStateAddress.ts)。\n */\n cacheStamp = 0;\n\n /** 要素オブジェクトの索引が持つ、この行への弱い参照(rowsByElement・#393。載せたときに作る) */\n ref: WeakRef<ListIndex> | undefined;\n\n /**\n * Creates a new ListIndex instance.\n *\n * @param parentListIndex - Parent list index for nested loops, or null for top-level\n * @param index - Current index value in the loop\n * @param homeParentListIndex - Parent this row's set belongs to (#256)\n */\n constructor(parentListIndex: IListIndex | null, index: number, homeParentListIndex: IListIndex | null) {\n this.parentListIndex = parentListIndex;\n this.position = parentListIndex ? parentListIndex.position + 1 : 0;\n this.length = this.position + 1;\n this._homeParentListIndex = homeParentListIndex;\n this._value = NO_VALUE;\n this._index = index;\n this._version = version;\n this._chainGeneration = chainGeneration;\n }\n\n /**\n * Gets current index value.\n *\n * @returns Current index number\n */\n get index() {\n return this._index;\n }\n\n /**\n * Sets index value and updates version.\n *\n * @param value - New index value\n */\n set index(value: number) {\n this._index = value;\n this._version = ++version;\n this.indexes[this.position] = value;\n }\n\n /**\n * Gets current version number for change detection.\n *\n * @returns Version number\n */\n get version(): number {\n return this._version;\n }\n\n /** 行集合を最初に展開した親(付け替えても変わらない)。 */\n get homeParentListIndex(): IListIndex | null {\n return this._homeParentListIndex;\n }\n\n set homeParentListIndex(home: IListIndex | null) {\n this._homeParentListIndex = home;\n }\n\n /** この行が表しているリスト要素(未記録なら `NO_VALUE`)。 */\n get value(): unknown {\n return this._value;\n }\n\n set value(value: unknown) {\n this._value = value;\n }\n\n /**\n * Checks if parent indexes have changed since last access.\n *\n * @returns true if parent has newer version, false otherwise\n */\n get dirty(): boolean {\n if (this.parentListIndex === null) {\n return false;\n } else {\n return this.parentListIndex.dirty || this.parentListIndex.version > this._version;\n }\n }\n\n /**\n * Gets array of all index values from root to current level.\n * Rebuilds array if parent indexes have changed (dirty).\n *\n * @returns Array of index values\n */\n get indexes(): number[] {\n if (this.parentListIndex === null) {\n if (typeof this._indexes === \"undefined\") {\n this._indexes = [this._index];\n }\n } else {\n if (typeof this._indexes === \"undefined\" || this.dirty) {\n this._indexes = [...this.parentListIndex.indexes, this._index];\n this._version = version;\n }\n }\n return this._indexes;\n }\n\n /**\n * Gets array of WeakRef to all ListIndex instances from root to current level.\n *\n * @returns Array of WeakRef<IListIndex>\n */\n get listIndexes(): WeakRef<IListIndex>[] {\n if (this.parentListIndex === null) {\n if (typeof this._listIndexes === \"undefined\") {\n this._listIndexes = [new WeakRef(this)];\n }\n } else {\n if (typeof this._listIndexes === \"undefined\" || this._chainGeneration !== chainGeneration) {\n this._listIndexes = [...this.parentListIndex.listIndexes, new WeakRef(this)];\n this._chainGeneration = chainGeneration;\n }\n }\n return this._listIndexes;\n }\n\n /**\n * Gets variable name for this loop index ($1, $2, etc.).\n *\n * @returns Variable name string\n */\n get varName(): string {\n return `$${this.position + 1}`;\n }\n\n /**\n * Gets ListIndex at specified position in hierarchy.\n * Supports negative indexing from end.\n *\n * @param pos - Position index (0-based, negative for from end)\n * @returns ListIndex at position or null if not found/garbage collected\n */\n /**\n * 退役した親を、同じ深さの生きた親へ差し替える(#256)。**行の identity は保つ**ので、\n * 描画済み content も、その行に紐づくバインドしていない DOM の状態も残る。\n * 添字の値は親が変われば変わりうる(並べ替えを伴う置換)ため、`indexes` と WeakRef 連鎖を\n * 捨て、version を進めて子孫の `dirty` を立てる。`_homeParentListIndex` は動かさない\n * ── 外した行が戻ってきたときに持ち主を返す先だから。\n */\n reparent(parentListIndex: IListIndex | null): void {\n this.parentListIndex = parentListIndex;\n this._indexes = undefined;\n this._listIndexes = undefined;\n this._version = ++version;\n chainGeneration++;\n }\n\n at(pos: number): IListIndex | null {\n if (pos >= 0) {\n return this.listIndexes[pos]?.deref() || null;\n } else {\n return this.listIndexes[this.listIndexes.length + pos]?.deref() || null;\n }\n }\n}\n\n/**\n * Factory function to create ListIndex instance.\n *\n * @param parentListIndex - Parent list index for nested loops, or null for top-level\n * @param index - Current index value in the loop\n * @param homeParentListIndex - Row set this row joins (#256); defaults to the minting parent\n * @returns New IListIndex instance\n */\nexport function createListIndex(\n parentListIndex: IListIndex | null,\n index: number,\n homeParentListIndex: IListIndex | null = parentListIndex,\n): IListIndex {\n return new ListIndex(parentListIndex, index, homeParentListIndex);\n}\n\n/**\n * 台帳(`listIndexesByList`)専用の入口。行は必ずこのモジュールが鋳造した実体なので、\n * 到達不能な防御分岐を置かずに直接呼ぶ。\n */\nexport function reparentListIndex(listIndex: IListIndex, parentListIndex: IListIndex | null): void {\n (listIndex as ListIndex).reparent(parentListIndex);\n}\n\n/**\n * 台帳専用の入口その 2。行集合の home を読む(`IListIndex` を広げないための cast ──\n * この型は dist/index.d.ts に出るので、内部だけの都合で公開面を増やさない)。\n */\nexport function getHomeParentListIndex(listIndex: IListIndex): IListIndex | null {\n return (listIndex as ListIndex).homeParentListIndex;\n}\n\n/** 台帳専用の入口その 2'。行集合を別の配列へ引き継いだ親を home にする(createListDiff・#394) */\nexport function rehomeListIndex(listIndex: IListIndex, home: IListIndex | null): void {\n (listIndex as ListIndex).homeParentListIndex = home;\n}\n\n/**\n * キャッシュ専用の入口。行の下のキャッシュの印を読む(行の無いアドレスは undefined — #389)。\n * 載せるときと読むときの両方がこれで引くので、行の無いアドレスの項目は印の比較で外れない。\n */\nexport function getRowCacheStamp(listIndex: IListIndex | null): number | undefined {\n return (listIndex as ListIndex | null)?.cacheStamp;\n}\n\n/** キャッシュ専用の入口その 2。行の下のキャッシュをまとめて無効にする(#389) */\nexport function advanceRowCacheStamp(listIndex: IListIndex): void {\n (listIndex as ListIndex).cacheStamp++;\n}\n\n/**\n * 台帳専用の入口その 3。差分が返した行に、その行が表している要素を憶えさせる(#256)。\n * 要素の書き込みがその場で行の要素を替えたときも呼ぶ(setByAddress の _setByAddressWithSwap・#359)。\n * 前に憶えていた要素と違えば真を返す — 差分がこれを見て、行はそのままで要素だけが替わった行を\n * 描き直させる(createListDiff の syncListIndexes)。\n */\nexport function setListIndexValue(listIndex: IListIndex, value: unknown): boolean {\n const row = listIndex as ListIndex;\n const previous = row.value;\n const changed = previous !== NO_VALUE && !Object.is(previous, value);\n if (previous !== value) {\n rowsByElement.get(previous as object)?.delete(row.ref!);\n rememberRowOfElement(value, row);\n }\n row.value = value;\n return changed;\n}\n\n/**\n * 要素オブジェクト → それを表している入れ子のリストの行(#393)。同じ要素オブジェクトは別の行にも居る — 同じ配列の\n * 2 つの位置、共有された配列の写し(ほかの外側の行がまだ持つ配列の写しは、行を借りずに新しい行を作る — createListDiff)。\n * 行の下への書き込み(`groups.1.items.0.v`)は、同じ要素を表す別の行のアドレスにも知らせる(setByAddress の notifyWrite)。\n * 行は弱く持つ — 外側の行ごと外した行・捨てた state の行は差分を通らず退役の印も付かないので、強く持つと要素が生きている\n * 間ずっと残った(外側の行を不変更新するたびに内側の行の数だけ増えた)。集合は前に見直した大きさの倍に育ったときに、消えた\n * 行と、退役した行・退役した外側の行の下の行を外す — 消えた行だけを外すと、GC までの間、外側の行を消して戻すたびに集合が\n * 育った(500 回で 501)。ルート直下の行は載せない(別の行を引くのは入れ子の行の下への書き込みだけ)\n */\nconst rowsByElement = new WeakMap<object, Set<WeakRef<ListIndex>>>();\nconst pruneSizeByRows = new WeakMap<Set<WeakRef<ListIndex>>, number>();\n\nfunction rememberRowOfElement(element: unknown, row: ListIndex): void {\n if (typeof element !== \"object\" || element === null || row.parentListIndex === null) {\n return;\n }\n let held = rowsByElement.get(element);\n if (typeof held === \"undefined\") {\n held = new Set();\n rowsByElement.set(element, held);\n } else if (held.size >= (pruneSizeByRows.get(held) ?? 8)) {\n liveRowsOf(held, row, true);\n pruneSizeByRows.set(held, held.size * 2 + 8);\n }\n held.add(row.ref ??= new WeakRef(row));\n}\n\n/** 集合の生きている行のうち `row` でないもの(消えた行は外す。`stale` なら退役した行・その下の行も外す) */\nfunction liveRowsOf(held: Set<WeakRef<ListIndex>> | undefined, row: ListIndex, stale = false): ListIndex[] {\n const rows: ListIndex[] = [];\n held?.forEach((ref) => {\n const other = ref.deref();\n if (typeof other === \"undefined\" || (stale && isUnderRetiredRow(other))) {\n held.delete(ref);\n } else if (other !== row) {\n rows.push(other);\n }\n });\n return rows;\n}\n\n/** 同じ要素オブジェクトを表している別の行(台帳専用の入口その 4 — list/listIndexesByList.ts の getElementAliases) */\nexport function getRowsOfSameElement(listIndex: IListIndex): ListIndex[] {\n return liveRowsOf(rowsByElement.get((listIndex as ListIndex).value as object), listIndex as ListIndex);\n}\n\n/**\n * 差分で `newIndexes` から外れた行 = 消費者が画面から外した行(list/listIndexesByList.ts の retireListIndexes /\n * reviveListIndexes が付け外しする)。「生きた親集合に属さない」の判定材料。要素の索引の見直しも引くのでここに置く\n */\nexport const retiredListIndexes = new WeakSet<IListIndex>();\n\n/** 行か、その祖先の行が退役しているか */\nexport function isUnderRetiredRow(listIndex: IListIndex | null): boolean {\n for (let row = listIndex; row !== null; row = row.parentListIndex) {\n if (retiredListIndexes.has(row)) {\n return true;\n }\n }\n return false;\n}\n\n/** 行が表しているリスト要素(未記録なら undefined ではなく内部の印 — 台帳専用の入口その 5・list/listIndexesByList.ts の covers) */\nexport function getListIndexValue(listIndex: IListIndex): unknown {\n return (listIndex as ListIndex).value;\n}\n\n/**\n * 2 つの行が**同じリスト要素**を表しているか(#256)。\n * 差分を通っていない行(`hydrateBindings` / `setByAddress` が鋳造する行)は値を持たないので、\n * 未記録どうしは「同じ」と見なさない ── 値の無い行を取り違えて付け替えないため。\n * 行を書き換えない読むだけの判定なので、台帳の外からも使う: `$scan` の drain が、行のアドレスが\n * いまその位置の要素を表しているかを見る(scan/scanRuntime.ts の placementOf)。\n */\nexport function isSameListIndexValue(listIndex: IListIndex, other: IListIndex): boolean {\n const value = (listIndex as ListIndex).value;\n return value !== NO_VALUE && value === (other as ListIndex).value;\n}\n","/**\n * updater/updateBatch.ts\n *\n * 次に drain されるバッチの番号(updater が drain を始めるたびに進める)。書き込みが同じバッチのものかを\n * 見る側が読む — 要素書き込みの入れ替えの、揃う前の書き込み(proxy/methods/setByAddress.ts・#361)と、\n * 行はそのままで要素が替わった行の差分(list/createListDiff.ts・#359)。\n * updater は描画の適用を読み込むので、list/ から updater.ts を読むと循環する。番号だけを葉のモジュールに置く。\n */\nexport let updateBatch = 0;\n\n/** drain を始めた(updater 専用) */\nexport function advanceUpdateBatch(): void {\n updateBatch++;\n}\n","/**\n * 要素書き込みの入れ替えが揃ったとき、`for` の描画基準に据える「書き込む前の並びの写し」の印(#4)。\n *\n * `for` はこの写しとの差分でだけ、同じ位置で外す行と入る行の Content をその場で使い回す\n * (applyChangeToFor の collectInPlaceContents)。配列の置換の差分は、これまでどおり外した行の\n * Content をプールに通す。\n */\nconst swapBaselineLists = new WeakSet<object>();\n\nexport function markSwapBaselineList(list: readonly unknown[]): void {\n swapBaselineLists.add(list);\n}\n\nexport function isSwapBaselineList(list: unknown): boolean {\n return swapBaselineLists.has(list as object);\n}\n","/**\n * list/listIndexesByList.ts\n *\n * 行(`IListIndex`)の正本台帳。1 本の配列につき行集合は **1 組**。\n *\n * #256 が扱うのは「共有」ではなく「陳腐化」である。台帳はこの 2 つを分ける:\n *\n * - **生きた共有** ── 1 本の配列が 2 つの生きた親から到達できる形。行集合は 1 組のまま\n * 全員で共有する(どの親から読んでも同じ値が見える)。親ごとに私有の行集合を持たせると\n * 同じスロットに 2 本の絶対アドレスができ、片方へ書いた値がもう片方から**永久に**\n * 見えなくなる。共有そのものの帰結(親を読む getter が持ち主の行の文脈で評価される・\n * 1 スロットへ到達経路の数だけ書かれる)は残るが、それはデータが実際に共有されている\n * ことの帰結であって、**もう存在しない古い値**ではない。\n * - **陳腐化** ── 行オブジェクトだけを作り直す置換(`nodes.map(n => ({...n}))` は\n * `children` を参照ごと引き継ぐ)で、台帳の行がぶら下がる親が**退役した**形。読み手は\n * 新しい行の絶対アドレスを見るのに、書き手は行の親ポインタを遡って旧行の絶対アドレスを\n * dirty にするので、葉への書き込みが集計へ届かない(#256)。外側の行が内側のパスに別の値を書いて、前の配列を\n * **手放した**形も同じ(#394 — releaseListAtParent)。\n *\n * 判別は「台帳の行が持つ親が、生きた親集合に属するか」。属さないときだけ、**行の identity を\n * 保ったまま**新しい親へ付け替える(`reparentListIndex`)。作り直さないのは、消費者が\n * 描画済み content を行 ListIndex の identity で持っているため ── 作り直すと、著者が何も\n * 間違えていないページで行の DOM が丸ごと失われる(`<details>` の開閉のような、バインド\n * していない状態ごと)。\n *\n * 退役の signal は差分の `deleteIndexSet`(=エンジン自身が「この行はもう無い」と決めた\n * 集合)で、**復活の signal は同じ差分の `newIndexes`**。印は差分ごとに付け直され、\n * 消えない印は残らない(`retireListIndexes` / `reviveListIndexes` を `createListDiff` が\n * 対で呼ぶ)。\n *\n * 付け替えは**一方通行ではない**。行は自分の行集合を最初に展開した親(`home`)を憶えていて、\n * その home が**リストに戻ってきたら**持ち主を返す。これが無いと「行を削除して戻す」ページで\n * 持ち主が隣の行に移ったまま固定され、削除の履歴によって集計が凍る行が変わってしまう。\n *\n * 戻ってきたかどうかは **行オブジェクト(ListIndex)の identity ではなく、行が表している\n * リスト要素の identity** で判定する。同じ配列インスタンスを戻す綴りなら home そのものが\n * 生き返るが、行を戻す普通のやり方(新しい配列に同じ要素を並べ直す)では差分が ListIndex を\n * 作り直すので、ListIndex の identity で見ると home は永久に退役したままになる。\n * 要素そのものを作り直した行は**別の行**なので home には一致しない。生き残った行が\n * 1 つでもあればそちらへ戻るが、**全ての行を作り直す**綴り(`map(n => ({...n}))`)では\n * どの要素も一致せず、退役した親からの付け替えが位置に対して働く。\n */\nimport { createListIndex, getHomeParentListIndex, getListIndexValue, getRowsOfSameElement, isSameListIndexValue, isUnderRetiredRow, reparentListIndex, retiredListIndexes, setListIndexValue } from \"./createListIndex\";\nimport { IListIndex } from \"./types\";\nimport { updateBatch } from \"../updater/updateBatch\";\nimport { isSwapBaselineList, markSwapBaselineList } from \"./swapBaselineList\";\n\nconst listIndexesByList = new WeakMap<readonly unknown[], IListIndex[]>();\n\n/** 差分が捨てた行を退役として記録する(`createListDiff` が呼ぶ)。 */\nexport function retireListIndexes(listIndexes: Iterable<IListIndex>): void {\n for (const listIndex of listIndexes) {\n retiredListIndexes.add(listIndex);\n }\n}\n\n/**\n * 差分が「いま生きている」と返した行の退役印を落とす(`createListDiff` が呼ぶ)。\n * 同じ配列インスタンスを戻す・タブを切り替えて戻る等で、退役した行は実際に生き返る。\n */\nexport function reviveListIndexes(listIndexes: Iterable<IListIndex>): void {\n for (const listIndex of listIndexes) {\n retiredListIndexes.delete(listIndex);\n }\n}\n\n/**\n * 差分がリストから外し、まだ戻っていない行か。読むだけの判定で、`$scan` の drain が\n * 行のアドレスの指す行がもうリストに居ないかを見る(scan/scanRuntime.ts の placementOf)。\n */\nexport function isRetiredListIndex(listIndex: IListIndex): boolean {\n return retiredListIndexes.has(listIndex);\n}\n\n/**\n * 外側の行 → その行が内側のパスから手放した配列(#394)。外側の行の内側のパスへ別の配列を書くと(setByAddress)、\n * 前の配列の行がその外側の行を親に持っていても、その行はもうその配列を持たない。退役した親と同じく付け替えの元に\n * なり、戻り先(home)にもならない。同じ配列を書き戻したら外す(holdListAtParent)。\n */\nconst releasedListsByParent = new WeakMap<IListIndex, WeakSet<readonly unknown[]>>();\n\n/**\n * 外側の行 `parentListIndex` の内側のパス(`holder` の `key`)が、配列 `list` から別の値に替わった(setByAddress)。\n * 同じ要素の別のパスがまだその配列を持つ(`{ items: A, alt: A }` の `alt` だけを替えた)なら手放さず、真を返す —\n * 呼び手は、新しい配列に前の配列の行を貸させない(前の配列はまだ描かれている — createListDiff の keepPreviousList)\n */\nexport function releaseListAtParent(list: unknown, parentListIndex: IListIndex, holder: Record<string, unknown>, key: string): boolean {\n if (!listIndexesByList.has(list as readonly unknown[])) {\n return false;\n }\n let kept = false;\n for (const other in holder) {\n kept ||= other !== key && holder[other] === list;\n }\n if (!kept) {\n let released = releasedListsByParent.get(parentListIndex);\n if (typeof released === \"undefined\") {\n released = new WeakSet();\n releasedListsByParent.set(parentListIndex, released);\n }\n released.add(list as readonly unknown[]);\n }\n // 行集合の親がこの外側の行なら、配列をまだ持つ別の外側の行へいま付け替える。その外側の行が引くまで待つと、間に描き直した\n // 行の下のアドレスが手放した外側の行を経由し、その外側の行の新しい値(写し)を読み書きした(隠れた外側の行に知らせた\n // 更新で、別の外側の行が写しに替えた — f5/if/1242)。付け替え先は、手放したキーで配列を持つ外側の行。別のキーがまだ\n // 持つときも、このキーの分は手放すので付け替える — 残ったキーのアドレスは、憶えた親(この外側の行)を使い続ける\n // (address/StateAddress.ts・f6/dual/43)\n const rows = listIndexesByList.get(list as readonly unknown[])!;\n const moved = movedByList.get(list as readonly unknown[]);\n if (rows[0]?.parentListIndex === parentListIndex && !(kept && moved?.[0] === parentListIndex && moved[1] === updateBatch)) {\n for (const other of holdersByList.get(list as readonly unknown[]) ?? []) {\n if (other !== parentListIndex && other.position === parentListIndex.position && isHoldingParent(list as readonly unknown[], other) &&\n Object(getListIndexValue(other))[key] === list) {\n rows.forEach((row) => reparentListIndex(row, other));\n handedOverByList.set(list as readonly unknown[], [parentListIndex, updateBatch]);\n break;\n }\n }\n }\n return kept;\n}\n\n/**\n * 配列 → 手放したときに行集合を付け替えた元の外側の行と、そのバッチ。同じバッチでその外側の行が別のキーに同じ配列を書いたら\n * (`items` から `alt` へ移した)、行集合を戻す — 付け替えた先の外側の行は書いたキーで配列を持たないので、移した先のキーの\n * アドレスが付け替えた先の外側の行の別の配列を読んだ(6 つ目の修理の検証の y7)\n */\nconst handedOverByList = new WeakMap<readonly unknown[], [IListIndex, number]>();\n\n/**\n * 配列 → その配列を内側のパスに書いた外側の行と、そのバッチ。同じバッチで先に別のキーへ書いてから元のキーを替えた(`alt` へ\n * 移してから `items` を替えた)外側の行は、まだその配列を持つので付け替えない — 移した先のキーのアドレスはこれから作られ、\n * 付け替えた先の外側の行の別の配列を読んだ(6 つ目の修理の検証の y7)\n */\nconst movedByList = new WeakMap<readonly unknown[], [IListIndex, number]>();\n\n/** 外側の行 `parentListIndex` の内側のパスに、配列 `list` を書いた(手放した印を外す) */\nexport function holdListAtParent(list: unknown, parentListIndex: IListIndex): void {\n releasedListsByParent.get(parentListIndex)?.delete(list as readonly unknown[]);\n const rows = listIndexesByList.get(list as readonly unknown[]);\n if (typeof rows !== \"undefined\") {\n movedByList.set(list as readonly unknown[], [parentListIndex, updateBatch]);\n const handedOver = handedOverByList.get(list as readonly unknown[]);\n if (handedOver?.[0] === parentListIndex && handedOver[1] === updateBatch) {\n rows.forEach((row) => reparentListIndex(row, parentListIndex));\n }\n }\n}\n\n/** 外側の行 `parentListIndex` が配列 `list` を手放したか(applyChangeToFor・#393) */\nexport function hasReleasedList(list: readonly unknown[], parentListIndex: IListIndex): boolean {\n return releasedListsByParent.get(parentListIndex)?.has(list) === true;\n}\n\n/**\n * 外側の行が、もうその配列を持たないか(退役した・内側のパスから手放した)。祖先の行が退役した行も同じ — 3 段のリストの\n * 外側の行を作り直すと、真ん中の行は差分を通らないので退役の印が付かない(見なければ、真ん中の行を作り直した後の\n * 内側の配列の行が、退役した外側の行の下の真ん中の行に残り、2 つの行から引かれた配列と取り違える)\n */\nfunction isGoneParent(list: readonly unknown[], parentListIndex: IListIndex): boolean {\n return hasReleasedList(list, parentListIndex) || isUnderRetiredRow(parentListIndex);\n}\n\n/**\n * 要素書き込みの入れ替えの途中で、書いた要素を映している行 → 書いたバッチ(setByAddress の _setByAddressWithSwap)。\n * 揃うと行は値に付いて元の要素へ戻るので、その間にこの行の下で引いた配列の行を、この行へ付け替えない — 付け替えると、\n * 揃った後にその配列を持たない行が親として残り、書き込みが別の配列に着地した(#394 と同じ系統)\n */\nconst swapPendingBatchByRow = new WeakMap<IListIndex, number>();\n\nexport function markRowSwapPending(row: IListIndex): void {\n swapPendingBatchByRow.set(row, updateBatch);\n}\n\nexport function clearRowSwapPending(row: IListIndex): void {\n swapPendingBatchByRow.delete(row);\n}\n\n/**\n * 外側の行 `row` の要素が、`other` の要素が配列を持つどのキーでも同じ配列を持つか(直下のキーだけ)。行のアドレスは\n * 行の親から引き直すので、同じ配列を `items` と `alt` の 2 つのキーに持つ外側の行がいると、片方のキーにしか持たない外側の行を\n * 親にした行の、もう片方のキーのアドレスが別の配列に着地した(R1 — 例: `{ items: 写し, alt: A }` を親にした `groups.0.items.0`)\n */\nfunction covers(list: readonly unknown[], row: IListIndex, other: IListIndex): boolean {\n const element = Object(getListIndexValue(row)) as Record<string, unknown>;\n const held = getListIndexValue(other) as Record<string, unknown>;\n for (const key in held) {\n if (held[key] === list && element[key] !== list) {\n return false;\n }\n }\n return true;\n}\n\n/** 付け替え先にしてよい親か(配列を持っていて、入れ替えの途中で別の要素を映していない) */\nfunction isHoldingParent(list: readonly unknown[], parentListIndex: IListIndex): boolean {\n return !isGoneParent(list, parentListIndex) && swapPendingBatchByRow.get(parentListIndex) !== updateBatch;\n}\n\n/**\n * 2 つ以上の外側の行から引かれた配列 → 引いた外側の行(#393)。行の親は 1 つなので、もう片方の外側の行から引いた行も同じ\n * 親を持つ。その行を別の配列(写し)に貸すと、写しの要素の書き込みが行の親を経由して元の配列に着地し、元の配列を描く\n * 外側の行の添字も写しの位置へ振り直される。差分は、ほかにまだ持っている外側の行がある配列の行を貸さない(createListDiff)。\n * 持っているかはその都度見る(手放した・退役した外側の行は数えない)ので、共有をやめた配列の写しは行を借りて DOM を保つ。\n * もう持っていない外側の行は、見たときと、集合が前に見直した大きさの倍に育ったときに外す — 外した外側の行を持ち続けず、\n * 見直しの手間は足した数に比例する(9,000 行が同じ配列を持つページで、足すたびに全部を見直すと作り直しが 4 倍遅れた)\n */\nconst holdersByList = new WeakMap<readonly unknown[], Set<IListIndex>>();\nconst pruneSizeByList = new WeakMap<readonly unknown[], number>();\n\nfunction addHolders(list: readonly unknown[], holders: (IListIndex | null)[]): void {\n let held = holdersByList.get(list);\n if (typeof held === \"undefined\") {\n held = new Set();\n holdersByList.set(list, held);\n } else if (held.size >= (pruneSizeByList.get(list) ?? 8)) {\n held.forEach((holder) => {\n if (isGoneParent(list, holder)) {\n held!.delete(holder);\n }\n });\n pruneSizeByList.set(list, held.size * 2 + 8);\n }\n for (const holder of holders) {\n held.add(holder!);\n }\n}\n\n/** `requester` のほかに、配列をまだ持っている外側の行があるか(見た、もう持っていない外側の行は外す) */\nexport function isHeldElsewhere(list: readonly unknown[], requester: IListIndex): boolean {\n const held = holdersByList.get(list);\n for (const holder of held ?? []) {\n if (isGoneParent(list, holder)) {\n held!.delete(holder);\n } else if (holder !== requester) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * 行を写しに貸した配列(#393)。差分は、外側の行の内側のパスに書いた写しへ前の配列の行を貸す(DOM を保つため)。\n * 前の配列を別の外側の行がまだ持っていて(書いた外側の行はまだ引いていなかった — if で隠れていた等)後から引くと、\n * 台帳は行をその外側の行へ付け替えようとする — 付け替えると写しの行も動き、写しの要素の書き込みが前の配列に着地する。\n * 貸した配列には、付け替える代わりに新しい行集合を作る(resolveListIndexesByList)。\n */\nconst lentLists = new WeakSet<readonly unknown[]>();\n\nexport function markListLent(list: readonly unknown[]): void {\n lentLists.add(list);\n}\n\n/**\n * 同じ要素オブジェクトを表している、書いた配列の外の生きた行(createListIndex.ts の getRowsOfSameElement・#393)。退役した行・\n * 退役した外側の行の下の行(外側の行ごと外した行 — 差分を通らない)は数えない\n */\nexport function getElementAliases(row: IListIndex, readList: () => readonly unknown[]): readonly IListIndex[] {\n const others = getRowsOfSameElement(row);\n if (others.length === 0) {\n return others;\n }\n // 入れ子のリストの、書いた配列(`readList` — 別の行が居るときだけ読む)の外の行だけ — 深さの違う行は書いたパスの\n // アドレスにならず、同じ配列の 2 つの位置・ルート直下の写しは、同じオブジェクトを 2 つの行に置いた形の制約のまま(#365 / #362)\n const rows = new Set(listIndexesByList.get(readList()));\n return others.filter((other) => other.position === row.position && !rows.has(other) && !isUnderRetiredRow(other));\n}\n\n/**\n * 台帳の行がぶら下がる親(`oldParent`)を、いま要求している親(`newParent`)へ\n * 付け替えてよいか。**親がもうその配列を持たないとき(退役した・手放した)だけ**真 ──\n * 持っているなら共有であって陳腐化ではないので、main と同じく 1 組の行集合に合流させる。\n * 深さ(`position`)が変わる付け替えはしない。行の `position` / `length` は鋳造時に\n * 確定していて、そこがずれると絶対アドレスの段数が壊れる(bind-component が 1 本の\n * 配列を 2 つの深さから展開する形が実際にある)。\n */\nfunction canReparent(list: readonly unknown[], oldParent: IListIndex | null, newParent: IListIndex | null): boolean {\n if (oldParent === newParent) {\n // 自分が展開した行集合(ここが圧倒的多数)。ルート直下どうし(両方 null)もここ。\n return false;\n }\n if (oldParent === null || newParent === null) {\n return false;\n }\n if (oldParent.position !== newParent.position) {\n return false;\n }\n return isGoneParent(list, oldParent) && isHoldingParent(list, newParent);\n}\n\n/**\n * 要求している親(`newParent`)が、退役した `home` の**行そのもの**か。\n * 行を戻す普通のやり方(新しい配列に同じ要素を並べ直す)では差分が ListIndex を作り直すので、\n * home の ListIndex は二度と生き返らない。同じリスト要素を同じ深さで表している生きた行が\n * 現れたら、それが戻ってきた home である。\n */\nfunction isRestoredHome(\n list: readonly unknown[],\n home: IListIndex | null,\n oldParent: IListIndex | null,\n newParent: IListIndex | null,\n): boolean {\n if (home === null || newParent === null) {\n return false;\n }\n if (newParent === oldParent) {\n // すでにそこにある(=毎回 reparent して version を進めない)。\n return false;\n }\n if (!retiredListIndexes.has(home)) {\n // home が生きているなら「生き返った home」の分岐が扱う。\n return false;\n }\n if (!isHoldingParent(list, newParent) || newParent.position !== home.position) {\n return false;\n }\n // 手放した home の要素は、もうこの配列を持たない(#394)\n return !hasReleasedList(list, home) && isSameListIndexValue(newParent, home);\n}\n\n/**\n * 行集合の親をどこへ向けるか。`null` なら何もしない。\n * 優先順位は **「生き返った home」>「戻ってきた home の行」>「陳腐化した親の付け替え」**。\n */\nfunction getRepairTarget(list: readonly unknown[], first: IListIndex, parentListIndex: IListIndex | null): IListIndex | null {\n const home = getHomeParentListIndex(first);\n const oldParent = first.parentListIndex;\n if (home !== null && home !== oldParent && !isGoneParent(list, home) && covers(list, home, oldParent!)) {\n return home;\n }\n if (isRestoredHome(list, home, oldParent, parentListIndex)) {\n return parentListIndex;\n }\n return canReparent(list, oldParent, parentListIndex) ? parentListIndex : null;\n}\n\n/**\n * 台帳を**引き当てるだけ**。行の親ポインタには触らない。\n * 観測(テスト・世代の後始末・`$scan` の drain が行の置き換わりを見る判定)と存在判定はこちらを使う。\n */\nexport function getListIndexesByList(list: readonly unknown[]): IListIndex[] | null {\n const listIndexes = listIndexesByList.get(list);\n if (typeof listIndexes === \"undefined\") {\n return null;\n }\n return listIndexes;\n}\n\n/**\n * 台帳を引き当て、**必要なら親ポインタを修理して**返す(#256)。\n * 引き当てのついでに行を書き換えるので、観測目的では使わないこと ──\n * 修理が要るのは「その親の文脈で値を解決する」経路(差分・アドレス解決)だけ。\n */\nexport function resolveListIndexesByList(\n list: readonly unknown[],\n parentListIndex: IListIndex | null,\n): IListIndex[] | null {\n const listIndexes = listIndexesByList.get(list);\n if (typeof listIndexes === \"undefined\") {\n return null;\n }\n const first = listIndexes[0];\n // 描いた並びの写し(要素書き込みの入れ替えの前の並び — swapBaselineList.ts・下の貸した行の写し)は state に居ないので、\n // その台帳を引いても行を付け替えない — 写しを持つ外側の行の印(手放した・退役した)が無いので、行集合を手放した外側の行\n // (home)へ戻してしまう(#394)\n if (typeof first !== \"undefined\" && !isSwapBaselineList(list)) {\n // 行の親とは別の、配列を持っている外側の行から引いた。入れ替えの途中で別の要素を映している行が引いたのは共有ではない\n // (揃うと行は元の要素へ戻る)\n const other = parentListIndex !== null && first.parentListIndex !== parentListIndex &&\n swapPendingBatchByRow.get(parentListIndex) !== updateBatch;\n const target = getRepairTarget(list, first, parentListIndex);\n if (target !== null && lentLists.has(list)) {\n lentLists.delete(list);\n // この配列を描いた `for` が描いたのは貸した行。描いた並びを、貸した行の台帳を持つ写しへ移す(#320 の記録)\n const image = [...list];\n markSwapBaselineList(image);\n listIndexesByList.set(image, listIndexes);\n rebaseRenderedList(list, image);\n const rows = listIndexes.map((_row, i) => {\n const row = createListIndex(target, i);\n setListIndexValue(row, list[i]);\n return row;\n });\n listIndexesByList.set(list, rows);\n return rows;\n }\n if (target !== null) {\n // 1 組の行集合は 1 つの親のもとにある、を保つ(差分が別の親の行を混ぜて\n // 作った集合も、ここで揃える)。\n for (const listIndex of listIndexes) {\n reparentListIndex(listIndex, target);\n }\n } else if (other) {\n // 2 つの外側の行が持つ配列(holdersByList)。要求した外側の行が、いまの親より多くのキーで配列を持つなら、そちらを親に\n // する(上の covers — 片方のキーにしか持たない外側の行が先に引いた)\n addHolders(list, [first.parentListIndex, parentListIndex]);\n const parent = first.parentListIndex;\n if (parent !== null && parent.position === parentListIndex!.position && !covers(list, parent, parentListIndex!) &&\n covers(list, parentListIndex!, parent)) {\n for (const listIndex of listIndexes) {\n reparentListIndex(listIndex, parentListIndex);\n }\n }\n }\n }\n return listIndexes;\n}\n\n/**\n * 要素の書き込み(setByAddress の renewReplacedRow・#333)が写した台帳のうち、その配列の台帳としてしか\n * 参照されていないもの。次の要素の書き込みは写さずにその場で書き換えてよい(写すと、1 バッチで全要素を\n * 書く `$setAll(\"items.*\", …)` が O(n²) になる)。台帳の配列を別の持ち手が捕まえたら外す — 別の配列の\n * 台帳にする(下の setListIndexesByList)、差分が持つ(createListDiff)、入れ替えが持つ(swapInfo.ts)、\n * `$eqIndex` の監視が付く(dependency/keyedDependency.ts の registerIndexWatcher / moveIndexWatchers)。\n */\nconst ownedListIndexes = new WeakSet<IListIndex[]>();\n\nexport function isOwnedListIndexes(listIndexes: IListIndex[]): boolean {\n return ownedListIndexes.has(listIndexes);\n}\n\nexport function disownListIndexes(listIndexes: IListIndex[]): void {\n ownedListIndexes.delete(listIndexes);\n}\n\nexport function setListIndexesByList(list: readonly unknown[], listIndexes: IListIndex[] | null, owned = false): void {\n if (listIndexes === null) {\n listIndexesByList.delete(list);\n return;\n }\n if (owned) {\n ownedListIndexes.add(listIndexes);\n } else {\n disownListIndexes(listIndexes);\n }\n listIndexesByList.set(list, listIndexes);\n}\n\n/**\n * `for` が描いた並び(#320)。1 本の配列につき 1 つで、その配列を描いたどの `for` もこれを指す。\n *\n * 描画の基準(lastListValueByAbsoluteStateAddress.ts)はアドレスごとに 1 本なので、同じリストを描く `for` が複数あると、画面から外れていて\n * 描かなかった `for`(`if` で消された・DOM から外された)を待たずに進む。そうした `for` は自分が\n * 描いた並びとの差分を取る(applyChangeToFor)。その並びを配列そのもので覚えると、要素書き込みが\n * 配列をその場で書き換えて台帳を差し替えたときに「描いた並び」が失われるので、ここを 1 段挟む。\n * 要素書き込みの入れ替えが揃ったら、ここを書き込む前の並びの写しに差し替える(rebaseRenderedList)。\n */\nexport interface IRenderedList {\n value: readonly unknown[];\n}\n\nconst renderedListByList: WeakMap<readonly unknown[], IRenderedList> = new WeakMap();\n\nexport function getRenderedList(list: readonly unknown[]): IRenderedList {\n let rendered = renderedListByList.get(list);\n if (typeof rendered === \"undefined\") {\n rendered = { value: list };\n renderedListByList.set(list, rendered);\n }\n return rendered;\n}\n\n/** この配列を描いた `for` がいて、描いた後にまだ描画の基準を移していないか(setByAddress の renewReplacedRow) */\nexport function hasRenderedList(list: readonly unknown[]): boolean {\n return renderedListByList.has(list);\n}\n\n/**\n * 要素書き込みの入れ替えが揃った(setByAddress の notifySwappedList)。この配列をこれまでに描いた `for` が\n * 描いたのは、書き込む前の並び(`image` — 写しと台帳の写し)。以後この配列を描く `for` は新しい並びを指す。\n */\nexport function rebaseRenderedList(list: readonly unknown[], image: readonly unknown[]): void {\n const rendered = renderedListByList.get(list);\n if (typeof rendered !== \"undefined\") {\n rendered.value = image;\n renderedListByList.delete(list);\n }\n}\n","import { IAbsoluteStateAddress } from \"../address/types\";\nimport { IListIndex } from \"./types\";\nimport { getListIndexesByList, isRetiredListIndex } from \"./listIndexesByList\";\n\nconst lastListValueByAbsoluteStateAddress: WeakMap<IAbsoluteStateAddress, readonly unknown[]> = new WeakMap();\n\n/**\n * 上の記録の逆引き(#379): state 要素ごとに、配列 → その配列をいま描画の基準にしているアドレス。\n * 同じ配列を別のアドレスの `for` も描いている(2 つの外側の行が同じ内側の配列を持つ・同じ行の別パス)とき、\n * 要素書き込みの入れ替えが揃ったら、その `for` にも書き込む前の並びからの差分で描き直させる(setByAddress の\n * notifySwappedList → 下の markSwappedList)。state 要素ごとに分けるのは、別の state の `for` を描き直させず、\n * 捨てた state を配列から持ち続けないため。退役した行(リストから外した外側の行)とその下のアドレスは、集合が\n * 前に見直したときの 2 倍に育ったときに外す(行の数に比例する手間で、外した外側の行を持ち続けない)。\n */\nconst addressesByListByStateElement: WeakMap<object, WeakMap<readonly unknown[], Set<IAbsoluteStateAddress>>> = new WeakMap();\nconst NO_ADDRESSES: ReadonlySet<IAbsoluteStateAddress> = new Set<IAbsoluteStateAddress>();\n/** 逆引きの集合を次に見直す大きさ(退役した行の下のアドレスを外す — setLastListValueByAbsoluteStateAddress) */\nconst sweepAtByAddresses: WeakMap<Set<IAbsoluteStateAddress>, number> = new WeakMap();\nconst SWEEP_MIN = 8;\n\n/**\n * 同じ配列を描く別の `for` のアドレス → 要素書き込みの入れ替えが揃ったその配列(#379)。そのアドレスの `for`(同じ行を\n * 描く `for` が 2 つあれば両方)が描くときに見て(isSwappedList — applyChangeToFor)、描いた後の記録(上の set)で\n * 消える。まだその配列を描くなら、自分が描いた並び(入れ替えの前の写しへ移された #320 の記録)との差分を取る。\n * 基準そのもの(上の記録)は差し替えない — 同じバッチでその `for` のパスへ別の配列を書いていたら、いままでの基準との\n * 差分(#320 の突き合わせ)で描く。写しを基準にすると、差分が新しい配列の行を引き直し、その行が写しの行集合の\n * 持ち主の外側の行へ付け替わる(#256)。\n */\nconst swappedListByAddress: WeakMap<IAbsoluteStateAddress, readonly unknown[]> = new WeakMap();\n\nfunction addressesByListOf(address: IAbsoluteStateAddress): WeakMap<readonly unknown[], Set<IAbsoluteStateAddress>> {\n const stateElement = address.absolutePathInfo.stateElement;\n let addressesByList = addressesByListByStateElement.get(stateElement);\n if (typeof addressesByList === \"undefined\") {\n addressesByList = new WeakMap();\n addressesByListByStateElement.set(stateElement, addressesByList);\n }\n return addressesByList;\n}\n\nexport function getLastListValueByAbsoluteStateAddress(address: IAbsoluteStateAddress): readonly unknown[] {\n return lastListValueByAbsoluteStateAddress.get(address) ?? [];\n}\n\nexport function setLastListValueByAbsoluteStateAddress(address: IAbsoluteStateAddress, value: readonly unknown[]): void {\n const previous = lastListValueByAbsoluteStateAddress.get(address);\n lastListValueByAbsoluteStateAddress.set(address, value);\n swappedListByAddress.delete(address);\n const addressesByList = addressesByListOf(address);\n if (previous !== value && typeof previous !== \"undefined\") {\n addressesByList.get(previous)!.delete(address);\n }\n const addresses = addressesByList.get(value);\n if (typeof addresses === \"undefined\") {\n addressesByList.set(value, new Set([address]));\n } else if (!addresses.has(address)) {\n // 足すたびに全部を見ると、同じ配列を N 行が持つページの描画が N² になる。集合が前に見た後の 2 倍に育ったときだけ見る\n if (addresses.size >= (sweepAtByAddresses.get(addresses) ?? SWEEP_MIN)) {\n addresses.forEach((held) => {\n if (isUnderRetiredRow(held.listIndex)) {\n addresses.delete(held);\n }\n });\n sweepAtByAddresses.set(addresses, Math.max(SWEEP_MIN, addresses.size * 2));\n }\n addresses.add(address);\n }\n}\n\n/**\n * アドレスの行か、その祖先の行が退役しているか。外側の行をリストから外すと、その下の行(3 段なら中の行)は\n * 差分を通らないので退役の印が付かない — 祖先まで見ないと、作り直すたびに外したアドレスが残り続ける\n */\nfunction isUnderRetiredRow(listIndex: IListIndex | null): boolean {\n for (let row = listIndex; row !== null; row = row.parentListIndex) {\n if (isRetiredListIndex(row)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * この state 要素で、この配列をいま描画の基準にしているアドレス(`address` の state 要素で引く)。退役した行の下の\n * アドレスはここでも外す — 外側の行を減らした後の要素書き込みが、外した行の `for` を毎回数えないように\n */\nexport function getAddressesByLastListValue(address: IAbsoluteStateAddress, value: readonly unknown[]): ReadonlySet<IAbsoluteStateAddress> {\n const addresses = addressesByListOf(address).get(value);\n if (typeof addresses === \"undefined\") {\n return NO_ADDRESSES;\n }\n addresses.forEach((held) => {\n if (isUnderRetiredRow(held.listIndex)) {\n addresses.delete(held);\n }\n });\n return addresses;\n}\n\n/** 同じ配列を描く別の `for` に、その配列の入れ替えが揃ったことを知らせる(上の swappedListByAddress)。もう知らせてあれば偽 */\nexport function markSwappedList(address: IAbsoluteStateAddress, list: readonly unknown[]): boolean {\n if (swappedListByAddress.has(address)) {\n return false;\n }\n swappedListByAddress.set(address, list);\n return true;\n}\n\n/**\n * 入れ替えが揃ったと知らされていて、いま描く値がその配列か。同じ中身の写し(同じバッチで\n * `[...items]` を書いた)は元の配列の台帳をそのまま持つので、同じ配列として扱う\n */\nexport function isSwappedList(address: IAbsoluteStateAddress, value: unknown): boolean {\n const list = swappedListByAddress.get(address);\n return typeof list !== \"undefined\" && (list === value || getListIndexesByList(value as unknown[]) === getListIndexesByList(list));\n}\n\nexport function clearLastListValueByAbsoluteStateAddress(address: IAbsoluteStateAddress): void {\n const previous = lastListValueByAbsoluteStateAddress.get(address);\n lastListValueByAbsoluteStateAddress.delete(address);\n if (typeof previous !== \"undefined\") {\n addressesByListOf(address).get(previous)!.delete(address);\n }\n}\n\nexport function hasLastListValueByAbsoluteStateAddress(address: IAbsoluteStateAddress): boolean {\n return lastListValueByAbsoluteStateAddress.has(address);\n}\n\n// `for` が描いた並び(#320)の記録は、行の台帳と一緒に持つ(list/listIndexesByList.ts — 台帳を作り直すときに描いた並びを移す・#393)\nexport { getRenderedList, hasRenderedList, rebaseRenderedList } from \"./listIndexesByList\";\nexport type { IRenderedList } from \"./listIndexesByList\";\n","/**\n * list/stateListBaseline.ts\n *\n * state 側のリスト差分基準 — 「最後に **state 側が観測した** リスト値」。\n *\n * 描画側の基準([lastListValueByAbsoluteStateAddress](./lastListValueByAbsoluteStateAddress.ts))\n * とは別の問いに答える台帳である。あちらは「最後に**描画した**値」で、`applyChangeToFor` が\n * 「画面に対して何を足し引きするか」を決めるために使う。こちらは読み(`$getAll`)と\n * 依存ウォーク(`walkDependency`)が「**前回見た形からどう変わったか**」を決めるために使う。\n *\n * 統合してはならない。ウォークが描画側の基準を進めると、その後の `applyChangeToFor` が\n * 空の差分を見て描画を落とす。逆に描画側の基準だけに頼ると、`for` バインドの無いリストでは\n * 基準が永久に空のままになり、`createListDiff` の「旧リストが空」分岐が新しい配列に\n * **新しい ListIndex を鋳造**する。子リストの台帳は旧親 ListIndex を指したまま残るので\n * 親子の連鎖が切れ、集計が恒久的に stale になるか `ListIndexes not found` で恒久的に\n * throw する(docs/state-recursive-path-impl-plan.md §3-2 の E1)。\n *\n * 書き手は 5 系統ある。いずれも「観測した」という同じ意味を持つ。\n * - 読み: `collectWildcardIndexes`(`commitDiffBaseline: true` のときだけ。固定 arity の\n * `$setAll` は走査を借りるだけで動かさない — docs/state-set-all-design.md §6-2)\n * - 再帰の走査: `recursion/walk.ts`(合併形の `$getAll` と**再帰の `$setAll` の両方**が確定する。\n * cold な書き込みが ListIndex 世代を鋳造したまま基準を残すと、次の構造変更で深い子台帳が\n * 孤児になるため — docs/state-recursive-path-impl-plan.md §6)\n * - 描画: `applyChangeFromBindings` / `hydrateBindings`(描画側の基準と同時に書く)\n * - 依存ウォーク: `walkDependency`(ウォーク完了後にまとめて確定する)\n * - 添字から行を引く経路(直接添字・`$postUpdate`・`$resolve` / `$setAll` の行の引き直し —\n * proxy/methods/getListIndexesByAddress.ts): 台帳の無いリストに台帳を生やしたときだけ(#324)。\n * 生やした行を基準に載せないと、描いていないリストを写し替えたときに行が退役せず、子リストの\n * 台帳が古い行にぶら下がったまま残る\n *\n * キーは **絶対アドレス**。`IStateAddress` は listIndex が null のとき pathInfo だけで\n * intern されるため、同じパス形状のルートリストを持つ 2 つの state 要素がエントリを\n * 共有してしまう(`createStateAddress` の `_cacheNullListIndex`)。\n */\nimport { IAbsoluteStateAddress } from \"../address/types\";\n\nconst stateListBaselineByAbsoluteStateAddress: WeakMap<IAbsoluteStateAddress, readonly unknown[]> = new WeakMap();\n/**\n * 更新バッチ中の観測は**即座に確定しない**。バッチ内で同じリストへ 2 回構造書き込みすると、\n * 2 回目のウォークが「一度も描画されず直後に上書きされる中間値」を基準に diff を取り、\n * 中間値が落とした行の ListIndex が鋳造し直されて子リストの台帳が恒久的に切れるため。\n *\n * バッチが開いている間の観測はここに溜め、バッチ末尾(updater の drain 終了)でまとめて\n * 確定する。こうするとバッチ内のどのウォークも「バッチ開始時の値」と diff を取り、\n * これは描画側(applyChangeToFor が描画基準で取る diff)と一致する。\n *\n * 深さで数えるのは、drain の最中に $updatedCallback などが書いて新しいバッチが\n * 始まる形があるため。0 に戻ったバッチだけが確定する。\n */\nlet pendingBaselines: Map<IAbsoluteStateAddress, readonly unknown[]> | null = null;\nlet batchDepth = 0;\n\nexport function getStateListBaseline(address: IAbsoluteStateAddress): readonly unknown[] {\n // pending は意図的に見ない。バッチ中の読み手には「バッチ開始時の値」を返す。\n return stateListBaselineByAbsoluteStateAddress.get(address) ?? [];\n}\n\nexport function setStateListBaseline(address: IAbsoluteStateAddress, value: readonly unknown[]): void {\n if (pendingBaselines !== null) {\n pendingBaselines.set(address, value);\n return;\n }\n stateListBaselineByAbsoluteStateAddress.set(address, value);\n}\n\n/** 更新バッチの開始(updater が最初の enqueue で呼ぶ)。 */\nexport function beginStateListBaselineBatch(): void {\n batchDepth++;\n if (pendingBaselines === null) {\n pendingBaselines = new Map<IAbsoluteStateAddress, readonly unknown[]>();\n }\n}\n\n/** 更新バッチの終了(updater が drain の finally で呼ぶ)。入れ子が全部閉じたら確定する。 */\nexport function endStateListBaselineBatch(): void {\n if (batchDepth === 0) {\n // enqueue を経ない直接 drain(testApplyChange)。開いていないバッチは閉じない。\n return;\n }\n batchDepth--;\n if (batchDepth > 0 || pendingBaselines === null) {\n return;\n }\n for (const [address, value] of pendingBaselines) {\n stateListBaselineByAbsoluteStateAddress.set(address, value);\n }\n pendingBaselines = null;\n}\n\n/** 台帳から 1 件落とす(描画側の clearLastListValueByAbsoluteStateAddress と対にしておく)。 */\nexport function clearStateListBaseline(address: IAbsoluteStateAddress): void {\n pendingBaselines?.delete(address);\n stateListBaselineByAbsoluteStateAddress.delete(address);\n}\n\nexport function hasStateListBaseline(address: IAbsoluteStateAddress): boolean {\n return (pendingBaselines?.has(address) ?? false)\n || stateListBaselineByAbsoluteStateAddress.has(address);\n}\n","\nexport const setLoopContextSymbol: unique symbol = Symbol(\"$$setLoopContext\");\nexport const getByAddressSymbol: unique symbol = Symbol(\"$$getByAddress\");\nexport const hasByAddressSymbol: unique symbol = Symbol(\"$$hasByAddress\");\nexport const connectedCallbackSymbol: unique symbol = Symbol(\"$$connectedCallback\");\nexport const disconnectedCallbackSymbol: unique symbol = Symbol(\"$$disconnectedCallback\");\nexport const updatedCallbackSymbol: unique symbol = Symbol(\"$$updatedCallback\");\nexport const errorCallbackSymbol: unique symbol = Symbol(\"$$errorCallback\");\n","import { IListIndex } from \"../list/types\";\nimport { ITreePath, IAbsoluteStateAddress } from \"./types\";\n\nconst _cache: WeakMap<IListIndex, WeakMap<ITreePath, IAbsoluteStateAddress>> = new WeakMap();\nconst _cacheNullListIndex: WeakMap<ITreePath, IAbsoluteStateAddress> = new WeakMap();\n\nclass AbsoluteStateAddress implements IAbsoluteStateAddress {\n readonly absolutePathInfo: ITreePath;\n readonly listIndex: IListIndex | null;\n\n constructor(absolutePathInfo: ITreePath, listIndex: IListIndex | null) {\n this.absolutePathInfo = absolutePathInfo;\n this.listIndex = listIndex;\n }\n}\n\nexport function createAbsoluteStateAddress(absolutePathInfo: ITreePath, listIndex: IListIndex | null): IAbsoluteStateAddress {\n if (listIndex === null) {\n let cached = _cacheNullListIndex.get(absolutePathInfo);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n cached = new AbsoluteStateAddress(absolutePathInfo, null);\n _cacheNullListIndex.set(absolutePathInfo, cached);\n return cached;\n } else {\n let cacheByAbsolutePathInfo = _cache.get(listIndex);\n if (typeof cacheByAbsolutePathInfo === \"undefined\") {\n cacheByAbsolutePathInfo = new WeakMap<ITreePath, IAbsoluteStateAddress>();\n _cache.set(listIndex, cacheByAbsolutePathInfo);\n }\n let cached = cacheByAbsolutePathInfo.get(absolutePathInfo);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n cached = new AbsoluteStateAddress(absolutePathInfo, listIndex);\n cacheByAbsolutePathInfo.set(absolutePathInfo, cached);\n return cached;\n }\n}\n","import { IStateElement } from \"../components/types\";\nimport { ITreePath, IPathInfo } from \"./types\";\n\n/**\n * ツリー(`<wcs-state>` 要素)に固定したパス。絶対アドレスの intern の中間ノードであり、\n * 行バインディングのパターン台帳のキーでもある(docs/state-row-instantiation-redesign.md §3-3)。\n *\n * 表は「要素を弱キーにした WeakMap → PathInfo をキーにした Map」の 2 段。PathInfo はページの\n * 寿命だけ生きる(強参照の Map に載っている)ので内側は WeakMap である必要が無く、Map のほうが\n * 引きが速い。各段は get 1 回と undefined 比較で引く — has してから get する形は同じ表を\n * 2 回引いていた。読みのベンチ(e2e/bench/plain-read.mjs)では、キャッシュを引く読みが\n * getter で約 1ns、行の getter で 3〜5ns 速くなり、この関数を通らない素のパスの読みは変わらない\n * (docs/spikes/state-address-intern-placement/README.md の main-tp)。\n *\n * ノードへの強参照経路は要素の WeakMap エントリ(ephemeron)だけなので、要素が DOM から外れれば\n * ノードごと回収される(e2e/tests/state-address-gc.spec.ts)。\n */\nconst treePathsByElement: WeakMap<IStateElement, Map<IPathInfo, ITreePath>> = new WeakMap();\n\nexport function getTreePath(stateElement: IStateElement, pathInfo: IPathInfo): ITreePath {\n let table = treePathsByElement.get(stateElement);\n if (table === undefined) {\n table = new Map();\n treePathsByElement.set(stateElement, table);\n }\n let treePath = table.get(pathInfo);\n if (treePath === undefined) {\n treePath = Object.freeze(new TreePath(stateElement, pathInfo));\n table.set(pathInfo, treePath);\n }\n return treePath;\n}\n\nclass TreePath implements ITreePath {\n readonly pathInfo: IPathInfo;\n readonly stateElement: IStateElement;\n constructor(stateElement: IStateElement, pathInfo: IPathInfo) {\n this.pathInfo = pathInfo;\n this.stateElement = stateElement;\n }\n}\n","import { IStateElement } from \"../components/types\";\nimport { IListIndex } from \"../list/types\";\nimport { createAbsoluteStateAddress } from \"./AbsoluteStateAddress\";\nimport { getTreePath } from \"./TreePath\";\nimport { IAbsoluteStateAddress, IPathInfo, IStateAddress } from \"./types\";\n\n/**\n * ツリー非依存のアドレスを、`stateElement`(どのツリーか)まで確定した絶対アドレスへ持ち上げる。\n *\n * 恒久台帳(cache / bindings / baseline / updater の queue)はモジュール単一でツリーをまたぐので、\n * キーは必ずこちらを使う — `IStateAddress` をそのままキーにすると、同じパス形状や同じ配列を持つ\n * 2 つの `<wcs-state>` が混線する(__tests__/addressLedgerKeyGuard.test.ts が番人)。\n *\n * 持ち上げは選択の余地が無い決定的な変換で、以前は各呼び出し元が 2 行で手書きしていた。\n * ここに集めて、intern の関数(getTreePath / createAbsoluteStateAddress)を src/address/ の外から\n * 直接呼ばせない(__tests__/addressImportBoundary.test.ts が番人)。2 本の型を 1 本に畳む統合\n * (docs/state-address-unification-design.md)は、素のパスの読みを退行させることが実測で分かり、\n * 閉じた(同 §12)— この持ち上げは残る。\n */\nexport function liftAddress(stateElement: IStateElement, address: IStateAddress): IAbsoluteStateAddress {\n return createAbsoluteStateAddress(getTreePath(stateElement, address.pathInfo), address.listIndex);\n}\n\n/** `IStateAddress` を経ずに、構成要素から直接絶対アドレスを作る。 */\nexport function absoluteAddressOf(\n stateElement: IStateElement,\n pathInfo: IPathInfo,\n listIndex: IListIndex | null,\n): IAbsoluteStateAddress {\n return createAbsoluteStateAddress(getTreePath(stateElement, pathInfo), listIndex);\n}\n","\nconst rootNodeByFragment: WeakMap<DocumentFragment, Node> = new WeakMap();\n\nexport function setRootNodeByFragment(fragment: DocumentFragment, rootNode: Node | null): void {\n if (rootNode === null) {\n rootNodeByFragment.delete(fragment);\n } else {\n rootNodeByFragment.set(fragment, rootNode);\n }\n}\n\nexport function getRootNodeByFragment(fragment: DocumentFragment): Node | null {\n return rootNodeByFragment.get(fragment) || null;\n}\n","import { IPathInfo } from \"./types.js\";\n\nconst cacheCalcWildcardLen: Map<string, number> = new Map(); \n\nexport function calcWildcardLen(pathInfo: IPathInfo, targetPathInfo: IPathInfo): number {\n let path1: IPathInfo;\n let path2: IPathInfo;\n if (pathInfo.wildcardCount === 0 || targetPathInfo.wildcardCount === 0) {\n return 0;\n }\n if (pathInfo.wildcardCount === 1 \n && targetPathInfo.wildcardCount > 0 \n && targetPathInfo.wildcardPathSet.has(pathInfo.path)) {\n return 1;\n }\n if (pathInfo.id < targetPathInfo.id) {\n path1 = pathInfo;\n path2 = targetPathInfo;\n } else {\n path1 = targetPathInfo;\n path2 = pathInfo;\n }\n const key = `${path1.path}\\t${path2.path}`;\n let len = cacheCalcWildcardLen.get(key);\n if (typeof len !== \"undefined\") {\n return len;\n }\n const matchPath = path1.wildcardPathSet.intersection(path2.wildcardPathSet);\n len = matchPath.size;\n cacheCalcWildcardLen.set(key, len);\n return len;\n}\n\n","/**\n * list/wildcardLevel.ts\n *\n * 「パス上のワイルドカード位置」→「listIndex チェーン上の段」の変換を 1 箇所に集める。\n *\n * チェーンの長さは常に `Δ + W`(W = そのパスの wildcardCount、Δ = そのスコープの\n * base 深さ)である。通常の state スコープは Δ=0 なので「位置 i = 段 i」で済んでいたが、\n * `bind-component` の子スコープがホストの `for` の内側にいる場合は Δ>0 になる\n * (docs/state-bind-component-nested-for-design.md)。\n *\n * そこで**先頭ではなく末尾を基準に数える**。`IListIndex.at()` は負値を受けるので:\n *\n * at(i) → at(i - W) // listIndexes[(Δ+W) + (i-W)] = listIndexes[Δ+i]\n *\n * Δ=0 のときは両者が同じ要素を指すため、この書き換えは既存スコープに対して\n * 意味論を変えない。Δ の値を呼び出し側へ配管する必要も無い。\n */\n\nimport { IListIndex } from \"./types\";\n\n/**\n * ワイルドカード位置 `wildcardPos`(先頭から 0 始まり)に対応する listIndex を返す。\n * `wildcardCount` は `wildcardPos` が属するパスのワイルドカード総数。\n *\n * 範囲外(`wildcardPos >= wildcardCount`)は null。Δ=0 では `at(pos)` が\n * チェーン長を超えて null を返していたのと同じ結果になる。**このガードは必須**で、\n * 落とすと「1 段ループの中で `$2` を読む」が黙って `$1` を返す\n * (末尾起点では `at(1-1)=at(0)` に化けるため)。\n */\nexport function listIndexAtWildcard(\n listIndex: IListIndex,\n wildcardPos: number,\n wildcardCount: number,\n): IListIndex | null {\n if (wildcardPos < 0 || wildcardPos >= wildcardCount) {\n return null;\n }\n return listIndex.at(wildcardPos - wildcardCount);\n}\n\n/**\n * ユーザーランドへ渡すインデックス列。チェーンの先頭 Δ 段(base)を落とし、\n * **そのスコープ自身のループ分だけ**にする。\n *\n * コンポーネントの作者は、自分がリストの中に置かれるかどうかを知らずに書く。\n * `$1` や `onClick(event, index)` の意味が設置場所で変わってはいけないので、\n * Δ は境界の内側に閉じ込める。`$resolve(path, indexes)` は台帳の配列位置で\n * 引くため、ここで返した列がそのまま往復で使える。\n */\nexport function getScopedIndexes(listIndex: IListIndex, wildcardCount: number): number[] {\n // indexes は型上は必須だが、防御的フォールバックを既存挙動として持っている\n const indexes = listIndex.indexes ?? [];\n if (indexes.length === wildcardCount) {\n return indexes;\n }\n return indexes.slice(indexes.length - wildcardCount);\n}\n","import { calcWildcardLen } from \"../address/calcWildcardLen\";\nimport { IBindingInfo } from \"../types\";\nimport { getLoopContextByNode } from \"./loopContextByNode\";\nimport { IListIndex, ILoopContext } from \"./types\";\nimport { listIndexAtWildcard } from \"./wildcardLevel\";\n\nconst listIndexByBindingInfoByLoopContext: WeakMap<ILoopContext, WeakMap<IBindingInfo, IListIndex | null>> = new WeakMap();\n\nexport function getListIndexByBindingInfo(bindingInfo: IBindingInfo): IListIndex | null {\n const loopContext = getLoopContextByNode(bindingInfo.node);\n if (loopContext === null) {\n return null;\n }\n let listIndexByBindingInfo = listIndexByBindingInfoByLoopContext.get(loopContext);\n if (typeof listIndexByBindingInfo === \"undefined\") {\n listIndexByBindingInfo = new WeakMap<IBindingInfo, IListIndex | null>();\n listIndexByBindingInfoByLoopContext.set(loopContext, listIndexByBindingInfo);\n } else {\n const listIndex = listIndexByBindingInfo.get(bindingInfo);\n if (typeof listIndex !== \"undefined\") {\n return listIndex;\n }\n }\n\n let listIndex: IListIndex | null = null;\n try {\n const wildcardLen = calcWildcardLen(loopContext.pathInfo, bindingInfo.statePathInfo);\n if (wildcardLen > 0) {\n listIndex = listIndexAtWildcard(loopContext.listIndex, wildcardLen - 1, loopContext.pathInfo.wildcardCount);\n }\n return listIndex;\n } finally {\n listIndexByBindingInfo.set(bindingInfo, listIndex);\n }\n\n}\n","import { absoluteAddressOf } from \"../address/liftAddress\";\nimport { IAbsoluteStateAddress } from \"../address/types\";\nimport { getRootNodeByFragment } from \"../apply/rootNodeByFragment\";\nimport { getListIndexByBindingInfo } from \"../list/getListIndexByBindingInfo\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo } from \"./types\";\n\nconst absoluteStateAddressByBinding: WeakMap<IBindingInfo, IAbsoluteStateAddress> = new WeakMap();\n\n/**\n * binding の解決済み root を返す。knownRootNode があれば getRootNode() と\n * fragment フォールバックを省略する(リスト行活性化のホットパス)。\n */\nexport function resolveBindingRootNode(binding: IBindingInfo, knownRootNode?: Node | null): Node {\n if (knownRootNode != null) {\n return knownRootNode;\n }\n let rootNode: Node = binding.replaceNode.getRootNode() as Node;\n // binding.replaceNodeはisConnected=trueになっていることが前提、切断されている場合はraiseErrorを返す\n if (binding.replaceNode.isConnected === false) {\n // DocumentFragmentでバッファリングされている場合は、ルートノードをDocumentFragmentから実際のルートノードに切り替える\n const rootNodeByFragment = getRootNodeByFragment(rootNode as DocumentFragment);\n if (rootNodeByFragment === null) {\n raiseError(`Cannot get absolute state address for disconnected binding: ${binding.bindingType} ${binding.statePathName} on ${binding.node.nodeName}`);\n } else {\n rootNode = rootNodeByFragment;\n }\n }\n return rootNode;\n}\n\nexport function getAbsoluteStateAddressByBinding(binding: IBindingInfo, knownRootNode?: Node | null): IAbsoluteStateAddress {\n // 切断されていても、キャッシュされていれば絶対状態アドレスを返す。\n let absoluteStateAddress: IAbsoluteStateAddress | null = null;\n absoluteStateAddress = absoluteStateAddressByBinding.get(binding) || null;\n if (absoluteStateAddress !== null) {\n return absoluteStateAddress;\n }\n\n const rootNode: Node = resolveBindingRootNode(binding, knownRootNode);\n\n const listIndex = getListIndexByBindingInfo(binding);\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n absoluteStateAddress = absoluteAddressOf(stateElement, binding.statePathInfo, listIndex);\n absoluteStateAddressByBinding.set(binding, absoluteStateAddress);\n return absoluteStateAddress;\n}\n\nexport function clearAbsoluteStateAddressByBinding(binding: IBindingInfo) {\n absoluteStateAddressByBinding.delete(binding);\n}","import { createAbsoluteStateAddress } from \"../address/AbsoluteStateAddress\";\nimport { ITreePath, IAbsoluteStateAddress } from \"../address/types\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { IListIndex } from \"../list/types\";\nimport { IBindingInfo } from \"./types\";\n\n/**\n * 絶対アドレス → 登録 binding の台帳。\n *\n * リスト行の絶対アドレスは (absolutePathInfo, listIndex) の組ごとに一意で、\n * 登録される binding は通常 1 本しかない。アドレスごとに Set を確保すると\n * 行×binding の数だけ Set アロケーションが積み上がるため、単一値で持ち\n * 2 本目から Set に昇格する(interestedSessionsByNode と同じ前例)。\n */\nconst bindingsByAbsoluteStateAddress: WeakMap<IAbsoluteStateAddress, IBindingInfo | Set<IBindingInfo>> = new WeakMap();\n\n/**\n * 参照専用の取得。未登録アドレスにエントリを生成・キャッシュしない\n * (リスト置換の drain は大量のバインディング無しアドレスを照会するため、\n * 生成すると空エントリが溜まり続ける)。\n * 戻り値は単一 binding(登録 1 本)か Set(2 本以上)のどちらか。\n * 呼び出し側は Set を変異してはならない(instanceof で分岐できるよう\n * ReadonlySet でなく Set 型で返す)。\n */\nexport function peekBindingsByAbsoluteStateAddress(\n absoluteStateAddress: IAbsoluteStateAddress,\n): IBindingInfo | Set<IBindingInfo> | undefined {\n return bindingsByAbsoluteStateAddress.get(absoluteStateAddress);\n}\n\nexport function addBindingByAbsoluteStateAddress(absoluteStateAddress: IAbsoluteStateAddress, binding: IBindingInfo): void {\n const current = bindingsByAbsoluteStateAddress.get(absoluteStateAddress);\n if (typeof current === \"undefined\") {\n bindingsByAbsoluteStateAddress.set(absoluteStateAddress, binding);\n } else if (current instanceof Set) {\n current.add(binding);\n } else if (current !== binding) {\n bindingsByAbsoluteStateAddress.set(absoluteStateAddress, new Set([current, binding]));\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-added\", absoluteAddress: absoluteStateAddress, binding });\n }\n}\n\nexport function clearBindingSetByAbsoluteStateAddress(absoluteStateAddress: IAbsoluteStateAddress): void {\n bindingsByAbsoluteStateAddress.delete(absoluteStateAddress);\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-cleared\", absoluteAddress: absoluteStateAddress });\n }\n}\n\nexport function removeBindingByAbsoluteStateAddress(absoluteStateAddress: IAbsoluteStateAddress, binding: IBindingInfo): void {\n const current = bindingsByAbsoluteStateAddress.get(absoluteStateAddress);\n if (typeof current === \"undefined\") {\n return;\n }\n if (current instanceof Set) {\n current.delete(binding);\n } else if (current === binding) {\n bindingsByAbsoluteStateAddress.delete(absoluteStateAddress);\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-removed\", absoluteAddress: absoluteStateAddress, binding });\n }\n}\n\n/**\n * パターン索引台帳(リスト行バインディング専用・docs/state-row-instantiation-redesign.md §3-3)。\n *\n * 行バインディングは (absolutePathInfo, listIndex) の 2 段キーで登録し、登録側では\n * AbsoluteStateAddress の intern(アドレスオブジェクト割当 + listIndex ごとの\n * intern 用 WeakMap)を一切行わない。書き込み側(setByAddress → enqueue)は従来\n * どおり intern 済みアドレスを使うため、drain はアドレスの構成要素\n * (absolutePathInfo / listIndex — どちらもオブジェクト同一性が保証済み)で\n * このパターン台帳を引ける。リオーダーは listIndex 同一性キーの帰結として\n * 従来同様ゼロタッチ。wholesale destroy は従来同様削除ゼロ(listIndex ごと GC 崩壊)。\n *\n * devtools 計装(state:binding-added/removed)はプロトコル契約なので、sink 接続時に\n * 限りアドレスを intern してイベントを流す(フック未接続時のコストは分岐 1 個の規範を維持)。\n */\nconst patternLedger: WeakMap<ITreePath, WeakMap<IListIndex, IBindingInfo | Set<IBindingInfo>>> = new WeakMap();\n\nexport function addBindingByPattern(absolutePathInfo: ITreePath, listIndex: IListIndex, binding: IBindingInfo): void {\n let rowMap = patternLedger.get(absolutePathInfo);\n if (typeof rowMap === \"undefined\") {\n rowMap = new WeakMap();\n patternLedger.set(absolutePathInfo, rowMap);\n }\n const current = rowMap.get(listIndex);\n if (typeof current === \"undefined\") {\n rowMap.set(listIndex, binding);\n } else if (current instanceof Set) {\n current.add(binding);\n } else if (current !== binding) {\n rowMap.set(listIndex, new Set([current, binding]));\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-added\", absoluteAddress: createAbsoluteStateAddress(absolutePathInfo, listIndex), binding });\n }\n}\n\nexport function removeBindingByPattern(absolutePathInfo: ITreePath, listIndex: IListIndex, binding: IBindingInfo): void {\n const rowMap = patternLedger.get(absolutePathInfo);\n if (typeof rowMap === \"undefined\") {\n return;\n }\n const current = rowMap.get(listIndex);\n if (typeof current === \"undefined\") {\n return;\n }\n if (current instanceof Set) {\n current.delete(binding);\n } else if (current === binding) {\n rowMap.delete(listIndex);\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:binding-removed\", absoluteAddress: createAbsoluteStateAddress(absolutePathInfo, listIndex), binding });\n }\n}\n\n/**\n * drain(updater)用の統合参照。従来台帳 → パターン台帳の順に引く。\n * 従来台帳を先に引くのは、listIndex 付きでも旧経路(SSR ハイドレーション等)で\n * アドレス台帳に登録される可能性を許容するため(取りこぼし防止)。\n */\nexport function peekBindingsForAddress(\n absoluteStateAddress: IAbsoluteStateAddress,\n): IBindingInfo | Set<IBindingInfo> | undefined {\n const entry = bindingsByAbsoluteStateAddress.get(absoluteStateAddress);\n if (typeof entry !== \"undefined\") {\n return entry;\n }\n if (absoluteStateAddress.listIndex === null) {\n return undefined;\n }\n return patternLedger.get(absoluteStateAddress.absolutePathInfo)?.get(absoluteStateAddress.listIndex);\n}\n","import { WILDCARD } from \"../define\";\nimport { IListIndex } from \"../list/types\";\nimport { getListIndexValue } from \"../list/createListIndex\";\nimport { getListIndexesByList } from \"../list/listIndexesByList\";\nimport { IPathInfo, IStateAddress } from \"./types\";\n\nconst _cache: WeakMap<IListIndex, WeakMap<IPathInfo, IStateAddress>> = new WeakMap();\nconst _cacheNullListIndex: WeakMap<IPathInfo, IStateAddress> = new WeakMap();\n\nclass StateAddress implements IStateAddress {\n readonly pathInfo: IPathInfo;\n readonly listIndex: IListIndex | null;\n private _parentAddress: IStateAddress | undefined;\n /** 行のアドレス(末尾がワイルドカードで行を持つ)。親のアドレスは行の親に付いて変わる */\n private readonly _rowAddress: boolean;\n\n constructor(pathInfo: IPathInfo, listIndex: IListIndex | null) {\n this.pathInfo = pathInfo;\n this.listIndex = listIndex;\n this._rowAddress = listIndex !== null && pathInfo.lastSegment === WILDCARD;\n }\n\n /**\n * 行のアドレス(末尾がワイルドカード)の親は、行の**いまの**親から引く。行の親は台帳が付け替える(外側の行を作り直した・\n * 外側の行が内側の配列を手放した — list/listIndexesByList.ts の #256 / #394)。憶えた親を使い続けると、付け替えの後の\n * 読み書きが、もうその配列を持たない外側の行を経由して別の配列に着地した(#393 / #394)。ただし、いまの親がこのアドレスの\n * キーではこの行の配列を持たず、憶えた親が持つなら、憶えた親を使う — 同じ配列を外側の行ごとに別のキー(`items` と `alt`)に\n * 持つと、行の親はどちらか一方のキーにしか合わない(R1・f6 dual)\n */\n get parentAddress(): IStateAddress | null {\n const cached = this._parentAddress;\n if (typeof cached !== 'undefined' && (!this._rowAddress || cached.listIndex === this.listIndex!.parentListIndex)) {\n return cached;\n }\n const parentPathInfo = this.pathInfo.parentPathInfo;\n if (parentPathInfo === null) {\n return null;\n }\n const lastSegment = this.pathInfo.segments[this.pathInfo.segments.length - 1];\n let parentListIndex: IListIndex | null = null;\n if (lastSegment === WILDCARD) {\n parentListIndex = this.listIndex?.parentListIndex ?? null;\n } else {\n parentListIndex = this.listIndex;\n }\n const next = createStateAddress(parentPathInfo, parentListIndex);\n if (typeof cached !== 'undefined' && !holdsRow(next, this.listIndex!) && holdsRow(cached, this.listIndex!)) {\n return cached;\n }\n return this._parentAddress = next;\n }\n}\n\n/** 外側の行のアドレス `address`(`groups.*.items`)の配列が、行 `row` をその位置に持つか(要素のオブジェクトを素で読む) */\nfunction holdsRow(address: IStateAddress, row: IListIndex): boolean {\n const pathInfo = address.pathInfo;\n let value = getListIndexValue(address.listIndex!);\n for (const segment of pathInfo.segments.slice(pathInfo.wildcardPositions[pathInfo.wildcardCount - 1] + 1)) {\n value = Object(value)[segment];\n }\n return getListIndexesByList(value as unknown[])?.[row.index] === row;\n}\n\nexport function createStateAddress(pathInfo: IPathInfo, listIndex: IListIndex | null): IStateAddress {\n if (listIndex === null) {\n let cached = _cacheNullListIndex.get(pathInfo);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n cached = new StateAddress(pathInfo, null);\n _cacheNullListIndex.set(pathInfo, cached);\n return cached;\n } else {\n let cacheByPathInfo = _cache.get(listIndex);\n if (typeof cacheByPathInfo === \"undefined\") {\n cacheByPathInfo = new WeakMap<IPathInfo, IStateAddress>();\n _cache.set(listIndex, cacheByPathInfo);\n }\n let cached = cacheByPathInfo.get(pathInfo);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n cached = new StateAddress(pathInfo, listIndex);\n cacheByPathInfo.set(pathInfo, cached);\n return cached;\n }\n}","import { createStateAddress } from \"../address/StateAddress\";\nimport { IStateAddress } from \"../address/types\";\nimport { getListIndexByBindingInfo } from \"../list/getListIndexByBindingInfo\";\nimport { raiseError } from \"../raiseError\";\nimport { IBindingInfo } from \"../types\";\n\nconst stateAddressByBindingInfo: WeakMap<IBindingInfo, IStateAddress> = new WeakMap();\n\nexport function getStateAddressByBindingInfo(bindingInfo: IBindingInfo) {\n let stateAddress: IStateAddress | null = null;\n stateAddress = stateAddressByBindingInfo.get(bindingInfo) || null;\n if (stateAddress !== null) {\n return stateAddress;\n }\n if (bindingInfo.statePathInfo.wildcardCount > 0) {\n const listIndex = getListIndexByBindingInfo(bindingInfo);\n if (listIndex === null) {\n raiseError(`Cannot resolve state address for binding with wildcard statePathName \"${bindingInfo.statePathName}\" because list index is null.`);\n }\n stateAddress = createStateAddress(bindingInfo.statePathInfo, listIndex);\n } else {\n stateAddress = createStateAddress(bindingInfo.statePathInfo, null);\n }\n stateAddressByBindingInfo.set(bindingInfo, stateAddress);\n return stateAddress;\n}\n\n// call for change loopContext\nexport function clearStateAddressByBindingInfo(bindingInfo: IBindingInfo) {\n stateAddressByBindingInfo.delete(bindingInfo);\n}","import { IBindingInfo } from \"../types\";\n\n/**\n * イベントハンドラ登録の台帳。\n *\n * 旧実装は Map<string, Set<IBindingInfo>>(文字列キーの強参照 Map)で binding を\n * 保持していたため、binding.node → 行 DOM サブツリー全体が解放不能だった\n * (detach 系はほぼ呼ばれないため、リスト削除後も全イベントバインディングが\n * 永久保持されるリーク。clear-10k 後に 10k 行分の detached DOM が残留していた)。\n *\n * WeakSet(帰属判定・冪等性)と件数カウンタ(「最後の 1 件が外れたらハンドラを\n * 掃除する」判定)に分離し、binding を強参照しない。GC で binding が消えた場合\n * カウンタは減らないが、残るのはキー文字列と数値のみで実害はない。\n */\nexport interface IHandlerBindingRegistry {\n /** binding を key に登録する。新規登録なら true を返す(既登録は冪等に false) */\n add(key: string, binding: IBindingInfo): boolean;\n /** binding を key から外す。key の登録件数が 0 になったら true を返す */\n remove(key: string, binding: IBindingInfo): boolean;\n has(key: string, binding: IBindingInfo): boolean;\n countOf(key: string): number;\n readonly keyCount: number;\n clear(): void;\n}\n\nexport function createHandlerBindingRegistry(): IHandlerBindingRegistry {\n const attachedByKey = new Map<string, WeakSet<IBindingInfo>>();\n const countByKey = new Map<string, number>();\n return {\n add(key: string, binding: IBindingInfo): boolean {\n let attached = attachedByKey.get(key);\n if (typeof attached === \"undefined\") {\n attached = new WeakSet<IBindingInfo>();\n attachedByKey.set(key, attached);\n }\n if (attached.has(binding)) {\n return false;\n }\n attached.add(binding);\n countByKey.set(key, (countByKey.get(key) ?? 0) + 1);\n return true;\n },\n remove(key: string, binding: IBindingInfo): boolean {\n const attached = attachedByKey.get(key);\n if (typeof attached === \"undefined\" || !attached.has(binding)) {\n return false;\n }\n attached.delete(binding);\n const next = (countByKey.get(key) ?? 1) - 1;\n if (next <= 0) {\n attachedByKey.delete(key);\n countByKey.delete(key);\n return true;\n }\n countByKey.set(key, next);\n return false;\n },\n has(key: string, binding: IBindingInfo): boolean {\n return attachedByKey.get(key)?.has(binding) ?? false;\n },\n countOf(key: string): number {\n return countByKey.get(key) ?? 0;\n },\n get keyCount(): number {\n return countByKey.size;\n },\n clear(): void {\n attachedByKey.clear();\n countByKey.clear();\n },\n };\n}\n","import { EVENT_PROP_PREFIX, MODIFIER_READONLY } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo, IFilterInfo } from \"../types\";\nimport { setLoopContextSymbol } from \"../proxy/symbols\";\nimport { filterListKey } from \"../binding/filterKey\";\nimport { createHandlerBindingRegistry } from \"./handlerBindingRegistry\";\n\nconst handlerByHandlerKey: Map<string, (event: Event) => any> = new Map();\n// binding を強参照しない台帳(handlerBindingRegistry.ts のリーク解説を参照)\nconst bindingRegistry = /*#__PURE__*/ createHandlerBindingRegistry();\n\nfunction getHandlerKey(binding: IBindingInfo, eventName: string): string {\n const filterKey = filterListKey(binding.inFilters);\n return `${binding.statePathName}::${eventName}::${filterKey}`;\n}\n\nfunction getEventName(binding: IBindingInfo): string {\n let eventName = 'input';\n for(const modifier of binding.propModifiers) {\n if (modifier.startsWith(EVENT_PROP_PREFIX)) {\n eventName = modifier.slice(EVENT_PROP_PREFIX.length);\n }\n }\n return eventName;\n}\n\nconst checkboxEventHandlerFunction = (\n statePathName: string,\n inFilters: IFilterInfo[],\n) => (event: Event): any => {\n const node = event.target as HTMLInputElement;\n if (node === null) {\n console.warn(`[@wcstack/state] event.target is null.`);\n return;\n }\n if (node.type !== 'checkbox') {\n console.warn(`[@wcstack/state] event.target is not a checkbox input element.`);\n return;\n }\n const checked = node.checked;\n const newValue = node.value;\n let filteredNewValue: unknown = newValue;\n for(const filter of inFilters) {\n filteredNewValue = filter.filterFn(filteredNewValue);\n }\n\n const rootNode = node.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for two-way binding.`);\n }\n\n const loopContext = getLoopContextByNode(node);\n stateElement.createState(\"writable\", (state) => {\n state[setLoopContextSymbol](loopContext, () => {\n let currentValue = state[statePathName];\n if (Array.isArray(currentValue)) {\n if (checked) {\n if (currentValue.indexOf(filteredNewValue) === -1) {\n state[statePathName] = currentValue.concat(filteredNewValue);\n }\n } else {\n const index = currentValue.indexOf(filteredNewValue);\n if (index !== -1) {\n state[statePathName] = currentValue.toSpliced(index, 1);\n }\n }\n } else {\n if (checked) {\n state[statePathName] = [filteredNewValue];\n } else {\n state[statePathName] = [];\n }\n }\n });\n });\n}\n\nexport function attachCheckboxEventHandler(binding: IBindingInfo): boolean {\n if (binding.bindingType === \"checkbox\" && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const key = getHandlerKey(binding, eventName);\n let checkboxEventHandler = handlerByHandlerKey.get(key);\n if (typeof checkboxEventHandler === \"undefined\") {\n checkboxEventHandler = checkboxEventHandlerFunction(\n binding.statePathName,\n binding.inFilters\n );\n handlerByHandlerKey.set(key, checkboxEventHandler);\n }\n (binding.node as Element).addEventListener(eventName, checkboxEventHandler);\n bindingRegistry.add(key, binding);\n return true;\n }\n return false;\n}\n\nexport function detachCheckboxEventHandler(binding: IBindingInfo): boolean {\n if (binding.bindingType === \"checkbox\" && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const key = getHandlerKey(binding, eventName);\n const checkboxEventHandler = handlerByHandlerKey.get(key);\n if (typeof checkboxEventHandler === \"undefined\") {\n return false;\n }\n (binding.node as Element).removeEventListener(eventName, checkboxEventHandler);\n\n if (bindingRegistry.countOf(key) === 0) {\n return false;\n }\n if (bindingRegistry.remove(key, binding)) {\n handlerByHandlerKey.delete(key);\n }\n return true;\n }\n return false;\n}\n\nexport const __private__ = {\n handlerByHandlerKey,\n bindingRegistry,\n getHandlerKey,\n getEventName,\n checkboxEventHandlerFunction,\n};\n","/**\n * captureHandlerRejection.ts\n *\n * state 側ハンドラ(`$on` の event-token subscriber、`onXxx:` の state メソッド、\n * DOM イベント起点の command-token emit)の戻り値を受け取り、Promise が混ざって\n * いれば reject を捕捉して報告する。\n *\n * なぜ必要か:\n * 発火経路はハンドラの完了を待たない。戻り値は `Token.emit` の結果配列にしか現れず、\n * 呼び出し側(eventTokenHandler / handler)はそれを捨てている。そのため **async\n * ハンドラが reject すると unhandled rejection になり**、しかも「どのハンドラで\n * 落ちたか」の手掛かりがスタックにしか残らない(特性化:\n * `__tests__/poc.asyncOnLoopContext.test.ts`)。\n *\n * 握り潰しではない:\n * 可視性は `console.error` で保たれ、state 名・ハンドラ名が付く分むしろ特定は容易に\n * なる。非同期の失敗を「例外の伝播」ではなく「診断可能な報告」に落とすのは\n * never-throw(async-io-node-guidelines.md §3.6)と同じ方針であり、I/O ノードが\n * `error` プロパティへ流すのと同じ位置づけの、state 側ハンドラ版にあたる。\n *\n * **同期 throw の扱いは発火経路で違う。** 同期に呼ぶ経路(twoway / radio / checkbox の\n * `createState`、state 側からの `Token.emit`)では従来どおり呼び出し元へ伝播する。\n * DOM イベント起点(`event/handler.ts`)は `createStateAsync` を使うので、ハンドラの同期 throw も\n * `async` 関数の中で reject に変わり、**呼び出し元(DOM のイベント配送)には届かない** —\n * 捨てると unhandled rejection になるだけなので、`reportHandlerError` で報告へ落とす。\n * プログラマエラーを loud に落とす `raiseError` の意図(見えること)はそれで保たれる。\n */\n\nfunction isThenable(value: unknown): value is PromiseLike<unknown> {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\n/**\n * @param result ハンドラ呼び出しの戻り値。`Token.emit` の結果配列(subscriber ごとの\n * 戻り値)と、単一ハンドラの戻り値の両方を受ける。\n * @param describe 報告に載せるハンドラの識別名(例: `$on.\"rowFailed\" of state \"default\"`)。\n */\n/**\n * ハンドラの失敗を報告する(発火経路が呼び出し元へ投げ返せないとき)。\n * 文言は `captureHandlerRejection` と同じ形にして、報告の出どころを 1 つに保つ。\n */\nexport function reportHandlerError(error: unknown, describe: string): void {\n console.error(`[wcstack/state] ${describe} rejected.`, error);\n}\n\nexport function captureHandlerRejection(result: unknown, describe: string): void {\n // emit は subscriber ごとの戻り値配列。単一ハンドラの戻り値はそのまま届く。\n const values = Array.isArray(result) ? result : [result];\n for (const value of values) {\n if (!isThenable(value)) {\n continue;\n }\n // Promise.resolve は native Promise をそのまま返すため、catch の登録によって\n // 元の Promise が handled になる(thenable は同値の Promise に包まれる)。\n Promise.resolve(value).catch((error: unknown) => reportHandlerError(error, describe));\n }\n}\n","// command-token / event-token が共有する pub/sub プリミティブ。\n// _subscribers は Set のため挿入順を保持する。\n// emit() は subscribe() された順に呼び出され、戻り値配列も同じ順序で返る。\n//\n// 「誰が subscribe し誰が emit するか」だけが command / event の違い:\n// - command-token: element が subscribe / state が emit\n// - event-token: state(`$on`) が subscribe / element(listener) が emit\n\nexport type TokenSubscriber = (...args: unknown[]) => unknown;\n\nexport interface IToken {\n readonly name: string;\n readonly size: number;\n subscribe(fn: TokenSubscriber): () => void;\n unsubscribe(fn: TokenSubscriber): boolean;\n emit(...args: unknown[]): unknown[];\n}\n\nexport class Token implements IToken {\n private _name: string;\n private _subscribers: Set<TokenSubscriber> = new Set();\n\n constructor(name: string) {\n this._name = name;\n }\n\n get name(): string {\n return this._name;\n }\n\n get size(): number {\n return this._subscribers.size;\n }\n\n subscribe(fn: TokenSubscriber): () => void {\n this._subscribers.add(fn);\n return () => {\n this._subscribers.delete(fn);\n };\n }\n\n unsubscribe(fn: TokenSubscriber): boolean {\n return this._subscribers.delete(fn);\n }\n\n /**\n * 全 subscriber へ配る。**1 つが throw しても残りへ配り続ける** — トークンはファンアウトの\n * 口で、購読者どうしは互いを知らない(README の「click fans the command out to every\n * subscriber」の例は、片方の要素が投げたらもう片方に届かない形では成り立たない)。\n * 投げた分は握り潰さず `console.error` に載せ、結果配列にはその位置を `undefined` で残す。\n *\n * 握り潰しでないことの根拠は `event/captureHandlerRejection.ts` と同じ: 発火経路は\n * ハンドラの完了を待たず、DOM イベント起点では例外を呼び出し元へ投げ返せない。\n * 「例外の伝播」ではなく「診断可能な報告」に落とすのが state 側ハンドラの方針。\n */\n emit(...args: unknown[]): unknown[] {\n const results: unknown[] = [];\n for (const fn of this._subscribers) {\n try {\n results.push(fn(...args));\n } catch (error) {\n results.push(undefined);\n console.error(`[wcstack/state] a subscriber of token \"${this.name}\" threw; the remaining subscribers still received it.`, error);\n }\n }\n return results;\n }\n}\n","import type { IStateElement } from \"../components/types\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { Token } from \"../token/Token\";\n\n// EventToken は共有 pub/sub プリミティブ Token の薄い特化(element→state 方向)。\n// instanceof による型判別を成立させるため独立クラスとして維持する。\nexport class EventToken extends Token {\n /**\n * 属する state 要素(devtools のツリー識別 — protocol v2 追補)。\n * registry(getOrCreateEventToken)経由の生成でのみ渡る optional 参照。\n * 寿命は registry 側の WeakMap が管理する(CommandToken と同じ位置づけ)。\n */\n private _stateElement: IStateElement | undefined;\n\n constructor(name: string, stateElement?: IStateElement) {\n super(name);\n this._stateElement = stateElement;\n }\n\n emit(...args: unknown[]): unknown[] {\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"state:token-emit\",\n kind: \"event\",\n tokenName: this.name,\n args,\n subscriberCount: this.size,\n stateElement: this._stateElement,\n });\n }\n return super.emit(...args);\n }\n}\n\nexport function isEventToken(value: unknown): value is EventToken {\n return value instanceof EventToken;\n}\n","import { IStateElement } from \"../components/types\";\nimport { EventToken } from \"./EventToken\";\n\nconst registryByStateElement: WeakMap<IStateElement, Map<string, EventToken>> = new WeakMap();\n\nexport function getOrCreateEventToken(stateElement: IStateElement, name: string): EventToken {\n let registry = registryByStateElement.get(stateElement);\n if (typeof registry === \"undefined\") {\n registry = new Map<string, EventToken>();\n registryByStateElement.set(stateElement, registry);\n }\n let token = registry.get(name);\n if (typeof token === \"undefined\") {\n // stateElement を渡すのは devtools のツリー識別(protocol v2 追補)のため\n token = new EventToken(name, stateElement);\n registry.set(name, token);\n }\n return token;\n}\n\nexport function clearEventTokenRegistry(stateElement: IStateElement): void {\n registryByStateElement.delete(stateElement);\n}\n\nexport const __private__ = {\n registryByStateElement,\n};\n","/**\n * eventToken.<propertyName>: <eventTokenName> バインディングの attach ハンドラ。\n *\n * command-token の双対(element→state)。要素が dispatch する CustomEvent を受けて\n * event-token を emit し、state 側の `$on` ハンドラ群へ pub/sub で配送する。\n *\n * 設計(MVP スコープ: wc-bindable カスタム要素のみ):\n * - キーは生イベント名ではなく **wcBindable property 名**。実 DOM イベント名は\n * wcBindable.properties[].event から解決する(command-token が wcBindable.commands で\n * 検証するのと対称。コロンを含む namespaced event 名と binding 構文の `:` 衝突も回避)。\n * - <prop> が wcBindable.properties に宣言されていることは attach 時に検証する\n * (要素クラス参照のみで DOM 接続に非依存。fail-fast / typo 耐性)。\n * - <eventTokenName> が $eventTokens に宣言されていることは **発火時** に検証する\n * (state 解決が必要なため。詳細は下記の fire-time 解決の注記を参照)。\n * - subscriber 引数規約は `(state, event, ...listIndexes)`。\n * - modifier `#prevent` / `#stop` は既存イベント binding と同等にサポート。\n *\n * token はイベント発火ごとに registry から解決する(getOrCreateEventToken)。これにより\n * state の再 set で registry が作り直されても最新の subscriber 群へ配送できる。\n *\n * state element の解決と `$eventTokens` 検証は **発火時** に行う(attach 時ではない)。\n * 構造ブロック(for/if)や SSR hydration では、binding 初期化時にノードが detached な\n * DocumentFragment / wrapper 上にあり、その時点では element.getRootNode() から state を\n * 解決できないため。onclick / two-way ハンドラと同じく fire-time 解決に揃えている。\n */\n\nimport { EVENT_TOKEN_NAMESPACE, MODIFIER_PREVENT, MODIFIER_STOP } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { setLoopContextSymbol } from \"../proxy/symbols\";\nimport { getScopedIndexes } from \"../list/wildcardLevel\";\nimport { didYouMean, LINT_HINT } from \"../errorGuidance\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration, ReadBindableResult } from \"../protocol/wcBindableReader\";\nimport { IBindingInfo } from \"../types\";\nimport { captureHandlerRejection } from \"./captureHandlerRejection\";\nimport { getOrCreateEventToken } from \"./eventTokenRegistry\";\n\ninterface IEventTokenListener {\n readonly eventName: string;\n readonly handler: (event: Event) => void;\n}\n\nconst listenerByBinding: WeakMap<IBindingInfo, IEventTokenListener> = new WeakMap();\n\nfunction getWcBindable(element: Element): ReadBindableResult | null {\n const customTagName = getCustomElement(element);\n if (customTagName === null) {\n return null;\n }\n // attach 側で未定義要素は whenDefined 後に再試行するため、ここに来る時点で customClass は定義済み。\n return readBindableDeclaration(element);\n}\n\nexport function attachEventTokenHandler(binding: IBindingInfo): boolean {\n if (binding.propSegments[0] !== EVENT_TOKEN_NAMESPACE) {\n return false;\n }\n const element = binding.node as Element;\n\n // カスタム要素が未定義なら定義後に再試行(wcBindable が必要なため)。\n const customTagName = getCustomElement(element);\n const registry = getCustomElementRegistry(element);\n if (customTagName !== null && registry?.get(customTagName) === undefined) {\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${customTagName}>.`);\n }\n return true;\n }\n\n // 再評価で二重 attach しない。\n if (listenerByBinding.has(binding)) {\n return true;\n }\n\n const propertyName = binding.propSegments[1];\n if (typeof propertyName !== \"string\" || propertyName.length === 0) {\n raiseError(`eventToken binding requires a property name (e.g., \"eventToken.error\").`);\n }\n\n const bindable = getWcBindable(element);\n if (bindable === null) {\n raiseError(`eventToken binding requires a wc-bindable custom element. <${element.tagName.toLowerCase()}> is not wc-bindable.`);\n }\n const propDesc = bindable.knownProperties.get(propertyName);\n if (typeof propDesc === \"undefined\") {\n raiseError(`Property \"${propertyName}\" is not declared in wcBindable.properties of <${element.tagName.toLowerCase()}>.${didYouMean(propertyName, bindable.knownProperties.keys())}`);\n }\n const eventName = propDesc.event;\n\n const tokenName = binding.statePathName;\n const modifiers = binding.propModifiers;\n const handler = (event: Event): void => {\n if (modifiers.includes(MODIFIER_PREVENT)) event.preventDefault();\n if (modifiers.includes(MODIFIER_STOP)) event.stopPropagation();\n\n // state は発火時の live root から解決する(attach 時は detached の可能性があるため)。\n const rootNode = element.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for eventToken handler.`);\n }\n if (!stateElement.eventTokenNames.has(tokenName)) {\n // lint も同じケースを wcs/token-undeclared で検出する(三面同語彙)。\n raiseError(`[wcs/token-undeclared] eventToken \"${tokenName}\" is not declared in $eventTokens.${didYouMean(tokenName, stateElement.eventTokenNames)}${LINT_HINT}`);\n }\n const loopContext = getLoopContextByNode(element);\n stateElement.createStateAsync(\"writable\", async (state) => {\n const results = state[setLoopContextSymbol](loopContext, () => {\n const indexes = loopContext !== null\n ? getScopedIndexes(loopContext.listIndex, loopContext.pathInfo.wildcardCount) : [];\n const token = getOrCreateEventToken(stateElement, tokenName);\n return token.emit(state, event, ...indexes);\n });\n // この経路はハンドラの完了を待たない(emit の戻り値はここでしか見えない)。\n // async な $on ハンドラの reject を unhandled にせず報告へ落とす。\n captureHandlerRejection(results, `$on.\"${tokenName}\"`);\n });\n };\n\n element.addEventListener(eventName, handler);\n listenerByBinding.set(binding, { eventName, handler });\n return true;\n}\n\nexport function detachEventTokenHandler(binding: IBindingInfo): boolean {\n if (binding.propSegments[0] !== EVENT_TOKEN_NAMESPACE) {\n return false;\n }\n const listener = listenerByBinding.get(binding);\n if (typeof listener === \"undefined\") {\n return false;\n }\n (binding.node as Element).removeEventListener(listener.eventName, listener.handler);\n listenerByBinding.delete(binding);\n return true;\n}\n\nexport const __private__ = {\n listenerByBinding,\n};\n","import type { IStateElement } from \"../components/types\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { Token } from \"../token/Token\";\nimport { ICommandToken } from \"./types\";\n\n// CommandToken は共有 pub/sub プリミティブ Token の薄い特化。\n// instanceof による型判別を成立させるため独立クラスとして維持する。\n//\nexport class CommandToken extends Token implements ICommandToken {\n /**\n * 属する state 要素(devtools のツリー識別 — protocol v2 追補)。\n * registry(getOrCreateCommandToken)経由の生成でのみ渡る optional 参照で、\n * token の寿命は registry 側の WeakMap が state 要素に紐づけている(ここが\n * 寿命を延ばす新しい経路にはならない)。emit の payload にだけ載せる。\n */\n private _stateElement: IStateElement | undefined;\n\n constructor(name: string, stateElement?: IStateElement) {\n super(name);\n this._stateElement = stateElement;\n }\n\n emit(...args: unknown[]): unknown[] {\n if (devtoolsSink !== null) {\n // subscriberCount 0 の emit(空撃ち)もそのまま流す — whenDefined 前の\n // command 空撃ちレース類をタイムラインで可視化するため\n devtoolsSink({\n type: \"state:token-emit\",\n kind: \"command\",\n tokenName: this.name,\n args,\n subscriberCount: this.size,\n stateElement: this._stateElement,\n });\n }\n return super.emit(...args);\n }\n}\n\nexport function isCommandToken(value: unknown): value is ICommandToken {\n return value instanceof CommandToken;\n}\n","import { createStateAddress } from \"../address/StateAddress\";\nimport { IPathInfo } from \"../address/types\";\nimport { isCommandToken } from \"../command/CommandToken\";\nimport { ICommandToken } from \"../command/types\";\nimport { EVENT_PROP_PREFIX, MODIFIER_PREVENT, MODIFIER_STOP, STATE_COMMAND_NAMESPACE_NAME } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { getByAddressSymbol, setLoopContextSymbol } from \"../proxy/symbols\";\nimport { getScopedIndexes } from \"../list/wildcardLevel\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo } from \"../types\";\nimport { captureHandlerRejection, reportHandlerError } from \"./captureHandlerRejection\";\nimport { createHandlerBindingRegistry } from \"./handlerBindingRegistry\";\n\n// onclick: $command.<name> のように、DOM イベントから command token を直接 emit する形式かを判定する。\n// 右辺が $command 名前空間配下のパス($command.<token>)のときに true。\nfunction isCommandTokenPath(statePathName: string): boolean {\n return statePathName.startsWith(STATE_COMMAND_NAMESPACE_NAME + \".\");\n}\n\nconst handlerByHandlerKey: Map<string, (event: Event) => any> = new Map();\n// binding を強参照しない台帳(handlerBindingRegistry.ts のリーク解説を参照)\n// 純粋な割り当て(Map 2 個)。バンドラが未使用時に落とせるよう明示する(ヘルパーだけの import に残さない)\nconst bindingRegistry = /*#__PURE__*/ createHandlerBindingRegistry();\n\nfunction getHandlerKey(binding: IBindingInfo): string {\n const modifierKey = binding.propModifiers.filter(m => m === MODIFIER_PREVENT || m === MODIFIER_STOP).sort().join(',');\n return `${binding.statePathName}::${modifierKey}`;\n}\n\nconst stateEventHandlerFunction = (\n handlerName: string,\n modifiers: string[],\n statePathInfo: IPathInfo\n) => (event: Event): any => {\n if (modifiers.includes(MODIFIER_PREVENT)) event.preventDefault();\n if (modifiers.includes(MODIFIER_STOP)) event.stopPropagation();\n\n const node = event.target as Element;\n const rootNode = node.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for event handler.`);\n }\n\n const loopContext = getLoopContextByNode(node);\n const isCommand = isCommandTokenPath(handlerName);\n // `createStateAsync` の戻り Promise を捨てると、ハンドラの**同期 throw**(未宣言の\n // command token・state に無いハンドラ名・作者のメソッドが投げた例外)が `async` 関数の中で\n // reject に変わり、そのまま unhandled rejection に沈む。DOM のイベント配送には投げ返せない\n // 経路なので、少なくとも報告へ落とす(captureHandlerRejection.ts の方針と同じ)\n stateElement.createStateAsync(\"writable\", async (state) => {\n const results = state[setLoopContextSymbol](loopContext, () => {\n // マウントされたスコープ(v2): 作者のハンドラが受ける添字は自スコープの\n // ループ分だけ(§4-4 / P2-9)。翻訳で増えたワイルドカード数を落とす。\n // 翻訳された for の台帳に無いループ文脈は外側スコープのもの(境界ホップで\n // 借りた行)なので、作者から見える添字は 0 本。\n // 記録の解決はノードから(findMountRecordForNode)— Shadow 形は rootNode\n // (shadowRoot)で直に引け、Light DOM 形はスコープ根がコンポーネント要素\n // 自身なので祖先走査が要る(rootNode だけ見ると Light DOM で外側の添字が漏れる)\n let scopedWildcardCount = loopContext !== null ? loopContext.pathInfo.wildcardCount : 0;\n if (loopContext !== null) {\n // 添字の段数はスコープ機能の handlerScope hook(webComponent/addressHooks.ts)が決める。\n // hook の無い state は判定 1 個で抜ける\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const scopes = hooks.handlerScope;\n for (let i = 0; i < scopes.length; i++) {\n scopedWildcardCount = scopes[i](stateElement, node, rootNode, loopContext, scopedWildcardCount);\n }\n }\n }\n const indexes = loopContext !== null\n ? getScopedIndexes(loopContext.listIndex, scopedWildcardCount) : [];\n if (isCommand) {\n // command token を解決して emit。引数はハンドラ呼び出しと同じく (event, ...listIndexes) を透過する。\n const token = state[getByAddressSymbol](createStateAddress(statePathInfo, null));\n if (!isCommandToken(token)) {\n raiseError(`Event binding \"${handlerName}\" did not resolve to a CommandToken. Declare the name in $commandTokens and reference it as $command.<name>.`);\n }\n return (token as ICommandToken).emit(event, ...indexes);\n }\n const handler = state[handlerName];\n if (typeof handler !== \"function\") {\n raiseError(`Handler \"${handlerName}\" is not a function on the state tree.`);\n }\n return Reflect.apply(handler, state, [event, ...indexes]);\n });\n // eventTokenHandler と同じく、この経路もハンドラの完了を待たない。async な\n // state メソッド / command subscriber の reject を unhandled にせず報告へ落とす。\n captureHandlerRejection(results, `\"${handlerName}\"`);\n }).catch((error: unknown) => reportHandlerError(error, `\"${handlerName}\"`));\n}\n\n/**\n * DOM イベントリスナを張る束縛かを判定する(要件 B5 / D34)。\n *\n * 名前の綴り(`on` で始まるか)だけでは足りない: 明示のプロパティ形 `.online:` は\n * `propName` が `\"online\"` でも **プロパティ束縛**(`bindingType: 'prop'`)であって\n * `\"line\"` イベントの購読ではない。`spread` で配線される `once`(`<wcs-timer>` /\n * `<wcs-raf>` …)も同じ形。種別で判定することで、`for` 行の内(`structural/rowPlan.ts`\n * の `isEvent`)と外で同じ束縛が同じ意味になる。\n *\n * `eventToken.<prop>:` も `bindingType: 'event'` だが DOM イベントではない(pub/sub 配線)\n * ので、`on` 接頭辞の検査も併せて残す。\n */\nfunction isDomEventBinding(binding: IBindingInfo): boolean {\n return binding.bindingType === 'event' && binding.propName.startsWith(EVENT_PROP_PREFIX);\n}\n\nexport function attachEventHandler(binding: IBindingInfo): boolean {\n if (!isDomEventBinding(binding)) {\n return false;\n }\n const key = getHandlerKey(binding);\n let stateEventHandler = handlerByHandlerKey.get(key);\n if (typeof stateEventHandler === \"undefined\") {\n stateEventHandler = stateEventHandlerFunction(binding.statePathName, binding.propModifiers, binding.statePathInfo);\n handlerByHandlerKey.set(key, stateEventHandler);\n }\n\n const eventName = binding.propName.slice(2);\n (binding.node as Element).addEventListener(eventName, stateEventHandler);\n\n bindingRegistry.add(key, binding);\n return true;\n}\n\nexport function detachEventHandler(binding: IBindingInfo): boolean {\n if (!isDomEventBinding(binding)) {\n return false;\n }\n const key = getHandlerKey(binding);\n const stateEventHandler = handlerByHandlerKey.get(key);\n if (typeof stateEventHandler === \"undefined\") {\n return false;\n }\n const eventName = binding.propName.slice(2);\n (binding.node as Element).removeEventListener(eventName, stateEventHandler);\n\n if (bindingRegistry.countOf(key) === 0) {\n return false;\n }\n if (bindingRegistry.remove(key, binding)) {\n handlerByHandlerKey.delete(key);\n }\n return true;\n}\n\nexport const __private__ = {\n handlerByHandlerKey,\n bindingRegistry,\n getHandlerKey,\n};\n\n","import { EVENT_PROP_PREFIX, MODIFIER_READONLY } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo, IFilterInfo } from \"../types\";\nimport { setLoopContextSymbol } from \"../proxy/symbols\";\nimport { filterListKey } from \"../binding/filterKey\";\nimport { createHandlerBindingRegistry } from \"./handlerBindingRegistry\";\n\nconst handlerByHandlerKey: Map<string, (event: Event) => any> = new Map();\n// binding を強参照しない台帳(handlerBindingRegistry.ts のリーク解説を参照)\nconst bindingRegistry = /*#__PURE__*/ createHandlerBindingRegistry();\n\nfunction getHandlerKey(binding: IBindingInfo, eventName: string): string {\n const filterKey = filterListKey(binding.inFilters);\n return `${binding.statePathName}::${eventName}::${filterKey}`;\n}\n\nfunction getEventName(binding: IBindingInfo): string {\n let eventName = 'input';\n for(const modifier of binding.propModifiers) {\n if (modifier.startsWith(EVENT_PROP_PREFIX)) {\n eventName = modifier.slice(EVENT_PROP_PREFIX.length);\n }\n }\n return eventName;\n}\n\nconst radioEventHandlerFunction = (\n statePathName: string,\n inFilters: IFilterInfo[],\n) => (event: Event): any => {\n const node = event.target as HTMLInputElement;\n if (node === null) {\n console.warn(`[@wcstack/state] event.target is null.`);\n return;\n }\n if (node.type !== 'radio') {\n console.warn(`[@wcstack/state] event.target is not a radio input element.`);\n return;\n }\n if (node.checked === false) {\n return;\n }\n const newValue = node.value;\n let filteredNewValue: unknown = newValue;\n for(const filter of inFilters) {\n filteredNewValue = filter.filterFn(filteredNewValue);\n }\n\n const rootNode = node.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for two-way binding.`);\n }\n\n const loopContext = getLoopContextByNode(node);\n stateElement.createState(\"writable\", (state) => {\n state[setLoopContextSymbol](loopContext, () => {\n state[statePathName] = filteredNewValue;\n });\n });\n}\n\nexport function attachRadioEventHandler(binding: IBindingInfo): boolean {\n if (binding.bindingType === \"radio\" && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const key = getHandlerKey(binding, eventName);\n let radioEventHandler = handlerByHandlerKey.get(key);\n if (typeof radioEventHandler === \"undefined\") {\n radioEventHandler = radioEventHandlerFunction(\n binding.statePathName,\n binding.inFilters\n );\n handlerByHandlerKey.set(key, radioEventHandler);\n }\n (binding.node as Element).addEventListener(eventName, radioEventHandler);\n bindingRegistry.add(key, binding);\n return true;\n }\n return false;\n}\n\nexport function detachRadioEventHandler(binding: IBindingInfo): boolean {\n if (binding.bindingType === \"radio\" && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const key = getHandlerKey(binding, eventName);\n const radioEventHandler = handlerByHandlerKey.get(key);\n if (typeof radioEventHandler === \"undefined\") {\n return false;\n }\n (binding.node as Element).removeEventListener(eventName, radioEventHandler);\n\n if (bindingRegistry.countOf(key) === 0) {\n return false;\n }\n if (bindingRegistry.remove(key, binding)) {\n handlerByHandlerKey.delete(key);\n }\n return true;\n }\n return false;\n}\n\nexport const __private__ = {\n handlerByHandlerKey,\n bindingRegistry,\n getHandlerKey,\n getEventName,\n radioEventHandlerFunction,\n};\n","import { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\nimport { raiseError } from \"../raiseError\";\n\nconst CHECK_TYPES = new Set([ 'radio', 'checkbox' ]);\nconst DEFAULT_VALUE_PROP_NAMES = new Set([ 'value', 'valueAsNumber', 'valueAsDate' ]);\n\nexport function isPossibleTwoWay(node: Node, propName: string): boolean {\n if (node.nodeType !== Node.ELEMENT_NODE) {\n return false;\n }\n const element = node as Element;\n const tagName = element.tagName.toLowerCase();\n if (tagName === 'input') {\n const inputType = (element.getAttribute('type') || 'text').toLowerCase();\n if (inputType === 'button') {\n return false;\n }\n if (CHECK_TYPES.has(inputType) && propName === 'checked') {\n return true;\n }\n if (DEFAULT_VALUE_PROP_NAMES.has(propName)) {\n return true;\n }\n }\n if (tagName === 'select' && propName === 'value') {\n return true;\n }\n if (tagName === 'textarea' && propName === 'value') {\n return true;\n }\n const customTagName = getCustomElement(element);\n if (customTagName !== null) {\n const customClass = getCustomElementRegistry(element)?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n raiseError(`Custom element <${customTagName}> is not defined. Cannot determine if property \"${propName}\" is suitable for two-way binding.`);\n }\n const bindable = readBindableDeclaration(element);\n if (bindable?.knownProperties.has(propName)) {\n return true;\n }\n }\n return false;\n}\n","/**\n * propagation/propagation.ts\n *\n * Phase 3 の因果伝播コア(feature flag `enablePropagationContext` 下)。\n * 依存は types のみの葉モジュールとし、twowayHandler / applyChangeToProperty /\n * setByAddress / updater の計装点から循環 import なしで参照できるようにする。\n *\n * wire 識別は (node × member × statePathName) で行う。設計書の\n * WriteReceipt は bindingId + generation を持つが、twoway handler は共有\n * handler(handlerByHandlerKey)で binding インスタンスに到達できないため、\n * runtime の edge / receipt 照合キーは wire 単位とする。BindingSession\n * generation との統合(再 attach 後の edge ID 非再利用)は session 側の\n * 計装が揃う段階で bindingGeneration に反映する。\n */\n\nimport { IPropagationContext, IWriteReceipt } from \"./types\";\n\nexport type PropagationEdgeDirection = \"to-element\" | \"to-state\";\n\nlet nextWireId = 1;\nlet nextTransactionId = 1;\nlet nextSynchronousScopeId = 1;\n\n// node を強参照しない wire 台帳。inner key = `${statePathName}::${member}`\nconst wireIdsByNode = new WeakMap<Node, Map<string, number>>();\n\nfunction wireKey(member: string, statePathName: string): string {\n return `${statePathName}::${member}`;\n}\n\n/**\n * wire(配線)の安定 ID を返す。edge ID の基底と receipt の bindingId に使う。\n */\nexport function getWireId(\n node: Node,\n member: string,\n statePathName: string,\n): number {\n let byKey = wireIdsByNode.get(node);\n if (typeof byKey === \"undefined\") {\n byKey = new Map();\n wireIdsByNode.set(node, byKey);\n }\n const key = wireKey(member, statePathName);\n let wireId = byKey.get(key);\n if (typeof wireId === \"undefined\") {\n wireId = nextWireId++;\n byKey.set(key, wireId);\n }\n return wireId;\n}\n\n/** wire × 方向 → edge ID。方向を含めるため再利用されない */\nexport function getEdgeId(wireId: number, direction: PropagationEdgeDirection): number {\n return direction === \"to-element\" ? wireId * 2 : wireId * 2 + 1;\n}\n\nconst EMPTY_EDGES: ReadonlySet<number> = new Set<number>();\n\n/** 外部 event / API update ごとの transaction 開始。current context は変更しない */\nexport function beginPropagationTransaction(originBindingId: number): IPropagationContext {\n return {\n transactionId: nextTransactionId++,\n originBindingId,\n visitedEdges: EMPTY_EDGES,\n hop: 0,\n };\n}\n\n/** edge を 1 つ通過した新しい context を返す(visitedEdges 追加・hop+1) */\nexport function extendPropagationContext(\n context: IPropagationContext,\n edgeId: number,\n): IPropagationContext {\n const visitedEdges = new Set(context.visitedEdges);\n visitedEdges.add(edgeId);\n return {\n transactionId: context.transactionId,\n originBindingId: context.originBindingId,\n visitedEdges,\n hop: context.hop + 1,\n };\n}\n\n// 同期 dynamic scope の current context(updater drain / element 書き込み中に設定)\nlet currentContext: IPropagationContext | null = null;\n\nexport function getCurrentPropagationContext(): IPropagationContext | null {\n return currentContext;\n}\n\nexport function runWithPropagationContext<T>(\n context: IPropagationContext | null,\n callback: () => T,\n): T {\n const previous = currentContext;\n currentContext = context;\n try {\n return callback();\n } finally {\n currentContext = previous;\n }\n}\n\n// WriteReceipt: 同期 scope 限定のスタック。scope 終了時に必ず破棄される\ninterface IActiveWriteReceipt {\n readonly receipt: IWriteReceipt;\n readonly node: Node;\n}\n\nconst receiptStack: IActiveWriteReceipt[] = [];\n\n/**\n * state → element 書き込みを receipt scope で包んで実行する。\n * setter が同期 dispatch する event は matchWriteReceipt でこの receipt を観測できる。\n */\nexport function runWithWriteReceipt<T>(\n node: Node,\n member: string,\n writtenValue: unknown,\n bindingId: number,\n transactionId: number,\n callback: () => T,\n): T {\n const receipt: IWriteReceipt = {\n bindingId,\n bindingGeneration: 0,\n member,\n transactionId,\n synchronousScopeId: nextSynchronousScopeId++,\n writtenValue,\n };\n receiptStack.push({ receipt, node });\n try {\n return callback();\n } finally {\n receiptStack.pop();\n }\n}\n\n/**\n * (node, member) に対する最も内側の active receipt を返す。\n * confirmation / normalization の判定(writtenValue との Object.is 比較)は\n * 呼び出し側が行う。scope 外(非同期に届いた event)では null。\n */\nexport function matchWriteReceipt(node: Node, member: string): IWriteReceipt | null {\n for (let i = receiptStack.length - 1; i >= 0; i--) {\n const active = receiptStack[i];\n if (active.node === node && active.receipt.member === member) {\n return active.receipt;\n }\n }\n return null;\n}\n\n// テスト用\nexport const __private__ = {\n receiptStack,\n};\n","/**\n * occurrenceWrite.ts\n *\n * 要素(wc-bindable の出力・双方向バインドの要素)から届いた値を state へ書き込む 1 write に、\n * その出どころを伝える one-shot トークン。\n *\n * 1. occurrence(wc-bindable の `semantics: \"event\"`)は same-value guard(`config.sameValueGuard`・\n * 既定 ON)を 1 回分だけ飛ばす。\n * same-value guard は primitive が `Object.is` 同値なら set / enqueue / 依存伝播 / DOM 適用 /\n * `$updatedCallback` をまるごとスキップする。current value(state)にとっては正しい最適化だが、\n * occurrence(同じ payload でも「もう一度起きた」ことに意味がある)へ適用すると発生を取りこぼす。\n * どちらであるかは producer の declaration が `semantics` で宣言する\n * (docs/architecture-hardening/12-wc-bindable-observable-inventory.md)。\n * 2. 要素から来た書き込みはどれも、リストの要素(`for` の行そのもの — `status: .`)へ書いても入れ替え\n * (#4 の同一性モデル)として扱わない。要素が自分の行へ出す値は「その行の値の更新」で、別の行との\n * 入れ替えではない。入れ替えとして扱うと、同じ値から進む行が別の行と入れ替わり、以後の出力が別の行に\n * 届いた(#337)。\n *\n * one-shot にしている理由:\n * フラグを書き込みの呼び出しスタック全体へ張ると、その内側で走る `$updatedCallback` や\n * 依存伝播が行う無関係な書き込みまで巻き込む。`setByAddress` が最初のガード評価で\n * トークンを消費するため、影響は目的の 1 write に閉じる。\n */\n\nimport type { IStateElement } from \"../components/types\";\nimport type { ILoopContext } from \"../list/types\";\nimport { setLoopContextSymbol } from \"./symbols\";\n\nlet pending = 0;\n\n/**\n * 要素から届いた値を、その要素の行の文脈で state へ書く(双方向バインドの commit と初期同期)。\n * `occurrence` なら同値ガードも飛ばす。書き込みが setByAddress へ届かなくても、トークンはここで破棄する。\n */\nexport function commitElementValue(\n stateElement: IStateElement,\n loopContext: ILoopContext | null,\n statePathName: string,\n value: unknown,\n occurrence = false,\n): void {\n pending = occurrence ? 2 : 1;\n try {\n stateElement.createState(\"writable\", (state) => {\n state[setLoopContextSymbol](loopContext, () => {\n state[statePathName] = value;\n });\n });\n } finally {\n pending = 0;\n }\n}\n\n/**\n * ガード評価側が呼ぶ。0 = 要素から来ていない、1 = 要素から来た、2 = 要素から来た occurrence。\n * トークンは呼んだ時点で消費される。\n */\nexport function consumeElementWrite(): number {\n const consumed = pending;\n pending = 0;\n return consumed;\n}\n","import { isPossibleTwoWay } from \"./isPossibleTwoWay\";\nimport { EVENT_PROP_PREFIX, MODIFIER_READONLY } from \"../define\";\nimport { config } from \"../config\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { beginPropagationTransaction, extendPropagationContext, getCurrentPropagationContext, getEdgeId, getWireId, matchWriteReceipt, runWithPropagationContext } from \"../propagation/propagation\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo, IFilterInfo } from \"../types\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\nimport { filterListKey } from \"../binding/filterKey\";\nimport { createHandlerBindingRegistry } from \"./handlerBindingRegistry\";\nimport { commitElementValue } from \"../proxy/occurrenceWrite\";\n\nconst handlerByHandlerKey: Map<string, (event: Event) => any> = new Map();\n// binding を強参照しない台帳(handlerBindingRegistry.ts のリーク解説を参照)\nconst bindingRegistry = /*#__PURE__*/ createHandlerBindingRegistry();\nconst producerValueObserversByNode = new WeakMap<Node, Map<string, Set<(value: unknown) => void>>>();\n\nconst DEFAULT_GETTER = (e: Event) => (e as CustomEvent).detail;\n\n/**\n * 既定 getter(`(e) => e.detail`)が要素の宣言と噛み合っていない典型 2 形を、\n * 要素 × プロパティごとに 1 回だけ警告する(README「What the element writes back」)。\n *\n * (a) detail が undefined なのに `element[propName]` には値がある —\n * CustomEvent でない Event を dispatch している / `detail` を付け忘れている\n * (b) detail が `{ <propName>: … }` の形のラッパーで、`element[propName]` はオブジェクトでない —\n * `getter: (e) => e.detail.<propName>` が要る\n *\n * どちらも state には黙って undefined / ラッパーが書かれ、例外も lint 診断も出ない\n * (payload の形は静的に見えない)。挙動は変えない — 書き込みはそのまま行う。\n * occurrence(`semantics: \"event\"`)は payload が任意なので対象外(呼び出し側で除外)。\n */\nconst warnedDefaultGetter = new WeakMap<Element, Set<string>>();\nfunction warnDefaultGetterMismatch(node: Element, propName: string, detail: unknown): void {\n const propValue = (node as any)[propName];\n let reason: string | null = null;\n if (typeof detail === \"undefined\") {\n if (typeof propValue !== \"undefined\") {\n reason = `the event carried no detail (undefined) while element.${propName} is ${typeof propValue}`;\n }\n } else if (\n detail !== null && typeof detail === \"object\" && Object.prototype.hasOwnProperty.call(detail, propName)\n && (propValue === null || typeof propValue !== \"object\")\n ) {\n reason = `the event's detail is an object with a \"${propName}\" key while element.${propName} is ${typeof propValue}`;\n }\n if (reason === null) return;\n let props = warnedDefaultGetter.get(node);\n if (typeof props === \"undefined\") {\n props = new Set();\n warnedDefaultGetter.set(node, props);\n }\n if (props.has(propName)) return;\n props.add(propName);\n console.warn(\n `[@wcstack/state] [wcs/default-getter-mismatch] <${node.tagName.toLowerCase()}> \"${propName}\": ${reason}. ` +\n `With no getter, state receives e.detail as-is. Dispatch the value itself as detail, or declare ` +\n `getter (e.g. (e) => e.detail.${propName}, or (e) => e.target.${propName}) on that wcBindable property.`\n );\n}\n\n/**\n * getter 関数ごとの安定した識別子。\n *\n * ハンドラのクロージャは `valueGetter` の**実体**を捕捉するのに、鍵は「getter があるか」の\n * 真偽しか持っていなかった。propName / イベント名 / state パス / フィルタ列が同じで getter だけ\n * 違う 2 つの wc-bindable タグを同じパスに繋ぐと、後から配線した方が**先のタグの getter で\n * 畳んだ値**を state に書く。`filterListKey` を入れて塞いだのと同じ不完全さが getter に残っていた。\n */\nconst getterIds = new WeakMap<object, number>();\nlet nextGetterId = 0;\nfunction getterIdOf(valueGetter: ((event: Event) => any) | null): string {\n if (valueGetter === null) {\n return \"n\";\n }\n let id = getterIds.get(valueGetter);\n if (typeof id === \"undefined\") {\n getterIds.set(valueGetter, id = ++nextGetterId);\n }\n return `g${id}`;\n}\n\n/**\n * attach 時に控えた「何を、どのイベント名で付けたか」。**detach はここだけを見る。**\n *\n * `wcBindable` の宣言は live と規定されている(`protocol/wcBindableReader.ts`)ので、attach と\n * detach の間に差し替わりうる(composite shell は `target.constructor.wcBindable` で synthesized\n * 宣言を出すので絵空事ではない)。detach 側で作り直すと、宣言に依存する 3 つ — 二方向かの判定\n * (`isPossibleTwoWay`)、イベント名(`getEventName`)、ハンドラの鍵(`getHandlerKey`)— が\n * すべてずれうる。判定がずれれば門で早戻りしてリスナが残り、イベント名や鍵がずれれば\n * `removeEventListener` が空振りしてリスナが残る。**控えがあるかどうかが「attach したか」\n * そのもの**なので、detach は宣言を一切読み直さない。\n */\ninterface IAttachedTwoway {\n readonly key: string;\n readonly eventName: string;\n}\nconst attachedByBinding = new WeakMap<IBindingInfo, IAttachedTwoway>();\n\nfunction getHandlerKey(binding: IBindingInfo, eventName: string, valueGetter: ((event: Event) => any) | null, isOccurrence: boolean): string {\n const filterKey = filterListKey(binding.inFilters);\n return `${binding.propName}::${binding.statePathName}::${eventName}::${filterKey}::${getterIdOf(valueGetter)}::${isOccurrence ? 'o' : 's'}`;\n}\n\nfunction getEventName(binding: IBindingInfo): string {\n const tagName = (binding.node as Element).tagName.toLowerCase();\n // 1.default event name\n let eventName = (tagName === 'select') ? 'change' : 'input';\n // 2.wcBindable protocol\n const customTagName = getCustomElement(binding.node as Element);\n if (customTagName !== null) {\n const customClass = getCustomElementRegistry(binding.node)?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n raiseError(`Custom element <${customTagName}> is not defined. Cannot determine event name for two-way binding.`);\n }\n const propDesc = readBindableDeclaration(binding.node)?.knownProperties.get(binding.propName);\n if (propDesc) {\n eventName = propDesc.event;\n }\n }\n // 3.modifier(`#onchange` 等 — `on` + イベント名の修飾子形。README「Modifiers」参照)\n for(const modifier of binding.propModifiers) {\n if (modifier.startsWith(EVENT_PROP_PREFIX)) {\n eventName = modifier.slice(EVENT_PROP_PREFIX.length);\n }\n }\n return eventName;\n}\n\nfunction getValueGetter(binding: IBindingInfo): ((event: Event) => any) | null {\n const customTagName = getCustomElement(binding.node as Element);\n if (customTagName !== null) {\n const propDesc = readBindableDeclaration(binding.node)?.knownProperties.get(binding.propName);\n if (propDesc) {\n return propDesc.getter ?? DEFAULT_GETTER;\n }\n }\n return null;\n}\n\n/**\n * producer が `semantics: \"event\"` を宣言した property か。occurrence は同じ payload でも\n * 「もう一度起きた」ことに意味があるため、state への書き込みで same-value guard を通さない\n * (docs/async-io-node-guidelines.md §3.3.1 の `event`)。宣言が無い property は従来どおり\n * — 未指定は「未指定」であって state ではないので、挙動は変えない。\n */\nfunction isOccurrenceProperty(binding: IBindingInfo): boolean {\n const customTagName = getCustomElement(binding.node as Element);\n if (customTagName === null) return false;\n const propDesc = readBindableDeclaration(binding.node)?.knownProperties.get(binding.propName);\n return propDesc?.semantics === \"event\";\n}\n\nconst twowayEventHandlerFunction = (\n propName: string,\n statePathName: string,\n inFilters: IFilterInfo[],\n valueGetter: ((event: Event) => any) | null,\n isOccurrence: boolean,\n) => (event: Event): any => {\n const node = event.target as Element;\n if (node === null) {\n console.warn(`[@wcstack/state] event.target is null.`);\n return;\n }\n let newValue: any;\n if (valueGetter !== null) {\n newValue = valueGetter(event);\n if (valueGetter === DEFAULT_GETTER && !isOccurrence) {\n warnDefaultGetterMismatch(node, propName, newValue);\n }\n } else {\n if (!(propName in node)) {\n console.warn(`[@wcstack/state] Property \"${propName}\" does not exist on target element.`);\n return;\n }\n newValue = (node as any)[propName];\n }\n let filteredNewValue = newValue;\n for(const filter of inFilters) {\n filteredNewValue = filter.filterFn(filteredNewValue);\n }\n const producerObservers = producerValueObserversByNode.get(node)?.get(propName);\n if (typeof producerObservers !== \"undefined\") {\n for (const observer of producerObservers) observer(filteredNewValue);\n }\n\n let propagationContext: ReturnType<typeof getCurrentPropagationContext> = null;\n if (config.enablePropagationContext) {\n // Phase 3: element → state edge の因果判定(設計書 §4)。\n const wireId = getWireId(node, propName, statePathName);\n const receipt = matchWriteReceipt(node, propName);\n if (receipt !== null && Object.is(receipt.writtenValue, newValue)) {\n // 規則 4: 同じ setter call stack 内で同じ member から Object.is 同値の\n // 通知が戻った場合だけ confirmation として再伝播を抑止する。\n // shadow diagnostic(§8): primitive なら same-value guard も同じ結論に\n // なるため、provenance だけが守っている非 primitive の echo を可視化する。\n if (config.debug) {\n console.debug(`[@wcstack/state] propagation: write confirmation suppressed echo.`, {\n node,\n propName,\n statePathName,\n transactionId: receipt.transactionId,\n coveredBySameValueGuard: config.sameValueGuard\n && (filteredNewValue === null || typeof filteredNewValue !== \"object\"),\n });\n }\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"propagation:suppressed\",\n reason: \"confirmation\",\n transactionId: receipt.transactionId,\n edgeId: getEdgeId(wireId, \"to-state\"),\n node,\n member: propName,\n });\n }\n return;\n }\n // receipt があるが値が異なる場合は正規化差分: element の確定値として受理し、\n // 新しい edge を通る変更として継続する(規則 5・decision gate)。\n const toStateEdgeId = getEdgeId(wireId, \"to-state\");\n const baseContext = getCurrentPropagationContext();\n if (baseContext !== null && baseContext.visitedEdges.has(toStateEdgeId)) {\n // 規則 2: 同じ transaction が同じ edge を再度通ろうとした場合だけ抑止\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"propagation:suppressed\",\n reason: \"visited-edge\",\n transactionId: baseContext.transactionId,\n edgeId: toStateEdgeId,\n node,\n member: propName,\n });\n }\n return;\n }\n // 規則 1: 外部 event(受け皿の context が無い)なら新しい transaction を開始\n propagationContext = extendPropagationContext(\n baseContext ?? beginPropagationTransaction(wireId),\n toStateEdgeId,\n );\n }\n\n const rootNode = node.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for two-way binding.`);\n }\n\n const loopContext = getLoopContextByNode(node);\n // 要素から来た書き込み: 行そのものへ書いても入れ替えにしない(#337)。occurrence は同値でも\n // 取りこぼしてはならない(§3.3.1 `event`)。トークンは setByAddress の最初のガード評価で\n // 消費されるため、この write 1 回だけに効く(proxy/occurrenceWrite.ts)。\n const commitToState = (): void => commitElementValue(stateElement, loopContext, statePathName, filteredNewValue, isOccurrence);\n if (propagationContext !== null) {\n runWithPropagationContext(propagationContext, commitToState);\n } else {\n commitToState();\n }\n}\n\nexport function addTwowayValueObserver(\n node: Node,\n propName: string,\n observer: (value: unknown) => void,\n): () => void {\n let byProperty = producerValueObserversByNode.get(node);\n if (typeof byProperty === \"undefined\") {\n byProperty = new Map();\n producerValueObserversByNode.set(node, byProperty);\n }\n let observers = byProperty.get(propName);\n if (typeof observers === \"undefined\") {\n observers = new Set();\n byProperty.set(propName, observers);\n }\n observers.add(observer);\n return () => {\n observers?.delete(observer);\n if (observers?.size === 0) byProperty?.delete(propName);\n if (byProperty?.size === 0) producerValueObserversByNode.delete(node);\n };\n}\n\nexport function attachTwowayEventHandler(binding: IBindingInfo): void {\n const customTagName = getCustomElement(binding.node as Element);\n if (customTagName !== null) {\n const registry = getCustomElementRegistry(binding.node);\n const customClass = registry?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${customTagName}>.`);\n }\n return;\n }\n }\n\n if (isPossibleTwoWay(binding.node, binding.propName) && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1) {\n const eventName = getEventName(binding);\n const valueGetter = getValueGetter(binding);\n const isOccurrence = isOccurrenceProperty(binding);\n const key = getHandlerKey(binding, eventName, valueGetter, isOccurrence);\n attachedByBinding.set(binding, { key, eventName });\n let twowayEventHandler = handlerByHandlerKey.get(key);\n if (typeof twowayEventHandler === \"undefined\") {\n twowayEventHandler = twowayEventHandlerFunction(\n binding.propName,\n binding.statePathName,\n binding.inFilters,\n valueGetter,\n isOccurrence\n );\n handlerByHandlerKey.set(key, twowayEventHandler);\n }\n (binding.node as Element).addEventListener(eventName, twowayEventHandler);\n bindingRegistry.add(key, binding);\n }\n}\n\nexport function detachTwowayEventHandler(binding: IBindingInfo): void {\n // 控えが無い = attach していない(未定義のカスタム要素、二方向でないプロパティ、`#ro`)。\n // ここで `wcBindable` を読み直さないのが要点 — 理由は `attachedByBinding` の注記\n const attached = attachedByBinding.get(binding);\n if (typeof attached === \"undefined\") {\n return;\n }\n attachedByBinding.delete(binding);\n const twowayEventHandler = handlerByHandlerKey.get(attached.key);\n if (typeof twowayEventHandler === \"undefined\") {\n return;\n }\n (binding.node as Element).removeEventListener(attached.eventName, twowayEventHandler);\n\n if (bindingRegistry.remove(attached.key, binding)) {\n handlerByHandlerKey.delete(attached.key);\n }\n}\n\nexport const __private__ = {\n handlerByHandlerKey,\n bindingRegistry,\n producerValueObserversByNode,\n getHandlerKey,\n getEventName,\n getValueGetter,\n twowayEventHandlerFunction,\n DEFAULT_GETTER,\n};\n","// framework 自身が detach し明示的に解体(deactivate/unmount)したノード。\n// BindingOwner の MutationObserver は削除サブツリー走査でこれらをスキップする。\n//\n// 根拠: 削除時の handleRemovedNode は binding を dispose するだけ(DOM 構造変更も\n// connect-snapshot 依存も無い)で、framework が unmount 経路で既に dispose 済みの\n// content に対しては純粋な冗長走査(forEachInclusive で削除サブツリー全体を歩く)に\n// なる。create(追加)経路は two-way の connect-time snapshot を observer に依存する\n// ため対象外だが、削除は依存が無いため安全に飛ばせる。\n//\n// マークは observer が削除を配送した時点で消費(削除)する。マーク〜配送の間隔は\n// 単一 microtask であり、その間に外部 DOM 変異は割り込めない(framework の drain は\n// 同期)ため、マークは framework 由来の削除にしか一致しない。\nconst observerSkipNodes = new WeakSet<Node>();\n\nexport function markObserverSkipOnRemove(node: Node): void {\n observerSkipNodes.add(node);\n}\n\n// マーク済みなら true を返しつつマークを消費する。未マークなら false。\nexport function consumeObserverSkipOnRemove(node: Node): boolean {\n if (!observerSkipNodes.has(node)) {\n return false;\n }\n observerSkipNodes.delete(node);\n return true;\n}\n\n// framework 自身がマウント(Content.appendTo / mountAfter)したノード。\n// 追加サブツリー走査の実質の仕事は connect-snapshot 待ち(observationPending)の\n// record への配送だけで、record 自体は同期マウント(activateContent → start)で\n// observer flush より先に active 済み。よって待ちがグローバルに 1 つも無ければ\n// 追加側走査も冗長であり丸ごとスキップできる(削除側スキップの対称形)。\n// マーク〜配送が単一 microtask で外部変異が割り込めない前提も削除側と同じ。\n// framework の削除を親ごとの件数で数える(1 つの mutation record がその件数の子をまとめて消したとき、\n// 削除ノードごとの WeakSet 印の代わりに 1 回の判定で飛ばせる)\nconst skipRemovedChildrenByParent = new WeakMap<Node, number>();\n\nexport function markObserverSkipRemovedChildren(parent: Node, count: number): void {\n skipRemovedChildrenByParent.set(parent, (skipRemovedChildrenByParent.get(parent) ?? 0) + count);\n}\n\n/** Consumes `count` framework removals of `parent`; false (and nothing consumed) when the count does not cover them. */\nexport function consumeObserverSkipRemovedChildren(parent: Node, count: number): boolean {\n const pending = skipRemovedChildrenByParent.get(parent);\n if (typeof pending === \"undefined\" || pending < count) {\n return false;\n }\n if (pending === count) {\n skipRemovedChildrenByParent.delete(parent);\n } else {\n skipRemovedChildrenByParent.set(parent, pending - count);\n }\n return true;\n}\n\nconst observerSkipAddedNodes = new WeakSet<Node>();\n\nexport function markObserverSkipOnAdd(node: Node): void {\n observerSkipAddedNodes.add(node);\n}\n\n// マーク済みなら true を返しつつマークを消費する(削除側と同じ one-shot 契約)。\nexport function consumeObserverSkipOnAdd(node: Node): boolean {\n if (!observerSkipAddedNodes.has(node)) {\n return false;\n }\n observerSkipAddedNodes.delete(node);\n return true;\n}\n\n// connect-snapshot 待ち(two-way sync=connect で未接続のまま activate された record)の\n// グローバル件数。> 0 の間は追加側スキップを無効化して従来走査に戻す。\n// increment は settleInitialRecord、decrement は readProducerSnapshot(消化時)と\n// runTeardowns(未消化のまま終端した record のリーク防止)が担う。\nlet pendingObservationCount = 0;\n\nexport function incrementPendingObservation(): void {\n pendingObservationCount++;\n}\n\nexport function decrementPendingObservation(): void {\n pendingObservationCount--;\n}\n\nexport function hasPendingObservation(): boolean {\n return pendingObservationCount > 0;\n}\n","import { ICustomElementRegistryAdapter } from \"../platform/customElementRegistry\";\n\ninterface IDefinitionWaiter {\n active: boolean;\n readonly resolve: () => void;\n readonly reject: (error: unknown) => void;\n}\n\ninterface IDefinitionEntry {\n readonly waiters: Set<IDefinitionWaiter>;\n}\n\n/**\n * Shares one CustomElementRegistry.whenDefined() continuation per registry/tag.\n * Waiters can be removed independently, so a never-defined tag does not retain\n * binding records or their DOM nodes after teardown.\n */\nexport class DefinitionCoordinator {\n private readonly entries = new Map<string, IDefinitionEntry>();\n\n constructor(private readonly registry: ICustomElementRegistryAdapter) {}\n\n wait(\n tagName: string,\n resolve: () => void,\n reject: (error: unknown) => void = () => undefined,\n ): () => void {\n const normalizedTagName = tagName.toLowerCase();\n let entry = this.entries.get(normalizedTagName);\n if (typeof entry === \"undefined\") {\n entry = { waiters: new Set() };\n this.entries.set(normalizedTagName, entry);\n this.registry.whenDefined(normalizedTagName).then(\n () => this.settle(normalizedTagName, null),\n (error: unknown) => this.settle(normalizedTagName, error),\n );\n }\n\n const waiter: IDefinitionWaiter = { active: true, resolve, reject };\n entry.waiters.add(waiter);\n return () => {\n if (!waiter.active) return;\n waiter.active = false;\n entry?.waiters.delete(waiter);\n };\n }\n\n pendingCount(tagName: string): number {\n return this.entries.get(tagName.toLowerCase())?.waiters.size ?? 0;\n }\n\n private settle(tagName: string, error: unknown): void {\n const entry = this.entries.get(tagName);\n if (typeof entry === \"undefined\") return;\n this.entries.delete(tagName);\n const waiters = Array.from(entry.waiters);\n entry.waiters.clear();\n for (const waiter of waiters) {\n if (!waiter.active) continue;\n waiter.active = false;\n if (error === null) waiter.resolve();\n else waiter.reject(error);\n }\n }\n}\n\nconst coordinatorByRegistry = new WeakMap<ICustomElementRegistryAdapter, DefinitionCoordinator>();\n\nexport function getDefinitionCoordinator(\n registry: ICustomElementRegistryAdapter,\n): DefinitionCoordinator {\n let coordinator = coordinatorByRegistry.get(registry);\n if (typeof coordinator === \"undefined\") {\n coordinator = new DefinitionCoordinator(registry);\n coordinatorByRegistry.set(registry, coordinator);\n }\n return coordinator;\n}\n","import { getRootNodeByFragment } from \"../apply/rootNodeByFragment\";\nimport { getStateAddressByBindingInfo } from \"../binding/getStateAddressByBindingInfo\";\nimport { IStateElement } from \"../components/types\";\nimport { config } from \"../config\";\nimport { ATTR_NAMESPACE, CLASS_NAMESPACE, COMMAND_NAMESPACE, MODIFIER_KEY_INIT, MODIFIER_KEY_SYNC, STYLE_NAMESPACE } from \"../define\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { hasByAddressSymbol } from \"../proxy/symbols\";\nimport { commitElementValue } from \"../proxy/occurrenceWrite\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo } from \"../types\";\n\n/**\n * 左辺の先頭セグメントが名前空間になる束縛 — `apply/applyChange.ts` の\n * `applyChangeByFirstSegment` と**同じ集合**。\n *\n * ここが 1 つでも欠けると、欠けた名前空間が下の wcBindable プロパティ検証に落ちて\n * `Property \"class.on\" is not declared by wcBindable.` が飛び、**そのルートの束縛が\n * 1 つも立たなくなる**(`class.` / `attr.` / `style.` が実際にそうなっていた。\n * `command.` だけが除外されていた)。\n *\n * 集合の一致は `__tests__/bindings.initialSync.namespaces.test.ts` が apply 層の\n * ディスパッチ表と突き合わせて固定する(`manifest.test.ts` の drift 検出と同じ手)。\n */\nconst LEFT_HAND_NAMESPACES: ReadonlySet<string> = new Set<string>([\n CLASS_NAMESPACE, ATTR_NAMESPACE, STYLE_NAMESPACE, COMMAND_NAMESPACE,\n]);\n\nexport type InitialAuthority = \"state\" | \"element\" | \"auto\" | \"none\";\nexport type ResolvedInitialAuthority = Exclude<InitialAuthority, \"auto\">;\nexport type InitialSyncOn = \"call\" | \"connect\";\n\nexport interface IInitialSyncPolicy {\n readonly authority: InitialAuthority;\n readonly syncOn: InitialSyncOn;\n readonly observable: boolean;\n /**\n * wcBindable 宣言が properties のみ(output-only member)であること。\n * authority は初期同期のみを支配する(docs/architecture-hardening/09 §3.6)が、\n * output-only member への state→element 書き込みは初期に限らず契約として\n * 恒久ブロックする。その判定を authority と分離してここに持つ。\n */\n readonly outputOnly: boolean;\n}\n\nfunction readOption(\n binding: IBindingInfo,\n key: \"init\" | \"sync\",\n): string | null {\n let result: string | null = null;\n for (const modifier of binding.propModifiers) {\n const separator = modifier.indexOf(\"=\");\n if (separator < 0) continue;\n const modifierKey = modifier.slice(0, separator).trim();\n const value = modifier.slice(separator + 1).trim();\n if (modifierKey !== MODIFIER_KEY_INIT && modifierKey !== MODIFIER_KEY_SYNC) {\n raiseError(`Unknown binding modifier \"${modifierKey}\" in \"${modifier}\".`);\n }\n if (modifierKey !== key) continue;\n if (result !== null) {\n raiseError(`Binding modifier \"${key}\" may only be specified once.`);\n }\n result = value;\n }\n return result;\n}\n\nfunction parseAuthority(value: string | null): InitialAuthority | null {\n if (value === null) return null;\n if (value === \"state\" || value === \"element\" || value === \"auto\" || value === \"none\") {\n return value;\n }\n return raiseError(`Invalid init modifier value \"${value}\".`);\n}\n\nfunction parseSyncOn(value: string | null): InitialSyncOn {\n if (value === null || value === \"call\") return \"call\";\n if (value === \"connect\") return \"connect\";\n return raiseError(`Invalid sync modifier value \"${value}\".`);\n}\n\nexport function hasInitialSyncModifier(binding: IBindingInfo): boolean {\n return binding.propModifiers.some((modifier) => modifier.includes(\"=\"));\n}\n\n// 頻出ポリシー(修飾子なしの通常バインディング)の凍結シングルトン。リスト行では\n// binding ごとに resolveInitialSyncPolicy が走るため、毎回のオブジェクト割り当てを\n// 避ける(record.initialPolicy は読み取り専用でしか使われない)。\nconst STATE_CALL_POLICY: IInitialSyncPolicy = Object.freeze({ authority: \"state\", syncOn: \"call\", observable: false, outputOnly: false });\nconst NONE_CALL_POLICY: IInitialSyncPolicy = Object.freeze({ authority: \"none\", syncOn: \"call\", observable: false, outputOnly: false });\n\nfunction statePolicy(authority: InitialAuthority, syncOn: IInitialSyncPolicy[\"syncOn\"]): IInitialSyncPolicy {\n if (authority === \"state\" && syncOn === \"call\") return STATE_CALL_POLICY;\n return { authority, syncOn, observable: false, outputOnly: false };\n}\n\nexport function resolveInitialSyncPolicy(binding: IBindingInfo): IInitialSyncPolicy {\n if (!config.enableDirectionalInitialSync) {\n if (hasInitialSyncModifier(binding)) {\n raiseError(\"init=/sync= modifiers require enableDirectionalInitialSync.\");\n }\n return STATE_CALL_POLICY;\n }\n\n const explicitAuthority = parseAuthority(readOption(binding, MODIFIER_KEY_INIT));\n const syncOn = parseSyncOn(readOption(binding, MODIFIER_KEY_SYNC));\n if (binding.bindingType === \"event\") {\n if (explicitAuthority !== null && explicitAuthority !== \"none\") {\n raiseError(\"Event bindings only allow init=none.\");\n }\n return syncOn === \"call\" ? NONE_CALL_POLICY : { authority: \"none\", syncOn, observable: false, outputOnly: false };\n }\n // 左辺の名前空間(`class.` / `attr.` / `style.` / `command.`)は bindingType こそ \"prop\" だが、\n // `propName` は wcBindable の property **ではない**。下の property authority 検証\n // (未宣言なら raiseError)に掛けてはならず、掛けると wc-bindable 要素に `class.on: flag` と\n // 書いただけで `Property \"class.on\" is not declared by wcBindable.` が飛び、\n // **そのルートの束縛が 1 つも立たなくなる**(`getBindingsReady` ごと reject)。\n // 値の初期同期を持たない配線なので、現行互換の \"state\" authority を返す\n // (command token は従来どおり初期 apply で配線される)。\n if (LEFT_HAND_NAMESPACES.has(binding.propSegments[0])) {\n return statePolicy(\"state\", syncOn);\n }\n if (binding.bindingType !== \"prop\") {\n if (explicitAuthority !== null && explicitAuthority !== \"state\" && explicitAuthority !== \"none\") {\n raiseError(`Binding type \"${binding.bindingType}\" does not support init=${explicitAuthority}.`);\n }\n return statePolicy(explicitAuthority ?? \"state\", syncOn);\n }\n\n const declaration = readBindableDeclaration(binding.node);\n if (declaration === null) {\n return statePolicy(explicitAuthority ?? \"state\", syncOn);\n }\n const hasOutput = declaration.knownProperties.has(binding.propName);\n const hasInput = declaration.declaredInputs.has(binding.propName);\n if (!hasOutput && !hasInput) {\n raiseError(`Property \"${binding.propName}\" is not declared by wcBindable.`);\n }\n\n const allowed = hasOutput && hasInput\n ? new Set<InitialAuthority>([\"state\", \"element\", \"auto\", \"none\"])\n : hasOutput\n ? new Set<InitialAuthority>([\"element\", \"none\"])\n : new Set<InitialAuthority>([\"state\", \"none\"]);\n const defaultAuthority: InitialAuthority = hasOutput && !hasInput ? \"element\" : \"state\";\n const authority = explicitAuthority ?? defaultAuthority;\n if (!allowed.has(authority)) {\n raiseError(`init=${authority} is incompatible with wcBindable member \"${binding.propName}\".`);\n }\n if (syncOn === \"connect\" && !hasOutput) {\n raiseError(`sync=connect requires observable property \"${binding.propName}\".`);\n }\n return { authority, syncOn, observable: hasOutput, outputOnly: hasOutput && !hasInput };\n}\n\n/**\n * 初期同期が読み書きする state 要素を引く。`for:` の行は文書へ挿入する前のバッチ\n * fragment の上で活性化される(`apply/applyChangeToFor.ts`)ので、その間の\n * `getRootNode()` は fragment 自身を返す。fragment → 実ルートの台帳\n * (`setRootNodeByFragment`)で引き直す — `applyChange` と同じ手順。\n * 引き直さないと、クラス定義済みの要素を `for:` の行に置いたとき初期同期が投げ、\n * 一覧の反映ごと失敗していた(#319)。\n */\nfunction getSyncStateElement(node: Node): IStateElement | null {\n let rootNode: Node | null = node.getRootNode();\n if (rootNode instanceof DocumentFragment && !(rootNode instanceof ShadowRoot)) {\n rootNode = getRootNodeByFragment(rootNode);\n }\n return rootNode === null ? null : getStateElement(rootNode);\n}\n\nexport function isBindingStateInitialized(binding: IBindingInfo): boolean {\n const stateElement = getSyncStateElement(binding.replaceNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n const address = getStateAddressByBindingInfo(binding);\n let initialized = false;\n stateElement.createState(\"readonly\", (state) => {\n initialized = state[hasByAddressSymbol](address);\n });\n return initialized;\n}\n\nexport function resolveInitialAuthority(\n binding: IBindingInfo,\n authority: InitialAuthority,\n): ResolvedInitialAuthority {\n if (authority !== \"auto\") return authority;\n return isBindingStateInitialized(binding) ? \"state\" : \"element\";\n}\n\nexport function commitProducerValue(binding: IBindingInfo, value: unknown): void {\n let filteredValue = value;\n for (const filter of binding.inFilters) {\n filteredValue = filter.filterFn(filteredValue);\n }\n const stateElement = getSyncStateElement(binding.node);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for initial binding sync.`);\n }\n // 要素から来た書き込み: 行そのものへ書いても入れ替えにしない(proxy/occurrenceWrite.ts・#337)\n commitElementValue(stateElement, getLoopContextByNode(binding.node), binding.statePathName, filteredValue);\n}\n","import { applyChangeFromBindings } from \"../apply/applyChangeFromBindings\";\nimport { EVENT_TOKEN_NAMESPACE, MODIFIER_READONLY } from \"../define\";\nimport { IAbsoluteStateAddress } from \"../address/types\";\nimport { getTreePath } from \"../address/TreePath\";\nimport { ITreePath } from \"../address/types\";\nimport { clearAbsoluteStateAddressByBinding, getAbsoluteStateAddressByBinding, resolveBindingRootNode } from \"../binding/getAbsoluteStateAddressByBinding\";\nimport { addBindingByAbsoluteStateAddress, addBindingByPattern, removeBindingByAbsoluteStateAddress, removeBindingByPattern } from \"../binding/getBindingSetByAbsoluteStateAddress\";\nimport { getListIndexByBindingInfo } from \"../list/getListIndexByBindingInfo\";\nimport { getLastListValueByAbsoluteStateAddress, hasLastListValueByAbsoluteStateAddress, setLastListValueByAbsoluteStateAddress } from \"../list/lastListValueByAbsoluteStateAddress\";\nimport { getStateListBaseline, hasStateListBaseline, setStateListBaseline } from \"../list/stateListBaseline\";\nimport { IListIndex } from \"../list/types\";\nimport { clearStateAddressByBindingInfo } from \"../binding/getStateAddressByBindingInfo\";\nimport { config } from \"../config\";\nimport { filterListKey } from \"../binding/filterKey\";\nimport { detachCheckboxEventHandler, attachCheckboxEventHandler } from \"../event/checkboxHandler\";\nimport { detachEventTokenHandler, attachEventTokenHandler } from \"../event/eventTokenHandler\";\nimport { detachEventHandler, attachEventHandler } from \"../event/handler\";\nimport { detachRadioEventHandler, attachRadioEventHandler } from \"../event/radioHandler\";\nimport { detachTwowayEventHandler, attachTwowayEventHandler, addTwowayValueObserver } from \"../event/twowayHandler\";\nimport { isPossibleTwoWay } from \"../event/isPossibleTwoWay\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry, upgradeCustomElement } from \"../platform/customElementRegistry\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IBindingInfo } from \"../types\";\nimport { consumeObserverSkipOnAdd, consumeObserverSkipOnRemove, consumeObserverSkipRemovedChildren, decrementPendingObservation, hasPendingObservation, incrementPendingObservation } from \"./observerSkip\";\nimport { getDefinitionCoordinator } from \"./DefinitionCoordinator\";\nimport { commitProducerValue, hasInitialSyncModifier, IInitialSyncPolicy, ResolvedInitialAuthority, resolveInitialAuthority, resolveInitialSyncPolicy } from \"./initialSync\";\nimport { replaceToReplaceNode } from \"./replaceToReplaceNode\";\nimport type { IRowPlan } from \"../structural/types\";\n\nexport type BindingPhase =\n | \"discovered\"\n | \"waiting-definition\"\n | \"ready-to-attach\"\n | \"attaching\"\n | \"synchronizing\"\n | \"active\"\n | \"failed\"\n | \"disposed\";\n\nexport interface IBindingRecord {\n readonly id: number;\n readonly info: IBindingInfo;\n readonly generation: number;\n phase: BindingPhase;\n /**\n * 追加の後始末クロージャ(radio/checkbox/observer/定義キャンセル等の希少ケース)。\n * 頻出の後始末(イベント detach・双方向 detach・アドレス台帳解除)はクロージャで\n * なく record のフラグ/フィールドから runTeardowns がデータ駆動で実行するため、\n * 大多数の record では null のまま(行あたり Set×5 + クロージャ×10 の割当を排除)。\n */\n teardowns: Set<() => void> | null;\n}\n\ninterface IBindingOptions {\n registerAddress: boolean;\n registerPathInfo: boolean;\n applyOnReconnect: boolean;\n}\n\ninterface IInternalBindingRecord extends IBindingRecord {\n /**\n * generation はプラン行のプール再利用(record オブジェクト再利用)で更新するため\n * 内部表現では書き込み可能にする(IBindingRecord 公開面は readonly のまま)\n */\n generation: number;\n readonly session: BindingSession;\n readonly anchor: Node;\n readonly options: IBindingOptions;\n address: IAbsoluteStateAddress | null;\n /**\n * パターン索引台帳((absolutePathInfo, listIndex) 2 段キー)への登録。リスト行の\n * binding は address を intern せずこちらに登録する。address とは排他。\n */\n patternPathInfo: ITreePath | null;\n patternListIndex: IListIndex | null;\n pendingDefinitions: number;\n initialPolicy: IInitialSyncPolicy | null;\n resolvedAuthority: ResolvedInitialAuthority | null;\n initialSettled: boolean;\n /**\n * 最初の shouldApplyState 相談(= 初期 state sweep / 初回 render の選別)を\n * 消費済みか。authority は初期同期のみを支配する(09 §3.6)ため、初回相談は\n * authority で答え、以降の定常 apply は output-only 契約と connect-snapshot\n * 未解決だけをブロックする。\n */\n initialApplyDone: boolean;\n /** initialPolicy.outputOnly のミラー(settle 時確定・定常ゲートの分岐を総域にする) */\n outputOnlyMember: boolean;\n observationPending: boolean;\n eventSequence: number;\n hasProducerValue: boolean;\n producerValue: unknown;\n /** attachEventHandler 済み(dispose 時に detachEventHandler をデータ駆動実行) */\n eventAttached: boolean;\n /** attachTwowayEventHandler 済み(dispose 時に detachTwowayEventHandler をデータ駆動実行) */\n twowayAttached: boolean;\n}\n\ninterface IDeferredDefinition {\n readonly node: Node;\n /** 登録した世代(session の disposedAt と比べる) */\n readonly born: number;\n /** 張っている registry の待ちの取り消し。null はまだ張っていない(fragment の中)か、外れて下ろした */\n cancel: (() => void) | null;\n /** ノードが今属する registry で待ちを張る(張り済み・session が手放した待ちは何もしない) */\n arm: () => void;\n}\n\ninterface IObservableRoot extends Node {\n contains(other: Node | null): boolean;\n}\n\nlet nextRecordId = 0;\n// 次の microtask にまとめて張る定義待ち(全 session で 1 本・登録順)。null は並んでいる待ちが無い\nlet armQueue: IDeferredDefinition[] | null = null;\nlet nextGeneration = 0;\n\n// プラン行の帳簿は束縛ごとの record ではなく行に 1 つの record(slot 配列)で持つ\n// (行ランタイム設計 R3)。phase は slot ごとの SLOT_*、フラグは FLAG_* のビット。\nconst SLOT_ACTIVE = 0;\nconst SLOT_DISPOSED = 1;\nconst SLOT_FAILED = 2;\nconst FLAG_INITIAL_APPLY_DONE = 1;\nconst FLAG_EVENT_ATTACHED = 2;\nconst SLOT_PHASE_NAMES: readonly BindingPhase[] = [\"active\", \"disposed\", \"failed\"];\ninterface IRowRecord {\n readonly id: number;\n /** この行を持つ共有 session(行 → session の逆引き。設計 R3) */\n readonly session: BindingSession;\n generation: number;\n readonly plan: IRowPlan;\n readonly bindings: readonly IBindingInfo[];\n /** activate が address 登録を昇格したか(従来の record.options.registerAddress に相当、行で共有) */\n registered: boolean;\n /** SLOT_* per slot */\n readonly phases: number[];\n /** FLAG_* bits per slot */\n readonly flags: number[];\n readonly addresses: (IAbsoluteStateAddress | null)[];\n readonly patternPathInfos: (ITreePath | null)[];\n readonly patternListIndexes: (IListIndex | null)[];\n}\n// 束縛 → その行の record(record が共有 session を知っている。設計 R3)\nconst rowByBinding = new WeakMap<IBindingInfo, IRowRecord>();\n// 行 slot に振った record id(`getRecord` — 検査・テスト専用の経路でしか作られない)\nconst rowSlotIds = new WeakMap<IRowRecord, number[]>();\n\nconst recordByBinding = new WeakMap<IBindingInfo, IInternalBindingRecord>();\nconst sessionByRoot = new WeakMap<Node, BindingSession>();\n\n// binding の構造キーは不変フィールドのみから決まる。リスト行の初期化では同一 binding に\n// 対し remember() が2回呼ばれる(createContent 内 initializeBindingsByFragment と\n// activateContent の registerAddress 目的の initialize)ため、2度目の文字列生成を避けるべく\n// binding 単位でメモ化する。プロファイル上 bindingKey は create-10k の JS 自己時間で上位。\nconst bindingKeyByBinding = new WeakMap<IBindingInfo, string>();\n\n// node → その node に関心を持つ session(anchor として binding を覚えている、\n// または定義待ちタスクを抱えている)。BindingOwner は mutation で増減した\n// サブツリーを1回だけ走査し、ここに登録された session だけへ per-node 配送する。\n// 全 session ブロードキャストだと、リスト行の逐次 append などで\n// 「session 数 × 変異ノード数」の O(n²) ファンアウトになるため、その正本台帳。\n// 大多数の node は関心 session が1つなので単一値で持ち、2つ目から Set に昇格する。\nconst interestedSessionsByNode = new WeakMap<Node, BindingSession | Set<BindingSession>>();\n\nfunction addInterestedSession(node: Node, session: BindingSession): void {\n const current = interestedSessionsByNode.get(node);\n if (typeof current === \"undefined\") {\n interestedSessionsByNode.set(node, session);\n return;\n }\n if (current === session) return;\n if (current instanceof Set) {\n current.add(session);\n return;\n }\n interestedSessionsByNode.set(node, new Set([current, session]));\n}\n\n/**\n * このノードに既にバインドが張られているか。\n *\n * binder プロトコル(`bind()`)の冪等判定に使う。`remember` が binding ごとに\n * `addInterestedSession(binding.replaceNode, …)` を呼ぶので、バインド済みノードは\n * 必ずこの台帳に載っている。新しい台帳を足さずに済むぶん、二重管理の齟齬が無い。\n */\nexport function hasInterestedSession(node: Node): boolean {\n return interestedSessionsByNode.has(node);\n}\n\nfunction forEachInterestedSession(node: Node, callback: (session: BindingSession) => void): void {\n const current = interestedSessionsByNode.get(node);\n if (typeof current === \"undefined\") return;\n if (current instanceof Set) {\n for (const session of Array.from(current)) callback(session);\n return;\n }\n callback(current);\n}\n\nfunction forEachInclusive(root: Node, callback: (node: Node) => void): void {\n callback(root);\n // 葉ノード(fragment 一括挿入時のテキスト・空セル等が大多数)では\n // Array.from(childNodes) の空配列アロケーションを避ける。callback が子を\n // 追加しうるため firstChild は callback 後に判定する(従来と同一意味論)。\n if (root.firstChild === null) return;\n for (const child of Array.from(root.childNodes)) {\n forEachInclusive(child, callback);\n }\n}\n\nfunction isObservableRoot(value: unknown): value is IObservableRoot {\n if (typeof value !== \"object\" || value === null) return false;\n const node = value as Node;\n return node.nodeType === 9 || (node.nodeType === 11 && \"host\" in (node as object));\n}\n\nfunction observableRootFor(node: Node): IObservableRoot | null {\n const root = node.getRootNode();\n return isObservableRoot(root) ? root : null;\n}\n\nclass BindingOwner {\n private readonly observer: MutationObserver | null;\n\n constructor(readonly root: IObservableRoot) {\n const Observer = (globalThis as { MutationObserver?: typeof MutationObserver }).MutationObserver;\n this.observer = typeof Observer === \"function\"\n ? new Observer((mutations) => this.handleMutations(mutations))\n : null;\n this.observer?.observe(root, { childList: true, subtree: true });\n }\n\n private handleMutations(mutations: MutationRecord[]): void {\n const removed: Node[] = [];\n const added: Node[] = [];\n for (let m = 0; m < mutations.length; m++) {\n const mutation = mutations[m];\n const removedNodes = mutation.removedNodes;\n // 削除された子がすべて framework の削除(消去が親に件数で印を付けた)なら record ごと飛ばし、\n // ノードごとの印には触れない\n if (removedNodes.length === 0 || !consumeObserverSkipRemovedChildren(mutation.target, removedNodes.length)) {\n for (let i = 0; i < removedNodes.length; i++) removed.push(removedNodes[i]);\n }\n const addedNodes = mutation.addedNodes;\n for (let i = 0; i < addedNodes.length; i++) added.push(addedNodes[i]);\n }\n // 走査は owner が1回だけ行い、関心 session が居る node だけを配送・contains\n // 検査へ進める。contains は O(木の深さ) なので、関心の無い node で呼ばない。\n const reconnected: IBindingInfo[] = [];\n for (const subtree of removed) {\n // framework が unmount した削除サブツリーは binding を明示 dispose 済みなので\n // observer 側の冗長走査(forEachInclusive で全 node を歩き handleRemovedNode を\n // 呼ぶ)を丸ごとスキップする。clear/大量 delete のホットスポット短縮。\n if (consumeObserverSkipOnRemove(subtree)) continue;\n forEachInclusive(subtree, (node) => {\n forEachInterestedSession(node, (session) => {\n if (this.root.contains(node)) return;\n session.handleRemovedNode(node);\n });\n });\n }\n for (const subtree of added) {\n // framework がマウントしたサブツリーは record が同期 activate 済みで、追加側\n // 走査の実質の仕事は connect-snapshot 待ちへの配送だけ。待ちがグローバルに\n // 無ければ丸ごとスキップする(待ちがあればマークだけ消費して従来走査に戻す)。\n if (consumeObserverSkipOnAdd(subtree) && !hasPendingObservation()) continue;\n forEachInclusive(subtree, (node) => {\n forEachInterestedSession(node, (session) => {\n if (!this.root.contains(node)) return;\n session.handleAddedNode(node, reconnected);\n });\n });\n }\n if (reconnected.length > 0) applyChangeFromBindings(reconnected);\n }\n}\n\nconst ownerByRoot = new WeakMap<IObservableRoot, BindingOwner>();\n\nfunction getBindingOwner(root: IObservableRoot): BindingOwner {\n let owner = ownerByRoot.get(root);\n if (typeof owner === \"undefined\") {\n owner = new BindingOwner(root);\n ownerByRoot.set(root, owner);\n }\n return owner;\n}\n\nfunction bindingKey(binding: IBindingInfo): string {\n // 引数は型付きの値で書き出す(要件 B9)— `defaults(0)` と `defaults('0')` を取り違えない\n const inFilters = filterListKey(binding.inFilters);\n const outFilters = filterListKey(binding.outFilters);\n return [\n binding.bindingType,\n binding.propName,\n binding.propModifiers.join(\",\"),\n binding.statePathName,\n inFilters,\n outFilters,\n binding.uuid ?? \"\",\n ].join(\"\\u0000\");\n}\n\n/*\n * 束縛が状態の台帳へ出入りする経路(行ランタイム設計 R4)。行 slot(registerRowSlot /\n * unregisterRowSlot)と record(registerAddress / runTeardowns / rebindAddresses)が同じ登録・\n * 解除をそれぞれ書き写していたのを 1 箇所にした。登録した形(アドレスか、パターンの\n * pathInfo + listIndex か)は呼び出し側の器(行の slot 配列 / record のフィールド)へ書く —\n * ここで値の組を返すと行ごとに割り当てが増えるため、器は呼び出し側に残す。\n */\n\n/** リスト行: (absolutePathInfo, listIndex) のパターン台帳へ入れる(AbsoluteStateAddress の intern を省く) */\nfunction registerPattern(binding: IBindingInfo, listIndex: IListIndex, knownRoot?: Node | null): ITreePath {\n const stateElement = getStateElement(resolveBindingRootNode(binding, knownRoot));\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n const absolutePathInfo = getTreePath(stateElement, binding.statePathInfo);\n addBindingByPattern(absolutePathInfo, listIndex, binding);\n return absolutePathInfo;\n}\n\n/** リスト行でない束縛: 絶対アドレスの台帳へ入れる */\nfunction registerAbsoluteAddress(binding: IBindingInfo, knownRoot?: Node | null): IAbsoluteStateAddress {\n const address = getAbsoluteStateAddressByBinding(binding, knownRoot);\n addBindingByAbsoluteStateAddress(address, binding);\n return address;\n}\n\n/**\n * 台帳から外す。`address` が null ならパターン登録(`pathInfo` + `listIndex`)。相対アドレス\n * (getValue)と絶対アドレス(applyChangeToFor / updatedCallback 経由の遅延 intern)のメモは\n * パターン登録でも作られうるので、どちらでも対称にクリアする。\n */\nfunction unregisterFromLedger(\n binding: IBindingInfo,\n address: IAbsoluteStateAddress | null,\n pathInfo: ITreePath | null,\n listIndex: IListIndex | null,\n): void {\n if (address !== null) {\n removeBindingByAbsoluteStateAddress(address, binding);\n } else {\n removeBindingByPattern(pathInfo!, listIndex!, binding);\n }\n clearStateAddressByBindingInfo(binding);\n clearAbsoluteStateAddressByBinding(binding);\n}\n\nfunction addRecordTeardown(record: IInternalBindingRecord, teardown: () => void): void {\n if (record.teardowns === null) {\n record.teardowns = new Set();\n }\n record.teardowns.add(teardown);\n}\n\nexport class BindingSession {\n private readonly records = new Set<IInternalBindingRecord>();\n /**\n * initializeRow で設定される行プラン。非 null のとき activate は\n * スロット整列の高速経路(activatePlanRows)を使う。\n */\n private rowPlan: IRowPlan | null = null;\n /** この session が持つ生きている行(`for` 束縛 1 つにつき session 1 つ、行は複数。設計 R3) */\n private readonly rows = new Set<IRowRecord>();\n // anchor ノードが持つ binding は大多数が 1 本なので単一値で持ち、2 本目から\n // Map(remember 経路のキー照合用)に昇格する(台帳・興味 session と同じ前例)\n private readonly knownBindingsByNode = new WeakMap<Node, IBindingInfo | Map<string, IBindingInfo>>();\n private readonly optionsByBinding = new WeakMap<IBindingInfo, IBindingOptions>();\n private readonly deferredByNode = new WeakMap<Node, Set<IDeferredDefinition>>();\n private readonly deferred = new Set<IDeferredDefinition>();\n /**\n * 最後に session ごと解体した(dispose / destroyRecords — 行の Content が消えた・プールに入った)時点の\n * 世代。これより前に生まれた record・定義待ちは、外れて戻ってきても張り直さない・適用し直さない(#352)\n */\n private disposedAt = 0;\n\n constructor(root: Node | null = null) {\n if (root !== null) this.observe(root);\n }\n\n /**\n * knownRoot: 呼び出し側が root を確定済みのときの per-binding observe 省略。\n * - undefined: 従来どおり binding ごとに anchor から root を導出して observe\n * - null: detached fragment 上(createContent)の初期化。observableRootFor が\n * 必ず null を返す状況なので observe(= getRootNode)を丸ごと省略する\n * - Node: 呼び出し側で owner 保証済み(activate 経由のみ。initialize へは未使用)\n */\n initialize(\n bindings: readonly IBindingInfo[],\n options: Partial<IBindingOptions> = {},\n knownRoot?: Node | null,\n ): IBindingInfo[] {\n const registerAddress = options.registerAddress ?? true;\n const resolvedOptions: IBindingOptions = {\n registerAddress,\n registerPathInfo: options.registerPathInfo ?? registerAddress,\n applyOnReconnect: options.applyOnReconnect ?? true,\n };\n const initialized: IBindingInfo[] = [];\n for (const candidate of bindings) {\n const binding = this.remember(candidate, resolvedOptions);\n const rowRecord = this.rowOf(binding);\n const rowSlot = rowRecord === null ? -1 : rowRecord.bindings.indexOf(binding);\n if (rowRecord !== null && rowRecord.phases[rowSlot] === SLOT_ACTIVE) {\n const row = rowRecord;\n this.observe(binding.replaceNode);\n if (resolvedOptions.registerAddress && row.addresses[rowSlot] === null && row.patternPathInfos[rowSlot] === null) {\n row.registered = true;\n this.registerRowSlot(row, rowSlot);\n }\n continue;\n }\n const existing = recordByBinding.get(binding);\n if (typeof existing !== \"undefined\" && existing.phase !== \"disposed\" && existing.phase !== \"failed\") {\n this.observe(existing.anchor);\n if (resolvedOptions.registerAddress && existing.address === null && existing.patternListIndex === null) {\n existing.options.registerAddress = true;\n this.registerAddress(existing);\n }\n if (existing.phase === \"active\") this.settleInitialRecord(existing);\n this.settleConnectedSnapshot(existing);\n continue;\n }\n this.start(binding, resolvedOptions, knownRoot);\n initialized.push(binding);\n }\n return initialized.filter((binding) => this.shouldApplyState(binding));\n }\n\n /**\n * activateContent 専用の再活性化パス。createContent 側の initialize で\n * remember 済みの binding 配列(bindingsByContent がそのまま保持する同一オブジェクト)\n * にだけ使える前提で、remember の再実行(キー照合・options マージ・興味登録)を省き、\n * 必要な仕事だけ行う: 初回活性化はアドレス登録+初期同期、pool 再利用(disposed)は\n * start による再構築、未知の binding は防御的に従来 initialize へ倒す。\n *\n * knownRoot は呼び出し側(applyChangeToFor / applyChangeToIf の apply context)が\n * 確定済みの root。owner(root ごとの MutationObserver)の保証を呼び出しあたり\n * 1 回に集約し、binding ごとの observe(= getRootNode)とアドレス解決の\n * getRootNode を丸ごと省略する。\n */\n activate(bindings: readonly IBindingInfo[], knownRoot: Node): void {\n if (isObservableRoot(knownRoot)) getBindingOwner(knownRoot);\n if (this.rowPlan !== null) {\n this.activatePlanRows(this.rowPlan, bindings, knownRoot);\n return;\n }\n for (const binding of bindings) {\n const record = recordByBinding.get(binding);\n if (typeof record !== \"undefined\" && record.session === this\n && record.phase !== \"disposed\" && record.phase !== \"failed\") {\n if (record.address === null && record.patternListIndex === null) {\n // 初回活性化(owner は冒頭で保証済み)\n record.options.registerAddress = true;\n this.registerAddress(record, knownRoot);\n }\n if (record.phase === \"active\") this.settleInitialRecord(record);\n this.settleConnectedSnapshot(record);\n continue;\n }\n const options = this.optionsByBinding.get(binding);\n if (typeof options === \"undefined\") {\n // この session で remember されていない binding(防御): 従来経路\n this.initialize([binding], { registerAddress: true, registerPathInfo: false, applyOnReconnect: false });\n continue;\n }\n // pool 再利用: record は disposed。活性化要件(アドレス登録)を昇格して再構築\n options.registerAddress = true;\n this.start(binding, options, knownRoot);\n }\n }\n\n shouldApplyState(binding: IBindingInfo): boolean {\n if (!config.enableDirectionalInitialSync) {\n if (hasInitialSyncModifier(binding)) resolveInitialSyncPolicy(binding);\n return true;\n }\n const row = this.rowOf(binding);\n if (row !== null) {\n const slot = row.bindings.indexOf(binding);\n if (slot >= 0) {\n if (!row.registered) return true;\n if (row.phases[slot] === SLOT_FAILED) return false;\n const planSlot = row.plan.slots[slot];\n if ((row.flags[slot] & FLAG_INITIAL_APPLY_DONE) === 0) {\n row.flags[slot] |= FLAG_INITIAL_APPLY_DONE;\n return planSlot.authority === \"state\";\n }\n if (planSlot.authority === \"state\") return true;\n return !planSlot.policy.outputOnly;\n }\n }\n const record = recordByBinding.get(binding);\n if (typeof record === \"undefined\" || record.session !== this) return true;\n if (!record.options.registerAddress || record.phase === \"waiting-definition\") return true;\n if (record.phase === \"failed\") return false;\n if (record.phase === \"active\") this.settleInitialRecord(record);\n // authority は初期同期のみを支配する(09 §3.6: init=element は「snapshot を\n // state へ入れる」、init=none は「次の変更から扱う」)。settle 後の最初の相談\n // = 初期 state sweep / 初回 render / deferred initial apply の選別なので\n // authority で答え、ここで初期適用を消費する。\n if (!record.initialApplyDone) {\n record.initialApplyDone = true;\n return record.resolvedAuthority === \"state\";\n }\n if (record.resolvedAuthority === \"state\") return true;\n // 定常: two-way / input member は authority と無関係に state→element を流す。\n // 恒久ブロックは (1) output-only member の契約(書き込み無意味・DCC/router の\n // conformance が依存)と (2) sync=connect の接続 snapshot が未解決の間\n //(初期競合が未決着のうちは state push が element 初期値を潰しうる)だけ。\n return !record.outputOnlyMember && !record.observationPending;\n }\n\n /**\n * **検査・テスト専用**(本番の呼び出し元は無い)。行の slot には record オブジェクトが\n * 無いので、呼ぶたびに読み取り専用の合成オブジェクトを作る — ホットパスでは使わないこと。\n *\n * `id` は record の id と同じ通し番号から取る。かつて `row.id * 64 + slot` で合成していたが、\n * 1 行が 64 スロットを超えると別の行の id と衝突した(`row.id` 自身も同じ通し番号なので、\n * 素の record の id とも衝突しうる)。台帳は WeakMap なので本番経路の割り当ては増えない。\n */\n getRecord(binding: IBindingInfo): IBindingRecord | null {\n const row = this.rowOf(binding);\n const slot = row === null ? -1 : row.bindings.indexOf(binding);\n if (row !== null && slot >= 0) {\n let ids = rowSlotIds.get(row);\n if (typeof ids === \"undefined\") {\n rowSlotIds.set(row, ids = []);\n }\n const id = ids[slot] ?? (ids[slot] = ++nextRecordId);\n return { id, info: binding, generation: row.generation, phase: SLOT_PHASE_NAMES[row.phases[slot]], teardowns: null };\n }\n const record = recordByBinding.get(binding);\n return record?.session === this ? record : null;\n }\n\n /**\n * teardown を足せるのは record を持つ束縛だけ(設計 R3)。唯一の呼び出し元は\n * `scheduleDeferredApply`(未定義カスタム要素への遅延適用)で、プラン行はカスタム要素を\n * 含み得ないため行 slot には来ない。\n */\n addTeardown(binding: IBindingInfo, teardown: () => void): boolean {\n const record = recordByBinding.get(binding);\n if (typeof record === \"undefined\" || !this.isAlive(record, record.generation)) {\n return false;\n }\n addRecordTeardown(record, teardown);\n return true;\n }\n\n deferUntilDefined(\n node: Node,\n tagName: string,\n callback: () => void,\n reject: (error: unknown) => void = () => undefined,\n ): () => void {\n const tasks = this.deferredByNode.get(node) ?? new Set<IDeferredDefinition>();\n // 済ませる(一度きり)。済んだ・取り消した task はどちらの台帳にも居ない\n const finish = (): boolean => tasks.delete(task) && this.deferred.delete(task);\n const wait = (): void => {\n const registry = getCustomElementRegistry(node);\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${tagName}>.`);\n }\n task.cancel = getDefinitionCoordinator(registry).wait(\n tagName,\n () => {\n if (!finish()) return;\n try {\n upgradeCustomElement(registry, node);\n callback();\n } catch (error) {\n reject(error);\n }\n },\n (error) => {\n if (!finish()) return;\n reject(error);\n },\n );\n };\n const task: IDeferredDefinition = {\n node,\n born: ++nextGeneration,\n cancel: null,\n arm: () => {\n // 張り済み(cancel あり)か、session の手を離れた(済んだ・取り消した・外れて下ろした)待ちは張らない\n if (task.cancel !== null || !this.deferred.has(task)) return;\n try {\n wait();\n } catch (error) {\n // 後から張る待ちの失敗は呼び出し元へ返せない\n finish();\n reject(error);\n }\n },\n };\n const root = node.getRootNode();\n // まだ DocumentFragment の中(行を fragment で組んで活性化してから差し込む経路)。fragment の中の要素は\n // 行き先の registry にまだ結び付いていない — Chromium は global registry を返し、スコープ付き registry の\n // shadow root へ差し込むとそちらに付け替わる(#357)。差し込みは同じ同期処理のうちに済むので、待つ先は\n // その後で引く。\n // 並んでいる待ちがあれば、その後ろに並ぶ(ノードごとの登録順を保つ)。two-way・イベントを\n // 付ける待ち(createContent の fragment の中で登録)より先に値の遅延適用(差し込んだ後の活性化で登録)が\n // 走ると、初期同期の前に state の値が要素へ書かれる — `#init=element` の要素の値が消える。\n // 並べた待ちは microtask 1 回でまとめて、登録順に張る\n if (armQueue !== null || root.nodeType === 11 && !isObservableRoot(root)) {\n if (armQueue === null) {\n const queue: IDeferredDefinition[] = armQueue = [];\n queueMicrotask(() => {\n armQueue = null;\n for (let i = 0; i < queue.length; i++) queue[i].arm();\n });\n }\n armQueue.push(task);\n } else {\n wait();\n }\n if (isObservableRoot(root)) getBindingOwner(root);\n addInterestedSession(node, this);\n this.deferredByNode.set(node, tasks.add(task));\n this.deferred.add(task);\n return () => {\n finish();\n task.cancel?.();\n };\n }\n\n disposeBinding(binding: IBindingInfo): void {\n const row = this.rowOf(binding);\n if (row !== null) {\n const slot = row.bindings.indexOf(binding);\n if (slot >= 0) {\n this.disposeRowSlot(row, slot);\n return;\n }\n }\n const record = recordByBinding.get(binding);\n if (typeof record === \"undefined\" || record.session !== this) return;\n this.disposeRecord(record);\n }\n\n /** 行の session か(`for` 束縛ごとに 1 つを全行で共有する形。設計 R3) */\n get isRowSession(): boolean {\n return this.rowPlan !== null;\n }\n\n get currentRowPlan(): IRowPlan | null {\n return this.rowPlan;\n }\n\n /**\n * 共有 session の行単位の解体(設計 R3)。この content の行だけを解体する。\n *\n * 生きている行が 1 つも無くなったら、行ごと session だった頃の `dispose()` と同じく\n * 残っている定義待ち(`deferUntilDefined`)を取り消す。プラン行そのものは未定義要素を\n * 持てない(`compileRowPlan` がカスタム要素のテンプレートを不適格にする)が、\n * この session に注入された待ちが残ると閉包が強参照で残り続ける。\n */\n disposeBindings(bindings: readonly IBindingInfo[]): void {\n for (let i = 0; i < bindings.length; i++) {\n this.disposeBinding(bindings[i]);\n }\n if (this.rows.size > 0) {\n return;\n }\n for (const task of Array.from(this.deferred)) {\n task.cancel?.();\n this.deferred.delete(task);\n this.deferredByNode.get(task.node)?.delete(task);\n }\n }\n\n /** 行単位の wholesale destroy(設計 R3)。行を持たない session は従来どおり全部を捨てる */\n destroyRow(bindings: readonly IBindingInfo[]): void {\n const row = bindings.length > 0 ? this.rowOf(bindings[0]) : null;\n if (row === null) {\n this.destroyRecords();\n return;\n }\n this.destroyRowRecord(row);\n this.rows.delete(row);\n }\n\n private destroyRowRecord(row: IRowRecord): void {\n for (let i = 0; i < row.bindings.length; i++) {\n const address = row.addresses[i];\n if (address !== null) {\n removeBindingByAbsoluteStateAddress(address, row.bindings[i]);\n row.addresses[i] = null;\n }\n row.phases[i] = SLOT_DISPOSED;\n }\n }\n\n dispose(): void {\n this.disposedAt = nextGeneration;\n for (const row of Array.from(this.rows)) {\n for (let i = 0; i < row.bindings.length; i++) this.disposeRowSlot(row, i);\n }\n for (const record of Array.from(this.records)) this.disposeRecord(record);\n for (const task of Array.from(this.deferred)) {\n task.cancel?.();\n this.deferred.delete(task);\n this.deferredByNode.get(task.node)?.delete(task);\n }\n }\n\n /**\n * wholesale destroy(全行クリアで teardown を GC に任せる高速経路)を適用して\n * よいか。定義待ち(DefinitionCoordinator の waiter / deferred spread タスク)は\n * 強参照 Map に閉包が残り、connect-snapshot 待ちは pending カウンタが戻らなく\n * なるため、1 つでもあれば従来経路(teardown 実行)に倒す。\n */\n canWholesaleDestroy(): boolean {\n if (this.deferred.size > 0) return false;\n if (this.records.size === 0) return true; // 空の Set の反復も割り当てるので先に抜ける\n for (const record of this.records) {\n if (record.pendingDefinitions > 0 || record.observationPending) return false;\n }\n return true;\n }\n\n /**\n * 全 record を teardown を走らせずに終端化する(canWholesaleDestroy が true の\n * content 専用)。イベント listener・loopContext・パターン台帳(listIndex キー)は\n * ノード/binding もろとも GC で崩壊する(recordByBinding 以下は全て弱参照)。\n * 例外は null-listIndex の従来台帳(record.address): キーの intern 済み\n * AbsoluteStateAddress が PathInfo キャッシュ経由で生涯生存するため GC で\n * 崩壊せず、共有エントリに残った binding が binding.node 経由で行 DOM 全体を\n * 永久リークする。ここだけ明示除去する(行イベント binding が典型で行あたり\n * 高々数件・Set.delete のみなので wholesale の速度特性は保たれる)。\n * handlerBindingRegistry のカウンタは減らないが、残るのはキー文字列と数値のみで\n * 実害はない設計(handlerBindingRegistry.ts の弱参照化コメント参照)。\n */\n destroyRecords(): void {\n this.disposedAt = nextGeneration;\n for (const row of this.rows) this.destroyRowRecord(row);\n this.rows.clear();\n for (const record of this.records) {\n if (record.address !== null) {\n removeBindingByAbsoluteStateAddress(record.address, record.info);\n record.address = null;\n }\n record.phase = \"disposed\";\n record.teardowns = null;\n }\n this.records.clear();\n }\n\n /**\n * マウントスコープ専用(Phase 2・webComponent/mountScope.ts): 全 record の台帳登録を\n * **現在のループ文脈の listIndex** で張り直す。行 content のプール再利用でコンポーネント\n * 要素が別の行に付け替わると、スコープの binding は旧行の listIndex で台帳に載ったままに\n * なる — その 1 点だけを直す(listener・record・依存グラフは張り直し不要)。\n *\n * `for` binding は lastListValue(差分の基準)を旧アドレスから新アドレスへ引き継ぐ。\n * 引き継がないと再適用が全行 add と誤認し、旧行の DOM が残ったまま新行を重ねて\n * マウントする。戻り値は再適用すべき binding(呼び出し側が applyChangeFromBindings する)。\n */\n /**\n * マウントスコープ再接続専用: アクティブな record の binding ノード(text は差し替え前の\n * comment — ループ文脈の直接エントリはこのノードに載る)を列挙する。\n * remountScopeBindings が現在の行の文脈へ張り替えるために使う。\n */\n forEachActiveBindingNode(callback: (node: Node) => void): void {\n for (const row of this.rows) {\n for (let i = 0; i < row.bindings.length; i++) {\n if (row.phases[i] === SLOT_ACTIVE) callback(row.bindings[i].node);\n }\n }\n for (const record of this.records) {\n if (record.phase !== \"active\") continue;\n callback(record.info.node);\n }\n }\n\n rebindAddresses(): IBindingInfo[] {\n const rebound: IBindingInfo[] = [];\n for (const row of this.rows) {\n for (let i = 0; i < row.bindings.length; i++) {\n if (row.phases[i] !== SLOT_ACTIVE) continue;\n if (row.addresses[i] === null && row.patternPathInfos[i] === null) continue;\n const binding = row.bindings[i];\n this.unregisterRowSlot(row, i);\n this.registerRowSlot(row, i);\n if (this.shouldApplyState(binding)) rebound.push(binding);\n }\n }\n for (const record of this.records) {\n if (record.phase !== \"active\") continue;\n const binding = record.info;\n if (record.address === null && record.patternListIndex === null) continue;\n const oldAbs = binding.bindingType === \"for\" ? getAbsoluteStateAddressByBinding(binding) : null;\n unregisterFromLedger(binding, record.address, record.patternPathInfo, record.patternListIndex);\n record.address = null;\n record.patternPathInfo = null;\n record.patternListIndex = null;\n this.registerAddress(record);\n if (oldAbs !== null) {\n const newAbs = getAbsoluteStateAddressByBinding(binding);\n // 記録の有無は has で見る(get は未記録でも `[]` を返すため、!= null 判定は\n // 常に真 — 未記録の旧アドレスから空配列を持ち込んで、新アドレスに残っていた\n // 正当な記録を潰しうる)\n if (newAbs !== oldAbs && hasLastListValueByAbsoluteStateAddress(oldAbs)) {\n setLastListValueByAbsoluteStateAddress(newAbs, getLastListValueByAbsoluteStateAddress(oldAbs));\n }\n // state 側の基準(E1)も同じ理由で引き継ぐ。記録の有無は has で見る(同上)\n if (newAbs !== oldAbs && hasStateListBaseline(oldAbs)) {\n setStateListBaseline(newAbs, getStateListBaseline(oldAbs));\n }\n }\n if (this.shouldApplyState(binding)) {\n rebound.push(binding);\n }\n }\n return rebound;\n }\n\n observe(node: Node): void {\n const root = observableRootFor(node);\n if (root === null) return;\n // owner(root ごとの MutationObserver)の存在だけ保証する。session の配送先\n // 登録は node 単位(interestedSessionsByNode)で行い、owner は session を\n // 直接は保持しない。\n getBindingOwner(root);\n }\n\n handleMutations(root: IObservableRoot, removed: readonly Node[], added: readonly Node[]): void {\n for (const subtree of removed) {\n forEachInclusive(subtree, (node) => {\n if (root.contains(node)) return;\n this.handleRemovedNode(node);\n });\n }\n const reconnected: IBindingInfo[] = [];\n for (const subtree of added) {\n forEachInclusive(subtree, (node) => {\n if (!root.contains(node)) return;\n this.handleAddedNode(node, reconnected);\n });\n }\n if (reconnected.length > 0) applyChangeFromBindings(reconnected);\n }\n\n handleRemovedNode(node: Node): void {\n const known = this.knownBindingsByNode.get(node);\n if (typeof known !== \"undefined\") {\n if (known instanceof Map) {\n for (const binding of known.values()) this.disposeBinding(binding);\n } else {\n this.disposeBinding(known);\n }\n }\n // 外れている間は registry の待ちを下ろす(戻らない要素を掴み続けない)。task はノードの台帳(弱参照)\n // にだけ残し、戻ったら handleAddedNode が張り直す(#352)\n this.deferredByNode.get(node)?.forEach((task) => {\n task.cancel?.();\n task.cancel = null;\n this.deferred.delete(task);\n });\n }\n\n /** `onError`: a caller that can report a binding failing to start again (a mount scope's re-initialization) */\n handleAddedNode(node: Node, reconnected: IBindingInfo[], onError?: (error: unknown) => void): void {\n // 外れたときに下ろした定義待ちを、今属する registry で張り直す(#352)。外れている間に session ごと\n // 解体された(行が消えた・プールに入った)待ちは張り直さない — 消えた行の文脈で展開しない\n this.deferredByNode.get(node)?.forEach((task) => {\n if (task.born <= this.disposedAt) return;\n this.deferred.add(task);\n task.arm();\n });\n const known = this.knownBindingsByNode.get(node);\n if (typeof known === \"undefined\") return;\n const bindings = known instanceof Map ? known.values() : [known];\n for (const binding of bindings) {\n const record = recordByBinding.get(binding);\n if (record?.phase === \"active\") {\n this.settleConnectedSnapshot(record);\n continue;\n }\n if (record?.phase !== \"disposed\") continue;\n const options = this.optionsByBinding.get(binding);\n if (typeof options === \"undefined\") continue;\n try {\n this.start(binding, options);\n // 要素の定義を待っていた束縛の遅延適用は、外れたときに解体と一緒に取り消された — 再接続で適用し直さない\n // 束縛(行)でも、その行が生きていれば(外れている間に session ごと解体されていなければ)適用し直し、\n // 待ちを予約し直す(#352)\n if ((options.applyOnReconnect || record.pendingDefinitions > 0 && record.generation > this.disposedAt)\n && this.shouldApplyState(binding)) reconnected.push(binding);\n } catch (error) {\n // Mutation delivery cannot surface initialization errors to a caller.\n onError?.(error);\n }\n }\n }\n\n /**\n * anchor の known 台帳を Map 形へ正規化して返す(remember のキー照合用)。\n * 単一値(プラン行 or 既存単独 binding)は実キーを引いて昇格する。\n */\n private knownMapFor(anchor: Node): Map<string, IBindingInfo> {\n const current = this.knownBindingsByNode.get(anchor);\n if (current instanceof Map) {\n return current;\n }\n const map = new Map<string, IBindingInfo>();\n if (typeof current !== \"undefined\") {\n let key = bindingKeyByBinding.get(current);\n if (typeof key === \"undefined\") {\n key = bindingKey(current);\n bindingKeyByBinding.set(current, key);\n }\n map.set(key, current);\n }\n this.knownBindingsByNode.set(anchor, map);\n return map;\n }\n\n private remember(binding: IBindingInfo, options: IBindingOptions): IBindingInfo {\n const anchor = binding.replaceNode;\n // detached fragment 上でも登録しておく(node 単位の台帳なので root 非依存)。\n // fragment 一括マウントで後から接続された行にも mutation 配送が届くようにする。\n addInterestedSession(anchor, this);\n const known = this.knownMapFor(anchor);\n let key = bindingKeyByBinding.get(binding);\n if (typeof key === \"undefined\") {\n key = bindingKey(binding);\n bindingKeyByBinding.set(binding, key);\n }\n const remembered = known.get(key);\n if (typeof remembered !== \"undefined\") {\n const rememberedOptions = this.optionsByBinding.get(remembered);\n if (typeof rememberedOptions !== \"undefined\") {\n rememberedOptions.registerAddress ||= options.registerAddress;\n rememberedOptions.registerPathInfo ||= options.registerPathInfo;\n rememberedOptions.applyOnReconnect ||= options.applyOnReconnect;\n }\n return remembered;\n }\n known.set(key, binding);\n this.optionsByBinding.set(binding, { ...options });\n return binding;\n }\n\n /**\n * RowPlan 経路の一括初期化(createContent 専用・docs/state-row-instantiation-redesign.md §3-2)。\n * プラン行の binding はこの呼び出しでのみ生成されるため remember(キー照合・\n * options マージ)を丸ごと省略し、policy/authority はテンプレート時に解決済みの\n * 値を焼き込む。options は行内共有の 1 オブジェクト(activate が\n * registerAddress を昇格するとき行内全 binding が同時に昇格する — 従来も\n * activate は全 binding を同順で昇格するため観測可能な差はない)。\n */\n initializeRow(plan: IRowPlan, bindings: readonly IBindingInfo[]): void {\n this.rowPlan = plan;\n const slots = plan.slots;\n const n = bindings.length;\n const row: IRowRecord = {\n id: ++nextRecordId,\n session: this,\n generation: ++nextGeneration,\n plan,\n bindings,\n registered: false,\n // 素の配列(Smi)。型付き配列は本体と backing store で 1 本あたり 100 B を超え、cold の\n // 生成では行ごとの割り当ての上位に出た(設計 R5)\n phases: new Array<number>(n).fill(SLOT_ACTIVE),\n flags: new Array<number>(n).fill(0),\n addresses: new Array<IAbsoluteStateAddress | null>(n).fill(null),\n patternPathInfos: new Array<ITreePath | null>(n).fill(null),\n patternListIndexes: new Array<IListIndex | null>(n).fill(null),\n };\n this.rows.add(row);\n for (let i = 0; i < n; i++) {\n const binding = bindings[i];\n const anchor = binding.replaceNode;\n addInterestedSession(anchor, this);\n this.addKnownRowBinding(anchor, binding, i);\n rowByBinding.set(binding, row);\n if (slots[i].isEvent) {\n // 印は `attachEventHandler` の**戻り値**で立てる。今は `structural/rowPlan.ts` の\n // 名前空間除外によって `slot.isEvent` ⟺ `isDomEventBinding` が成り立っているが、\n // そこが緩んだ瞬間に「張っていないのに張った印」が立ち、detach が空振りする\n let attached = false;\n try {\n attached = attachEventHandler(binding);\n } catch (error) {\n row.phases[i] = SLOT_FAILED;\n throw error;\n }\n if (attached) row.flags[i] |= FLAG_EVENT_ATTACHED;\n }\n // 非 event スロットはプラン適格性により双方向不能・radio/checkbox 不能・\n // token 配線不能が確定しているため attach 系を一切呼ばない\n }\n }\n\n /**\n * プラン行の活性化(activate の高速経路)。bindings は initializeRow と同一の\n * スロット整列配列(bindingsByContent がそのまま保持)である前提。\n * プラン行の record は policy/authority 解決済み・observable なし・\n * connect-snapshot なしが構造的に保証されているため、settleInitialRecord /\n * settleConnectedSnapshot の呼び出し自体を省略できる。\n * プール再利用(disposed/failed)では record オブジェクトを再利用し、\n * 世代だけ進めて listener attach とアドレス登録をやり直す(record 再割当なし)。\n */\n private activatePlanRows(plan: IRowPlan, bindings: readonly IBindingInfo[], knownRoot: Node): void {\n const row = bindings.length > 0 ? this.rowOf(bindings[0]) : null;\n if (row === null || row.bindings !== bindings) {\n // この session の行でない binding 配列(防御): 従来経路\n for (const binding of bindings) {\n this.initialize([binding], { registerAddress: true, registerPathInfo: false, applyOnReconnect: false });\n }\n return;\n }\n row.registered = true;\n const slots = plan.slots;\n let revived = false;\n for (let i = 0; i < bindings.length; i++) {\n if (row.phases[i] !== SLOT_ACTIVE) {\n // pool 再利用: 世代だけ進めて listener attach とアドレス登録をやり直す\n if (!revived) {\n row.generation = ++nextGeneration;\n revived = true;\n this.rows.add(row);\n }\n row.phases[i] = SLOT_ACTIVE;\n row.flags[i] = 0;\n if (slots[i].isEvent) {\n let attached = false;\n try {\n attached = attachEventHandler(bindings[i]);\n } catch (error) {\n row.phases[i] = SLOT_FAILED;\n this.runRowSlotTeardowns(row, i);\n throw error;\n }\n if (attached) row.flags[i] |= FLAG_EVENT_ATTACHED;\n }\n this.registerRowSlot(row, i, knownRoot);\n continue;\n }\n if (row.addresses[i] === null && row.patternPathInfos[i] === null) {\n // 初回活性化\n this.registerRowSlot(row, i, knownRoot);\n }\n }\n }\n\n private rowOf(binding: IBindingInfo): IRowRecord | null {\n const row = rowByBinding.get(binding);\n return typeof row !== \"undefined\" && row.session === this ? row : null;\n }\n\n private registerRowSlot(row: IRowRecord, slot: number, knownRoot?: Node | null): void {\n if (row.addresses[slot] !== null || row.patternPathInfos[slot] !== null) return;\n const binding = row.bindings[slot];\n const listIndex = getListIndexByBindingInfo(binding);\n if (listIndex !== null) {\n row.patternPathInfos[slot] = registerPattern(binding, listIndex, knownRoot);\n row.patternListIndexes[slot] = listIndex;\n } else {\n row.addresses[slot] = registerAbsoluteAddress(binding, knownRoot);\n }\n // registerPathInfo は行オプションで常に false\n }\n\n private unregisterRowSlot(row: IRowRecord, slot: number): void {\n const address = row.addresses[slot];\n const pathInfo = row.patternPathInfos[slot];\n if (address === null && pathInfo === null) return;\n // 外せなかった(台帳の throw)ときは器を残す: 後で生き返った行が登録し直さないように\n unregisterFromLedger(row.bindings[slot], address, pathInfo, row.patternListIndexes[slot]);\n row.addresses[slot] = null;\n row.patternPathInfos[slot] = null;\n row.patternListIndexes[slot] = null;\n }\n\n private disposeRowSlot(row: IRowRecord, slot: number): void {\n if (row.phases[slot] === SLOT_DISPOSED) return;\n row.phases[slot] = SLOT_DISPOSED;\n this.runRowSlotTeardowns(row, slot);\n for (let i = 0; i < row.phases.length; i++) {\n if (row.phases[i] === SLOT_ACTIVE) return;\n }\n this.rows.delete(row);\n }\n\n private runRowSlotTeardowns(row: IRowRecord, slot: number): void {\n try {\n this.unregisterRowSlot(row, slot);\n } catch {\n // Cleanup is best-effort; one faulty resource must not retain the rest.\n }\n if ((row.flags[slot] & FLAG_EVENT_ATTACHED) !== 0) {\n row.flags[slot] &= ~FLAG_EVENT_ATTACHED;\n try {\n detachEventHandler(row.bindings[slot]);\n } catch {\n // Cleanup is best-effort.\n }\n }\n }\n\n private addKnownRowBinding(anchor: Node, binding: IBindingInfo, slotIndex: number): void {\n const current = this.knownBindingsByNode.get(anchor);\n if (typeof current === \"undefined\") {\n this.knownBindingsByNode.set(anchor, binding);\n return;\n }\n // 同一 anchor に複数スロット(複数エントリの data-wcs): Map へ昇格。\n // プラン行はキー照合されないため添字ベースの合成キーで一意性だけ担保する\n if (current instanceof Map) {\n current.set(\"@plan:\" + slotIndex, binding);\n return;\n }\n const map = new Map<string, IBindingInfo>();\n map.set(\"@plan:first\", current);\n map.set(\"@plan:\" + slotIndex, binding);\n this.knownBindingsByNode.set(anchor, map);\n }\n\n private start(binding: IBindingInfo, options: IBindingOptions, knownRoot?: Node | null): void {\n replaceToReplaceNode(binding);\n const recordOptions = this.optionsByBinding.get(binding) ?? { ...options };\n const record: IInternalBindingRecord = {\n id: ++nextRecordId,\n info: binding,\n generation: ++nextGeneration,\n phase: \"discovered\",\n teardowns: null,\n session: this,\n anchor: binding.replaceNode,\n options: recordOptions,\n address: null,\n patternPathInfo: null,\n patternListIndex: null,\n pendingDefinitions: 0,\n initialPolicy: null,\n resolvedAuthority: null,\n initialSettled: false,\n initialApplyDone: false,\n outputOnlyMember: false,\n observationPending: false,\n eventSequence: 0,\n hasProducerValue: false,\n producerValue: undefined,\n eventAttached: false,\n twowayAttached: false,\n };\n recordByBinding.set(binding, record);\n this.records.add(record);\n // knownRoot が渡されたときは observe を省略する(null = detached fragment 上で\n // observableRootFor が必ず null、Node = activate 冒頭で owner 保証済み)\n if (typeof knownRoot === \"undefined\") this.observe(record.anchor);\n\n try {\n record.phase = \"attaching\";\n this.attachListeners(record);\n if (record.options.registerAddress) this.registerAddress(record, knownRoot);\n if (record.pendingDefinitions === 0) record.phase = \"active\";\n } catch (error) {\n record.phase = \"failed\";\n this.runTeardowns(record);\n this.records.delete(record);\n throw error;\n }\n }\n\n private attachListeners(record: IInternalBindingRecord): void {\n const binding = record.info;\n if (attachEventHandler(binding)) {\n record.eventAttached = true;\n return;\n }\n\n if (binding.propSegments[0] === EVENT_TOKEN_NAMESPACE) {\n this.attachAfterDefinition(record, () => {\n if (attachEventTokenHandler(binding)) {\n addRecordTeardown(record, () => detachEventTokenHandler(binding));\n }\n });\n return;\n }\n\n if (attachRadioEventHandler(binding)) {\n addRecordTeardown(record, () => detachRadioEventHandler(binding));\n }\n if (attachCheckboxEventHandler(binding)) {\n addRecordTeardown(record, () => detachCheckboxEventHandler(binding));\n }\n this.attachAfterDefinition(record, () => {\n // directional initial sync の producer-value observer は twowayEventHandlerFunction\n // からのみ呼ばれる(唯一の consumer)。その handler が attach されるのは\n // isPossibleTwoWay かつ非 ro の binding だけ(attachTwowayEventHandler と同条件)\n // なので、one-way / event / eventToken / radio(非value) 等では observer は決して\n // fire しない。以前は attachListeners 冒頭で全 binding に無条件登録していたが、\n // fire しえない大多数の binding に対する setup 死荷重だった。ここへ移すことで\n // 「twoway handler が付く binding のみ observer 登録」を構造的に保証する\n // (undefined custom element は attachAfterDefinition が定義後まで遅延するので\n // isPossibleTwoWay の未定義 CE raiseError も踏まない)。\n if (\n config.enableDirectionalInitialSync\n && isPossibleTwoWay(binding.node, binding.propName)\n && binding.propModifiers.indexOf(MODIFIER_READONLY) === -1\n ) {\n const removeObserver = addTwowayValueObserver(binding.node, binding.propName, (value) => {\n if (!this.isAlive(record, record.generation)) return;\n record.eventSequence += 1;\n record.hasProducerValue = true;\n record.producerValue = value;\n });\n addRecordTeardown(record, removeObserver);\n }\n attachTwowayEventHandler(binding);\n record.twowayAttached = true;\n });\n }\n\n private attachAfterDefinition(record: IInternalBindingRecord, attach: () => void): void {\n const tagName = getCustomElement(record.info.node);\n if (tagName === null) {\n attach();\n return;\n }\n const registry = getCustomElementRegistry(record.info.node);\n if (registry === null) {\n raiseError(`CustomElementRegistry is unavailable for <${tagName}>.`);\n }\n if (typeof registry.get(tagName) !== \"undefined\") {\n attach();\n return;\n }\n\n record.phase = \"waiting-definition\";\n record.pendingDefinitions += 1;\n const generation = record.generation;\n // 待つ先の registry は deferUntilDefined が引く — 行の中身(createContent の fragment の中)は\n // 差し込んだ後の木の registry で待つ(#357)\n addRecordTeardown(record, this.deferUntilDefined(record.info.node, tagName, () => {\n if (!this.isAlive(record, generation)) return;\n attach();\n record.pendingDefinitions -= 1;\n if (record.pendingDefinitions === 0) {\n record.phase = \"active\";\n this.settleInitialRecord(record);\n }\n }, () => {\n if (!this.isAlive(record, generation)) return;\n record.phase = \"failed\";\n this.runTeardowns(record);\n this.records.delete(record);\n }));\n }\n\n private settleInitialRecord(record: IInternalBindingRecord): void {\n if (!config.enableDirectionalInitialSync || record.initialSettled || !record.options.registerAddress) return;\n record.phase = \"synchronizing\";\n try {\n const policy = resolveInitialSyncPolicy(record.info);\n const authority = resolveInitialAuthority(record.info, policy.authority);\n record.initialPolicy = policy;\n record.resolvedAuthority = authority;\n record.initialSettled = true;\n record.outputOnlyMember = policy.outputOnly;\n record.phase = \"active\";\n if (!policy.observable) return;\n if (\n policy.syncOn === \"connect\"\n && record.info.node instanceof HTMLElement\n && !record.info.node.isConnected\n ) {\n record.observationPending = true;\n // 待ちが 1 件でもある間は追加側 observer スキップを無効化する\n incrementPendingObservation();\n return;\n }\n this.readProducerSnapshot(record, policy.syncOn === \"call\");\n } catch (error) {\n record.phase = \"failed\";\n this.runTeardowns(record);\n this.records.delete(record);\n throw error;\n }\n }\n\n private readProducerSnapshot(record: IInternalBindingRecord, eventWins: boolean): void {\n if (!this.isAlive(record, record.generation)) return;\n const target = record.info.node as Node & Record<string, unknown>;\n const name = record.info.propName;\n if (!(name in target)) return;\n const sequence = record.eventSequence;\n const value = target[name];\n if (record.observationPending) {\n record.observationPending = false;\n decrementPendingObservation();\n }\n if (eventWins && record.eventSequence !== sequence) return;\n record.hasProducerValue = true;\n record.producerValue = value;\n if (record.resolvedAuthority === \"element\") {\n commitProducerValue(record.info, value);\n }\n }\n\n private settleConnectedSnapshot(record: IInternalBindingRecord): void {\n if (\n !config.enableDirectionalInitialSync\n || !record.observationPending\n || !(record.info.node instanceof HTMLElement)\n || !record.info.node.isConnected\n ) return;\n try {\n this.readProducerSnapshot(record, false);\n } catch {\n record.phase = \"failed\";\n this.runTeardowns(record);\n this.records.delete(record);\n }\n }\n\n private registerAddress(record: IInternalBindingRecord, knownRoot?: Node | null): void {\n if (record.address !== null || record.patternListIndex !== null) return;\n const binding = record.info;\n const listIndex = getListIndexByBindingInfo(binding);\n if (listIndex !== null) {\n record.patternPathInfo = registerPattern(binding, listIndex, knownRoot);\n record.patternListIndex = listIndex;\n } else {\n record.address = registerAbsoluteAddress(binding, knownRoot);\n }\n // 台帳解除は runTeardowns が record.address / pattern フィールドから\n // データ駆動で行う(クロージャ不要)\n if (!record.options.registerPathInfo) return;\n const rootNode = binding.replaceNode.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n if (binding.bindingType !== \"event\") {\n stateElement.setPathInfo(binding.statePathName, binding.bindingType);\n }\n }\n\n private isAlive(record: IInternalBindingRecord, generation: number): boolean {\n return record.generation === generation\n && recordByBinding.get(record.info) === record\n && record.phase !== \"disposed\"\n && record.phase !== \"failed\";\n }\n\n private disposeRecord(record: IInternalBindingRecord): void {\n if (record.phase === \"disposed\") return;\n record.phase = \"disposed\";\n this.runTeardowns(record);\n this.records.delete(record);\n }\n\n private runTeardowns(record: IInternalBindingRecord): void {\n // runTeardowns は record の終端(disposed / failed)でのみ呼ばれる。未消化の\n // connect-snapshot 待ちが残っていれば必ずカウンタを戻す(スキップ再有効化)。\n if (record.observationPending) {\n record.observationPending = false;\n decrementPendingObservation();\n }\n const binding = record.info;\n // データ駆動の後始末(従来はクロージャで積んでいた頻出3種)。実行順は従来の\n // 逆順実行と同じ: アドレス台帳解除(最後に積まれていた)→ 双方向 detach →\n // 希少クロージャ群(逆順)→ イベント detach。各 detach は互いに独立した資源を\n // 対象とするため、この順序で意味論は変わらない。\n if (record.address !== null || record.patternListIndex !== null) {\n try {\n unregisterFromLedger(binding, record.address, record.patternPathInfo, record.patternListIndex);\n record.address = null;\n record.patternPathInfo = null;\n record.patternListIndex = null;\n } catch {\n // Cleanup is best-effort; one faulty resource must not retain the rest.\n }\n }\n if (record.twowayAttached) {\n record.twowayAttached = false;\n try {\n detachTwowayEventHandler(binding);\n } catch {\n // Cleanup is best-effort.\n }\n }\n if (record.teardowns !== null) {\n const teardowns = Array.from(record.teardowns).reverse();\n record.teardowns = null;\n for (const teardown of teardowns) {\n try {\n teardown();\n } catch {\n // Cleanup is best-effort; one faulty resource must not retain the rest.\n }\n }\n }\n if (record.eventAttached) {\n record.eventAttached = false;\n try {\n detachEventHandler(binding);\n } catch {\n // Cleanup is best-effort.\n }\n }\n }\n}\n\nexport function getOrCreateBindingSession(root: Node): BindingSession {\n let session = sessionByRoot.get(root);\n if (typeof session === \"undefined\") {\n session = new BindingSession(root);\n sessionByRoot.set(root, session);\n }\n return session;\n}\n\nexport function getBindingSession(binding: IBindingInfo): BindingSession | null {\n return recordByBinding.get(binding)?.session ?? rowByBinding.get(binding)?.session ?? null;\n}\n\n/**\n * 要素の定義を待って、まだ two-way・イベントを付けていない(初期同期もしていない)束縛か。\n * `applyChange` はこの間、要素がもう定義済みに見えても値を直接書かず、定義待ちの後ろへ回す(#357)。\n */\nexport function isWaitingDefinition(binding: IBindingInfo): boolean {\n return recordByBinding.get(binding)?.phase === \"waiting-definition\";\n}\n","import { IBindingInfo } from \"../types.js\";\n\nexport function replaceToReplaceNode(bindingInfo: IBindingInfo): void {\n const node = bindingInfo.node;\n const replaceNode = bindingInfo.replaceNode;\n if (node === replaceNode) {\n return;\n }\n if (node.parentNode === null) {\n // already replaced\n return;\n }\n node.parentNode.replaceChild(replaceNode, node);\n}\n","/**\n * core/componentApplyHooks.ts — カスタム要素のプロパティ束縛の受け口(設計案 S5)。\n *\n * `bind-component` の機能(webComponent/bindComponentLifecycle.ts)が install で置く。apply 側\n * (apply/applyChange.ts・apply/applyChangeToProperty.ts)は、置かれていなければカスタム要素への\n * 束縛も素のプロパティ書き込みとして扱い、何も控えない — 控えの読み手は bind-component の中にしか居ない。\n */\n\nexport interface IComponentApplyHooks {\n /** `bind-component` の配線が完了した (要素, state プロパティ)。値を運ばない通知チャネルへ切り替える */\n isComplete(element: Element, stateProp: string): boolean;\n /** 宣言済み・未完了。完了前の初期適用は書かない */\n isDeclared(element: Element, stateProp: string): boolean;\n /** 完了前の丸ごと書き込み(`state: user`)が置き換える作者のオブジェクトを控える */\n rememberOverwrittenObject(element: Element, prop: string, previous: object): void;\n /** 完了前の部分書き込み(`state.theme: theme`)が作者のオブジェクトに作ったキーを控える */\n recordInjectedKey(element: Element, prop: string, key: string): void;\n /** 完了前の部分書き込みが上書きする作者の既存キーの値を控える */\n rememberOverwrittenValue(element: Element, prop: string, key: string, previous: unknown): void;\n}\n\n/** 置かれていなければ null(apply 側は判定 1 回で素の書き込みに倒す) */\nexport let componentApplyHooks: IComponentApplyHooks | null = null;\n\n/** 機能の install が呼ぶ(冪等 — 置き換え) */\nexport function setComponentApplyHooks(hooks: IComponentApplyHooks | null): void {\n componentApplyHooks = hooks;\n}\n","import { IFilterInfo } from \"../binding/types.js\";\n\nexport function getFilteredValue(value: any, filters: IFilterInfo[]) {\n let filteredValue = value;\n for(const filter of filters) {\n filteredValue = filter.filterFn(filteredValue);\n }\n return filteredValue;\n}\n","import { createEmptyArray } from \"../createEmptyArray\";\nimport { IBindingInfo } from \"../types\";\nimport { getFilteredValue } from \"./getFilteredValue\";\nimport { IApplyContext } from \"./types\";\n\nconst EMPTY_ARRAY = createEmptyArray<unknown>();\n\nexport function applyChangeToCheckbox(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const element = binding.node as HTMLInputElement;\n const elementValue = element.value;\n const elementFilteredValue = getFilteredValue(elementValue, binding.inFilters);\n const normalizedNewValue = Array.isArray(newValue) ? newValue : EMPTY_ARRAY;\n element.checked = normalizedNewValue.includes(elementFilteredValue);\n}\n","\nexport function createEmptyArray<T>(): Readonly<Array<T>> {\n return Object.freeze<Array<T>>([]);\n}\n","/**\n * command.<methodName>: <commandToken-path> バインディングの適用ハンドラ。\n *\n * subscribe lifecycle:\n * - 同一 binding に同じ token が再評価された場合は no-op。\n * - 異なる token が来た場合は古い subscription を解除し、新しい token に subscribe し直す。\n * 旧解除は新しい binding 妥当性検証(methodName・wcBindable.commands チェック)を\n * 通過した後に行うため、再評価が validation で失敗しても旧購読は温存される(fail-fast)。\n * - element は WeakRef で保持し、subscriber 経由で element を強参照しないようにする。\n * これにより、element が DOM から消えた後に subscriber が token._subscribers に\n * 残っていても element 本体は GC 可能。\n * - emit 時に下記いずれかなら自動で subscription を破棄する(lazy purge):\n * - WeakRef.deref() が undefined(element が既に GC 済み)\n * - element.isConnected が false(DOM から取り外されている)\n *\n * 既知の制約:\n * - emit が来なければ stale subscriber は token に残り続ける(要素が GC されても subscriber 関数自体は残る)。\n * registry は state 要素をキーにした WeakMap なので、state 要素ごと GC されたときに解放される。\n * 切断では registry を捨てない — 捨てると、ルート <wcs-state> を付け直した後の emit が\n * 購読者の居ない新しい token に届き、命令が無言で止まる(#273)。\n * element ライフサイクルに直接フックする手段が現状の binding 機構に無いため、能動的な purge は将来課題。\n */\n\nimport { isCommandToken } from \"../command/CommandToken\";\nimport { ICommandToken } from \"../command/types\";\nimport { didYouMean } from \"../errorGuidance\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration, ReadBindableResult } from \"../protocol/wcBindableReader\";\nimport { raiseError } from \"../raiseError\";\nimport { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\ninterface ICommandSubscription {\n readonly token: ICommandToken;\n readonly unsubscribe: () => void;\n readonly elementRef: WeakRef<Element>;\n}\n\nconst subscribedBindings: WeakMap<IBindingInfo, ICommandSubscription> = new WeakMap();\n\nfunction getWcBindable(element: Element): ReadBindableResult | null {\n const customTagName = getCustomElement(element);\n if (customTagName === null) {\n return null;\n }\n const customClass = getCustomElementRegistry(element)?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n raiseError(`Custom element <${customTagName}> is not defined for command binding.`);\n }\n return readBindableDeclaration(element);\n}\n\nexport function applyChangeToCommand(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n if (!isCommandToken(newValue)) {\n raiseError(`command binding requires a CommandToken value (use $command.<tokenName> with a name declared in $commandTokens).`);\n }\n const token = newValue as ICommandToken;\n\n const existing = subscribedBindings.get(binding);\n if (existing && existing.token === token) {\n return;\n }\n\n // 新しい binding 妥当性検証は、旧 subscription を解除する前に通す(fail-fast)。\n const element = binding.node as Element;\n const methodName = binding.propSegments[1];\n if (typeof methodName !== \"string\" || methodName.length === 0) {\n raiseError(`command binding requires a method name (e.g., \"command.fetch\").`);\n }\n\n const bindable = getWcBindable(element);\n if (bindable === null) {\n raiseError(`command binding requires a wc-bindable custom element. <${element.tagName.toLowerCase()}> is not wc-bindable.`);\n }\n if (!bindable.declaredCommands.has(methodName)) {\n // eventTokenHandler の property 検証と対双の did-you-mean(設計 §3)。\n raiseError(`Command \"${methodName}\" is not declared in wcBindable.commands of <${element.tagName.toLowerCase()}>.${didYouMean(methodName, bindable.declaredCommands.keys())}`);\n }\n\n // ここまで来たら旧解除して新 subscribe に切り替える。\n if (existing) {\n existing.unsubscribe();\n subscribedBindings.delete(binding);\n }\n\n const elementRef = new WeakRef(element);\n let unsubscribe: (() => void) | null = null;\n const subscriber = (...args: unknown[]): unknown => {\n const el = elementRef.deref();\n if (!el || !el.isConnected) {\n unsubscribe?.();\n subscribedBindings.delete(binding);\n return undefined;\n }\n const method = (el as unknown as Record<string, unknown>)[methodName];\n if (typeof method !== \"function\") {\n raiseError(`Method \"${methodName}\" is not a function on <${el.tagName.toLowerCase()}>.`);\n }\n return Reflect.apply(method as (...a: unknown[]) => unknown, el, args);\n };\n unsubscribe = token.subscribe(subscriber);\n subscribedBindings.set(binding, { token, unsubscribe, elementRef });\n}\n\nexport const __private__ = {\n subscribedBindings,\n};\n","import { IContent } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\n\nconst bindingsByContent: WeakMap<IContent, IBindingInfo[]> = new WeakMap();\n\nexport function getBindingsByContent(content: IContent): IBindingInfo[] {\n return bindingsByContent.get(content) ?? [];\n}\n\nexport function setBindingsByContent(content: IContent, bindings: IBindingInfo[]): void {\n bindingsByContent.set(content, bindings);\n}\n","import { IContent } from \"../structural/types\";\n\nconst nodesByContent: WeakMap<IContent, Node[]> = new WeakMap();\n\nexport function getNodesByContent(content: IContent): Node[] {\n return nodesByContent.get(content) ?? [];\n}\n\nexport function setNodesByContent(content: IContent, nodes: Node[]): void {\n nodesByContent.set(content, nodes);\n}\n","import { setLoopContextByNode } from \"../list/loopContextByNode\";\nimport { ILoopContext } from \"../list/types\";\nimport { IContent } from \"../structural/types\";\nimport { getNodesByContent } from \"./nodesByContent\";\n\nexport function bindLoopContextToContent(content: IContent, loopContext: ILoopContext | null): void {\n const nodes = getNodesByContent(content);\n for(const node of nodes) {\n setLoopContextByNode(node, loopContext);\n }\n}\n\nexport function unbindLoopContextToContent(content: IContent): void {\n const nodes = getNodesByContent(content);\n for (let i = 0; i < nodes.length; i++) { // 添字ループ(消去の窓に反復子のごみを残さない)\n setLoopContextByNode(nodes[i], null);\n }\n}\n","import { IContent } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\n\nconst indexBindingsByContent: WeakMap<IContent, IBindingInfo[]> = new WeakMap();\n\nexport function getIndexBindingsByContent(content: IContent): IBindingInfo[] {\n return indexBindingsByContent.get(content) ?? [];\n}\n\nexport function setIndexBindingsByContent(content: IContent, bindings: IBindingInfo[]): void {\n indexBindingsByContent.set(content, bindings);\n}\n","/* v8 ignore file */\nexport {};\n\ndeclare global {\n interface Set<T> {\n difference(other: Set<T>): Set<T>;\n intersection(other: Set<T>): Set<T>;\n }\n}\n\nif (!Set.prototype.difference) {\n Set.prototype.difference = function <T>(this: Set<T>, other: Set<T>): Set<T> {\n const result = new Set(this);\n for (const elem of other) {\n result.delete(elem);\n }\n return result;\n };\n}\n\nif (!Set.prototype.intersection) {\n Set.prototype.intersection = function <T>(this: Set<T>, other: Set<T>): Set<T> {\n const result = new Set<T>();\n for (const elem of other) {\n if (this.has(elem)) {\n result.add(elem);\n }\n }\n return result;\n };\n}\n","import { IAbsoluteStateAddress, IPathInfo } from \"../address/types\";\nimport { advanceRowCacheStamp } from \"../list/createListIndex\";\nimport { ICacheEntry } from \"./types\";\n\nconst cacheEntryByAbsoluteStateAddress: WeakMap<IAbsoluteStateAddress, ICacheEntry> = new WeakMap();\n\n/**\n * 同じ行の下に子孫のパスがキャッシュに載ったことのあるパス(`items.*.m.k0` を載せると `items.*.m` と\n * `items.*`)。このパスの値を無効にすると、行の印を進めて子孫の項目をまとめて外す(#389)。\n * パスの単位で state を問わない — 別の state が載せた分で印を進めても、読み直しが増えるだけ。\n */\nconst rowCacheParents: WeakSet<IPathInfo> = new WeakSet();\n\nexport function getCacheEntryByAbsoluteStateAddress(\n address: IAbsoluteStateAddress\n): ICacheEntry | null {\n return cacheEntryByAbsoluteStateAddress.get(address) ?? null;\n}\n\nexport function setCacheEntryByAbsoluteStateAddress(\n address: IAbsoluteStateAddress,\n cacheEntry: ICacheEntry | null\n): void {\n if (cacheEntry === null) {\n cacheEntryByAbsoluteStateAddress.delete(address);\n } else {\n cacheEntryByAbsoluteStateAddress.set(address, cacheEntry);\n // 行の値(ワイルドカードを含むパス)は行ごとに載る。要素の書き込み・`$postUpdate` が子のパスのキャッシュに\n // 届くように(#364):\n // - 行の下で同じ行の親になるパスに印を付ける。そのパスの値を無効にすると行の印が進み、子のパスの項目は\n // 読みで外れる(dirtyCacheEntryByAbsoluteStateAddress)。子のパスを要素パスからの静的な辺に載せると、\n // 要素の書き込みの依存ウォークの費用が行の下で読んだパスの数に比例した(#389 — 動的なキー 1 万個で\n // 1 回 約 5 ms)。\n // - 静的な辺に載せるのはリストの連なり(`items → items.*`)だけ。`for` で描いていないリストでも、リストへの\n // 代入・`$postUpdate(\"items\")` の依存ウォークが行へ届く。\n // 子のパスを読む getter へは、依存の辺が同じ行の親からも張られる(State.addDynamicDependency)。\n // 2 回目からは印の判定と登録済みのパスの判定(State.setPathInfo)1 回ずつで抜ける\n const { stateElement, pathInfo } = address.absolutePathInfo;\n if (pathInfo.wildcardCount > 0) {\n for (let parent = pathInfo.parentPathInfo;\n parent !== null && parent.wildcardCount === pathInfo.wildcardCount && !rowCacheParents.has(parent);\n parent = parent.parentPathInfo) {\n rowCacheParents.add(parent);\n }\n stateElement.setPathInfo(pathInfo.lastWildcardPath!, \"prop\", \"internal\");\n }\n }\n}\n\nexport function dirtyCacheEntryByAbsoluteStateAddress(\n address: IAbsoluteStateAddress\n): void {\n const cacheEntry = cacheEntryByAbsoluteStateAddress.get(address);\n if (cacheEntry) {\n cacheEntry.dirty = true;\n }\n // 同じ行の下に載った子孫のパスの項目もまとめて外す(#389)。無効にするのは値が変わりうるときで、その下の\n // 値も変わりうる\n if (address.listIndex !== null && rowCacheParents.has(address.absolutePathInfo.pathInfo)) {\n advanceRowCacheStamp(address.listIndex);\n }\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/transition-runner.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// transition-runner protocol — how a package that mutates the DOM hands that\n// mutation to whoever is arbitrating view transitions on the page.\n//\n// @wcstack/state and @wcstack/router must not depend on @wcstack/view-transition\n// (zero runtime dependencies, independently publishable), so the arbiter installs\n// itself on a well-known global symbol and the participants look it up lazily.\n// No arbiter installed means the mutation is invoked directly, synchronously —\n// byte-for-byte the behavior these packages had before the protocol existed.\n//\n// docs/view-transition-design.md §4 is the normative description.\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/transition-runner.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/transitionRunner.ts). Those copies are generated — do not edit them.\n\n/**\n * Global key the arbiter installs itself under. `Symbol.for` so independently\n * loaded copies of this file (two CDN bundles on one page) still agree.\n */\nexport const TRANSITION_RUNNER_KEY = Symbol.for(\"wcstack.transition-runner\");\n\n/** Who is asking. Backs the arbiter's `for=` participant gate. */\nexport type TransitionSource = \"router\" | \"state\";\n\n/** `view-transition-name` assignment policy the arbiter declares for participants. */\nexport type TransitionNaming = \"manual\" | \"auto\";\n\nexport interface IWcsTransitionRunOptions {\n /** Participant id, for the `for=` gate and for diagnostics. */\n readonly source?: string;\n /** Transition types, where the environment supports `startViewTransition({ types })`. */\n readonly types?: readonly string[];\n}\n\nexport interface IWcsTransitionRunner {\n readonly protocol: \"wcs-transition-runner\";\n /** Integer protocol version. All versions >= 1 are participant-compatible. */\n readonly version: number;\n /** `\"auto\"` licenses a participant to assign `view-transition-name` itself. */\n readonly naming: TransitionNaming;\n /** Upper bound on auto-assigned names; past it a participant stops naming. */\n readonly namingLimit: number;\n /** Whether this participant animates at all. */\n accepts(source: string): boolean;\n /**\n * Invoke `mutate` inside a view transition when one is possible.\n *\n * Contract (docs/view-transition-design.md §4):\n * - `mutate` is invoked exactly once, whatever happens to the transition.\n * - The promise resolves once `mutate` has run — never waits for the animation.\n * - When no transition is started, `mutate` runs synchronously inside `run()`.\n * - It rejects only if `mutate` threw.\n */\n run(mutate: () => void, options?: IWcsTransitionRunOptions): Promise<void>;\n}\n\n/**\n * The installed arbiter, or null when there is none, it speaks a version this\n * reader does not, or it does not accept this participant.\n *\n * Looked up on every call rather than cached: the tag can be added, removed, or\n * reconfigured at any point in a page's life, and a stale cache would either\n * animate what the author just switched off or miss what they switched on.\n */\nexport function getTransitionRunner(source: string): IWcsTransitionRunner | null {\n const candidate = (globalThis as Record<symbol, unknown>)[TRANSITION_RUNNER_KEY] as\n | IWcsTransitionRunner\n | undefined;\n if (candidate === undefined || candidate === null) return null;\n if (candidate.protocol !== \"wcs-transition-runner\") return null;\n if (typeof candidate.version !== \"number\" || candidate.version < 1) return null;\n if (typeof candidate.run !== \"function\") return null;\n if (typeof candidate.accepts !== \"function\" || !candidate.accepts(source)) return null;\n return candidate;\n}\n\n/**\n * Run `mutate` under the installed arbiter, or directly when there is none.\n *\n * Returns `undefined` in the no-arbiter case instead of a resolved promise: the\n * state drain calls this on every batch, and awaiting is a caller's choice, not\n * an allocation the common path should pay for. `await` accepts both.\n */\nexport function runTransition(\n source: string,\n mutate: () => void,\n types?: readonly string[],\n): Promise<void> | undefined {\n const runner = getTransitionRunner(source);\n if (runner === null) {\n mutate();\n return undefined;\n }\n return runner.run(mutate, { source, types });\n}\n","import { IAbsoluteStateAddress } from \"../address/types\";\nimport type { IStateElement } from \"../components/types\";\nimport { beginStateListBaselineBatch, endStateListBaselineBatch } from \"../list/stateListBaseline\";\nimport { advanceUpdateBatch } from \"./updateBatch\";\nimport { applyChangeFromBindings } from \"../apply/applyChangeFromBindings\";\nimport { peekBindingsForAddress } from \"../binding/getBindingSetByAbsoluteStateAddress\";\nimport { inSsr } from \"../config\";\nimport { MAX_PROPAGATION_HOPS, MAX_RENDER_CHAIN_DEPTH } from \"../define\";\nimport { runTransition } from \"../protocol/transitionRunner\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { IPropagationContext } from \"../propagation/types\";\nimport { IBindingInfo } from \"../types\";\n\n/**\n * drain(_applyChange)終了通知のリスナー(docs/state-streams-design.md §3-2)。\n * バッチ内の更新アドレス(AbsoluteStateAddress のインスタンス同一性で\n * dedup 済みの Set)を受け取る。stream runtime の依存駆動 restart が\n * この通知を交差判定の入力にする。\n */\nexport type UpdateBatchListener = (batch: ReadonlySet<IAbsoluteStateAddress>) => void;\n\ninterface IRegisteredBatchListener {\n readonly listener: UpdateBatchListener;\n readonly priority: number;\n}\n\nconst updateBatchListeners: IRegisteredBatchListener[] = [];\n\n/**\n * 書き込みの enqueue を見る機能(設計案 H2 の enqueue 側)。`$watch` の連鎖深さ(watch/chainDepth.ts)と\n * `on` scan の保留 reset(scan/eventReset.ts)が install で登録する。互いに独立なので順序契約は無い。\n * 登録が無ければ enqueue は配列長 0 の判定 1 回で抜ける。\n */\nexport type EnqueueListener = (absoluteAddress: IAbsoluteStateAddress) => void;\n\nconst enqueueListeners: EnqueueListener[] = [];\n\n/**\n * 描画起点の書き込み連鎖の深さ(#338・MAX_RENDER_CHAIN_DEPTH)。書き込みは enqueue の時点で 3 通りに分かれる。\n * - binding の適用(下の applyBindings)の最中: 「次のバッチはこの連鎖の続き」と印を付ける\n * (行を作るときの要素の初期同期・binding が設定したその場で要素が同期に出したイベント・`$renderedCallback` など)\n * - drain の外(作者の操作・非同期に届く I/O ノードのイベント・`$stream` の値・ハイドレーション): 次のバッチを深さ 0 から\n * 数え直す。microtask で刻む書き手(`await` の続き・待ちの無い `$stream`)が描画の書き戻しと同じバッチに\n * 乗り続けても、連鎖を伸ばさない\n * - drain 終了リスナー(`$scan` / `$watch` / `$streams` restart)の中: 伸ばしも数え直させもせず、今のバッチの\n * 深さを次のバッチへ引き継ぐ。`$watch` は自分の連鎖上限を持つので重ねて数えない。引き継がないと、描画の\n * 書き戻しを `$watch` / `$scan` が受けて書く循環(要素が `x` へ書き、`$watch` が `x` から一覧の読むキーへ書く)で、\n * リスナーの書き込みだけが載った次のバッチが深さ 0 に戻り、上限に掛からずに回り続けていた(#353)\n * 適用が書かなかったバッチの次は深さ 0 なので、一度で収まる書き戻し(行の初期同期など)は伸びない。\n */\n/** 適用中のバッチの深さ + 1。drain 終了リスナーの最中はバッチの深さ、drain の外なら -1 */\nlet applyingDepth = -1;\n/** 次に drain されるバッチの深さ */\nlet pendingDepth = 0;\n/** 次のバッチに drain の外からの書き込みがある(深さ 0 から数え直す) */\nlet pendingExternal = false;\n\n/** 機能の install が呼ぶ(冪等 — 同じ listener は 1 回だけ) */\nexport function registerEnqueueListener(listener: EnqueueListener): void {\n if (!enqueueListeners.includes(listener)) {\n enqueueListeners.push(listener);\n }\n}\n\n/**\n * drain 終了リスナーを登録する。\n *\n * `priority` の昇順に呼ばれる(同値は登録順)。機構間の実行順序\n * (`$scan` → `$watch` → `$streams` restart。前の 2 つは同じ watch リスナーの中の順序で、\n * `$scan` は畳んで書いてから `$watch` を発火する —\n * docs/state-watch-hook-design.md §3-2 層 1・docs/state-scan-design.md D11)は\n * この優先度で固定する — import 順に順序を持たせると、無関係な import 整理で\n * 静かに壊れるため。定数は define.ts の `*_LISTENER_PRIORITY` を使うこと。\n */\nexport function registerUpdateBatchListener(listener: UpdateBatchListener, priority = 0): void {\n // 挿入ソート: 同値優先度の中では登録順を保つ(find は最初の「より大きい」要素を指す)\n const index = updateBatchListeners.findIndex((registered) => registered.priority > priority);\n const entry = { listener, priority };\n if (index === -1) {\n updateBatchListeners.push(entry);\n } else {\n updateBatchListeners.splice(index, 0, entry);\n }\n}\n\n/**\n * drain 終了リスナーを解除する(テスト間の分離用)。\n */\nexport function unregisterUpdateBatchListener(listener: UpdateBatchListener): void {\n const index = updateBatchListeners.findIndex((registered) => registered.listener === listener);\n if (index !== -1) {\n updateBatchListeners.splice(index, 1);\n }\n}\n\n/**\n * 全リスナーに drain のバッチを優先度順で通知する。\n * リスナーの throw は握りつぶさない(内部バグの隠蔽防止)。\n * stream / watch 側リスナーが entry ごとに自前で try/catch する契約(設計書 §3-2)。\n */\nfunction notifyUpdateBatchListeners(batch: ReadonlySet<IAbsoluteStateAddress>): void {\n // 反復中の register / unregister(ハンドラ内の切断・再 set)に耐えるためコピーする\n for (const registered of updateBatchListeners.slice()) {\n registered.listener(batch);\n }\n}\n\n/**\n * 遷移越しの適用が失敗したときの報告。\n *\n * 遷移の中では例外を同期的に呼び出し元へ投げ返せない。今日の drain は\n * queueMicrotask の中で throw する = uncaught として観測されるので、それと同じ\n * 「loud に出す」挙動へ揃える。握り潰すと `$updatedCallback` の throw が黙って\n * 消える(README の 3 層表が定める伝播の契約が破れる)。\n */\nexport function reportDeferredApplyFailure(error: unknown): void {\n queueMicrotask(() => { throw error; });\n}\n\n/** queue に積まれる update record(address + 書き込み時点の因果 context) */\ninterface IQueuedUpdateRecord {\n readonly absoluteAddress: IAbsoluteStateAddress;\n readonly context: IPropagationContext | null;\n}\n\nclass Updater {\n private _queueUpdateRecords: IQueuedUpdateRecord[] = [];\n /**\n * 描画だけをやり直すアドレス(`enqueueRenderOnlyAddress`)。書き込みの record とは別に持つ —\n * drain 終了リスナーへ渡すバッチにも、`hasQueuedPath`(`on` scan の保留 reset の判定)にも混ぜない。\n */\n private _queueRenderOnlyAddresses: IAbsoluteStateAddress[] = [];\n constructor() {\n }\n\n enqueueAbsoluteAddress(\n absoluteAddress: IAbsoluteStateAddress,\n context: IPropagationContext | null = null,\n ): void {\n // 書き込みの時点を見る機能(`$watch` の連鎖のマーク・`on` scan の `resetOn` の保留)。\n // install されていなければ配列長 0 の判定 1 回\n for (let i = 0; i < enqueueListeners.length; i++) {\n enqueueListeners[i](absoluteAddress);\n }\n // 描画連鎖の印(上の applyingDepth の説明)\n if (applyingDepth > pendingDepth) {\n pendingDepth = applyingDepth;\n }\n if (applyingDepth < 0) {\n pendingExternal = true;\n }\n const requireStartProcess = this._isQueueEmpty();\n this._queueUpdateRecords.push({ absoluteAddress, context });\n if (requireStartProcess) {\n this._scheduleDrain();\n }\n }\n\n /**\n * 描画だけをやり直させる(#4)。値を書いたわけではないので、書き込みの着地としては扱わない —\n * binding の適用には載せるが、drain 終了リスナー(`$scan` / `$watch` / `$streams` restart)へ渡す\n * バッチに入れず、`$watch` の連鎖や `on` scan の reset の印も付けない。同じバッチで同じアドレスが\n * 書き込みとしても積まれていれば、そちらが着地になる。\n * 呼び手は要素書き込みの入れ替えの完了(proxy/methods/setByAddress.ts の notifySwappedList)。\n */\n enqueueRenderOnlyAddress(absoluteAddress: IAbsoluteStateAddress): void {\n const requireStartProcess = this._isQueueEmpty();\n this._queueRenderOnlyAddresses.push(absoluteAddress);\n if (requireStartProcess) {\n this._scheduleDrain();\n }\n }\n\n private _isQueueEmpty(): boolean {\n return this._queueUpdateRecords.length === 0 && this._queueRenderOnlyAddresses.length === 0;\n }\n\n private _scheduleDrain(): void {\n // このバッチのあいだ、依存ウォークと読みが観測したリスト値は保留にする。\n // 確定は drain の finally(list/stateListBaseline.ts の頭のコメント)。\n beginStateListBaselineBatch();\n queueMicrotask(() => {\n const updateRecords = this._queueUpdateRecords;\n const renderOnlyAddresses = this._queueRenderOnlyAddresses;\n this._queueUpdateRecords = [];\n this._queueRenderOnlyAddresses = [];\n advanceUpdateBatch();\n this._applyChange(updateRecords, renderOnlyAddresses);\n });\n }\n\n /**\n * まだ drain されていない書き込み(次のバッチ)に、この state のこのパスがあるか。\n * drain の最中のキューは次のバッチの分だけになっている(_applyChange の前に差し替える)。\n * `on` scan の保留 reset を、発火しない drain で捨ててよいかの判定に使う(scan/eventReset.ts)。\n */\n hasQueuedPath(stateElement: IStateElement, path: string): boolean {\n return this._queueUpdateRecords.some((record) =>\n record.absoluteAddress.absolutePathInfo.stateElement === stateElement\n && record.absoluteAddress.absolutePathInfo.pathInfo.path === path);\n }\n\n // テスト用に公開\n testApplyChange(\n absoluteAddresses: IAbsoluteStateAddress[],\n contexts?: readonly (IPropagationContext | null)[],\n ): void {\n this._applyChange(absoluteAddresses.map((absoluteAddress, index) => ({\n absoluteAddress,\n context: contexts?.[index] ?? null,\n })));\n }\n\n private _applyChange(\n updateRecords: IQueuedUpdateRecord[],\n renderOnlyAddresses: readonly IAbsoluteStateAddress[] = [],\n ): void {\n // Note: AbsoluteStateAddress はキャッシュされているため、\n // 同一の (stateElement, address) は同じインスタンスとなり、\n // Map / Set による重複排除が正しく機能する。\n // coalescing は last-write-wins: 同じ address は最後の update の\n // (値は state 側が既に保持) context をそのまま採用する(設計書 §4.1)。\n // visitedEdges の合成や synthetic transaction への置換は行わない。\n //\n // このメソッドの反復は for...of を使わない(添字ループと Map#forEach)。drain は 1 バッチに 1 回しか\n // 呼ばれないので最適化段に上がらず、for...of は反復ごとに結果オブジェクト(Map なら [key, value] の\n // 配列も)を割り当てる。cold の 1,000 行生成では行ごとに数件の依存アドレスが積まれ、その分が\n // 生成の割り当ての 1 割近くを占めていた(設計 R5)。\n //\n // このバッチの描画連鎖の深さを消費する(キューはもう次のバッチの分なので、ここから先の印は次のバッチのもの)\n let depth = pendingExternal ? 0 : pendingDepth;\n pendingDepth = 0;\n pendingExternal = false;\n const contextByAbsoluteAddress = new Map<IAbsoluteStateAddress, IPropagationContext | null>();\n // drain 終了リスナーへ渡すのは書き込みの着地だけ。描画だけのアドレスは、この後で適用の対象に足す\n // (同じアドレスの書き込みがあれば、その context のまま着地として残る)。Map の鍵から作り直さず\n // ここで積む(鍵の iterator は反復ごとに割り当てる。順序は同じ = 最初に現れた順)\n const landedAddresses = new Set<IAbsoluteStateAddress>();\n for (let i = 0; i < updateRecords.length; i++) {\n const record = updateRecords[i];\n const previous = contextByAbsoluteAddress.get(record.absoluteAddress);\n if (\n devtoolsSink !== null\n && typeof previous !== \"undefined\" && previous !== null\n && record.context !== null\n && previous.transactionId !== record.context.transactionId\n ) {\n devtoolsSink({\n type: \"propagation:coalesced\",\n absoluteAddress: record.absoluteAddress,\n droppedTransactionId: previous.transactionId,\n winnerTransactionId: record.context.transactionId,\n });\n }\n contextByAbsoluteAddress.set(record.absoluteAddress, record.context);\n landedAddresses.add(record.absoluteAddress);\n }\n for (let i = 0; i < renderOnlyAddresses.length; i++) {\n const absoluteAddress = renderOnlyAddresses[i];\n if (!contextByAbsoluteAddress.has(absoluteAddress)) {\n contextByAbsoluteAddress.set(absoluteAddress, null);\n }\n }\n const processBindings: IBindingInfo[] = [];\n const propagationContextByBinding = new Map<IBindingInfo, IPropagationContext | null>();\n contextByAbsoluteAddress.forEach((context, absoluteAddress) => {\n if (context !== null && context.hop >= MAX_PROPAGATION_HOPS) {\n // hop 上限超過: この transaction の未処理 record だけを quarantine する。\n // 既に適用した値は戻さず、updater から例外は投げない(設計書 §4 規則 6)。\n console.error(`[@wcstack/state] propagation hop limit exceeded; update record quarantined.`, {\n path: absoluteAddress.absolutePathInfo.pathInfo.path,\n transactionId: context.transactionId,\n hop: context.hop,\n maxHops: MAX_PROPAGATION_HOPS,\n });\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"propagation:hop-limit\",\n absoluteAddress,\n transactionId: context.transactionId,\n hop: context.hop,\n });\n }\n return;\n }\n // peek: バインディングの無いアドレス(リスト置換で enqueue される中間\n // アドレス等)に空エントリを生成・蓄積しない。エントリは単一 binding\n // (通常ケース)か Set(同一アドレスに 2 本以上)のどちらか。\n // 従来台帳 → パターン台帳(リスト行)の順で引く。\n const entry = peekBindingsForAddress(absoluteAddress);\n if (entry === undefined) {\n return;\n }\n if (entry instanceof Set) {\n for(const binding of entry) {\n if (binding.replaceNode.isConnected === false) {\n // 切断されているバインディングは無視\n continue;\n }\n processBindings.push(binding);\n if (context !== null) {\n propagationContextByBinding.set(binding, context);\n }\n }\n } else if (entry.replaceNode.isConnected !== false) {\n processBindings.push(entry);\n if (context !== null) {\n propagationContextByBinding.set(entry, context);\n }\n }\n });\n // drain 終了フック: binding 適用後に dedup 済みバッチを通知する(設計書 §3-2)。\n // testApplyChange も同じ _applyChange を通るため、テストから同期に駆動できる。\n // quarantine された address も state 値は適用済みのため通知対象に含める。\n //\n // try/finally なのは、適用側が throw しても `$watch` / `$streams` restart を\n // 落とさないため。binding 1 本の失敗は applyChangeFromBindings が隔離するので\n // ここへ来るのは $updatedCallback の throw(契約どおり loud に伝播させる)等に\n // 限られるが、そのとき drain フックまで道連れにすると「機構間の順序は固定」\n // (README の 3 層表)が黙って破れる。例外は握らない = 伝播は維持する。\n try {\n const applyBindings = (): void => {\n // 遷移越しに後で走っても、このバッチの深さで印を付ける(閉包で持つ)。throw しても必ず下ろす —\n // 下ろし忘れると、以後の無関係な書き込みが全部この連鎖の続きに数えられる\n applyingDepth = depth + 1;\n try {\n // context が無い場合は従来どおり 1 引数で呼ぶ(呼び出し契約の互換維持)\n if (propagationContextByBinding.size > 0) {\n applyChangeFromBindings(processBindings, propagationContextByBinding);\n } else {\n applyChangeFromBindings(processBindings);\n }\n } finally {\n applyingDepth = -1;\n }\n };\n // View transition 参加点(docs/view-transition-design.md §7.2)。arbiter が\n // 居なければ runTransition はその場で applyBindings を呼び、undefined を返す\n // = 従来と完全に同じ同期適用。SSR では遷移そのものを持たない(G5)。\n //\n // 適用する binding が 0 本のバッチは arbiter へ渡さない。書き込みはバインドの\n // 有無に関わらず enqueue される(setByAddress)ため、headless なパス\n // (`$watch` 専用・`$streams` の内部状態・リスト置換の中間アドレス)への\n // 書き込みだけでもここへ到達する。それでページ全体をスナップショットするのは\n // 無駄なだけでなく、既定の mode=\"latest\" では「アニメーションすべき DOM 変更が\n // 無い遷移」が実行中の本物の遷移をスキップしてしまう(ルート遷移が毎回途中で\n // 切れる/active が空撃ちで振動する)。\n if (depth > MAX_RENDER_CHAIN_DEPTH && processBindings.length > 0) {\n // 描画起点の連鎖の打ち切り(#338): このバッチの binding を適用しない = 適用が書かないので連鎖が\n // 止まる。値は巻き戻さず、drain 終了リスナーには通常どおり通知する(hop 上限の quarantine と同じ\n // 姿勢)。適用するものが無いバッチは連鎖がそこで自然に終わるので報告しない — hop 上限が全部を\n // quarantine したバッチもここへは来ない(報告は 1 つの機構から 1 回)。\n // `$watch` / `$scan` を挟む循環(#353)は、適用を止めてもリスナーの書き込みが深さを引き継いで次のバッチを\n // 作る。報告は連鎖が初めて越えたバッチ(深さは 1 バッチに 1 段までしか伸びないので上限 + 1)だけにし、\n // 引き継ぐ深さを 1 つ進めて、続くバッチは報告せずに適用しない\n if (depth++ === MAX_RENDER_CHAIN_DEPTH + 1) {\n // パスで畳む(行ごとのアドレスが同じパスで並ぶと、循環しているパスが読み取りにくい)\n const paths = [...new Set(Array.from(landedAddresses, (absAddress) => absAddress.absolutePathInfo.pathInfo.path))];\n console.error(\n `[@wcstack/state] render chain depth limit exceeded; bindings for this batch were not applied.`,\n { maxDepth: MAX_RENDER_CHAIN_DEPTH, paths },\n );\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:render-chain-limit\", maxDepth: MAX_RENDER_CHAIN_DEPTH, paths });\n }\n }\n } else if (inSsr() || processBindings.length === 0) {\n applyBindings();\n } else {\n const pending = runTransition(\"state\", applyBindings);\n if (pending !== undefined) {\n pending.catch(reportDeferredApplyFailure);\n }\n }\n } finally {\n // バッチ中に溜めたリスト差分基準を確定する。notifyUpdateBatchListeners より先に\n // 置くのは、リスナー($watch / $streams restart)の中で走る書き込みが\n // 「このバッチの結果」を基準として見るべきだから。\n endStateListBaselineBatch();\n // リスナーの書き込みは描画連鎖を伸ばしも数え直させもせず、このバッチの深さを引き継ぐ(applyingDepth の\n // 説明)。リスナーは throw しない契約(内部バグだけ)なので finally で包まない — 残っても次の drain が戻す\n applyingDepth = depth;\n notifyUpdateBatchListeners(landedAddresses);\n applyingDepth = -1;\n }\n }\n\n}\n\n// コンストラクタは空でフィールド初期化だけ(純粋な割り当て)。バンドラが未使用時に落とせるよう\n// 明示する: ヘルパーだけの import(defineState / 型 / version)にランタイムを残さない\nconst updater = /*#__PURE__*/ new Updater();\n\nexport function getUpdater(): Updater {\n return updater;\n}\n\n// テスト用にprivateメソッドを公開\nexport const __private__ = {\n Updater,\n reportDeferredApplyFailure,\n};\n","/**\n * keyedDependency.ts — 鍵付き購読(`$eq(path, key)` / `$eqPath(path, keyPath)` / `$eqIndex(path, level)`)。\n *\n * 「`path` の値が鍵に等しいか」だけを知りたい getter は、`path` のパターン辺ではなく\n * その鍵の下に自分の行アドレスを登録する。`path` への書き込みは、旧値と新値の鍵に\n * 登録された行だけを dirty 化して enqueue する(パターン辺なら全行に展開されるところを\n * 高々 2 行に抑える。docs/state-next-major-tech-survey.md §10.1・§10.10、要件 N6 / D7)。\n *\n * - 行の購読は、差分がその行の listIndex を退役させた時点で落とす\n * (`dropKeyedSubscriptionsByListIndex`、list/createListDiff.ts が呼ぶ)。差分が行を\n * 復活させたときは、getter の再評価が購読を張り直す。\n * - `$eqIndex` は行の index を鍵にする(getter を index 依存には記録しない)。段によって 2 通り:\n * - 最内段(getter 自身の行の段)は行ごとの購読を持たず、リスト(listIndex 配列)単位の\n * 監視を 1 つ置く(`registerIndexWatcher`)。書き込みは `indexes[旧値]` と `indexes[新値]`\n * の行を、差分は配列が変わったとき(`moveIndexWatchers`)「最後の値の位置にいた行と来た行」\n * だけを enqueue する。移動行ごとの処理も退役時の解除も無い。\n * - 外側の段は行ごとに index を鍵にして購読し、差分が index を付け替えるとき\n * (syncListIndexes → `rekeyIndexSubscriptions`)に鍵も付け替える。移動した行は\n * 「`path` の最後の値が旧 index か新 index に等しい」ときだけ enqueue する。\n * どちらも 1 行削除で再評価されるのは高々 2 行。\n * - `path` の最後の値は登録時と書き込み時に控える(差分側の判定に使う)。書き込みが旧値を\n * 読めなかったとき(オブジェクトの書き込みは同値ガードを通らない)は、これを旧い鍵として使う\n * — 読めないまま新しい鍵の行だけを再評価すると、前に選ばれていた行が真のまま残る。\n * - `path` の祖先への書き込み(`$eq(\"sel.id\")` に対する `sel = {…}`)は `path` への書き込みを\n * 経ないので、祖先 → 配下の鍵付きパスの逆引きを持ち、旧い親と新しい親から鍵を辿って知らせる\n * (`keyedDescendantDependents`)。\n *\n * 不変条件: 同じ (アドレス, path) の購読は 1 つ。`keyByPathByAddress` が現在の鍵の正本で、\n * 台帳(`byPath`)とは常に一致する。退役した行のエントリは台帳・逆引きの両方から同時に消える。\n * 制約: Map の鍵比較は SameValueZero(`-0` と `+0` は同じ鍵、`NaN` 同士は同じ鍵)。\n */\nimport { IAbsoluteStateAddress, IPathInfo } from \"../address/types\";\nimport { getPathInfo } from \"../address/PathInfo\";\nimport { WILDCARD } from \"../define\";\nimport { createStateAddress } from \"../address/StateAddress\";\nimport { liftAddress } from \"../address/liftAddress\";\nimport { disownListIndexes, isRetiredListIndex } from \"../list/listIndexesByList\";\nimport { dirtyCacheEntryByAbsoluteStateAddress } from \"../cache/cacheEntryByAbsoluteStateAddress\";\nimport { IStateElement } from \"../components/types\";\nimport { IListIndex } from \"../list/types\";\nimport { getUpdater } from \"../updater/updater\";\n\ntype KeyMap = Map<unknown, Set<IAbsoluteStateAddress>>;\ninterface IElementLedger {\n readonly byPath: Map<string, KeyMap>;\n /** `path` の最後に見た値(登録時か書き込み時)。差分側の鍵付け替えが読む */\n readonly lastValue: Map<string, unknown>;\n /** 祖先の逆引きに載せ終えた path */\n readonly recorded: Set<string>;\n /**\n * getter の評価中に呼ばれたが、`path` が getter かその下にあるので鍵付きで購読できず、追跡付きの\n * 読みに落ちた path。台帳の動作には使わず、DevTools の要約(要件 D17)だけが読む\n */\n readonly tracked: Set<string>;\n}\ninterface IEntry {\n readonly stateElement: IStateElement;\n readonly path: string;\n readonly absAddress: IAbsoluteStateAddress;\n /** `$eqIndex` のとき、index を鍵にしている段の listIndex(それ以外は null) */\n readonly levelListIndex: IListIndex | null;\n}\nconst ledgerByElement = new WeakMap<IStateElement, IElementLedger>();\n// アドレス → (path → 現在の鍵)。再評価した getter が購読を新しい鍵へ移すための逆引き\nconst keyByPathByAddress = new WeakMap<IAbsoluteStateAddress, Map<string, unknown>>();\n// 行の listIndex にぶら下がる購読(退役時に落とす)\nconst entriesByListIndex = new WeakMap<IListIndex, IEntry[]>();\n// index を鍵にしている購読を、その index の段の listIndex から引く(付け替え用)\nconst indexKeyedByListIndex = new WeakMap<IListIndex, IEntry[]>();\n// 一度も登録が無ければ差分側のフックは Map 参照すら行わない\nlet anyRegistered = false;\n\n/**\n * リスト差分が enqueue した鍵付き購読者のアドレス。**依存ウォークの起点として使う分**。\n *\n * 書き込み起点の通知(`setByAddress` の `notifyKeyed`)は購読者から `walkDependency` を回して\n * 派生先まで届けるが(`walkKeyedDependents`)、差分起点の 2 経路(`moveIndexWatchers` /\n * `rekeyIndexSubscriptions`)は `createListDiff` から呼ばれ、そこには state proxy が無い\n * (ウォークはリスト展開で値を読む)。そこで**積むだけ**にして、proxy を持つ地点\n * (`walkDependency` の末尾)が引き取って回す。積む側は引き取り手を知らない。\n *\n * ツリー別に分ける理由が 2 つある。\n * - 引き取り手は自分のツリーしか辿れない(`walkDependency` は 1 ツリーの依存表と proxy で回る)。\n * 1 本の配列にすると、別ツリーのウォークが来たときに他人の分を取り出して**捨ててしまう**。\n * - 集合(Set)にしてあるので、引き取り手が来ないまま差分が続いても、溜まるのは\n * 「そのツリーの相異なる購読者アドレス」止まり(アドレスは intern 済み)。台帳が既に持っている\n * 分を超えない。\n *\n * `WeakMap` なので、ツリーが捨てられれば取り残しごと回収される。鍵付き購読を使わないページは\n * 積む側が `anyRegistered` で先に抜けるため、引き取り手の負担は `WeakMap#get` 1 回だけ。\n */\nconst pendingKeyedWalk = new WeakMap<IStateElement, Set<IAbsoluteStateAddress>>();\n\nfunction pushPendingKeyedWalk(absAddress: IAbsoluteStateAddress): void {\n const stateElement = absAddress.absolutePathInfo.stateElement;\n let pending = pendingKeyedWalk.get(stateElement);\n if (typeof pending === \"undefined\") {\n pendingKeyedWalk.set(stateElement, pending = new Set());\n }\n pending.add(absAddress);\n}\n\n/** このツリーに積まれた起点を取り出す(無ければ null)。引き取り手は proxy を持っている地点だけ */\nexport function takePendingKeyedWalk(stateElement: IStateElement): Set<IAbsoluteStateAddress> | null {\n const pending = pendingKeyedWalk.get(stateElement);\n if (typeof pending === \"undefined\") {\n return null;\n }\n pendingKeyedWalk.delete(stateElement);\n return pending;\n}\n\n/**\n * リスト単位の index 監視(`$eqIndex` の最内段)。行ごとの購読を持たず、書き込みは\n * `indexes[旧値]` と `indexes[新値]` の行を、差分は「最後の値の位置にいた行と来た行」だけを\n * enqueue する。差分がリストの listIndex 配列を作り直したら監視を新しい配列へ移す。\n */\ninterface IIndexWatcher {\n readonly stateElement: IStateElement;\n readonly path: string;\n /** 監視中のリストの listIndex 配列(差分で付け替わる) */\n indexes: IListIndex[];\n /** この監視を張った getter のパス(同じリストの複数 getter を 1 監視で扱う) */\n readonly getters: Set<IPathInfo>;\n}\nconst watchersByElement = new WeakMap<IStateElement, Map<string, Set<IIndexWatcher>>>();\nconst watchersByIndexes = new WeakMap<IListIndex[], IIndexWatcher[]>();\n/**\n * 祖先の listIndex → その配下で購読を持つ行の listIndex。\n *\n * 入れ子リストの**親行**が退役しても、子のリスト(`groups.*.rows`)には差分が来ない — 配列ごと\n * 捨てられるだけなので `dropKeyedSubscriptionsByListIndex` が子には呼ばれず、台帳の強参照\n * (`ledger.byPath` の `Set<IAbsoluteStateAddress>`)が残る。`IListIndex` は `parentListIndex`\n * (上向き)しか持たないので、登録の時点で祖先の側に自分を載せて逆引きを作る。\n *\n * 集合の中身は強参照だが、**祖先が生きている間だけ**(WeakMap)で、行が落ちるときは\n * `unlinkAncestors` で外れる。祖先自身が回収されれば集合ごと消える。\n */\nconst descendantRowsByAncestor = new WeakMap<IListIndex, Set<IListIndex>>();\n/** `$eqIndex` 最内段の監視 → それが載っているリストの親行(親の退役で監視ごと落とす) */\nconst watchersByOwnerListIndex = new WeakMap<IListIndex, Set<IIndexWatcher>>();\n// 祖先パス → その配下の鍵付きパス(祖先への書き込みを配下の鍵付き購読へ届ける)\nconst descendantsByElement = new WeakMap<IStateElement, Map<string, Set<string>>>();\nconst EMPTY: IAbsoluteStateAddress[] = [];\n\n/** `path` の祖先を逆引きに載せる(同じ path は 1 回だけ)。祖先の無いトップレベルの path は載せない */\nfunction recordAncestors(stateElement: IStateElement, path: string): void {\n const ledger = ledgerOf(stateElement);\n if (ledger.recorded.has(path)) {\n return;\n }\n ledger.recorded.add(path);\n const cumulativePaths = getPathInfo(path).cumulativePaths;\n if (cumulativePaths.length < 2) {\n return;\n }\n let byAncestor = descendantsByElement.get(stateElement);\n if (typeof byAncestor === \"undefined\") {\n descendantsByElement.set(stateElement, byAncestor = new Map());\n }\n for (let i = 0; i < cumulativePaths.length - 1; i++) {\n let descendants = byAncestor.get(cumulativePaths[i]);\n if (typeof descendants === \"undefined\") {\n byAncestor.set(cumulativePaths[i], descendants = new Set());\n }\n descendants.add(path);\n }\n}\n\nfunction ledgerOf(stateElement: IStateElement): IElementLedger {\n let ledger = ledgerByElement.get(stateElement);\n if (typeof ledger === \"undefined\") {\n ledgerByElement.set(stateElement, ledger = { byPath: new Map(), lastValue: new Map(), recorded: new Set(), tracked: new Set() });\n }\n return ledger;\n}\n\nfunction keyMapOf(ledger: IElementLedger, path: string): KeyMap {\n let keyMap = ledger.byPath.get(path);\n if (typeof keyMap === \"undefined\") {\n ledger.byPath.set(path, keyMap = new Map());\n }\n return keyMap;\n}\n\nfunction addToKey(keyMap: KeyMap, key: unknown, absAddress: IAbsoluteStateAddress): void {\n let set = keyMap.get(key);\n if (typeof set === \"undefined\") {\n keyMap.set(key, set = new Set());\n }\n set.add(absAddress);\n}\n\n/** 鍵から行を外し、空になった鍵は Map から消す(オブジェクトの鍵を行の退役後まで握らない) */\nfunction removeFromKey(keyMap: KeyMap, key: unknown, absAddress: IAbsoluteStateAddress): void {\n const set = keyMap.get(key)!;\n set.delete(absAddress);\n if (set.size === 0) {\n keyMap.delete(key);\n }\n}\n\n/** 台帳へ登録する。既に同じ (アドレス, path) が登録済みなら鍵を移すだけで、false を返す */\nfunction subscribe(ledger: IElementLedger, path: string, key: unknown, absAddress: IAbsoluteStateAddress): boolean {\n const keyMap = keyMapOf(ledger, path);\n let previous = keyByPathByAddress.get(absAddress);\n if (typeof previous === \"undefined\") {\n keyByPathByAddress.set(absAddress, previous = new Map());\n }\n if (previous.has(path)) {\n const oldKey = previous.get(path);\n if (!Object.is(oldKey, key)) {\n removeFromKey(keyMap, oldKey, absAddress);\n previous.set(path, key);\n addToKey(keyMap, key, absAddress);\n }\n return false;\n }\n previous.set(path, key);\n addToKey(keyMap, key, absAddress);\n return true;\n}\n\n/** 追加して「この listIndex の最初のエントリだったか」を返す(祖先への登録は行ごとに 1 回でよい) */\nfunction pushEntry(map: WeakMap<IListIndex, IEntry[]>, listIndex: IListIndex, entry: IEntry): boolean {\n const entries = map.get(listIndex);\n if (typeof entries === \"undefined\") {\n map.set(listIndex, [entry]);\n return true;\n }\n entries.push(entry);\n return false;\n}\n\n/**\n * 行を祖先の逆引きへ載せる / から外す。深さぶんのループで、鍵付き購読を持つ行の登録と退役でしか\n * 走らない(`$eq` 系を使わないページは 1 回も通らない)。\n *\n * 祖先は `listIndexes`(WeakRef 配列)ではなく `parentListIndex` を辿る。`parentListIndex` は\n * 強参照なので、自分が生きていれば祖先も生きている = `deref()` の空振りを考えなくてよく、\n * `listIndexes` getter の再構築(`reparent` の世代が変わると配列を作り直す)も踏まない。\n *\n * **不変条件: 購読を持つ行は、生きたまま別の親へ付け替えられない。** チェーンを記録するのは\n * 「その行の最初の購読」の 1 回だけで、外すのは行が落ちるときだけなので、途中で\n * `reparentListIndex`(`list/listIndexesByList.ts` の `getRepairTarget`。第 1 分岐は**旧親が\n * 退役していなくても** `home` へ付け替えうる)が走ると逆引きは古い親を指したまま残る。\n * 破れると 2 方向に壊れる:\n * (a) 旧親の退役が、**生きている**行の購読を落とす(選択が効かなくなる)\n * (b) 実親の退役が子を落とし損ねる(=この逆引きが塞いだリークの再発)\n * 破れていないことは `__tests__/dependency.keyedAncestorIndex.test.ts` が検査している\n * (記録した祖先が今も `parentListIndex` チェーン上に居るかの突き合わせ)。付け替えを\n * 許す必要が出たら、`reparentListIndex` から `unlinkAncestors` → `linkAncestors` を\n * 張り直す形にするのが構造的に強い。\n */\nfunction linkAncestors(listIndex: IListIndex): void {\n for (let ancestor = listIndex.parentListIndex; ancestor !== null; ancestor = ancestor.parentListIndex) {\n let rows = descendantRowsByAncestor.get(ancestor);\n if (typeof rows === \"undefined\") {\n descendantRowsByAncestor.set(ancestor, rows = new Set());\n }\n rows.add(listIndex);\n }\n}\n\nfunction unlinkAncestors(listIndex: IListIndex): void {\n for (let ancestor = listIndex.parentListIndex; ancestor !== null; ancestor = ancestor.parentListIndex) {\n const rows = descendantRowsByAncestor.get(ancestor);\n // 祖先ごと退役した場合は、`dropKeyedSubscriptionsByListIndex` が先に集合を外している\n if (typeof rows === \"undefined\") {\n continue;\n }\n rows.delete(listIndex);\n if (rows.size === 0) {\n descendantRowsByAncestor.delete(ancestor);\n }\n }\n}\n\nfunction record(ledger: IElementLedger, path: string, current: unknown, absAddress: IAbsoluteStateAddress, isNew: boolean, entry: IEntry): void {\n ledger.lastValue.set(path, current);\n if (!isNew) {\n return;\n }\n // 行の外(トップレベルの getter)からの登録は listIndex を持たず、退役で落ちることもない\n if (absAddress.listIndex !== null) {\n if (pushEntry(entriesByListIndex, absAddress.listIndex, entry)) {\n // この行の最初の購読。祖先の逆引きへ 1 回だけ載せる\n linkAncestors(absAddress.listIndex);\n }\n }\n if (entry.levelListIndex !== null) {\n pushEntry(indexKeyedByListIndex, entry.levelListIndex, entry);\n }\n}\n\n/** `$eq` / `$eqPath`: 評価中の getter のアドレスを `key` の下に登録する。`current` は今読んだ `path` の値 */\nexport function registerKeyedDependency(\n stateElement: IStateElement,\n path: string,\n key: unknown,\n absAddress: IAbsoluteStateAddress,\n current: unknown,\n): void {\n anyRegistered = true;\n const ledger = ledgerOf(stateElement);\n recordAncestors(stateElement, path);\n const isNew = subscribe(ledger, path, key, absAddress);\n record(ledger, path, current, absAddress, isNew, { stateElement, path, absAddress, levelListIndex: null });\n}\n\n/** `$eqIndex`: `levelListIndex.index` を鍵にして登録する。差分が index を変えたとき鍵も付け替える */\nexport function registerIndexKeyedDependency(\n stateElement: IStateElement,\n path: string,\n levelListIndex: IListIndex,\n absAddress: IAbsoluteStateAddress,\n current: unknown,\n): void {\n anyRegistered = true;\n const ledger = ledgerOf(stateElement);\n recordAncestors(stateElement, path);\n const isNew = subscribe(ledger, path, levelListIndex.index, absAddress);\n record(ledger, path, current, absAddress, isNew, { stateElement, path, absAddress, levelListIndex });\n}\n\n/** getter の評価中の `$eq` / `$eqPath` / `$eqIndex` が、`path` が getter 由来のため追跡付きの読みに落ちた */\nexport function recordTrackedKeyedPath(stateElement: IStateElement, path: string): void {\n ledgerOf(stateElement).tracked.add(path);\n}\n\n/** DevTools の要約(devtools/keyedSubscriptions.ts)が読む、この state の台帳。読むだけで変えない */\nexport interface IKeyedLedgerView {\n readonly byPath: ReadonlyMap<string, ReadonlyMap<unknown, ReadonlySet<IAbsoluteStateAddress>>>;\n readonly lastValue: ReadonlyMap<string, unknown>;\n readonly tracked: ReadonlySet<string>;\n /** `$eqIndex` の最内段のリスト単位の監視(path → 監視) */\n readonly watchers: ReadonlyMap<string, ReadonlySet<unknown>> | undefined;\n}\n\nexport function getKeyedLedgerView(stateElement: IStateElement): IKeyedLedgerView | null {\n const ledger = ledgerByElement.get(stateElement);\n if (typeof ledger === \"undefined\") {\n return null;\n }\n return { byPath: ledger.byPath, lastValue: ledger.lastValue, tracked: ledger.tracked, watchers: watchersByElement.get(stateElement) };\n}\n\nexport function hasKeyedDependents(stateElement: IStateElement, path: string): boolean {\n return ledgerByElement.get(stateElement)?.byPath.has(path) === true\n || watchersByElement.get(stateElement)?.has(path) === true;\n}\n\n/** `$eqIndex` の最内段: リスト(listIndex 配列)単位の監視を 1 つ登録し、getter のパスを足す */\nexport function registerIndexWatcher(\n stateElement: IStateElement,\n path: string,\n getterPathInfo: IPathInfo,\n indexes: IListIndex[],\n current: unknown,\n): void {\n anyRegistered = true;\n ledgerOf(stateElement).lastValue.set(path, current);\n recordAncestors(stateElement, path);\n let byPath = watchersByElement.get(stateElement);\n if (typeof byPath === \"undefined\") {\n watchersByElement.set(stateElement, byPath = new Map());\n }\n let watchers = byPath.get(path);\n if (typeof watchers === \"undefined\") {\n byPath.set(path, watchers = new Set());\n }\n let byList = watchersByIndexes.get(indexes);\n let watcher: IIndexWatcher | undefined;\n if (typeof byList === \"undefined\") {\n watchersByIndexes.set(indexes, byList = []);\n // 監視は配列に付くので、要素の書き込みはもうその場で書き換えない(listIndexesByList.ts)\n disownListIndexes(indexes);\n } else {\n watcher = byList.find((w) => w.stateElement === stateElement && w.path === path);\n }\n if (typeof watcher === \"undefined\") {\n watcher = { stateElement, path, indexes, getters: new Set() };\n byList.push(watcher);\n watchers.add(watcher);\n // 入れ子リストの監視は、そのリストを抱える**親行**に紐づける。親が退役すると\n // この配列には差分が来ない(配列ごと捨てられる)ので、ここで持ち主を控えておかないと\n // `watchersByElement` に死んだ監視が積み上がる。トップレベルのリスト(親が null)は\n // 孤児にならないので紐づけない\n const owner = indexes[0]?.parentListIndex ?? null;\n if (owner !== null) {\n let owned = watchersByOwnerListIndex.get(owner);\n if (typeof owned === \"undefined\") {\n watchersByOwnerListIndex.set(owner, owned = new Set());\n }\n owned.add(watcher);\n }\n }\n watcher.getters.add(getterPathInfo);\n}\n\nfunction watchedRowsAt(watcher: IIndexWatcher, key: unknown, out: IAbsoluteStateAddress[]): void {\n if (typeof key !== \"number\") {\n return;\n }\n const listIndex = watcher.indexes[key];\n if (typeof listIndex === \"undefined\") {\n return;\n }\n for (const getterPathInfo of watcher.getters) {\n out.push(liftAddress(watcher.stateElement, createStateAddress(getterPathInfo, listIndex)));\n }\n}\n\n/**\n * 差分がリストの listIndex 配列を `oldIndexes` → `newIndexes` に付け替えた: 監視を新しい配列へ移し、\n * `path` の最後の値の位置にいた行と来た行(違うときだけ)を dirty 化して enqueue する。\n * 同じ差分の 2 回目の呼び出し(キャッシュ命中)は旧配列に監視が無いので何もしない。\n */\nexport function moveIndexWatchers(oldIndexes: IListIndex[], newIndexes: IListIndex[]): void {\n if (!anyRegistered || oldIndexes === newIndexes) {\n return;\n }\n const watchers = watchersByIndexes.get(oldIndexes);\n if (typeof watchers === \"undefined\") {\n return;\n }\n watchersByIndexes.delete(oldIndexes);\n const existing = watchersByIndexes.get(newIndexes);\n watchersByIndexes.set(newIndexes, typeof existing === \"undefined\" ? watchers : existing.concat(watchers));\n disownListIndexes(newIndexes);\n for (const watcher of watchers) {\n watcher.indexes = newIndexes;\n const last = ledgerOf(watcher.stateElement).lastValue.get(watcher.path);\n if (typeof last !== \"number\") {\n continue;\n }\n const before = oldIndexes[last];\n const after = newIndexes[last];\n if (before === after) {\n continue;\n }\n for (const listIndex of [before, after]) {\n if (typeof listIndex === \"undefined\" || isRetiredListIndex(listIndex)) {\n continue;\n }\n for (const getterPathInfo of watcher.getters) {\n const absAddress = liftAddress(watcher.stateElement, createStateAddress(getterPathInfo, listIndex));\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n getUpdater().enqueueAbsoluteAddress(absAddress, null);\n pushPendingKeyedWalk(absAddress);\n }\n }\n }\n}\n\nfunction collect(set: Set<IAbsoluteStateAddress> | undefined, out: IAbsoluteStateAddress[]): void {\n if (typeof set === \"undefined\") {\n return;\n }\n for (const address of set) {\n out.push(address);\n }\n}\n\n/**\n * `path` への書き込み: 旧値(同値ガードが読めたとき)と新値の鍵に登録された行アドレス。\n * 控えていた最後の値が旧値と違う(旧値を読めなかった)ときは、その鍵の行も加える。\n * 新値を `path` の最後の値として控える。呼び出し側は hasKeyedDependents で門を通す。\n */\nexport function keyedDependents(\n stateElement: IStateElement,\n path: string,\n hasOldKey: boolean,\n oldKey: unknown,\n newKey: unknown,\n): IAbsoluteStateAddress[] {\n const ledger = ledgerByElement.get(stateElement);\n const keyMap = ledger?.byPath.get(path);\n const watchers = watchersByElement.get(stateElement)?.get(path);\n if (typeof ledger === \"undefined\" || (typeof keyMap === \"undefined\" && typeof watchers === \"undefined\")) {\n return EMPTY;\n }\n const hasLast = ledger.lastValue.has(path);\n const last = ledger.lastValue.get(path);\n ledger.lastValue.set(path, newKey);\n const out: IAbsoluteStateAddress[] = [];\n const newDiffers = !hasOldKey || !Object.is(oldKey, newKey);\n // 行が最後に見た値。旧値を読めなかったときに真のまま残る行はここにいる\n const lastDiffers = hasLast && (!hasOldKey || !Object.is(last, oldKey)) && !Object.is(last, newKey);\n if (typeof keyMap !== \"undefined\") {\n if (hasOldKey) {\n collect(keyMap.get(oldKey), out);\n }\n if (lastDiffers) {\n collect(keyMap.get(last), out);\n }\n if (newDiffers) {\n collect(keyMap.get(newKey), out);\n }\n }\n if (typeof watchers !== \"undefined\") {\n for (const watcher of watchers) {\n if (hasOldKey) {\n watchedRowsAt(watcher, oldKey, out);\n }\n if (lastDiffers) {\n watchedRowsAt(watcher, last, out);\n }\n if (newDiffers) {\n watchedRowsAt(watcher, newKey, out);\n }\n }\n }\n return out;\n}\n\nexport function hasKeyedDescendants(stateElement: IStateElement, path: string): boolean {\n return descendantsByElement.get(stateElement)?.has(path) === true;\n}\n\n/** `value` から `segments` を辿った値(途中がオブジェクトでなければ undefined) */\nfunction valueAt(value: unknown, segments: readonly string[]): unknown {\n let current = value;\n for (const segment of segments) {\n if (typeof current !== \"object\" || current === null) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[segment];\n }\n return current;\n}\n\n/**\n * `path`(鍵付きパスの祖先)への書き込み: 配下の鍵付きパスごとに、旧い親と新しい親から鍵を辿り、\n * その鍵の行を返す(`keyedDependents` と同じ扱い)。残りのパスにワイルドカードがあると行ごとの鍵が\n * 辿れないので、そのパスに購読している行をすべて返す。呼び出し側は hasKeyedDescendants で門を通す。\n */\nexport function keyedDescendantDependents(\n stateElement: IStateElement,\n path: string,\n oldValue: unknown,\n newValue: unknown,\n hasOldValue: boolean = true,\n): IAbsoluteStateAddress[] {\n const depth = getPathInfo(path).segments.length;\n const out: IAbsoluteStateAddress[] = [];\n for (const descendant of descendantsByElement.get(stateElement)!.get(path)!) {\n const rest = getPathInfo(descendant).segments.slice(depth);\n if (rest.includes(WILDCARD)) {\n allDependents(stateElement, descendant, out);\n continue;\n }\n // `hasOldValue` が偽なのは `$postUpdate`(in-place 変異の通知 — 旧い親がどこにも無い)。\n // 旧い鍵は台帳の `lastValue` から引かせる(`keyedDependents` の lastDiffers 経路)\n const oldKey = hasOldValue ? valueAt(oldValue, rest) : undefined;\n for (const address of keyedDependents(stateElement, descendant, hasOldValue, oldKey, valueAt(newValue, rest))) {\n out.push(address);\n }\n }\n return out;\n}\n\n/** `path` に鍵付きで購読しているすべての行 */\nfunction allDependents(stateElement: IStateElement, path: string, out: IAbsoluteStateAddress[]): void {\n const keyMap = ledgerByElement.get(stateElement)!.byPath.get(path);\n if (typeof keyMap !== \"undefined\") {\n for (const set of keyMap.values()) {\n collect(set, out);\n }\n }\n const watchers = watchersByElement.get(stateElement)?.get(path);\n if (typeof watchers !== \"undefined\") {\n for (const watcher of watchers) {\n for (let index = 0; index < watcher.indexes.length; index++) {\n watchedRowsAt(watcher, index, out);\n }\n }\n }\n}\n\nfunction removeIndexEntry(entry: IEntry): void {\n const entries = indexKeyedByListIndex.get(entry.levelListIndex!)!;\n const at = entries.indexOf(entry);\n entries.splice(at, 1);\n}\n\n/** 1 行ぶんの購読を台帳と逆引きから落とす */\nfunction dropRowSubscriptions(listIndex: IListIndex): void {\n const entries = entriesByListIndex.get(listIndex);\n if (typeof entries === \"undefined\") {\n return;\n }\n entriesByListIndex.delete(listIndex);\n // 生きている親の下で行が出入りする形(単層リストの削除)でも、祖先の集合に死んだ行を\n // 残さない\n unlinkAncestors(listIndex);\n for (const entry of entries) {\n const { stateElement, path, absAddress } = entry;\n const keys = keyByPathByAddress.get(absAddress)!;\n const key = keys.get(path);\n keys.delete(path);\n removeFromKey(ledgerByElement.get(stateElement)!.byPath.get(path)!, key, absAddress);\n if (entry.levelListIndex !== null) {\n removeIndexEntry(entry);\n }\n }\n}\n\n/** `listIndex` が親として抱えていたリストの `$eqIndex` 監視を落とす */\nfunction dropWatchersOwnedBy(listIndex: IListIndex): void {\n const owned = watchersByOwnerListIndex.get(listIndex);\n if (typeof owned === \"undefined\") {\n return;\n }\n watchersByOwnerListIndex.delete(listIndex);\n for (const watcher of owned) {\n // 台帳の不変条件で必ず引ける: 監視を入れるのは `registerIndexWatcher` だけで両方へ同時に入れ、\n // 抜くのはここと `moveIndexWatchers`(`watcher.indexes` と `watchersByIndexes` を同時に\n // 付け替える)だけ。`dropRowSubscriptions` 側と同じく `!` で不変条件を宣言する\n const byPath = watchersByElement.get(watcher.stateElement)!;\n const watchers = byPath.get(watcher.path)!;\n watchers.delete(watcher);\n if (watchers.size === 0) {\n byPath.delete(watcher.path);\n }\n const byList = watchersByIndexes.get(watcher.indexes)!;\n byList.splice(byList.indexOf(watcher), 1);\n if (byList.length === 0) {\n watchersByIndexes.delete(watcher.indexes);\n }\n }\n}\n\n/**\n * 差分が `listIndex` を退役させた: その行にぶら下がる購読を台帳と逆引きから落とす\n * (復活した行は再評価で張り直す)。\n *\n * **入れ子リストの子孫も一緒に落とす。** 親が退役しても子のリストには差分が来ない\n * (配列ごと捨てられる)ので、ここで辿らないと子行の購読が台帳に残り続ける —\n * 描画は正しい(updater が dead アドレスを弾く)が、強参照のリークであり、D17 の\n * pull API が「4 行のページで rows 20」という嘘を返す。\n * 逆引きは**全段の祖先**に載せてあるので、再帰せずここで一度に落とせる。\n */\nexport function dropKeyedSubscriptionsByListIndex(listIndex: IListIndex): void {\n if (!anyRegistered) {\n return;\n }\n dropRowSubscriptions(listIndex);\n dropWatchersOwnedBy(listIndex);\n const descendants = descendantRowsByAncestor.get(listIndex);\n if (typeof descendants === \"undefined\") {\n return;\n }\n // `unlinkAncestors` が回している間に同じ集合を触るので、先に切り離す\n descendantRowsByAncestor.delete(listIndex);\n for (const descendant of descendants) {\n dropRowSubscriptions(descendant);\n dropWatchersOwnedBy(descendant);\n descendantRowsByAncestor.delete(descendant);\n }\n}\n\n/**\n * 差分が `listIndex` の index を `oldIndex` → `newIndex` に変えた: その段を鍵にする `$eqIndex` の購読を\n * 新しい鍵へ移し、`path` の最後の値が旧 index か新 index に等しい行だけを dirty 化して enqueue する\n * (それ以外の移動行では `$eqIndex` の答えは変わらない)。syncListIndexes から、drain が差分を\n * 適用する前に呼ばれる。\n */\nexport function rekeyIndexSubscriptions(listIndex: IListIndex, oldIndex: number, newIndex: number): void {\n if (!anyRegistered) {\n return;\n }\n const entries = indexKeyedByListIndex.get(listIndex);\n if (typeof entries === \"undefined\") {\n return;\n }\n for (const { stateElement, path, absAddress } of entries) {\n const ledger = ledgerByElement.get(stateElement)!;\n const keyMap = ledger.byPath.get(path)!;\n removeFromKey(keyMap, oldIndex, absAddress);\n addToKey(keyMap, newIndex, absAddress);\n keyByPathByAddress.get(absAddress)!.set(path, newIndex);\n const last = ledger.lastValue.get(path);\n if (Object.is(last, oldIndex) || Object.is(last, newIndex)) {\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n getUpdater().enqueueAbsoluteAddress(absAddress, null);\n pushPendingKeyedWalk(absAddress);\n }\n }\n}\n\n/** テスト用: この state で `path` の下に購読されている行アドレスの数 */\nexport function countKeyedSubscriptions(stateElement: IStateElement, path: string): number {\n const keyMap = ledgerByElement.get(stateElement)?.byPath.get(path);\n if (typeof keyMap === \"undefined\") {\n return 0;\n }\n let n = 0;\n for (const set of keyMap.values()) {\n n += set.size;\n }\n return n;\n}\n","import \"../polyfills\";\nimport { createListIndex, rehomeListIndex, setListIndexValue } from \"./createListIndex\";\nimport { disownListIndexes, isHeldElsewhere, markListLent, resolveListIndexesByList, retireListIndexes, reviveListIndexes, setListIndexesByList } from \"./listIndexesByList\";\nimport { IListDiff, IListIndex } from \"./types\";\nimport { dropKeyedSubscriptionsByListIndex, moveIndexWatchers, rekeyIndexSubscriptions } from \"../dependency/keyedDependency\";\nimport { updateBatch } from \"../updater/updateBatch\";\n\nconst listDiffByOldListByNewList = new WeakMap<readonly unknown[], WeakMap<readonly unknown[], IListDiff>>();\n\nconst EMPTY_LIST = Object.freeze([]);\nconst EMPTY_SET = new Set<IListIndex>();\n/** 行はそのままで要素が替わった行(syncListIndexes・#359)。新しい配列ごとに、拾ったバッチの番号と一緒に持つ */\nconst valueChangesByList = new WeakMap<readonly unknown[], [number, IListIndex[]]>();\n\n/**\n * 新しい配列 → まだ state に居る前の配列(#362)。配列をそのまま返していた getter が写しを返すようになった\n * (TodoMVC の絞り込み all → done)ときに、getter の評価が控える(proxy/methods/getByAddress.ts)。\n * 差分は前の配列の行を新しい配列へ貸さない — 貸すと行の添字が写しの位置へ振り直され、前の配列(`todos`)の\n * 数値添字の読み書きが別の要素に着地した。前の配列は生きているので、その行を退役させもしない。\n * 前の配列は弱く持つ — 強く持つと、写しを書き直すたびに写しの鎖(とそれぞれの行)が残った(同じ外側の行の 2 つのキーに\n * 写しを書き直す 300 回で happy-dom のヒープが 58 MB → 594 MB)。state から消えた前の配列は、もう生きていない\n */\nconst livePreviousLists = new WeakMap<object, WeakRef<object>>();\n\nexport function keepPreviousList(list: object, previous: unknown): void {\n livePreviousLists.set(list, new WeakRef(Object(previous)));\n}\n\nfunction previousOf(list: object): unknown {\n return livePreviousLists.get(list)?.deref();\n}\n\nfunction getListDiff(rawOldList: readonly unknown[], rawNewList: readonly unknown[]): IListDiff | null {\n const oldList = (Array.isArray(rawOldList) && rawOldList.length > 0) ? rawOldList : EMPTY_LIST;\n const newList = (Array.isArray(rawNewList) && rawNewList.length > 0) ? rawNewList : EMPTY_LIST;\n let diffByNewList = listDiffByOldListByNewList.get(oldList);\n if (!diffByNewList) {\n return null;\n }\n return diffByNewList.get(newList) || null;\n}\n\nfunction setListDiff(oldList: readonly unknown[], newList: readonly unknown[], diff: IListDiff): void {\n let diffByNewList = listDiffByOldListByNewList.get(oldList);\n if (!diffByNewList) {\n diffByNewList = new WeakMap<readonly unknown[], IListDiff>();\n listDiffByOldListByNewList.set(oldList, diffByNewList);\n }\n diffByNewList.set(newList, diff);\n}\n/**\n * Checks if two lists are identical by comparing length and each element.\n * @param oldList - Previous list to compare\n * @param newList - New list to compare\n * @returns True if lists are identical, false otherwise\n */\nexport function isSameList(oldList: readonly unknown[], newList: readonly unknown[]): boolean {\n if (oldList.length !== newList.length) {\n return false;\n }\n\n for (let i = 0; i < oldList.length; i++) {\n if (oldList[i] !== newList[i]) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Aligns each list index's .index with its position in the new list.\n * A diff only becomes the rendered state once the updater applies it: an\n * earlier diff in the same batch (two replacements in one microtask) may have\n * moved shared indexes toward a list that never got applied, and a cache hit\n * skips recomputation entirely — so every createListDiff return re-aligns.\n * 同じ走査で、行が表している要素も憶えさせる(#256)。行を戻す普通のやり方は\n * 配列を作り直すので ListIndex も作り直される ── 「同じ行が戻ってきた」と言えるのは\n * 行オブジェクトの identity ではなく、この値だけ。\n * 憶えていた要素と違う行は、行の同一性だけを突き合わせる差分(両方の配列に台帳がある)が「変わらない」と\n * 見る行で、要素だけが替わっている(#359 — 要素の書き込みがその場で行の要素を替えた配列から、その行の元の\n * 要素を持つ前の配列へ戻した)。`valueChangeIndexes` に集め、依存ウォークに行ごと描き直させる。\n * 拾えるのは最初の呼び出しだけ(憶えた要素をここで付け直す)なので、同じバッチの間は、同じ配列への差分を\n * 取り直した呼び出しにも前の呼び出しが拾った行を渡す(`valueChangesByList`)— 同じ配列を別のパスが描く\n * (配列をそのまま返す getter の `for`)と、そのパスのリストの展開は同じ配列への差分を取り直す。\n */\nfunction syncListIndexes(diff: IListDiff, newList: readonly unknown[]): void {\n const newIndexes = diff.newIndexes;\n let changed: IListIndex[] | undefined;\n for (let i = 0; i < newIndexes.length; i++) {\n if (newIndexes[i].index !== i) {\n const oldIndex = newIndexes[i].index;\n newIndexes[i].index = i;\n // `$eqIndex` の購読は差分側で鍵を付け替える(dependency/keyedDependency.ts)\n rekeyIndexSubscriptions(newIndexes[i], oldIndex, i);\n }\n if (setListIndexValue(newIndexes[i], newList[i])) {\n (changed ??= []).push(newIndexes[i]);\n }\n }\n const kept = valueChangesByList.get(newList);\n if (kept?.[0] === updateBatch) {\n changed = changed ? kept[1].concat(changed) : kept[1];\n }\n if (changed) {\n valueChangesByList.set(newList, [updateBatch, changed]);\n }\n diff.valueChangeIndexes = changed;\n}\n\n/**\n * 行を退役させ、その行の鍵付き購読(`$eq` 系)を行と一緒に落とす。差分が捨てた行と、\n * 要素の書き込みが別の要素に差し替えた行(setByAddress の renewReplacedRow・#333)が使う。\n */\nexport function retireRows(rows: Iterable<IListIndex>): void {\n retireListIndexes(rows);\n for (const retired of rows) {\n dropKeyedSubscriptionsByListIndex(retired);\n }\n}\n\n/**\n * Creates or updates list indexes by comparing old and new lists.\n * Optimizes by reusing existing list indexes when values match.\n * @param parentListIndex - Parent list index for nested lists, or null for top-level\n * @param oldList - Previous list (will be normalized to array)\n * @param newList - New list (will be normalized to array)\n * @param oldIndexes - Array of existing list indexes to potentially reuse\n * @returns Array of list indexes for the new list\n */\nexport function createListDiff(\n parentListIndex: IListIndex | null,\n rawOldList: unknown,\n rawNewList: unknown,\n): IListDiff {\n const diff = computeListDiff(parentListIndex, rawOldList, rawNewList);\n syncListIndexes(\n diff,\n (Array.isArray(rawNewList) && rawNewList.length > 0) ? rawNewList : EMPTY_LIST,\n );\n // 捨てた行を退役、返した行を復活として記録する。台帳はこれを見て「共有」と「陳腐化」を\n // 分ける(#256)。両方を毎回の差分で付け直すので、消えない印は残らない。\n // deleteIndexSet と newIndexes は構造上交わらない。\n reviveListIndexes(diff.newIndexes);\n // 前の配列がまだ state に居る(livePreviousLists)なら、その行も `$eqIndex` の監視も前の配列のまま\n if (previousOf(rawNewList as object) !== rawOldList) {\n retireRows(diff.deleteIndexSet);\n // `$eqIndex` の最内段の監視は listIndex 配列に付く: 配列が変わったら移し、最後の値の位置の行を enqueue\n moveIndexWatchers(diff.oldIndexes, diff.newIndexes);\n }\n return diff;\n}\n\n/**\n * 前の配列の行を新しい配列へ貸した(#393 — listIndexesByList.ts の markListLent)。行集合は新しい配列を持つ親のものに\n * なるので、home もそこへ移す(#394。前の home は新しい配列を持ったことが無く、手放してもいないので、戻すと別の外側の行の\n * 配列を引いた)\n */\nfunction lendRows(oldList: readonly unknown[], rows: IListIndex[], parentListIndex: IListIndex | null): void {\n markListLent(oldList);\n if (parentListIndex !== null) {\n for (const row of rows) {\n rehomeListIndex(row, parentListIndex);\n }\n }\n}\n\nfunction computeListDiff(\n parentListIndex: IListIndex | null,\n rawOldList: unknown,\n rawNewList: unknown,\n): IListDiff {\n // Normalize inputs to arrays (handles null/undefined)\n const oldList: readonly unknown[] = (Array.isArray(rawOldList) && rawOldList.length > 0) ? rawOldList : EMPTY_LIST;\n const newList: readonly unknown[] = (Array.isArray(rawNewList) && rawNewList.length > 0) ? rawNewList : EMPTY_LIST;\n const cachedDiff = getListDiff(oldList, newList);\n // 差分を取った後で新しい配列の台帳が差し替わった(同じバッチの要素書き込みの入れ替えが揃った —\n // #335)なら、キャッシュした差分の行は古い。台帳どうしで取り直す。台帳はキャッシュが当たっても引き直す —\n // 行の親が退役した・配列を手放した外側の行のままだと、行の下の読みが別の外側の行の配列を引く(#256 / #394)\n if (cachedDiff && cachedDiff.newIndexes === resolveListIndexesByList(newList, parentListIndex)) {\n return cachedDiff;\n }\n // 台帳は 1 本の配列につき行集合 1 組(listIndexesByList.ts)。親は「行がぶら下がる親が\n // 退役していたら、この親へ付け替える」ための差し替え先として渡す(#256)。\n const oldIndexes = resolveListIndexesByList(oldList, parentListIndex) || [];\n // 新しく鋳造する行の home は鋳造した親(createListIndex の既定)。前の行集合を引き継ぐ行も、引き継いだ親を home に\n // する(lendRows)— 1 組の行集合に home は 1 つ(#256)\n let retValue: IListDiff | undefined;\n try {\n // Early return for empty list\n if (newList.length === 0) {\n return retValue = {\n oldIndexes: oldIndexes,\n newIndexes: [] as IListIndex[],\n changeIndexSet: EMPTY_SET,\n deleteIndexSet: new Set<IListIndex>(oldIndexes),\n addIndexSet: EMPTY_SET,\n };\n }\n // If old list was empty, create all new indexes\n // 前の配列がまだ state に居る(livePreviousLists)なら、その行を貸さずに新しい行を作る(#362)\n let newIndexes: IListIndex[] | null = resolveListIndexesByList(newList, parentListIndex);\n // ほかの外側の行もまだ持っている配列の行は、写しに貸さない(#393 — listIndexesByList.ts の holdersByList)。元の配列は\n // その外側の行にまだ居るので、行を退役させもしない\n if (newIndexes === null && parentListIndex !== null && isHeldElsewhere(oldList, parentListIndex)) {\n keepPreviousList(newList, oldList);\n }\n if (oldList.length === 0 || (newIndexes === null && previousOf(newList) === oldList)) {\n if (newIndexes === null) {\n newIndexes = [];\n for(let i = 0; i < newList.length; i++) {\n const newListIndex = createListIndex(parentListIndex, i);\n newIndexes.push(newListIndex);\n }\n }\n return retValue = {\n oldIndexes: oldIndexes,\n newIndexes: newIndexes,\n changeIndexSet: EMPTY_SET,\n deleteIndexSet: new Set<IListIndex>(oldIndexes),\n addIndexSet: new Set<IListIndex>(newIndexes),\n };\n }\n // If lists are identical, return existing indexes unchanged (optimization)\n // 新しい配列が別の行集合を持つなら下で行どうしを突き合わせる — 要素の書き込みは位置を新しい行にするので\n // (別の要素を書いてから元の要素へ戻す — #333)、同じ中身の配列でも行が違い、前の配列の行(退役した行を\n // 含む)を被せると、新しい配列を描いた `for` に無い行が台帳に戻る\n if (isSameList(oldList, newList) && (newIndexes ?? oldIndexes) === oldIndexes) {\n if (oldList !== newList) {\n lendRows(oldList, oldIndexes, parentListIndex);\n }\n return retValue = {\n oldIndexes: oldIndexes,\n newIndexes: oldIndexes,\n changeIndexSet: EMPTY_SET,\n deleteIndexSet: EMPTY_SET,\n addIndexSet: EMPTY_SET,\n };\n }\n if (newIndexes !== null) {\n return calcDiffIndexes(oldIndexes, newIndexes);\n }\n newIndexes = [];\n\n // Use index-based map for efficiency\n // Supports duplicate values by storing array of indexes\n const indexByValue = new Map<unknown, number[]>();\n for(let i = 0; i < oldList.length; i++) {\n const val = oldList[i];\n let indexes = indexByValue.get(val);\n if (!indexes) {\n indexes = [];\n indexByValue.set(val, indexes);\n }\n indexes.push(i);\n }\n\n // Build new indexes array by matching values with old list\n const changeIndexSet: Set<IListIndex> = new Set();\n const addIndexSet: Set<IListIndex> = new Set();\n // 前の配列の行を 1 つでも新しい配列へ貸したか(listIndexesByList.ts の markListLent・#393)\n let lent = false;\n for(let i = 0; i < newList.length; i++) {\n const newValue = newList[i];\n const existingIndexes = indexByValue.get(newValue);\n const oldIndex = existingIndexes && existingIndexes.length > 0 ? existingIndexes.shift() : undefined;\n \n if (typeof oldIndex === \"undefined\") {\n // New element\n const newListIndex = createListIndex(parentListIndex, i);\n newIndexes.push(newListIndex);\n addIndexSet.add(newListIndex);\n } else {\n // Reuse existing element\n const existingListIndex = oldIndexes[oldIndex];\n lent = true;\n // Judge position change against the old list's order (oldIndexes array\n // order), not the mutable .index — an earlier diff in the same batch\n // may have already moved .index toward a list that was never applied.\n // The .index itself is re-aligned by syncListIndexes on return.\n if (oldIndex !== i) {\n changeIndexSet.add(existingListIndex);\n }\n newIndexes.push(existingListIndex);\n }\n }\n \n if (lent) {\n lendRows(oldList, newIndexes, parentListIndex);\n }\n const deleteIndexSet: Set<IListIndex> = (new Set(oldIndexes)).difference(new Set(newIndexes));\n return retValue = {\n oldIndexes: oldIndexes,\n newIndexes: newIndexes,\n changeIndexSet: changeIndexSet,\n deleteIndexSet: deleteIndexSet,\n addIndexSet: addIndexSet,\n };\n } finally {\n if (typeof retValue !== \"undefined\") {\n setListDiff(oldList, newList, retValue);\n // 差分が両方の台帳の配列を持つので、要素の書き込みはもうその場で書き換えない(listIndexesByList.ts)\n disownListIndexes(oldIndexes);\n setListIndexesByList(newList, retValue.newIndexes);\n }\n }\n}\n\n/**\n * Diff between two lists whose listIndex ledgers both already exist.\n * Rows are joined by listIndex identity — the same key applyChangeToFor and\n * walkDependency consume the result sets with. A value-based join could mark\n * oldIndexes-side objects that are absent from newIndexes (ledgers built along\n * unconnected diff chains hold different objects for the same value); such\n * orphan markers never match the consumers' has() lookups and only pollute\n * the dirty set. Rows without shared identity are represented as add+delete.\n * 台帳に書かず・キャッシュもしない純粋な突き合わせなので、共有の記録から外れていた `for` が\n * 自分の描いた行と今の行を突き合わせるのにも使う(applyChangeToFor、#320)。\n */\nexport function calcDiffIndexes(\n oldIndexes: IListIndex[],\n newIndexes: IListIndex[],\n): IListDiff {\n const newIndexSet: Set<IListIndex> = new Set(newIndexes);\n const oldIndexSet: Set<IListIndex> = new Set(oldIndexes);\n const changeIndexSet: Set<IListIndex> = new Set();\n const addIndexSet: Set<IListIndex> = newIndexSet.difference(oldIndexSet);\n const deleteIndexSet: Set<IListIndex> = oldIndexSet.difference(newIndexSet);\n // Old positions come from the oldIndexes array order (.index may have been\n // mutated by an unapplied diff in the same batch).\n const oldPosByIndex = new Map<IListIndex, number>();\n for (let i = 0; i < oldIndexes.length; i++) {\n oldPosByIndex.set(oldIndexes[i], i);\n }\n for (let i = 0; i < newIndexes.length; i++) {\n const index = newIndexes[i];\n if (addIndexSet.has(index)) {\n continue;\n }\n if (oldPosByIndex.get(index) !== i) {\n // 位置が違うことだけを記録\n changeIndexSet.add(index);\n }\n }\n return {\n oldIndexes: oldIndexes,\n newIndexes: newIndexes,\n changeIndexSet: changeIndexSet,\n deleteIndexSet: deleteIndexSet,\n addIndexSet: addIndexSet,\n };\n}","import { IListDiff, IListIndex } from \"./types\";\n\n/**\n * Indices into `seq` whose values form a longest strictly-increasing\n * subsequence, returned in ascending order. Classic patience-sorting\n * LIS in O(n log n). `seq` values are assumed distinct (old list\n * positions are unique).\n */\nexport function longestIncreasingSubsequence(seq: number[]): number[] {\n const n = seq.length;\n // tails[k] = index into seq of the smallest tail of an increasing\n // subsequence of length k+1; prev[i] = predecessor index to rebuild the chain.\n const tails: number[] = [];\n const prev: number[] = new Array(n).fill(-1);\n for (let i = 0; i < n; i++) {\n const value = seq[i];\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (seq[tails[mid]] < value) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n if (lo > 0) {\n prev[i] = tails[lo - 1];\n }\n tails[lo] = i;\n }\n const result: number[] = [];\n let k = tails.length > 0 ? tails[tails.length - 1] : -1;\n while (k >= 0) {\n result.push(k);\n k = prev[k];\n }\n result.reverse();\n return result;\n}\n\n/**\n * Determines which reused list indexes can stay where they are when the DOM\n * is brought into the new list order.\n *\n * Returns null when the reused indexes already appear in their old relative\n * order (no inversions) — the caller's existing position guard then performs\n * no moves, so nothing extra is needed. When inversions exist, returns the\n * set of indexes forming a longest increasing subsequence of old positions:\n * leaving exactly those in place and moving every other content yields the\n * correct final order with the fewest content moves (the naive forward walk\n * otherwise cascades: a single swap of rows 2/999 in 1000 rows moves ~997\n * contents instead of 2).\n *\n * Note: IListIndex.index is already mutated to the NEW position by\n * createListDiff, so old positions must come from the oldIndexes array order.\n */\nexport function computeStableIndexSet(diff: IListDiff): ReadonlySet<IListIndex> | null {\n // No reused index changed position, or nothing was reused: relative order\n // is already correct and the walk performs no moves.\n if (diff.changeIndexSet.size === 0 || diff.addIndexSet.size === diff.newIndexes.length) {\n return null;\n }\n const oldPosByIndex = new Map<IListIndex, number>();\n for (let i = 0; i < diff.oldIndexes.length; i++) {\n oldPosByIndex.set(diff.oldIndexes[i], i);\n }\n const reused: IListIndex[] = [];\n const seq: number[] = [];\n let prevPos = -1;\n let sorted = true;\n for (const index of diff.newIndexes) {\n if (diff.addIndexSet.has(index)) {\n continue;\n }\n const pos = oldPosByIndex.get(index);\n if (pos === undefined) {\n // Invariant break (a reused index missing from oldIndexes): fall back\n // to the settle walk rather than compute a stable set from bad data.\n return null;\n }\n if (pos < prevPos) {\n sorted = false;\n }\n prevPos = pos;\n reused.push(index);\n seq.push(pos);\n }\n if (sorted) {\n return null;\n }\n const lis = longestIncreasingSubsequence(seq);\n const stable = new Set<IListIndex>();\n for (const seqIndex of lis) {\n stable.add(reused[seqIndex]);\n }\n return stable;\n}\n","import { IContent } from \"../structural/types\";\nimport type { BindingSession } from \"./BindingSession\";\n\nconst bindingSessionByContent = new WeakMap<IContent, BindingSession>();\n\nexport function getBindingSessionByContent(content: IContent): BindingSession | null {\n return bindingSessionByContent.get(content) ?? null;\n}\n\nexport function setBindingSessionByContent(content: IContent, session: BindingSession): void {\n bindingSessionByContent.set(content, session);\n}\n","import type { IContent, IRowPlan } from \"./types\";\n\n/**\n * structural/planByContent.ts — 行プランから実体化した content の逆引き(行ランタイム設計 R2)。\n *\n * プラン経路で作られた content だけがここに載る。活性化のとき、その行が「プラン行か」を\n * 1 回の WeakMap 引きで判定するためのもの(プラン初期描画の門)。\n */\nconst planByContent = new WeakMap<IContent, IRowPlan>();\n\nexport function setPlanByContent(content: IContent, plan: IRowPlan): void {\n planByContent.set(content, plan);\n}\n\nexport function getPlanByContent(content: IContent): IRowPlan | null {\n return planByContent.get(content) ?? null;\n}\n","import { applyChange, applyValueToBinding } from \"../apply/applyChange\";\nimport { IApplyContext } from \"../apply/types\";\nimport { getAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding\";\nimport { addBindingByAbsoluteStateAddress, removeBindingByAbsoluteStateAddress } from \"../binding/getBindingSetByAbsoluteStateAddress\";\nimport { getBindingsByContent } from \"../bindings/bindingsByContent\";\nimport { getBindingSessionByContent } from \"../bindings/bindingSessionByContent\";\nimport { getIndexBindingsByContent } from \"../bindings/indexBindingsByContent\";\nimport type { BindingSession } from \"../bindings/BindingSession\";\nimport { bindLoopContextToContent, unbindLoopContextToContent } from \"../bindings/bindLoopContextToContent\";\nimport { scheduleDeferredSpreads } from \"../bindings/initializeBindings\";\nimport { ILoopContext } from \"../list/types\";\nimport { getByAddressSymbol } from \"../proxy/symbols\";\nimport type { IBindingInfo } from \"../types\";\nimport { getPlanByContent } from \"./planByContent\";\nimport { IContent, IRowPlan } from \"./types\";\n\n/**\n * プラン初期描画(行ランタイム設計 R2)の下ごしらえ。\n *\n * 行の下の**素の葉**(どの接頭辞も getter でなく、tail にワイルドカードが無く、event /\n * index 束縛でもない)の slot は、行オブジェクトを proxy で 1 回読めば値が取れる。その\n * 「行のパスからの残り」をプランと行パスの組ごとに 1 回だけ作って持つ(行不変)。\n * null は「この slot はプラン初期描画に載せない」。\n */\ninterface ISlotTail {\n /** 行オブジェクトからの残りのセグメント */\n readonly tail: string[];\n /** getter 判定のための、行パスからの累積パス */\n readonly prefixes: string[];\n}\n\nconst tailsByPlan = new WeakMap<IRowPlan, Map<string, (ISlotTail | null)[]>>();\n\nfunction slotTails(plan: IRowPlan, bindings: readonly IBindingInfo[], rowPath: string): (ISlotTail | null)[] {\n let byRowPath = tailsByPlan.get(plan);\n if (typeof byRowPath === \"undefined\") {\n tailsByPlan.set(plan, byRowPath = new Map());\n }\n const cached = byRowPath.get(rowPath);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n const prefix = rowPath + \".\";\n const tails = bindings.map((binding, i) => {\n const slot = plan.slots[i];\n if (slot.isEvent || slot.isIndexBinding) {\n return null;\n }\n const path = binding.statePathInfo.path;\n if (!path.startsWith(prefix)) {\n return null;\n }\n const tail = path.slice(prefix.length).split(\".\");\n const prefixes: string[] = [];\n let accumulated = rowPath;\n for (const segment of tail) {\n if (segment === \"*\") {\n // 行より下のワイルドカード(入れ子リスト)は行オブジェクトの素の読みでは解けない\n return null;\n }\n accumulated += \".\" + segment;\n prefixes.push(accumulated);\n }\n return { tail, prefixes };\n });\n byRowPath.set(rowPath, tails);\n return tails;\n}\n\n/**\n * getter は state ごとの集合で、`_state` の再セットで作り直される。行ごとに引き直す\n * (プラン側にキャッシュすると、再セット後も古い判定を使ってしまう)。\n */\nfunction hasGetterOnPrefix(prefixes: string[], getterPaths: ReadonlySet<string>): boolean {\n for (let k = 0; k < prefixes.length; k++) {\n if (getterPaths.has(prefixes[k])) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * プラン行の初期描画。行オブジェクトを proxy で 1 回読み、素の葉の slot にはその生の値を\n * そのまま渡す(読み 7 → 4・適用 3 → 1 回/行。調査 §10.13)。getter の slot と、\n * 載せられない slot は従来どおり `applyChange` を通る。\n */\nfunction applyPlanRow(\n plan: IRowPlan,\n bindings: readonly IBindingInfo[],\n session: BindingSession,\n loopContext: ILoopContext,\n context: IApplyContext,\n): void {\n const tails = slotTails(plan, bindings, loopContext.pathInfo.path);\n const getterPaths = context.stateElement.getterPaths;\n // 素の葉読みは `getByAddress` の readMissing hook(マウントの公開 getter の dispatch —\n // webComponent/exportIndex.ts)を迂回する。公開キー `P.k` は **`getterPaths` に載らない**\n // ので `hasGetterOnPrefix` にも掛からず、素の葉として undefined に落ちていた。\n // hook を持たない state(スコープ機能を入れていないページ)は真偽値 1 個で抜ける。\n //\n // 追加コスト(Chromium 149・10,000 行 × 7 スロット × 1 段 = 70,000 回の走査、中央値 60 本):\n // 素の走査 0.10 ms → hook 無し 0.20 ms → hook 有り 0.40 ms。create-10k の実測(v3 cold 中央値\n // 302.3 ms・docs/research/state-next/a3-v251-vs-3.0.json)に対して最悪 +0.3 ms ≒ 0.1 % で、\n // 同ベンチのサンプル分散(272.9〜450.3 ms)に埋もれる。R2 の改善幅(2.5.1 比 −18.7 %)は保たれる。\n const hasReadMissing = (context.stateElement.addressHooks?.readMissing.length ?? 0) !== 0;\n let rowValue: any;\n let rowRead = false;\n for (let i = 0; i < bindings.length; i++) {\n const binding = bindings[i];\n if (!session.shouldApplyState(binding)) {\n continue;\n }\n const slotTail = tails[i];\n if (slotTail === null || hasGetterOnPrefix(slotTail.prefixes, getterPaths)) {\n applyChange(binding, context);\n continue;\n }\n if (context.appliedBindingSet.has(binding)) {\n continue;\n }\n if (!rowRead) {\n rowValue = (context.state as any)[getByAddressSymbol](loopContext);\n rowRead = true;\n }\n const tail = slotTail.tail;\n let value: any = rowValue;\n let missingKey = false;\n for (let k = 0; k < tail.length; k++) {\n if (value === null || typeof value === \"undefined\") {\n value = undefined;\n break;\n }\n // 「ツリーにそのキーが無い」= readMissing hook が答える形(getByAddress と同じ判定)。\n // この slot だけ従来経路へ倒し、hook に聞かせる\n if (hasReadMissing && !(tail[k] in Object(value))) {\n missingKey = true;\n break;\n }\n value = value[tail[k]];\n }\n if (missingKey) {\n applyChange(binding, context);\n continue;\n }\n context.appliedBindingSet.add(binding);\n applyValueToBinding(binding, context, value);\n }\n}\n\nexport function activateContent(\n content: IContent,\n loopContext: ILoopContext | null,\n context: IApplyContext,\n): void {\n bindLoopContextToContent(content, loopContext);\n const bindings = getBindingsByContent(content);\n const session = getBindingSessionByContent(content);\n if (session !== null) {\n // createContent 側の initialize で remember 済みの同一 binding 配列なので、\n // remember を再実行しない専用パスで活性化する(リスト行生成のホットパス)。\n // context.rootNode は applyChangeFromBindings が確定済みの root(fragment\n // バッファ中は setRootNodeByFragment の対応先と同一)で、binding ごとの\n // getRootNode を省略できる\n session.activate(bindings, context.rootNode);\n // プラン初期描画(設計 R2)。載せないのは 2 つ:\n // `$updatedCallback` を持つ state — 束縛ごとのアドレス集計が要る\n // `**` を持つ state — 展開形の getter が `getterPaths` に無いので素の葉と見分けられない\n if (loopContext !== null\n && context.stateElement.hasUpdatedCallback === false\n && context.stateElement.hasRecursion !== true) {\n const plan = getPlanByContent(content);\n if (plan !== null) {\n applyPlanRow(plan, bindings, session, loopContext, context);\n return;\n }\n }\n }\n for (const binding of bindings) {\n if (session === null) {\n const absoluteStateAddress = getAbsoluteStateAddressByBinding(binding);\n addBindingByAbsoluteStateAddress(absoluteStateAddress, binding);\n }\n if (session !== null && !session.shouldApplyState(binding)) {\n continue;\n }\n applyChange(binding, context);\n }\n // 未定義カスタム要素への spread(#330)は行が生きている間だけ定義を待つ。解体(session の dispose)が\n // 待ちを取り消すので、使い回す行・再表示する枝はここで予約し直す。持つのは createContent の行だけ\n //(session あり・プラン行はカスタム要素を持てない)\n if (content.spreads) scheduleDeferredSpreads(content.spreads, loopContext, session!, bindings, getIndexBindingsByContent(content));\n}\n\nexport function deactivateContent(\n content: IContent,\n): void {\n if (!content.mounted) {\n return;\n }\n const bindings = getBindingsByContent(content);\n const session = getBindingSessionByContent(content);\n for (let i = 0; i < bindings.length; i++) { // 添字ループ(消去の窓に反復子のごみを残さない)\n const binding = bindings[i];\n if (session !== null) {\n session.disposeBinding(binding);\n } else {\n const absoluteStateAddress = getAbsoluteStateAddressByBinding(binding);\n removeBindingByAbsoluteStateAddress(absoluteStateAddress, binding);\n }\n }\n unbindLoopContextToContent(content);\n}\n","\nexport function createEmptySet<T>(): Readonly<Set<T>> {\n return Object.freeze(new Set<T>());\n}\n","import { createEmptySet } from \"../createEmptySet\";\nimport { IContent } from \"./types\";\n\nconst contentSetByNode = new WeakMap<Node, Set<IContent>>();\n\nconst EMPTY_SET = /*#__PURE__*/ createEmptySet<IContent>();\n\nexport function setContentByNode(node: Node, content: IContent): void {\n const contents = contentSetByNode.get(node);\n if (contents) {\n contents.add(content);\n } else {\n contentSetByNode.set(node, new Set([content]));\n }\n}\n\nexport function getContentSetByNode(node: Node): Readonly<Set<IContent>> {\n const contents = contentSetByNode.get(node);\n if (typeof contents !== \"undefined\") {\n return contents;\n }\n return EMPTY_SET;\n}\n\nexport function deleteContentByNode(node: Node, content: IContent): void {\n const contents = contentSetByNode.get(node);\n if (contents) {\n contents.delete(content);\n if (contents.size === 0) {\n contentSetByNode.delete(node);\n }\n }\n}","import { clearAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding.js\";\nimport { clearStateAddressByBindingInfo } from \"../binding/getStateAddressByBindingInfo.js\";\nimport { getBindingsByContent, setBindingsByContent } from \"../bindings/bindingsByContent.js\";\nimport { getBindingSessionByContent, setBindingSessionByContent } from \"../bindings/bindingSessionByContent.js\";\nimport { IDeferredSpreadEntry, markNodeRegistered } from \"../bindings/collectNodesAndBindingInfos.js\";\nimport { setIndexBindingsByContent } from \"../bindings/indexBindingsByContent.js\";\nimport { initializeBindingsByFragment, initializeRowBindings } from \"../bindings/initializeBindings.js\";\nimport { resolveInitializedBinding } from \"../bindings/initializeBindingPromiseByNode.js\";\nimport { setNodesByContent } from \"../bindings/nodesByContent.js\";\nimport { markObserverSkipOnAdd, markObserverSkipOnRemove } from \"../bindings/observerSkip.js\";\nimport { config, inSsr } from \"../config.js\";\nimport { INDEX_BY_INDEX_NAME } from \"../define.js\";\nimport { raiseError } from \"../raiseError.js\";\nimport { IBindingInfo } from \"../types.js\";\nimport { getContentSetByNode, setContentByNode } from \"./contentsByNode.js\";\nimport { getFragmentInfoByUUID } from \"./fragmentInfoByUUID.js\";\nimport { resolveNodePath } from \"./resolveNodePath.js\";\nimport { compileRowPlan } from \"./rowPlan.js\";\nimport { setPlanByContent } from \"./planByContent.js\";\nimport { IContent, IFragmentInfo, IRowPlan } from \"./types.js\";\n\nconst recursiveBindingTypes = new Set(['if', 'elseif', 'else', 'for']);\n\nclass Content implements IContent {\n private _content: DocumentFragment;\n private _childNodeArray: Node[] = [];\n private _firstNode: Node | null = null;\n private _lastNode: Node | null = null;\n private _mounted: boolean = false;\n /**\n * 範囲モード。トップレベルに構造ディレクティブを持つ content でのみ true。\n * この content の実レンジは自分の childNodeArray より広い(ネストした\n * if/for が自分のアンカー直後に実ノードを挿すため)ので、移動は\n * firstNode..lastNode の DOM レンジで行う。\n */\n private _ranged: boolean = false;\n // 出力しない宣言(持つ行だけに後から付ける — 全行にフィールドを足さない)\n declare spreads?: IDeferredSpreadEntry[];\n constructor(content: DocumentFragment, ranged: boolean = false) {\n this._content = content;\n this._ranged = ranged;\n // childNodes(NodeList)と Array.from の iterator を作らずに兄弟ポインタで集める。複製した\n // ばかりの fragment ではここが childNodes に触れる最初の場所になる(resolveNodePath と同じ理由、設計 R5)\n const childNodeArray: Node[] = [];\n for (let node = content.firstChild; node !== null; node = node.nextSibling) {\n childNodeArray.push(node);\n }\n this._childNodeArray = childNodeArray;\n this._firstNode = this._childNodeArray.length > 0 ? this._childNodeArray[0] : null;\n this._lastNode = this._childNodeArray.length > 0 ? this._childNodeArray[this._childNodeArray.length - 1] : null;\n }\n\n get firstNode(): Node | null {\n return this._firstNode;\n }\n\n get lastNode(): Node | null {\n return this._lastNode;\n }\n\n get mounted(): boolean {\n return this._mounted;\n }\n\n appendTo(targetNode: Node): void {\n const childNodes = this._childNodeArray;\n for (let i = 0; i < childNodes.length; i++) {\n const node = childNodes[i];\n // framework 起点のマウントを observer に伝える。中間 fragment へ append する\n // 経路でも、後続の一括 insertBefore(fragment) の mutation record には\n // この top-level node が addedNodes として現れるため、ここでのマークが届く。\n markObserverSkipOnAdd(node);\n targetNode.appendChild(node);\n }\n this._mounted = true;\n }\n\n /**\n * 移動対象ノード列。通常は自分のトップレベルノードそのもの(同一参照を返すので\n * 追加アロケーション無し)。範囲モードでマウント中のときだけ、ネストした構造\n * ディレクティブが挿した実ノードを含む DOM レンジを収集する。\n */\n private _movableNodes(): Node[] {\n if (!this._ranged || !this._mounted) {\n return this._childNodeArray;\n }\n const first = this._firstNode;\n const last = this._lastNode;\n if (first === null || last === null || first.parentNode === null) {\n return this._childNodeArray;\n }\n // 移動でsiblingが変わるため、先に列を確定させてから動かす\n const nodes: Node[] = [];\n for (let node: Node | null = first; node !== null; node = node.nextSibling) {\n nodes.push(node);\n if (node === last) {\n return nodes;\n }\n }\n // last へ到達しない(想定外の不連続)→ 従来どおり自分のノードだけ動かす\n return this._childNodeArray;\n }\n\n mountAfter(targetNode: Node): void {\n const parentNode = targetNode.parentNode;\n if (parentNode) {\n // マウント済み content にも再突入する(if の true→true 再適用・SSR\n // ハイドレーション産 content 等)。固定の nextSibling へ一括 insertBefore\n // すると、マウント済みでは nextSibling が自分の先頭ノードを指すため\n // 先頭ノードが末尾へ回転する。anchor を進めながら位置一致ノードを\n // スキップすることで冪等にする(mutation record も発生させない)。\n let anchor: Node = targetNode;\n for(const node of this._movableNodes()) {\n if (anchor.nextSibling !== node) {\n // moveBefore も childList mutation record を出すため、マークは両分岐の前\n markObserverSkipOnAdd(node);\n // moveBefore は取り外しを伴わない移動 — 接続済み行の reorder で\n // フォーカス・iframe・アニメーション状態を保存する(docs/a11y-design.md §4-1)。\n // この 1 文は 4 つのノード状態を共有する: (a) 接続済み reorder、\n // (b) clone フラグメント由来(root 違い)、(c) プール/unmount 済み(親なし)、\n // (d) バッチフラグメント内。moveBefore は「同一ツリー・親あり」を要求し\n // (b)(c)(d) では HierarchyRequestError を投げるため、same-parent ガード\n // (同 root かつ親が非 null の同時証明 = フォーカス保存が意味を持つ (a) と\n // 正確に一致)は外せない。ガードを外す「簡略化」をしてはならない。\n const mover = parentNode as Node & {\n moveBefore?: (node: Node, child: Node | null) => void;\n };\n if (node.parentNode === parentNode && typeof mover.moveBefore === \"function\") {\n mover.moveBefore(node, anchor.nextSibling);\n } else {\n parentNode.insertBefore(node, anchor.nextSibling);\n }\n }\n anchor = node;\n }\n }\n this._mounted = true;\n }\n\n tryDestroy(): boolean {\n const session = getBindingSessionByContent(this);\n // session 無し(SSR ハイドレーション産)や、定義待ち・connect-snapshot 待ちを\n // 抱える content は teardown 省略でリークするため従来経路に倒す。\n if (session === null || !session.canWholesaleDestroy()) {\n return false;\n }\n session.destroyRow(getBindingsByContent(this));\n // 添字ループ: for...of の反復子オブジェクトを行ごとに割り当てない(消去の scavenge を窓から外す)\n const childNodes = this._childNodeArray;\n for (let i = 0; i < childNodes.length; i++) {\n const node = childNodes[i];\n // unmount と同じ理由の observer 向け削除マーク(clear の一括削除でも\n // top-level node が mutation record の root に現れる)\n // この content が自分でノードを外すときだけ印を付ける(親の一括削除は親側で件数を数える)\n if (node.parentNode !== null) {\n markObserverSkipOnRemove(node);\n node.parentNode.removeChild(node);\n }\n }\n const bindings = getBindingsByContent(this);\n for (let i = 0; i < bindings.length; i++) {\n const binding = bindings[i];\n if (recursiveBindingTypes.has(binding.bindingType)) {\n getContentSetByNode(binding.node).forEach((content) => {\n if (!content.tryDestroy()) {\n content.unmount();\n }\n });\n }\n }\n this._mounted = false;\n return true;\n }\n\n /**\n * 自分のノードを DOM に残したまま、unmount と同じ解体をする(#4)。\n *\n * 行の置き換えで `for` が同じ位置の Content を新しい行に使い回すとき、入力中の欄を DOM から\n * 外さないための経路。解体そのものは省けない — 中の構造ディレクティブ(ネストした for / if)が\n * 持つ Content を古い行のまま残すと、新しい行として活性化したときに内側の行が二重に描かれ、\n * `if` の中身は古い行のアドレスに紐づいたまま取り残される。\n */\n unmountInPlace(): void {\n {\n // 共有 session(`for` 束縛ごとに 1 つ)ではこの content の行だけを解体する(設計 R3)。\n // session ごと dispose すると同じリストの生きている行まで巻き込む\n const session = getBindingSessionByContent(this);\n if (session !== null) {\n if (session.isRowSession) session.disposeBindings(getBindingsByContent(this));\n else session.dispose();\n }\n }\n this._teardownBindings();\n }\n\n /** binding ごとの解体(ネストした構造ディレクティブの Content・アドレス台帳) */\n private _teardownBindings(): void {\n const bindings = getBindingsByContent(this);\n for (let i = 0; i < bindings.length; i++) {\n const binding = bindings[i];\n if (recursiveBindingTypes.has(binding.bindingType)) {\n getContentSetByNode(binding.node).forEach((content) => { content.unmount(); });\n }\n clearStateAddressByBindingInfo(binding);\n clearAbsoluteStateAddressByBinding(binding);\n }\n }\n\n unmount(): void {\n {\n // 共有 session(`for` 束縛ごとに 1 つ)ではこの content の行だけを解体する(設計 R3)。\n // session ごと dispose すると同じリストの生きている行まで巻き込む\n const session = getBindingSessionByContent(this);\n if (session !== null) {\n if (session.isRowSession) session.disposeBindings(getBindingsByContent(this));\n else session.dispose();\n }\n }\n for(const node of this._childNodeArray) {\n // framework 起点の削除であることを observer に伝える。clear の\n // parentNode.textContent='' 一括削除でも、この top-level node が\n // 削除サブツリーの root として mutation record に現れるため、ここで\n // マークしておけば observer の冗長走査をスキップできる。マークは\n // 同期実行中に立ち、observer は次 microtask で読むので順序は保証される。\n if (node.parentNode !== null) {\n markObserverSkipOnRemove(node);\n node.parentNode.removeChild(node);\n }\n }\n const bindings = getBindingsByContent(this);\n for (let i = 0; i < bindings.length; i++) {\n const binding = bindings[i];\n if (recursiveBindingTypes.has(binding.bindingType)) {\n getContentSetByNode(binding.node).forEach((content) => { content.unmount(); });\n }\n clearStateAddressByBindingInfo(binding);\n clearAbsoluteStateAddressByBinding(binding);\n }\n this._mounted = false;\n }\n}\n\n/**\n * トップレベルに構造ディレクティブのプレースホルダを持つか。\n *\n * これを持つ content は、ネストした if/for が「自分のアンカー直後」に実ノードを\n * 挿すため、自分の childNodeArray が実レンジより狭くなる。その状態だと\n * (1) 呼び出し側の位置追跡(applyChangeToFor の lastNode)が実ノードの手前で\n * 止まり後続行が割り込む、(2) 移動時にネスト分を置き去りにする、の 2 つが起きる。\n * 該当テンプレートにだけ終端マーカーを持たせて実レンジを閉じる。\n */\nfunction hasTopLevelStructural(fragment: DocumentFragment): boolean {\n // config は setConfig で差し替わりうるので都度組む。テンプレート単位に一度しか\n // 走らない判定なので、この生成コストが行あたりに乗ることはない。\n const structural = new RegExp(\n `^@@(?:${config.commentForPrefix}|${config.commentIfPrefix}`\n + `|${config.commentElseIfPrefix}|${config.commentElsePrefix}):`,\n );\n for (let node = fragment.firstChild; node !== null; node = node.nextSibling) {\n if (node.nodeType !== Node.COMMENT_NODE) {\n continue;\n }\n // Comment の data は常に文字列(textContent の null 分岐を持ち込まない)\n if (structural.test((node as Comment).data)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * 範囲モードの要否をテンプレート単位で一度だけ判定してキャッシュする。\n * 大多数のテンプレート(トップレベルが素の要素)は false を引くだけで、\n * 行ごとの追加コストはゼロ。\n */\nfunction resolveRanged(fragmentInfo: IFragmentInfo): boolean {\n let ranged = fragmentInfo.topLevelStructural;\n if (typeof ranged === 'undefined') {\n ranged = fragmentInfo.topLevelStructural = hasTopLevelStructural(fragmentInfo.fragment);\n }\n return ranged;\n}\n\n/**\n * 添字 `$N`(`INDEX_BY_INDEX_NAME` の位置 pos = N - 1)のビット。32 段目より奥の添字は最上位のビットに\n * まとめる(まとめた添字どうしは区別されず、多めに辿るだけ — 取りこぼしはしない)。\n */\nexport function indexBit(pos: number): number {\n return 1 << Math.min(pos, 31);\n}\n\n/** `$1` … `$depth` のビット集合(32 段以上は全部) */\nfunction indexBitsUpTo(depth: number): number {\n return 2 ** Math.min(depth, 32) - 1;\n}\n\n/** 段で絞らない(if の枝・SSR の行) */\nexport const ALL_INDEX_BITS = -1;\n\n/**\n * テンプレートの中(入れ子のテンプレートも含む)で使う添字(`$1` …)のビット集合。テンプレート単位に一度だけ\n * 求めてキャッシュする(resolveRanged と同じ門)。入れ子の構造ディレクティブの条件(`if: $1|lt(2)`)は、\n * 置き場の解析結果として外側のテンプレートの中身に居る。\n */\nfunction indexBitsOfFragment(fragmentInfo: IFragmentInfo): number {\n let bits = fragmentInfo.indexBits;\n if (typeof bits === 'undefined') {\n bits = 0;\n for (const nodeInfo of fragmentInfo.nodeInfos) {\n for (const result of nodeInfo.parseBindTextResults) {\n if (result.statePathName in INDEX_BY_INDEX_NAME) {\n bits |= indexBit(INDEX_BY_INDEX_NAME[result.statePathName]);\n }\n if (typeof result.uuid === 'string') {\n bits |= indexBitsOfFragment(getFragmentInfoByUUID(result.uuid)!);\n }\n }\n }\n fragmentInfo.indexBits = bits;\n }\n return bits;\n}\n\n/** 構造ディレクティブの束縛の中(入れ子の奥も含む)で使う添字のビット集合 */\nexport function getIndexBitsByBinding(binding: IBindingInfo): number {\n return indexBitsOfFragment(getFragmentInfoByUUID(binding.uuid as string)!);\n}\n\n/**\n * 行の位置が変わったときに当て直す列(indexBindingsByContent)に入れる束縛か: 添字の束縛(`$1` …)と、\n * 中に `depthBits` の添字の束縛を持つ入れ子の構造ディレクティブ(内側の for の行・if の枝の添字の束縛へ辿る\n * 入口 — applyChangeToFor.ts の applyIndexBindings・#360)。for の行の位置が変わって値の変わる添字は、その for の\n * 段の `$d` だけ — 行を動かしうるのはその for と外側の for なので、`depthBits` は `$1` … `$d`。中にそれ以外の添字\n * しか無い入れ子(内側の行が自分の番号 `$2` だけを描く形など)まで入れると、位置の変わった行ごとに、当て直す\n * もの無しに入れ子の行を全部辿る(#390)。SSR の行(ssr/hydrateBindings.ts)も同じ振り分け。\n */\nexport function isIndexBinding(binding: IBindingInfo, depthBits: number): boolean {\n return binding.statePathName in INDEX_BY_INDEX_NAME\n || (recursiveBindingTypes.has(binding.bindingType) && (getIndexBitsByBinding(binding) & depthBits) !== 0);\n}\n\nconst ROW_END_PREFIX = 'wcs-row-end';\n\n/**\n * 終端マーカーの付与。バインディング初期化の後に足すので nodePath 解決には影響しない\n * (末尾追加なので既存 index もずれない)。SSR 描画中は付けない — SSR は行ごとに\n * `@@wcs-for-start/end` を出力しており、そちらがレンジの正本かつハイドレーション\n * が読む対象なので、余計なコメントを混ぜない。\n */\nfunction appendRowEndMarker(cloneFragment: DocumentFragment, uuid: string): void {\n cloneFragment.appendChild(document.createComment(`${ROW_END_PREFIX}:${uuid}`));\n}\n\n/**\n * SSR ハイドレーション用: 既存の DOM ノード配列から Content を生成する。\n * テンプレートからの clone ではなく、SSR で描画済みのノードをそのまま使う。\n * `ranged` は createContent と同じ範囲モード(終端マーカーは呼び出し側が `nodes` の末尾に置く)。\n */\nexport function createContentFromNodes(\n nodes: Node[],\n ranged?: boolean,\n): IContent {\n const fragment = document.createDocumentFragment();\n // ノードを fragment に移動せず、参照だけ持つ Content を作る\n const content = new Content(fragment, ranged);\n // Content の内部状態を直接設定\n (content as any)._childNodeArray = nodes;\n (content as any)._firstNode = nodes.length > 0 ? nodes[0] : null;\n (content as any)._lastNode = nodes.length > 0 ? nodes[nodes.length - 1] : null;\n (content as any)._mounted = true; // SSR で既にマウント済み\n return content;\n}\n\n/**\n * RowPlan 経路の実体化: clone → nodePath 解決 → スロットから薄い binding を複製 →\n * initializeRowBindings。パース再生(spread 展開・remember・キー文字列・options\n * オブジェクト・policy 再解決)を行ごとに繰り返さない\n * (docs/state-row-instantiation-redesign.md §3-1/§3-2)。\n */\nfunction createPlanContent(\n bindingInfo: IBindingInfo,\n fragmentInfo: IFragmentInfo,\n plan: IRowPlan,\n): IContent {\n const cloneFragment = document.importNode(fragmentInfo.fragment, true);\n const nodeInfos = fragmentInfo.nodeInfos;\n const nodes: Node[] = new Array(nodeInfos.length);\n for (let i = 0; i < nodeInfos.length; i++) {\n const node = resolveNodePath(cloneFragment, nodeInfos[i].nodePath);\n if (node === null) {\n raiseError(`Node not found by path [${nodeInfos[i].nodePath.join(', ')}] in fragment.`);\n }\n // 再スキャン防止と初期化完了マークは従来経路と同じ台帳に載せる\n markNodeRegistered(node);\n resolveInitializedBinding(node);\n nodes[i] = node;\n }\n const slots = plan.slots;\n const bindings: IBindingInfo[] = new Array(slots.length);\n const indexBindings: IBindingInfo[] = [];\n for (let k = 0; k < slots.length; k++) {\n const slot = slots[k];\n const node = nodes[slot.nodeIndex];\n // text スロットは事前正規化済みの Text がそのまま replaceNode(従来経路の\n // getBindingInfos と同じ帰結)。prop/event は node === replaceNode\n const binding: IBindingInfo = { ...slot.template, node, replaceNode: node };\n bindings[k] = binding;\n if (slot.isIndexBinding) {\n indexBindings.push(binding);\n }\n }\n const session = initializeRowBindings(plan, bindings, bindingInfo.node);\n // プラン経路の content は範囲モードにならない: compileRowPlan は bindingType が\n // text / prop / event のもの以外(= for / if / elseif / else)を含む時点で不適格に\n // するため、プラン適格なフラグメントはトップレベル構造アンカーを持ち得ない。\n const content = new Content(cloneFragment);\n setBindingSessionByContent(content, session);\n setBindingsByContent(content, bindings);\n // 活性化がこの行をプラン初期描画に載せてよいか判定するための逆引き(設計 R2)\n setPlanByContent(content, plan);\n setIndexBindingsByContent(content, indexBindings);\n setNodesByContent(content, nodes);\n setContentByNode(bindingInfo.node, content);\n return content;\n}\n\nexport function createContent(\n bindingInfo: IBindingInfo,\n): IContent {\n if (typeof bindingInfo.uuid === 'undefined' || bindingInfo.uuid === null) {\n raiseError(`BindingInfo.uuid is null.`);\n }\n const fragmentInfo = getFragmentInfoByUUID(bindingInfo.uuid);\n if (!fragmentInfo) {\n raiseError(`Fragment with UUID \"${bindingInfo.uuid}\" not found.`);\n }\n // SSR 描画中は行ごとの @@wcs-for-start/end がレンジの正本なので終端マーカーは付けない\n const ranged = !inSsr() && resolveRanged(fragmentInfo);\n let plan = fragmentInfo.rowPlan;\n if (typeof plan === 'undefined' || (plan !== null && plan.directional !== config.enableDirectionalInitialSync)) {\n // 初回 or config(directional)が変わったときだけコンパイル。不適格は null を\n // キャッシュして以後は従来経路へ直行する\n plan = fragmentInfo.rowPlan = compileRowPlan(fragmentInfo);\n }\n if (plan !== null) {\n return createPlanContent(bindingInfo, fragmentInfo, plan);\n }\n const cloneFragment = document.importNode(fragmentInfo.fragment, true);\n const initialInfo = initializeBindingsByFragment(cloneFragment, fragmentInfo.nodeInfos);\n if (ranged) {\n // uuid は冒頭のガードで非 null が確定している(raiseError は never を返す)\n appendRowEndMarker(cloneFragment, bindingInfo.uuid);\n }\n const content = new Content(cloneFragment, ranged);\n if (initialInfo.spreads.length > 0) content.spreads = initialInfo.spreads;\n setBindingSessionByContent(content, initialInfo.bindingSession);\n setBindingsByContent(content, initialInfo.bindingInfos);\n // 行の位置が変わったときに当て直す列(isIndexBinding)。for の行の段は、その for のリストのパスの\n // ワイルドカードの数 + 1。if の枝は自分の段を持たないので絞らない(辿るときに applyIndexBindings が絞る)\n const depthBits = bindingInfo.bindingType === 'for'\n ? indexBitsUpTo(bindingInfo.statePathInfo.wildcardCount + 1)\n : ALL_INDEX_BITS;\n const indexBindings: IBindingInfo[] = [];\n for(const binding of initialInfo.bindingInfos) {\n if (isIndexBinding(binding, depthBits)) {\n indexBindings.push(binding);\n }\n }\n setIndexBindingsByContent(content, indexBindings);\n setNodesByContent(content, initialInfo.nodes);\n setContentByNode(bindingInfo.node, content);\n return content;\n}\n","import { ILoopContext } from \"../list/types\";\nimport { IBindingInfo } from \"../types\";\nimport { INDEX_BY_INDEX_NAME } from \"../define\";\nimport {\n collectNodesAndBindingInfosOf,\n collectNodesAndBindingInfosByFragment,\n IDeferredSpreadEntry,\n ParseResultTransform,\n processDeferredNode,\n uncollectedNodes,\n} from \"./collectNodesAndBindingInfos\";\nimport { getSubscriberNodes } from \"./getSubscriberNodes\";\nimport { IFragmentNodeInfo, IRowPlan } from \"../structural/types\";\nimport { setLoopContextByNode } from \"../list/loopContextByNode\";\nimport { applyChangeFromBindings } from \"../apply/applyChangeFromBindings\";\nimport { IInitialBindingInfo } from \"./types\";\nimport { BindingSession, getOrCreateBindingSession } from \"./BindingSession\";\n\n/**\n * 未定義カスタム要素への `...: path` を `whenDefined` 後の配線として予約する。\n * ハイドレーション経路(`ssr/hydrateBindings.ts`)も同じ手順を通すため export している —\n * あちらは `collectNodesAndBindingInfos` の 3 要素目を捨てていて、SSR したページでだけ\n * spread が永久に配線されなかった。\n *\n * `contentBindings` は構造テンプレートの行(Content)の束縛の列(#330。`activateContent` が渡す)。\n * 行の待ちは行の解体(session の dispose)が取り消し、次の活性化(プールからの使い回し・`if:` の\n * 再表示)が予約し直す。定義されたら展開した束縛をこの列に足して行の束縛にし(以後の解体・活性化は\n * 他の束縛と同じ)、`deferredSpreads` から外す — 展開は一度きり。添字の束縛(`$1`)は `indexBindings`\n * (行の添字が変わったときに当て直す列)にも足す — createContent の振り分けと同じ。\n */\nexport function scheduleDeferredSpreads(\n deferredSpreads: IDeferredSpreadEntry[],\n parentLoopContext: ILoopContext | null,\n session: BindingSession,\n contentBindings?: IBindingInfo[],\n indexBindings?: IBindingInfo[],\n): void {\n for (const entry of deferredSpreads) {\n // 生きている行の活性化し直し(`if:` の真→真)で待ちを重ねない(取り消し済み・発火済みなら何もしない)\n entry.cancel?.();\n entry.cancel = session.deferUntilDefined(entry.node, entry.tagName, () => {\n const bindings = processDeferredNode(entry);\n if (contentBindings) {\n deferredSpreads.splice(deferredSpreads.indexOf(entry), 1);\n contentBindings.push(...bindings);\n indexBindings!.push(...bindings.filter((binding) => binding.statePathName in INDEX_BY_INDEX_NAME));\n }\n if (bindings.length === 0) return;\n setLoopContextByNode(entry.node, parentLoopContext);\n // 行の束縛は行と同じ選択肢で(createContent の初期化 → activate の昇格と同じ結果)\n const initialized = session.initialize(bindings, contentBindings && { registerPathInfo: false, applyOnReconnect: false });\n applyChangeFromBindings(initialized);\n }, (error: unknown) => {\n console.error(`[@wcstack/state] deferred spread failed for <${entry.tagName}>.`, error);\n });\n }\n}\n\nexport function initializeBindings(\n root: Document | DocumentFragment | Element,\n parentLoopContext: ILoopContext | null,\n transform?: ParseResultTransform,\n // The subscriber nodes to bind. The binder passes its own: the walk never returns `root` itself (binder.ts)\n nodes: Node[] = getSubscriberNodes(root),\n // The binder passes a session of its own: one keyed by its subtree could be a mount scope's (binder.ts)\n session: BindingSession = getOrCreateBindingSession(root),\n): void {\n // Only the nodes not collected yet (#414). A collected node is bound already — by an earlier walk, or\n // as a row's node — and keeps the loop context it was given: a subtree handed over again (the router\n // hands a route's content over on every entry) reset its rows' nodes to `parentLoopContext`, and a\n // row's `if:` failed on its next toggle.\n const [subscriberNodes, allBindings, deferredSpreads] = collectNodesAndBindingInfosOf(uncollectedNodes(nodes), transform);\n for (const node of subscriberNodes) {\n setLoopContextByNode(node, parentLoopContext);\n }\n const initialized = session.initialize(allBindings);\n applyChangeFromBindings(initialized);\n scheduleDeferredSpreads(deferredSpreads, parentLoopContext, session);\n}\n\nexport function initializeBindingsByFragment(\n root: DocumentFragment,\n nodeInfos: IFragmentNodeInfo[],\n): IInitialBindingInfo {\n const [subscriberNodes, allBindings, spreads] = collectNodesAndBindingInfosByFragment(root, nodeInfos);\n const session = new BindingSession();\n // knownRoot=null: detached fragment 上の初期化。observableRootFor が必ず null を\n // 返す(observe は no-op)ため、binding ごとの getRootNode を省略する\n const initialized = session.initialize(allBindings, {\n registerAddress: false,\n applyOnReconnect: false,\n }, null);\n return {\n nodes: subscriberNodes,\n bindingInfos: initialized,\n bindingSession: session,\n spreads,\n };\n}\n\n/**\n * RowPlan 経路の行初期化(createContent 専用)。remember / spread 展開 /\n * shouldApplyState フィルタを経ず、プランのスロットから直接 record を構築する。\n * 返す session は従来経路と同じ活性化(activate)・破棄(dispose/wholesale)\n * インターフェースを持つ。\n */\n// `for` 束縛(そのノード)ごとに 1 つの session を全行で共有する(設計 R3)。\n// プランが差し替わったら(再セット・方向性初期同期の設定変更)新しい session に切り替える。\nconst rowSessionByForNode = new WeakMap<Node, BindingSession>();\nexport function initializeRowBindings(plan: IRowPlan, bindings: IBindingInfo[], forNode: Node): BindingSession {\n let session = rowSessionByForNode.get(forNode);\n if (typeof session === \"undefined\" || session.currentRowPlan !== plan) {\n session = new BindingSession();\n rowSessionByForNode.set(forNode, session);\n }\n session.initializeRow(plan, bindings);\n return session;\n}\n","import { IInitialSyncPolicy, resolveInitialSyncPolicy } from \"../bindings/initialSync\";\nimport { planBinding } from \"../bindings/planFilters\";\nimport { config } from \"../config\";\nimport { COMMAND_NAMESPACE, EVENT_TOKEN_NAMESPACE, INDEX_BY_INDEX_NAME } from \"../define\";\nimport { isPossibleTwoWay } from \"../event/isPossibleTwoWay\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { IBindingInfo } from \"../types\";\nimport { resolveNodePath } from \"./resolveNodePath\";\nimport { IFragmentInfo, IRowPlan, IRowPlanSlot } from \"./types\";\n\n/**\n * rowPlan.ts — 行実体化プランのコンパイル(docs/state-row-instantiation-redesign.md §3-1)。\n *\n * テンプレート(fragmentInfo)を初回行生成時に一度だけ検査し、全スロットが\n * 「行不変の判定をテンプレート時に確定できる」種別のときだけプランを返す。\n * 1 スロットでも確定できなければ null(テンプレート丸ごと従来経路 = 部分適用しない。\n * 経路混在のデバッグ困難を避ける設計判断・同 §5)。\n *\n * プラン適格の条件(すべて満たすこと):\n * - bindingType が text / prop / event のみ(構造 for/if・radio/checkbox・spread は不適格)\n * - バインディング先ノードがカスタム要素でない(定義待ち・wcBindable 検証が不要)\n * - prop が command / eventToken 名前空間でない(token 配線 teardown が要るため)\n * - prop が双方向可能(isPossibleTwoWay)でない(connect-snapshot / observer 配線が要るため)\n * - initial-sync policy が観測不要(observable=false)かつ authority が \"auto\" でない\n * - text スロットは事前正規化済みの Text ノードである\n */\nexport function compileRowPlan(fragmentInfo: IFragmentInfo): IRowPlan | null {\n const directional = config.enableDirectionalInitialSync;\n const slots: IRowPlanSlot[] = [];\n const nodeInfos = fragmentInfo.nodeInfos;\n for (let nodeIndex = 0; nodeIndex < nodeInfos.length; nodeIndex++) {\n const nodeInfo = nodeInfos[nodeIndex];\n const node = resolveNodePath(fragmentInfo.fragment, nodeInfo.nodePath);\n if (node === null) {\n return null;\n }\n for (const template of nodeInfo.parseBindTextResults) {\n const bindingType = template.bindingType;\n if (bindingType !== \"text\" && bindingType !== \"prop\" && bindingType !== \"event\") {\n return null;\n }\n // command.<name>(prop 扱い)と eventToken.<prop>(event 扱い)は token 配線の\n // teardown / attach 分岐が要るため不適格\n const namespace = template.propSegments[0];\n if (namespace === COMMAND_NAMESPACE || namespace === EVENT_TOKEN_NAMESPACE) {\n return null;\n }\n if (bindingType === \"text\") {\n if (node.nodeType !== Node.TEXT_NODE) {\n return null;\n }\n } else if (getCustomElement(node) !== null) {\n return null;\n }\n if (bindingType === \"prop\" && isPossibleTwoWay(node, template.propName)) {\n return null;\n }\n // フィルタの実関数は行不変なので、テンプレートごとに 1 回だけ引く(要件 D16。\n // 未知のフィルタはここで名指しで落ちる — 不適格として倒さない。従来経路へ倒しても\n // 同じ診断が出るだけで、行の生成まで遅れる)\n const planned = planBinding(template);\n let policy: IInitialSyncPolicy;\n try {\n // 判定はテンプレートのノードで行う(policy は node の宣言と行不変フィールドの\n // 純関数)。修飾子エラー等の throw は不適格として従来経路に倒し、従来経路が\n // 同じエラーを同じタイミング(初回行生成)で報告する。\n const probe: IBindingInfo = { ...planned, node, replaceNode: node };\n policy = resolveInitialSyncPolicy(probe);\n } catch {\n return null;\n }\n if (policy.observable || policy.authority === \"auto\") {\n return null;\n }\n slots.push({\n nodeIndex,\n template: planned,\n isEvent: bindingType === \"event\",\n isIndexBinding: template.statePathName in INDEX_BY_INDEX_NAME,\n policy,\n authority: policy.authority,\n });\n }\n }\n if (slots.length === 0) {\n // 束縛を 1 つも持たないテンプレート(静的な行)はプランに載せない(設計 R3)。\n // 行の帳簿(`session.rows`)の出入りは「スロットの binding」を鍵に回るので、0 スロットだと\n // 登録した行を解放する手掛かりが無く、`destroyRow([])` も共有 session の全行破棄へ倒れる。\n // 静的な行に最適化する余地は無い(適用も購読も無い)ので、従来経路に任せる方が安い\n return null;\n }\n return { directional, slots };\n}\n","import { getTransitionRunner } from \"../protocol/transitionRunner\";\nimport { IContent } from \"../structural/types\";\n\n/**\n * Automatic `view-transition-name` assignment (docs/view-transition-design.md §6).\n *\n * A name has to be on the element *before* the browser snapshots the old state,\n * so it cannot be assigned inside the transition's update callback — \"name only\n * what changed\" is impossible. The names are therefore assigned as structural\n * content mounts, and only when the page's arbiter declares `naming=\"auto\"`.\n *\n * The name follows the *content*, not the row's data: a pooled content reused for\n * another item keeps its name, which is exactly what the DOM does, so the\n * transition morphs the element that really was reused.\n */\nexport interface IAutoNaming {\n readonly limit: number;\n}\n\nexport type TransitionNameKind = \"row\" | \"branch\";\n\n/** Elements that already carry a generated name (never renamed). */\nconst namedElements = new WeakSet<Element>();\n\n/**\n * The generated-name ledger is per *document*, not per module instance.\n *\n * `view-transition-name` has to be unique across the whole document: the moment\n * two elements share one, the browser aborts the transition outright. A\n * module-scope counter breaks that as soon as `@wcstack/state` is loaded twice on\n * one page (two CDN bundles), because both copies would start minting\n * `wcs-row-1`. The transition-runner key is a `Symbol.for` for exactly this\n * reason, and the counter needs the same protection.\n *\n * Sharing the cap is right for the same reason: the cost a cap exists to bound —\n * one snapshot group per named element — is a document-wide cost, not a\n * per-bundle one.\n */\nconst NAMING_LEDGER_KEY = Symbol.for(\"wcstack.state.view-transition-naming\");\n\ninterface INamingLedger {\n counter: number;\n assigned: number;\n warned: boolean;\n}\n\nfunction getLedger(): INamingLedger {\n const slot = globalThis as Record<symbol, INamingLedger | undefined>;\n return (slot[NAMING_LEDGER_KEY] ??= { counter: 0, assigned: 0, warned: false });\n}\n\n// テスト用: ドキュメント単位の命名台帳を初期化する\nexport function __test_resetTransitionNaming(): void {\n const ledger = getLedger();\n ledger.counter = 0;\n ledger.assigned = 0;\n ledger.warned = false;\n}\n\n/**\n * The active auto-naming policy, or null when names are the author's business\n * (the default) — one arbiter lookup per structural apply, not per row.\n */\nexport function getAutoNaming(): IAutoNaming | null {\n const runner = getTransitionRunner(\"state\");\n if (runner === null || runner.naming !== \"auto\") {\n return null;\n }\n return { limit: runner.namingLimit };\n}\n\nfunction firstElementOf(content: IContent): Element | null {\n const first = content.firstNode;\n if (first === null) {\n return null;\n }\n const last = content.lastNode;\n for (let node: Node | null = first; node !== null; node = node.nextSibling) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n return node as Element;\n }\n if (node === last) {\n break;\n }\n }\n return null;\n}\n\n/**\n * Give this content's first element a unique name plus a class for group\n * styling, unless it already has one or the cap has been reached.\n *\n * The cap exists because every named element becomes its own snapshot group; a\n * few hundred of them make a transition visibly slow. Past it naming stops and\n * says so once — silently degrading would leave the author wondering why only\n * the first part of a list animates.\n */\nexport function applyTransitionName(\n content: IContent,\n kind: TransitionNameKind,\n naming: IAutoNaming,\n): void {\n const element = firstElementOf(content);\n if (element === null || namedElements.has(element)) {\n return;\n }\n // A node without `style` (anything outside HTMLElement / SVGElement) cannot\n // carry a name. Bail before touching the ledger: consuming the cap and marking\n // the element as named would burn a slot for a name that was never written,\n // and leave that element permanently ineligible.\n const style = (element as HTMLElement).style;\n if (style === undefined) {\n return;\n }\n const ledger = getLedger();\n if (ledger.assigned >= naming.limit) {\n if (!ledger.warned) {\n ledger.warned = true;\n console.warn(\n `[@wcstack/state] auto view-transition-name limit (${naming.limit}) reached; ` +\n \"further elements are left unnamed. Raise naming-limit on <wcs-view-transition>, \" +\n 'or switch to naming=\"manual\" and name only what should morph.',\n );\n }\n return;\n }\n namedElements.add(element);\n ledger.assigned += 1;\n ledger.counter += 1;\n style.setProperty(\"view-transition-name\", `wcs-${kind}-${ledger.counter}`);\n // Group handle for CSS (`::view-transition-group(*.wcs-row)`). Ignored by\n // engines that predate view-transition-class, which costs nothing.\n style.setProperty(\"view-transition-class\", `wcs-${kind}`);\n}\n","import { getPathInfo } from \"../address/PathInfo\";\nimport { createStateAddress } from \"../address/StateAddress\";\nimport { getAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding\";\nimport { getBindingsByContent } from \"../bindings/bindingsByContent\";\nimport { bindLoopContextToContent } from \"../bindings/bindLoopContextToContent\";\nimport { markObserverSkipRemovedChildren } from \"../bindings/observerSkip\";\nimport { getIndexBindingsByContent } from \"../bindings/indexBindingsByContent\";\nimport { inSsr, ssrBlockRemoval } from \"../config\";\nimport { INDEX_BY_INDEX_NAME, WILDCARD } from \"../define\";\nimport { calcDiffIndexes, createListDiff } from \"../list/createListDiff\";\nimport { getListIndexByBindingInfo } from \"../list/getListIndexByBindingInfo\";\nimport { getLastListValueByAbsoluteStateAddress, getRenderedList, IRenderedList, isSwappedList } from \"../list/lastListValueByAbsoluteStateAddress\";\nimport { getListIndexesByList, hasReleasedList, isRetiredListIndex } from \"../list/listIndexesByList\";\nimport { computeStableIndexSet } from \"../list/stableListOrder\";\nimport { isSwapBaselineList } from \"../list/swapBaselineList\";\nimport { IListDiff, IListIndex } from \"../list/types\";\nimport { raiseError } from \"../raiseError\";\nimport { activateContent, deactivateContent } from \"../structural/activateContent\";\nimport { deleteContentByNode, getContentSetByNode } from \"../structural/contentsByNode\";\nimport { createContent, getIndexBitsByBinding, indexBit } from \"../structural/createContent\";\nimport { IContent } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\nimport { applyChange } from \"./applyChange\";\nimport { setRootNodeByFragment } from \"./rootNodeByFragment\";\nimport { IApplyContext } from \"./types\";\nimport { applyTransitionName, getAutoNaming } from \"./viewTransitionNaming\";\n\nconst lastNodeByNode: WeakMap<Node, Node> = new WeakMap();\nconst contentByListIndexByNode: WeakMap<Node, WeakMap<IListIndex, IContent>> = new WeakMap();\nconst pooledContentsByNode: WeakMap<Node, IContent[]> = new WeakMap();\nconst isOnlyNodeInParentContentByNode: WeakMap<Node, boolean> = new WeakMap();\n// この for(アンカー)が最後に描いた並び(#320。lastListValueByAbsoluteStateAddress.ts の IRenderedList)\nconst renderedListByNode: WeakMap<Node, IRenderedList> = new WeakMap();\n// SSR 描画中の行の境界コメント [`@@wcs-for-start`, `@@wcs-for-end`](#334)\nconst ssrBoundsByContent: WeakMap<IContent, Comment[]> = new WeakMap();\n\n/**\n * SSR 描画中: 行を境界コメントで挟んで `parent` の `prev` の直後(null なら末尾)に置き、終端コメントを返す\n * (次の行はその後ろ)。境界は行の Content の範囲の外なので、Content だけを動かすと境界が置き去りになる\n * (#334 — 描いてある行の中身が自分の境界の前へ出て、足した行の境界が入れ子になった)。描いてある行は\n * 境界ごと(中の if / for が描いたノードも含めて)動かす。ラベルの添字は今の位置に付け直す(ハイドレーション\n * は添字で行を組む)。\n */\nfunction placeSsrRow(content: IContent, parent: Node, prev: Node | null, label: string): Comment {\n let bounds = ssrBoundsByContent.get(content);\n if (typeof bounds === 'undefined') {\n bounds = [document.createComment(''), document.createComment('')];\n ssrBoundsByContent.set(content, bounds);\n }\n const [start, end] = bounds;\n start.data = `@@wcs-for-start:${label}`;\n end.data = `@@wcs-for-end:${label}`;\n if (!content.mounted) {\n // 祖先の unmount(if の非表示)で外れた行は、中身だけが外れて境界が残る。外してから置き直す\n start.remove();\n end.remove();\n }\n const ref = prev === null ? null : prev.nextSibling;\n if (start.parentNode === null) {\n // 新しい行・プールから戻す行・祖先の unmount で外れた行・その場で使い回す行(外すときに境界を外した):\n // 境界を置いてから中身を挟む(中の if / for は、この後の活性化が境界の内側へ描く)\n parent.insertBefore(start, ref);\n parent.insertBefore(end, ref);\n content.mountAfter(start);\n } else if (ref !== start) {\n let node: Node = start;\n while (node !== end) {\n const next = node.nextSibling as Node;\n parent.insertBefore(node, ref);\n node = next;\n }\n parent.insertBefore(end, ref);\n }\n return end;\n}\n\n// テスト用ヘルパー(内部状態の操作)\nexport function __test_setContentByListIndex(node: Node, index: IListIndex, content: IContent | null): void {\n setContent(node, index, content);\n}\n\nexport function __test_deleteLastNodeByNode(node: Node): void {\n lastNodeByNode.delete(node);\n}\n\n// SSR ハイドレーション用: Content を ListIndex に登録する\nexport function hydrateSetContent(node: Node, index: IListIndex, content: IContent): void {\n setContent(node, index, content);\n}\n\nexport function hydrateSetLastNode(node: Node, lastNode: Node): void {\n lastNodeByNode.set(node, lastNode);\n}\n\n// SSR ハイドレーション用: サーバーが描いた並びを、この for が描いた並びとして記録する(クライアントで描いた\n// for と同じく、要素の書き込みが描画の基準を書き込む前の写しへ移せるように — #351)\nexport function hydrateSetRenderedList(node: Node, list: readonly unknown[]): void {\n renderedListByNode.set(node, getRenderedList(list));\n}\n\nexport function __test_deleteContentByNode(node: Node): void {\n contentByListIndexByNode.delete(node);\n}\n\nfunction getPooledContents(bindingInfo: IBindingInfo): IContent[] {\n return pooledContentsByNode.get(bindingInfo.node) || [];\n}\n\n// プールの上限(アンカーごと)。プールはアンカー(文書に永続するコメントノード)\n// から content とその DOM サブツリー・バインディング群を強参照するため、無制限だと\n// 大きなリストのクリア後もメモリが解放されない(10k 行で 10MB 級)。上限超過分は\n// contentSetByNode の台帳からも外して GC 可能にする。再追加時は createContent で\n// 作り直すコストと引き換えになる。\nconst MAX_POOLED_CONTENTS = 1000;\nlet maxPooledContents = MAX_POOLED_CONTENTS;\n\n// テスト用: プール上限の変更と現在のプールサイズ取得\nexport function __test_setMaxPooledContents(limit: number): number {\n const prev = maxPooledContents;\n maxPooledContents = limit;\n return prev;\n}\n\nexport function __test_getPooledContentsCount(node: Node): number {\n return (pooledContentsByNode.get(node) || []).length;\n}\n\nfunction setPooledContent(bindingInfo: IBindingInfo, content: IContent): void {\n let contents = pooledContentsByNode.get(bindingInfo.node);\n if (typeof contents === 'undefined') {\n contents = [];\n pooledContentsByNode.set(bindingInfo.node, contents);\n }\n if (contents.length < maxPooledContents) {\n contents.push(content);\n } else {\n // 上限超過: content を完全に手放す。contentSetByNode は createContent 時に\n // 追加されたきり解放経路が無いため、ここで外さないと GC できない。\n deleteContentByNode(bindingInfo.node, content);\n }\n}\n\n/**\n * 親の中身を一括で捨てて良いか(全行削除の近道)の判定に数えるノードか。要素・空白でないテキストの\n * ほかに、**構造ディレクティブのアンカー(コメント)** も数える(#4)。数えないと、同じ親に居る `if` の\n * アンカーまで textContent='' で消え、その `if` は以後何も描けない — 行の中が `if` だけの形では、\n * 行の器ごと壊れる(行を描き直さない main では表に出ないが、消えているのは同じ)。\n */\nfunction countsAsParentContent(node: Node): boolean {\n if (node.nodeType === Node.ELEMENT_NODE) {\n return true;\n }\n if (node.nodeType === Node.TEXT_NODE) {\n return (node.textContent?.trim() ?? '') !== '';\n }\n return node.nodeType === Node.COMMENT_NODE && (node as Comment).data.startsWith('@@wcs-');\n}\n\nfunction isOnlyNodeInParentContent(firstNode: Node, lastNode: Node): boolean {\n let prevCheckNode = firstNode.previousSibling;\n let nextCheckNode = lastNode.nextSibling;\n let onlyNode = true;\n while(prevCheckNode !== null) {\n if (countsAsParentContent(prevCheckNode)) {\n onlyNode = false;\n break;\n }\n prevCheckNode = prevCheckNode.previousSibling;\n }\n while(nextCheckNode !== null) {\n if (countsAsParentContent(nextCheckNode)) {\n onlyNode = false;\n break;\n }\n nextCheckNode = nextCheckNode.nextSibling;\n }\n return onlyNode;\n}\n\n// A stable content may be left in place only when its first node verifiably\n// follows the settled walk position in the same tree: the listIndexes ledger\n// can lag the physical DOM (element-write swaps reorder listIndexes without\n// moving nodes; hidden regions unmount contents that stay registered). Empty\n// contents (null firstNode) always take the settle walk so their mount\n// bookkeeping matches the pre-LIS behavior.\nfunction isPhysicallyAfter(lastNode: Node, firstNode: Node | null): boolean {\n if (firstNode === null) {\n return false;\n }\n if (lastNode.nextSibling === firstNode) {\n return true;\n }\n const position = lastNode.compareDocumentPosition(firstNode);\n return (position & Node.DOCUMENT_POSITION_FOLLOWING) !== 0\n && (position & Node.DOCUMENT_POSITION_DISCONNECTED) === 0;\n}\n\ninterface IInPlaceContents {\n /** 入る行の listIndex → その場で使い回す Content */\n readonly byAddedIndex: Map<IListIndex, IContent>;\n readonly reused: Set<IContent>;\n}\n\n/**\n * 要素書き込みの入れ替えを描き直す差分(基準が「書き込む前の並びの写し」— swapBaselineList.ts)で、\n * 同じ位置の「外す行」と「入る行」を組にし、外す行の Content を入る行にその場で使い回す(#4)。\n * 行の置き換え(リストに無かった値の書き込み)はその位置の行が新しい行に替わるだけなので、プールを通して\n * ブロックを DOM から外す必要が無い — 外すと、双方向バインドの入力で打鍵ごとにフォーカスが失われる。\n * 配列の置換の差分は対象にしない(外した行の Content はこれまでどおりプールを通す)。\n */\nfunction collectInPlaceContents(\n contentMap: WeakMap<IListIndex, IContent>,\n lastValue: unknown,\n diff: IListDiff,\n): IInPlaceContents | null {\n if (!isSwapBaselineList(lastValue)) {\n return null;\n }\n let inPlace: IInPlaceContents | null = null;\n for (let position = 0; position < diff.newIndexes.length; position++) {\n const added = diff.newIndexes[position];\n const removed = diff.oldIndexes[position];\n const content = diff.addIndexSet.has(added) && diff.deleteIndexSet.has(removed)\n ? contentMap.get(removed)\n : undefined;\n if (typeof content === \"undefined\") {\n continue;\n }\n inPlace ??= { byAddedIndex: new Map(), reused: new Set() };\n inPlace.byAddedIndex.set(added, content);\n inPlace.reused.add(content);\n }\n return inPlace;\n}\n\nconst STRUCTURAL_BINDING_TYPES = new Set(['if', 'elseif', 'else', 'for']);\n\n/**\n * 使い回す Content の「適用済み」の印を落とす。入れ子の構造ディレクティブが持つ Content も辿る —\n * `if` の中の `for` や、`elseif` / `else` のアンカーは行の Content ではなく**内側の** Content に\n * 属するので、行の binding だけ落としても新しい行として適用し直されない(印が残ったまま\n * activateContent の applyChange に飛ばされ、解体した内側が描き直されないまま空になる)。\n */\nfunction clearAppliedMarks(content: IContent, context: IApplyContext): void {\n for (const binding of getBindingsByContent(content)) {\n context.appliedBindingSet.delete(binding);\n if (!STRUCTURAL_BINDING_TYPES.has(binding.bindingType)) {\n continue;\n }\n for (const nested of getContentSetByNode(binding.node)) {\n clearAppliedMarks(nested, context);\n }\n }\n}\n\n/**\n * 位置が変わった行の添字の束縛(`$1` …)を当て直す。行の中の入れ子の構造ディレクティブ(createContent が\n * 同じ列に入れる)の Content — 内側の for の行・if の枝、その奥 — も辿る(#360)。内側の for は同じ配列を\n * 描き続けるので差分が出ず、if は条件が変わらないので、ここで辿らないと外側の軸の添字が古いまま残る。\n * 辿るのは、中(入れ子の奥も含む)で動いた行の段の添字(`movedBit` — `for: rows` の行なら `$1`)を使う入れ子\n * だけ。それ以外の添字(外側の行の番号・入れ子の行の自分の番号)は動いても変わらない(#390)。\n * 添字を条件に持つ構造ディレクティブ(`if: $1|lt(2)`)は当て直してから辿る(真のままなら枝は描き直されない)。\n * 外れている Content(プールの行・偽の if の枝)は辿らない(戻すときの活性化が全部の束縛を当てる)。\n */\nfunction applyIndexBindings(content: IContent, context: IApplyContext, movedBit: number): void {\n for (const binding of getIndexBindingsByContent(content)) {\n if (!STRUCTURAL_BINDING_TYPES.has(binding.bindingType)) {\n applyChange(binding, context);\n continue;\n }\n if (binding.statePathName in INDEX_BY_INDEX_NAME) {\n applyChange(binding, context);\n }\n if ((getIndexBitsByBinding(binding) & movedBit) === 0) {\n continue;\n }\n for (const nested of getContentSetByNode(binding.node)) {\n if (nested.mounted) {\n applyIndexBindings(nested, context, movedBit);\n }\n }\n }\n}\n\n/**\n * 入れ子の `for` が持つ Content を解体して台帳から外す(#4)。その場で使い回す行の中身は新しい行として\n * 作り直されるので、外した Content をアンカーの content 台帳(contentSetByNode)に残すと、置き換えの\n * たびに伸び続ける。プールへ返さないのは、返すと次の適用で内側の `for` が「全行削除」の近道\n * (親の textContent を空にする)に入り、囲む `if` のアンカーごと行を壊すため。`if` の Content は\n * アンカーごとに 1 つを使い回すので外さない。\n */\nfunction dropNestedContents(content: IContent): void {\n for (const binding of getBindingsByContent(content)) {\n if (!STRUCTURAL_BINDING_TYPES.has(binding.bindingType)) {\n continue;\n }\n const dropped = binding.bindingType === 'for';\n for (const nested of getContentSetByNode(binding.node)) {\n dropNestedContents(nested);\n if (!dropped || !nested.mounted) {\n continue;\n }\n deactivateContent(nested);\n nested.unmount();\n deleteContentByNode(binding.node, nested);\n // 描いた行を捨てたので、その for が描いた並びも捨てて白紙から描かせる(#320。残すと次の適用が、\n // 捨てた行を自分の行として差分の旧側に数え、台帳から外した Content をプールへ戻してしまう)。行の Content の\n // 台帳も捨てる — 残すと、同じ行を別の外側の行の for も描いている(2 つの外側の行が同じ配列を持つ — #393)とき、\n // その for がアドレスに残した描画の基準を自分の描いた並びと取り違え、描いていない行を探して落ちた\n renderedListByNode.delete(binding.node);\n contentByListIndexByNode.delete(binding.node);\n }\n }\n}\n\nfunction setContent(node: Node, listIndex: IListIndex, content: IContent | null): void {\n let contentByListIndex = contentByListIndexByNode.get(node);\n if (typeof contentByListIndex === 'undefined') {\n if (content === null) {\n return;\n }\n contentByListIndex = new WeakMap<IListIndex, IContent>();\n contentByListIndexByNode.set(node, contentByListIndex);\n }\n if (content === null) {\n contentByListIndex.delete(listIndex);\n } else {\n contentByListIndex.set(listIndex, content);\n }\n}\n\nexport function applyChangeToFor(\n bindingInfo: IBindingInfo, \n context: IApplyContext,\n newValue: unknown, \n): void {\n const listPathInfo = bindingInfo.statePathInfo;\n const listIndex = getListIndexByBindingInfo(bindingInfo);\n const absAddress = getAbsoluteStateAddressByBinding(bindingInfo);\n const recordedLastValue = getLastListValueByAbsoluteStateAddress(absAddress);\n const rendered = renderedListByNode.get(bindingInfo.node);\n let lastValue: readonly unknown[];\n let diff: IListDiff;\n // 共有の記録が、この for の描いた並びを置いて進んだ(#320)。同じリストを描く別の for だけが描いた —\n // この for は `if` で消されていた・DOM から外されていた — か、行の Content の使い回しでこの for が\n // 別の行に付け替わった。行の台帳(どの値がどの行か)は共有の差分で進め、描き替えは自分が描いた行と\n // 今の行を行の同一性で突き合わせて決める。描いた並びが空なら台帳は無い(全行 add)。\n // 今の行の親がこの配列を手放した外側の行(台帳の食い違い)なら突き合わせに使わない — 別の行の値を描き、その後の\n // 書き込みを別の行へ着地させる。従来の差分(行を付け替える)に戻す。行の親が、この配列をまだ持つ別の外側の行なのは\n // 食い違いではない(2 つの外側の行が同じ配列を持つ — #393)\n // 同じ配列を描く別の `for` で要素書き込みの入れ替えが揃い、この for はまだその配列を描く(setByAddress の\n // notifySwappedList・#379)。自分が描いた並び(入れ替えの前の写しへ移された記録)といまの台帳を、行の同一性だけで\n // 突き合わせる。差分(createListDiff)は通さない — 台帳の行の親を、書いていない外側の行へ付け替えてしまう(#256)\n const swapped = typeof rendered !== 'undefined' && isSwappedList(absAddress, newValue);\n const shared = !swapped && typeof rendered !== 'undefined' && rendered.value !== recordedLastValue\n ? createListDiff(listIndex, recordedLastValue, newValue)\n : null;\n if (swapped) {\n lastValue = rendered!.value;\n diff = calcDiffIndexes(getListIndexesByList(lastValue)!, getListIndexesByList(newValue as unknown[])!);\n } else if (shared !== null && shared.newIndexes.every((row) => row.parentListIndex === listIndex || isRetiredListIndex(row.parentListIndex!) || !hasReleasedList(newValue as unknown[], row.parentListIndex!))) {\n lastValue = rendered!.value;\n diff = calcDiffIndexes(getListIndexesByList(lastValue) ?? [], shared.newIndexes);\n } else {\n // lastListValue はアドレスキーの共有台帳。まだ何も描いていない binding ノード\n //(content 台帳が空)が、既に描画済みのアドレスに後から参加する形 — マウント\n // スコープの再初期化(コンポーネントが connectedCallback で shadow を張り直す)や\n // 後着ノードの binder 適用 — では、共有の記録で差分を取ると「既存 content の\n // 再利用・維持」を指示され、この binding には無いので落ちる。自分の台帳が空なら\n // 白紙から全行 add で描く(同じアドレスの他の binding の差分には影響しない)\n lastValue = recordedLastValue.length > 0 && !contentByListIndexByNode.has(bindingInfo.node)\n ? []\n : recordedLastValue;\n diff = createListDiff(listIndex, lastValue, newValue);\n }\n const newListValue = Array.isArray(newValue) ? newValue : [];\n context.newListValueByAbsAddress.set(absAddress, newListValue);\n renderedListByNode.set(bindingInfo.node, getRenderedList(newListValue));\n\n let contentMap = contentByListIndexByNode.get(bindingInfo.node);\n // 要素書き込みの入れ替えを描き直す差分では、同じ位置で外す行の Content を入る行がその場で使い回す(#4)\n const inPlaceContents = typeof contentMap !== 'undefined' ? collectInPlaceContents(contentMap, lastValue, diff) : null;\n const fullDelete = Array.isArray(lastValue)\n && lastValue.length === diff.deleteIndexSet.size\n && diff.deleteIndexSet.size > 0;\n // その場で使い回す Content があるときは、親を空にする近道を取らない(使い回す行の DOM も消える)\n if (fullDelete && inPlaceContents === null && bindingInfo.node.parentNode !== null) {\n let isOnlyNode = isOnlyNodeInParentContentByNode.get(bindingInfo.node);\n if (typeof isOnlyNode === 'undefined') {\n const lastNode = lastNodeByNode.get(bindingInfo.node) || bindingInfo.node;\n // 描いた行が祖先の unmount(`if` の非表示・プールに入った行)で既に外れているなら、アンカーから数える。\n // 外れた末尾には後ろの兄弟が無いので、同じ親に居る兄弟の `for` / `if` を見落として「この for だけ」と\n // 覚え、親を空にする近道がそのアンカーごと消す(プールから戻した行で内側の for が描いていた行を外す形)\n isOnlyNode = isOnlyNodeInParentContent(bindingInfo.node, lastNode.parentNode === bindingInfo.node.parentNode ? lastNode : bindingInfo.node);\n isOnlyNodeInParentContentByNode.set(bindingInfo.node, isOnlyNode);\n }\n if (isOnlyNode) {\n const parentNode = bindingInfo.node.parentNode;\n // 全行は 1 つの mutation record で消えるので、親に「framework の削除がこの件数」と 1 回書けば\n // observer はその record を丸ごと飛ばせる(行ごとの印を消費しない。bindings/observerSkip.ts)\n markObserverSkipRemovedChildren(parentNode, parentNode.childNodes.length);\n parentNode.textContent = '';\n parentNode.appendChild(bindingInfo.node);\n }\n }\n // 全削除時、プールに収まらない content は再利用されないため、per-binding の\n // teardown(listener 解除・アドレス台帳・loopContext 掃除)を丸ごと省略して\n // ノードごと GC に任せる(tryDestroy)。プール行きの分だけ従来どおり解体する\n // (プール行は binding が生存し続けるため address キャッシュのクリアが必須)。\n // content 台帳の WeakMap ビルトインは V8 プロファイルで本関数の self に計上される\n // ホットスポット: 外側の node→map 解決はループ外に持ち上げ、fullDelete(旧全行が\n // deleteIndexSet に載る=台帳の全エントリが消える)では per-index delete を廃して\n // 台帳ごと 1 回で手放す。\n let poolBudget = fullDelete\n ? maxPooledContents - getPooledContents(bindingInfo).length\n : Number.POSITIVE_INFINITY;\n const ssrMode = inSsr();\n if (typeof contentMap !== 'undefined') {\n // Set の for...of は行ごとに反復子の結果オブジェクトを割り当てる(消去の scavenge の引き金)ので forEach で回す\n const map = contentMap;\n diff.deleteIndexSet.forEach((deleteIndex) => {\n const content = map.get(deleteIndex);\n if (typeof content !== 'undefined') {\n if (ssrMode) {\n // 外す行の境界も外す(#334。その場で使い回す行は、足す行として境界を置き直す)。SSR の外で\n // 描いた行(同じ文書で後から SSR が始まった)は境界を持たない\n ssrBoundsByContent.get(content)?.forEach((bound) => bound.remove());\n ssrBlockRemoval.seen = true;\n }\n if (inPlaceContents !== null && inPlaceContents.reused.has(content)) {\n // 同じ位置に入る行がその場で使い回す。自分のノードは DOM に残し、プールにも入れないが、\n // 解体は unmount と同じ(ネストした for / if の Content とアドレス台帳を落とす)\n deactivateContent(content);\n dropNestedContents(content);\n content.unmountInPlace();\n } else if (poolBudget <= 0 && content.tryDestroy()) {\n deleteContentByNode(bindingInfo.node, content);\n } else {\n deactivateContent(content);\n content.unmount();\n setPooledContent(bindingInfo, content);\n poolBudget -= 1;\n }\n if (!fullDelete) {\n map.delete(deleteIndex);\n }\n }\n });\n if (fullDelete) {\n contentByListIndexByNode.delete(bindingInfo.node);\n contentMap = undefined;\n }\n }\n\n let lastNode = bindingInfo.node;\n const elementPathInfo = getPathInfo(listPathInfo.path + '.' + WILDCARD);\n const loopContextStack = context.stateElement.loopContextStack;\n // When the new order contains inversions, contents in the stable set (an LIS\n // of old positions) keep their relative order and must not be moved; moving\n // only the rest avoids the cascade where one swap relocates every row in\n // between. null = no inversions; the position guard below then does no moves.\n const stableIndexSet = computeStableIndexSet(diff);\n let fragment: DocumentFragment | null = null;\n if (diff.newIndexes.length == diff.addIndexSet.size \n && diff.newIndexes.length > 0\n && lastNode.isConnected\n && inPlaceContents === null\n ) {\n // 全部追加の場合はまとめて処理\n fragment = document.createDocumentFragment();\n setRootNodeByFragment(fragment, context.rootNode);\n }\n // SSR の境界コメントのラベル(`<uuid>:<path>:` + 行の添字)\n const ssrLabel = ssrMode ? `${bindingInfo.uuid}:${listPathInfo.path}:` : '';\n // 自動命名ポリシーは行ごとではなく apply ごとに 1 回だけ引く\n // (docs/view-transition-design.md §6)。既定の manual では null で、\n // 以降の行ループは分岐 1 つ分しか増えない。\n const autoNaming = getAutoNaming();\n // 追加行ごとの WeakMap 解決を避けるためプール配列も 1 回だけ引く(プールの配列\n // 実体は setPooledContent が一度作ったら不変なので、delete ループ後の参照で安定)\n const pooledContents = pooledContentsByNode.get(bindingInfo.node);\n for(const index of diff.newIndexes) {\n let content: IContent | undefined;\n // add\n if (diff.addIndexSet.has(index)) {\n const stateAddress = createStateAddress(elementPathInfo, index);\n loopContextStack.createLoopContext(stateAddress, (loopContext) => {\n content = inPlaceContents?.byAddedIndex.get(index)\n ?? (typeof pooledContents !== 'undefined' ? pooledContents.pop() : undefined);\n if (typeof content === 'undefined') {\n content = createContent(bindingInfo);\n } else {\n // プール(か同じ位置)から使い回す Content の binding は、同じバッチで**外した行として**適用済みのことがある。\n // 外した行のアドレスへの書き込み(行の葉・要素の置き換え)で enqueue された binding が、この `for`\n // より先に適用された形。印が残ると activateContent の applyChange が飛ばし、新しい行に外した行の\n // 値が残る(表示と state が食い違う)。新しい行として適用し直す\n clearAppliedMarks(content, context);\n // DOM に戻す前に新しい行のループ文脈を張る。戻した瞬間に中のマウント済みコンポーネントの\n // 再接続(`$connectedCallback`)が同期で走り、要素の行を引く(#368)\n bindLoopContextToContent(content, loopContext);\n }\n // コンテント活性化の前にDOMツリーに追加しておく必要がある\n if (ssrMode) {\n lastNode = fragment !== null\n ? placeSsrRow(content, fragment, null, ssrLabel + index.index)\n : placeSsrRow(content, lastNode.parentNode!, lastNode, ssrLabel + index.index);\n } else if (fragment !== null) {\n content.appendTo(fragment);\n } else if (lastNode.nextSibling !== content.firstNode) {\n // Ensure content is in correct position (e.g. if previous siblings were deleted/moved)\n content.mountAfter(lastNode);\n }\n // コンテントを活性化\n activateContent(content, loopContext, context);\n if (autoNaming !== null) {\n applyTransitionName(content, \"row\", autoNaming);\n }\n });\n if (typeof content === 'undefined') {\n raiseError(`Content not found for ListIndex: ${index.index} at path \"${listPathInfo.path}\"`);\n }\n if (inPlaceContents !== null && inPlaceContents.reused.has(content)) {\n // その場で使い回した行の中のコンポーネントは DOM から外れない = 付け替えを知らせる\n // connectedCallback が来ないので、マウントスコープを新しい行の listIndex へ張り直す(#4)。\n // スコープ機能の rowReused hook(webComponent/addressHooks.ts)。hook の無い state は判定 1 個で抜ける\n const hooks = context.stateElement.addressHooks;\n if (hooks) {\n const reused = hooks.rowReused;\n for (let i = 0; i < reused.length; i++) {\n reused[i](context.stateElement, content);\n }\n }\n }\n } else {\n // getContent 相当(undefined→null 正規化は後段の raiseError 判定が null 比較のため維持)\n content = (typeof contentMap !== 'undefined' ? contentMap.get(index) ?? null : null)!;\n if (diff.changeIndexSet.has(index)) {\n // change(値の変わる添字は、この for の段の `$d` — d はリストのパスのワイルドカードの数 + 1)\n applyIndexBindings(content, context, indexBit(listPathInfo.wildcardCount));\n }\n // Update lastNode for next iteration to ensure correct order\n // Ensure content is in correct position (e.g. if previous siblings were deleted/moved)\n if (content === null) {\n raiseError(`Content not found for ListIndex: ${index.index} at path \"${listPathInfo.path}\"`);\n }\n // 祖先の unmount(if の非表示など)で解体された行は、ここで物理的に\n // 戻されるだけでは binding が dispose 済みのまま復活しない。位置合わせの\n // 前に判定しておき(mountAfter が mounted を立てる)、戻した後に再活性化する。\n const unmountedByAncestor = !content.mounted;\n if (ssrMode) {\n lastNode = placeSsrRow(content, lastNode.parentNode!, lastNode, ssrLabel + index.index);\n } else if (!(stableIndexSet !== null && stableIndexSet.has(index) && isPhysicallyAfter(lastNode, content.firstNode))\n && lastNode.nextSibling !== content.firstNode) {\n // Stable contents are already in correct relative order — but only\n // trust that after physical verification (see isPhysicallyAfter).\n // Contents out of order (and everything unverifiable) settle via the\n // self-healing mountAfter walk.\n content.mountAfter(lastNode);\n }\n if (unmountedByAncestor) {\n // 再活性化しないと、行の同一性が保たれる更新が以後すべて無視される\n // (docs/state-deactivated-content-stale-update.md)。activate は\n // disposed record の再構築を含むので、プール再利用と同じ経路で戻る。\n const revivedContent = content;\n const stateAddress = createStateAddress(elementPathInfo, index);\n loopContextStack.createLoopContext(stateAddress, (loopContext) => {\n activateContent(revivedContent, loopContext, context);\n });\n }\n }\n if (!ssrMode) {\n // SSR では行の終端コメント(placeSsrRow が返す)のまま\n lastNode = content.lastNode || lastNode;\n }\n if (typeof contentMap === 'undefined') {\n contentMap = new WeakMap<IListIndex, IContent>();\n contentByListIndexByNode.set(bindingInfo.node, contentMap);\n }\n contentMap.set(index, content);\n }\n lastNodeByNode.set(bindingInfo.node, lastNode);\n if (fragment !== null) {\n // Mount all at once\n bindingInfo.node.parentNode!.insertBefore(fragment, bindingInfo.node.nextSibling);\n setRootNodeByFragment(fragment, null);\n }\n}\n","import { bindLoopContextToContent } from \"../bindings/bindLoopContextToContent\";\nimport { config, inSsr, ssrBlockRemoval } from \"../config\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { activateContent, deactivateContent } from \"../structural/activateContent\";\nimport { getContentSetByNode } from \"../structural/contentsByNode\";\nimport { createContent } from \"../structural/createContent\";\nimport { IContent } from \"../structural/types\";\nimport { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\nimport { applyTransitionName, getAutoNaming } from \"./viewTransitionNaming\";\n\nfunction bindingInfoText(bindingInfo: IBindingInfo): string {\n return `${bindingInfo.bindingType} ${bindingInfo.statePathName} ${bindingInfo.outFilters.map(f => f.filterName).join('|')} ${bindingInfo.node.isConnected ? '(connected)' : '(disconnected)'}`;\n}\n\nexport function applyChangeToIf(\n bindingInfo: IBindingInfo,\n context: IApplyContext,\n rawNewValue: unknown,\n): void {\n const newValue = Boolean(rawNewValue);\n let content: IContent | undefined;\n const contents = getContentSetByNode(bindingInfo.node);\n if (contents.size === 0) {\n content = createContent(bindingInfo);\n } else {\n content = contents.values().next().value!;\n }\n const ssrMode = inSsr();\n const uuid = bindingInfo.uuid ?? '';\n const keyword = bindingInfo.bindingType; // if, elseif, else\n if (!newValue) {\n if (config.debug) {\n console.log(`unmount if content : ${bindingInfoText(bindingInfo)}`);\n }\n if (ssrMode && content.mounted) ssrBlockRemoval.seen = true;\n deactivateContent(content);\n content.unmount();\n }\n if (newValue) {\n if (config.debug) {\n console.log(`mount if content : ${bindingInfoText(bindingInfo)}`);\n }\n // DOM に戻す前にループ文脈を張る。再表示で戻した瞬間に中のマウント済みコンポーネントの\n // 再接続(`$connectedCallback`)が同期で走り、要素の行を引く(#368)\n const loopContext = getLoopContextByNode(bindingInfo.node);\n bindLoopContextToContent(content, loopContext);\n if (ssrMode) {\n // 描いてある枝(真のままの描き直し)は境界の組ごとその場に残す(#356)。組を置き直すと枝の\n // トップレベルのノードだけが新しい組へ移り、先に描いた入れ子の枝・行は古い組の中に残った\n if (!content.mounted) {\n const startComment = document.createComment(`@@wcs-${keyword}-start:${uuid}:${bindingInfo.statePathName}`);\n bindingInfo.node.parentNode!.insertBefore(startComment, bindingInfo.node.nextSibling);\n content.mountAfter(startComment);\n const endComment = document.createComment(`@@wcs-${keyword}-end:${uuid}:${bindingInfo.statePathName}`);\n const afterNode = content.lastNode ?? startComment;\n afterNode.parentNode!.insertBefore(endComment, afterNode.nextSibling);\n }\n } else {\n content.mountAfter(bindingInfo.node);\n }\n activateContent(content, loopContext, context);\n // 自動命名(docs/view-transition-design.md §6)。manual(既定)では null。\n const autoNaming = getAutoNaming();\n if (autoNaming !== null) {\n applyTransitionName(content, \"branch\", autoNaming);\n }\n }\n}\n\n","/**\n * SSR 時に HTML 属性で表現できないプロパティバインディングを蓄積するストア。\n * ハイドレーション時にクライアント側で復元する。\n */\n\nexport interface ISsrPropertyEntry {\n propName: string;\n value: unknown;\n}\n\n// node → プロパティエントリのリスト\nconst store: WeakMap<Node, ISsrPropertyEntry[]> = new WeakMap();\n\nexport function addSsrProperty(node: Node, propName: string, value: unknown): void {\n let entries = store.get(node);\n if (!entries) {\n entries = [];\n store.set(node, entries);\n }\n // 同じプロパティの既存エントリは上書き\n const existing = entries.find(e => e.propName === propName);\n if (existing) {\n existing.value = value;\n } else {\n entries.push({ propName, value });\n }\n}\n\nexport function getSsrProperties(node: Node): ISsrPropertyEntry[] {\n return store.get(node) ?? [];\n}\n\nexport function getAllSsrPropertyNodes(): Node[] {\n // WeakMap は列挙不可なので、別途トラッキングが必要\n return Array.from(trackedNodes);\n}\n\nconst trackedNodes: Set<Node> = new Set();\n\nexport function trackSsrPropertyNode(node: Node): void {\n trackedNodes.add(node);\n}\n\nexport function clearSsrPropertyStore(): void {\n trackedNodes.clear();\n}\n","/**\n * Trusted Types (`require-trusted-types-for 'script'`) 対応。正本は docs/csp.md §7。\n *\n * state が HTML sink に流すのは **状態の値**(`innerHTML: path` などのプロパティ\n * バインド)で、ユーザー入力が混ざり得る文字列そのもの。ここに identity policy を\n * 噛ませて通すのは TT の無効化と同義なので、state は自前の policy を作らない。\n * 利用側が sanitizer を持つ policy を注入したときだけ通し、無ければ従来どおり\n * ブラウザに弾かせる(ただし何を設定すれば直るかは必ず言う)。\n *\n * 注入口は全 @wcstack パッケージ共通のグローバルスロット。buildless(CDN 一発)でも\n * inline script 1 本で差し込める:\n *\n * ```js\n * globalThis[Symbol.for(\"wcstack.trustedTypes.policy\")] =\n * trustedTypes.createPolicy(\"my-app\", { createHTML: (s) => DOMPurify.sanitize(s) });\n * ```\n *\n * バンドラ経由なら `setTrustedTypesPolicy()` を使う。値は毎回スロットから読むので\n * 後から差し替えても効く(identity policy を作る router / worker 側だけは\n * `createPolicy` の重複を避けるため生成結果をシングルトンで保持する)。\n */\n\nexport interface IWcsTrustedTypesPolicy {\n createHTML?(input: string): unknown;\n createScriptURL?(input: string): unknown;\n}\n\n/** 利用側が policy を差し込むグローバルスロット(全 @wcstack パッケージ共通)。 */\nexport const TRUSTED_TYPES_POLICY_SLOT = Symbol.for(\"wcstack.trustedTypes.policy\");\n\ntype SymbolSlotHolder = { [key: symbol]: unknown };\n\n/**\n * 利用側が注入した policy を返す。state はここに identity policy をフォールバック\n * させない(それをやると TT を無効化することになる)。\n */\nexport function getTrustedTypesPolicy(): IWcsTrustedTypesPolicy | null {\n const value = (globalThis as SymbolSlotHolder)[TRUSTED_TYPES_POLICY_SLOT];\n if (value === null || typeof value !== \"object\") return null;\n return value as IWcsTrustedTypesPolicy;\n}\n\n/** 利用側 policy を設定する(`null` で解除)。最初のバインド適用前に呼ぶこと。 */\nexport function setTrustedTypesPolicy(policy: IWcsTrustedTypesPolicy | null): void {\n (globalThis as SymbolSlotHolder)[TRUSTED_TYPES_POLICY_SLOT] = policy;\n}\n\n/**\n * TrustedHTML が要求されるプロパティか。`textContent` などの安全な sink は含めない。\n * ホットパス(全プロパティ書き込み)から呼ばれるので文字列比較だけで済ませる。\n */\nexport function isHtmlSinkProp(prop: string): boolean {\n return prop === \"innerHTML\" || prop === \"outerHTML\" || prop === \"srcdoc\";\n}\n\n/**\n * HTML sink へ書く値を利用側 policy に通す。policy が無ければ値をそのまま返す\n * = TT 有効下ではブラウザが弾く(意図どおり)。policy がある場合は TT 非対応\n * ブラウザでも通す: sanitizer は Chromium だけで効いても意味がないため。\n */\nexport function trustHtmlValue(value: unknown): unknown {\n if (typeof value !== \"string\") return value;\n const policy = getTrustedTypesPolicy();\n const createHTML = policy?.createHTML;\n if (typeof createHTML !== \"function\") return value;\n return createHTML.call(policy, value);\n}\n\nlet _enforced: boolean | undefined = undefined;\n\n/**\n * TT が実際に強制されているかを実測する。エラーメッセージの文言に依存しないよう、\n * 使い捨ての要素へ実際に書いて確かめる。`default` policy がある場合は書き込みが\n * 通る=我々の書き込みも通るので、正しく false になる。\n *\n * cold path(書き込みが失敗した後)でしか呼ばれない。\n */\nexport function isTrustedTypesEnforced(): boolean {\n if (_enforced !== undefined) return _enforced;\n if (!(\"trustedTypes\" in globalThis)) {\n _enforced = false;\n return _enforced;\n }\n try {\n document.createElement(\"div\").innerHTML = \"<i></i>\";\n _enforced = false;\n } catch {\n _enforced = true;\n }\n return _enforced;\n}\n\nlet _reported = false;\n\n/** テスト用: 実測キャッシュと一度きりの診断をリセットする。 */\nexport function _resetTrustedTypesDiagnostics(): void {\n _enforced = undefined;\n _reported = false;\n}\n\n/**\n * HTML sink への書き込み失敗を診断する。applyChangeToProperty の catch は\n * `config.debug` 時しか warn しないため、TT が原因のときは黙って壊れていた。\n * 原因と直し方が分かる形で一度だけ報告する。\n */\nexport function reportTrustedTypesBlock(element: Element, prop: string): void {\n if (_reported) return;\n if (!isTrustedTypesEnforced()) return;\n _reported = true;\n const hasPolicy = typeof getTrustedTypesPolicy()?.createHTML === \"function\";\n const cause = hasPolicy\n ? \"The injected policy's createHTML() did not return a TrustedHTML.\"\n : \"No sanitizing policy is installed, and @wcstack/state deliberately does not \"\n + \"pass state values through an identity policy — that would defeat the CSP.\";\n console.error(\n `[@wcstack/state] Writing to \"${prop}\" was blocked by Trusted Types `\n + `(require-trusted-types-for 'script'). ${cause}\\n`\n + `Install a sanitizing policy before the first binding is applied:\\n`\n + ` globalThis[Symbol.for(\"wcstack.trustedTypes.policy\")] =\\n`\n + ` trustedTypes.createPolicy(\"my-app\", { createHTML: (s) => DOMPurify.sanitize(s) });\\n`\n + `Or bind the value as text instead of HTML. See docs/csp.md section 7.`,\n { element, property: prop },\n );\n}\n","import { config, inSsr } from \"../config\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { applyMirrorAttribute, getInputAttributeMirror } from \"../event/getInputAttributeMirror\";\nimport { beginPropagationTransaction, extendPropagationContext, getCurrentPropagationContext, getEdgeId, getWireId, runWithPropagationContext, runWithWriteReceipt } from \"../propagation/propagation\";\nimport { isPossibleTwoWay } from \"../event/isPossibleTwoWay\";\nimport { getCustomElement } from \"../getCustomElement\";\nimport { IBindingInfo } from \"../types\";\nimport { componentApplyHooks } from \"../core/componentApplyHooks\";\nimport { IApplyContext } from \"./types\";\nimport { addSsrProperty, trackSsrPropertyNode } from \"./ssrPropertyStore\";\nimport { isHtmlSinkProp, reportTrustedTypesBlock, trustHtmlValue } from \"../trustedTypes\";\n\n// SSR 時に HTML 属性で代替可能なプロパティ\n// これら以外のプロパティは ssrPropertyStore に蓄積してハイドレーション時に復元\nconst SSR_ATTR_PROPS: Record<string, (element: Element, value: unknown) => void> = {\n value(element, value) {\n if (element.tagName === 'TEXTAREA') {\n element.textContent = String(value ?? '');\n } else {\n element.setAttribute('value', String(value ?? ''));\n }\n },\n checked(element, value) {\n if (value) element.setAttribute('checked', '');\n else element.removeAttribute('checked');\n },\n selected(element, value) {\n if (value) element.setAttribute('selected', '');\n else element.removeAttribute('selected');\n },\n disabled(element, value) {\n if (value) element.setAttribute('disabled', '');\n else element.removeAttribute('disabled');\n },\n selectedIndex(element, value) {\n const options = element.querySelectorAll('option');\n const idx = Number(value);\n for (let i = 0; i < options.length; i++) {\n if (i === idx) options[i].setAttribute('selected', '');\n else options[i].removeAttribute('selected');\n }\n },\n};\n\n/**\n * 表示のプロパティは `textContent` / `innerText` / `innerHTML` の 3 つ(要件 B8)。ここへの\n * undefined は「値が無い」ので空にする — 要素の入力と違って生かすべき既定値が無く、\n * スキップすると、使い回した行に前の行の表示が残る。\n *\n * `outerHTML` は **入れない**。`trustedTypes.isHtmlSinkProp` は HTML sink として認めるが、\n * `element.outerHTML = \"\"` は要素そのものを DOM から外すので、「空にする」では済まず束縛先の\n * ノードごと失われる(以降の更新が届かない)。値が無いときはスキップして前の描画を残す方が\n * まだ壊れ方が小さい。`outerHTML:` を表示面として正しく畳むには「置換のやり直し」の設計が要る。\n */\nexport function applyChangeToProperty(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n if (binding.propSegments.length === 1) {\n const displayProp = binding.propSegments[0];\n if (displayProp === \"textContent\" || displayProp === \"innerText\") {\n // テキストの表示プロパティは IDL 側で文字列化される — `textContent` は nullable DOMString\n // (null は空文字)、`innerText` は [LegacyNullToEmptyString]。ブラウザでは生値を代入しても\n // 同じ結果になるが、SSR(happy-dom)の setter は**非文字列の falsy を落とす**ので\n // `textContent: count` が 0 のとき、サーバ HTML だけが空になっていた(ハイドレーション用\n // props には正しい値が載るのでクライアントでは戻る= no-JS / SEO / 初回描画だけが壊れる)。\n // IDL と同じ規則にここで自分で寄せる。副次的に、比較(下の current !== newValue)も\n // 文字列同士になり、数値を束ねた表示が毎回書き直されなくなる。\n // `== null` は null と undefined の両方(意図的な緩い比較)\n newValue = newValue == null ? \"\" : String(newValue);\n } else if (typeof newValue === \"undefined\" && displayProp === \"innerHTML\") {\n // `innerHTML` を上の文字列化に含めない理由: TrustedHTML を String() で潰すと Trusted Types の\n // 強制下で書き込みが拒否される(trustedTypes.trustHtmlValue は非文字列を素通しする)。\n // 値が無いときに空にする規則だけは表示面として共通(要件 B8)\n newValue = \"\";\n }\n }\n // 要素の入力への undefined は「状態が値を持たない=無意見」であり、書き込み自体をスキップして\n // 要素側の既定値を生かす。書き込んでしまうと setter の文字列化で\n // \"undefined\" 属性や removeAttribute が走り要素が壊れる (spread で未初期化\n // slot を配線したときに顕在化)。明示的なクリアは null で表現する。\n // mirror 属性 (applyMirrorAttribute) の「undefined → 属性削除」と同じ語彙。\n if (typeof newValue === \"undefined\") {\n if (config.debug) {\n console.debug(`Skipped property write: state value is undefined.`, {\n element: binding.node,\n propSegments: binding.propSegments,\n statePathName: binding.statePathName,\n });\n }\n return;\n }\n const element = binding.node as Element;\n const propSegments = binding.propSegments;\n if (propSegments.length === 1) {\n const firstSegment = propSegments[0];\n\n const current = (element as any)[firstSegment];\n if (current !== newValue) {\n // 完了前の丸ごとマウント(`state: user`)は、作者の state オブジェクトを親の\n // オブジェクトで置き換えてしまう。あとで戻せるように置き換え前を控える\n // (webComponent/preCompletionWrites.ts — bind-component の機能が core/componentApplyHooks.ts に置く。\n // 置かれていなければ判定 1 回で抜ける)。オブジェクト → オブジェクトの書き込みで\n // 相手がカスタム要素のときだけ台帳に触る(通常の書き込みは typeof 判定で抜ける)。\n if (componentApplyHooks !== null && current !== null && typeof current === 'object'\n && newValue !== null && typeof newValue === 'object'\n && getCustomElement(element) !== null) {\n componentApplyHooks.rememberOverwrittenObject(element, firstSegment, current);\n }\n // Trusted Types: HTML sink (`innerHTML` 等) への書き込みだけ、利用側が注入した\n // sanitizer 付き policy を通す。state が identity policy を作って素通しさせるのは\n // TT の無効化と同義なので採らない(docs/csp.md §7)。sink 以外は文字列比較 3 回で\n // 抜けるので、ホットパスの実コストはほぼ無い。\n const isHtmlSink = isHtmlSinkProp(firstSegment);\n\n const performWrite = (): void => {\n let propertyWriteSucceeded = false;\n try {\n (element as any)[firstSegment] = isHtmlSink ? trustHtmlValue(newValue) : newValue;\n propertyWriteSucceeded = true;\n } catch (error) {\n // TT が原因のときは config.debug に関係なく報告する。ここを黙って握り潰すと\n // 「バインドを書いたのに何も起きない」という最悪の壊れ方をする。\n if (isHtmlSink) {\n reportTrustedTypesBlock(element, firstSegment);\n }\n if (config.debug) {\n console.warn(`Failed to set property '${firstSegment}' on element.`, {\n element,\n newValue,\n error\n });\n }\n }\n // wc-bindable inputs[].attribute ミラー。プロパティ書き込みが成功したときだけ\n // 属性へ反映する。setter が値を拒否した場合に属性だけ進んでしまうと\n // property と attribute が乖離し、attributeChangedCallback や CSS セレクタが\n // 実際のプロパティ値と矛盾した状態で発火するため、ここでガードする。\n if (propertyWriteSucceeded) {\n const mirrorAttr = getInputAttributeMirror(element, firstSegment);\n if (mirrorAttr !== null) {\n try {\n applyMirrorAttribute(element, mirrorAttr, newValue);\n } catch (error) {\n if (config.debug) {\n console.warn(`Failed to mirror attribute '${mirrorAttr}' on element.`, {\n element,\n newValue,\n error\n });\n }\n }\n }\n }\n };\n // Zero-cost fast path (§4 最適化): the propagation edge / WriteReceipt\n // machinery only matters when the element write can *echo* — i.e. the setter\n // may synchronously dispatch an event a two-way wire feeds back to state.\n // `isPossibleTwoWay` is the same conservative check the two-way listener\n // registration uses, and it is cheap for the common one-way case (textContent\n // / class / style on plain elements return false fast). One-way bindings can\n // never re-traverse an edge, so skipping the context/receipt is safe and\n // avoids a per-apply Set copy + receipt allocation. Diamond / coalescing are\n // unaffected — those ride the write-transaction context threaded through the\n // updater, not the element edge.\n if (config.enablePropagationContext && isPossibleTwoWay(element, firstSegment)) {\n // Phase 3: state → element edge の通過を記録し、同じ transaction が\n // 同じ edge を再度通ろうとした場合だけ抑止する(設計書 §4 規則 2)。\n // 書き込みは WriteReceipt scope で包み、setter が同期 dispatch する\n // event が confirmation / 正規化を判定できるようにする(規則 3)。\n const wireId = getWireId(element, firstSegment, binding.statePathName);\n const edgeId = getEdgeId(wireId, \"to-element\");\n const baseContext = _context?.propagationContextByBinding?.get(binding)\n ?? getCurrentPropagationContext()\n ?? beginPropagationTransaction(wireId);\n if (baseContext.visitedEdges.has(edgeId)) {\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"propagation:suppressed\",\n reason: \"visited-edge\",\n transactionId: baseContext.transactionId,\n edgeId,\n node: element,\n member: firstSegment,\n });\n }\n } else {\n const extendedContext = extendPropagationContext(baseContext, edgeId);\n runWithPropagationContext(extendedContext, () =>\n runWithWriteReceipt(element, firstSegment, newValue, wireId, extendedContext.transactionId, performWrite));\n }\n } else {\n performWrite();\n }\n }\n if (inSsr()) {\n const attrHandler = SSR_ATTR_PROPS[firstSegment];\n if (attrHandler) {\n // 属性で代替可能 → HTML 属性に反映\n attrHandler(element, newValue);\n } else {\n // 属性で代替不可 → ハイドレーション用ストアに蓄積\n addSsrProperty(element, firstSegment, newValue);\n trackSsrPropertyNode(element);\n }\n }\n return;\n }\n const firstSegment = propSegments[0];\n let subObject = (element as any)[firstSegment];\n for (let i = 1; i < propSegments.length - 1; i++) {\n const segment = propSegments[i];\n if (subObject == null) {\n return;\n }\n subObject = subObject[segment];\n }\n const lastSegment = propSegments[propSegments.length - 1];\n const oldValue = subObject[lastSegment];\n if (oldValue !== newValue) {\n if (Object.isFrozen(subObject)) {\n if (config.debug) {\n console.warn(`Attempting to set property on frozen object.`, {\n element,\n propSegments,\n oldValue,\n newValue\n });\n }\n return;\n }\n // 完了前の部分マウント(`state.theme: theme`)が、作者の state オブジェクトに無かった\n // キーを作る(積み)ことを控える。R1 の衝突報告はこのキーを作者のものとして扱わない\n // (webComponent/preCompletionWrites.ts — core/componentApplyHooks.ts 越し)\n if (componentApplyHooks !== null && propSegments.length === 2 && typeof subObject === 'object' && subObject !== null\n && getCustomElement(element) !== null) {\n if (!(lastSegment in subObject)) {\n componentApplyHooks.recordInjectedKey(element, firstSegment, lastSegment);\n } else {\n // 既存キーの上書き: 作者の値を控える(v2 の厳格 R1 が snapshot 前に復元する)。\n // 完了後の (element, stateProp) への適用はここへルーティングされない\n //(applyChangeToWebComponent の no-op へ行く — apply/applyChange.ts)ので、\n // ここに来る上書きは常に完了前=控えの対象で良い\n componentApplyHooks.rememberOverwrittenValue(element, firstSegment, lastSegment, subObject[lastSegment]);\n }\n }\n try {\n subObject[lastSegment] = newValue;\n } catch (error) {\n if (config.debug) {\n console.warn(`Failed to set property on sub-object.`, {\n element,\n propSegments,\n oldValue,\n newValue,\n error\n });\n }\n }\n }\n // サブオブジェクトプロパティ (e.g. style.xxx) は属性に反映済みなのでストア不要\n}\n","import { getCustomElement } from \"../getCustomElement\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry\";\nimport { readBindableDeclaration } from \"../protocol/wcBindableReader\";\n\n/**\n * 要素 `element` の `propName` プロパティ書き込みに対して、\n * wc-bindable inputs の `attribute` ミラー先属性名を返す。\n *\n * - wc-bindable でないネイティブ要素や、inputs 未宣言、attribute フィールド無しは null\n * - inputs に同名宣言があっても `attribute` を持たないものはミラー対象外\n *\n * 戻り値の string がそのまま `setAttribute(name, value)` の name となる。\n */\nexport function getInputAttributeMirror(element: Element, propName: string): string | null {\n const customTagName = getCustomElement(element);\n if (customTagName === null) {\n return null;\n }\n const customClass = getCustomElementRegistry(element)?.get(customTagName);\n if (typeof customClass === \"undefined\") {\n return null;\n }\n const input = readBindableDeclaration(element)?.declaredInputs.get(propName);\n if (typeof input?.attribute === \"string\" && input.attribute.length > 0) {\n return input.attribute;\n }\n return null;\n}\n\n/**\n * mirror 属性値の表現を決める。\n * - null / undefined → 属性削除\n * - object / array → JSON.stringify (失敗時は String(value))\n * - その他 (string / number / boolean / bigint) → String(value)\n */\nexport function applyMirrorAttribute(element: Element, attributeName: string, value: unknown): void {\n if (value === null || typeof value === \"undefined\") {\n element.removeAttribute(attributeName);\n return;\n }\n let formatted: string;\n if (typeof value === \"object\") {\n try {\n formatted = JSON.stringify(value);\n } catch {\n formatted = String(value);\n }\n } else {\n formatted = String(value);\n }\n element.setAttribute(attributeName, formatted);\n}\n","import { inSsr } from \"../config\";\nimport { IBindingInfo } from \"../binding/types\";\nimport { IApplyContext } from \"./types\";\n\nconst ssrWrappedNodes: WeakSet<Node> = new WeakSet();\n\nexport function applyChangeToText(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n // nodeValue は nullable DOMString(実ブラウザでは null / undefined とも空文字に\n // 正規化される)ため、比較前に同じ規則で文字列化する。生値のまま比較すると\n // 数値など非文字列値は常に不一致になり、同値でも毎回 DOM 書き込みが走る。\n // 注: happy-dom は undefined を \"undefined\" にする非準拠実装なので String() に\n // 頼らず明示的に \"\" へ正規化する。\n const text = newValue === null || newValue === undefined ? \"\" : String(newValue);\n if (binding.replaceNode.nodeValue !== text) {\n binding.replaceNode.nodeValue = text;\n }\n // SSR モード時: テキストノードの前後にコメントを挿入して境界を明示\n if (inSsr() && !ssrWrappedNodes.has(binding.replaceNode)) {\n ssrWrappedNodes.add(binding.replaceNode);\n const parentNode = binding.replaceNode.parentNode;\n if (parentNode) {\n const path = binding.statePathName;\n const startComment = document.createComment(`@@wcs-text-start:${path}`);\n const endComment = document.createComment(`@@wcs-text-end:${path}`);\n parentNode.insertBefore(startComment, binding.replaceNode);\n parentNode.insertBefore(endComment, binding.replaceNode.nextSibling);\n }\n }\n}\n","import { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\n/**\n * カスタム要素の state プロパティバインディング(`state[.sub]: path`)に対する\n * 適用のルート先(apply/applyChange.ts の resolveCustomElementApply)。\n *\n * v2 では state プロパティのバインディングは全てマウント(webComponent/mountScope.ts)で、\n * 配送は「翻訳されたバインディング+単一台帳+静的依存」が担う — 親→子の再読込\n * 通知チャネル(v1 の innerState への $postUpdate)はこの経路では何も運ぶものが無い。\n * 完了済みの (element, stateProp) への適用は意図的な no-op。\n *\n * 未完了(宣言前)の適用はここへ来ない(applyChangeToProperty の積み、または\n * skipPendingMountWrite — apply/applyChange.ts)。\n */\nexport function applyChangeToWebComponent(_binding: IBindingInfo, _context: IApplyContext, _newValue: unknown): void {\n // no-op(上記)\n return;\n}\n","import { getStateAddressByBindingInfo } from \"../binding/getStateAddressByBindingInfo\";\nimport { IBindingInfo } from \"../binding/types\";\nimport { INDEX_BY_INDEX_NAME } from \"../define\";\nimport { getIndexValueByLoopContext } from \"../list/getIndexValueByLoopContext\";\nimport { getLoopContextByNode } from \"../list/loopContextByNode\";\nimport { getByAddressSymbol } from \"../proxy/symbols\";\nimport { IStateProxy } from \"../proxy/types\";\nimport { raiseError } from \"../raiseError\";\n\nexport function getValue(state: IStateProxy, binding: IBindingInfo): any {\n const stateAddress = getStateAddressByBindingInfo(binding);\n if (stateAddress.pathInfo.path in INDEX_BY_INDEX_NAME) {\n const loopContext = getLoopContextByNode(binding.node);\n if (loopContext === null) {\n raiseError(`ListIndex not found for binding: ${binding.statePathName}`);\n }\n return getIndexValueByLoopContext(loopContext, stateAddress.pathInfo.path);\n } else {\n return state[getByAddressSymbol](stateAddress);\n }\n}\n","import { INDEX_BY_INDEX_NAME } from \"../define\";\nimport { wildcardScopeMessage } from \"../pathDiagnostics\";\nimport { raiseError } from \"../raiseError\";\nimport { ILoopContext } from \"./types\";\nimport { listIndexAtWildcard } from \"./wildcardLevel\";\n\n// indexName ... $1, $2, ...\nexport function getIndexValueByLoopContext(loopContext: ILoopContext, indexName: string): number | null {\n if (loopContext.listIndex === null) {\n raiseError(`ListIndex not found for loopContext:`);\n }\n const indexPos = INDEX_BY_INDEX_NAME[indexName];\n if (typeof indexPos === \"undefined\") {\n raiseError(`Invalid index name: ${indexName}`);\n }\n const listIndex = listIndexAtWildcard(loopContext.listIndex, indexPos, loopContext.pathInfo.wildcardCount);\n if (listIndex === null) {\n // 位置が範囲外 = `$2` を 1 段のループの中で読んだ、という取り違え。\n // 元の文面(`Index not found at position 1 for loopContext:`)は内部の言葉で、\n // 何段必要で何段あるのかが書かれていなかった。\n raiseError(wildcardScopeMessage(`\"${indexName}\"`, indexPos + 1, loopContext.pathInfo.wildcardCount));\n }\n return listIndex.index;\n}","import { getBindingSession } from \"../bindings/BindingSession.js\";\nimport { getDefinitionCoordinator } from \"../bindings/DefinitionCoordinator.js\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry.js\";\nimport { IBindingInfo } from \"../types.js\";\nimport { applyChangeFromBindings } from \"./applyChangeFromBindings.js\";\n\nconst scheduledBindings = new WeakSet<IBindingInfo>();\n\nfunction reportFailure(tagName: string, error: unknown): void {\n console.error(`[@wcstack/state] deferred apply failed for <${tagName}>.`, error);\n}\n\nexport function scheduleDeferredApply(binding: IBindingInfo, tagName: string): void {\n if (scheduledBindings.has(binding)) return;\n scheduledBindings.add(binding);\n\n const applyLatest = (): void => {\n scheduledBindings.delete(binding);\n const currentSession = getBindingSession(binding);\n if (currentSession !== null && !currentSession.shouldApplyState(binding)) {\n return;\n }\n applyChangeFromBindings([binding]);\n };\n const reject = (error: unknown): void => {\n scheduledBindings.delete(binding);\n reportFailure(tagName, error);\n };\n\n const session = getBindingSession(binding);\n if (session !== null) {\n const cancel = session.deferUntilDefined(binding.replaceNode, tagName, applyLatest, reject);\n if (!session.addTeardown(binding, () => {\n scheduledBindings.delete(binding);\n cancel();\n })) {\n scheduledBindings.delete(binding);\n cancel();\n }\n return;\n }\n\n // Compatibility fallback for direct applyChange() callers outside a session.\n const registry = getCustomElementRegistry(binding.replaceNode);\n if (registry === null) {\n scheduledBindings.delete(binding);\n reportFailure(tagName, new Error(\"CustomElementRegistry is unavailable.\"));\n return;\n }\n getDefinitionCoordinator(registry).wait(tagName, () => {\n if (!binding.replaceNode.isConnected) {\n scheduledBindings.delete(binding);\n return;\n }\n applyLatest();\n }, reject);\n}\n","import { getAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding.js\";\nimport { ATTR_NAMESPACE, CLASS_NAMESPACE, COMMAND_NAMESPACE, STYLE_NAMESPACE } from \"../define.js\";\nimport { getBindingSession, isWaitingDefinition } from \"../bindings/BindingSession.js\";\nimport { getCustomElement } from \"../getCustomElement.js\";\nimport { getCustomElementRegistry } from \"../platform/customElementRegistry.js\";\nimport { raiseError } from \"../raiseError.js\";\nimport { getStateElement } from \"../stateElementByName.js\";\nimport { IBindingInfo } from \"../types.js\";\nimport { componentApplyHooks } from \"../core/componentApplyHooks.js\";\nimport { applyChangeToAttribute } from \"./applyChangeToAttribute.js\";\nimport { applyChangeToCheckbox } from \"./applyChangeToCheckbox.js\";\nimport { applyChangeToClass } from \"./applyChangeToClass.js\";\nimport { applyChangeToCommand } from \"./applyChangeToCommand.js\";\nimport { applyChangeToFor } from \"./applyChangeToFor.js\";\nimport { applyChangeToIf } from \"./applyChangeToIf.js\";\nimport { applyChangeToProperty } from \"./applyChangeToProperty.js\";\nimport { applyChangeToRadio } from \"./applyChangeToRadio.js\";\nimport { applyChangeToStyle } from \"./applyChangeToStyle.js\";\nimport { applyChangeToText } from \"./applyChangeToText.js\";\nimport { applyChangeToWebComponent } from \"./applyChangeToWebComponent.js\";\nimport { getFilteredValue } from \"./getFilteredValue.js\";\nimport { getValue } from \"./getValue.js\";\nimport { getRootNodeByFragment } from \"./rootNodeByFragment.js\";\nimport { scheduleDeferredApply } from \"./scheduleDeferredApply.js\";\nimport { ApplyChangeFn, IApplyContext } from \"./types.js\";\n\n// キーは define.ts の namespace 語彙定数(manifest.syntax.bindingTypes.propNamespaces と\n// 同一の正本)。集合の一致は __tests__/manifest.test.ts の drift テストが強制するため\n// export する(manifest エントリは DOM 非依存でこのファイルを import できない)。\nexport const applyChangeByFirstSegment: { readonly [key: string]: ApplyChangeFn } = Object.freeze({\n [CLASS_NAMESPACE]: applyChangeToClass,\n [ATTR_NAMESPACE]: applyChangeToAttribute,\n [STYLE_NAMESPACE]: applyChangeToStyle,\n [COMMAND_NAMESPACE]: applyChangeToCommand,\n});\n\nconst applyChangeByBindingType: { [key: string]: ApplyChangeFn } = {\n \"text\": applyChangeToText,\n \"for\": applyChangeToFor,\n \"if\": applyChangeToIf,\n \"else\": applyChangeToIf,\n \"elseif\": applyChangeToIf,\n \"radio\": applyChangeToRadio,\n \"checkbox\": applyChangeToCheckbox,\n};\n\nconst fnByBinding: WeakMap<IBindingInfo, ApplyChangeFn> = new WeakMap();\nconst deferredSelectBindingByBinding: WeakMap<IBindingInfo, boolean> = new WeakMap();\n\n// 未 define カスタム要素チェックの確定メモ。customTag が無い、または define 済みを\n// 一度確認したら以後は不変(define は不可逆)なので apply 毎の getCustomElement /\n// registry 照会を省略できる。scoped registry を導入する場合はこの不可逆前提を再検討。\nconst definedApplyVerifiedByBinding: WeakMap<IBindingInfo, boolean> = new WeakMap();\n\n/**\n * 宣言済みマウントの完了前の初期適用は書かない。子が完了すればマウント経由で\n * ライブに読むので、ここで親の値を書く意味は無い(書くと害がある —\n * webComponent/completeWebComponent.ts の宣言台帳を参照 — core/componentApplyHooks.ts 越しに引く)。v2 では部分規則\n *(`state.name: user.name`)にも同じ原則を適用する: 積みの上書きが作者の既定値を\n * 汚すと、厳格 R1(作者の own data key は私有・D19)の privateSnapshot が親の値で\n * 汚染される。積みが要るのは**未宣言**(`<wcs-state bind-component>` がまだ来ていない\n * 非同期定義や、そもそも bind-component の無い素のプロパティパス配線)だけ。\n */\nfunction skipPendingMountWrite(): void {}\n\n/**\n * カスタム要素へのプロパティバインディングの適用関数を決める。\n *\n * - 完了済み(bindWebComponent が公開プロパティを差し替え終えた)→ 値を運ばない\n * 再読込通知(applyChangeToWebComponent)。1 セグメント(`state: user`)も含む —\n * 残余が空なら「子の登録済みパス全部を読み直せ」の意味(ルート規則。\n * docs/state-mount-design.md §3-2 / impl-plan P1-2)\n * - 未完了だが `<wcs-state bind-component>` が宣言済み → 今回は\n * 書かない(skipPendingMountWrite — 部分規則も含む、上記)\n * - それ以外(未宣言)→ 素のプロパティ書き込み(積み)\n *\n * 以前は 1 セグメントを通知チャネルから除いていた(残余が空だと applyChangeToWebComponent\n * が raiseError し、updater の drain が捕まえないので同じバッチの無関係な更新まで\n * 巻き添えにした)。残余空がルート規則の意味を持った今、その除外は要らない。\n */\nfunction resolveCustomElementApply(binding: IBindingInfo): ApplyChangeFn {\n // 完了・宣言の台帳は bind-component の機能が受け口に置く。置かれていなければ素の書き込み\n const hooks = componentApplyHooks;\n if (hooks !== null) {\n const element = binding.replaceNode as Element;\n const stateProp = binding.propSegments[0];\n if (hooks.isComplete(element, stateProp)) {\n return applyChangeToWebComponent;\n }\n if (hooks.isDeclared(element, stateProp)) {\n return skipPendingMountWrite;\n }\n }\n return applyChangeToProperty;\n}\n\nfunction _applyChange(binding: IBindingInfo, context: IApplyContext): void {\n applyValueToBinding(binding, context, getValue(context.state, binding));\n}\n\n/**\n * 値が既に手元にあるときの `_applyChange` の後半(フィルタ適用 → DOM 書き込み)。\n * プラン初期描画(structural/activateContent.ts、設計 R2)が、行オブジェクトから直に\n * 読んだ素の値を渡すために使う。値の出どころ以外は通常の適用と同じ経路。\n */\nexport function applyValueToBinding(binding: IBindingInfo, context: IApplyContext, value: unknown): void {\n const filteredValue = getFilteredValue(value, binding.outFilters);\n\n if (deferredSelectBindingByBinding.get(binding) === true) {\n context.deferredSelectBindings.push({ binding, value: filteredValue, stateElement: context.stateElement });\n return;\n }\n let fn = fnByBinding.get(binding);\n if (typeof fn !== 'undefined') {\n fn(binding, context, filteredValue);\n return;\n }\n if (fnByBinding.has(binding)) {\n fn = resolveCustomElementApply(binding);\n if (fn === applyChangeToWebComponent) {\n fnByBinding.set(binding, fn); // 確定したのでキャッシュ\n }\n fn(binding, context, filteredValue);\n return;\n }\n\n fn = applyChangeByBindingType[binding.bindingType];\n if (typeof fn === 'undefined') {\n const firstSegment = binding.propSegments[0];\n fn = applyChangeByFirstSegment[firstSegment];\n fnByBinding.set(binding, fn);\n if (typeof fn === 'undefined') {\n const customTag = getCustomElement(binding.replaceNode);\n if (customTag) {\n fn = resolveCustomElementApply(binding);\n if (fn === applyChangeToWebComponent) {\n fnByBinding.set(binding, fn); // 確定したのでキャッシュ\n }\n } else {\n fn = applyChangeToProperty;\n fnByBinding.set(binding, fn);\n }\n }\n }\n if (fn === applyChangeToProperty) {\n const element = binding.node as Element;\n if (element.tagName === 'SELECT') {\n const propName = binding.propSegments[0];\n if (propName === 'value' || propName === 'selectedIndex') {\n context.deferredSelectBindings.push({ binding, value: filteredValue, stateElement: context.stateElement });\n deferredSelectBindingByBinding.set(binding, true);\n return;\n }\n }\n }\n fn(binding, context, filteredValue);\n}\n\nexport function applyChange(binding: IBindingInfo, context: IApplyContext): void {\n if (context.appliedBindingSet.has(binding)) {\n return;\n }\n context.appliedBindingSet.add(binding);\n // $updatedCallback が定義されていない state では、更新アドレスの集計自体が\n // 不要(drain 終端の呼び出しごと省略される)。大量バインディング適用時の\n // Set 蓄積を避ける。undefined(テスト用モック等)は従来通り集計する。\n if (context.stateElement.hasUpdatedCallback !== false) {\n const absAddress = getAbsoluteStateAddressByBinding(binding);\n if (context.updatedAbsAddressSetByStateElement.has(context.stateElement)) {\n const addressSet = context.updatedAbsAddressSetByStateElement.get(context.stateElement)!;\n addressSet.add(absAddress);\n } else {\n context.updatedAbsAddressSetByStateElement.set(context.stateElement, new Set([\n absAddress\n ]));\n }\n }\n const bindingSession = getBindingSession(binding);\n if (bindingSession !== null && !bindingSession.shouldApplyState(binding)) {\n return;\n }\n if (binding.bindingType === \"event\") {\n return;\n }\n if (definedApplyVerifiedByBinding.get(binding) !== true) {\n const customTag = getCustomElement(binding.replaceNode);\n if (customTag) {\n // 定義済みに見えても、束縛がまだ定義を待っている(two-way・イベントも初期同期もまだ)なら同じく待つ —\n // 行の中身は fragment の中で「未定義」と判断して待ちを並べ、スコープ付き registry の木へ差し込んだ\n // 時点で upgrade される。ここで書くと初期同期より先に state の値が要素へ入る(#357)\n if (getCustomElementRegistry(binding.replaceNode)?.get(customTag) === undefined || isWaitingDefinition(binding)) {\n // 未 define のカスタム要素へは今は適用できない(accessor 未確立の要素に\n // 素の own property を書くと upgrade 後に class accessor を隠してしまう)。\n // whenDefined 後に最新 state 値で再適用する(two-way attach / deferred\n // spread と対称。docs/state-binding-init-races.md §2)。\n scheduleDeferredApply(binding, customTag);\n return;\n }\n }\n // customTag 無し or define 済み確定 → 以後この検査を省略(不可逆)\n definedApplyVerifiedByBinding.set(binding, true);\n }\n // applyChangeFromBindings のグループ化ループが解決済みルートの一致を検証済みの\n // 場合、getRootNode の再解決(native 呼び出し)を省略できる。activateContent 経由\n // (フラグメント内の新規 content)も、フラグメントは setRootNodeByFragment で\n // context.rootNode に解決されるため同じ不変条件が成り立つ。\n if (context.sameRootVerified === true) {\n _applyChange(binding, context);\n return;\n }\n let rootNode: Node | null = binding.replaceNode.getRootNode() as Node;\n if (rootNode instanceof DocumentFragment && !(rootNode instanceof ShadowRoot)) {\n rootNode = getRootNodeByFragment(rootNode);\n if (rootNode === null) {\n raiseError(`Root node for fragment not found for binding.`);\n }\n }\n if (rootNode !== context.rootNode) {\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n stateElement.createState(\"readonly\", (targetState) => {\n const newContext = {\n rootNode: rootNode,\n stateElement: stateElement,\n state: targetState,\n appliedBindingSet: context.appliedBindingSet,\n newListValueByAbsAddress: context.newListValueByAbsAddress,\n updatedAbsAddressSetByStateElement: context.updatedAbsAddressSetByStateElement,\n deferredSelectBindings: context.deferredSelectBindings,\n }\n _applyChange(binding, newContext);\n });\n } else {\n _applyChange(binding, context);\n }\n}\n","import { raiseError } from \"../raiseError\";\nimport { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\nexport function applyChangeToClass(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const element = binding.node as Element;\n const className = binding.propSegments[1];\n // 「値が無い」(undefined / null)はクラスを外す — 要件 B8 の `attr.` と同じ語彙。\n // throw にしていると、使い回した行に値の無い行オブジェクトが来たときに**行ごと**描かれなかった\n // (`attr.title:` は属性が消えるだけで済んでいた)\n if (newValue === undefined || newValue === null) {\n element.classList.toggle(className, false);\n return;\n }\n // truthy な非 boolean(`class.on: label` に文字列が来る等)は今も throw する。クラスの束縛は\n // 真偽の切り替えなので、truthy な文字列は意図より書き間違いである方がずっと多い。ただし\n // **行の中で throw すると行ごと描かれない**という失敗モードは残るので、この取り違えは\n // 静的検出(`@wcstack/lint` / VS Code 拡張のパス型推論)で前に倒す方針。\n // 作者が truthy 扱いを意図しているなら `class.on: flag|truthy` と書く(README の B8 節)。\n if (typeof newValue !== 'boolean') {\n raiseError(`Invalid value for class application: expected boolean, got ${typeof newValue}. Write \"|truthy\" if you mean to coerce.`);\n }\n element.classList.toggle(className, newValue as boolean);\n}","import { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\nexport function applyChangeToAttribute(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const element = binding.node as Element;\n const attrName = binding.propSegments[1];\n // 値が無い(undefined / null)属性は削除する(要件 B8)。以前は文字列 \"undefined\" / \"null\" を書いていた\n if (newValue === undefined || newValue === null) {\n if (element.hasAttribute(attrName)) {\n element.removeAttribute(attrName);\n }\n return;\n }\n // 属性の値は常に文字列なので、比較の前に同じ規則で文字列化する(`applyChangeToText` と同じ)。\n // 生値のまま比べると数値・真偽値を束ねた属性は同値でも毎回 setAttribute が走っていた\n const text = String(newValue);\n if (element.getAttribute(attrName) !== text) {\n element.setAttribute(attrName, text);\n }\n}\n","import { IBindingInfo } from \"../types\";\nimport { IApplyContext } from \"./types\";\n\nexport function applyChangeToStyle(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const styleName = binding.propSegments[1];\n const style = (binding.node as HTMLElement).style;\n // 値が無い(undefined / null)スタイルは消す(要件 B8)\n if (newValue === undefined || newValue === null) {\n newValue = \"\";\n }\n const currentValue = (style as any)[styleName];\n if (currentValue !== newValue) {\n (style as any)[styleName] = newValue;\n }\n}\n","import { IBindingInfo } from \"../types\";\nimport { getFilteredValue } from \"./getFilteredValue\";\nimport { IApplyContext } from \"./types\";\n\nexport function applyChangeToRadio(binding: IBindingInfo, _context: IApplyContext, newValue: unknown): void {\n const element = binding.node as HTMLInputElement;\n const elementValue = element.value;\n const elementFilteredValue = getFilteredValue(elementValue, binding.inFilters);\n element.checked = newValue === elementFilteredValue;\n}\n","import { IAbsoluteStateAddress } from \"../address/types\";\nimport { IStateElement } from \"../components/types\";\nimport { config } from \"../config\";\nimport { devtoolsSink } from \"../platform/devtoolsSink\";\nimport { setLastListValueByAbsoluteStateAddress } from \"../list/lastListValueByAbsoluteStateAddress\";\nimport { setStateListBaseline } from \"../list/stateListBaseline\";\nimport { errorCallbackSymbol, updatedCallbackSymbol } from \"../proxy/symbols\";\nimport { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IPropagationContext } from \"../propagation/types\";\nimport { IBindingErrorInfo, IBindingInfo } from \"../types\";\nimport { applyChange } from \"./applyChange\";\nimport { applyChangeToProperty } from \"./applyChangeToProperty\";\nimport { getRootNodeByFragment } from \"./rootNodeByFragment\";\nimport { IApplyContext, IDeferredSelectBinding } from \"./types\";\n\n/** $errorCallback へ配送する失敗 1 件(drain 末尾でまとめて配送する) */\ninterface IBindingFailure {\n readonly error: unknown;\n readonly info: IBindingErrorInfo;\n}\n\n/**\n * バインディング 1 本の適用失敗を報告する(握り潰しではない)。\n *\n * `console.error` だけだと devtools からは「静かに握られた失敗」が見えないため、\n * 同じ地点から sink にも流す(`state:watch-error` と同じ位置づけ)。\n * 値と DOM は巻き戻さない — 伝播 hop 上限超過・watch 連鎖打ち切りと同じ姿勢。\n *\n * state が `$errorCallback` を宣言していれば、console.error の代わりにそこへ配送する\n * (作者が報告を引き取った。ページ内で受けるための口)。配送は batch の末尾 —\n * $updatedCallback と同じ位置 — にまとめる。devtools sink へは宣言の有無に関わらず流す。\n */\nfunction reportBindingApplyError(\n binding: IBindingInfo,\n error: unknown,\n stateElement: IStateElement | null,\n failuresByStateElement: Map<IStateElement, IBindingFailure[]>,\n): void {\n const handled = stateElement !== null && stateElement.hasErrorCallback === true;\n if (handled) {\n const info: IBindingErrorInfo = {\n path: binding.statePathName,\n bindingType: binding.bindingType,\n node: binding.node,\n };\n const failures = failuresByStateElement.get(stateElement);\n if (failures === undefined) {\n failuresByStateElement.set(stateElement, [{ error, info }]);\n } else {\n failures.push({ error, info });\n }\n } else {\n console.error(\n `[@wcstack/state] binding \"${binding.bindingType}: ${binding.statePathName}\" failed to apply; ` +\n `the rest of this batch continues.`,\n { node: binding.node, error },\n );\n }\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"state:binding-apply-error\",\n path: binding.statePathName,\n bindingType: binding.bindingType,\n error,\n });\n }\n}\n\n/**\n * バインディング情報の配列を処理し、各バインディングに対して状態の変更を適用する。\n *\n * 2フェーズで処理:\n * Phase 1: 構造的更新(for/if) + 値更新(select以外) — select.value/selectedIndex は遅延収集\n * Phase 2: 遅延されたselect.value/selectedIndex を適用(option要素の生成後)\n *\n * 最適化のため、以下のグループ化を行う:\n * 同じ rootNode を持つバインディングをグループ化 → createState の呼び出しを削減\n *\n * `options.updatedCallback === false` は `$updatedCallback` を呼ばない。唯一の呼び手は再セットの\n * 再適用(apply/reapplyStateBindings.ts)で、再セットは書き込みではないため。`$errorCallback` は\n * 適用の失敗の報告なので、どの経路でも配送する。\n */\nexport function applyChangeFromBindings(\n bindings: IBindingInfo[],\n propagationContextByBinding?: ReadonlyMap<IBindingInfo, IPropagationContext | null>,\n options?: { readonly updatedCallback?: boolean },\n): void {\n let bindingIndex = 0;\n const appliedBindingSet: Set<IBindingInfo> = new Set();\n const newListValueByAbsAddress: Map<IAbsoluteStateAddress, readonly unknown[]> = new Map();\n const updatedAbsAddressSetByStateElement: Map<IStateElement, Set<IAbsoluteStateAddress>> = new Map();\n const deferredSelectBindings: IDeferredSelectBinding[] = [];\n const failuresByStateElement: Map<IStateElement, IBindingFailure[]> = new Map();\n\n // Phase 1: 構造的更新 + 値更新(select.value/selectedIndex は遅延)\n while(bindingIndex < bindings.length) {\n let binding = bindings[bindingIndex];\n if (binding.replaceNode.isConnected === false) {\n // 切断されているバインディングは無視、本来は事前に除去されているはず\n if (config.debug) {\n console.log(`applyChangeFromBindings: skip disconnected binding: ${binding.bindingType} ${binding.statePathName} on ${binding.node.nodeName}`, binding);\n }\n bindingIndex++;\n continue;\n }\n let rootNode: Node | null = binding.replaceNode.getRootNode() as Node;\n if (rootNode instanceof DocumentFragment && !(rootNode instanceof ShadowRoot)) {\n rootNode = getRootNodeByFragment(rootNode);\n if (rootNode === null) {\n raiseError(`Root node for fragment not found for binding.`);\n }\n }\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for binding.`);\n }\n\n stateElement.createState(\"readonly\", (state) => {\n const context: IApplyContext = {\n rootNode: rootNode,\n stateElement: stateElement,\n state: state,\n appliedBindingSet: appliedBindingSet,\n newListValueByAbsAddress: newListValueByAbsAddress,\n updatedAbsAddressSetByStateElement: updatedAbsAddressSetByStateElement,\n deferredSelectBindings: deferredSelectBindings,\n // グループ内の binding は下の do/while が「解決済みルート === rootNode」を\n // 検証してから applyChange に渡す(applyChange 側の getRootNode 省略の根拠)\n sameRootVerified: true,\n propagationContextByBinding: propagationContextByBinding,\n };\n\n do {\n // 1 本の失敗を 1 本に閉じ込める(§ エラー隔離)。隔離しないと、stale な\n // アドレスを読んだ 1 本の throw がバッチの残り・$updatedCallback・drain\n // リスナー($watch / $streams restart)まで道連れにし、「値は新しいのに\n // DOM は途中まで」という再現困難な半端状態を作る。\n try {\n applyChange(binding, context);\n } catch (error) {\n reportBindingApplyError(binding, error, stateElement, failuresByStateElement);\n }\n bindingIndex++;\n\n const nextBindingInfo: IBindingInfo | undefined = bindings[bindingIndex];\n if (!nextBindingInfo) break; // 終端に到達\n const nextRootNode = nextBindingInfo.replaceNode.getRootNode() as Node;\n if (nextRootNode !== context.rootNode) break; // ルートが変わった\n binding = nextBindingInfo;\n } while(true); // eslint-disable-line no-constant-condition\n });\n }\n // Phase 2: 遅延されたselect.value/selectedIndex を適用\n // applyChangeToProperty は propagationContextByBinding 以外の context を\n // 参照しないため、遅延分は最小 context を渡す\n for (const { binding, value, stateElement } of deferredSelectBindings) {\n try {\n applyChangeToProperty(binding, { propagationContextByBinding } as unknown as IApplyContext, value);\n } catch (error) {\n reportBindingApplyError(binding, error, stateElement ?? null, failuresByStateElement);\n }\n }\n\n for(const [ absAddress, newListValue ] of newListValueByAbsAddress.entries()) {\n setLastListValueByAbsoluteStateAddress(absAddress, newListValue);\n // 描画の基準とは別に、state 側の基準(読み・依存ウォークの共有正本)も進める。\n // 初回描画はどの書き込みも経ていないので、ここで観測しておかないと最初の構造\n // 書き込みで基準が空のまま ListIndex を鋳造してしまう(E1)。\n setStateListBaseline(absAddress, newListValue);\n }\n if (options?.updatedCallback !== false) {\n for(const [ stateElement, absAddressSet ] of updatedAbsAddressSetByStateElement.entries()) {\n stateElement.createState(\"writable\", (state) => {\n state[updatedCallbackSymbol](Array.from(absAddressSet));\n });\n }\n }\n // $errorCallback の配送。$updatedCallback の後・失敗した本数ぶん・this は writable proxy。\n // callback 自身の throw は隔離する — 1 件の報告失敗が残りの報告と drain を道連れにしない\n for (const [ stateElement, failures ] of failuresByStateElement.entries()) {\n stateElement.createState(\"writable\", (state) => {\n for (const { error, info } of failures) {\n try {\n state[errorCallbackSymbol](error, info);\n } catch (callbackError) {\n console.error(\n `[@wcstack/state] $errorCallback threw while handling the failure of binding \"${info.bindingType}: ${info.path}\".`,\n { error: callbackError, original: error, node: info.node },\n );\n }\n }\n });\n }\n}\n","import { isLightDomMappedStateElement } from \"./bindings/lightDomComponentScope\";\nimport { State } from \"./components/State\";\nimport { IStateElement } from \"./components/types\";\nimport { config } from \"./config\";\nimport { getCustomElementRegistry } from \"./platform/customElementRegistry\";\nimport { raiseError } from \"./raiseError\";\n\nexport async function waitForStateInitialize(root: Document | Element | DocumentFragment): Promise<void> {\n const elements = root.querySelectorAll(config.tagNames.state);\n const promises: Promise<void>[] = [];\n const registry = getCustomElementRegistry(root);\n if (registry === null) {\n // null レジストリのサブツリーでは <wcs-state> が upgrade されないので\n // initializePromise が生えず、待っても永久に初期化されない。\n raiseError(`CustomElementRegistry is unavailable for <${config.tagNames.state}>.`);\n }\n await registry.whenDefined(config.tagNames.state);\n for(const element of elements) {\n // Light DOM の mapped コンポーネントの state は待たない。それはこの root の\n // バインディングが張られてからでないと初期化できず(自分を束ねるホスト binding を\n // 待つ)、ここで待つと循環する(§1.13)。Shadow DOM 形では別 rootNode にいるので\n // そもそもこの集合に現れず、plain 形は循環しないので従来どおり待つ。\n if (isLightDomMappedStateElement(element)) {\n continue;\n }\n const stateElement = element as State as IStateElement;\n promises.push(stateElement.initializePromise);\n }\n await Promise.all(promises);\n}\n","import { waitInitializeBinding } from \"./bindings/initializeBindingPromiseByNode\";\nimport { initializeBindings } from \"./bindings/initializeBindings\";\nimport { config } from \"./config\";\nimport { convertMustacheToComments } from \"./mustache/convertMustacheToComments\";\nimport { collectStructuralFragments } from \"./structural/collectStructuralFragments\";\nimport { waitForStateInitialize } from \"./waitForStateInitialize\";\n\nexport async function buildBindings(root: Document | ShadowRoot): Promise<void> {\n if (root === document) {\n // document配下のwcs-stateの初期化(connectedCallbackの完了)を待機する\n await waitForStateInitialize(document);\n // baindingを取得して、初期値をセットする\n convertMustacheToComments(document);\n collectStructuralFragments(document, document);\n initializeBindings(document.body, null);\n } else {\n const shadowRoot = root as ShadowRoot;\n if (shadowRoot.host.hasAttribute(config.bindAttributeName)) {\n // data-wcsを持つWebComponentは、WebComponentのbindingが完了するまで待機する。\n await waitInitializeBinding(shadowRoot.host);\n }\n // shadowRoot配下のwcs-stateの初期化(connectedCallbackの完了)を待機する\n await waitForStateInitialize(shadowRoot);\n // baindingを取得して、初期値をセットする\n convertMustacheToComments(shadowRoot);\n collectStructuralFragments(shadowRoot, shadowRoot);\n initializeBindings(shadowRoot, null);\n }\n}\n","/**\n * core/featureEntries.ts — 受け口の機能名 → 利用者が入れるエントリ(設計案 §3 H5・§4)。\n *\n * barrier に当たったページが要るのは「どの import を足すか」であって内部の機能名ではない。\n * 内部では別々の機能(watch / scan / stream)が 1 つのエントリ(temporal)に載るので、\n * 対応表は 1 箇所に置き、3 つの barrier(addressHooks・lifecycleHooks・ssrHooks)が共有する。\n */\n/**\n * 鍵は `registerFeatureHooks` / `registerDeclarationHooks` / `requireLifecycleFeature` が使う\n * **実際の機能名**でなければならない(`__tests__/core.featureEntries.test.ts` が固定する)。\n * かつて `stream` と書かれていたが登録名は `streams` で、`@wcstack/state/features/streams`\n * という存在しないエントリを案内していた。\n */\nconst ENTRY_BY_FEATURE: Record<string, string> = {\n watch: \"temporal\",\n scan: \"temporal\",\n streams: \"temporal\",\n scopes: \"scopes\",\n dcc: \"scopes\",\n recursion: \"recursion\",\n ssr: \"ssr\",\n devtools: \"devtools\",\n};\n\n/** 未 install の機能を宣言が要求したときの文言(readiness barrier、H5 / D13) */\nexport function featureNotInstalledMessage(feature: string, declaration: string): string {\n const entry = ENTRY_BY_FEATURE[feature] ?? feature;\n return `[wcs/feature-not-installed] ${declaration} needs the \"${feature}\" feature: ` +\n `install it with installFeatures([...]) from \"@wcstack/state/features/${entry}\" before the state is defined.`;\n}\n","/**\n * core/ssrHooks.ts — SSR(サーバー描画とハイドレーション)の受け口(設計案 H8、S5)。\n *\n * core が持つのは SSR **モード**(config の `inSsr()` と apply 側が書く `@@wcs-*` コメント)と\n * `enable-ssr` 属性の判定だけ。`<wcs-ssr>` の読み書きとハイドレーションの実装は ssr 機能\n * (src/ssr/)が install で置く。core から機能への辺はこの 1 本の受け口に畳まれている。\n *\n * 受け口(core 側の呼び出し点):\n * hydrate ルート登録(stateElementByName)で、`enable-ssr` のクライアント側\n * loadState `_initialize` の冒頭で、`<wcs-ssr>` に載った state データを読む\n * emitSnapshot サーバー側の `connectedCallback` の末尾で `<wcs-ssr>` を書き出す\n */\nimport { raiseError } from \"../raiseError\";\nimport { featureNotInstalledMessage } from \"./featureEntries\";\n\nexport interface ISsrHooks {\n /** クライアント: SSR 出力からバインディングを起こす。偽なら core が通常の構築へ倒す */\n hydrate(root: Document): Promise<boolean>;\n /** クライアント: この要素の前に置かれた `<wcs-ssr>` の state データ(無ければ null) */\n loadState(element: Element): Record<string, any> | null;\n /** サーバー: バインディング完了後に `<wcs-ssr>` を書き出す */\n emitSnapshot(element: Element): Promise<void>;\n}\n\n/** 置かれていなければ null。`enable-ssr` の無いページはここを一度も見ない */\nexport let ssrHooks: ISsrHooks | null = null;\n\n/** 機能の install が呼ぶ(冪等 — 置き換え) */\nexport function setSsrHooks(hooks: ISsrHooks | null): void {\n ssrHooks = hooks;\n}\n\n/**\n * `enable-ssr` が SSR 機能を要求した: 未 install なら名指しで throw する(readiness barrier、H5 / D13)。\n * full / auto は `bootstrapState()` が install するので起きない。\n */\nexport function requireSsrHooks(declaration: string): ISsrHooks {\n if (ssrHooks === null) {\n raiseError(featureNotInstalledMessage(\"ssr\", declaration));\n }\n return ssrHooks;\n}\n","import { buildBindings } from \"./buildBindings\";\nimport { requireSsrHooks } from \"./core/ssrHooks\";\nimport { IStateElement } from \"./components/types\";\nimport { config, inSsr } from \"./config\";\nimport { raiseError } from \"./raiseError\";\nimport { devtoolsSink } from \"./platform/devtoolsSink\";\nimport { drainPendingBinds } from \"./bindings/binder\";\n\n// v2: 1 rootNode 1 ツリー(P3-6)。名前次元は無い — 追加の state はマウント(mount= / bind-component)で載る。\nconst stateElementByNode: WeakMap<Node, IStateElement> = new WeakMap();\nconst bindingsReadyByNode: WeakMap<Node, Promise<void>> = new WeakMap();\n\n// devtools 用の列挙可能な登録簿(protocol §4.1 — 唯一の常時 ON 台帳)。\n// サイズは <wcs-state> 要素数に拘束され、unregister(disconnectedCallback)で\n// 必ず削除されるためリークしない。\nconst liveStateElements: Set<IStateElement> = new Set();\n\n// ルートの登録を待つ機能(先に接続されたボリュームの引き取り — webComponent/volume.ts)の受け口。\n// 登録は 1 ルートにつき 1 回なので大域の listener 列で足りる(hot path には載らない)\ntype StateElementRegisteredListener = (rootNode: Node, element: IStateElement) => void;\nconst registeredListeners: StateElementRegisteredListener[] = [];\n\nexport function onStateElementRegistered(listener: StateElementRegisteredListener): void {\n if (!registeredListeners.includes(listener)) {\n registeredListeners.push(listener);\n }\n}\n\nexport function getLiveStateElements(): ReadonlySet<IStateElement> {\n return liveStateElements;\n}\n\nexport function getStateElement(rootNode: Node): IStateElement | null {\n return stateElementByNode.get(rootNode) ?? null;\n}\n\n/**\n * 指定された rootNode のバインディング初期化が完了するまで待機する Promise を返す。\n */\nexport function getBindingsReady(rootNode: Node): Promise<void> {\n return bindingsReadyByNode.get(rootNode) ?? Promise.resolve();\n}\n\n/**\n * この rootNode ではバインド構築が起きない、と確定する(#257)。\n *\n * ルートの state 要素が初期化に失敗すると `setStateElement` に到達しないので、\n * 台帳はエントリが無いまま残る。上の既定(未登録 = 即時解決)は「まだ登録されて\n * いない」と「バインドを張り終えた」を区別しないため、@wcstack/server の\n * `waitForReady` は**バインディングが 1 本も無いページ**を ready と報告してしまう。\n * 失敗した rootNode には reject 済みの ready を置き、待ち手へ同じ診断を届ける。\n *\n * 呼び手は State の `_failInitializeLoudly` ただ 1 つで、そちらが「この rootNode に\n * 生きたルートが居ない」ことを確かめてから呼ぶ(2 本目の `<wcs-state>` が落ちても\n * 1 本目の ready は壊さない)。\n */\nexport function markBindingsUnavailable(rootNode: Node, error: unknown): void {\n const failed = Promise.reject(error);\n // reject と同じティックで handled を立てる(getBindingsReady を誰も呼ばない\n // ページで unhandled rejection にしないため)。await した側は従来どおり受け取る\n failed.catch(() => undefined);\n bindingsReadyByNode.set(rootNode, failed);\n}\n\nconst bindingsBuiltRoots: WeakSet<Node> = new WeakSet();\n\n/**\n * マウントされたスコープ(コンポーネントの ShadowRoot)に、**親の** state element を\n * 別名として載せる(Phase 2・impl-plan §3-0 の 2)。\n *\n * `getRootNode()` で state element を解決する全てのサイト\n * (getAbsoluteStateAddressByBinding / applyChange / applyChangeFromBindings /\n * fragmentInfoByUUID)が、この 1 エントリで無改造のまま親ツリーに到達する。\n * `setStateElement` と違い、初回登録の副作用(buildBindings の起動・\n * liveStateElements・devtools イベント)は持たない — マウントスコープの構築は\n * webComponent/mountScope.ts が自前で行う。\n */\nexport function setStateElementAlias(rootNode: Node, element: IStateElement): void {\n const existing = stateElementByNode.get(rootNode);\n if (typeof existing !== \"undefined\") {\n // 再初期化(connectedCallback で shadow を張り直すコンポーネントの再接続)は\n // 同じ親を指し直すだけなので冪等。別要素への付け替えは設定ミス\n if (existing === element) {\n return;\n }\n raiseError(`A state tree is already registered on this root.`);\n }\n stateElementByNode.set(rootNode, element);\n}\n\n/**\n * マウントされたスコープの ready を登録する(`getBindingsReady(childShadow)` の互換面)。\n * 完了で binder の `areBindingsBuilt` も真にする。\n */\nexport function setBindingsReadyForScope(rootNode: Node, ready: Promise<void>): void {\n bindingsReadyByNode.set(rootNode, ready);\n ready.then(() => markBindingsBuilt(rootNode), () => undefined);\n}\n\n/**\n * この rootNode の初期バインド構築が完了しているか。\n *\n * binder プロトコル(`bind()`)が使う。router の `<wcs-head>` はクローンを\n * `connectedCallback` の中で head へ入れるので、**state が最初の走査を終える前**に\n * bind を求めてくる。そこで同期に束ねても state 要素の初期化が済んでおらず、\n * 結果は空のままになる。完了までは binder 側で保留する。\n *\n * 「まだ登録も済んでいない」と「もう構築が終わった」を取り違えないよう、判定は\n * 完了の側で持つ。<wcs-state> の登録は connectedCallback の await より後に起きるので、\n * 「エントリの有無」で進行中かを測ると読み込み順によって逆の答えを返す。\n */\nexport function areBindingsBuilt(rootNode: Node): boolean {\n return bindingsBuiltRoots.has(rootNode);\n}\n\nfunction markBindingsBuilt(rootNode: Node): void {\n bindingsBuiltRoots.add(rootNode);\n}\n\nexport function setStateElement(rootNode: Node, element: IStateElement | null): void {\n\n const existing = stateElementByNode.get(rootNode);\n\n if (element === null) {\n // 削除の場合、登録が無ければ何もしない\n if (existing === undefined) {\n return;\n }\n stateElementByNode.delete(rootNode);\n liveStateElements.delete(existing);\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:element-unregistered\", rootNode, element: existing });\n }\n if (config.debug) {\n console.debug(`State element unregistered`);\n }\n } else {\n // 登録の場合\n if (existing === element) {\n // 同じ要素の再登録は冪等(setStateElementAlias と同じ規範)。ロード完了前の\n // remove → append(DOM の移動・行プールの張り直し・shadow の組み直し)は\n // `_initialize` を 2 本同時に走らせるので、後から登録に来たほうが**自分自身**を\n // 「2 本目の <wcs-state>」と誤診する。DOM の移動は正常な操作であり、拒否すると\n // 健全なページの connectedCallbackPromise が reject される(#257)。\n // 切断時に登録を解除する案では直らない — 実測で、切断の時点ではまだ何も\n // 登録されていない(登録は進行中の `_initialize` の続きで起きる)。\n return;\n }\n if (existing === undefined) {\n // 初めてルートノードに登録する場合\n // enable-ssr 属性があり、サーバーサイドでない場合はハイドレーション\n const enableSsr = !inSsr() && (element as unknown as Element).hasAttribute?.('enable-ssr');\n // instanceof ではなく constructor.name で判定するのは意図的。SSR では\n // @wcstack/server の installGlobals が happy-dom の一部だけを globalThis に載せるが、\n // そのリスト(GLOBALS_KEYS)に `Document` は入っていない。Node にも `Document` は\n // 無いので `rootNode instanceof Document` は ReferenceError になる。\n // `ShadowRoot` はリストに含まれるため他所では instanceof を使っている\n // (docs/architecture-hardening/15-state-component-mechanism-consistency.md §3.3)。\n // reject を配管しないと、バインディング初期化中の例外は unhandled rejection として\n // 漏れるだけで ready が永久に未解決のまま残り、await getBindingsReady() の先が\n // 無言でハングする(docs/state-bind-component-nested-for-design.md §8.2)。\n if (rootNode.constructor.name === 'HTMLDocument' || rootNode.constructor.name === 'Document') {\n const ready = new Promise<void>((resolve, reject) => {\n queueMicrotask(async () => {\n try {\n if (enableSsr) {\n // ハイドレーションは SSR 機能(ssr/hydrateBindings.ts)。未 install なら名指しで落とす(H5 / D13)\n const success = await requireSsrHooks(`the \"enable-ssr\" attribute`).hydrate(rootNode as Document);\n if (!success) {\n await buildBindings(rootNode as Document);\n }\n } else {\n await buildBindings(rootNode as Document);\n }\n markBindingsBuilt(rootNode);\n // binder が居ない時点で差し出されたサブツリーを引き取る。ここが\n // 「state が確実に居る」最初の瞬間で、router の auto バンドルが\n // state のそれより先に走る順序を吸収できる唯一の場所である。\n drainPendingBinds();\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n });\n bindingsReadyByNode.set(rootNode, ready);\n } else if (rootNode.constructor.name === 'ShadowRoot') {\n const ready = new Promise<void>((resolve, reject) => {\n queueMicrotask(async () => {\n try {\n await buildBindings(rootNode as ShadowRoot);\n markBindingsBuilt(rootNode);\n // binder が居ない時点で差し出されたサブツリーを引き取る。ここが\n // 「state が確実に居る」最初の瞬間で、router の auto バンドルが\n // state のそれより先に走る順序を吸収できる唯一の場所である。\n drainPendingBinds();\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n });\n bindingsReadyByNode.set(rootNode, ready);\n }\n }\n if (existing !== undefined) {\n // v2 は 1 rootNode 1 ツリー。2 つ目の <wcs-state> は設定エラー — 追加の状態は\n // マウント(mount= / ホスト配線の bind-component)でツリーに載せる\n // 文言は実測のゾンビの姿に合わせる(#257 第 3 ラウンド): 2 本目は state を\n // 組み上げたまま**登録されない**。データもトークンも $on の購読も生きているのに\n // 誰もバインドしておらず、_initialized が false なので切断時の後始末も走らない\n raiseError(\n `A state tree is already registered on this root — one <wcs-state> per root in v2. ` +\n `This second element stays unregistered: it keeps the state it loaded and its ` +\n `declarations stay live, but nothing binds to it and disconnecting it runs no ` +\n `cleanup — remove it. Mount additional states onto the tree instead: ` +\n `<wcs-state mount=\"...\">.`,\n );\n }\n stateElementByNode.set(rootNode, element);\n liveStateElements.add(element);\n // ルートの登録を待っていた機能へ(先に接続されて保留中のボリュームの引き取り — ロード順に依存しない、V5)\n for (let i = 0; i < registeredListeners.length; i++) {\n registeredListeners[i](rootNode, element);\n }\n if (devtoolsSink !== null) {\n devtoolsSink({ type: \"state:element-registered\", rootNode, element });\n }\n if (config.debug) {\n console.debug(`State element registered`, element);\n }\n }\n}\n","import { raiseError } from \"../raiseError\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { IFragmentInfo } from \"./types\";\n\nconst fragmentInfoByUUID = new Map<string, IFragmentInfo>();\n\nexport function setFragmentInfoByUUID(uuid: string, rootNode: Node, fragmentInfo: IFragmentInfo | null): void {\n if (fragmentInfo === null) {\n fragmentInfoByUUID.delete(uuid);\n } else {\n fragmentInfoByUUID.set(uuid, fragmentInfo);\n // v2: ルートに 1 ツリーなので参照は 1 回でよい(名前ごとの再解決は名前次元と一緒に消えた)\n const stateElement = getStateElement(rootNode);\n if (stateElement === null) {\n raiseError(`No state tree found on this root for fragment info.`);\n }\n const bindingPartial = fragmentInfo.parseBindTextResult;\n stateElement.setPathInfo(bindingPartial.statePathName, bindingPartial.bindingType);\n for(const nodeInfo of fragmentInfo.nodeInfos) {\n for(const nodeBindingPartial of nodeInfo.parseBindTextResults) {\n stateElement.setPathInfo(nodeBindingPartial.statePathName, nodeBindingPartial.bindingType);\n }\n }\n }\n}\n\nexport function getFragmentInfoByUUID(uuid: string): IFragmentInfo | null {\n return fragmentInfoByUUID.get(uuid) || null;\n}\n\nexport function getAllFragmentUUIDs(): string[] {\n return Array.from(fragmentInfoByUUID.keys());\n}\n\n/**\n * 台帳を空にする。**サーバーのレンダリング 1 回分の後始末専用**(`ssr/buildSsrDocument.ts` の\n * `resetSsrRenderState`)。\n *\n * この台帳はモジュール寿命で削除の口が無く、`renderToString` が同じプロセスで別のドキュメントを\n * 描いても前のドキュメントのテンプレートが残り続ける。出力への混入そのものは直列化側の\n * 到達可能性フィルタ(`Ssr.buildContent`)で閉じてあるので、ここは**メモリ**の口である。\n * ブラウザでは呼ばない — 台帳は生きているページの構造テンプレートの正本。\n */\nexport function clearFragmentInfos(): void {\n fragmentInfoByUUID.clear();\n}","import { config } from \"../config\";\nimport { VOLUME_INJECTION_PROP } from \"../define\";\nimport { raiseError } from \"../raiseError\";\nimport { parseBindTextsForElement } from \"../bindTextParser/parseBindTextsForElement\";\nimport { parseCommentNode } from \"./parseCommentNode\";\nimport { parseBindTextForEmbeddedNode } from \"../bindTextParser/parseBindTextForEmbeddedNode\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { getFragmentInfoByUUID } from \"../structural/fragmentInfoByUUID\";\n\nexport function getParseBindTextResults(node: Node): ParseBindTextResult[] {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as Element;\n const bindText = element.getAttribute(config.bindAttributeName) || '';\n const results = parseBindTextsForElement(bindText);\n // ボリューム要素の `state.<key>: path` は注入口の宣言で、束縛ではない(B14③)。ボリュームが\n // 接ぎ木の時に自分で読む — ここで束縛にすると、無い `state` プロパティへの書き込みとして適用に失敗する\n if (element.localName === config.tagNames.state) {\n if (element.hasAttribute(\"mount\")) {\n return results.filter((result) => result.propSegments[0] !== VOLUME_INJECTION_PROP);\n }\n // `mount=` の無い `<wcs-state>` の左辺 `state…` は、誰も読まないまま束縛として残り、\n // 存在しない `state` プロパティへの書き込みとして適用の段で落ちていた。書いた場所を名指しする。\n // 1 段(`state: x`)と 2 段以上(`state.<key>: x`)で助言が違う — 前者に `mount=` を足しても\n // 今度は `inject one key at a time` になるので、助言が回らないように分ける\n const injection = results.find((result) => result.propSegments[0] === VOLUME_INJECTION_PROP);\n if (typeof injection !== \"undefined\") {\n const where =\n `on a volume element — a <${config.tagNames.state}> with a \"mount\" attribute`;\n raiseError(injection.propSegments.length === 1\n ? `[wcs/mount-path-invalid] \"${injection.propName}\" is the reserved namespace for volume injection, ` +\n `so it cannot be bound as an element property. Write one key at a time ` +\n `(\"${VOLUME_INJECTION_PROP}.<key>: <path>\") ${where}.`\n : `[wcs/mount-path-invalid] \"${injection.propName}: ${injection.statePathName}\" is a volume injection ` +\n `declaration, and it can only be written ${where}. Add mount=\"<path>\", or bind an element ` +\n `property instead.`);\n }\n }\n return results;\n } else if (node.nodeType === Node.COMMENT_NODE) {\n const bindTextOrUUID = parseCommentNode(node);\n if (bindTextOrUUID === null) {\n raiseError(`Comment node binding text not found.`);\n }\n const fragmentInfo = getFragmentInfoByUUID(bindTextOrUUID);\n let parseBindingTextResult = fragmentInfo?.parseBindTextResult ?? null;\n let uuid: string | null = null;\n if (parseBindingTextResult === null) {\n // It is not a structural fragment UUID, so treat it as bindText\n parseBindingTextResult = parseBindTextForEmbeddedNode(bindTextOrUUID);\n uuid = null;\n } else {\n uuid = bindTextOrUUID;\n }\n return [{\n ...parseBindingTextResult,\n uuid: uuid,\n }]\n }\n return [];\n}","import { IParsedFilter } from \"../types\";\n\n/**\n * `if` / `else` の反転として、エンジン自身がパース結果へ足すフィルタ(解析の段の形 —\n * 名前と引数だけ。要件 D16)。実関数は束縛計画の段で登録簿から引かれる。\n *\n * `not` は core(`core/filterRegistry.ts` の `CORE_FILTERS`)と `features/formats`\n * (`formats/builtinFilters.ts`)が**同じ実装**(`!value`)を持つので、formats を入れない\n * 分割 core のページでも、入れたページでも同じ答えになる。ここが食い違うと\n * `if: 0` に対する `else:` がどちらの枝も描かれない(`applyChangeToIf` は `Boolean()` で\n * 寄せるのに `not` が非 boolean で throw していた)。\n */\nlet _notFilterInfo: IParsedFilter | undefined = undefined;\n\nexport function createNotFilter(): IParsedFilter {\n return _notFilterInfo ??= { filterName: \"not\", args: [] };\n}\n","import { indexOfOutsideQuotes, splitOutsideQuotes } from \"../bindTextParser/utils.js\";\nimport { config } from \"../config.js\";\nimport { DELIMITER, WILDCARD } from \"../define.js\";\n\nconst COMMENT_REGEX = /^(\\s*@@\\s*(?:.*?)\\s*:\\s*)(.+?)(\\s*)$/;\n\n/**\n * 右辺の短縮パス(`.name` / `.`)を展開する。\n *\n * ここの `|` 走査は、**現在の文法では素の `indexOf` と結果が変わらない** — 右辺で引用符が\n * 現れるのはフィルタ引数、つまり最初の `|` より後ろだけなので、「引用符の中の `|` が\n * 最初に来る」形が作れない(ゆえに変異テストでも差が出ない)。それでも正本のヘルパで\n * 走らせているのは、下の `expandBindAttribute` の `;` / `:` と規準を 1 つに揃えるため。\n * **パスそのものに引用符を許す拡張が入れば、ここだけが素の走査だと即座に破れる。**\n */\nfunction expandShorthandInStatePart(statePart: string, forPath: string): string {\n const prefix = forPath + DELIMITER + WILDCARD;\n const pipeIndex = indexOfOutsideQuotes(statePart, '|');\n let pathPart: string;\n let suffix: string;\n if (pipeIndex !== -1) {\n pathPart = statePart.slice(0, pipeIndex).trim();\n suffix = statePart.slice(pipeIndex);\n } else {\n pathPart = statePart.trim();\n suffix = '';\n }\n if (pathPart === '.') {\n pathPart = prefix;\n } else if (pathPart.startsWith('.')) {\n pathPart = prefix + DELIMITER + pathPart.slice(1);\n } else {\n return statePart;\n }\n if (suffix.length > 0) {\n return pathPart + suffix;\n }\n return pathPart;\n}\n\nfunction expandCommentData(data: string, forPath: string): string {\n const match = COMMENT_REGEX.exec(data);\n if (match === null) {\n return data;\n }\n const commentPrefix = match[1];\n const bindText = match[2];\n const commentSuffix = match[3];\n const expanded = expandShorthandInStatePart(bindText, forPath);\n return commentPrefix + expanded + commentSuffix;\n}\n\n/**\n * `for` 行の短縮パス(`.name` / `.`)を `items.*.name` へ展開する。\n *\n * 区切りの走査は**引用符の外だけ**(要件 B1)。`splitBindTexts` と同じ正本のヘルパを使う:\n * ここで素の `split(';')` / `indexOf(':')` / `indexOf('|')` を使うと、\n * `value|defaults('00:00'): .startTime` のようなごく普通のフィルタ引数で `statePart` が\n * `00'): .startTime` になり、短縮展開が起きず `.startTime` のまま残って\n * `[wcs/binding-path-missing]` が出る — しかも `getBindingsReady` は reject しないので\n * **行が 1 つも描画されないまま無言で終わる**。lint と拡張は正しく展開するので気づけない。\n */\nfunction expandBindAttribute(attrValue: string, forPath: string): string {\n const parts = splitOutsideQuotes(attrValue, ';');\n let changed = false;\n const result = parts.map(part => {\n const trimmed = part.trim();\n if (trimmed.length === 0) return part;\n const colonIndex = indexOfOutsideQuotes(trimmed, ':');\n if (colonIndex === -1) return part;\n const propPart = trimmed.slice(0, colonIndex).trim();\n const statePart = trimmed.slice(colonIndex + 1).trim();\n const expanded = expandShorthandInStatePart(statePart, forPath);\n if (expanded !== statePart) {\n changed = true;\n return `${propPart}: ${expanded}`;\n }\n return part;\n });\n if (!changed) return attrValue;\n return result.join(';');\n}\n\nexport function expandShorthandInBindAttribute(attrValue: string, forPath: string): string {\n return expandBindAttribute(attrValue, forPath);\n}\n\nexport function expandShorthandPaths(root: DocumentFragment, forPath: string): void {\n const bindAttr = config.bindAttributeName;\n const walker = document.createTreeWalker(\n root,\n NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT,\n );\n\n while (walker.nextNode()) {\n const node = walker.currentNode;\n if (node.nodeType === Node.COMMENT_NODE) {\n const comment = node as Comment;\n comment.data = expandCommentData(comment.data, forPath);\n continue;\n }\n const element = node as Element;\n if (element instanceof HTMLTemplateElement) {\n continue;\n }\n const attr = element.getAttribute(bindAttr);\n if (attr !== null) {\n const expanded = expandBindAttribute(attr, forPath);\n if (expanded !== attr) {\n element.setAttribute(bindAttr, expanded);\n }\n }\n }\n}\n","\nexport function getNodePath(node: Node): number[] {\n let currentNode: Node | null = node;\n const path: number[] = [];\n while(currentNode.parentNode !== null) {\n const nodes: Node[] = Array.from(currentNode.parentNode.childNodes);\n const index = nodes.indexOf(currentNode);\n path.unshift(index);\n currentNode = currentNode.parentNode;\n }\n return path;\n}\n","import { getParseBindTextResults } from \"../bindings/getParseBindTextResults\";\nimport { getSubscriberNodes } from \"../bindings/getSubscriberNodes\";\nimport { getNodePath } from \"./getNodePath\";\nimport { IFragmentNodeInfo } from \"./types\";\n\n/**\n * 正規化で捨てたコメントの原文(テキスト束縛だけ)。空 Text からは元の\n * `<!--@@: path|filter-->` を復元できないが、SSR のスナップショットはこの fragment を\n * **マークアップとして**直列化するので、原文が無いと `for` / `if` テンプレートの中の\n * `{{ }}` がスナップショットから丸ごと消える(ハイドレーション後に恒久的に空になる)。\n * 直列化の直前に原文へ戻すための控え。`Ssr.buildContent` だけが読む。\n */\nconst textCommentDataByNode = new WeakMap<Node, string>();\n\n/**\n * 正規化前のコメント原文(テキスト束縛の空 Text に対して)。無ければ null。\n * `null`(nodePath の解決に失敗)も受ける — `WeakMap.get` は弱く保持できないキーに\n * `undefined` を返すので、呼び手が解決失敗を分岐で捌かずに済む。\n */\nexport function getNormalizedTextCommentData(node: Node | null): string | null {\n return textCommentDataByNode.get(node as Node) ?? null;\n}\n\nexport function getFragmentNodeInfos(fragment: DocumentFragment): IFragmentNodeInfo[] {\n const fragmnentNodeInfos: IFragmentNodeInfo[] = [];\n const subscriberNodes = getSubscriberNodes(fragment);\n for(const subscriberNode of subscriberNodes) {\n const parseBindingTextResults = getParseBindTextResults(subscriberNode);\n let node = subscriberNode;\n // テンプレート登録時の事前正規化: text 専用の wcs-text コメントは、この時点で\n // 空 Text に置き換えておく。行 clone は最初から Text を持ち、getBindingInfos が\n // その Text を replaceNode に使うため、行ごとの createTextNode と start() 時の\n // replaceChild(コメント→Text 差し替え)が丸ごと不要になる。\n // 置換は同じ位置なので nodePath は不変。wcs-for/if 等の構造コメントは\n // アンカーとしてコメントのまま維持する(bindingType で判別)。\n // 非フラグメント経路(実 DOM 上のコメント)は従来どおり実行時に差し替える。\n if (\n subscriberNode.nodeType === Node.COMMENT_NODE\n && parseBindingTextResults.length === 1\n && parseBindingTextResults[0].bindingType === \"text\"\n && subscriberNode.parentNode !== null\n ) {\n const textNode = document.createTextNode(\"\");\n // 原文を控えてから捨てる(SSR の直列化が戻す — textCommentDataByNode を参照)\n textCommentDataByNode.set(textNode, (subscriberNode as Comment).data);\n subscriberNode.parentNode.replaceChild(textNode, subscriberNode);\n node = textNode;\n }\n fragmnentNodeInfos.push({\n nodePath: getNodePath(node),\n parseBindTextResults: parseBindingTextResults,\n });\n }\n return fragmnentNodeInfos;\n}","\nexport function optimizeFragment(fragment: DocumentFragment): void {\n const childNodes = Array.from(fragment.childNodes);\n for(const childNode of childNodes) {\n if (childNode.nodeType === Node.TEXT_NODE) {\n const textContent = childNode.textContent || '';\n if (textContent.trim() === '') {\n // Remove empty text nodes\n fragment.removeChild(childNode);\n }\n }\n }\n}\n","import { getParseBindTextResults } from \"../bindings/getParseBindTextResults\";\nimport { findNestedLightDomComponents } from \"../bindings/lightDomComponentScope\";\nimport { parseBindTextsForElement } from \"../bindTextParser/parseBindTextsForElement\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { config } from \"../config\";\nimport { getUUID } from \"../getUUID\";\nimport { raiseError } from \"../raiseError\";\nimport { BindingType } from \"../types\";\nimport { createNotFilter } from \"./createNotFilter\";\nimport { expandShorthandInBindAttribute, expandShorthandPaths } from \"./expandShorthandPaths\";\nimport { setFragmentInfoByUUID } from \"./fragmentInfoByUUID\";\nimport { getFragmentNodeInfos } from \"./getFragmentNodeInfos\";\nimport { getNodePath } from \"./getNodePath\";\nimport { optimizeFragment } from \"./optimizeFragment\";\nimport { IFragmentInfo } from \"./types\";\n\nconst keywordByBindingType: Map<BindingType, string> = new Map<BindingType, string>([\n [\"for\", config.commentForPrefix],\n [\"if\", config.commentIfPrefix],\n [\"elseif\", config.commentElseIfPrefix],\n [\"else\", config.commentElsePrefix],\n]);\n\nconst notFilter = /*#__PURE__*/ createNotFilter();\n\nfunction cloneNotParseBindTextResult(\n bindingType: BindingType,\n parseBindTextResult: ParseBindTextResult\n): ParseBindTextResult {\n const filters = parseBindTextResult.outFilters;\n return {\n ...parseBindTextResult,\n outFilters: [...filters, notFilter],\n bindingType: bindingType,\n };\n}\n\n/**\n * パース結果の変換フック(Phase 2 のマウント — impl-plan §3-0 の 1)。\n *\n * マウントされたスコープでは、フラグメントのパース結果(テンプレート自身の for/if と\n * nodeInfos の中身)を**登録時にここで**親ツリーの絶対パスへ書き換える。行の実体化\n * (collectNodesAndBindingInfosByFragment)は変換済みの nodeInfos をそのまま使うので、\n * 行生成のホットパスに変換コストは載らない。\n *\n * shorthand 展開(`.name` → `<forPath>.*.name`)は**変換前の**内側パスで行う —\n * 変換後のパスを forPath に使うと、展開結果が絶対パスになり二重変換の判別が\n * つかなくなるため。したがって入れ子のフラグメントも常に「スコープ相対のパース結果 →\n * 変換」の順を保ち、変換は各レベルで一度だけ掛かる。\n *\n * `uuid` を持つ nodeInfo エントリ(入れ子フラグメントの参照 — 再帰で変換済み)には\n * 掛けない(collectNodesAndBindingInfos.applyTransform と同じ規則)。\n */\nexport type FragmentParseTransform = (parsed: ParseBindTextResult, forPath?: string) => ParseBindTextResult;\n\nfunction transformNodeInfos(\n nodeInfos: IFragmentInfo[\"nodeInfos\"],\n transform: FragmentParseTransform,\n forPath: string | undefined,\n): void {\n for (const nodeInfo of nodeInfos) {\n for (let i = 0; i < nodeInfo.parseBindTextResults.length; i++) {\n const parsed = nodeInfo.parseBindTextResults[i];\n if (parsed.uuid != null) continue;\n // forPath はこのフラグメントの中身を囲む for のスコープ相対パス(`$n` のシフト量の根拠)\n nodeInfo.parseBindTextResults[i] = transform(parsed, forPath);\n }\n }\n}\n\nfunction _getFragmentInfo(\n rootNode: Node,\n fragment: DocumentFragment,\n parseBindingTextResult: ParseBindTextResult,\n forPath?: string,\n transform?: FragmentParseTransform,\n // else 節はテンプレート自身の結果を if の**変換済み**結果から clone するため、\n // そこだけ再変換しない(nodeInfos は通常どおり変換する)\n transformOwnResult: boolean = true,\n): IFragmentInfo {\n optimizeFragment(fragment);\n if (typeof forPath === \"string\") {\n expandShorthandPaths(fragment, forPath);\n }\n collectStructuralFragments(rootNode, fragment, forPath, transform);\n // after replacing and collect node infos on child fragment\n const fragmentInfo = {\n fragment: fragment,\n // own result(テンプレート自身の for/if/elseif)にも forPath を渡す — `$n` の\n // シフト量は囲む for の翻訳が根拠(translateParsedForMount)で、渡し漏れると\n // record.delta に落ち、翻訳がワイルドカードを増やす部分マウント内の for の\n // `if: $n` / `elseif: $n` が誤った添字に解決される(transformNodeInfos と対称)。\n // if/elseif の forPath(呼び手の childForPath)は外側 forPath そのもの。\n // for テンプレートの own path は `$n` になり得ず、非 `$n` パスの変換は forPath を\n // 読まないため、for に自パスが渡っても無害\n parseBindTextResult: typeof transform === \"undefined\" || !transformOwnResult\n ? parseBindingTextResult\n : transform(parseBindingTextResult, forPath),\n nodeInfos: getFragmentNodeInfos(fragment),\n }\n if (typeof transform !== \"undefined\") {\n transformNodeInfos(fragmentInfo.nodeInfos, transform, forPath);\n }\n return fragmentInfo;\n}\n\n\nexport function collectStructuralFragments(rootNode: Node, walkRoot: Document | Element | DocumentFragment, forPath?: string, transform?: FragmentParseTransform): void {\n const elseKeyword = config.commentElsePrefix;\n // Light DOM の mapped コンポーネントの内側は、その子スコープが自分で処理する(§1.13)。\n // fragment info は rootNode + state 名で登録されるため、ホストのパスでここを拾うと\n // コンポーネント側の state がまだ名前登録を済ませておらず解決に失敗する。\n // コンポーネント要素自身は template ではないので、REJECT でサブツリーごと落として問題ない。\n const nestedComponents = findNestedLightDomComponents(walkRoot);\n const walker = document.createTreeWalker(\n walkRoot,\n NodeFilter.SHOW_ELEMENT,\n {\n acceptNode(node: Node) {\n const element = node as Element;\n if (nestedComponents.length > 0 && nestedComponents.indexOf(element) !== -1) {\n return NodeFilter.FILTER_REJECT;\n }\n if (element.tagName.toLowerCase() === 'template') {\n const bindText = element.getAttribute(config.bindAttributeName) || '';\n if (bindText.length > 0) {\n return NodeFilter.FILTER_ACCEPT;\n }\n }\n return NodeFilter.FILTER_SKIP;\n }\n }\n );\n let lastIfFragmentInfo: IFragmentInfo | null = null; // for elseif chaining\n const elseFragmentInfos: IFragmentInfo[] = []; // for elseif chaining\n const templates: HTMLTemplateElement[] = [];\n while (walker.nextNode()) {\n const template = walker.currentNode as HTMLTemplateElement;\n templates.push(template);\n }\n\n for(const template of templates) {\n let bindText = template.getAttribute(config.bindAttributeName) || '';\n if (typeof forPath === \"string\") {\n bindText = expandShorthandInBindAttribute(bindText, forPath);\n }\n const parseBindTextResults = parseBindTextsForElement(bindText);\n let parseBindTextResult = parseBindTextResults[0];\n const keyword = keywordByBindingType.get(parseBindTextResult.bindingType);\n if (typeof keyword === 'undefined') {\n continue;\n }\n\n const bindingType = parseBindTextResult.bindingType;\n const fragment = template.content;\n const uuid = getUUID();\n let fragmentInfo: IFragmentInfo | null = null;\n\n // Determine childForPath for shorthand expansion\n const childForPath = bindingType === \"for\"\n ? parseBindTextResult.statePathName\n : forPath;\n\n if (bindingType === \"else\") {\n // check last 'if' or 'elseif' fragment info\n if (lastIfFragmentInfo === null) {\n raiseError(`'else' binding found without preceding 'if' or 'elseif' binding.`);\n }\n // else condition(if の変換済み結果の clone なので自身の再変換はしない)\n parseBindTextResult = cloneNotParseBindTextResult(\"else\", lastIfFragmentInfo.parseBindTextResult);\n fragmentInfo = _getFragmentInfo(rootNode, fragment, parseBindTextResult, childForPath, transform, false);\n setFragmentInfoByUUID(uuid, rootNode, fragmentInfo);\n\n const lastElseFragmentInfo = elseFragmentInfos.at(-1);\n const placeHolder = document.createComment(`@@${keyword}:${uuid}`);\n if (typeof lastElseFragmentInfo !== \"undefined\") {\n template.remove();\n lastElseFragmentInfo.fragment.appendChild(placeHolder);\n lastElseFragmentInfo.nodeInfos.push({\n nodePath: getNodePath(placeHolder),\n parseBindTextResults: getParseBindTextResults(placeHolder),\n });\n } else {\n template.replaceWith(placeHolder);\n }\n } else if (bindingType === \"elseif\") {\n // check last 'if' or 'elseif' fragment info\n if (lastIfFragmentInfo === null) {\n raiseError(`'elseif' binding found without preceding 'if' or 'elseif' binding.`);\n }\n\n fragmentInfo = _getFragmentInfo(rootNode, fragment, parseBindTextResult, childForPath, transform);\n setFragmentInfoByUUID(uuid, rootNode, fragmentInfo);\n const placeHolder = document.createComment(`@@${keyword}:${uuid}`);\n\n // create else fragment\n const elseUUID = getUUID();\n const elseFragmentInfo: IFragmentInfo = {\n fragment: document.createDocumentFragment(),\n parseBindTextResult: cloneNotParseBindTextResult(\"else\", lastIfFragmentInfo.parseBindTextResult),\n nodeInfos: [],\n };\n elseFragmentInfo.fragment.appendChild(placeHolder);\n elseFragmentInfo.nodeInfos.push({\n nodePath: getNodePath(placeHolder),\n parseBindTextResults: getParseBindTextResults(placeHolder),\n });\n setFragmentInfoByUUID(elseUUID, rootNode, elseFragmentInfo);\n const lastElseFragmentInfo = elseFragmentInfos.at(-1);\n elseFragmentInfos.push(elseFragmentInfo);\n const elsePlaceHolder = document.createComment(`@@${elseKeyword}:${elseUUID}`);\n\n if (typeof lastElseFragmentInfo !== \"undefined\") {\n template.remove();\n lastElseFragmentInfo.fragment.appendChild(elsePlaceHolder);\n lastElseFragmentInfo.nodeInfos.push({\n nodePath: getNodePath(elsePlaceHolder),\n parseBindTextResults: getParseBindTextResults(elsePlaceHolder),\n });\n } else {\n template.replaceWith(elsePlaceHolder);\n }\n\n } else {\n fragmentInfo = _getFragmentInfo(rootNode, fragment, parseBindTextResult, childForPath, transform);\n setFragmentInfoByUUID(uuid, rootNode, fragmentInfo);\n const placeHolder = document.createComment(`@@${keyword}:${uuid}`);\n template.replaceWith(placeHolder);\n }\n\n // Update lastIfFragmentInfo for if/elseif/else chaining\n if (bindingType === \"if\") {\n elseFragmentInfos.length = 0; // start new if chain\n lastIfFragmentInfo = fragmentInfo;\n } else if (bindingType === \"elseif\") {\n lastIfFragmentInfo = fragmentInfo;\n } else if (bindingType === \"else\") {\n lastIfFragmentInfo = null;\n elseFragmentInfos.length = 0; // end if chain\n }\n }\n}\n","import { BINDER_KEY, IWcsBinder, flushPendingBinds } from \"../protocol/binder\";\nimport { config } from \"../config\";\nimport { convertMustacheToComments } from \"../mustache/convertMustacheToComments\";\nimport { collectStructuralFragments } from \"../structural/collectStructuralFragments\";\nimport { BindingSession, hasInterestedSession } from \"./BindingSession\";\nimport { areBindingsBuilt } from \"../stateElementByName\";\nimport { initializeBindings } from \"./initializeBindings\";\nimport { getSubscriberNodes } from \"./getSubscriberNodes\";\nimport { isLightDomMappedStateElement } from \"./lightDomComponentScope\";\n\n/**\n * binder プロトコルの提供側(docs/binder-protocol-design.md)。\n *\n * `buildBindings` は起動時に `document.body` を 1 回走査するだけなので、そのとき\n * document に居なかったノードのバインドは存在しない。router が後から差し込む\n * ルート内容や `<wcs-head>` のクローンがこれに当たり、書いたバインドが黙って\n * 何もしない状態になっていた。`bind()` はその取りこぼしを 1 サブツリー分だけ\n * 埋める。\n *\n * **走査を勝手に広げない。** MutationObserver が見た全追加ノードを走査する形に\n * すると、バインドを 1 個も持たない挿入(大多数)にコストが乗り、さらに\n * `innerHTML` で入れた外部由来の DOM が `data-wcs` を発火させることになる。\n * ここで束ねるのは**明示的に渡されたものだけ**である。\n */\nconst BIND_ATTRIBUTE_SELECTOR = (): string => `[${config.bindAttributeName}]`;\n\n/**\n * このサブツリーは既にバインド済みか。\n *\n * ルート内容は「起動時に active だったので全部バインド済み」か「一度も走査されて\n * いないので全部未バインド」のどちらかで、途中の状態を取らない。したがって\n * **宣言を持つ最初のノード 1 個**を見れば足りる。全ノードを走査して判定するのは\n * 同じ結論により高いコストを払うだけになる。\n */\nfunction alreadyBound(subtree: Node): boolean {\n if (hasInterestedSession(subtree)) {\n return true;\n }\n if (!isElement(subtree)) {\n return false;\n }\n if (subtree.hasAttribute(config.bindAttributeName)) {\n // 属性を持つのに台帳に居ない = 未バインド\n return false;\n }\n const first = subtree.querySelector(BIND_ATTRIBUTE_SELECTOR());\n return first !== null && hasInterestedSession(first);\n}\n\nfunction isElement(node: Node): node is Element {\n return node.nodeType === 1;\n}\n\nfunction bindNow(subtree: Element): void {\n // A subtree no longer in the document is left alone: one held until the first build may have\n // left it since (the build's own walk replaces a structural template handed over with its anchor).\n if (!subtree.isConnected || alreadyBound(subtree)) {\n return;\n }\n // Bind inside the subtree only, its root included (#409). `getSubscriberNodes`'s TreeWalker never\n // returns its root, and roots that declare on themselves do come here (`<wcs-head>`'s\n // `<title data-wcs=\"…\">`, a route's content handed over node by node), so the root is taken in by\n // hand — the shape SSR's hydration uses. This used to walk from the parent instead, which also\n // reached the root's siblings: a later sibling's structural template, not collected yet, was\n // registered as a plain binding, failed to apply and was never rendered, and siblings nobody\n // handed over were bound.\n const nodes: Node[] = subtree.hasAttribute(config.bindAttributeName) ? [subtree] : [];\n // A Light DOM mount (wired from the host, its `<wcs-state bind-component>` right under it): the\n // root's declarations belong to the host, and what is inside to the component's scope, which\n // collects it once wired (§1.13 — `getSubscriberNodes` prunes a nested one, never its walk root).\n if (!Array.from(subtree.children).some(\n (child) => child.localName === config.tagNames.state && isLightDomMappedStateElement(child))) {\n convertMustacheToComments(subtree);\n collectStructuralFragments(subtree.getRootNode(), subtree);\n nodes.push(...getSubscriberNodes(subtree));\n }\n // A session of its own, keyed by nothing. A session found by its root is what a scope disposes as a\n // whole: keyed by `subtree`, a Light DOM mount's host bindings joined the mount scope's session\n // (keyed by the component), and its re-initialization tore them down.\n initializeBindings(subtree, null, undefined, nodes, new BindingSession());\n}\n\n/**\n * 初期バインド構築より前に差し出されたサブツリー。\n *\n * `<wcs-head>` は `connectedCallback` の中でクローンを head へ入れるので、\n * state / router のどちらを先に読み込んでも「まだ構築が終わっていない」時点で\n * bind を求めてくる。そこで同期に束ねても `<wcs-state>` の登録が済んでおらず、\n * バインドは state を見つけられない。**構築の完了を唯一の合図にする。**\n */\nconst beforeFirstBuild: Element[] = [];\n\nfunction bind(subtree: Node): void {\n // Nothing to bind in a subtree not in a document (held, it would wait for a build that never comes)\n if (!isElement(subtree) || !subtree.isConnected || alreadyBound(subtree)) {\n return;\n }\n if (!areBindingsBuilt(subtree.getRootNode())) {\n beforeFirstBuild.push(subtree);\n return;\n }\n bindNow(subtree);\n}\n\n/**\n * 初期バインド構築の完了時に呼ぶ(stateElementByName.ts)。binder が居ない時点で\n * 差し出された分(プロトコルの保留キュー)と、居たが早すぎた分をまとめて束ねる。\n */\nexport function drainPendingBinds(): void {\n const pending = beforeFirstBuild.splice(0, beforeFirstBuild.length);\n for (const subtree of pending) {\n bindNow(subtree);\n }\n flushPendingBinds();\n}\n\nconst binder: IWcsBinder = {\n protocol: \"wcs-binder\",\n version: 1,\n bind,\n};\n\n/**\n * グローバル symbol へ自分を載せる。`bootstrapState` から呼ぶ。\n *\n * 既に別のコピーが載っているなら譲る。1 ページに 2 つの state バンドルが載る構成\n * (CDN の取り違え)で、後から読まれた側が先客を追い出すと、先客がバインドした\n * ノードの台帳と食い違う。\n */\nexport function registerBinder(): void {\n const globals = globalThis as Record<symbol, unknown>;\n if (globals[BINDER_KEY] === undefined) {\n globals[BINDER_KEY] = binder;\n }\n // ここでは引き取らない。`<wcs-state>` の登録は connectedCallback の await より\n // 後なので、この時点ではまだ state が居ない。保留分は初期バインド構築の完了時に\n // 流す(stateElementByName.ts)。そこが「state が確実に居る」最初の瞬間である。\n}\n\n/** テスト用: 登録を外す */\nexport function _unregisterBinder(): void {\n const globals = globalThis as Record<symbol, unknown>;\n if (globals[BINDER_KEY] === binder) {\n delete globals[BINDER_KEY];\n }\n}\n"],"names":["BINDER_KEY","Symbol","for","PENDING_KEY","TAKEN_KEY","flushPendingBinds","binder","candidate","globalThis","protocol","version","bind","getBinder","queue","globals","undefined","pendingQueue","length","pending","splice","taken","WeakSet","takenSet","subtree","add","MUSTACHE_REGEX","SKIP_TAGS","Set","convertMustacheToComments","root","skip","config","enableMustache","walker","document","createTreeWalker","NodeFilter","SHOW_TEXT","textNodes","nextNode","push","currentNode","textNode","parentElement","has","tagName","replaceTextNode","convertTextNodes","templates","Array","from","querySelectorAll","template","namespaceURI","SVG_NAMESPACE","newTemplate","createElement","childNodes","i","childNode","content","appendChild","attr","attributes","setAttribute","name","value","replaceWith","text","data","lastIndex","test","fragment","createDocumentFragment","match","exec","index","createTextNode","slice","bindText","createComment","parentNode","replaceChild","STRUCTURAL_BINDING_TYPE_SET","finalizeArg","firstQuoteStart","lastQuoteEnd","startLimit","start","endLimit","end","NUMBER_LITERAL","toLiteral","quoted","Number","parseFilterArgsWithLiterals","argsText","args","literals","current","inQuote","hasQuote","flush","arg","char","raiseError","LINT_HINT","last","trimFn","s","trim","isQuote","c","indexOfOutsideQuotes","quote","splitOutsideQuotes","separator","parts","parseFilters","filterTextList","filterIOType","sourceText","source","join","map","filterText","openParenIndex","closeParenIndex","found","lastIndexOfOutsideQuotes","lastIndexOf","trailing","filterName","substring","includes","MODIFIER_SEPARATOR","modifiers","split","cacheFilterInfos","Map","parsePropPart","propPart","pos","FILTER_SEPARATOR","propText","filterTexts","filtersText","filters","get","set","modifierParts","propName","propModifiersText","propSegments","DELIMITER","some","segment","propModifiers","inFilters","parseStatePart","statePart","stateAndPath","indexOf","statePathName","isLoopRelative","startsWith","body","statePathInfo","getPathInfo","outFilters","KEYWORDS_WITHOUT_MODIFIERS","ELSE_KEYWORD","SPREAD_PROP","EXPLICIT_PROPERTY_REJECTED_HEADS","CLASS_NAMESPACE","ATTR_NAMESPACE","STYLE_NAMESPACE","COMMAND_NAMESPACE","EVENT_TOKEN_NAMESPACE","VOLUME_INJECTION_PROP","parseBindTextsForElement","bindTexts","BINDING_SEPARATOR","splitBindTexts","filter","results","separatorIndex","PROP_VALUE_SEPARATOR","keyword","pathInfo","bindingType","stateResult","propResult","EVENT_PROP_PREFIX","r","bindTextByNode","WeakMap","bindingTypeKeywordSet","commentTextPrefix","commentForPrefix","commentIfPrefix","commentElseIfPrefix","commentElsePrefix","EMBEDDED_REGEX","RegExp","parseCommentNode","node","savedText","nodeType","Node","COMMENT_NODE","parseBindTextForEmbeddedNode","bindingPromiseByNode","resolvedNodes","id","async","waitInitializeBinding","bindingPromise","resolveFn","promise","Promise","resolve","getInitializeBindingPromiseByNode","resolveInitializedBinding","existing","cache","getCustomElement","cached","ELEMENT_NODE","element","toLowerCase","hasAttribute","is","getAttribute","toAdapter","registry","whenDefined","getCustomElementRegistry","owner","customElementRegistry","scoped","customElements","owned","upgradeCustomElement","upgrade","readBindableDeclaration","target","addEventListener","removeEventListener","declaration","constructor","wcBindable","isInteger","knownProperties","readNamedList","properties","isValidPropertyDescriptor","declaredInputs","inputs","isValidInputDescriptor","declaredCommands","commands","isValidCommandDescriptor","liveDeclaration","descriptor","event","getter","attribute","isValidEntry","isArray","entries","entry","makeExpandedEntry","base","expandedPath","dedupKey","expandSpread","options","allowDeferred","expanded","spreadOrigin","result","bindable","targetBase","seen","keys","lastIndexByKey","key","final","debug","overrider","tagText","console","resolveNodePath","path","remaining","firstChild","nextSibling","planFilters","planned","filterFn","resolveFilterFn","planBinding","parsed","bindingsByNode","getBindingsByNode","isLightDomMappedStateElement","stateElement","Element","bindAttributeName","findNestedLightDomComponents","components","stateElements","tagNames","state","component","isInsideAnyComponent","contains","getSubscriberNodes","subscriberNodes","nestedComponents","SHOW_ELEMENT","SHOW_COMMENT","acceptNode","FILTER_ACCEPT","FILTER_SKIP","registeredNodeSet","processParseResultsForNode","parseResults","transform","bindings","deferred","parseBindingTextResults","bindingInfos","parseBindingTextResult","replaceNode","TEXT_NODE","getBindingInfos","uuid","applyTransform","setBindingsByNode","collectNodesAndBindingInfos","collectNodesAndBindingInfosOf","allBindings","deferredSpreads","getParseBindTextResults","markNodeRegistered","processDeferredNode","delete","unregisterNode","loopContextByNode","mountedScopeHost","setMountedScopeHost","resolver","getLoopContextByNode","paramNode","loopContext","next","ShadowRoot","setLoopContextByNode","count","getUUID","toString","chainGeneration","NO_VALUE","ListIndex","parentListIndex","position","_index","_version","_indexes","_listIndexes","_chainGeneration","_homeParentListIndex","_value","cacheStamp","ref","homeParentListIndex","this","indexes","home","dirty","listIndexes","WeakRef","varName","reparent","at","deref","createListIndex","reparentListIndex","listIndex","getHomeParentListIndex","rehomeListIndex","getRowCacheStamp","setListIndexValue","row","previous","changed","Object","rowsByElement","held","size","pruneSizeByRows","liveRowsOf","rememberRowOfElement","stale","rows","forEach","other","isUnderRetiredRow","retiredListIndexes","getListIndexValue","isSameListIndexValue","updateBatch","swapBaselineLists","markSwapBaselineList","list","isSwapBaselineList","listIndexesByList","isRetiredListIndex","releasedListsByParent","releaseListAtParent","holder","kept","released","moved","movedByList","holdersByList","isHoldingParent","handedOverByList","holdListAtParent","handedOver","hasReleasedList","isGoneParent","swapPendingBatchByRow","markRowSwapPending","clearRowSwapPending","covers","pruneSizeByList","lentLists","getElementAliases","readList","others","getRepairTarget","first","oldParent","newParent","isRestoredHome","canReparent","getListIndexesByList","resolveListIndexesByList","image","rebaseRenderedList","_row","holders","addHolders","parent","ownedListIndexes","isOwnedListIndexes","disownListIndexes","setListIndexesByList","renderedListByList","getRenderedList","rendered","hasRenderedList","lastListValueByAbsoluteStateAddress","addressesByListByStateElement","NO_ADDRESSES","sweepAtByAddresses","swappedListByAddress","addressesByListOf","address","absolutePathInfo","addressesByList","getLastListValueByAbsoluteStateAddress","setLastListValueByAbsoluteStateAddress","addresses","Math","max","getAddressesByLastListValue","markSwappedList","hasLastListValueByAbsoluteStateAddress","stateListBaselineByAbsoluteStateAddress","pendingBaselines","batchDepth","getStateListBaseline","setStateListBaseline","beginStateListBaselineBatch","endStateListBaselineBatch","hasStateListBaseline","setLoopContextSymbol","getByAddressSymbol","hasByAddressSymbol","connectedCallbackSymbol","disconnectedCallbackSymbol","updatedCallbackSymbol","errorCallbackSymbol","_cache","_cacheNullListIndex","AbsoluteStateAddress","createAbsoluteStateAddress","cacheByAbsolutePathInfo","treePathsByElement","getTreePath","table","treePath","freeze","TreePath","liftAddress","absoluteAddressOf","rootNodeByFragment","setRootNodeByFragment","rootNode","getRootNodeByFragment","cacheCalcWildcardLen","calcWildcardLen","targetPathInfo","path1","path2","wildcardCount","wildcardPathSet","len","intersection","listIndexAtWildcard","wildcardPos","getScopedIndexes","listIndexByBindingInfoByLoopContext","getListIndexByBindingInfo","bindingInfo","listIndexByBindingInfo","wildcardLen","absoluteStateAddressByBinding","resolveBindingRootNode","binding","knownRootNode","getRootNode","isConnected","nodeName","getAbsoluteStateAddressByBinding","absoluteStateAddress","getStateElement","clearAbsoluteStateAddressByBinding","bindingsByAbsoluteStateAddress","addBindingByAbsoluteStateAddress","devtoolsSink","type","absoluteAddress","removeBindingByAbsoluteStateAddress","patternLedger","peekBindingsForAddress","StateAddress","_parentAddress","_rowAddress","lastSegment","WILDCARD","parentAddress","parentPathInfo","segments","createStateAddress","holdsRow","wildcardPositions","cacheByPathInfo","stateAddressByBindingInfo","getStateAddressByBindingInfo","stateAddress","clearStateAddressByBindingInfo","createHandlerBindingRegistry","attachedByKey","countByKey","attached","remove","countOf","keyCount","clear","handlerByHandlerKey","bindingRegistry","getHandlerKey","eventName","filterKey","filterListKey","getEventName","modifier","attachCheckboxEventHandler","MODIFIER_READONLY","checkboxEventHandler","warn","checked","filteredNewValue","createState","currentValue","concat","toSpliced","isThenable","then","reportHandlerError","error","describe","captureHandlerRejection","values","catch","Token","_name","_subscribers","subscribe","fn","unsubscribe","emit","EventToken","_stateElement","super","kind","tokenName","subscriberCount","registryByStateElement","getOrCreateEventToken","token","clearEventTokenRegistry","listenerByBinding","attachEventTokenHandler","customTagName","propertyName","getWcBindable","propDesc","didYouMean","handler","MODIFIER_PREVENT","preventDefault","MODIFIER_STOP","stopPropagation","eventTokenNames","createStateAsync","CommandToken","isCommandToken","modifierKey","m","sort","stateEventHandlerFunction","handlerName","isCommand","STATE_COMMAND_NAMESPACE_NAME","scopedWildcardCount","hooks","addressHooks","scopes","handlerScope","Reflect","apply","isDomEventBinding","attachEventHandler","stateEventHandler","detachEventHandler","attachRadioEventHandler","radioEventHandler","CHECK_TYPES","DEFAULT_VALUE_PROP_NAMES","isPossibleTwoWay","inputType","customClass","nextWireId","nextTransactionId","nextSynchronousScopeId","wireIdsByNode","getWireId","member","byKey","wireKey","wireId","getEdgeId","direction","EMPTY_EDGES","beginPropagationTransaction","originBindingId","transactionId","visitedEdges","hop","extendPropagationContext","context","edgeId","currentContext","getCurrentPropagationContext","runWithPropagationContext","callback","receiptStack","commitElementValue","occurrence","consumeElementWrite","consumed","producerValueObserversByNode","DEFAULT_GETTER","e","detail","warnedDefaultGetter","getterIds","nextGetterId","attachedByBinding","valueGetter","isOccurrence","getterIdOf","twowayEventHandlerFunction","newValue","propValue","reason","prototype","hasOwnProperty","call","props","warnDefaultGetterMismatch","producerObservers","observer","propagationContext","enablePropagationContext","receipt","active","matchWriteReceipt","writtenValue","coveredBySameValueGuard","sameValueGuard","toStateEdgeId","baseContext","commitToState","attachTwowayEventHandler","getValueGetter","semantics","isOccurrenceProperty","twowayEventHandler","observerSkipNodes","markObserverSkipOnRemove","consumeObserverSkipOnRemove","skipRemovedChildrenByParent","consumeObserverSkipRemovedChildren","observerSkipAddedNodes","markObserverSkipOnAdd","consumeObserverSkipOnAdd","pendingObservationCount","decrementPendingObservation","hasPendingObservation","DefinitionCoordinator","wait","reject","normalizedTagName","waiters","settle","waiter","pendingCount","coordinatorByRegistry","getDefinitionCoordinator","coordinator","LEFT_HAND_NAMESPACES","readOption","MODIFIER_KEY_INIT","MODIFIER_KEY_SYNC","hasInitialSyncModifier","STATE_CALL_POLICY","authority","syncOn","observable","outputOnly","NONE_CALL_POLICY","statePolicy","resolveInitialSyncPolicy","enableDirectionalInitialSync","explicitAuthority","parseSyncOn","hasOutput","hasInput","getSyncStateElement","DocumentFragment","resolveInitialAuthority","initialized","isBindingStateInitialized","nextRecordId","armQueue","nextGeneration","SLOT_PHASE_NAMES","rowByBinding","rowSlotIds","recordByBinding","sessionByRoot","bindingKeyByBinding","interestedSessionsByNode","addInterestedSession","session","hasInterestedSession","forEachInterestedSession","forEachInclusive","child","isObservableRoot","BindingOwner","Observer","MutationObserver","mutations","handleMutations","observe","childList","removed","added","mutation","removedNodes","addedNodes","reconnected","handleRemovedNode","handleAddedNode","applyChangeFromBindings","ownerByRoot","getBindingOwner","bindingKey","registerPattern","knownRoot","rowMap","addBindingByPattern","registerAbsoluteAddress","unregisterFromLedger","removeBindingByPattern","addRecordTeardown","record","teardown","teardowns","BindingSession","records","rowPlan","knownBindingsByNode","optionsByBinding","deferredByNode","disposedAt","initialize","registerAddress","resolvedOptions","registerPathInfo","applyOnReconnect","remember","rowRecord","rowOf","rowSlot","phases","patternPathInfos","registered","registerRowSlot","phase","anchor","patternListIndex","settleInitialRecord","settleConnectedSnapshot","shouldApplyState","activate","activatePlanRows","slot","planSlot","plan","slots","flags","policy","initialApplyDone","resolvedAuthority","outputOnlyMember","observationPending","getRecord","ids","info","generation","addTeardown","isAlive","deferUntilDefined","tasks","finish","task","cancel","born","arm","queueMicrotask","disposeBinding","disposeRowSlot","disposeRecord","isRowSession","currentRowPlan","disposeBindings","destroyRow","destroyRowRecord","destroyRecords","dispose","canWholesaleDestroy","pendingDefinitions","forEachActiveBindingNode","rebindAddresses","rebound","unregisterRowSlot","oldAbs","patternPathInfo","newAbs","observableRootFor","known","onError","knownMapFor","remembered","rememberedOptions","initializeRow","n","fill","patternListIndexes","addKnownRowBinding","isEvent","revived","runRowSlotTeardowns","slotIndex","replaceToReplaceNode","recordOptions","initialPolicy","initialSettled","eventSequence","hasProducerValue","producerValue","eventAttached","twowayAttached","attachListeners","runTeardowns","detachRadioEventHandler","detachCheckboxEventHandler","attachAfterDefinition","removeObserver","byProperty","observers","addTwowayValueObserver","listener","detachEventTokenHandler","attach","HTMLElement","readProducerSnapshot","eventWins","sequence","filteredValue","commitProducerValue","setPathInfo","detachTwowayEventHandler","reverse","getOrCreateBindingSession","getBindingSession","componentApplyHooks","setComponentApplyHooks","getFilteredValue","EMPTY_ARRAY","subscribedBindings","bindingsByContent","getBindingsByContent","setBindingsByContent","nodesByContent","getNodesByContent","setNodesByContent","nodes","bindLoopContextToContent","indexBindingsByContent","getIndexBindingsByContent","setIndexBindingsByContent","difference","elem","cacheEntryByAbsoluteStateAddress","rowCacheParents","getCacheEntryByAbsoluteStateAddress","setCacheEntryByAbsoluteStateAddress","cacheEntry","lastWildcardPath","dirtyCacheEntryByAbsoluteStateAddress","TRANSITION_RUNNER_KEY","getTransitionRunner","run","accepts","runTransition","mutate","types","runner","updateBatchListeners","enqueueListeners","applyingDepth","pendingDepth","pendingExternal","registerEnqueueListener","registerUpdateBatchListener","priority","findIndex","unregisterUpdateBatchListener","reportDeferredApplyFailure","Updater","_queueUpdateRecords","_queueRenderOnlyAddresses","enqueueAbsoluteAddress","requireStartProcess","_isQueueEmpty","_scheduleDrain","enqueueRenderOnlyAddress","updateRecords","renderOnlyAddresses","_applyChange","hasQueuedPath","testApplyChange","absoluteAddresses","contexts","depth","contextByAbsoluteAddress","landedAddresses","droppedTransactionId","winnerTransactionId","processBindings","propagationContextByBinding","MAX_PROPAGATION_HOPS","maxHops","applyBindings","MAX_RENDER_CHAIN_DEPTH","paths","absAddress","maxDepth","inSsr","batch","notifyUpdateBatchListeners","updater","getUpdater","ledgerByElement","keyByPathByAddress","entriesByListIndex","indexKeyedByListIndex","anyRegistered","pendingKeyedWalk","pushPendingKeyedWalk","takePendingKeyedWalk","watchersByElement","watchersByIndexes","descendantRowsByAncestor","watchersByOwnerListIndex","descendantsByElement","EMPTY","recordAncestors","ledger","ledgerOf","recorded","cumulativePaths","byAncestor","descendants","byPath","lastValue","tracked","addToKey","keyMap","removeFromKey","keyMapOf","oldKey","pushEntry","isNew","ancestor","linkAncestors","levelListIndex","registerKeyedDependency","registerIndexKeyedDependency","recordTrackedKeyedPath","getKeyedLedgerView","watchers","hasKeyedDependents","registerIndexWatcher","getterPathInfo","watcher","byList","find","w","getters","watchedRowsAt","out","moveIndexWatchers","oldIndexes","newIndexes","before","after","collect","keyedDependents","hasOldKey","newKey","hasLast","newDiffers","lastDiffers","hasKeyedDescendants","valueAt","keyedDescendantDependents","oldValue","hasOldValue","descendant","rest","allDependents","removeIndexEntry","dropRowSubscriptions","unlinkAncestors","dropWatchersOwnedBy","dropKeyedSubscriptionsByListIndex","rekeyIndexSubscriptions","oldIndex","newIndex","listDiffByOldListByNewList","EMPTY_LIST","EMPTY_SET","valueChangesByList","livePreviousLists","keepPreviousList","previousOf","isSameList","oldList","newList","retireRows","retireListIndexes","retired","createListDiff","rawOldList","rawNewList","diff","cachedDiff","diffByNewList","getListDiff","retValue","changeIndexSet","deleteIndexSet","addIndexSet","requester","isHeldElsewhere","newListIndex","lendRows","calcDiffIndexes","indexByValue","val","lent","existingIndexes","shift","existingListIndex","setListDiff","computeListDiff","valueChangeIndexes","syncListIndexes","reviveListIndexes","newIndexSet","oldIndexSet","oldPosByIndex","computeStableIndexSet","reused","seq","prevPos","sorted","lis","tails","prev","lo","hi","mid","k","longestIncreasingSubsequence","stable","seqIndex","bindingSessionByContent","getBindingSessionByContent","setBindingSessionByContent","planByContent","tailsByPlan","hasGetterOnPrefix","prefixes","getterPaths","applyPlanRow","rowPath","byRowPath","prefix","isIndexBinding","tail","accumulated","slotTails","hasReadMissing","readMissing","rowValue","rowRead","slotTail","applyChange","appliedBindingSet","missingKey","applyValueToBinding","activateContent","hasUpdatedCallback","hasRecursion","getPlanByContent","spreads","scheduleDeferredSpreads","deactivateContent","mounted","unbindLoopContextToContent","createEmptySet","contentSetByNode","setContentByNode","contents","getContentSetByNode","deleteContentByNode","recursiveBindingTypes","Content","_content","_childNodeArray","_firstNode","_lastNode","_mounted","_ranged","ranged","childNodeArray","firstNode","lastNode","appendTo","targetNode","_movableNodes","mountAfter","mover","moveBefore","insertBefore","tryDestroy","removeChild","unmount","unmountInPlace","_teardownBindings","resolveRanged","fragmentInfo","topLevelStructural","structural","hasTopLevelStructural","indexBit","min","ALL_INDEX_BITS","indexBitsOfFragment","bits","indexBits","nodeInfo","nodeInfos","parseBindTextResults","INDEX_BY_INDEX_NAME","getFragmentInfoByUUID","getIndexBitsByBinding","depthBits","createContentFromNodes","createPlanContent","cloneFragment","importNode","nodePath","indexBindings","nodeIndex","forNode","rowSessionByForNode","initializeRowBindings","setPlanByContent","createContent","directional","namespace","compileRowPlan","initialInfo","collectNodesAndBindingInfosByFragment","bindingSession","initializeBindingsByFragment","appendRowEndMarker","namedElements","NAMING_LEDGER_KEY","getAutoNaming","naming","limit","namingLimit","applyTransitionName","firstElementOf","style","counter","assigned","warned","getLedger","setProperty","lastNodeByNode","contentByListIndexByNode","pooledContentsByNode","isOnlyNodeInParentContentByNode","renderedListByNode","ssrBoundsByContent","placeSsrRow","label","bounds","hydrateSetContent","contentByListIndex","setContent","hydrateSetLastNode","hydrateSetRenderedList","countsAsParentContent","textContent","isPhysicallyAfter","compareDocumentPosition","DOCUMENT_POSITION_FOLLOWING","DOCUMENT_POSITION_DISCONNECTED","STRUCTURAL_BINDING_TYPES","clearAppliedMarks","nested","applyIndexBindings","movedBit","dropNestedContents","dropped","bindingInfoText","f","applyChangeToIf","rawNewValue","Boolean","ssrMode","log","ssrBlockRemoval","startComment","endComment","afterNode","autoNaming","store","getSsrProperties","getAllSsrPropertyNodes","trackedNodes","clearSsrPropertyStore","TRUSTED_TYPES_POLICY_SLOT","getTrustedTypesPolicy","setTrustedTypesPolicy","_enforced","_reported","reportTrustedTypesBlock","prop","innerHTML","isTrustedTypesEnforced","cause","createHTML","property","SSR_ATTR_PROPS","String","removeAttribute","selected","disabled","selectedIndex","idx","applyChangeToProperty","_context","displayProp","firstSegment","rememberOverwrittenObject","isHtmlSink","performWrite","propertyWriteSucceeded","trustHtmlValue","mirrorAttr","input","getInputAttributeMirror","attributeName","formatted","JSON","stringify","applyMirrorAttribute","extendedContext","bindingId","bindingGeneration","synchronousScopeId","pop","runWithWriteReceipt","attrHandler","addSsrProperty","subObject","isFrozen","rememberOverwrittenValue","recordInjectedKey","ssrWrappedNodes","applyChangeToWebComponent","_binding","_newValue","getValue","indexName","indexPos","wildcardScopeMessage","getIndexValueByLoopContext","scheduledBindings","reportFailure","applyChangeByFirstSegment","className","classList","toggle","attrName","styleName","methodName","elementRef","el","method","applyChangeByBindingType","nodeValue","listPathInfo","recordedLastValue","swapped","isSwappedList","shared","every","newListValue","newListValueByAbsAddress","contentMap","inPlaceContents","inPlace","byAddedIndex","collectInPlaceContents","fullDelete","isOnlyNode","prevCheckNode","previousSibling","nextCheckNode","onlyNode","isOnlyNodeInParentContent","markObserverSkipRemovedChildren","poolBudget","getPooledContents","POSITIVE_INFINITY","deleteIndex","bound","setPooledContent","elementPathInfo","loopContextStack","stableIndexSet","ssrLabel","pooledContents","createLoopContext","rowReused","unmountedByAncestor","revivedContent","if","else","elseif","radio","elementFilteredValue","checkbox","normalizedNewValue","fnByBinding","deferredSelectBindingByBinding","definedApplyVerifiedByBinding","skipPendingMountWrite","resolveCustomElementApply","stateProp","isComplete","isDeclared","deferredSelectBindings","updatedAbsAddressSetByStateElement","customTag","isWaitingDefinition","applyLatest","currentSession","Error","scheduleDeferredApply","sameRootVerified","targetState","newContext","reportBindingApplyError","failuresByStateElement","hasErrorCallback","failures","bindingIndex","nextBindingInfo","updatedCallback","absAddressSet","callbackError","original","parentLoopContext","contentBindings","initializeBindings","uncollectedNodes","waitForStateInitialize","elements","promises","initializePromise","all","buildBindings","collectStructuralFragments","shadowRoot","host","ENTRY_BY_FEATURE","watch","scan","streams","dcc","recursion","ssr","devtools","featureNotInstalledMessage","feature","ssrHooks","setSsrHooks","requireSsrHooks","stateElementByNode","bindingsReadyByNode","liveStateElements","registeredListeners","onStateElementRegistered","getLiveStateElements","getBindingsReady","markBindingsUnavailable","failed","bindingsBuiltRoots","setStateElementAlias","setBindingsReadyForScope","ready","markBindingsBuilt","setStateElement","enableSsr","hydrate","drainPendingBinds","fragmentInfoByUUID","setFragmentInfoByUUID","bindingPartial","parseBindTextResult","nodeBindingPartial","clearFragmentInfos","localName","injection","where","bindTextOrUUID","_notFilterInfo","createNotFilter","COMMENT_REGEX","expandShorthandInStatePart","forPath","pipeIndex","pathPart","suffix","expandCommentData","commentPrefix","commentSuffix","expandBindAttribute","attrValue","part","trimmed","colonIndex","expandShorthandInBindAttribute","expandShorthandPaths","bindAttr","comment","HTMLTemplateElement","getNodePath","unshift","textCommentDataByNode","getNormalizedTextCommentData","getFragmentNodeInfos","fragmnentNodeInfos","subscriberNode","optimizeFragment","keywordByBindingType","notFilter","cloneNotParseBindTextResult","_getFragmentInfo","transformOwnResult","transformNodeInfos","walkRoot","elseKeyword","FILTER_REJECT","lastIfFragmentInfo","elseFragmentInfos","childForPath","lastElseFragmentInfo","placeHolder","elseUUID","elseFragmentInfo","elsePlaceHolder","BIND_ATTRIBUTE_SELECTOR","alreadyBound","isElement","querySelector","bindNow","children","beforeFirstBuild","registerBinder"],"mappings":"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"}