@wcstack/state 3.3.0 → 3.5.0
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.
- package/README.ja.md +94 -27
- package/README.md +94 -27
- package/dist/auto.min.js +1 -1
- package/dist/auto.min.js.map +1 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/split/chunks/binder.js +1 -1
- package/dist/split/chunks/binder.js.map +1 -1
- package/dist/split/chunks/checkDependency.js +1 -1
- package/dist/split/chunks/checkDependency.js.map +1 -1
- package/dist/split/chunks/declarationAliases.js.map +1 -1
- package/dist/split/chunks/diagnosticsHooks.js.map +1 -1
- package/dist/split/chunks/featureBridge.js +1 -1
- package/dist/split/chunks/filterRegistry.js +1 -1
- package/dist/split/chunks/filterRegistry.js.map +1 -1
- package/dist/split/chunks/getAllPropertyDescriptors.js +1 -1
- package/dist/split/chunks/lifecycleHooks.js +1 -1
- package/dist/split/chunks/lifecycleHooks.js.map +1 -1
- package/dist/split/chunks/pathDiagnostics.js +1 -1
- package/dist/split/chunks/pathDiagnostics.js.map +1 -1
- package/dist/split/chunks/registerComponents.js +1 -1
- package/dist/split/chunks/registerComponents.js.map +1 -1
- package/dist/split/chunks/setAll.js +1 -1
- package/dist/split/chunks/setAll.js.map +1 -1
- package/dist/split/chunks/version.js +1 -1
- package/dist/split/core.d.ts +77 -1
- package/dist/split/core.js +1 -1
- package/dist/split/features/devtools.js +1 -1
- package/dist/split/features/devtools.js.map +1 -1
- package/dist/split/features/diagnostics.js +1 -1
- package/dist/split/features/diagnostics.js.map +1 -1
- package/dist/split/features/formats.js +1 -1
- package/dist/split/features/formats.js.map +1 -1
- package/dist/split/features/recursion.js +1 -1
- package/dist/split/features/recursion.js.map +1 -1
- package/dist/split/features/scopes.js +1 -1
- package/dist/split/features/scopes.js.map +1 -1
- package/dist/split/features/ssr.js +1 -1
- package/dist/split/features/ssr.js.map +1 -1
- package/dist/split/features/temporal.js +1 -1
- package/dist/split/features/temporal.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setAll.js","sources":["../../../../../src/command/commandTokenRegistry.ts","../../../../../src/command/commandNamespace.ts","../../../../../src/proxy/assertWritable.ts","../../../../../src/address/ResolvedAddress.ts","../../../../../src/proxy/methods/getContextListIndex.ts","../../../../../src/proxy/methods/isCacheable.ts","../../../../../src/proxy/methods/getByAddress.ts","../../../../../src/proxy/apis/wildcardIndexes.ts","../../../../../src/proxy/methods/getListIndexByIndexes.ts","../../../../../src/list/mergeKeyedList.ts","../../../../../src/proxy/methods/hasByAddress.ts","../../../../../src/proxy/methods/swapInfo.ts","../../../../../src/dependency/walkDependency.ts","../../../../../src/dependency/topologicalRank.ts","../../../../../src/proxy/methods/setByAddress.ts","../../../../../src/proxy/apis/resolve.ts","../../../../../src/proxy/apis/getAll.ts","../../../../../src/proxy/methods/getListIndex.ts","../../../../../src/proxy/apis/setAll.ts"],"sourcesContent":["import { IStateElement } from \"../components/types\";\nimport { CommandToken } from \"./CommandToken\";\nimport { ICommandToken } from \"./types\";\n\nconst registryByStateElement: WeakMap<IStateElement, Map<string, ICommandToken>> = new WeakMap();\n\nexport function getOrCreateCommandToken(stateElement: IStateElement, name: string): ICommandToken {\n let registry = registryByStateElement.get(stateElement);\n if (typeof registry === \"undefined\") {\n registry = new Map<string, ICommandToken>();\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 CommandToken(name, stateElement);\n registry.set(name, token);\n }\n return token;\n}\n\nexport const __private__ = {\n registryByStateElement,\n};\n","/**\n * `state.$command` でアクセスされる command token の namespace proxy を提供する。\n *\n * - state element 単位で memo 化し、同一 stateElement なら同じ proxy が返る。\n * - 宣言された名前 (`$commandTokens` に列挙されたもの) のみ token を返す。\n * 宣言外の名前にアクセスした場合は undefined を返す。\n * (`constructor` / `Symbol.toPrimitive` / `then` など内部システムが触るキーで\n * 例外を投げないため。typo は subsequent な `.emit()` 呼び出しで TypeError として\n * 間接的に表面化する。)\n * - token そのものの memo は `getOrCreateCommandToken` 側に集約されており、\n * namespace proxy は薄いゲートウェイとして振る舞う。\n */\n\nimport { IStateElement } from \"../components/types\";\nimport { raiseError } from \"../raiseError\";\nimport { getOrCreateCommandToken } from \"./commandTokenRegistry\";\nimport { ICommandToken } from \"./types\";\n\nconst namespaceProxyByStateElement: WeakMap<IStateElement, object> = new WeakMap();\n\nexport function getCommandNamespace(stateElement: IStateElement): object {\n const cached = namespaceProxyByStateElement.get(stateElement);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n const proxy = new Proxy(Object.create(null), {\n get(_target: object, prop: PropertyKey): ICommandToken | undefined {\n if (typeof prop !== \"string\") {\n return undefined;\n }\n if (!stateElement.commandTokenNames.has(prop)) {\n return undefined;\n }\n return getOrCreateCommandToken(stateElement, prop);\n },\n has(_target: object, prop: PropertyKey): boolean {\n return typeof prop === \"string\" && stateElement.commandTokenNames.has(prop);\n },\n ownKeys(): string[] {\n return Array.from(stateElement.commandTokenNames);\n },\n getOwnPropertyDescriptor(_target: object, prop: PropertyKey): PropertyDescriptor | undefined {\n if (typeof prop === \"string\" && stateElement.commandTokenNames.has(prop)) {\n return {\n configurable: true,\n enumerable: true,\n value: getOrCreateCommandToken(stateElement, prop),\n };\n }\n return undefined;\n },\n set(): boolean {\n raiseError(`$command namespace is read-only; assigning to it is not allowed.`);\n },\n deleteProperty(): boolean {\n raiseError(`$command namespace is read-only; deleting from it is not allowed.`);\n },\n });\n namespaceProxyByStateElement.set(stateElement, proxy);\n return proxy;\n}\n\nexport function clearCommandNamespace(stateElement: IStateElement): void {\n namespaceProxyByStateElement.delete(stateElement);\n}\n\nexport const __private__ = {\n namespaceProxyByStateElement,\n};\n","import { raiseError } from \"../raiseError\";\nimport type { IStateHandler } from \"./types\";\n\n/**\n * 書き込み API の入口が共通で呼ぶ、書き込み能力の検査(要件 B6)。\n *\n * set トラップ・`$resolve` の書き・`$setAll`(`**` のブロードキャストを含む)の 4 つの入口が、\n * 同じ規則・同じ文言で readonly のプロキシからの書き込みを拒否する。以前は set トラップだけが\n * 検査していて、`$resolve` / `$setAll` は readonly のプロキシからでも書けた。\n *\n * 共通の書き込み境界(`setByAddress`)には置かない: ランタイム自身(`$scan` の畳み込み・\n * `$watch` の連鎖など)が readonly のハンドラのまま内部の書き込みをしており、そこは利用者の\n * 書き込みではないため。\n */\nexport function assertWritable(handler: IStateHandler): void {\n if (handler.mutability === \"readonly\") {\n raiseError(`This state is readonly.`);\n }\n}\n","/**\n * getResolvedPathInfo.ts\n *\n * Utility for parsing and generating detailed path information (IResolvedPathInfo)\n * from State property names (path strings), including wildcard and index information.\n *\n * Main responsibilities:\n * - Breaks down property names to determine presence and type of wildcards and indexes\n * - Automatically determines wildcard type: context/all/partial/none\n * - Caches by path for reusability and performance\n * - Retrieves structured path information via getStructuredPathInfo\n *\n * Design points:\n * - Caches using Map to handle reserved words like \"constructor\" and \"toString\"\n * - Flexibly determines wildcards (*) and numeric indexes, storing them in wildcardIndexes\n * - context type indicates unresolved indexes, all type indicates all resolved indexes, partial type indicates mixed\n * - ResolvedPathInfo class centralizes path parsing and information management\n */\nimport { IResolvedAddress, WildcardType } from './types';\nimport { getPathInfo } from './PathInfo';\n\n/**\n * Cache for resolved path information.\n * Uses Map to safely handle property names including reserved words like \"constructor\" and \"toString\".\n */\nconst _cache: Map<string, IResolvedAddress> = new Map();\n\n/**\n * Class that parses and stores resolved path information.\n * \n * Analyzes property path strings to extract:\n * - Path segments and their hierarchy\n * - Wildcard locations and types\n * - Numeric indexes vs unresolved wildcards\n * - Wildcard type classification (none/context/all/partial)\n */\nclass ResolvedAddress implements IResolvedAddress {\n readonly path;\n readonly segments;\n readonly wildcardCount;\n readonly wildcardType;\n readonly wildcardIndexes;\n readonly pathInfo;\n \n /**\n * Constructs resolved path information from a property path string.\n * \n * Parses the path to identify wildcards (*) and numeric indexes,\n * classifies the wildcard type, and generates structured path information.\n * \n * @param name - Property path string (e.g., \"items.*.name\" or \"data.0.value\")\n */\n constructor(path: string) {\n // Split path into individual segments\n const segments = path.split(\".\");\n const tmpPatternSegments = segments.slice();\n let incompleteCount = 0; // Count of unresolved wildcards (*)\n let completeCount = 0; // Count of resolved wildcards (numeric indexes)\n let wildcardCount = 0;\n let wildcardType: WildcardType = \"none\";\n const wildcardIndexes: (number | null)[] = [];\n\n // Process each segment to identify wildcards and indexes\n for(let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n if (segment === \"*\") {\n // Unresolved wildcard\n tmpPatternSegments[i] = \"*\";\n wildcardIndexes.push(null);\n incompleteCount++;\n wildcardCount++;\n } else {\n const number = Number(segment);\n if (!Number.isNaN(number)) {\n // Numeric index - treat as resolved wildcard\n tmpPatternSegments[i] = \"*\";\n wildcardIndexes.push(number);\n completeCount++;\n wildcardCount++;\n }\n }\n }\n // Generate pattern string with wildcards normalized\n const structuredPath = tmpPatternSegments.join(\".\");\n const pathInfo = getPathInfo(structuredPath);\n \n // Classify wildcard type based on resolved vs unresolved counts\n if (incompleteCount > 0 || completeCount > 0) {\n if (incompleteCount === wildcardCount) {\n // All wildcards are unresolved - need context to resolve\n wildcardType = \"context\";\n } else if (completeCount === wildcardCount) {\n // All wildcards are resolved with numeric indexes\n wildcardType = \"all\";\n } else {\n // Mix of resolved and unresolved wildcards\n wildcardType = \"partial\";\n }\n }\n this.path = path;\n this.segments = segments;\n this.wildcardCount = wildcardCount;\n this.wildcardType = wildcardType;\n this.wildcardIndexes = wildcardIndexes;\n this.pathInfo = pathInfo;\n }\n}\n\n/**\n * Retrieves or creates resolved path information for a property path.\n * \n * This function caches resolved path information for performance.\n * On first access, it parses the path and creates a ResolvedPathInfo instance.\n * Subsequent accesses return the cached result.\n * \n * @param name - Property path string (e.g., \"items.*.name\", \"data.0.value\")\n * @returns Resolved path information containing segments, wildcards, and type classification\n */\nexport function getResolvedAddress(name:string):IResolvedAddress {\n let nameInfo: IResolvedAddress | undefined;\n // Return cached value or create, cache, and return new instance\n return _cache.get(name) ?? (_cache.set(name, nameInfo = new ResolvedAddress(name)), nameInfo);\n}","/**\n * getContextListIndex.ts\n *\n * Stateの内部APIとして、現在のプロパティ参照スコープにおける\n * 指定したstructuredPath(ワイルドカード付きプロパティパス)に対応する\n * リストインデックス(IListIndex)を取得する関数です。\n *\n * 主な役割:\n * - handlerの最後にアクセスされたAddressから、指定パスに対応するリストインデックスを取得\n * - ワイルドカード階層に対応し、多重ループやネストした配列バインディングにも利用可能\n *\n * 設計ポイント:\n * - 直近のプロパティ参照情報を取得\n * - info.indexByWildcardPathからstructuredPathのインデックスを特定\n * - listIndex.at(index)で該当階層のリストインデックスを取得\n * - パスが一致しない場合や参照が存在しない場合はnullを返す\n */\n\nimport { IListIndex } from \"../../list/types\";\nimport { listIndexAtWildcard } from \"../../list/wildcardLevel\";\nimport { IStateHandler } from \"../types\";\n\nexport function getContextListIndex(\n handler: IStateHandler,\n structuredPath: string\n): IListIndex | null {\n if (handler.addressStackLength === 0) {\n return null;\n }\n const address = handler.lastAddressStack;\n if (address === null) {\n return null;\n }\n const index: number | undefined = address.pathInfo.indexByWildcardPath[structuredPath];\n if (typeof index === \"undefined\") {\n return null;\n }\n if (address.listIndex === null) {\n return null;\n }\n return listIndexAtWildcard(address.listIndex, index, address.pathInfo.wildcardCount);\n}\n","import { IStateAddress } from \"../../address/types\";\nimport { IStateElement } from \"../../components/types\";\n\n/**\n * このアドレスの値をキャッシュしてよいか(getByAddress / setByAddress 共通の判定)。\n *\n * ワイルドカードを含むパス(リスト行)と宣言済み getter は再評価が高くつくため\n * キャッシュする。ただし mapped な `bind-component` の state は例外で、丸ごと外す。\n *\n * mapped な state は値を持たず、読みも書きも親スコープの state へ解決される\n * (innerState proxy)。同じ値は親側のキャッシュにも載り、その無効化は親の依存 walk が\n * 担う。子側にもう一段キャッシュを置くと、正本でない複製を親の無効化が届かない場所に\n * 作ることになり、親起点の書き込みのあと子だけが旧値を読み続ける。二重に持たないのが\n * 唯一の整合手段なので、mapped な state 要素ではキャッシュ層を持たない — 親の\n * キャッシュがそのまま効くので、失うのは重複していた一段だけ\n * (docs/architecture-hardening/15-state-component-mechanism-consistency.md §1.8)。\n */\nexport function isCacheable(stateElement: IStateElement, address: IStateAddress): boolean {\n\n // マーカーで終わるパス(`users.*.#m1` — オーバーレイ値)はキャッシュしない。\n // オーバーレイ値 proxy は評価中の receiver / handler を閉じ込めるため、drain を\n // 跨いで使い回せない(webComponent/overlay.ts)。マーカーの**下**のパス\n // (私有キー・getter の値)は通常どおりキャッシュされ、依存 walk が無効化する。\n if (stateElement.hasMounts === true && address.pathInfo.lastSegment.charCodeAt(0) === 35 /* '#' */) {\n return false;\n }\n return address.pathInfo.wildcardCount > 0 ||\n stateElement.getterPaths.has(address.pathInfo.path);\n}\n","/**\n * getByAddress.ts\n *\n * StateClassの内部APIとして、構造化パス情報(IStructuredPathInfo)とリストインデックス(IListIndex)を指定して\n * 状態オブジェクト(target)から値を取得するための関数(getByAddress)の実装です。\n *\n * 主な役割:\n * - 指定されたパス・インデックスに対応するState値を取得(多重ループやワイルドカードにも対応)\n * - 依存関係の自動登録(checkDependencyで登録)\n * - キャッシュ機構(リストもキャッシュ対象)\n * - getter経由で値取得時はpushAddressでスコープを一時設定\n * - 存在しない場合は親pathAddressやlistIndexを辿って再帰的に値を取得\n *\n * 設計ポイント:\n * - checkDependencyで依存追跡を実行 \n * - キャッシュ有効時はstateAddressで値をキャッシュし、取得・再利用を最適化\n * - ワイルドカードや多重ループにも柔軟に対応し、再帰的な値取得を実現\n * - finallyでキャッシュへの格納を保証\n */\n\nimport { liftAddress } from \"../../address/liftAddress\";\nimport { IStateAddress } from \"../../address/types\";\nimport { getCacheEntryByAbsoluteStateAddress, setCacheEntryByAbsoluteStateAddress } from \"../../cache/cacheEntryByAbsoluteStateAddress\";\nimport { getCommandNamespace } from \"../../command/commandNamespace\";\nimport { IStateElement } from \"../../components/types\";\nimport { STATE_COMMAND_NAMESPACE_NAME, WILDCARD } from \"../../define\";\nimport { missingRootPathMessage, wildcardScopeMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { NOT_HANDLED } from \"../../core/addressHooks\";\nimport { IStateHandler } from \"../types\";\nimport { checkDependency } from \"./checkDependency\";\nimport { isCacheable } from \"./isCacheable\";\n\n/**\n * namespace 配下のパスは raw state を持たないため、proxy の get トラップと同じ\n * namespace オブジェクトを辿る。1セグメント目は namespace 本体、2セグメント目以降は\n * namespace 上のキーを順に走査する。走査値が object / function 以外(null /\n * undefined / primitive の葉)になったら undefined を返す — 葉より深い読み\n * (例: `$streamStatus.<name>.<key>`、error が primitive throw のときの\n * `$streamError.<name>.message`)は宣言外アクセスと同じ undefined 解決とし、\n * Reflect.get の non-object TypeError を updater の drain に漏らさない\n * (§4-1 の throw しない寛容規約)。\n */\nfunction walkNamespace(namespace: object, segments: string[]): any {\n let value: any = namespace;\n for (let i = 1; i < segments.length; i++) {\n // Object(v) !== v は「v が object / function でない」(= primitive / null / undefined)判定\n if (Object(value) !== value) {\n return undefined;\n }\n value = Reflect.get(value, segments[i]);\n }\n return value;\n}\n\n// 「ツリーに意見が無い」読み(親が無い・親にそのキーが無い)を機能に聞く(設計案 H1 の readMissing)。\n// 親が無ければ parentValue は null。hook の無い state は判定 1 個で抜ける\nfunction readMissing(\n stateElement: IStateElement,\n address: IStateAddress,\n parentValue: object | null,\n receiver: any,\n handler: IStateHandler,\n): unknown {\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const missing = hooks.readMissing;\n for (let i = 0; i < missing.length; i++) {\n const handled = missing[i](stateElement, address, parentValue, receiver, handler);\n if (handled !== NOT_HANDLED) return handled;\n }\n }\n return NOT_HANDLED;\n}\n\nfunction _getByAddress(\n target : object,\n address : IStateAddress,\n receiver : any,\n handler : IStateHandler,\n stateElement: IStateElement,\n): any {\n const firstSegment = address.pathInfo.segments[0];\n if (firstSegment === STATE_COMMAND_NAMESPACE_NAME) {\n // $command 名前空間: キーは宣言済み command token 名\n return walkNamespace(getCommandNamespace(stateElement), address.pathInfo.segments);\n }\n // $streamStatus / $streamError(stream/addressHooks.ts)とマーカーで終わるパスのオーバーレイ\n // (webComponent/addressHooks.ts)は getByAddress の read hook が先に答える(宣言・マウントのある state だけに付く)\n if (address.pathInfo.path in target) {\n // getterの中で参照の可能性があるので、addressをプッシュする\n if (stateElement.getterPaths.has(address.pathInfo.path)) {\n handler.pushAddress(address);\n try {\n return Reflect.get(target, address.pathInfo.path, receiver);\n } finally {\n handler.popAddress();\n }\n\n } else {\n return Reflect.get(target, address.pathInfo.path);\n }\n } else {\n // 親アドレスが無い = 単一セグメントのパスが state に存在しない。ここは元から\n // throw していたが、文面が内部実装の言葉だったので打ち間違いだと分からなかった。\n // 深いパスの console.warn(pathDiagnostics.checkDeclaredPath)と語彙を揃える。\n // 親が無い(= ルート欠落): ツリーに意見が無いので readMissing hook(予約済みボリューム\n // スロットの配下なら undefined — D22)に先に聞き、無ければ raise する\n if (address.parentAddress === null) {\n const missing = readMissing(stateElement, address, null, receiver, handler);\n if (missing !== NOT_HANDLED) {\n return missing;\n }\n raiseError(missingRootPathMessage(address.pathInfo.path, target, stateElement.getterPaths));\n }\n const parentAddress = address.parentAddress;\n const parentValue = getByAddress(target, parentAddress, receiver, handler);\n // 親が居ないパスの読みは undefined(=「state に意見が無い」)。`Reflect.get` に\n // そのまま渡すと生の `TypeError: Reflect.get called on non-object` になり、\n // updater の drain も行ループも捕まえないので **1 本の stale な読みが同じバッチの\n // 無関係な更新まで道連れにする**(§1.7 / §1.9 と同じ構図)。\n //\n // 実際に踏むのは「消えた行を指すバインディングが、その行を消す `for` より先に\n // 適用される」形。同一スコープならトポロジカル順で `for` が先に来るので起きないが、\n // bind-component は親スコープの通知と子スコープの `for` が別経路で流れるため\n // 順序が保証されない(docs/state-bind-component-nested-for-design.md)。\n // undefined はプロパティ書き込みがスキップされる値なので DOM は触られず、\n // 直後に `for` が行ごと外して整合する。\n if (parentValue === null || typeof parentValue === \"undefined\") {\n return undefined;\n }\n const lastSegment = address.pathInfo.segments[address.pathInfo.segments.length - 1];\n // 「ツリーの未存在キー」の分岐だけ readMissing hook(公開 getter の dispatch など)に聞く\n // (X1 — 命中する読みは無改造)。hook の無い state は判定 1 個で抜ける\n const hooks = stateElement.addressHooks;\n if (hooks && hooks.readMissing.length !== 0 && lastSegment !== WILDCARD\n && !(lastSegment in Object(parentValue))) {\n const missing = readMissing(stateElement, address, Object(parentValue), receiver, handler);\n if (missing !== NOT_HANDLED) {\n return missing;\n }\n }\n if (lastSegment === WILDCARD) {\n // listIndex が無いまま末尾ワイルドカードに到達 = そのパスの階数を満たす\n // ループ文脈が無い(`matrix.*.*` を 1 段の `for` の中で読む等)。元の文面は\n // 内部の言葉(address.listIndex?.index is undefined)で、何段必要なのかが\n // 書かれていなかった(pathDiagnostics.ts)。\n const index = address.listIndex?.index ?? raiseError(\n wildcardScopeMessage(\n `path \"${address.pathInfo.path}\"`,\n address.pathInfo.wildcardCount,\n address.listIndex?.length ?? 0,\n ),\n );\n return Reflect.get(parentValue, index);\n } else {\n return Reflect.get(parentValue, lastSegment);\n }\n }\n}\n\nfunction _getByAddressWithCache(\n target : object, \n address : IStateAddress,\n receiver : any,\n handler : IStateHandler,\n stateElement: IStateElement\n): any {\n const absAddress = liftAddress(stateElement, address);\n const cacheEntry = getCacheEntryByAbsoluteStateAddress(absAddress);\n // 世代印(issue #258 の X10)。絶対アドレスは再セットを跨いで同一なので、dirty だけでは\n // 旧世代の値と新世代の値を見分けられない。世代の違う項目は単に miss として再評価し、\n // 下で新しい印を付けて上書きする(列挙も掃き出しも要らず、どのアドレス形状でも自己修復する)。\n const generation = stateElement.stateGeneration;\n if (cacheEntry !== null && cacheEntry.dirty === false && cacheEntry.generation === generation) {\n return cacheEntry.value;\n }\n const value = _getByAddress(target, address, receiver, handler, stateElement);\n setCacheEntryByAbsoluteStateAddress(absAddress, {\n value: value,\n dirty: false,\n generation: generation\n });\n return value;\n}\n\nexport function getByAddress(\n target : object,\n address : IStateAddress,\n receiver : any,\n handler : IStateHandler\n): any {\n // 再帰 getter の遅延実体化(Phase B)。**キャッシュ参照より前**でなければならない。\n // 未定義のまま一度読まれると isCacheable が wildcardCount > 0 だけでキャッシュ可を\n // 返すので undefined が dirty:false で固定され、後からアクセサを生やしても恒久的に\n // 直らない(Phase A の A7)。宣言の無い state は boolean 判定 1 個で抜け、宣言のある\n // state も 2 回目からは PathInfo キーの記憶 1 回で抜ける(書き側と対称・第 5 サイクル)。\n checkDependency(handler, address);\n if (handler.stateElement.hasRecursion === true) {\n handler.stateElement.recursionRegistry!.materializeForPathInfo(handler.stateElement, address.pathInfo);\n }\n const stateElement = handler.stateElement;\n // 読み書き境界の hook(設計案 H1): 宣言が要求した機能の分だけ state に付いている。無ければ判定 1 回\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const readHooks = hooks.read;\n for (let i = 0; i < readHooks.length; i++) {\n const handled = readHooks[i](stateElement, address, receiver, handler);\n if (handled !== NOT_HANDLED) return handled;\n }\n }\n const cacheable = isCacheable(stateElement, address);\n if (cacheable) {\n return _getByAddressWithCache(target, address, receiver, handler, stateElement);\n } else {\n return _getByAddress(target, address, receiver, handler, stateElement);\n }\n}\n","/**\n * wildcardIndexes.ts\n *\n * ワイルドカードを含むパスから「解決済み添字タプルの集合」を列挙する共有走査。\n * `$getAll`(読み)と `$setAll`(書き)が**同じ展開規則・同じ順序**で動くための単一の正本\n * (docs/state-set-all-design.md §6-1)。\n *\n * 添字は**前方一致の接頭辞**で、足りない分は「その階層を全部展開する」という意味を持つ\n * (README の `$getAll(\"scores.*\", [])` がこれ)。返るタプルは常にワイルドカードの本数と\n * 同じ長さになるので、そのまま `$resolve` の厳密一致な添字として使える。\n *\n * 順序は**深さ優先・添字昇順**(ネストは添字タプルの辞書順)で決定的。\n * `$getAll(p, i)` の戻り順と `$setAll(p, i, …)` の適用順が一致する根拠がこれであり、\n * `$setAll` の `{ spread: true }` 形はこの順序に乗っている。\n *\n * Throws: LIST-201(インデックス未解決)、BIND-201(ワイルドカード情報不整合)\n */\n\nimport { liftAddress } from \"../../address/liftAddress\";\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { IAbsoluteStateAddress, IPathInfo } from \"../../address/types\";\nimport { getStateListBaseline, setStateListBaseline } from \"../../list/stateListBaseline\";\nimport { createListDiff } from \"../../list/createListDiff\";\nimport { IListIndex } from \"../../list/types\";\nimport { raiseError } from \"../../raiseError\";\nimport { getByAddress } from \"../methods/getByAddress\";\nimport { IStateHandler } from \"../types\";\n\n/**\n * 各ワイルドカード階層で最後に観測したリスト値は、state 側の共有基準\n * ([stateListBaseline](../../list/stateListBaseline.ts))に置く。ListIndex の同一性を\n * 跨いで保つための差分基準であり、読み・描画・依存ウォークが同じ「前回見た形」を見る\n * ことでリスト置換のたびに ListIndex を鋳造し直す事故を防ぐ。\n *\n * 書き(`$setAll`)はこの走査を借りるだけで記録を更新しない\n * (`commitDiffBaseline: false`。設計 §6-2)。\n */\n\nexport interface ICollectWildcardIndexesOptions {\n /**\n * 走査で観測したリスト値を差分基準として記録するか。\n * 読み(`$getAll`)だけが `true`。書き(`$setAll`)は読みの基準を動かさない。\n */\n readonly commitDiffBaseline: boolean;\n}\n\n/**\n * `pathInfo` のワイルドカードを `indexes`(前方一致の接頭辞)で絞り込みつつ展開し、\n * マッチする添字タプルを列挙する。\n *\n * 添字の本数検査(上限)は呼び出し側の責務 — API 名を診断メッセージに出すため。\n */\nexport function collectWildcardIndexes(\n target : object,\n receiver: any,\n handler : IStateHandler,\n pathInfo: IPathInfo,\n indexes : number[],\n options : ICollectWildcardIndexesOptions,\n): number[][] {\n const newValueByAddress: Map<IAbsoluteStateAddress, any> = new Map();\n\n const walkWildcardPattern = (\n wildcardParentPathInfos: IPathInfo[],\n wildcardIndexPos: number,\n listIndex: IListIndex | null,\n indexes: number[],\n indexPos: number,\n parentIndexes: number[],\n results: number[][]\n ) => {\n const wildcardParentPathInfo = wildcardParentPathInfos[wildcardIndexPos] ?? null;\n if (wildcardParentPathInfo === null) {\n results.push(parentIndexes);\n return;\n }\n const wildcardAddress = createStateAddress(wildcardParentPathInfo, listIndex);\n const wildcardAbsAddress = liftAddress(handler.stateElement, wildcardAddress);\n const oldValue = getStateListBaseline(wildcardAbsAddress);\n const newValue = getByAddress(target, wildcardAddress, receiver, handler);\n const listDiff = createListDiff(\n listIndex, oldValue, newValue);\n const listIndexes = listDiff.newIndexes;\n const index = indexes[indexPos] ?? null;\n newValueByAddress.set(wildcardAbsAddress, newValue);\n if (index === null) {\n for(let i = 0; i < listIndexes.length; i++) {\n const listIndex = listIndexes[i];\n walkWildcardPattern(\n wildcardParentPathInfos,\n wildcardIndexPos + 1,\n listIndex,\n indexes,\n indexPos + 1,\n parentIndexes.concat(listIndex.index),\n results);\n }\n } else {\n // 範囲外 index はリスト自体の不在と別原因なので index を含める\n // (docs/state-bind-component-nested-for-design.md §8.4)\n const listIndex = listIndexes[index] ??\n raiseError(`ListIndex not found at index ${index} of ${wildcardParentPathInfo.path}`);\n if ((wildcardIndexPos + 1) < wildcardParentPathInfos.length) {\n walkWildcardPattern(\n wildcardParentPathInfos,\n wildcardIndexPos + 1,\n listIndex,\n indexes,\n indexPos + 1,\n parentIndexes.concat(listIndex.index),\n results\n );\n } else {\n // 最終ワイルドカード層まで到達しているので、結果を確定\n results.push(parentIndexes.concat(listIndex.index));\n }\n }\n }\n\n const resultIndexes: number[][] = [];\n walkWildcardPattern(\n pathInfo.wildcardParentPathInfos,\n 0,\n null,\n indexes,\n 0,\n [],\n resultIndexes\n );\n if (options.commitDiffBaseline) {\n for(const [address, newValue] of newValueByAddress.entries()) {\n setStateListBaseline(address, Array.isArray(newValue) ? newValue : []);\n }\n }\n return resultIndexes;\n}\n","/**\n * getListIndexByIndexes.ts\n *\n * 解決済みの添字タプル(ワイルドカード 1 段につき 1 個)から、対応する ListIndex を\n * **正本レジストリ**(listIndexesByList)経由で引き当てる。\n *\n * `$resolve` と `$setAll` の共有部分。列挙側(wildcardIndexes.ts)が走査中に生成した\n * ListIndex をそのまま書き込み先にせず、ここで引き直すことで、binding が使っている\n * ListIndex と同一の同一性に載る(docs/state-set-all-design.md §6-2)。\n *\n * 添字の本数がワイルドカードの本数と一致していることは呼び出し側の責務。\n */\n\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { IPathInfo } from \"../../address/types\";\nimport { resolveListIndexesByList } from \"../../list/listIndexesByList\";\nimport { IListIndex } from \"../../list/types\";\nimport { raiseError } from \"../../raiseError\";\nimport { IStateHandler } from \"../types\";\nimport { getByAddress } from \"./getByAddress\";\n\nexport function getListIndexByIndexes(\n target : object,\n receiver: any,\n handler : IStateHandler,\n pathInfo: IPathInfo,\n indexes : number[],\n): IListIndex | null {\n // ワイルドカード階層ごとにListIndexを解決していく\n let listIndex: IListIndex | null = null;\n for(let i = 0; i < pathInfo.wildcardParentPathInfos.length; i++) {\n const wildcardParentPathInfo = pathInfo.wildcardParentPathInfos[i];\n const wildcardAddress = createStateAddress(wildcardParentPathInfo, listIndex);\n const tmpValue = getByAddress(target, wildcardAddress, receiver, handler);\n const listIndexes = resolveListIndexesByList(tmpValue, listIndex);\n if (listIndexes == null) {\n raiseError(`ListIndexes not found: ${wildcardParentPathInfo.path}`);\n }\n const index = indexes[i];\n // 範囲外 index はリスト自体の不在と別原因なので index を含める\n // (docs/state-bind-component-nested-for-design.md §8.4)\n listIndex = listIndexes[index] ??\n raiseError(`ListIndex not found at index ${index} of ${wildcardParentPathInfo.path}`);\n }\n return listIndex;\n}\n","/**\n * list/mergeKeyedList.ts\n *\n * `$listKeys` 宣言済みリストパスへの配列代入で、キーが一致する行の\n * 「オブジェクト強制・値展開」を行う(docs/state-list-key-design.md §2)。\n *\n * - キー突合し、一致行は**旧オブジェクトを据え置いた**ハイブリッド配列を作る\n * → 配列要素の参照が変わらないので for は行を再利用する(DOM・フォーカス・\n * 非バインド DOM 状態が保存される)\n * - 一致行の「変化したフィールド」だけを列挙して返す\n * → 呼び出し側が per-path 書き込みとして発行する(§7.0 の穴を塞ぐ正典イディオム)\n *\n * このモジュールは純粋な計算のみで、state への書き込みは行わない。\n */\n\nimport { STATE_LIST_KEYS_NAME } from \"../define\";\nimport { raiseError } from \"../raiseError\";\nimport type { ListKeySpec } from \"./listKeys\";\n\ntype Row = Record<string, unknown>;\n\n/** キーが一致し、旧オブジェクトへ値展開すべき行 */\nexport interface IKeyedRowMatch {\n /** ハイブリッド配列上の位置(= 新配列上の位置) */\n readonly position: number;\n /** 据え置かれる旧行オブジェクト(書き込み先) */\n readonly oldRow: Row;\n /** 値の供給元となる新行オブジェクト(格納はされない) */\n readonly newRow: Row;\n}\n\nexport interface IKeyedListMerge {\n /** 実際に格納すべきハイブリッド配列(一致行は旧オブジェクト) */\n readonly list: unknown[];\n /** 値展開が必要な一致行。空にはならない(空なら mergeKeyedList が null を返す) */\n readonly matched: readonly IKeyedRowMatch[];\n}\n\nexport interface IFieldWrite {\n readonly field: string;\n readonly value: unknown;\n}\n\n/**\n * 値展開は own enumerable データプロパティのコピーなので、プロトタイプや\n * アクセサを持つオブジェクトでは意味論が保てない。plain object 以外は即エラー(§5)。\n */\nfunction assertPlainRow(row: unknown, path: string, side: string, position: number): asserts row is Row {\n if (typeof row !== \"object\" || row === null) {\n raiseError(\n `${STATE_LIST_KEYS_NAME} list \"${path}\": ${side} row at index ${position} must be a plain object ` +\n `(got ${row === null ? \"null\" : typeof row}).`\n );\n }\n const proto = Object.getPrototypeOf(row);\n if (proto !== Object.prototype && proto !== null) {\n raiseError(\n `${STATE_LIST_KEYS_NAME} list \"${path}\": ${side} row at index ${position} must be a plain object ` +\n `(class instances and exotic objects cannot be value-expanded).`\n );\n }\n}\n\nfunction keyOf(row: Row, spec: ListKeySpec, path: string, side: string, position: number): unknown {\n const key = typeof spec === \"function\" ? spec(row) : row[spec];\n if (key === undefined || key === null) {\n raiseError(\n `${STATE_LIST_KEYS_NAME} list \"${path}\": ${side} row at index ${position} has no key ` +\n `(${typeof spec === \"function\" ? \"key function\" : `field \"${spec}\"`} returned ${String(key)}).`\n );\n }\n return key;\n}\n\n/** 行を検証しつつキーを抽出する。キー重複は即エラー(§5)。 */\nfunction extractKeys(list: readonly unknown[], spec: ListKeySpec, path: string, side: string): unknown[] {\n const keys: unknown[] = new Array(list.length);\n const seen = new Set<unknown>();\n for (let i = 0; i < list.length; i++) {\n const row = list[i];\n assertPlainRow(row, path, side, i);\n const key = keyOf(row, spec, path, side, i);\n if (seen.has(key)) {\n raiseError(`${STATE_LIST_KEYS_NAME} list \"${path}\": duplicate key ${JSON.stringify(key)} in ${side} list.`);\n }\n seen.add(key);\n keys[i] = key;\n }\n return keys;\n}\n\n/**\n * キー突合してハイブリッド配列を組む。値展開すべき一致行が 1 つも無ければ null\n * (呼び出し側は従来どおりの書き込みへ倒す)。\n *\n * 突合対象の旧配列は「最後に適用された配列」ではなく**現在格納されている配列**。\n * ハイブリッド構築が格納配列の参照を保存するため、同一マイクロタスク内の連続\n * 書き込みでも適用時の diff と transitive に整合する(§6)。\n */\nexport function mergeKeyedList(\n path: string,\n spec: ListKeySpec,\n oldValue: unknown,\n newList: readonly unknown[],\n): IKeyedListMerge | null {\n // 宣言済みパスなら初回代入(旧配列なし)でも新配列を検証する。\n // 「2 回目の代入で初めて重複キーが露見する」という不連続を避けるため。\n const newKeys = extractKeys(newList, spec, path, \"new\");\n if (!Array.isArray(oldValue) || oldValue.length === 0 || newList.length === 0) {\n return null;\n }\n const oldList: readonly unknown[] = oldValue;\n const oldKeys = extractKeys(oldList, spec, path, \"current\");\n const oldRowByKey = new Map<unknown, Row>();\n for (let i = 0; i < oldList.length; i++) {\n oldRowByKey.set(oldKeys[i], oldList[i] as Row);\n }\n\n const list: unknown[] = new Array(newList.length);\n const matched: IKeyedRowMatch[] = [];\n for (let i = 0; i < newList.length; i++) {\n const newRow = newList[i] as Row;\n const oldRow = oldRowByKey.get(newKeys[i]);\n if (typeof oldRow === \"undefined\" || oldRow === newRow) {\n // 追加行、または既に同一オブジェクト(生配列 in-place 変異 + コピー再代入の\n // イディオム)。後者は従来どおり walkDependency の全行フォールバックが担う。\n list[i] = newRow;\n continue;\n }\n list[i] = oldRow;\n matched.push({ position: i, oldRow, newRow });\n }\n return matched.length > 0 ? { list, matched } : null;\n}\n\n/**\n * 一致行について per-path 書き込みすべきフィールドを列挙する。\n *\n * - 変化したフィールドのみ(同値は書かない。無変化リフレッシュを完全なゼロコストに\n * するため — 全フィールド無条件書き込みだと §2.2 の利得が消える)\n * - 新行から消えた旧フィールドは **null** を書く(undefined ではない)\n *\n * 同値判定は Object.is。setByAddress の same-value guard と同じ基準にすることで、\n * 「発行したが guard に落とされる」無駄な書き込みを作らない。\n *\n * 消えたフィールドに null を使うのは、この処理系では undefined が\n * 「状態が値を持たない=無意見」であり applyChangeToProperty が書き込みごと\n * スキップするため(明示的なクリアの語彙は null)。undefined を書くと state 側は\n * 更新されるのに DOM だけ旧値のまま残り、まさに本機能が塞ごうとしている\n * stale を再導入してしまう。既に null / undefined のフィールドは DOM 上も\n * 空なので、クリア書き込み自体を発行しない。\n */\nexport function collectFieldWrites(oldRow: Row, newRow: Row): IFieldWrite[] {\n const writes: IFieldWrite[] = [];\n for (const field of Object.keys(newRow)) {\n if (!Object.is(oldRow[field], newRow[field])) {\n writes.push({ field, value: newRow[field] });\n }\n }\n for (const field of Object.keys(oldRow)) {\n if (!Object.hasOwn(newRow, field) && oldRow[field] != null) {\n writes.push({ field, value: null });\n }\n }\n return writes;\n}\n","import { IStateAddress } from \"../../address/types\";\nimport { WILDCARD } from \"../../define\";\nimport { IStateHandler } from \"../types\";\nimport { getByAddress } from \"./getByAddress\";\n\n/**\n * Reports whether an address has been initialized, independently of its value.\n * In particular, an own slot containing `undefined` is initialized while a\n * missing slot is not.\n */\nexport function hasByAddress(\n target: object,\n address: IStateAddress,\n receiver: unknown,\n handler: IStateHandler,\n): boolean {\n if (address.pathInfo.path in target) return true;\n const parentAddress = address.parentAddress;\n if (parentAddress === null) return false;\n const parentValue = getByAddress(target, parentAddress, receiver, handler);\n if (parentValue === null || (typeof parentValue !== \"object\" && typeof parentValue !== \"function\")) {\n return false;\n }\n const lastSegment = address.pathInfo.lastSegment;\n if (lastSegment === WILDCARD) {\n const index = address.listIndex?.index;\n return typeof index === \"number\" && index in parentValue;\n }\n return lastSegment in parentValue;\n}\n","import { ISwapInfo } from \"./types\";\n\n/**\n * 要素書き込みで入れ替え中のリストの「書き込む前の並び」。キーはリストの配列そのもの —\n * 台帳(listIndexesByList)と同じ単位にそろえる。アドレスはパスと listIndex でキャッシュされ\n * `<wcs-state>` を区別しないので、アドレスをキーにすると、別の state 要素や置き換え前の配列で\n * 揃わなかった入れ替えの記録を拾ってしまう。\n */\nconst swapInfoByList: WeakMap<object, ISwapInfo> = new WeakMap();\n\nexport function getSwapInfoByList(list: object): ISwapInfo | null {\n return swapInfoByList.get(list) ?? null;\n}\n\nexport function setSwapInfoByList(list: object, swapInfo: ISwapInfo | null): void {\n if (swapInfo === null) {\n swapInfoByList.delete(list);\n } else {\n swapInfoByList.set(list, swapInfo);\n }\n}\n","import { liftAddress } from \"../address/liftAddress\";\nimport { calcWildcardLen } from \"../address/calcWildcardLen\";\nimport { getPathInfo } from \"../address/PathInfo\";\nimport { createStateAddress } from \"../address/StateAddress\";\nimport { IAbsoluteStateAddress, IPathInfo, IStateAddress } from \"../address/types\";\nimport { IStateElement } from \"../components/types\";\nimport { config } from \"../config\";\nimport { DELIMITER, WILDCARD } from \"../define\";\nimport { createListDiff } from \"../list/createListDiff\";\nimport { getStateListBaseline, setStateListBaseline } from \"../list/stateListBaseline\";\nimport { IListDiff, IListIndex } from \"../list/types\";\nimport { listIndexAtWildcard } from \"../list/wildcardLevel\";\nimport { getByAddressSymbol } from \"../proxy/symbols\";\nimport { IStateProxy } from \"../proxy/types\";\nimport { raiseError } from \"../raiseError\";\nimport { takePendingKeyedWalk } from \"./keyedDependency\";\nimport { getTopologicalRanks } from \"./topologicalRank\";\nimport { SearchType } from \"./types\";\n\nconst MAX_DEPENDENCY_DEPTH = 1000;\n\nfunction getIndexes(listDiff: IListDiff, searchType: SearchType): Iterable<IListIndex> {\n switch (searchType) {\n case \"old\":\n return listDiff.oldIndexes;\n case \"new\":\n return listDiff.newIndexes;\n case \"add\":\n return listDiff.addIndexSet;\n case \"change\":\n return listDiff.changeIndexSet;\n case \"delete\":\n return listDiff.deleteIndexSet;\n default: \n if (config.debug) {\n console.log(`Invalid search type: ${searchType}`);\n }\n return [];\n }\n}\n\ntype ExpandContext = {\n readonly stateElement: IStateElement,\n /** ウォーク中に観測したリスト値。ウォーク完了後にまとめて基準へ確定する(E1)。 */\n readonly observedListValueByAbsAddress: Map<IAbsoluteStateAddress, readonly unknown[]>,\n readonly targetPathInfo: IPathInfo,\n readonly targetListIndexes: IListIndex[],\n readonly wildcardPaths: string[],\n readonly wildcardParentPaths: string[],\n readonly stateProxy: IStateProxy,\n readonly searchType: SearchType\n}\n\nfunction _walkExpandWildcard(\n context: ExpandContext, \n currentWildcardIndex: number,\n parentListIndex: IListIndex | null\n): void {\n const parentPath = context.wildcardParentPaths[currentWildcardIndex];\n const parentPathInfo = getPathInfo(parentPath);\n const parentAddress = createStateAddress(parentPathInfo, parentListIndex);\n const parentAbsAddress = liftAddress(context.stateElement, parentAddress);\n const lastValue = getStateListBaseline(parentAbsAddress);\n const newValue = context.stateProxy[getByAddressSymbol](parentAddress);\n const listDiff = createListDiff(\n parentAddress.listIndex, lastValue, newValue);\n context.observedListValueByAbsAddress.set(parentAbsAddress, Array.isArray(newValue) ? newValue : []);\n\n const loopIndexes = getIndexes(listDiff, context.searchType);\n if (currentWildcardIndex === context.wildcardPaths.length - 1) {\n context.targetListIndexes.push(...loopIndexes);\n } else {\n for(const listIndex of loopIndexes) {\n _walkExpandWildcard(\n context,\n currentWildcardIndex + 1,\n listIndex\n );\n }\n }\n}\n\n/**\n * 静的子展開(list → list.*)の展開範囲。\n * - \"full\": 新リストの全行を展開する(従来挙動)。\n * - \"diff\": 追加行(addIndexSet)と位置が変わった行(changeIndexSet)のみ展開する。\n * 未変更行は値が変わらないため dirty 化・再適用が不要(リスト置換のコストが\n * 既存行数に比例するスケーリング欠陥の解消。docs/list-replacement-dependency-scaling.md)。\n * 削除時の集計 getter は $getAll / $resolve がリスト本体(コンテナ)を読むことで\n * 登録される動的エッジ(list → 集計 getter)が担う。\n */\nexport type ListExpansion = \"full\" | \"diff\";\n\ntype Context = {\n readonly stateElement: IStateElement,\n /** ウォーク中に観測したリスト値。ウォーク完了後にまとめて基準へ確定する(E1)。 */\n readonly observedListValueByAbsAddress: Map<IAbsoluteStateAddress, readonly unknown[]>,\n readonly staticMap: Map<string, string[]>,\n readonly dynamicMap: Map<string, string[]>,\n readonly result: Set<IStateAddress>,\n readonly listPathSet: Set<string>,\n readonly visited: Set<IStateAddress>,\n readonly stateProxy: IStateProxy,\n readonly searchType: SearchType,\n readonly listExpansion: ListExpansion,\n /**\n * この書き込みでキー突合による値展開が成立したリストパス($listKeys)。\n * 変化フィールドは per-path 書き込みで個別に dirty 化済みなので、\n * 「diff に変化が見えない再代入」の全行フォールバックを適用しない\n * (docs/state-list-key-design.md §2.2)。\n */\n readonly keyedMergePath: string | null,\n /** パス → トポロジカル順位。訪問順の決定に使う(topologicalRank.ts 参照) */\n readonly ranks: ReadonlyMap<string, number>,\n}\n\n/**\n * 静的子展開の対象 listIndex 群。fullRows は行全体(list.* とその subtree)を展開する。\n * movedRows は「位置だけが変わった行」で、index 以外の入力が不変なため展開を\n * index 依存 getter の subtree(getMovedRowExpansionPaths)に限定できる。\n */\ntype ExpansionSelection = {\n readonly fullRows: Iterable<IListIndex>,\n readonly movedRows: Iterable<IListIndex> | null,\n}\n\nconst EMPTY_INDEXES: IListIndex[] = [];\n\n/**\n * 静的子展開で訪問する listIndex 群を選ぶ。\"diff\" でも次の場合は全行に倒す:\n * - diff に変化が一切見えない再代入(同一参照および内容同一コピーの再代入。\n * `arr[0].v = 5; s.items = [...arr]` のような in-place 変異後のリフレッシュ\n * イディオムは diff に映らないため、全行展開で従来挙動を保つ。\n * 削除だけの置換は除く — 残存行に変化は無く、集計はコンテナ動的エッジが担う)\n * - 他行を読む getter が検出されたリスト(隣接項目参照など。未変更行の派生値も変わりうる)\n */\nfunction selectExpansionIndexes(\n context: Context,\n sourcePath: string,\n _lastValue: unknown,\n _newValue: unknown,\n listDiff: IListDiff,\n): ExpansionSelection {\n if (context.listExpansion === \"full\") {\n return { fullRows: listDiff.newIndexes, movedRows: null };\n }\n if (context.stateElement.crossRowListPaths?.has(sourcePath)) {\n return { fullRows: listDiff.newIndexes, movedRows: null };\n }\n if (listDiff.addIndexSet.size === 0 && listDiff.changeIndexSet.size === 0) {\n // 追加も移動も無い。削除も無ければ「変化が見えない再代入」= リフレッシュ意図\n if (listDiff.deleteIndexSet.size === 0) {\n // ただしキー突合による値展開が成立した書き込みでは、変化フィールドは\n // per-path 書き込みで個別に dirty 化済み。全行展開は純粋な無駄になる\n // (無変化ポーリングをゼロコストにする — 設計書 §2.2)。\n if (context.keyedMergePath === sourcePath) {\n return { fullRows: EMPTY_INDEXES, movedRows: null };\n }\n return { fullRows: listDiff.newIndexes, movedRows: null };\n }\n // 削除のみ: 残存行は位置も値も不変なので展開しない\n return { fullRows: EMPTY_INDEXES, movedRows: null };\n }\n return { fullRows: listDiff.addIndexSet, movedRows: listDiff.changeIndexSet };\n}\n\nconst EMPTY_PATH_INFOS: IPathInfo[] = [];\n\n/**\n * 位置だけが変わった行(movedRows)で展開すべきパス群を求める。\n * `${listPath}.*` 配下にある、$1 等を読んだ実績のある getter\n * (indexDependentGetterPaths)だけを返す。行の同一性・listIndex は保たれ\n * index 以外の入力が不変なので、index を読まない getter / 値パスは再評価不要。\n * 戻り値:\n * - IPathInfo[](空可): この各パスだけを行の listIndex で展開する\n * - null: ネストしたワイルドカード配下に index 依存 getter がある\n * (listIndex の階数が合わず個別展開できない)→ 呼び出し側で行全体展開に倒す\n *\n * 配下判定は staticMap の subtree 走査ではなく indexDependentGetterPaths 側の\n * プレフィックス照合で行う。静的依存グラフは `State.setPathInfo` が\n * 「バインドされたパスから親方向へ」張るため、DOM にバインドされていない中間\n * getter(`.label` だけを描画し `.rank` は `.label` からしか読まれない綴り)は\n * subtree に現れない。そこを走査すると index 依存 getter を取りこぼし、\n * 「index を読む getter が subtree に無い=位置のみ変わった行の値は不変」という\n * 呼び出し側の判断が偽になって、移動行の getter が古い値のまま残る。\n * この集合は $1 を読んだ getter の数しか持たないので、走査コストも subtree より小さい。\n */\nfunction getMovedRowExpansionPaths(\n context: Context,\n wildcardPath: string,\n depPathInfo: IPathInfo,\n): IPathInfo[] | null {\n const indexGetters = context.stateElement.indexDependentGetterPaths;\n if (!indexGetters || indexGetters.size === 0) {\n return EMPTY_PATH_INFOS;\n }\n let result: IPathInfo[] | null = null;\n const prefix = wildcardPath + DELIMITER;\n for (const path of indexGetters) {\n if (path !== wildcardPath && !path.startsWith(prefix)) {\n continue;\n }\n const pathInfo = getPathInfo(path);\n if (pathInfo.wildcardCount !== depPathInfo.wildcardCount) {\n return null;\n }\n (result ??= []).push(pathInfo);\n }\n return result ?? EMPTY_PATH_INFOS;\n}\n\nfunction _walkDependency(\n context: Context,\n startAddress: IStateAddress,\n callback: (address: IStateAddress) => void\n): void {\n // rank ごとのバケットで訪問する。辺 (u → v) では必ず rank(u) < rank(v) なので、\n // バケット r を処理する時点で rank < r のパスは全て dirty 化済みになる\n // = ここでリスト実体を読んでも入力が揃っている(topologicalRank.ts 参照)。\n const buckets: (IStateAddress[] | undefined)[] = [];\n const ranks = context.ranks;\n\n const enqueue = (address: IStateAddress, minRank: number): void => {\n let rank = ranks.get(address.pathInfo.path) ?? minRank;\n if (rank < minRank) {\n // 循環など rank が先行関係を表せないケース。現在のバケットに載せて\n // 同一ループ内で処理する(打ち切りは visited が担う)。\n rank = minRank;\n }\n (buckets[rank] ??= []).push(address);\n };\n\n enqueue(startAddress, 0);\n\n // 依存アドレスを収集するための一時バッファ(アドレスごとに使い回す)\n const nextEntries: IStateAddress[] = [];\n\n for (let rank = 0; rank < buckets.length; rank++) {\n const bucket = buckets[rank];\n if (bucket === undefined) {\n continue;\n }\n // 同一バケットへの push(循環時)で伸びるため length は都度読む\n for (let cursor = 0; cursor < bucket.length; cursor++) {\n const address = bucket[cursor];\n if (context.visited.has(address)) {\n continue;\n }\n context.visited.add(address);\n callback(address);\n nextEntries.length = 0;\n _collectDependencies(context, address, nextEntries);\n for (let i = 0; i < nextEntries.length; i++) {\n enqueue(nextEntries[i], rank + 1);\n }\n }\n }\n}\n\n/**\n * address の依存アドレスを nextEntries に集め、context.result にも登録する。\n * リスト展開(list → list.*)と動的依存のワイルドカード展開はここで値を読むが、\n * 呼び出し元がトポロジカル順を保証しているため入力は揃っている。\n */\nfunction _collectDependencies(\n context: Context,\n address: IStateAddress,\n nextEntries: IStateAddress[],\n): void {\n const sourcePath = address.pathInfo.path;\n\n /**\n * パスから依存関係をたどる\n * users.*.name <= users.* <= users\n * ただし、users がリストであれば users.* の依存関係は展開する\n */\n const staticDeps = context.staticMap.get(sourcePath);\n if (staticDeps) {\n for(const dep of staticDeps) {\n const depPathInfo = getPathInfo(dep);\n if (context.listPathSet.has(sourcePath) && depPathInfo.lastSegment === WILDCARD) {\n //expand indexes\n const newValue = context.stateProxy[getByAddressSymbol](address);\n const absAddress = liftAddress(context.stateElement, address);\n const lastValue = getStateListBaseline(absAddress);\n const listDiff = createListDiff(\n address.listIndex, lastValue, newValue);\n context.observedListValueByAbsAddress.set(absAddress, Array.isArray(newValue) ? newValue : []);\n const selection = selectExpansionIndexes(context, sourcePath, lastValue, newValue, listDiff);\n for(const listIndex of selection.fullRows) {\n const depAddress = createStateAddress(depPathInfo, listIndex);\n context.result.add(depAddress);\n nextEntries.push(depAddress);\n }\n if (selection.movedRows !== null) {\n const movedPathInfos = getMovedRowExpansionPaths(context, dep, depPathInfo);\n if (movedPathInfos === null) {\n // ネスト配下に index 依存 getter: 安全側で行全体を展開(従来挙動)\n for(const listIndex of selection.movedRows) {\n const depAddress = createStateAddress(depPathInfo, listIndex);\n context.result.add(depAddress);\n nextEntries.push(depAddress);\n }\n } else if (movedPathInfos.length > 0) {\n // 位置のみ変わった行は index 依存 getter のパスだけを展開する\n for(const listIndex of selection.movedRows) {\n for(const pathInfo of movedPathInfos) {\n const depAddress = createStateAddress(pathInfo, listIndex);\n context.result.add(depAddress);\n nextEntries.push(depAddress);\n }\n }\n }\n // movedPathInfos が空: index を読む getter が subtree に無い =\n // 位置のみ変わった行の値は不変。展開・dirty 化とも不要。\n }\n } else {\n const depAddress = createStateAddress(depPathInfo, address.listIndex);\n context.result.add(depAddress);\n nextEntries.push(depAddress);\n }\n }\n }\n /**\n * 動的依存関係をたどる\n * 動的依存関係は、getterの実行時に決定される\n *\n * source, target\n *\n * products.*.price => products.*.tax\n * get \"products.*.tax\"() { return this[\"products.*.price\"] * 0.1; }\n *\n * products.*.price => products.summary\n * get \"products.summary\"() { return this.$getAll(\"products.*.price\", []).reduce(sum); }\n *\n * categories.*.name => categories.*.products.*.categoryName\n * get \"categories.*.products.*.categoryName\"() { return this[\"categories.*.name\"]; }\n */\n const dynamicDeps = context.dynamicMap.get(sourcePath);\n if (dynamicDeps) {\n for(const dep of dynamicDeps) {\n const depPathInfo = getPathInfo(dep);\n const listIndexes: (IListIndex | null)[] = [];\n if (depPathInfo.wildcardCount > 0) {\n // ワイルドカードを含む依存関係の処理\n // 同じ親を持つかをパスの集合積で判定する\n // polyfills.tsにてSetのintersectionメソッドを定義している\n const wildcardLen = calcWildcardLen(address.pathInfo, depPathInfo);\n const expandable = (depPathInfo.wildcardCount - wildcardLen) >= 1;\n if (expandable) {\n let listIndex: IListIndex | null;\n if (wildcardLen > 0) {\n // categories.*.name => categories.*.products.*.categoryName\n // ワイルドカードを含む同じ親(products.*)を持つのが、\n // さらに下位にワイルドカードがあるので展開する\n if (address.listIndex === null) {\n raiseError(`Cannot expand dynamic dependency with wildcard for non-list address: ${address.pathInfo.path}`);\n }\n listIndex = listIndexAtWildcard(address.listIndex!, wildcardLen - 1, address.pathInfo.wildcardCount);\n } else {\n // selectedIndex => items.*.selected\n // 同じ親を持たない場合はnullから開始\n listIndex = null;\n }\n const expandContext: ExpandContext = {\n stateElement: context.stateElement,\n observedListValueByAbsAddress: context.observedListValueByAbsAddress,\n targetPathInfo: depPathInfo,\n targetListIndexes: [],\n wildcardPaths: depPathInfo.wildcardPaths,\n wildcardParentPaths: depPathInfo.wildcardParentPaths,\n stateProxy: context.stateProxy,\n searchType: context.searchType,\n };\n _walkExpandWildcard(expandContext, wildcardLen, listIndex);\n listIndexes.push(...expandContext.targetListIndexes);\n } else {\n // products.*.price => products.*.tax\n // ワイルドカードを含む同じ親(products.*)を持つので、リストインデックスは引き継ぐ\n if (address.listIndex === null) {\n raiseError(`Cannot expand dynamic dependency with wildcard for non-list address: ${address.pathInfo.path}`);\n }\n const listIndex = listIndexAtWildcard(address.listIndex, wildcardLen - 1, address.pathInfo.wildcardCount);\n listIndexes.push(listIndex);\n }\n } else {\n // products.*.tax => currentTaxRate\n // 同じ親を持たないので、リストインデックスはnull\n listIndexes.push(null);\n }\n for(const listIndex of listIndexes) {\n const depAddress = createStateAddress(depPathInfo, listIndex);\n context.result.add(depAddress);\n nextEntries.push(depAddress);\n }\n }\n }\n}\n\n/**\n * リスト差分が積んだ鍵付き購読者を、このウォークの続きとして辿る(要件 D7 の派生先)。\n *\n * 鍵付き購読は意図的に依存グラフに載らない(載せると選択の更新が全行へ広がる)ので、\n * 差分の 2 経路(`moveIndexWatchers` / `rekeyIndexSubscriptions`)は購読者のアドレスを直に\n * enqueue するだけだった。そこで止まると「鍵付き getter に依存する別の getter」が陳腐化する。\n *\n * 積む側(`dependency/keyedDependency.ts`)は proxy を持たないので積むだけにし、**proxy を\n * 持っているここ**が引き取る。`createListDiff` はこのウォークの中(リスト展開)から呼ばれるので、\n * その場で積まれたものをウォークの末尾で拾える — 書き込みは既に済んでおり、値は新しい。\n * `context.visited` を共有するので、既に訪問したアドレスは二度走らない。\n * 引き取った先の展開がさらに差分を起こすことがあるため、空になるまで回す。\n */\nfunction drainKeyedWalk(context: Context, callback: (address: IStateAddress) => void): void {\n for (let guard = 0; guard < MAX_DEPENDENCY_DEPTH; guard++) {\n const pending = takePendingKeyedWalk(context.stateElement);\n if (pending === null) {\n return;\n }\n pending.forEach((absAddress) => {\n _walkDependency(context, createStateAddress(absAddress.absolutePathInfo.pathInfo, absAddress.listIndex), callback);\n });\n }\n}\n\nexport function walkDependency(\n stateElement: IStateElement,\n startAddress: IStateAddress,\n staticDependency: Map<string, string[]>,\n dynamicDependency: Map<string, string[]>,\n listPathSet: Set<string>,\n stateProxy: IStateProxy,\n searchType: SearchType,\n callback: (address: IStateAddress) => void,\n options?: { listExpansion?: ListExpansion, keyedMergePath?: string | null }\n): IStateAddress[] {\n // 依存ゼロの葉パス(staticMap / dynamicMap にエントリ無し)は context や Set を\n // 割り当てず、開始アドレスの callback だけで完結する。リスト行の値書き込み\n // (update ホットパス)は set 毎にここを通る。開始アドレスへの callback は\n // 従来の walk 先頭と同一で、戻り値(依存アドレス群)も従来どおり空。\n //\n // ここは `drainKeyedWalk` を通らない。積むのは `createListDiff` の中だけで、この経路は\n // それを呼ばないので**自分が積んだ分を取り残すことはない**。理屈の上で残るのは\n // 「ウォークの外(`applyChangeToFor` / `collectWildcardIndexes`)で積まれ、そのバッチの\n // ウォークがこの fast path だけだった」場合に限られる。積む経路は 2 本あり、根拠は同じでない:\n // - `moveIndexWatchers`(`$eqIndex` 最内段)— 同じリストの 2 度目の `createListDiff` は\n // キャッシュに当たり、`oldIndexes === newIndexes` で早戻りして積まない。\n // - `rekeyIndexSubscriptions`(`$eqIndex` 外段)— `syncListIndexes` から呼ばれるので\n // **キャッシュ命中でも早戻りしない**。それでも取り残しが観測されないのは、積んだ直後の\n // バッチに必ず「その置換を起こした書き込み」のウォークが居て、そこで引き取られるから。\n // こちらは「構造上ありえない」ではなく「実測で 0」— だから下の番人が要る\n // (同一バッチ 2 回のリスト置換 × 外段 `$eqIndex` でも pending 0・描画も正常)。\n // ここに drain を足すなら保留の有無を見る `WeakMap#get` が 1 回増え、\n // 実測で **+3.3 ns/回**(この判定自体が 1.9 ns)— 起こせない事象のためにホットパスへ\n // 恒久的に乗せる取引としては割に合わないので置いていない。前提が崩れていないことは\n // `__tests__/dependency.keyedAncestorIndex.test.ts` の取り残し検査が見張っており、\n // そこが落ちたらここに drain を置くこと。\n const startPath = startAddress.pathInfo.path;\n if (!staticDependency.has(startPath) && !dynamicDependency.has(startPath)) {\n callback(startAddress);\n return [];\n }\n // パス単位のトポロジカル順位。値を一切読まないグラフ走査で毎回求める(キャッシュは\n // 持たない — topologicalRank.ts)。依存グラフは追記が基本だが、再帰の再セットでは\n // 旧世代の生成アクセサを指す辺が外れることがある(recursion/registry.ts の forgetGenerated)。\n const ranks = getTopologicalRanks(startPath, staticDependency, dynamicDependency, MAX_DEPENDENCY_DEPTH);\n const context: Context = {\n ranks: ranks,\n stateElement: stateElement,\n observedListValueByAbsAddress: new Map<IAbsoluteStateAddress, readonly unknown[]>(),\n staticMap: staticDependency,\n dynamicMap: dynamicDependency,\n result: new Set<IStateAddress>(),\n listPathSet: listPathSet,\n visited: new Set<IStateAddress>(),\n stateProxy: stateProxy,\n searchType: searchType,\n listExpansion: options?.listExpansion ?? \"full\",\n keyedMergePath: options?.keyedMergePath ?? null,\n };\n _walkDependency(context, startAddress, callback);\n drainKeyedWalk(context, callback);\n // 観測したリスト値を state 側の基準として確定する(E1)。ウォークの最中に進めると\n // 同じウォーク内の 2 度目の観測が「変化なし」になるため、走査を終えてからまとめて書く\n // (`collectWildcardIndexes` の commitDiffBaseline と同じ形)。\n for (const [absAddress, value] of context.observedListValueByAbsAddress) {\n setStateListBaseline(absAddress, value);\n }\n return Array.from(context.result);\n}\n","/**\n * topologicalRank.ts — 依存グラフ(パス単位)のトポロジカル順位。\n *\n * 依存ウォークは list → list.* を展開するために途中でリスト実体を読む。この読み取りが\n * 正しい値を返すには「そのパスの入力(先行パス)がすべて dirty 化済み」である必要がある。\n * DFS ではダイヤモンド依存で片腕しか dirty 化していない段階で合流点を評価してしまうため、\n * パス単位の rank(= 最長経路長)を先に求め、rank の昇順で訪問する。\n *\n * rank の定義から、辺 (u → v) が存在すれば必ず rank(u) < rank(v) となる。したがって\n * rank r のバケットを処理する時点で rank < r のパスはすべて訪問(dirty 化)済みであり、\n * 同じバケット内のパス同士は互いに先行関係を持たない。\n *\n * 値を読まないグラフ走査なので、ウォーク 1 回あたりの追加コストは実測で誤差に\n * 収まる(メモ化しても差が出なかったため、キャッシュは持たない)。\n */\nimport { raiseError } from \"../raiseError\";\n\nexport function getTopologicalRanks(\n startPath: string,\n staticMap: Map<string, string[]>,\n dynamicMap: Map<string, string[]>,\n maxDepth: number,\n): ReadonlyMap<string, number> {\n // 1) startPath から到達可能なパス部分グラフと入次数を求める(値は一切読まない)\n const adjacency: Map<string, string[]> = new Map();\n const inDegree: Map<string, number> = new Map();\n const pending: string[] = [startPath];\n inDegree.set(startPath, 0);\n while (pending.length > 0) {\n const path = pending.pop()!;\n if (adjacency.has(path)) {\n continue;\n }\n const staticDeps = staticMap.get(path);\n const dynamicDeps = dynamicMap.get(path);\n let deps: string[];\n if (staticDeps === undefined) {\n deps = dynamicDeps ?? [];\n } else if (dynamicDeps === undefined) {\n deps = staticDeps;\n } else {\n deps = staticDeps.concat(dynamicDeps);\n }\n adjacency.set(path, deps);\n for (let i = 0; i < deps.length; i++) {\n const dep = deps[i];\n inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);\n if (!adjacency.has(dep)) {\n pending.push(dep);\n }\n }\n }\n\n // 2) Kahn 法。rank は最長経路長(rank[v] = max(rank[u]) + 1)。\n // 入次数が 0 に落ちて queue に入ったパスだけが「確定」で、緩和の途中で\n // 暫定値が入っただけのパス(= 循環の一部)は確定扱いにしない。\n const ranks: Map<string, number> = new Map();\n const settled: Set<string> = new Set();\n const queue: string[] = [];\n for (const [path, degree] of inDegree) {\n if (degree === 0) {\n ranks.set(path, 0);\n settled.add(path);\n queue.push(path);\n }\n }\n for (let i = 0; i < queue.length; i++) {\n const path = queue[i];\n const nextRank = ranks.get(path)! + 1;\n if (nextRank > maxDepth) {\n raiseError(`Maximum dependency depth of ${maxDepth} exceeded. Possible circular dependency detected at path: ${path}`);\n }\n const deps = adjacency.get(path)!;\n for (let j = 0; j < deps.length; j++) {\n const dep = deps[j];\n if (nextRank > (ranks.get(dep) ?? -1)) {\n ranks.set(dep, nextRank);\n }\n const remaining = inDegree.get(dep)! - 1;\n inDegree.set(dep, remaining);\n if (remaining === 0) {\n settled.add(dep);\n queue.push(dep);\n }\n }\n }\n\n // 3) 循環に含まれるパスは rank が決まらない(入次数が 0 に落ちない)。\n // そもそも正しい評価順が存在しないので、順序保証を諦めて確定済みの\n // 最大 rank の次にまとめる。打ち切りは従来どおり visited が担う。\n // 暫定値が残っていると確定パスとの前後関係を誤って表すため、必ず上書きする。\n if (settled.size !== adjacency.size) {\n let maxRank = -1;\n for (const path of settled) {\n const rank = ranks.get(path)!;\n if (rank > maxRank) {\n maxRank = rank;\n }\n }\n const cycleRank = maxRank + 1;\n for (const path of adjacency.keys()) {\n if (!settled.has(path)) {\n ranks.set(path, cycleRank);\n }\n }\n }\n return ranks;\n}\n\n","/**\n * setByAddress.ts\n *\n * Stateの内部APIとして、アドレス情報(IStateAddress)を指定して\n * 状態オブジェクト(target)に値を設定するための関数(setByAddress)の実装です。\n *\n * 主な役割:\n * - 指定されたパス・インデックスに対応するState値を設定(多重ループやワイルドカードにも対応)\n * - getter/setter経由で値設定時はpushAddressでスコープを一時設定\n * - 存在しない場合は親pathInfoやlistIndexを辿って再帰的に値を設定\n * - 設定後はupdater.enqueueUpdateAddressで更新情報を登録\n *\n * 設計ポイント:\n * - ワイルドカードや多重ループにも柔軟に対応し、再帰的な値設定を実現\n * - finallyで必ず更新情報を登録し、再描画や依存解決に利用\n * - getter/setter経由のスコープ切り替えも考慮した設計\n */\n\nimport { liftAddress, absoluteAddressOf } from \"../../address/liftAddress\";\nimport { IAbsoluteStateAddress, IStateAddress } from \"../../address/types\";\nimport { DELIMITER, WILDCARD } from \"../../define\";\nimport { createListIndex } from \"../../list/createListIndex\";\nimport { getListIndexesByList, setListIndexesByList } from \"../../list/listIndexesByList\";\nimport { getLastListValueByAbsoluteStateAddress, setLastListValueByAbsoluteStateAddress } from \"../../list/lastListValueByAbsoluteStateAddress\";\nimport { ISwapInfo } from \"./types\";\nimport { createListDiff } from \"../../list/createListDiff\";\nimport { collectFieldWrites, IKeyedListMerge, mergeKeyedList } from \"../../list/mergeKeyedList\";\nimport { IListIndex } from \"../../list/types\";\nimport { getPathInfo } from \"../../address/PathInfo\";\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { wildcardScopeMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { getUpdater } from \"../../updater/updater\";\nimport { IStateHandler, IStateProxy } from \"../types\";\nimport { getByAddress } from \"./getByAddress\";\nimport { isCacheable } from \"./isCacheable\";\nimport { hasByAddress } from \"./hasByAddress\";\nimport { markSwapBaselineList } from \"../../list/swapBaselineList\";\nimport { getSwapInfoByList, setSwapInfoByList } from \"./swapInfo\";\nimport { walkDependency } from \"../../dependency/walkDependency\";\nimport { NOT_HANDLED } from \"../../core/addressHooks\";\nimport { hasKeyedDependents, hasKeyedDescendants, keyedDependents, keyedDescendantDependents } from \"../../dependency/keyedDependency\";\nimport { dirtyCacheEntryByAbsoluteStateAddress, setCacheEntryByAbsoluteStateAddress } from \"../../cache/cacheEntryByAbsoluteStateAddress\";\nimport { config } from \"../../config\";\nimport { devtoolsSink } from \"../../platform/devtoolsSink\";\nimport { beginPropagationTransaction, getCurrentPropagationContext } from \"../../propagation/propagation\";\nimport { consumeOccurrenceWrite } from \"../occurrenceWrite\";\n\n/**\n * 宣言済みパスの `prev` 台帳へ旧値を記録する。台帳を読むのは `$watch`\n * (docs/state-watch-hook-design.md §4-1)と `$scan` の `from`(docs/state-scan-design.md §2-1)。\n *\n * same-value guard が既に読んだ旧値だけを使い、そのための追加読みはしない。\n * 台帳の実体は watch/addressHooks.ts の writeObserve hook(`$watch` / `$scan` を宣言した state にだけ付く)。\n * 宣言の無い state は `addressHooks` の null 判定 1 個で抜ける。\n */\nfunction recordDeclaredPrevValue(\n stateElement: IStateHandler[\"stateElement\"],\n path: string,\n absAddress: IAbsoluteStateAddress,\n oldValue: unknown,\n hasOldValue: boolean,\n): void {\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const observers = hooks.writeObserve;\n for (let i = 0; i < observers.length; i++) {\n observers[i](stateElement, path, absAddress, oldValue, hasOldValue);\n }\n }\n}\n\n// 書き込み・入れ替えの後の通知(設計案 H1 の written / swapped): 観測面を持つ機能(DCC の\n// bindable イベント・watch の旧値台帳)が state に付けた hook だけを呼ぶ\nfunction notifyWritten(stateElement: IStateHandler[\"stateElement\"], pathInfo: IStateAddress[\"pathInfo\"], detail?: { readonly value: unknown }): void {\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const written = hooks.written;\n for (let i = 0; i < written.length; i++) {\n written[i](stateElement, pathInfo, detail);\n }\n }\n}\n\nfunction notifySwapped(stateElement: IStateHandler[\"stateElement\"], elementAbsAddress: IAbsoluteStateAddress, displacedAbsAddress: IAbsoluteStateAddress): void {\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const swapped = hooks.swapped;\n for (let i = 0; i < swapped.length; i++) {\n swapped[i](stateElement, elementAbsAddress, displacedAbsAddress);\n }\n }\n}\n\n// Phase 3: 書き込み時点の因果 context を update record に付与する。\n// binding 経由の書き込みは呼び出し元の dynamic scope から context を引き継ぎ、\n// binding 外からの API update は新しい transaction を開始する(設計書 §4 規則 1)。\n// 依存 walk で enqueue される派生アドレスも同じ書き込みの因果に属する。\n\n// 鍵付き購読(`$eq` 系、dependency/keyedDependency.ts)への通知。同値ガードが読んだ旧値と\n// 新値の鍵に登録された行だけを dirty 化して enqueue する。購読の無いパスは Map 参照 2 回で抜ける。\n// 祖先への書き込み(`$eq(\"sel.id\")` に対する `sel = {…}`)は配下の鍵付きパスへ知らせる。その旧値は\n// 同値ガードが読めなかったときだけ `readOld` で書き込み前に読む\nfunction notifyKeyed(\n stateElement: IStateHandler[\"stateElement\"],\n path: string,\n hasOldValue: boolean,\n oldValue: unknown,\n value: unknown,\n readOld: () => unknown,\n): IAbsoluteStateAddress[] | null {\n const direct = hasKeyedDependents(stateElement, path);\n const descendants = hasKeyedDescendants(stateElement, path);\n if (!direct && !descendants) {\n return null;\n }\n const subscribers: IAbsoluteStateAddress[] = [];\n const enqueue = createKeyedEnqueue(subscribers);\n if (direct) {\n keyedDependents(stateElement, path, hasOldValue, oldValue, value).forEach(enqueue);\n }\n if (descendants) {\n keyedDescendantDependents(stateElement, path, hasOldValue ? oldValue : readOld(), value).forEach(enqueue);\n }\n return subscribers;\n}\n\n/** 鍵付き通知の伝播 context(`createKeyedEnqueue` と `walkKeyedDependents` で 1 本にする) */\nfunction keyedPropagationContext(): ReturnType<typeof getCurrentPropagationContext> | null {\n return config.enablePropagationContext ? (getCurrentPropagationContext() ?? null) : null;\n}\n\n/** 集めた購読者を `collected` へ控える(依存ウォークの起点。`walkKeyedDependents` が書き込み後に使う) */\nfunction createKeyedEnqueue(collected: IAbsoluteStateAddress[]): (absAddress: IAbsoluteStateAddress) => void {\n const updater = getUpdater();\n const context = keyedPropagationContext();\n return (absAddress: IAbsoluteStateAddress): void => {\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n updater.enqueueAbsoluteAddress(absAddress, context);\n collected.push(absAddress);\n };\n}\n\n/**\n * 鍵付き購読の購読者から、その**依存先**へ通知を伝播する。\n *\n * 鍵付き購読(`$eq` 系)は意図的に依存グラフに載らない(載せると選択の更新が全行に広がる)。\n * その代わり `notifyKeyed` が購読者のアドレスを直に enqueue するのだが、**そこで止まっていた**ため\n * 「鍵付き getter に依存する別の getter / バインディング」が陳腐化していた(素のツリーで再現。\n * docs/state-keyed-derived-propagation.md)。通常の書き込みは `notifyWrite` が同じ enqueue の後に\n * `walkDependency` を回しており、鍵付きだけが非対称だった。\n *\n * **収集は書き込みの前・ウォークはこの関数で書き込みの後**に分ける。`notifyKeyed` が\n * `Reflect.set` より前に走るのは旧値の鍵で「前に選ばれていた行」を引くためで、一方\n * `walkDependency` はリスト展開で書き込み**後**の値を読む前提(`notifyWrite` が `finally` に\n * いるのと同じ理由)。前で walk すると書き込み前の配列で展開してしまう。\n *\n * ホットパス(R2): 鍵付き選択の存在理由は「選択の更新を 2 行に抑える」ことなので、購読者ごとに\n * 依存表を 2 回引くだけの短絡を先に置く。依存先を持つ購読者は稀で、持たなければ\n * `createStateAddress` の割り当ても `walkDependency` の呼び出しも起きない。\n */\nfunction walkKeyedDependents(\n subscribers: IAbsoluteStateAddress[] | null,\n receiver: any,\n handler: IStateHandler,\n): void {\n if (subscribers === null || subscribers.length === 0) {\n return;\n }\n const stateElement = handler.stateElement;\n const staticDependency = stateElement.staticDependency;\n const dynamicDependency = stateElement.dynamicDependency;\n const updater = getUpdater();\n const context = keyedPropagationContext();\n for (let i = 0; i < subscribers.length; i++) {\n const treePath = subscribers[i].absolutePathInfo;\n const path = treePath.pathInfo.path;\n // 依存先ゼロの購読者(大多数)は Map 参照 2 回で抜ける\n if (!staticDependency.has(path) && !dynamicDependency.has(path)) {\n continue;\n }\n const address = createStateAddress(treePath.pathInfo, subscribers[i].listIndex);\n walkDependency(\n stateElement,\n address,\n staticDependency,\n dynamicDependency,\n stateElement.listPaths,\n receiver as IStateProxy,\n \"new\",\n (depAddress: IStateAddress) => {\n // 起点(購読者自身)は createKeyedEnqueue が済ませている — 二重 enqueue を避ける\n if (depAddress === address) return;\n const absDepAddress = liftAddress(stateElement, depAddress);\n dirtyCacheEntryByAbsoluteStateAddress(absDepAddress);\n updater.enqueueAbsoluteAddress(absDepAddress, context);\n },\n // `notifyWrite` と同じ規準。購読者は普通リストではないので実質効かないが、\n // 万一リストでも未変更行まで展開しない\n { listExpansion: \"diff\" },\n );\n }\n}\n\n/**\n * `$postUpdate` の鍵付き通知(proxy/apis/postUpdate.ts)。\n *\n * in-place 変異を通知する正規の idiom なので、呼ばれた時点で**変異はもう起きている** —\n * `setByAddress` と違って旧値がどこにも無い。`hasOldKey = false` で引くと、台帳が控えている\n * 「最後に観測した鍵」(`lastValue`)が旧値の代わりになり、前に選ばれていた行も\n * 新しく選ばれる行も一緒に再評価される。これが無いと `raw.sel.id = 2; $postUpdate(\"sel.id\")` で\n * 前の行が真のまま残った(2.6.0 で `setByAddress` 側に入れた修正の取りこぼし)。\n *\n * 現在値の読みは購読があるときだけ行う(`readCurrent` の thunk)。\n */\nexport function notifyKeyedPostUpdate(\n stateElement: IStateHandler[\"stateElement\"],\n path: string,\n readCurrent: () => unknown,\n receiver: any,\n handler: IStateHandler,\n): void {\n const direct = hasKeyedDependents(stateElement, path);\n const descendants = hasKeyedDescendants(stateElement, path);\n if (!direct && !descendants) {\n return;\n }\n const current = readCurrent();\n const subscribers: IAbsoluteStateAddress[] = [];\n const enqueue = createKeyedEnqueue(subscribers);\n if (direct) {\n keyedDependents(stateElement, path, false, undefined, current).forEach(enqueue);\n }\n if (descendants) {\n keyedDescendantDependents(stateElement, path, undefined, current, false).forEach(enqueue);\n }\n // `$postUpdate` は変異が**もう起きた**後に呼ばれるので、収集とウォークを分ける必要がない\n // (`setByAddress` 側だけが `Reflect.set` を跨ぐ)。派生先へ届かない穴は両方にあった\n walkKeyedDependents(subscribers, receiver, handler);\n}\n\nfunction notifyWrite(\n address : IStateAddress,\n absAddress: IAbsoluteStateAddress,\n receiver : any,\n handler : IStateHandler,\n keyedMergePath: string | null,\n cacheable: boolean,\n listExpansion: \"diff\" | \"full\" = \"diff\"\n): void {\n const propagationContext = config.enablePropagationContext\n ? (getCurrentPropagationContext() ?? beginPropagationTransaction(-1))\n : null;\n const updater = getUpdater();\n updater.enqueueAbsoluteAddress(absAddress, propagationContext);\n // 書いたアドレス自身のキャッシュを、依存ウォークより先に無効化する(#274)。ウォークはリスト展開\n // (list → list.*)と動的依存の親リスト展開で、書いたパスの値を読む。ワイルドカードを含むリストパス\n // (`groups.*.items`)はキャッシュ対象なので、無効化しないと書き込み前の配列がヒットし、基準との差分が\n // 「変化なし」になって置き換える前の行だけを展開する(長い配列に置き換えた分の行が着地しない)。\n // 依存先は下の callback が訪問のたびに読む前に無効化するが、開始アドレスは callback が飛ばす\n // (二重 enqueue の防止)のでここで済ませる — 開始アドレスも callback で無効化する $postUpdate と同じ順序。\n // 値は直後の commitWriteCache が載せ直す。\n if (cacheable) {\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n }\n // 依存関係のあるキャッシュを無効化(ダーティ)、更新対象として登録\n walkDependency(\n handler.stateElement,\n address,\n handler.stateElement.staticDependency,\n handler.stateElement.dynamicDependency,\n handler.stateElement.listPaths,\n receiver as IStateProxy,\n \"new\",\n (depAddress: IStateAddress) => {\n // キャッシュを無効化(ダーティ)\n if (depAddress === address) return;\n const absDepAddress = liftAddress(handler.stateElement, depAddress);\n dirtyCacheEntryByAbsoluteStateAddress(absDepAddress);\n // 更新対象として登録\n updater.enqueueAbsoluteAddress(absDepAddress, propagationContext);\n },\n // リスト置換時は追加行・位置変更行のみ展開する(未変更行の再訪を省く。\n // $postUpdate の手動リフレッシュは従来通り全行展開のまま)\n { listExpansion, keyedMergePath }\n )\n}\n\n/**\n * 書き込み完了後のキャッシュ整合(Issue #234)。\n *\n * ワイルドカードのデータパス(リスト行)は代入値がそのまま格納値なので、\n * 代入値を dirty:false で載せて次回の読みを省く。\n *\n * アクセサペア(getterPaths に載るパス)は getter が正本であり、setter は\n * 命令的な代入に過ぎない。代入値を getter の評価結果として固定すると\n * - setter が正規化・分配した結果と読みが食い違う\n * - getter が一度も評価されず動的依存が張られない → 依存先を書いても\n * walkDependency がこのキャッシュを dirty にできず、永続的に stale になる\n * (プリミティブ代入は同値ガードの旧値読みで偶然 getter が走るが、\n * オブジェクト代入は同値ガードを素通りするため救済がない)\n * ため、キャッシュを dirty にして次回の読みで getter を再評価させる。\n */\nfunction commitWriteCache(\n stateElement: IStateHandler[\"stateElement\"],\n path: string,\n absAddress: IAbsoluteStateAddress,\n value: unknown,\n cacheable: boolean,\n): void {\n if (!cacheable) {\n return;\n }\n if (stateElement.getterPaths.has(path)) {\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n return;\n }\n setCacheEntryByAbsoluteStateAddress(absAddress, {\n value: value,\n dirty: false,\n // 読み側(getByAddress)と同じ世代印を付ける — ヒットになるのは世代が一致する項目だけ\n // (cache/types.ts の `generation`)。\n generation: stateElement.stateGeneration\n });\n}\n\nfunction _setByAddress(\n target : object,\n address : IStateAddress,\n absAddress: IAbsoluteStateAddress,\n value : any,\n receiver : any,\n handler : IStateHandler,\n keyedMergePath: string | null,\n cacheable: boolean\n): any {\n try {\n if (address.pathInfo.path in target) {\n if (handler.stateElement.setterPaths.has(address.pathInfo.path)) {\n // setterの中で参照の可能性があるので、addressをプッシュする。\n // setter は命令的な代入であって派生(getter)ではないため、実行中の\n // 読み取り(同値ガードの旧値読み・$1 参照等)で依存を張らない。\n // アクセサペア(get/set 同名パス)では、抑止しないと setter 内の内部\n // 書き込みの同値ガード読みが「getter の依存」として誤登録される。\n handler.pushAddress(address);\n handler.beginUntrack();\n try {\n return Reflect.set(target, address.pathInfo.path, value, receiver);\n } finally {\n handler.endUntrack();\n handler.popAddress();\n }\n\n } else {\n return Reflect.set(target, address.pathInfo.path, value);\n }\n } else {\n const parentAddress = address.parentAddress;\n if (parentAddress === null) {\n return Reflect.set(target, address.pathInfo.path, value);\n }\n const parentValue = getByAddress(target, parentAddress, receiver, handler);\n const lastSegment = address.pathInfo.segments[address.pathInfo.segments.length - 1];\n if (lastSegment === WILDCARD) {\n // 読み取り側(getByAddress)と同じ取り違え。書き込みでも何段必要かを言う。\n const index = address.listIndex?.index ?? raiseError(\n wildcardScopeMessage(\n `path \"${address.pathInfo.path}\"`,\n address.pathInfo.wildcardCount,\n address.listIndex?.length ?? 0,\n ),\n );\n return Reflect.set(parentValue, index, value);\n } else {\n // 公開 getter への書き込み(X9)は setByAddressCore の fast path(親がオブジェクトの\n // 未存在キー)で dispatch 済み。ここに来るのは親が非オブジェクトの形だけ\n return Reflect.set(parentValue, lastSegment, value);\n }\n }\n } finally {\n notifyWrite(address, absAddress, receiver, handler, keyedMergePath, cacheable);\n }\n}\n\nfunction _setByAddressWithSwap(\n target : object,\n address : IStateAddress,\n absAddress: IAbsoluteStateAddress,\n value : any,\n receiver : any,\n handler : IStateHandler,\n keyedMergePath: string | null,\n cacheable: boolean\n) {\n // elementsの場合はswapInfoを準備(キーはリストの配列そのもの — swapInfo.ts 参照)\n const parentAddress = address.parentAddress ?? raiseError(`address.parentAddress is undefined path: ${address.pathInfo.path}`);\n const parentValue = getByAddress(target, parentAddress, receiver, handler) ?? [];\n let swapInfo = getSwapInfoByList(parentValue);\n if (swapInfo === null) {\n const listIndexes = getListIndexesByList(parentValue) ?? [];\n swapInfo = {\n value: [...parentValue], listIndexes: [...listIndexes]\n }\n setSwapInfoByList(parentValue, swapInfo);\n }\n try {\n return _setByAddress(target, address, absAddress, value, receiver, handler, keyedMergePath, cacheable);\n } finally {\n const index = swapInfo.value.indexOf(value);\n const currentParentValue = getByAddress(target, parentAddress, receiver, handler) ?? [];\n const currentListIndexes = Array.isArray(currentParentValue) ? (getListIndexesByList(currentParentValue) ?? []) : [];\n const curIndex = address.listIndex!.index;\n const listIndex = (index !== -1) ? \n swapInfo!.listIndexes[index] : \n createListIndex(parentAddress.listIndex, -1);\n currentListIndexes[curIndex] = listIndex;\n // 重複チェック\n // 重複していない場合、swapが完了したとみなし、インデックスを更新\n const listValueSet = new Set(currentParentValue);\n if (listValueSet.size === swapInfo!.value.length) {\n for(let i = 0; i < currentListIndexes.length; i++) {\n currentListIndexes[i].index = i;\n }\n // 完了したのでswapInfoを削除\n setSwapInfoByList(parentValue, null);\n notifySwappedList(parentAddress, swapInfo, currentParentValue, currentListIndexes, receiver, handler);\n }\n }\n}\n\n/**\n * 要素書き込みの入れ替え(または行の置き換え)が揃ったとき、リストを「書き込む前の並び →\n * いまの並び」の置換として描画し直させる(#4 — 同一性モデル)。\n *\n * 台帳は上で「listIndex は値に付いて動く」形に組み替え済み。ところが `for` の描画基準\n * (lastListValue)はその場で書き換えられた同じ配列なので、差分に入れ替えが映らず、ブロックは\n * 動かないまま中身だけが書き換わっていた。基準を「書き込む前の並びの写し」とその台帳の写しに\n * すると、`for` は写しといまの配列の差分を listIndex の同一性で突き合わせ(createListDiff の\n * calcDiffIndexes)、ブロックを値と一緒に動かし、置き換えた行を作り直す。基準を写しに替えるのは、\n * 描画基準がいま入れ替えている配列そのもののときだけ — 同じバッチで配列を丸ごと書き換えた後なら、\n * 描画はまだその前の配列で、そちらとの差分が入れ替えも含む。\n *\n * 行ごとの扱い(書き込む前といまの台帳の位置を比べる):\n * - 位置が変わらない行: 何もしない。\n * - 新しい listIndex の行(書き込む前の台帳に無い): その位置の値の書き込みとして着地させる。差し替えられた\n * 行は `for` の差分で退役し、その行のアドレスの着地は `$watch` / `$scan` の選別で捨てられるので、\n * 着地は新しい行が持つ(#274 の「その位置のいまの値で 1 回」)。要素パス自身の prev は、書き込みがその位置の\n * 前の行のアドレスで記録した値を引き継ぐ(引き継がないと `$watch \"items.*\"` の prev が消える)。ブロックは\n * `for` が同じ位置で外す行の Content をその場で使い回す(applyChangeToFor の collectInPlaceContents)。\n * - 値と一緒に動いた行: 値は変わっていないので、依存を無効化して描画だけをやり直す。書き込みを別の\n * バッチに分けると、途中のバッチで別の値を描いた行が残る。\n * リスト自身も描画だけを積む(updater の enqueueRenderOnlyAddress)。書き込みとして積むと、`items` の\n * `$watch` が配列の参照の変わらない入れ替えで発火する。\n */\n\nfunction notifySwappedList(\n parentAddress: IStateAddress,\n swapInfo: ISwapInfo,\n currentParentValue: unknown,\n currentListIndexes: readonly IListIndex[],\n receiver: any,\n handler: IStateHandler,\n): void {\n const stateElement = handler.stateElement;\n const updater = getUpdater();\n const listAbsAddress = liftAddress(stateElement, parentAddress);\n if (getLastListValueByAbsoluteStateAddress(listAbsAddress) === currentParentValue) {\n setListIndexesByList(swapInfo.value, swapInfo.listIndexes);\n setLastListValueByAbsoluteStateAddress(listAbsAddress, swapInfo.value);\n markSwapBaselineList(swapInfo.value);\n }\n updater.enqueueRenderOnlyAddress(listAbsAddress);\n\n const positionBefore = new Map<IListIndex, number>();\n swapInfo.listIndexes.forEach((listIndex, position) => positionBefore.set(listIndex, position));\n const elementPathInfo = getPathInfo(parentAddress.pathInfo.path + DELIMITER + WILDCARD);\n for (let position = 0; position < currentListIndexes.length; position++) {\n const listIndex = currentListIndexes[position];\n const before = positionBefore.get(listIndex);\n if (before === position) {\n continue;\n }\n const elementAddress = createStateAddress(elementPathInfo, listIndex);\n const elementAbsAddress = liftAddress(stateElement, elementAddress);\n if (typeof before === \"undefined\") {\n const displacedAbsAddress = absoluteAddressOf(stateElement, elementPathInfo, swapInfo.listIndexes[position] ?? null);\n notifySwapped(stateElement, elementAbsAddress, displacedAbsAddress);\n // 置き換えで入った行は中身が丸ごと新しい。差分展開だと入れ子のリストの行(`items.*.tags.*`)が\n // 着地せず `$watch` / `$scan` が取り逃すので、この行の下だけ全行展開で通知する\n notifyWrite(\n elementAddress, elementAbsAddress, receiver, handler, null,\n isCacheable(stateElement, elementAddress), \"full\",\n );\n continue;\n }\n walkDependency(\n stateElement,\n elementAddress,\n stateElement.staticDependency,\n stateElement.dynamicDependency,\n stateElement.listPaths,\n receiver as IStateProxy,\n \"new\",\n (depAddress: IStateAddress) => {\n const depAbsAddress = liftAddress(stateElement, depAddress);\n dirtyCacheEntryByAbsoluteStateAddress(depAbsAddress);\n updater.enqueueRenderOnlyAddress(depAbsAddress);\n },\n { listExpansion: \"diff\" },\n );\n }\n}\n\n/**\n * `$listKeys` 宣言済みリストパスへの配列代入を「キー一致行のオブジェクト値展開」に\n * 変換する(docs/state-list-key-design.md §2)。\n *\n * 1. キー突合して、一致行は旧オブジェクトを据え置いたハイブリッド配列を作る\n * 2. ハイブリッド配列を通常の書き込み経路で格納する\n * 3. createListDiff で listIndex を確定し、変化フィールドだけを per-path 書き込みで発行\n *\n * 3 を格納後に行うのが要点。フィールド書き込みは `list.*.field` を親経由で解決する\n * ため、親(ハイブリッド配列)が既に格納されていなければ正しい行に届かない。\n * また per-path 書き込みは再び setByAddress に入るので、ネストしたリストパスが\n * 宣言されていればそのレベルのキー突合が再帰的に走る(§4)。\n *\n * 未宣言時のコストは stateElement.listKeys の null 判定 1 回のみ(§7-1)。\n */\nfunction setKeyedListByAddress(\n target : object,\n address : IStateAddress,\n merge : IKeyedListMerge,\n oldList : readonly unknown[],\n receiver : any,\n handler : IStateHandler\n): any {\n const listPath = address.pathInfo.path;\n // diff の基準は「マージ相手にした配列」= 書き込み直前に格納されていた配列。\n // 読み手(applyChangeToFor / $getAll / resolve)は現在格納されている配列の\n // listIndex 台帳(listIndexesByList)へ収束するため、同じ基準で引くことで\n // 書き込みが dirty 化・キャッシュするアドレスと読み手のアドレスが一致する。\n // lastValue(最後に *適用* された配列)を基準にすると、for が未マウントで\n // lastValue が空のときに別台帳を作ってしまい、値は入っているのにワイルドカード\n // 読みだけ旧値のまま残る(設計書 §8.1)。\n // 格納より前に引くのは、格納時の walkDependency(listExpansion: \"diff\")が\n // 先にハイブリッド配列の台帳を作ってしまうと、後から上書きした台帳との間で\n // 同じ分裂が起きるため。先に確定させておけば以降は全経路がこれに合流する。\n const listParentListIndex = address.listIndex;\n if (getListIndexesByList(oldList) === null) {\n // 一度も描画されていないリストは台帳自体が無い。先に生やしておかないと\n // isSameList 経路が空の oldIndexes をそのまま新台帳にしてしまう。\n createListDiff(listParentListIndex, null, oldList);\n }\n const diff = createListDiff(listParentListIndex, oldList, merge.list);\n const result = setByAddressCore(target, address, merge.list, receiver, handler, listPath);\n const elementPathInfo = getPathInfo(listPath + DELIMITER + WILDCARD);\n for (const match of merge.matched) {\n const fieldWrites = collectFieldWrites(match.oldRow, match.newRow);\n if (fieldWrites.length === 0) {\n continue;\n }\n // createListDiff の契約上 newIndexes の長さはハイブリッド配列と一致するため\n // 通常 undefined にはならない。仮に不変条件が破れても、per-path 書き込みを\n // 諦めるだけで値そのものは行オブジェクトへ反映する(skip すると state だけが\n // 旧値のまま残り、本機能が塞ごうとしている stale を作ってしまう)。\n const listIndex: IListIndex | undefined = diff.newIndexes[match.position];\n for (const write of fieldWrites) {\n if (typeof listIndex === \"undefined\") {\n match.oldRow[write.field] = write.value;\n continue;\n }\n const fieldPathInfo = getPathInfo(elementPathInfo.path + DELIMITER + write.field);\n const fieldAddress = createStateAddress(fieldPathInfo, listIndex);\n setByAddress(target, fieldAddress, write.value, receiver, handler);\n }\n }\n return result;\n}\n\nexport function setByAddress(\n target : object,\n address : IStateAddress,\n value : any,\n receiver : any,\n handler : IStateHandler\n): any {\n const listKeys = handler.stateElement.listKeys;\n if (listKeys != null && Array.isArray(value)) {\n const keySpec = listKeys.get(address.pathInfo.path);\n if (typeof keySpec !== \"undefined\") {\n const oldValue = getByAddress(target, address, receiver, handler);\n const merge = mergeKeyedList(address.pathInfo.path, keySpec, oldValue, value);\n if (merge !== null) {\n // merge が非 null なのは oldValue が非空配列のときだけ(mergeKeyedList 参照)\n return setKeyedListByAddress(target, address, merge, oldValue as readonly unknown[], receiver, handler);\n }\n }\n }\n return setByAddressCore(target, address, value, receiver, handler, null);\n}\n\nfunction setByAddressCore(\n target : object,\n address : IStateAddress,\n value : any,\n receiver : any,\n handler : IStateHandler,\n keyedMergePath: string | null\n): any {\n const stateElement = handler.stateElement;\n const path = address.pathInfo.path;\n // 読み書き境界の hook(設計案 H1、書き側)。無ければ判定 1 回\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const writeHooks = hooks.write;\n for (let i = 0; i < writeHooks.length; i++) {\n const handled = writeHooks[i](stateElement, address, value, receiver, handler);\n if (handled !== NOT_HANDLED) return handled;\n }\n }\n // D22 後段(接ぎ木済みボリュームの親の丸ごと書き禁止)は webComponent/addressHooks.ts の write hook が担う\n // 再帰 getter への書き込み禁止([wcs/recursion-readonly])は recursion/addressHooks.ts の write hook が担う\n // occurrence(wc-bindable の `semantics: \"event\"`)由来の書き込みは、同値でも\n // 「もう一度起きた」ことを落としてはならないため same-value guard を 1 回だけ飛ばす。\n // トークンはここで消費されるので、この write の内側で走る他の書き込みには波及しない。\n const skipSameValueGuard = consumeOccurrenceWrite();\n\n // --- fast path: 宣言済み getter/setter でも swap 対象でもない、親を持つ葉パス ---\n // 従来は same-value guard の値読み・hasByAddress・実書き込みがそれぞれ親チェーンを\n // 解決していた(キャッシュヒットでも getByAddress 呼び出しの固定費 ×3)。\n // 親を 1 回だけ解決し、同じ親オブジェクトに対して guard 判定と Reflect.set を行う。\n // 非オブジェクト親などの例外形は従来経路へ倒し、挙動差を作らない。\n if (!(path in target) && address.parentAddress !== null && !stateElement.elementPaths.has(path)) {\n const parentValue = getByAddress(target, address.parentAddress, receiver, handler);\n if (typeof parentValue === \"object\" && parentValue !== null) {\n // ワイルドカード末尾で listIndex が無い不正アドレスは、従来どおり\n // 書き込み時(enqueue 済みの try 内)に raiseError する → key は undefined のまま持ち回す\n const lastSegment = address.pathInfo.lastSegment;\n const key: PropertyKey | undefined = lastSegment === WILDCARD\n ? address.listIndex?.index\n : lastSegment;\n let devOldValue: unknown;\n let devHasOldValue = false;\n if (!skipSameValueGuard && config.sameValueGuard && (value === null || typeof value !== \"object\")) {\n // hasByAddress と同じ「初期化済みスロットか」判定(undefined 格納と未初期化を区別)\n const has = key !== undefined && key in parentValue;\n const oldValue = key !== undefined ? (parentValue as Record<PropertyKey, unknown>)[key] : undefined;\n if (has && Object.is(oldValue, value)) {\n return true;\n }\n devOldValue = oldValue;\n devHasOldValue = true;\n }\n // key が undefined(listIndex の無い不正アドレス)なら読みは undefined — 書き込みが下で投げる\n // 購読者の収集は書き込みの**前**(旧値の鍵が要る)。そこからの依存ウォークは\n // 書き込みの**後**(下の finally の walkKeyedDependents)\n const keyedSubscribers = notifyKeyed(stateElement, path, devHasOldValue, devOldValue, value,\n () => (parentValue as Record<PropertyKey, unknown>)[key as PropertyKey]);\n const cacheable = isCacheable(stateElement, address);\n const absAddress = liftAddress(stateElement, address);\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"state:write\",\n absoluteAddress: absAddress,\n value,\n oldValue: devOldValue,\n hasOldValue: devHasOldValue,\n });\n }\n recordDeclaredPrevValue(stateElement, path, absAddress, devOldValue, devHasOldValue);\n let dispatchedExport = false;\n try {\n if (key === undefined) {\n // fast path 版の同じ取り違え(末尾ワイルドカードに listIndex が無い)。\n // 通常経路と同じ語彙で「何段必要か」を言う(pathDiagnostics.ts)。\n raiseError(wildcardScopeMessage(\n `path \"${path}\"`,\n address.pathInfo.wildcardCount,\n address.listIndex?.length ?? 0,\n ));\n }\n // 「親にそのキーが無い」書き込みは writeMissing hook(公開 getter への書き込み — X9)に先に聞く。\n // hook の無い state は判定 1 個で抜ける。hook が throw しても(setter の無い公開 getter)\n // 代入値をキャッシュに固定しないよう、呼ぶ前に印を立て、素通しなら戻す\n if (hooks && hooks.writeMissing.length !== 0 && lastSegment !== WILDCARD && !(key in parentValue)) {\n const missing = hooks.writeMissing;\n for (let i = 0; i < missing.length; i++) {\n dispatchedExport = true;\n const handled = missing[i](stateElement, address, parentValue, key, value, receiver, handler);\n if (handled !== NOT_HANDLED) {\n return handled;\n }\n dispatchedExport = false;\n }\n }\n return Reflect.set(parentValue, key, value);\n } finally {\n notifyWrite(address, absAddress, receiver, handler, keyedMergePath, cacheable);\n walkKeyedDependents(keyedSubscribers, receiver, handler);\n if (dispatchedExport) {\n // Exported row paths are cacheable but absent from getterPaths. The\n // accessor may normalize or reject the input; never pin that input.\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n } else {\n commitWriteCache(stateElement, path, absAddress, value, cacheable);\n }\n notifyWritten(stateElement, address.pathInfo, { value });\n }\n }\n }\n // --- end fast path ---\n\n // --- same-value guard (config.sameValueGuard・既定 ON) ---\n // primitive 値かつ Object.is 同値なら、set / enqueue / walkDependency / DOM 適用 /\n // $updatedCallback / DCC イベントを丸ごとスキップ(標準的なリアクティブ no-op)。\n // 参照型(object/array)は in-place mutation 取りこぼし防止のため素通し(ガードしない)。\n // devtools write イベント用: guard が既に取得した旧値のみ流用する\n // (参照型のために追加の get はしない — protocol §4.2)\n let devOldValue: unknown;\n let devHasOldValue = false;\n if (!skipSameValueGuard && config.sameValueGuard && (value === null || typeof value !== \"object\")) {\n const oldValue = getByAddress(target, address, receiver, handler);\n if (hasByAddress(target, address, receiver, handler) && Object.is(oldValue, value)) {\n return true;\n }\n devOldValue = oldValue;\n devHasOldValue = true;\n }\n // 購読者の収集は書き込みの**前**(旧値の鍵が要る)。ウォークは下の finally\n const keyedSubscribers = notifyKeyed(stateElement, path, devHasOldValue, devOldValue, value, () => getByAddress(target, address, receiver, handler));\n // --- end same-value guard ---\n const isSwappable = stateElement.elementPaths.has(address.pathInfo.path);\n const cacheable = isCacheable(stateElement, address);\n const absAddress = liftAddress(stateElement, address);\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"state:write\",\n absoluteAddress: absAddress,\n value,\n oldValue: devOldValue,\n hasOldValue: devHasOldValue,\n });\n }\n recordDeclaredPrevValue(stateElement, path, absAddress, devOldValue, devHasOldValue);\n try {\n if (isSwappable) {\n return _setByAddressWithSwap(target, address, absAddress, value, receiver, handler, keyedMergePath, cacheable);\n } else {\n return _setByAddress(target, address, absAddress, value, receiver, handler, keyedMergePath, cacheable);\n }\n } finally {\n // 鍵付き購読の派生先(`notifyWrite` は `_setByAddress` の中で済んでいる)。書き込み後なので\n // リスト展開が新しい値を読む\n walkKeyedDependents(keyedSubscribers, receiver, handler);\n // 要素書き込み(#4)の代入値は、書き込んだアドレスのキャッシュに固定しない。入れ替えでは listIndex が\n // 値に付いて動くので、書き込んだ時点の listIndex がこの位置に残るとは限らない — 固定すると、台帳は\n // 入れ替わったのにキャッシュだけが位置のまま交差する。notifyWrite が無効化した項目を、次の読みが\n // 台帳に沿って読み直す\n if (!isSwappable) {\n commitWriteCache(stateElement, path, absAddress, value, cacheable);\n }\n notifyWritten(stateElement, address.pathInfo, { value });\n }\n}\n\n","/**\n * resolve.ts\n *\n * StateClassのAPIとして、パス(path)とインデックス(indexes)を指定して\n * Stateの値を取得・設定するための関数(resolve)の実装です。\n *\n * 主な役割:\n * - 文字列パス(path)とインデックス配列(indexes)から、該当するState値の取得・設定を行う\n * - ワイルドカードや多重ループを含むパスにも対応\n * - value未指定時は取得(getByRef)、指定時は設定(setByRef)を実行\n *\n * 設計ポイント:\n * - getStructuredPathInfoでパスを解析し、ワイルドカード階層ごとにリストインデックスを解決\n * - handler.engine.getListIndexesSetで各階層のリストインデックス集合を取得\n * - getByRef/setByRefで値の取得・設定を一元的に処理\n * - 柔軟なバインディングやAPI経由での利用が可能\n */\n\nimport { getPathInfo } from \"../../address/PathInfo\";\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { indexArityMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { assertWritable } from \"../assertWritable\";\nimport { getByAddress } from \"../methods/getByAddress\";\nimport { getListIndexByIndexes } from \"../methods/getListIndexByIndexes\";\nimport { setByAddress } from \"../methods/setByAddress\";\nimport { IStateHandler } from \"../types\";\n\ntype ResolveFunction = (path: string, indexes: number[], ...value: [value?: any]) => any;\n\nexport function resolve(\n target: object, \n _prop: PropertyKey, \n receiver: any,\n handler: IStateHandler\n): ResolveFunction {\n return (path: string, indexes: number[], ...value: [value?: any]): any => {\n // 添字が配列でない(省略・`null` 等)のは素の TypeError にせず、形の診断にする\n // (`$getAll` / `$setAll` と同じ語彙)。`$resolve` は添字を省略できない — 省略形は `$getAll`\n if (!Array.isArray(indexes)) {\n raiseError(\n `$resolve(\"${path}\") requires an explicit indexes array (pass [] when the path has no wildcards) — got ` +\n `${indexes === null ? \"null\" : typeof indexes}.`\n );\n }\n // 読み(2 引数)か書き(3 引数)だけ。4 つ目以降は黙って捨てられていた(要件 B7 の「範囲外の\n // 引数個数は throw」と不一致 — 書きのつもりの取り違えが readonly エラーでしか現れなかった)\n if (value.length > 1) {\n raiseError(\n `$resolve(\"${path}\") takes 2 arguments to read and 3 to write (path, indexes, value) — got ` +\n `${2 + value.length}.`\n );\n }\n const pathInfo = getPathInfo(path);\n if (handler.addressStackLength > 0) {\n const lastInfo = handler.lastAddressStack?.pathInfo ?? null;\n const stateElement = handler.stateElement;\n if (lastInfo !== null && lastInfo.path !== pathInfo.path) {\n // gettersに含まれる場合は依存関係を登録\n if (stateElement.getterPaths.has(lastInfo.path)) {\n stateElement.addDynamicDependency(pathInfo.path, lastInfo.path);\n }\n }\n }\n\n // 添字の本数はワイルドカードの本数と**厳密に一致**する必要がある。\n // 不足は元から throw していたが、超過は黙って無視されていた(余分な要素を\n // 誰も読まないため)= `$resolve(\"items.*.price\", [row, col])` のような\n // 「1 本しか無いのに 2 本渡す」取り違えが、間違った値を返したまま通っていた。\n if (indexes.length !== pathInfo.wildcardParentPathInfos.length) {\n raiseError(indexArityMessage(\"$resolve\", path, pathInfo.wildcardParentPathInfos.length, indexes.length));\n }\n // ワイルドカード階層ごとにListIndexを解決していく(`$setAll` と共有)\n const listIndex = getListIndexByIndexes(target, receiver, handler, pathInfo, indexes);\n\n // ToDo:WritableかReadonlyかを判定して適切なメソッドを呼び出す\n const address = createStateAddress(pathInfo, listIndex);\n // 読みか書きかは引数の**個数**で決める(要件 B7)。値で決めると undefined を書けない\n if (value.length === 0) {\n return getByAddress(target, address, receiver, handler);\n } else {\n assertWritable(handler);\n setByAddress(target, address, value[0], receiver, handler);\n }\n };\n} ","/**\n * getAllReadonly\n *\n * ワイルドカードを含む State パスから、対象となる全要素を配列で取得する。\n * 走査そのものは `$setAll` と共有する(wildcardIndexes.ts)。\n *\n * `indexes` 省略時の既定はループ文脈の添字 `[$1..$n]`。正確には「path と文脈が\n * 共有するワイルドカード連鎖の分だけ文脈の添字を接頭辞として敷く」(整合最長接頭辞)。\n * 共有が無いのに文脈が添字を持つ場合は throw する — 異なる文脈の添字は流用しない。\n *\n * Throws: LIST-201(インデックス未解決)、BIND-201(ワイルドカード情報不整合)、\n * 添字本数超過(wcs/index-arity)、省略時の文脈不整合(getAllContextMismatchMessage)\n */\n\nimport { getPathInfo } from \"../../address/PathInfo\";\nimport { getAllContextMismatchMessage, indexArityMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { getScopedIndexes } from \"../../list/wildcardLevel\";\nimport { getContextListIndex } from \"../methods/getContextListIndex\";\nimport { IStateHandler } from \"../types\";\nimport { collectWildcardIndexes } from \"./wildcardIndexes\";\nimport { resolve } from \"./resolve\";\n\ntype GetAllFunction = (path: string, indexes?: number[]) => any[];\n\nexport function getAll(\n target: object,\n prop: PropertyKey,\n receiver: any,\n handler: IStateHandler\n): GetAllFunction {\n const resolveFn = resolve(target, prop, receiver, handler);\n return (path: string, indexes?: number[]): any[] => {\n // オーサリング層の `**`(束縛・合併形)は recursion/addressHooks.ts の get hook が先に受ける\n const pathInfo = getPathInfo(path);\n // 渡された添字が配列でない(`null` 等)のは素の TypeError にせず、形の診断にする。\n // 省略(undefined)だけが「文脈の添字」を意味する。\n if (typeof indexes !== \"undefined\" && !Array.isArray(indexes)) {\n raiseError(\n `$getAll(\"${path}\") requires the indexes to be an array when given ` +\n `(omit them for the loop context, or pass [] to expand every level) — got ` +\n `${indexes === null ? \"null\" : typeof indexes}.`\n );\n }\n if (handler.addressStackLength > 0) {\n const lastInfo = handler.lastAddressStack?.pathInfo ?? null;\n const stateElement = handler.stateElement;\n if (lastInfo !== null && lastInfo.path !== pathInfo.path) {\n // gettersに含まれる場合は依存関係を登録\n if (stateElement.getterPaths.has(lastInfo.path)) {\n stateElement.addDynamicDependency(pathInfo.path, lastInfo.path);\n }\n }\n }\n\n // 明示的に渡された添字だけを検査する。`$getAll` の添字は**前方一致の接頭辞**で、\n // 足りない分は「その階層を全部展開する」という正しい意味を持つ(README の\n // `$getAll(\"scores.*\", [])` がこれ)。一方**超過は意味を持たず黙って捨てられ**、\n // ワイルドカードの本数を取り違えたまま部分集合が返っていた。\n // 省略時に下で導出する添字は文脈由来なので、この検査には掛けない。\n if (typeof indexes !== \"undefined\" && indexes.length > pathInfo.wildcardParentPathInfos.length) {\n raiseError(indexArityMessage(\"$getAll\", path, pathInfo.wildcardParentPathInfos.length, indexes.length));\n }\n if (typeof indexes === \"undefined\") {\n // 省略時の既定はループ文脈の添字 `[$1..$n]`。ただし敷けるのは path と文脈が\n // **共有するワイルドカード連鎖**の分だけなので、path のワイルドカードを\n // 内側(最深)から探し、最初に文脈にヒットした階層の scoped indexes を接頭辞にする。\n // ワイルドカードパスの序数はパス文字列自身の `*` の本数で決まるため、深い側が\n // ヒットすれば浅い側は必ず含まれ、これが整合する最長の接頭辞になる。文脈が\n // path より深い分は自然に切り詰められ、導出した接頭辞は path のワイルドカード\n // 本数を超えないので、上の本数検査には掛けない。\n for (let i = pathInfo.wildcardPaths.length - 1; i >= 0; i--) {\n const listIndex = getContextListIndex(handler, pathInfo.wildcardPaths[i]);\n if (listIndex) {\n indexes = getScopedIndexes(listIndex, listIndex.length);\n break;\n }\n }\n if (typeof indexes === \"undefined\") {\n // 共有ゼロ。文脈が自スコープの添字を実際に持っているなら、既定の `[...$n]` は\n // **異なる文脈の添字の流用(混入)**になるため、黙って全展開へ倒さず throw する。\n // 文脈そのものが無い(トップレベル getter / メソッド直下)なら全展開が既定。\n const lastAddress = handler.addressStackLength > 0 ? handler.lastAddressStack : null;\n const contextListIndex = lastAddress?.listIndex ?? null;\n if (pathInfo.wildcardCount > 0 && lastAddress !== null && contextListIndex !== null &&\n contextListIndex.length > 0) {\n raiseError(getAllContextMismatchMessage(path, lastAddress.pathInfo.path));\n }\n indexes = [];\n }\n }\n // 読みなので差分基準を更新する(固定 arity の `$setAll` は更新しない。設計 §6-2)\n const resultIndexes = collectWildcardIndexes(\n target, receiver, handler, pathInfo, indexes, { commitDiffBaseline: true });\n const resultValues: any[] = [];\n for(let i = 0; i < resultIndexes.length; i++) {\n resultValues.push(resolveFn(\n pathInfo.path,\n resultIndexes[i]\n ));\n }\n return resultValues;\n }\n }\n","/**\n * getListIndex.ts\n *\n * StateClassの内部APIとして、パス情報(IResolvedAddress)から\n * 対応するリストインデックス(IListIndex)を取得する関数です。\n *\n * 主な役割:\n * - パスのワイルドカード種別(context/all/partial/none)に応じてリストインデックスを解決\n * - context型は現在のループコンテキストからリストインデックスを取得\n * - all型は各階層のリストインデックス集合からインデックスを辿って取得\n * - partial型やnone型は未実装またはnullを返す\n *\n * 設計ポイント:\n * - ワイルドカードや多重ループ、ネストした配列バインディングに柔軟に対応\n * - resolveListIndexesByListで各階層のリストインデックス集合を取得\n * - エラー時はraiseErrorで例外を投げる\n */\n\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { IResolvedAddress } from \"../../address/types\";\nimport { resolveListIndexesByList } from \"../../list/listIndexesByList\";\nimport { IListIndex } from \"../../list/types\";\nimport { raiseError } from \"../../raiseError\";\nimport { IStateHandler } from \"../types\";\nimport { getByAddress } from \"./getByAddress\";\nimport { getContextListIndex } from \"./getContextListIndex\";\n\nexport function getListIndex(\n target : object, \n resolvedAddress: IResolvedAddress, \n receiver: any,\n handler: IStateHandler\n): IListIndex | null {\n const pathInfo = resolvedAddress.pathInfo;\n switch (resolvedAddress.wildcardType) {\n case \"none\":\n return null;\n case \"context\": {\n const lastWildcardPath = pathInfo.wildcardPaths.at(-1) ?? \n raiseError(`lastWildcardPath is null: ${resolvedAddress.pathInfo.path}`);\n return getContextListIndex(handler, lastWildcardPath) ?? \n raiseError(`ListIndex not found: ${resolvedAddress.pathInfo.path}`);\n }\n case \"all\": {\n let parentListIndex: IListIndex | null = null;\n for(let i = 0; i < resolvedAddress.pathInfo.wildcardCount; i++) {\n const wildcardParentPathInfo = resolvedAddress.pathInfo.wildcardParentPathInfos[i] ?? \n raiseError(`wildcardParentPathInfo is null: ${resolvedAddress.pathInfo.path}`);\n const wildcardParentAddress = createStateAddress(wildcardParentPathInfo, parentListIndex);\n const wildcardParentValue = getByAddress(target, wildcardParentAddress, receiver, handler);\n const wildcardParentListIndexes: IListIndex[] = resolveListIndexesByList(wildcardParentValue, parentListIndex) ?? \n raiseError( `ListIndex not found: ${wildcardParentPathInfo.path}`);\n const wildcardIndex = resolvedAddress.wildcardIndexes[i] ?? \n raiseError(`wildcardIndex is null: ${resolvedAddress.pathInfo.path}`);\n // 範囲外 index はリスト自体の不在と別原因なので、メッセージに index を含める。\n // 親パスだけを名指しすると「リスト自体が見つからない」と誤読させる\n // (docs/state-bind-component-nested-for-design.md §8.4)。\n parentListIndex = wildcardParentListIndexes[wildcardIndex] ??\n raiseError(`ListIndex not found at index ${wildcardIndex} of ${wildcardParentPathInfo.path}`);\n }\n return parentListIndex;\n }\n case \"partial\": {\n raiseError(`Partial wildcard type is not supported yet: ${resolvedAddress.pathInfo.path}`);\n }\n }\n}\n","/**\n * setAll.ts\n *\n * ワイルドカードを含む State パスにマッチする**全アドレスへ一括で書き込む**。\n * `$getAll`(読み)の対称形(docs/state-set-all-design.md)。\n *\n * 存在理由は糖衣ではなく「**リスト全置換の回避**」(設計 §1-1)。\n * `this.users = this.users.map(...)` は配列を作り直すので ListIndex・行 getter\n * キャッシュ・差分描画がまとめて作り直しになる。`$setAll` は意味としては一括更新、\n * 実体は in-place な個別書き込みで、同じことを差分に載せたまま行う。\n *\n * 3 つの形(設計 §2):\n * - ブロードキャスト `$setAll(path, indexes, value)`\n * - mapper(第一級) `$setAll(path, indexes, (current, ...indexes) => next)`\n * - spread `$setAll(path, indexes, values, { spread: true })`\n */\n\nimport { getPathInfo } from \"../../address/PathInfo\";\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { IStateAddress } from \"../../address/types\";\nimport { indexArityMessage, setAllSpreadArityMessage, setAllValueKindMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { assertWritable } from \"../assertWritable\";\nimport { getByAddress } from \"../methods/getByAddress\";\nimport { getListIndexByIndexes } from \"../methods/getListIndexByIndexes\";\nimport { setByAddress } from \"../methods/setByAddress\";\nimport { IStateHandler } from \"../types\";\nimport { collectWildcardIndexes } from \"./wildcardIndexes\";\n\nexport interface ISetAllOptions {\n /**\n * `values` を**マッチ順に 1 件ずつ配る**。既定(省略/false)では配列もそのまま\n * ブロードキャストされる — 対象プロパティ自体が配列型のとき区別がつかないため、\n * 配分は明示的にオプトインさせる(設計 §3)。\n */\n readonly spread?: boolean;\n}\n\ntype SetAllFunction = (\n path: string,\n indexes: number[],\n value: any,\n options?: ISetAllOptions,\n) => number;\n\nexport function setAll(\n target : object,\n _prop : PropertyKey,\n receiver: any,\n handler : IStateHandler\n): SetAllFunction {\n return (path: string, indexes: number[], value: any, options?: ISetAllOptions): number => {\n assertWritable(handler);\n // オーサリング層の `**`(ブロードキャスト形)は recursion/addressHooks.ts の get hook が先に受ける\n const pathInfo = getPathInfo(path);\n\n // 書き込み API に暗黙の文脈依存は持たせない。`for` の中で `[]` と書けば\n // 「現在行」ではなく「全行」を意味する(設計 §4-1)。\n if (!Array.isArray(indexes)) {\n raiseError(setAllValueKindMessage(path, \"requires an explicit indexes array (pass [] to expand every level).\"));\n }\n // 添字は前方一致の接頭辞なので不足は正当。超過だけを弾く(`$getAll` と同じ規則)。\n if (indexes.length > pathInfo.wildcardParentPathInfos.length) {\n raiseError(indexArityMessage(\"$setAll\", path, pathInfo.wildcardParentPathInfos.length, indexes.length));\n }\n\n const spread = options?.spread === true;\n const isMapper = typeof value === \"function\";\n if (spread && isMapper) {\n raiseError(setAllValueKindMessage(path, \"cannot combine { spread: true } with a mapper function.\"));\n }\n if (spread && !Array.isArray(value)) {\n raiseError(setAllValueKindMessage(path, \"requires an array as the value when { spread: true } is set.\"));\n }\n\n // --- 第 1 相: 書き込み先を全部確定する(設計 §6) ---\n // 走査しながら書くと書き込みが ListIndex 集合を動かしうる。\n // 差分基準(state 側の共有正本 stateListBaseline)は、固定 arity の `$setAll` は走査を\n // 借りるだけで確定しない(§6-2。再帰の `$setAll` は確定する — recursion/walk.ts)。\n const resultIndexes = collectWildcardIndexes(\n target, receiver, handler, pathInfo, indexes, { commitDiffBaseline: false });\n\n if (spread && (value as unknown[]).length !== resultIndexes.length) {\n raiseError(setAllSpreadArityMessage(path, resultIndexes.length, (value as unknown[]).length));\n }\n\n const addresses: IStateAddress[] = [];\n for(let i = 0; i < resultIndexes.length; i++) {\n const listIndex = getListIndexByIndexes(target, receiver, handler, pathInfo, resultIndexes[i]);\n addresses.push(createStateAddress(pathInfo, listIndex));\n }\n\n // --- 第 2 相: 確定したアドレスにだけ書く ---\n let written = 0;\n for(let i = 0; i < addresses.length; i++) {\n const address = addresses[i];\n let nextValue: any;\n if (isMapper) {\n // 現在値は書く直前に読む。先行する書き込みが getter 経由で他行に及ぶ場合、\n // mapper が見るべきなのは最新値。\n const currentValue = getByAddress(target, address, receiver, handler);\n nextValue = value(currentValue, ...resultIndexes[i]);\n } else if (spread) {\n nextValue = (value as unknown[])[i];\n } else {\n nextValue = value;\n }\n // undefined は常にスキップ(設計 §5)。mapper の return 忘れで全行を潰さないため、\n // かつ「この行は変えない」を表現できるようにするため。クリアは null。\n if (typeof nextValue === \"undefined\") {\n continue;\n }\n setByAddress(target, address, nextValue, receiver, handler);\n written++;\n }\n return written;\n };\n}\n"],"names":["registryByStateElement","WeakMap","getOrCreateCommandToken","stateElement","name","registry","get","Map","set","token","CommandToken","namespaceProxyByStateElement","getCommandNamespace","cached","proxy","Proxy","Object","create","_target","prop","commandTokenNames","has","ownKeys","Array","from","getOwnPropertyDescriptor","configurable","enumerable","value","raiseError","deleteProperty","clearCommandNamespace","delete","assertWritable","handler","mutability","_cache","ResolvedAddress","path","segments","wildcardCount","wildcardType","wildcardIndexes","pathInfo","constructor","split","tmpPatternSegments","slice","incompleteCount","completeCount","i","length","segment","push","number","Number","isNaN","structuredPath","join","getPathInfo","this","getResolvedAddress","nameInfo","getContextListIndex","addressStackLength","address","lastAddressStack","index","indexByWildcardPath","listIndex","listIndexAtWildcard","isCacheable","hasMounts","lastSegment","charCodeAt","getterPaths","readMissing","parentValue","receiver","hooks","addressHooks","missing","handled","NOT_HANDLED","_getByAddress","target","STATE_COMMAND_NAMESPACE_NAME","namespace","Reflect","walkNamespace","parentAddress","missingRootPathMessage","getByAddress","WILDCARD","wildcardScopeMessage","pushAddress","popAddress","checkDependency","hasRecursion","recursionRegistry","materializeForPathInfo","readHooks","read","absAddress","liftAddress","cacheEntry","getCacheEntryByAbsoluteStateAddress","generation","stateGeneration","dirty","setCacheEntryByAbsoluteStateAddress","_getByAddressWithCache","collectWildcardIndexes","indexes","options","newValueByAddress","walkWildcardPattern","wildcardParentPathInfos","wildcardIndexPos","indexPos","parentIndexes","results","wildcardParentPathInfo","wildcardAddress","createStateAddress","wildcardAbsAddress","oldValue","getStateListBaseline","newValue","listIndexes","createListDiff","newIndexes","concat","resultIndexes","commitDiffBaseline","entries","setStateListBaseline","isArray","getListIndexByIndexes","tmpValue","resolveListIndexesByList","assertPlainRow","row","side","position","STATE_LIST_KEYS_NAME","proto","getPrototypeOf","prototype","keyOf","spec","key","String","extractKeys","list","keys","seen","Set","JSON","stringify","add","collectFieldWrites","oldRow","newRow","writes","field","is","hasOwn","hasByAddress","swapInfoByList","setSwapInfoByList","swapInfo","_walkExpandWildcard","context","currentWildcardIndex","parentListIndex","parentPath","wildcardParentPaths","parentPathInfo","parentAbsAddress","lastValue","stateProxy","getByAddressSymbol","listDiff","observedListValueByAbsAddress","loopIndexes","searchType","oldIndexes","addIndexSet","changeIndexSet","deleteIndexSet","config","debug","console","log","getIndexes","wildcardPaths","targetListIndexes","EMPTY_INDEXES","selectExpansionIndexes","sourcePath","_lastValue","_newValue","listExpansion","crossRowListPaths","fullRows","movedRows","size","keyedMergePath","EMPTY_PATH_INFOS","getMovedRowExpansionPaths","wildcardPath","depPathInfo","indexGetters","indexDependentGetterPaths","result","prefix","DELIMITER","startsWith","_walkDependency","startAddress","callback","buckets","ranks","enqueue","minRank","rank","nextEntries","bucket","undefined","cursor","visited","_collectDependencies","staticDeps","staticMap","dep","listPathSet","selection","depAddress","movedPathInfos","dynamicDeps","dynamicMap","wildcardLen","calcWildcardLen","expandContext","walkDependency","staticDependency","dynamicDependency","startPath","maxDepth","adjacency","inDegree","pending","pop","deps","settled","queue","degree","nextRank","j","remaining","maxRank","cycleRank","getTopologicalRanks","guard","takePendingKeyedWalk","forEach","absolutePathInfo","drainKeyedWalk","recordDeclaredPrevValue","hasOldValue","observers","writeObserve","notifyWritten","detail","written","notifySwapped","elementAbsAddress","displacedAbsAddress","swapped","notifyKeyed","readOld","direct","hasKeyedDependents","descendants","hasKeyedDescendants","subscribers","createKeyedEnqueue","keyedDependents","keyedDescendantDependents","keyedPropagationContext","enablePropagationContext","getCurrentPropagationContext","collected","updater","getUpdater","dirtyCacheEntryByAbsoluteStateAddress","enqueueAbsoluteAddress","walkKeyedDependents","treePath","listPaths","absDepAddress","notifyKeyedPostUpdate","readCurrent","current","notifyWrite","cacheable","propagationContext","beginPropagationTransaction","commitWriteCache","_setByAddress","setterPaths","beginUntrack","endUntrack","_setByAddressWithSwap","getListIndexesByList","indexOf","currentParentValue","currentListIndexes","curIndex","createListIndex","listAbsAddress","getLastListValueByAbsoluteStateAddress","setListIndexesByList","setLastListValueByAbsoluteStateAddress","markSwapBaselineList","enqueueRenderOnlyAddress","positionBefore","elementPathInfo","before","elementAddress","absoluteAddressOf","depAbsAddress","notifySwappedList","setByAddress","listKeys","keySpec","merge","newList","newKeys","oldList","oldKeys","oldRowByKey","matched","mergeKeyedList","listPath","listParentListIndex","diff","setByAddressCore","match","fieldWrites","write","fieldPathInfo","setKeyedListByAddress","writeHooks","skipSameValueGuard","consumeOccurrenceWrite","elementPaths","devOldValue","devHasOldValue","sameValueGuard","keyedSubscribers","devtoolsSink","type","absoluteAddress","dispatchedExport","writeMissing","isSwappable","resolve","_prop","lastInfo","addDynamicDependency","indexArityMessage","getAll","resolveFn","getScopedIndexes","lastAddress","contextListIndex","getAllContextMismatchMessage","resultValues","getListIndex","resolvedAddress","at","wildcardParentValue","wildcardParentListIndexes","wildcardIndex","setAll","setAllValueKindMessage","spread","isMapper","setAllSpreadArityMessage","addresses","nextValue"],"mappings":"yhBAIA,MAAMA,EAA6E,IAAIC,QAEjF,SAAUC,EAAwBC,EAA6BC,GACnE,IAAIC,EAAWL,EAAuBM,IAAIH,QAClB,IAAbE,IACTA,EAAW,IAAIE,IACfP,EAAuBQ,IAAIL,EAAcE,IAE3C,IAAII,EAAQJ,EAASC,IAAIF,GAMzB,YALqB,IAAVK,IAETA,EAAQ,IAAIC,EAAaN,EAAMD,GAC/BE,EAASG,IAAIJ,EAAMK,IAEdA,CACT,CCDA,MAAME,EAA+D,IAAIV,QAEnE,SAAUW,EAAoBT,GAClC,MAAMU,EAASF,EAA6BL,IAAIH,GAChD,QAAsB,IAAXU,EACT,OAAOA,EAET,MAAMC,EAAQ,IAAIC,MAAMC,OAAOC,OAAO,MAAO,CAC3C,GAAAX,CAAIY,EAAiBC,GACnB,GAAoB,iBAATA,GAGNhB,EAAaiB,kBAAkBC,IAAIF,GAGxC,OAAOjB,EAAwBC,EAAcgB,EAC/C,EACAE,IAAG,CAACH,EAAiBC,IACI,iBAATA,GAAqBhB,EAAaiB,kBAAkBC,IAAIF,GAExEG,QAAO,IACEC,MAAMC,KAAKrB,EAAaiB,mBAEjC,wBAAAK,CAAyBP,EAAiBC,GACxC,GAAoB,iBAATA,GAAqBhB,EAAaiB,kBAAkBC,IAAIF,GACjE,MAAO,CACLO,cAAc,EACdC,YAAY,EACZC,MAAO1B,EAAwBC,EAAcgB,GAInD,EACA,GAAAX,GACEqB,EAAW,mEACb,EACA,cAAAC,GACED,EAAW,oEACb,IAGF,OADAlB,EAA6BH,IAAIL,EAAcW,GACxCA,CACT,CAEM,SAAUiB,EAAsB5B,GACpCQ,EAA6BqB,OAAO7B,EACtC,CClDM,SAAU8B,EAAeC,GACF,aAAvBA,EAAQC,YACVN,EAAW,0BAEf,CCOA,MAAMO,EAAwC,IAAI7B,IAWlD,MAAM8B,EACKC,KACAC,SACAC,cACAC,aACAC,gBACAC,SAUT,WAAAC,CAAYN,GAEV,MAAMC,EAAWD,EAAKO,MAAM,KACtBC,EAAqBP,EAASQ,QACpC,IAAIC,EAAkB,EAClBC,EAAgB,EAChBT,EAAgB,EAChBC,EAA6B,OACjC,MAAMC,EAAqC,GAG3C,IAAI,IAAIQ,EAAI,EAAGA,EAAIX,EAASY,OAAQD,IAAK,CACvC,MAAME,EAAUb,EAASW,GACzB,GAAgB,MAAZE,EAEFN,EAAmBI,GAAK,IACxBR,EAAgBW,KAAK,MACrBL,IACAR,QACK,CACL,MAAMc,EAASC,OAAOH,GACjBG,OAAOC,MAAMF,KAEhBR,EAAmBI,GAAK,IACxBR,EAAgBW,KAAKC,GACrBL,IACAT,IAEJ,CACF,CAEA,MAAMiB,EAAiBX,EAAmBY,KAAK,KACzCf,EAAWgB,EAAYF,IAGzBT,EAAkB,GAAKC,EAAgB,KAGvCR,EAFEO,IAAoBR,EAEP,UACNS,IAAkBT,EAEZ,MAGA,WAGnBoB,KAAKtB,KAAOA,EACZsB,KAAKrB,SAAWA,EAChBqB,KAAKpB,cAAgBA,EACrBoB,KAAKnB,aAAeA,EACpBmB,KAAKlB,gBAAkBA,EACvBkB,KAAKjB,SAAWA,CAClB,EAaI,SAAUkB,GAAmBzD,GACjC,IAAI0D,EAEJ,OAAO1B,EAAO9B,IAAIF,KAAUgC,EAAO5B,IAAIJ,EAAM0D,EAAW,IAAIzB,EAAgBjC,IAAQ0D,EACtF,CCpGM,SAAUC,GACd7B,EACAuB,GAEA,GAAmC,IAA/BvB,EAAQ8B,mBACV,OAAO,KAET,MAAMC,EAAU/B,EAAQgC,iBACxB,GAAgB,OAAZD,EACF,OAAO,KAET,MAAME,EAA4BF,EAAQtB,SAASyB,oBAAoBX,GACvE,YAAqB,IAAVU,GAGe,OAAtBF,EAAQI,UAFH,KAKFC,EAAoBL,EAAQI,UAAWF,EAAOF,EAAQtB,SAASH,cACxE,CCxBM,SAAU+B,GAAYpE,EAA6B8D,GAMvD,QAA+B,IAA3B9D,EAAaqE,WAAqE,KAA/CP,EAAQtB,SAAS8B,YAAYC,WAAW,MAGxET,EAAQtB,SAASH,cAAgB,GACjCrC,EAAawE,YAAYtD,IAAI4C,EAAQtB,SAASL,MACvD,CC6BA,SAASsC,GACPzE,EACA8D,EACAY,EACAC,EACA5C,GAEA,MAAM6C,EAAQ5E,EAAa6E,aAC3B,GAAID,EAAO,CACT,MAAME,EAAUF,EAAMH,YACtB,IAAK,IAAI1B,EAAI,EAAGA,EAAI+B,EAAQ9B,OAAQD,IAAK,CACvC,MAAMgC,EAAUD,EAAQ/B,GAAG/C,EAAc8D,EAASY,EAAaC,EAAU5C,GACzE,GAAIgD,IAAYC,EAAa,OAAOD,CACtC,CACF,CACA,OAAOC,CACT,CAEA,SAASC,GACPC,EACApB,EACAa,EACA5C,EACA/B,GAGA,GADqB8D,EAAQtB,SAASJ,SAAS,KAC1B+C,EAEnB,OA1CJ,SAAuBC,EAAmBhD,GACxC,IAAIX,EAAa2D,EACjB,IAAK,IAAIrC,EAAI,EAAGA,EAAIX,EAASY,OAAQD,IAAK,CAExC,GAAIlC,OAAOY,KAAWA,EACpB,OAEFA,EAAQ4D,QAAQlF,IAAIsB,EAAOW,EAASW,GACtC,CACA,OAAOtB,CACT,CAgCW6D,CAAc7E,EAAoBT,GAAe8D,EAAQtB,SAASJ,UAI3E,KAAI0B,EAAQtB,SAASL,QAAQ+C,GAatB,CAML,GAA8B,OAA1BpB,EAAQyB,cAAwB,CAClC,MAAMT,EAAUL,GAAYzE,EAAc8D,EAAS,KAAMa,EAAU5C,GACnE,GAAI+C,IAAYE,EACd,OAAOF,EAETpD,EAAW8D,EAAuB1B,EAAQtB,SAASL,KAAM+C,EAAQlF,EAAawE,aAChF,CACA,MACME,EAAce,GAAaP,EADXpB,EAAQyB,cAC0BZ,EAAU5C,GAYlE,GAAI2C,QACF,OAEF,MAAMJ,EAAcR,EAAQtB,SAASJ,SAAS0B,EAAQtB,SAASJ,SAASY,OAAS,GAG3E4B,EAAQ5E,EAAa6E,aAC3B,GAAID,GAAsC,IAA7BA,EAAMH,YAAYzB,QAAgBsB,IAAgBoB,KACxDpB,KAAezD,OAAO6D,IAAe,CAC1C,MAAMI,EAAUL,GAAYzE,EAAc8D,EAASjD,OAAO6D,GAAcC,EAAU5C,GAClF,GAAI+C,IAAYE,EACd,OAAOF,CAEX,CACA,GAAIR,IAAgBoB,EAAU,CAK5B,MAAM1B,EAAQF,EAAQI,WAAWF,OAAStC,EACxCiE,EACE,SAAS7B,EAAQtB,SAASL,QAC1B2B,EAAQtB,SAASH,cACjByB,EAAQI,WAAWlB,QAAU,IAGjC,OAAOqC,QAAQlF,IAAIuE,EAAaV,EAClC,CACE,OAAOqB,QAAQlF,IAAIuE,EAAaJ,EAEpC,CAnEE,IAAItE,EAAawE,YAAYtD,IAAI4C,EAAQtB,SAASL,MAShD,OAAOkD,QAAQlF,IAAI+E,EAAQpB,EAAQtB,SAASL,MAR5CJ,EAAQ6D,YAAY9B,GACpB,IACE,OAAOuB,QAAQlF,IAAI+E,EAAQpB,EAAQtB,SAASL,KAAMwC,EACpD,SACE5C,EAAQ8D,YACV,CA8DN,CA2BM,SAAUJ,GACdP,EACApB,EACAa,EACA5C,GAOA+D,EAAgB/D,EAAS+B,IACiB,IAAtC/B,EAAQ/B,aAAa+F,cACvBhE,EAAQ/B,aAAagG,kBAAmBC,uBAAuBlE,EAAQ/B,aAAc8D,EAAQtB,UAE/F,MAAMxC,EAAe+B,EAAQ/B,aAEvB4E,EAAQ5E,EAAa6E,aAC3B,GAAID,EAAO,CACT,MAAMsB,EAAYtB,EAAMuB,KACxB,IAAK,IAAIpD,EAAI,EAAGA,EAAImD,EAAUlD,OAAQD,IAAK,CACzC,MAAMgC,EAAUmB,EAAUnD,GAAG/C,EAAc8D,EAASa,EAAU5C,GAC9D,GAAIgD,IAAYC,EAAa,OAAOD,CACtC,CACF,CAEA,OADkBX,GAAYpE,EAAc8D,GAlD9C,SACEoB,EACApB,EACAa,EACA5C,EACA/B,GAEA,MAAMoG,EAAaC,EAAYrG,EAAc8D,GACvCwC,EAAaC,EAAoCH,GAIjDI,EAAaxG,EAAayG,gBAChC,GAAmB,OAAfH,IAA4C,IAArBA,EAAWI,OAAmBJ,EAAWE,aAAeA,EACjF,OAAOF,EAAW7E,MAEpB,MAAMA,EAAQwD,GAAcC,EAAQpB,EAASa,EAAU5C,EAAS/B,GAMhE,OALA2G,EAAoCP,EAAY,CAC9C3E,MAAOA,EACPiF,OAAO,EACPF,WAAYA,IAEP/E,CACT,CA6BWmF,CAAuB1B,EAAQpB,EAASa,EAAU5C,EAAS/B,GAE3DiF,GAAcC,EAAQpB,EAASa,EAAU5C,EAAS/B,EAE7D,CCrKM,SAAU6G,GACd3B,EACAP,EACA5C,EACAS,EACAsE,EACAC,GAEA,MAAMC,EAAqD,IAAI5G,IAEzD6G,EAAsB,CAC1BC,EACAC,EACAjD,EACA4C,EACAM,EACAC,EACAC,KAEA,MAAMC,EAAyBL,EAAwBC,IAAqB,KAC5E,GAA+B,OAA3BI,EAEF,YADAD,EAAQpE,KAAKmE,GAGf,MAAMG,EAAkBC,EAAmBF,EAAwBrD,GAC7DwD,EAAqBrB,EAAYtE,EAAQ/B,aAAcwH,GACvDG,EAAWC,EAAqBF,GAChCG,EAAWpC,GAAaP,EAAQsC,EAAiB7C,EAAU5C,GAG3D+F,EAFWC,EACf7D,EAAWyD,EAAUE,GACMG,WACvBhE,EAAQ8C,EAAQM,IAAa,KAEnC,GADAJ,EAAkB3G,IAAIqH,EAAoBG,GAC5B,OAAV7D,EACF,IAAI,IAAIjB,EAAI,EAAGA,EAAI+E,EAAY9E,OAAQD,IAAK,CAC1C,MAAMmB,EAAY4D,EAAY/E,GAC9BkE,EACEC,EACAC,EAAmB,EACnBjD,EACA4C,EACAM,EAAW,EACXC,EAAcY,OAAO/D,EAAUF,OAC/BsD,EACJ,KACK,CAGL,MAAMpD,EAAY4D,EAAY9D,IAC5BtC,EAAW,gCAAgCsC,QAAYuD,EAAuBpF,QAC3EgF,EAAmB,EAAKD,EAAwBlE,OACnDiE,EACEC,EACAC,EAAmB,EACnBjD,EACA4C,EACAM,EAAW,EACXC,EAAcY,OAAO/D,EAAUF,OAC/BsD,GAIFA,EAAQpE,KAAKmE,EAAcY,OAAO/D,EAAUF,OAEhD,GAGIkE,EAA4B,GAUlC,GATAjB,EACEzE,EAAS0E,wBACT,EACA,KACAJ,EACA,EACA,GACAoB,GAEEnB,EAAQoB,mBACV,IAAI,MAAOrE,EAAS+D,KAAab,EAAkBoB,UACjDC,EAAqBvE,EAAS1C,MAAMkH,QAAQT,GAAYA,EAAW,IAGvE,OAAOK,CACT,CClHM,SAAUK,GACdrD,EACAP,EACA5C,EACAS,EACAsE,GAGA,IAAI5C,EAA+B,KACnC,IAAI,IAAInB,EAAI,EAAGA,EAAIP,EAAS0E,wBAAwBlE,OAAQD,IAAK,CAC/D,MAAMwE,EAAyB/E,EAAS0E,wBAAwBnE,GAE1DyF,EAAW/C,GAAaP,EADNuC,EAAmBF,EAAwBrD,GACZS,EAAU5C,GAC3D+F,EAAcW,EAAyBD,EAAUtE,GACpC,MAAf4D,GACFpG,EAAW,0BAA0B6F,EAAuBpF,QAE9D,MAAM6B,EAAQ8C,EAAQ/D,GAGtBmB,EAAY4D,EAAY9D,IACtBtC,EAAW,gCAAgCsC,QAAYuD,EAAuBpF,OAClF,CACA,OAAO+B,CACT,CCEA,SAASwE,GAAeC,EAAcxG,EAAcyG,EAAcC,GAC7C,iBAARF,GAA4B,OAARA,GAC7BjH,EACE,GAAGoH,WAA8B3G,OAAUyG,kBAAqBC,iCAChD,OAARF,EAAe,cAAgBA,OAG3C,MAAMI,EAAQlI,OAAOmI,eAAeL,GAChCI,IAAUlI,OAAOoI,WAAuB,OAAVF,GAChCrH,EACE,GAAGoH,WAA8B3G,OAAUyG,kBAAqBC,0FAItE,CAEA,SAASK,GAAMP,EAAUQ,EAAmBhH,EAAcyG,EAAcC,GACtE,MAAMO,EAAsB,mBAATD,EAAsBA,EAAKR,GAAOA,EAAIQ,GAOzD,OANIC,SACF1H,EACE,GAAGoH,WAA8B3G,OAAUyG,kBAAqBC,iBAC5C,mBAATM,EAAsB,eAAiB,UAAUA,iBAAoBE,OAAOD,QAGpFA,CACT,CAGA,SAASE,GAAYC,EAA0BJ,EAAmBhH,EAAcyG,GAC9E,MAAMY,EAAkB,IAAIpI,MAAMmI,EAAKvG,QACjCyG,EAAO,IAAIC,IACjB,IAAK,IAAI3G,EAAI,EAAGA,EAAIwG,EAAKvG,OAAQD,IAAK,CACpC,MAAM4F,EAAMY,EAAKxG,GACjB2F,GAAeC,EAAKxG,EAAMyG,EAAM7F,GAChC,MAAMqG,EAAMF,GAAMP,EAAKQ,EAAMhH,EAAMyG,EAAM7F,GACrC0G,EAAKvI,IAAIkI,IACX1H,EAAW,GAAGoH,WAA8B3G,qBAAwBwH,KAAKC,UAAUR,SAAWR,WAEhGa,EAAKI,IAAIT,GACTI,EAAKzG,GAAKqG,CACZ,CACA,OAAOI,CACT,CA+DM,SAAUM,GAAmBC,EAAaC,GAC9C,MAAMC,EAAwB,GAC9B,IAAK,MAAMC,KAASrJ,OAAO2I,KAAKQ,GACzBnJ,OAAOsJ,GAAGJ,EAAOG,GAAQF,EAAOE,KACnCD,EAAO/G,KAAK,CAAEgH,QAAOzI,MAAOuI,EAAOE,KAGvC,IAAK,MAAMA,KAASrJ,OAAO2I,KAAKO,GACzBlJ,OAAOuJ,OAAOJ,EAAQE,IAA2B,MAAjBH,EAAOG,IAC1CD,EAAO/G,KAAK,CAAEgH,QAAOzI,MAAO,OAGhC,OAAOwI,CACT,CC3JM,SAAUI,GACdnF,EACApB,EACAa,EACA5C,GAEA,GAAI+B,EAAQtB,SAASL,QAAQ+C,EAAQ,OAAO,EAC5C,MAAMK,EAAgBzB,EAAQyB,cAC9B,GAAsB,OAAlBA,EAAwB,OAAO,EACnC,MAAMb,EAAce,GAAaP,EAAQK,EAAeZ,EAAU5C,GAClE,GAAoB,OAAhB2C,GAAgD,iBAAhBA,GAAmD,mBAAhBA,EACrE,OAAO,EAET,MAAMJ,EAAcR,EAAQtB,SAAS8B,YACrC,GAAIA,IAAgBoB,EAAU,CAC5B,MAAM1B,EAAQF,EAAQI,WAAWF,MACjC,MAAwB,iBAAVA,GAAsBA,KAASU,CAC/C,CACA,OAAOJ,KAAeI,CACxB,CCrBA,MAAM4F,GAA6C,IAAIxK,QAMjD,SAAUyK,GAAkBhB,EAAciB,GAC7B,OAAbA,EACFF,GAAezI,OAAO0H,GAEtBe,GAAejK,IAAIkJ,EAAMiB,EAE7B,CCiCA,SAASC,GACPC,EACAC,EACAC,GAEA,MAAMC,EAAaH,EAAQI,oBAAoBH,GACzCI,EAAiBvH,EAAYqH,GAC7BtF,EAAgBkC,EAAmBsD,EAAgBH,GACnDI,EAAmB3E,EAAYqE,EAAQ1K,aAAcuF,GACrD0F,EAAYrD,EAAqBoD,GACjCnD,EAAW6C,EAAQQ,WAAWC,GAAoB5F,GAClD6F,EAAWrD,EACfxC,EAAcrB,UAAW+G,EAAWpD,GACtC6C,EAAQW,8BAA8BhL,IAAI2K,EAAkB5J,MAAMkH,QAAQT,GAAYA,EAAW,IAEjG,MAAMyD,EA/CR,SAAoBF,EAAqBG,GACvC,OAAQA,GACN,IAAK,MACH,OAAOH,EAASI,WAClB,IAAK,MACH,OAAOJ,EAASpD,WAClB,IAAK,MACH,OAAOoD,EAASK,YAClB,IAAK,SACH,OAAOL,EAASM,eAClB,IAAK,SACH,OAAON,EAASO,eAClB,QAIE,OAHIC,EAAOC,OACTC,QAAQC,IAAI,wBAAwBR,KAE/B,GAEb,CA6BsBS,CAAWZ,EAAUV,EAAQa,YACjD,GAAIZ,IAAyBD,EAAQuB,cAAcjJ,OAAS,EAC1D0H,EAAQwB,kBAAkBhJ,QAAQoI,QAElC,IAAI,MAAMpH,KAAaoH,EACrBb,GACEC,EACAC,EAAuB,EACvBzG,EAIR,CA8CA,MAAMiI,GAA8B,GAUpC,SAASC,GACP1B,EACA2B,EACAC,EACAC,EACAnB,GAEA,MAA8B,SAA1BV,EAAQ8B,eAGR9B,EAAQ1K,aAAayM,mBAAmBvL,IAAImL,GAFvC,CAAEK,SAAUtB,EAASpD,WAAY2E,UAAW,MAKnB,IAA9BvB,EAASK,YAAYmB,MAA+C,IAAjCxB,EAASM,eAAekB,KAExB,IAAjCxB,EAASO,eAAeiB,KAItBlC,EAAQmC,iBAAmBR,EACtB,CAAEK,SAAUP,GAAeQ,UAAW,MAExC,CAAED,SAAUtB,EAASpD,WAAY2E,UAAW,MAG9C,CAAED,SAAUP,GAAeQ,UAAW,MAExC,CAAED,SAAUtB,EAASK,YAAakB,UAAWvB,EAASM,eAC/D,CAEA,MAAMoB,GAAgC,GAqBtC,SAASC,GACPrC,EACAsC,EACAC,GAEA,MAAMC,EAAexC,EAAQ1K,aAAamN,0BAC1C,IAAKD,GAAsC,IAAtBA,EAAaN,KAChC,OAAOE,GAET,IAAIM,EAA6B,KACjC,MAAMC,EAASL,EAAeM,EAC9B,IAAK,MAAMnL,KAAQ+K,EAAc,CAC/B,GAAI/K,IAAS6K,IAAiB7K,EAAKoL,WAAWF,GAC5C,SAEF,MAAM7K,EAAWgB,EAAYrB,GAC7B,GAAIK,EAASH,gBAAkB4K,EAAY5K,cACzC,OAAO,MAER+K,IAAW,IAAIlK,KAAKV,EACvB,CACA,OAAO4K,GAAUN,EACnB,CAEA,SAASU,GACP9C,EACA+C,EACAC,GAKA,MAAMC,EAA2C,GAC3CC,EAAQlD,EAAQkD,MAEhBC,EAAU,CAAC/J,EAAwBgK,KACvC,IAAIC,EAAOH,EAAMzN,IAAI2D,EAAQtB,SAASL,OAAS2L,EAC3CC,EAAOD,IAGTC,EAAOD,IAERH,EAAQI,KAAU,IAAI7K,KAAKY,IAG9B+J,EAAQJ,EAAc,GAGtB,MAAMO,EAA+B,GAErC,IAAK,IAAID,EAAO,EAAGA,EAAOJ,EAAQ3K,OAAQ+K,IAAQ,CAChD,MAAME,EAASN,EAAQI,GACvB,QAAeG,IAAXD,EAIJ,IAAK,IAAIE,EAAS,EAAGA,EAASF,EAAOjL,OAAQmL,IAAU,CACrD,MAAMrK,EAAUmK,EAAOE,GACvB,IAAIzD,EAAQ0D,QAAQlN,IAAI4C,GAAxB,CAGA4G,EAAQ0D,QAAQvE,IAAI/F,GACpB4J,EAAS5J,GACTkK,EAAYhL,OAAS,EACrBqL,GAAqB3D,EAAS5G,EAASkK,GACvC,IAAK,IAAIjL,EAAI,EAAGA,EAAIiL,EAAYhL,OAAQD,IACtC8K,EAAQG,EAAYjL,GAAIgL,EAAO,EANjC,CAQF,CACF,CACF,CAOA,SAASM,GACP3D,EACA5G,EACAkK,GAEA,MAAM3B,EAAavI,EAAQtB,SAASL,KAO9BmM,EAAa5D,EAAQ6D,UAAUpO,IAAIkM,GACzC,GAAIiC,EACF,IAAI,MAAME,KAAOF,EAAY,CAC3B,MAAMrB,EAAczJ,EAAYgL,GAChC,GAAI9D,EAAQ+D,YAAYvN,IAAImL,IAAeY,EAAY3I,cAAgBoB,EAAU,CAE/E,MAAMmC,EAAW6C,EAAQQ,WAAWC,GAAoBrH,GAClDsC,EAAaC,EAAYqE,EAAQ1K,aAAc8D,GAC/CmH,EAAYrD,EAAqBxB,GACjCgF,EAAWrD,EACfjE,EAAQI,UAAW+G,EAAWpD,GAChC6C,EAAQW,8BAA8BhL,IAAI+F,EAAYhF,MAAMkH,QAAQT,GAAYA,EAAW,IAC3F,MAAM6G,EAAYtC,GAAuB1B,EAAS2B,EAAYpB,EAAWpD,EAAUuD,GACnF,IAAI,MAAMlH,KAAawK,EAAUhC,SAAU,CACzC,MAAMiC,EAAalH,EAAmBwF,EAAa/I,GACnDwG,EAAQ0C,OAAOvD,IAAI8E,GACnBX,EAAY9K,KAAKyL,EACnB,CACA,GAA4B,OAAxBD,EAAU/B,UAAoB,CAChC,MAAMiC,EAAiB7B,GAA0BrC,EAAS8D,EAAKvB,GAC/D,GAAuB,OAAnB2B,EAEF,IAAI,MAAM1K,KAAawK,EAAU/B,UAAW,CAC1C,MAAMgC,EAAalH,EAAmBwF,EAAa/I,GACnDwG,EAAQ0C,OAAOvD,IAAI8E,GACnBX,EAAY9K,KAAKyL,EACnB,MACK,GAAIC,EAAe5L,OAAS,EAEjC,IAAI,MAAMkB,KAAawK,EAAU/B,UAC/B,IAAI,MAAMnK,KAAYoM,EAAgB,CACpC,MAAMD,EAAalH,EAAmBjF,EAAU0B,GAChDwG,EAAQ0C,OAAOvD,IAAI8E,GACnBX,EAAY9K,KAAKyL,EACnB,CAKN,CACF,KAAO,CACL,MAAMA,EAAalH,EAAmBwF,EAAanJ,EAAQI,WAC3DwG,EAAQ0C,OAAOvD,IAAI8E,GACnBX,EAAY9K,KAAKyL,EACnB,CACF,CAiBF,MAAME,EAAcnE,EAAQoE,WAAW3O,IAAIkM,GAC3C,GAAIwC,EACF,IAAI,MAAML,KAAOK,EAAa,CAC5B,MAAM5B,EAAczJ,EAAYgL,GAC1B1G,EAAqC,GAC3C,GAAImF,EAAY5K,cAAgB,EAAG,CAIjC,MAAM0M,EAAcC,EAAgBlL,EAAQtB,SAAUyK,GAEtD,GADoBA,EAAY5K,cAAgB0M,GAAgB,EAChD,CACd,IAAI7K,EACA6K,EAAc,GAIU,OAAtBjL,EAAQI,WACVxC,EAAW,wEAAwEoC,EAAQtB,SAASL,QAEtG+B,EAAYC,EAAoBL,EAAQI,UAAY6K,EAAc,EAAGjL,EAAQtB,SAASH,gBAItF6B,EAAY,KAEd,MAAM+K,EAA+B,CACnCjP,aAAc0K,EAAQ1K,aACtBqL,8BAA+BX,EAAQW,8BAEvCa,kBAAmB,GACnBD,cAAegB,EAAYhB,cAC3BnB,oBAAqBmC,EAAYnC,oBACjCI,WAAYR,EAAQQ,WACpBK,WAAYb,EAAQa,YAEtBd,GAAoBwE,EAAeF,EAAa7K,GAChD4D,EAAY5E,QAAQ+L,EAAc/C,kBACpC,KAAO,CAGqB,OAAtBpI,EAAQI,WACVxC,EAAW,wEAAwEoC,EAAQtB,SAASL,QAEtG,MAAM+B,EAAYC,EAAoBL,EAAQI,UAAW6K,EAAc,EAAGjL,EAAQtB,SAASH,eAC3FyF,EAAY5E,KAAKgB,EACnB,CACF,MAGE4D,EAAY5E,KAAK,MAEnB,IAAI,MAAMgB,KAAa4D,EAAa,CAClC,MAAM6G,EAAalH,EAAmBwF,EAAa/I,GACnDwG,EAAQ0C,OAAOvD,IAAI8E,GACnBX,EAAY9K,KAAKyL,EACnB,CACF,CAEJ,UA2BgBO,GACdlP,EACAyN,EACA0B,EACAC,EACAX,EACAvD,EACAK,EACAmC,EACA3G,GAuBA,MAAMsI,EAAY5B,EAAajL,SAASL,KACxC,IAAKgN,EAAiBjO,IAAImO,KAAeD,EAAkBlO,IAAImO,GAE7D,OADA3B,EAASD,GACF,GAKT,MAAMG,EC/bF,SACJyB,EACAd,EACAO,EACAQ,GAGA,MAAMC,EAAmC,IAAInP,IACvCoP,EAAgC,IAAIpP,IACpCqP,EAAoB,CAACJ,GAE3B,IADAG,EAASnP,IAAIgP,EAAW,GACjBI,EAAQzM,OAAS,GAAG,CACzB,MAAMb,EAAOsN,EAAQC,MACrB,GAAIH,EAAUrO,IAAIiB,GAChB,SAEF,MAAMmM,EAAaC,EAAUpO,IAAIgC,GAC3B0M,EAAcC,EAAW3O,IAAIgC,GACnC,IAAIwN,EAEFA,OADiBzB,IAAfI,EACKO,GAAe,QACGX,IAAhBW,EACFP,EAEAA,EAAWrG,OAAO4G,GAE3BU,EAAUlP,IAAI8B,EAAMwN,GACpB,IAAK,IAAI5M,EAAI,EAAGA,EAAI4M,EAAK3M,OAAQD,IAAK,CACpC,MAAMyL,EAAMmB,EAAK5M,GACjByM,EAASnP,IAAImO,GAAMgB,EAASrP,IAAIqO,IAAQ,GAAK,GACxCe,EAAUrO,IAAIsN,IACjBiB,EAAQvM,KAAKsL,EAEjB,CACF,CAKA,MAAMZ,EAA6B,IAAIxN,IACjCwP,EAAuB,IAAIlG,IAC3BmG,EAAkB,GACxB,IAAK,MAAO1N,EAAM2N,KAAWN,EACZ,IAAXM,IACFlC,EAAMvN,IAAI8B,EAAM,GAChByN,EAAQ/F,IAAI1H,GACZ0N,EAAM3M,KAAKf,IAGf,IAAK,IAAIY,EAAI,EAAGA,EAAI8M,EAAM7M,OAAQD,IAAK,CACrC,MAAMZ,EAAO0N,EAAM9M,GACbgN,EAAWnC,EAAMzN,IAAIgC,GAAS,EAChC4N,EAAWT,GACb5N,EAAW,+BAA+B4N,8DAAqEnN,KAEjH,MAAMwN,EAAOJ,EAAUpP,IAAIgC,GAC3B,IAAK,IAAI6N,EAAI,EAAGA,EAAIL,EAAK3M,OAAQgN,IAAK,CACpC,MAAMxB,EAAMmB,EAAKK,GACbD,GAAYnC,EAAMzN,IAAIqO,KAAQ,IAChCZ,EAAMvN,IAAImO,EAAKuB,GAEjB,MAAME,EAAYT,EAASrP,IAAIqO,GAAQ,EACvCgB,EAASnP,IAAImO,EAAKyB,GACA,IAAdA,IACFL,EAAQ/F,IAAI2E,GACZqB,EAAM3M,KAAKsL,GAEf,CACF,CAMA,GAAIoB,EAAQhD,OAAS2C,EAAU3C,KAAM,CACnC,IAAIsD,GAAU,EACd,IAAK,MAAM/N,KAAQyN,EAAS,CAC1B,MAAM7B,EAAOH,EAAMzN,IAAIgC,GACnB4L,EAAOmC,IACTA,EAAUnC,EAEd,CACA,MAAMoC,EAAYD,EAAU,EAC5B,IAAK,MAAM/N,KAAQoN,EAAU/F,OACtBoG,EAAQ1O,IAAIiB,IACfyL,EAAMvN,IAAI8B,EAAMgO,EAGtB,CACA,OAAOvC,CACT,CDqWgBwC,CAAoBf,EAAWF,EAAkBC,EA7bpC,KA8brB1E,EAAmB,CACvBkD,MAAOA,EACP5N,aAAcA,EACdqL,8BAA+B,IAAIjL,IACnCmO,UAAWY,EACXL,WAAYM,EACZhC,OAAQ,IAAI1D,IACZ+E,YAAaA,EACbL,QAAS,IAAI1E,IACbwB,WAAYA,EACZK,WAAYA,EACZiB,cAAezF,GAASyF,eAAiB,OACzCK,eAAgB9F,GAAS8F,gBAAkB,MAE7CW,GAAgB9C,EAAS+C,EAAcC,GAnEzC,SAAwBhD,EAAkBgD,GACxC,IAAK,IAAI2C,EAAQ,EAAGA,EA1YO,IA0YuBA,IAAS,CACzD,MAAMZ,EAAUa,EAAqB5F,EAAQ1K,cAC7C,GAAgB,OAAZyP,EACF,OAEFA,EAAQc,QAASnK,IACfoH,GAAgB9C,EAASjD,EAAmBrB,EAAWoK,iBAAiBhO,SAAU4D,EAAWlC,WAAYwJ,IAE7G,CACF,CA0DE+C,CAAe/F,EAASgD,GAIxB,IAAK,MAAOtH,EAAY3E,KAAUiJ,EAAQW,8BACxChD,EAAqBjC,EAAY3E,GAEnC,OAAOL,MAAMC,KAAKqJ,EAAQ0C,OAC5B,CEhbA,SAASsD,GACP1Q,EACAmC,EACAiE,EACAuB,EACAgJ,GAEA,MAAM/L,EAAQ5E,EAAa6E,aAC3B,GAAID,EAAO,CACT,MAAMgM,EAAYhM,EAAMiM,aACxB,IAAK,IAAI9N,EAAI,EAAGA,EAAI6N,EAAU5N,OAAQD,IACpC6N,EAAU7N,GAAG/C,EAAcmC,EAAMiE,EAAYuB,EAAUgJ,EAE3D,CACF,CAIA,SAASG,GAAc9Q,EAA6CwC,EAAqCuO,GACvG,MAAMnM,EAAQ5E,EAAa6E,aAC3B,GAAID,EAAO,CACT,MAAMoM,EAAUpM,EAAMoM,QACtB,IAAK,IAAIjO,EAAI,EAAGA,EAAIiO,EAAQhO,OAAQD,IAClCiO,EAAQjO,GAAG/C,EAAcwC,EAAUuO,EAEvC,CACF,CAEA,SAASE,GAAcjR,EAA6CkR,EAA0CC,GAC5G,MAAMvM,EAAQ5E,EAAa6E,aAC3B,GAAID,EAAO,CACT,MAAMwM,EAAUxM,EAAMwM,QACtB,IAAK,IAAIrO,EAAI,EAAGA,EAAIqO,EAAQpO,OAAQD,IAClCqO,EAAQrO,GAAG/C,EAAckR,EAAmBC,EAEhD,CACF,CAWA,SAASE,GACPrR,EACAmC,EACAwO,EACAhJ,EACAlG,EACA6P,GAEA,MAAMC,EAASC,EAAmBxR,EAAcmC,GAC1CsP,EAAcC,EAAoB1R,EAAcmC,GACtD,IAAKoP,IAAWE,EACd,OAAO,KAET,MAAME,EAAuC,GACvC9D,EAAU+D,GAAmBD,GAOnC,OANIJ,GACFM,EAAgB7R,EAAcmC,EAAMwO,EAAahJ,EAAUlG,GAAO8O,QAAQ1C,GAExE4D,GACFK,EAA0B9R,EAAcmC,EAAMwO,EAAchJ,EAAW2J,IAAW7P,GAAO8O,QAAQ1C,GAE5F8D,CACT,CAGA,SAASI,KACP,OAAOnG,EAAOoG,yBAA4BC,KAAkC,KAAQ,IACtF,CAGA,SAASL,GAAmBM,GAC1B,MAAMC,EAAUC,IACV1H,EAAUqH,KAChB,OAAQ3L,IACNiM,EAAsCjM,GACtC+L,EAAQG,uBAAuBlM,EAAYsE,GAC3CwH,EAAUhP,KAAKkD,GAEnB,CAoBA,SAASmM,GACPZ,EACAhN,EACA5C,GAEA,GAAoB,OAAhB4P,GAA+C,IAAvBA,EAAY3O,OACtC,OAEF,MAAMhD,EAAe+B,EAAQ/B,aACvBmP,EAAmBnP,EAAamP,iBAChCC,EAAoBpP,EAAaoP,kBACjC+C,EAAUC,IACV1H,EAAUqH,KAChB,IAAK,IAAIhP,EAAI,EAAGA,EAAI4O,EAAY3O,OAAQD,IAAK,CAC3C,MAAMyP,EAAWb,EAAY5O,GAAGyN,iBAC1BrO,EAAOqQ,EAAShQ,SAASL,KAE/B,IAAKgN,EAAiBjO,IAAIiB,KAAUiN,EAAkBlO,IAAIiB,GACxD,SAEF,MAAM2B,EAAU2D,EAAmB+K,EAAShQ,SAAUmP,EAAY5O,GAAGmB,WACrEgL,GACElP,EACA8D,EACAqL,EACAC,EACApP,EAAayS,UACb9N,EACA,MACCgK,IAEC,GAAIA,IAAe7K,EAAS,OAC5B,MAAM4O,EAAgBrM,EAAYrG,EAAc2O,GAChD0D,EAAsCK,GACtCP,EAAQG,uBAAuBI,EAAehI,IAIhD,CAAE8B,cAAe,QAErB,CACF,CAaM,SAAUmG,GACd3S,EACAmC,EACAyQ,EACAjO,EACA5C,GAEA,MAAMwP,EAASC,EAAmBxR,EAAcmC,GAC1CsP,EAAcC,EAAoB1R,EAAcmC,GACtD,IAAKoP,IAAWE,EACd,OAEF,MAAMoB,EAAUD,IACVjB,EAAuC,GACvC9D,EAAU+D,GAAmBD,GAC/BJ,GACFM,EAAgB7R,EAAcmC,GAAM,OAAO+L,EAAW2E,GAAStC,QAAQ1C,GAErE4D,GACFK,EAA0B9R,EAAcmC,OAAM+L,EAAW2E,GAAS,GAAOtC,QAAQ1C,GAInF0E,GAAoBZ,EAAahN,EAAU5C,EAC7C,CAEA,SAAS+Q,GACPhP,EACAsC,EACAzB,EACA5C,EACA8K,EACAkG,EACAvG,EAAiC,QAEjC,MAAMwG,EAAqBpH,EAAOoG,yBAC7BC,KAAkCgB,MACnC,KACEd,EAAUC,IAChBD,EAAQG,uBAAuBlM,EAAY4M,GAQvCD,GACFV,EAAsCjM,GAGxC8I,GACEnN,EAAQ/B,aACR8D,EACA/B,EAAQ/B,aAAamP,iBACrBpN,EAAQ/B,aAAaoP,kBACrBrN,EAAQ/B,aAAayS,UACrB9N,EACA,MACCgK,IAEC,GAAIA,IAAe7K,EAAS,OAC5B,MAAM4O,EAAgBrM,EAAYtE,EAAQ/B,aAAc2O,GACxD0D,EAAsCK,GAEtCP,EAAQG,uBAAuBI,EAAeM,IAIhD,CAAExG,gBAAeK,kBAErB,CAiBA,SAASqG,GACPlT,EACAmC,EACAiE,EACA3E,EACAsR,GAEKA,IAGD/S,EAAawE,YAAYtD,IAAIiB,GAC/BkQ,EAAsCjM,GAGxCO,EAAoCP,EAAY,CAC9C3E,MAAOA,EACPiF,OAAO,EAGPF,WAAYxG,EAAayG,kBAE7B,CAEA,SAAS0M,GACPjO,EACApB,EACAsC,EACA3E,EACAkD,EACA5C,EACA8K,EACAkG,GAEA,IACE,KAAIjP,EAAQtB,SAASL,QAAQ+C,GAmBtB,CACL,MAAMK,EAAgBzB,EAAQyB,cAC9B,GAAsB,OAAlBA,EACF,OAAOF,QAAQhF,IAAI6E,EAAQpB,EAAQtB,SAASL,KAAMV,GAEpD,MAAMiD,EAAce,GAAaP,EAAQK,EAAeZ,EAAU5C,GAC5DuC,EAAcR,EAAQtB,SAASJ,SAAS0B,EAAQtB,SAASJ,SAASY,OAAS,GACjF,GAAIsB,IAAgBoB,EAAU,CAE5B,MAAM1B,EAAQF,EAAQI,WAAWF,OAAStC,EACxCiE,EACE,SAAS7B,EAAQtB,SAASL,QAC1B2B,EAAQtB,SAASH,cACjByB,EAAQI,WAAWlB,QAAU,IAGjC,OAAOqC,QAAQhF,IAAIqE,EAAaV,EAAOvC,EACzC,CAGE,OAAO4D,QAAQhF,IAAIqE,EAAaJ,EAAa7C,EAEjD,CAxCE,IAAIM,EAAQ/B,aAAaoT,YAAYlS,IAAI4C,EAAQtB,SAASL,MAgBxD,OAAOkD,QAAQhF,IAAI6E,EAAQpB,EAAQtB,SAASL,KAAMV,GAVlDM,EAAQ6D,YAAY9B,GACpB/B,EAAQsR,eACR,IACE,OAAOhO,QAAQhF,IAAI6E,EAAQpB,EAAQtB,SAASL,KAAMV,EAAOkD,EAC3D,SACE5C,EAAQuR,aACRvR,EAAQ8D,YACV,CA4BN,SACEiN,GAAYhP,EAASsC,EAAYzB,EAAU5C,EAAS8K,EAAgBkG,EACtE,CACF,CAEA,SAASQ,GACPrO,EACApB,EACAsC,EACA3E,EACAkD,EACA5C,EACA8K,EACAkG,GAGA,MAAMxN,EAAgBzB,EAAQyB,eAAiB7D,EAAW,4CAA4CoC,EAAQtB,SAASL,QACjHuC,EAAce,GAAaP,EAAQK,EAAeZ,EAAU5C,IAAY,GAC9E,IAAIyI,GHnY4BjB,EGmYC7E,EHlY1B4F,GAAenK,IAAIoJ,IAAS,MAD/B,IAA4BA,EGoYhC,GAAiB,OAAbiB,EAAmB,CACrB,MAAM1C,EAAc0L,EAAqB9O,IAAgB,GACzD8F,EAAW,CACT/I,MAAO,IAAIiD,GAAcoD,YAAa,IAAIA,IAE5CyC,GAAkB7F,EAAa8F,EACjC,CACA,IACE,OAAO2I,GAAcjO,EAAQpB,EAASsC,EAAY3E,EAAOkD,EAAU5C,EAAS8K,EAAgBkG,EAC9F,SACE,MAAM/O,EAAQwG,EAAS/I,MAAMgS,QAAQhS,GAC/BiS,EAAqBjO,GAAaP,EAAQK,EAAeZ,EAAU5C,IAAY,GAC/E4R,EAAqBvS,MAAMkH,QAAQoL,GAAuBF,EAAqBE,IAAuB,GAAM,GAC5GE,EAAW9P,EAAQI,UAAWF,MAC9BE,GAAuB,IAAVF,EACjBwG,EAAU1C,YAAY9D,GACtB6P,EAAgBtO,EAAcrB,cAChCyP,EAAmBC,GAAY1P,EAI/B,GADqB,IAAIwF,IAAIgK,GACZ9G,OAASpC,EAAU/I,MAAMuB,OAAQ,CAChD,IAAI,IAAID,EAAI,EAAGA,EAAI4Q,EAAmB3Q,OAAQD,IAC5C4Q,EAAmB5Q,GAAGiB,MAAQjB,EAGhCwH,GAAkB7F,EAAa,MA+BrC,SACEa,EACAiF,EACAkJ,EACAC,EACAhP,EACA5C,GAEA,MAAM/B,EAAe+B,EAAQ/B,aACvBmS,EAAUC,IACV0B,EAAiBzN,EAAYrG,EAAcuF,GAC7CwO,EAAuCD,KAAoBJ,IAC7DM,EAAqBxJ,EAAS/I,MAAO+I,EAAS1C,aAC9CmM,EAAuCH,EAAgBtJ,EAAS/I,OAChEyS,EAAqB1J,EAAS/I,QAEhC0Q,EAAQgC,yBAAyBL,GAEjC,MAAMM,EAAiB,IAAIhU,IAC3BoK,EAAS1C,YAAYyI,QAAQ,CAACrM,EAAW2E,IAAauL,EAAe/T,IAAI6D,EAAW2E,IACpF,MAAMwL,EAAkB7Q,EAAY+B,EAAc/C,SAASL,KAAOmL,EAAY5H,GAC9E,IAAK,IAAImD,EAAW,EAAGA,EAAW8K,EAAmB3Q,OAAQ6F,IAAY,CACvE,MAAM3E,EAAYyP,EAAmB9K,GAC/ByL,EAASF,EAAejU,IAAI+D,GAClC,GAAIoQ,IAAWzL,EACb,SAEF,MAAM0L,EAAiB9M,EAAmB4M,EAAiBnQ,GACrDgN,EAAoB7K,EAAYrG,EAAcuU,GACpD,QAAsB,IAAXD,EAAwB,CACjC,MAAMnD,EAAsBqD,EAAkBxU,EAAcqU,EAAiB7J,EAAS1C,YAAYe,IAAa,MAC/GoI,GAAcjR,EAAckR,EAAmBC,GAG/C2B,GACEyB,EAAgBrD,EAAmBvM,EAAU5C,EAAS,KACtDqC,GAAYpE,EAAcuU,GAAiB,QAE7C,QACF,CACArF,GACElP,EACAuU,EACAvU,EAAamP,iBACbnP,EAAaoP,kBACbpP,EAAayS,UACb9N,EACA,MACCgK,IACC,MAAM8F,EAAgBpO,EAAYrG,EAAc2O,GAChD0D,EAAsCoC,GACtCtC,EAAQgC,yBAAyBM,IAEnC,CAAEjI,cAAe,QAErB,CACF,CAtFMkI,CAAkBnP,EAAeiF,EAAUkJ,EAAoBC,EAAoBhP,EAAU5C,EAC/F,CACF,CACF,CAuJM,SAAU4S,GACZzP,EACApB,EACArC,EACAkD,EACA5C,GAEF,MAAM6S,EAAW7S,EAAQ/B,aAAa4U,SACtC,GAAgB,MAAZA,GAAoBxT,MAAMkH,QAAQ7G,GAAQ,CAC5C,MAAMoT,EAAUD,EAASzU,IAAI2D,EAAQtB,SAASL,MAC9C,QAAuB,IAAZ0S,EAAyB,CAClC,MAAMlN,EAAWlC,GAAaP,EAAQpB,EAASa,EAAU5C,GACnD+S,EL5eN,SACJ3S,EACAgH,EACAxB,EACAoN,GAIA,MAAMC,EAAU1L,GAAYyL,EAAS5L,EAAMhH,EAAM,OACjD,IAAKf,MAAMkH,QAAQX,IAAiC,IAApBA,EAAS3E,QAAmC,IAAnB+R,EAAQ/R,OAC/D,OAAO,KAET,MAAMiS,EAA8BtN,EAC9BuN,EAAU5L,GAAY2L,EAAS9L,EAAMhH,EAAM,WAC3CgT,EAAc,IAAI/U,IACxB,IAAK,IAAI2C,EAAI,EAAGA,EAAIkS,EAAQjS,OAAQD,IAClCoS,EAAY9U,IAAI6U,EAAQnS,GAAIkS,EAAQlS,IAGtC,MAAMwG,EAAkB,IAAInI,MAAM2T,EAAQ/R,QACpCoS,EAA4B,GAClC,IAAK,IAAIrS,EAAI,EAAGA,EAAIgS,EAAQ/R,OAAQD,IAAK,CACvC,MAAMiH,EAAS+K,EAAQhS,GACjBgH,EAASoL,EAAYhV,IAAI6U,EAAQjS,SACjB,IAAXgH,GAA0BA,IAAWC,GAMhDT,EAAKxG,GAAKgH,EACVqL,EAAQlS,KAAK,CAAE2F,SAAU9F,EAAGgH,SAAQC,YAJlCT,EAAKxG,GAAKiH,CAKd,CACA,OAAOoL,EAAQpS,OAAS,EAAI,CAAEuG,OAAM6L,WAAY,IAClD,CK0coBC,CAAevR,EAAQtB,SAASL,KAAM0S,EAASlN,EAAUlG,GACvE,GAAc,OAAVqT,EAEF,OAlER,SACI5P,EACApB,EACAgR,EACAG,EACAtQ,EACA5C,GAEF,MAAMuT,EAAWxR,EAAQtB,SAASL,KAW5BoT,EAAsBzR,EAAQI,UACE,OAAlCsP,EAAqByB,IAGvBlN,EAAewN,EAAqB,KAAMN,GAE5C,MAAMO,EAAOzN,EAAewN,EAAqBN,EAASH,EAAMvL,MAC1D6D,EAASqI,GAAiBvQ,EAAQpB,EAASgR,EAAMvL,KAAM5E,EAAU5C,EAASuT,GAC1EjB,EAAkB7Q,EAAY8R,EAAWhI,EAAY5H,GAC3D,IAAK,MAAMgQ,KAASZ,EAAMM,QAAS,CACjC,MAAMO,EAAc7L,GAAmB4L,EAAM3L,OAAQ2L,EAAM1L,QAC3D,GAA2B,IAAvB2L,EAAY3S,OACd,SAMF,MAAMkB,EAAoCsR,EAAKxN,WAAW0N,EAAM7M,UAChE,IAAK,MAAM+M,KAASD,EAAa,CAC/B,QAAyB,IAAdzR,EAA2B,CACpCwR,EAAM3L,OAAO6L,EAAM1L,OAAS0L,EAAMnU,MAClC,QACF,CACA,MAAMoU,EAAgBrS,EAAY6Q,EAAgBlS,KAAOmL,EAAYsI,EAAM1L,OAE3EyK,GAAazP,EADQuC,EAAmBoO,EAAe3R,GACpB0R,EAAMnU,MAAOkD,EAAU5C,EAC5D,CACF,CACA,OAAOqL,CACT,CAiBe0I,CAAsB5Q,EAAQpB,EAASgR,EAAOnN,EAAgChD,EAAU5C,EAEnG,CACF,CACA,OAAO0T,GAAiBvQ,EAAQpB,EAASrC,EAAOkD,EAAU5C,EAAS,KACrE,CAEA,SAAS0T,GACLvQ,EACApB,EACArC,EACAkD,EACA5C,EACA8K,GAEF,MAAM7M,EAAe+B,EAAQ/B,aACvBmC,EAAO2B,EAAQtB,SAASL,KAExByC,EAAQ5E,EAAa6E,aAC3B,GAAID,EAAO,CACT,MAAMmR,EAAanR,EAAMgR,MACzB,IAAK,IAAI7S,EAAI,EAAGA,EAAIgT,EAAW/S,OAAQD,IAAK,CAC1C,MAAMgC,EAAUgR,EAAWhT,GAAG/C,EAAc8D,EAASrC,EAAOkD,EAAU5C,GACtE,GAAIgD,IAAYC,EAAa,OAAOD,CACtC,CACF,CAMA,MAAMiR,EAAqBC,IAO3B,KAAM9T,KAAQ+C,IAAqC,OAA1BpB,EAAQyB,gBAA2BvF,EAAakW,aAAahV,IAAIiB,GAAO,CAC/F,MAAMuC,EAAce,GAAaP,EAAQpB,EAAQyB,cAAeZ,EAAU5C,GAC1E,GAA2B,iBAAhB2C,GAA4C,OAAhBA,EAAsB,CAG3D,MAAMJ,EAAcR,EAAQtB,SAAS8B,YAC/B8E,EAA+B9E,IAAgBoB,EACjD5B,EAAQI,WAAWF,MACnBM,EACJ,IAAI6R,EACAC,GAAiB,EACrB,IAAKJ,GAAsBpK,EAAOyK,iBAA6B,OAAV5U,GAAmC,iBAAVA,GAAqB,CAEjG,MAAMP,OAAcgN,IAAR9E,GAAqBA,KAAO1E,EAClCiD,OAAmBuG,IAAR9E,EAAqB1E,EAA6C0E,QAAO8E,EAC1F,GAAIhN,GAAOL,OAAOsJ,GAAGxC,EAAUlG,GAC7B,OAAO,EAET0U,EAAcxO,EACdyO,GAAiB,CACnB,CAIA,MAAME,EAAmBjF,GAAYrR,EAAcmC,EAAMiU,EAAgBD,EAAa1U,EACpF,IAAOiD,EAA6C0E,IAChD2J,EAAY3O,GAAYpE,EAAc8D,GACtCsC,EAAaC,EAAYrG,EAAc8D,GACxB,OAAjByS,GACFA,EAAa,CACXC,KAAM,cACNC,gBAAiBrQ,EACjB3E,QACAkG,SAAUwO,EACVxF,YAAayF,IAGjB1F,GAAwB1Q,EAAcmC,EAAMiE,EAAY+P,EAAaC,GACrE,IAAIM,GAAmB,EACvB,IAaE,QAZYxI,IAAR9E,GAGF1H,EAAWiE,EACT,SAASxD,KACT2B,EAAQtB,SAASH,cACjByB,EAAQI,WAAWlB,QAAU,IAM7B4B,GAAuC,IAA9BA,EAAM+R,aAAa3T,QAAgBsB,IAAgBoB,KAAc0D,KAAO1E,GAAc,CACjG,MAAMI,EAAUF,EAAM+R,aACtB,IAAK,IAAI5T,EAAI,EAAGA,EAAI+B,EAAQ9B,OAAQD,IAAK,CACvC2T,GAAmB,EACnB,MAAM3R,EAAUD,EAAQ/B,GAAG/C,EAAc8D,EAASY,EAAa0E,EAAK3H,EAAOkD,EAAU5C,GACrF,GAAIgD,IAAYC,EACd,OAAOD,EAET2R,GAAmB,CACrB,CACF,CACA,OAAOrR,QAAQhF,IAAIqE,EAAa0E,EAAK3H,EACvC,SACEqR,GAAYhP,EAASsC,EAAYzB,EAAU5C,EAAS8K,EAAgBkG,GACpER,GAAoB+D,EAAkB3R,EAAU5C,GAC5C2U,EAGFrE,EAAsCjM,GAEtC8M,GAAiBlT,EAAcmC,EAAMiE,EAAY3E,EAAOsR,GAE1DjC,GAAc9Q,EAAc8D,EAAQtB,SAAU,CAAEf,SAClD,CACF,CACF,CASA,IAAI0U,EACAC,GAAiB,EACrB,IAAKJ,GAAsBpK,EAAOyK,iBAA6B,OAAV5U,GAAmC,iBAAVA,GAAqB,CACjG,MAAMkG,EAAWlC,GAAaP,EAAQpB,EAASa,EAAU5C,GACzD,GAAIsI,GAAanF,EAAQpB,EAASa,EAAU5C,IAAYlB,OAAOsJ,GAAGxC,EAAUlG,GAC1E,OAAO,EAET0U,EAAcxO,EACdyO,GAAiB,CACnB,CAEA,MAAME,EAAmBjF,GAAYrR,EAAcmC,EAAMiU,EAAgBD,EAAa1U,EAAO,IAAMgE,GAAaP,EAAQpB,EAASa,EAAU5C,IAErI6U,EAAc5W,EAAakW,aAAahV,IAAI4C,EAAQtB,SAASL,MAC7D4Q,EAAY3O,GAAYpE,EAAc8D,GACtCsC,EAAaC,EAAYrG,EAAc8D,GACxB,OAAjByS,GACFA,EAAa,CACXC,KAAM,cACNC,gBAAiBrQ,EACjB3E,QACAkG,SAAUwO,EACVxF,YAAayF,IAGjB1F,GAAwB1Q,EAAcmC,EAAMiE,EAAY+P,EAAaC,GACrE,IACE,OAAIQ,EACKrD,GAAsBrO,EAAQpB,EAASsC,EAAY3E,EAAOkD,EAAU5C,EAAS8K,EAAgBkG,GAE7FI,GAAcjO,EAAQpB,EAASsC,EAAY3E,EAAOkD,EAAU5C,EAAS8K,EAAgBkG,EAEhG,SAGER,GAAoB+D,EAAkB3R,EAAU5C,GAK3C6U,GACH1D,GAAiBlT,EAAcmC,EAAMiE,EAAY3E,EAAOsR,GAE1DjC,GAAc9Q,EAAc8D,EAAQtB,SAAU,CAAEf,SAClD,CACF,CC7tBM,SAAUoV,GACd3R,EACA4R,EACAnS,EACA5C,GAEA,MAAO,CAACI,EAAc2E,KAAsBrF,KAGrCL,MAAMkH,QAAQxB,IACjBpF,EACE,aAAaS,0FACE,OAAZ2E,EAAmB,cAAgBA,GAAtC,KAKArF,EAAMuB,OAAS,GACjBtB,EACE,aAAaS,6EACV,EAAIV,EAAMuB,WAGjB,MAAMR,EAAWgB,EAAYrB,GAC7B,GAAIJ,EAAQ8B,mBAAqB,EAAG,CAClC,MAAMkT,EAAWhV,EAAQgC,kBAAkBvB,UAAY,KACjDxC,EAAe+B,EAAQ/B,aACZ,OAAb+W,GAAqBA,EAAS5U,OAASK,EAASL,MAE9CnC,EAAawE,YAAYtD,IAAI6V,EAAS5U,OACxCnC,EAAagX,qBAAqBxU,EAASL,KAAM4U,EAAS5U,KAGhE,CAMI2E,EAAQ9D,SAAWR,EAAS0E,wBAAwBlE,QACtDtB,EAAWuV,EAAkB,WAAY9U,EAAMK,EAAS0E,wBAAwBlE,OAAQ8D,EAAQ9D,SAGlG,MAAMkB,EAAYqE,GAAsBrD,EAAQP,EAAU5C,EAASS,EAAUsE,GAGvEhD,EAAU2D,EAAmBjF,EAAU0B,GAE7C,GAAqB,IAAjBzC,EAAMuB,OACR,OAAOyC,GAAaP,EAAQpB,EAASa,EAAU5C,GAE/CD,EAAeC,GACf4S,GAAazP,EAAQpB,EAASrC,EAAM,GAAIkD,EAAU5C,GAGxD,CC5DM,SAAUmV,GACdhS,EACAlE,EACA2D,EACA5C,GAEE,MAAMoV,EAAYN,GAAQ3R,EAAQlE,EAAM2D,EAAU5C,GAClD,MAAO,CAACI,EAAc2E,KAEpB,MAAMtE,EAAWgB,EAAYrB,GAU7B,QAPuB,IAAZ2E,GAA4B1F,MAAMkH,QAAQxB,IACnDpF,EACE,YAAYS,gIAEG,OAAZ2E,EAAmB,cAAgBA,GAAtC,KAGA/E,EAAQ8B,mBAAqB,EAAG,CAClC,MAAMkT,EAAWhV,EAAQgC,kBAAkBvB,UAAY,KACjDxC,EAAe+B,EAAQ/B,aACZ,OAAb+W,GAAqBA,EAAS5U,OAASK,EAASL,MAE9CnC,EAAawE,YAAYtD,IAAI6V,EAAS5U,OACxCnC,EAAagX,qBAAqBxU,EAASL,KAAM4U,EAAS5U,KAGhE,CAUA,QAHuB,IAAZ2E,GAA2BA,EAAQ9D,OAASR,EAAS0E,wBAAwBlE,QACtFtB,EAAWuV,EAAkB,UAAW9U,EAAMK,EAAS0E,wBAAwBlE,OAAQ8D,EAAQ9D,cAE1E,IAAZ8D,EAAyB,CAQlC,IAAK,IAAI/D,EAAIP,EAASyJ,cAAcjJ,OAAS,EAAGD,GAAK,EAAGA,IAAK,CAC3D,MAAMmB,EAAYN,GAAoB7B,EAASS,EAASyJ,cAAclJ,IACtE,GAAImB,EAAW,CACb4C,EAAUsQ,EAAiBlT,EAAWA,EAAUlB,QAChD,KACF,CACF,CACA,QAAuB,IAAZ8D,EAAyB,CAIlC,MAAMuQ,EAActV,EAAQ8B,mBAAqB,EAAI9B,EAAQgC,iBAAmB,KAC1EuT,EAAmBD,GAAanT,WAAa,KAC/C1B,EAASH,cAAgB,GAAqB,OAAhBgV,GAA6C,OAArBC,GACtDA,EAAiBtU,OAAS,GAC5BtB,EAAW6V,EAA6BpV,EAAMkV,EAAY7U,SAASL,OAErE2E,EAAU,EACZ,CACF,CAEA,MAAMoB,EAAgBrB,GACpB3B,EAAQP,EAAU5C,EAASS,EAAUsE,EAAS,CAAEqB,oBAAoB,IAChEqP,EAAsB,GAC5B,IAAI,IAAIzU,EAAI,EAAGA,EAAImF,EAAclF,OAAQD,IACvCyU,EAAatU,KAAKiU,EAChB3U,EAASL,KACT+F,EAAcnF,KAGlB,OAAOyU,EAEX,CC5EI,SAAUC,GACdvS,EACAwS,EACA/S,EACA5C,GAEA,MAAMS,EAAWkV,EAAgBlV,SACjC,OAAQkV,EAAgBpV,cACtB,IAAK,OACH,OAAO,KACT,IAAK,UAGH,OAAOsB,GAAoB7B,EAFFS,EAASyJ,cAAc0L,IAAG,IACjDjW,EAAW,6BAA6BgW,EAAgBlV,SAASL,UAEjET,EAAW,wBAAwBgW,EAAgBlV,SAASL,QAEhE,IAAK,MAAO,CACV,IAAIyI,EAAqC,KACzC,IAAI,IAAI7H,EAAI,EAAGA,EAAI2U,EAAgBlV,SAASH,cAAeU,IAAK,CAC9D,MAAMwE,EAAyBmQ,EAAgBlV,SAAS0E,wBAAwBnE,IAC9ErB,EAAW,mCAAmCgW,EAAgBlV,SAASL,QAEnEyV,EAAsBnS,GAAaP,EADXuC,EAAmBF,EAAwBqD,GACDjG,EAAU5C,GAC5E8V,EAA0CpP,EAAyBmP,EAAqBhN,IAC5FlJ,EAAY,wBAAwB6F,EAAuBpF,QACvD2V,EAAgBJ,EAAgBnV,gBAAgBQ,IACpDrB,EAAW,0BAA0BgW,EAAgBlV,SAASL,QAIhEyI,EAAkBiN,EAA0BC,IAC1CpW,EAAW,gCAAgCoW,QAAoBvQ,EAAuBpF,OAC1F,CACA,OAAOyI,CACT,CACA,IAAK,UACHlJ,EAAW,+CAA+CgW,EAAgBlV,SAASL,QAGzF,CCrBM,SAAU4V,GACd7S,EACA4R,EACAnS,EACA5C,GAEA,MAAO,CAACI,EAAc2E,EAAmBrF,EAAYsF,KACnDjF,EAAeC,GAEf,MAAMS,EAAWgB,EAAYrB,GAIxBf,MAAMkH,QAAQxB,IACjBpF,EAAWsW,EAAuB7V,EAAM,wEAGtC2E,EAAQ9D,OAASR,EAAS0E,wBAAwBlE,QACpDtB,EAAWuV,EAAkB,UAAW9U,EAAMK,EAAS0E,wBAAwBlE,OAAQ8D,EAAQ9D,SAGjG,MAAMiV,GAA6B,IAApBlR,GAASkR,OAClBC,EAA4B,mBAAVzW,EACpBwW,GAAUC,GACZxW,EAAWsW,EAAuB7V,EAAM,4DAEtC8V,IAAW7W,MAAMkH,QAAQ7G,IAC3BC,EAAWsW,EAAuB7V,EAAM,iEAO1C,MAAM+F,EAAgBrB,GACpB3B,EAAQP,EAAU5C,EAASS,EAAUsE,EAAS,CAAEqB,oBAAoB,IAElE8P,GAAWxW,EAAoBuB,SAAWkF,EAAclF,QAC1DtB,EAAWyW,EAAyBhW,EAAM+F,EAAclF,OAASvB,EAAoBuB,SAGvF,MAAMoV,EAA6B,GACnC,IAAI,IAAIrV,EAAI,EAAGA,EAAImF,EAAclF,OAAQD,IAAK,CAC5C,MAAMmB,EAAYqE,GAAsBrD,EAAQP,EAAU5C,EAASS,EAAU0F,EAAcnF,IAC3FqV,EAAUlV,KAAKuE,EAAmBjF,EAAU0B,GAC9C,CAGA,IAAI8M,EAAU,EACd,IAAI,IAAIjO,EAAI,EAAGA,EAAIqV,EAAUpV,OAAQD,IAAK,CACxC,MAAMe,EAAUsU,EAAUrV,GAC1B,IAAIsV,EACJ,GAAIH,EAAU,CAIZG,EAAY5W,EADSgE,GAAaP,EAAQpB,EAASa,EAAU5C,MAC1BmG,EAAcnF,GACnD,MACEsV,EADSJ,EACIxW,EAAoBsB,GAErBtB,OAIW,IAAd4W,IAGX1D,GAAazP,EAAQpB,EAASuU,EAAW1T,EAAU5C,GACnDiP,IACF,CACA,OAAOA,EAEX"}
|
|
1
|
+
{"version":3,"file":"setAll.js","sources":["../../../../../src/command/commandTokenRegistry.ts","../../../../../src/command/commandNamespace.ts","../../../../../src/proxy/assertWritable.ts","../../../../../src/proxy/methods/isCacheable.ts","../../../../../src/proxy/methods/getByAddress.ts","../../../../../src/proxy/apis/wildcardIndexes.ts","../../../../../src/proxy/methods/getListIndexesByAddress.ts","../../../../../src/proxy/methods/getListIndexByIndexes.ts","../../../../../src/list/mergeKeyedList.ts","../../../../../src/proxy/methods/hasByAddress.ts","../../../../../src/proxy/methods/swapInfo.ts","../../../../../src/dependency/walkDependency.ts","../../../../../src/dependency/topologicalRank.ts","../../../../../src/proxy/methods/setByAddress.ts","../../../../../src/proxy/apis/resolve.ts","../../../../../src/proxy/apis/getAll.ts","../../../../../src/proxy/methods/getListIndex.ts","../../../../../src/proxy/apis/setAll.ts"],"sourcesContent":["import { IStateElement } from \"../components/types\";\nimport { CommandToken } from \"./CommandToken\";\nimport { ICommandToken } from \"./types\";\n\nconst registryByStateElement: WeakMap<IStateElement, Map<string, ICommandToken>> = new WeakMap();\n\nexport function getOrCreateCommandToken(stateElement: IStateElement, name: string): ICommandToken {\n let registry = registryByStateElement.get(stateElement);\n if (typeof registry === \"undefined\") {\n registry = new Map<string, ICommandToken>();\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 CommandToken(name, stateElement);\n registry.set(name, token);\n }\n return token;\n}\n\nexport const __private__ = {\n registryByStateElement,\n};\n","/**\n * `state.$command` でアクセスされる command token の namespace proxy を提供する。\n *\n * - state element 単位で memo 化し、同一 stateElement なら同じ proxy が返る。\n * - 宣言された名前 (`$commandTokens` に列挙されたもの) のみ token を返す。\n * 宣言外の名前にアクセスした場合は undefined を返す。\n * (`constructor` / `Symbol.toPrimitive` / `then` など内部システムが触るキーで\n * 例外を投げないため。typo は subsequent な `.emit()` 呼び出しで TypeError として\n * 間接的に表面化する。)\n * - token そのものの memo は `getOrCreateCommandToken` 側に集約されており、\n * namespace proxy は薄いゲートウェイとして振る舞う。\n */\n\nimport { IStateElement } from \"../components/types\";\nimport { raiseError } from \"../raiseError\";\nimport { getOrCreateCommandToken } from \"./commandTokenRegistry\";\nimport { ICommandToken } from \"./types\";\n\nconst namespaceProxyByStateElement: WeakMap<IStateElement, object> = new WeakMap();\n\nexport function getCommandNamespace(stateElement: IStateElement): object {\n const cached = namespaceProxyByStateElement.get(stateElement);\n if (typeof cached !== \"undefined\") {\n return cached;\n }\n const proxy = new Proxy(Object.create(null), {\n get(_target: object, prop: PropertyKey): ICommandToken | undefined {\n if (typeof prop !== \"string\") {\n return undefined;\n }\n if (!stateElement.commandTokenNames.has(prop)) {\n return undefined;\n }\n return getOrCreateCommandToken(stateElement, prop);\n },\n has(_target: object, prop: PropertyKey): boolean {\n return typeof prop === \"string\" && stateElement.commandTokenNames.has(prop);\n },\n ownKeys(): string[] {\n return Array.from(stateElement.commandTokenNames);\n },\n getOwnPropertyDescriptor(_target: object, prop: PropertyKey): PropertyDescriptor | undefined {\n if (typeof prop === \"string\" && stateElement.commandTokenNames.has(prop)) {\n return {\n configurable: true,\n enumerable: true,\n value: getOrCreateCommandToken(stateElement, prop),\n };\n }\n return undefined;\n },\n set(): boolean {\n raiseError(`$command namespace is read-only; assigning to it is not allowed.`);\n },\n deleteProperty(): boolean {\n raiseError(`$command namespace is read-only; deleting from it is not allowed.`);\n },\n });\n namespaceProxyByStateElement.set(stateElement, proxy);\n return proxy;\n}\n\nexport function clearCommandNamespace(stateElement: IStateElement): void {\n namespaceProxyByStateElement.delete(stateElement);\n}\n\nexport const __private__ = {\n namespaceProxyByStateElement,\n};\n","import { raiseError } from \"../raiseError\";\nimport type { IStateHandler } from \"./types\";\n\n/**\n * 書き込み API の入口が共通で呼ぶ、書き込み能力の検査(要件 B6)。\n *\n * set トラップ・`$resolve` の書き・`$setAll`(`**` のブロードキャストを含む)の 4 つの入口が、\n * 同じ規則・同じ文言で readonly のプロキシからの書き込みを拒否する。以前は set トラップだけが\n * 検査していて、`$resolve` / `$setAll` は readonly のプロキシからでも書けた。\n *\n * 共通の書き込み境界(`setByAddress`)には置かない: ランタイム自身(`$scan` の畳み込み・\n * `$watch` の連鎖など)が readonly のハンドラのまま内部の書き込みをしており、そこは利用者の\n * 書き込みではないため。\n */\nexport function assertWritable(handler: IStateHandler): void {\n if (handler.mutability === \"readonly\") {\n raiseError(`This state is readonly.`);\n }\n}\n","import { IStateAddress } from \"../../address/types\";\nimport { IStateElement } from \"../../components/types\";\n\n/**\n * このアドレスの値をキャッシュしてよいか(getByAddress / setByAddress 共通の判定)。\n *\n * ワイルドカードを含むパス(リスト行)と宣言済み getter は再評価が高くつくため\n * キャッシュする。ただし mapped な `bind-component` の state は例外で、丸ごと外す。\n *\n * mapped な state は値を持たず、読みも書きも親スコープの state へ解決される\n * (innerState proxy)。同じ値は親側のキャッシュにも載り、その無効化は親の依存 walk が\n * 担う。子側にもう一段キャッシュを置くと、正本でない複製を親の無効化が届かない場所に\n * 作ることになり、親起点の書き込みのあと子だけが旧値を読み続ける。二重に持たないのが\n * 唯一の整合手段なので、mapped な state 要素ではキャッシュ層を持たない — 親の\n * キャッシュがそのまま効くので、失うのは重複していた一段だけ\n * (docs/architecture-hardening/15-state-component-mechanism-consistency.md §1.8)。\n */\nexport function isCacheable(stateElement: IStateElement, address: IStateAddress): boolean {\n\n // マーカーで終わるパス(`users.*.#m1` — オーバーレイ値)はキャッシュしない。\n // オーバーレイ値 proxy は評価中の receiver / handler を閉じ込めるため、drain を\n // 跨いで使い回せない(webComponent/overlay.ts)。マーカーの**下**のパス\n // (私有キー・getter の値)は通常どおりキャッシュされ、依存 walk が無効化する。\n if (stateElement.hasMounts === true && address.pathInfo.lastSegment.charCodeAt(0) === 35 /* '#' */) {\n return false;\n }\n return address.pathInfo.wildcardCount > 0 ||\n stateElement.getterPaths.has(address.pathInfo.path);\n}\n","/**\n * getByAddress.ts\n *\n * StateClassの内部APIとして、構造化パス情報(IStructuredPathInfo)とリストインデックス(IListIndex)を指定して\n * 状態オブジェクト(target)から値を取得するための関数(getByAddress)の実装です。\n *\n * 主な役割:\n * - 指定されたパス・インデックスに対応するState値を取得(多重ループやワイルドカードにも対応)\n * - 依存関係の自動登録(checkDependencyで登録)\n * - キャッシュ機構(リストもキャッシュ対象)\n * - getter経由で値取得時はpushAddressでスコープを一時設定\n * - 存在しない場合は親pathAddressやlistIndexを辿って再帰的に値を取得\n *\n * 設計ポイント:\n * - checkDependencyで依存追跡を実行 \n * - キャッシュ有効時はstateAddressで値をキャッシュし、取得・再利用を最適化\n * - ワイルドカードや多重ループにも柔軟に対応し、再帰的な値取得を実現\n * - finallyでキャッシュへの格納を保証\n */\n\nimport { liftAddress } from \"../../address/liftAddress\";\nimport { getPathInfo } from \"../../address/PathInfo\";\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { IPathInfo, IStateAddress } from \"../../address/types\";\nimport { keepPreviousList } from \"../../list/createListDiff\";\nimport { listIndexAtWildcard } from \"../../list/wildcardLevel\";\nimport { getRowCacheStamp } from \"../../list/createListIndex\";\nimport { getCacheEntryByAbsoluteStateAddress, setCacheEntryByAbsoluteStateAddress } from \"../../cache/cacheEntryByAbsoluteStateAddress\";\nimport { getCommandNamespace } from \"../../command/commandNamespace\";\nimport { IStateElement } from \"../../components/types\";\nimport { STATE_COMMAND_NAMESPACE_NAME, WILDCARD } from \"../../define\";\nimport { missingRootPathMessage, wildcardScopeMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { NOT_HANDLED } from \"../../core/addressHooks\";\nimport { IStateHandler } from \"../types\";\nimport { checkDependency } from \"./checkDependency\";\nimport { isCacheable } from \"./isCacheable\";\n\n/**\n * namespace 配下のパスは raw state を持たないため、proxy の get トラップと同じ\n * namespace オブジェクトを辿る。1セグメント目は namespace 本体、2セグメント目以降は\n * namespace 上のキーを順に走査する。走査値が object / function 以外(null /\n * undefined / primitive の葉)になったら undefined を返す — 葉より深い読み\n * (例: `$streamStatus.<name>.<key>`、error が primitive throw のときの\n * `$streamError.<name>.message`)は宣言外アクセスと同じ undefined 解決とし、\n * Reflect.get の non-object TypeError を updater の drain に漏らさない\n * (§4-1 の throw しない寛容規約)。\n */\nfunction walkNamespace(namespace: object, segments: string[]): any {\n let value: any = namespace;\n for (let i = 1; i < segments.length; i++) {\n // Object(v) !== v は「v が object / function でない」(= primitive / null / undefined)判定\n if (Object(value) !== value) {\n return undefined;\n }\n value = Reflect.get(value, segments[i]);\n }\n return value;\n}\n\n// 「ツリーに意見が無い」読み(親が無い・親にそのキーが無い)を機能に聞く(設計案 H1 の readMissing)。\n// 親が無ければ parentValue は null。hook の無い state は判定 1 個で抜ける\nfunction readMissing(\n stateElement: IStateElement,\n address: IStateAddress,\n parentValue: object | null,\n receiver: any,\n handler: IStateHandler,\n): unknown {\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const missing = hooks.readMissing;\n for (let i = 0; i < missing.length; i++) {\n const handled = missing[i](stateElement, address, parentValue, receiver, handler);\n if (handled !== NOT_HANDLED) return handled;\n }\n }\n return NOT_HANDLED;\n}\n\nfunction _getByAddress(\n target : object,\n address : IStateAddress,\n receiver : any,\n handler : IStateHandler,\n stateElement: IStateElement,\n): any {\n const firstSegment = address.pathInfo.segments[0];\n if (firstSegment === STATE_COMMAND_NAMESPACE_NAME) {\n // $command 名前空間: キーは宣言済み command token 名\n return walkNamespace(getCommandNamespace(stateElement), address.pathInfo.segments);\n }\n // $streamStatus / $streamError(stream/addressHooks.ts)とマーカーで終わるパスのオーバーレイ\n // (webComponent/addressHooks.ts)は getByAddress の read hook が先に答える(宣言・マウントのある state だけに付く)\n if (address.pathInfo.path in target) {\n // getterの中で参照の可能性があるので、addressをプッシュする\n if (stateElement.getterPaths.has(address.pathInfo.path)) {\n handler.pushAddress(address);\n try {\n return Reflect.get(target, address.pathInfo.path, receiver);\n } finally {\n handler.popAddress();\n }\n\n } else {\n return Reflect.get(target, address.pathInfo.path);\n }\n } else {\n // 親アドレスが無い = 単一セグメントのパスが state に存在しない。ここは元から\n // throw していたが、文面が内部実装の言葉だったので打ち間違いだと分からなかった。\n // 深いパスの console.warn(pathDiagnostics.checkDeclaredPath)と語彙を揃える。\n // 親が無い(= ルート欠落): ツリーに意見が無いので readMissing hook(予約済みボリューム\n // スロットの配下なら undefined — D22)に先に聞き、無ければ raise する\n if (address.parentAddress === null) {\n const missing = readMissing(stateElement, address, null, receiver, handler);\n if (missing !== NOT_HANDLED) {\n return missing;\n }\n raiseError(missingRootPathMessage(address.pathInfo.path, target, stateElement.getterPaths));\n }\n const parentAddress = address.parentAddress;\n const parentValue = getByAddress(target, parentAddress, receiver, handler);\n // 親が居ないパスの読みは undefined(=「state に意見が無い」)。`Reflect.get` に\n // そのまま渡すと生の `TypeError: Reflect.get called on non-object` になり、\n // updater の drain も行ループも捕まえないので **1 本の stale な読みが同じバッチの\n // 無関係な更新まで道連れにする**(§1.7 / §1.9 と同じ構図)。\n //\n // 実際に踏むのは「消えた行を指すバインディングが、その行を消す `for` より先に\n // 適用される」形。同一スコープならトポロジカル順で `for` が先に来るので起きないが、\n // bind-component は親スコープの通知と子スコープの `for` が別経路で流れるため\n // 順序が保証されない(docs/state-bind-component-nested-for-design.md)。\n // undefined はプロパティ書き込みがスキップされる値なので DOM は触られず、\n // 直後に `for` が行ごと外して整合する。\n if (parentValue === null || typeof parentValue === \"undefined\") {\n return undefined;\n }\n const lastSegment = address.pathInfo.segments[address.pathInfo.segments.length - 1];\n // 「ツリーの未存在キー」の分岐だけ readMissing hook(公開 getter の dispatch など)に聞く\n // (X1 — 命中する読みは無改造)。hook の無い state は判定 1 個で抜ける\n const hooks = stateElement.addressHooks;\n if (hooks && hooks.readMissing.length !== 0 && lastSegment !== WILDCARD\n && !(lastSegment in Object(parentValue))) {\n const missing = readMissing(stateElement, address, Object(parentValue), receiver, handler);\n if (missing !== NOT_HANDLED) {\n return missing;\n }\n }\n if (lastSegment === WILDCARD) {\n // listIndex が無いまま末尾ワイルドカードに到達 = そのパスの階数を満たす\n // ループ文脈が無い(`matrix.*.*` を 1 段の `for` の中で読む等)。元の文面は\n // 内部の言葉(address.listIndex?.index is undefined)で、何段必要なのかが\n // 書かれていなかった(pathDiagnostics.ts)。\n const index = address.listIndex?.index ?? raiseError(\n wildcardScopeMessage(\n `path \"${address.pathInfo.path}\"`,\n address.pathInfo.wildcardCount,\n address.listIndex?.length ?? 0,\n ),\n );\n return Reflect.get(parentValue, index);\n } else {\n return Reflect.get(parentValue, lastSegment);\n }\n }\n}\n\nfunction _getByAddressWithCache(\n target : object, \n address : IStateAddress,\n receiver : any,\n handler : IStateHandler,\n stateElement: IStateElement\n): any {\n const absAddress = liftAddress(stateElement, address);\n const cacheEntry = getCacheEntryByAbsoluteStateAddress(absAddress);\n // 世代印(issue #258 の X10)。絶対アドレスは再セットを跨いで同一なので、dirty だけでは\n // 旧世代の値と新世代の値を見分けられない。世代の違う項目は単に miss として再評価し、\n // 下で新しい印を付けて上書きする(列挙も掃き出しも要らず、どのアドレス形状でも自己修復する)。\n const generation = stateElement.stateGeneration;\n // 行の印(#389)。行の要素・途中の値が変わると印が進み、行の下の項目は外れる(cacheEntryByAbsoluteStateAddress.ts)。\n // 要素のパス(`items.*`)自身は対象にしない: 要素の値はそのパスの dirty でしか変わらず、印で外すと、並べ替えを\n // まだ振り直していない行・退役した行の位置を添字で読み直し、別の要素を新しい印付きで固定する\n const rowStamp = address.pathInfo.lastSegment === WILDCARD ? undefined : getRowCacheStamp(address.listIndex);\n if (cacheEntry !== null && cacheEntry.dirty === false && cacheEntry.generation === generation &&\n cacheEntry.rowStamp === rowStamp) {\n return cacheEntry.value;\n }\n const value = _getByAddress(target, address, receiver, handler, stateElement);\n // 関数はキャッシュしない。行マウントのメソッド(`users.*.#m1.save`)はワイルドカードを含むので\n // キャッシュ可に判定されるが、値は評価中の receiver / handler に束ねたメソッドで、次の呼び出しに\n // 使い回すと前のセッションの文脈で動く — 2 回目からツリーの読みが投げ、私有キーの書き込みも\n // 描き直されなかった(#321)。関数の値を読み直す費用は小さい\n if (typeof value !== \"function\") {\n setCacheEntryByAbsoluteStateAddress(absAddress, {\n value: value,\n dirty: false,\n generation: generation,\n rowStamp: rowStamp\n });\n }\n const previous = cacheEntry?.value;\n if (Array.isArray(value) && value !== previous && stateElement.getterPaths.has(address.pathInfo.path)) {\n inspectGetterList(target, address, value, previous, receiver, handler);\n }\n return value;\n}\n\n/** 読んだパスの値をそのまま返したことのある getter(#362)。書き込みの通知はこの getter だけを別名の候補にする */\nconst aliasGetterPathInfos = new WeakSet<IPathInfo>();\n\nexport function isAliasGetter(pathInfo: IPathInfo): boolean {\n return aliasGetterPathInfos.has(pathInfo);\n}\n\n/**\n * getter が新しい配列を返したとき、getter が読んだパスの値と突き合わせる(#362)。\n *\n * - 読んだパスの値そのもの(`get shown() { return this.filter === \"all\" ? this.todos : … }` の all)なら、\n * その getter を別名として憶える(setByAddress の notifyWrite が、元のパスへの書き込みを知らせる候補)。\n * - 前に返した配列が読んだパスにまだ居る(all → done で写しに替わった)なら、差分が前の配列の行を写しへ\n * 貸さないように控える(list/createListDiff.ts の livePreviousLists)。\n *\n * 読んだパスは動的依存の表から引く。getter が配列の同一性を変えたときだけ走るので、書き込みや読みの\n * ホットパスには乗らない。読むのは getter の行の文脈で読めるパスだけで、依存は張らない。\n */\nfunction inspectGetterList(\n target: object,\n address: IStateAddress,\n value: unknown[],\n previous: unknown,\n receiver: any,\n handler: IStateHandler,\n): void {\n const { path, wildcardCount } = address.pathInfo;\n handler.beginUntrack();\n try {\n for (const [source, targets] of handler.stateElement.dynamicDependency) {\n const sourcePathInfo = getPathInfo(source);\n // getter の行の文脈で読めるパスだけ(getter より深いワイルドカードのパスは読まない)\n if (!targets.includes(path) || sourcePathInfo.wildcardCount > wildcardCount) {\n continue;\n }\n const sourceValue = getByAddress(target,\n createStateAddress(sourcePathInfo, listIndexAtWildcard(address.listIndex!, sourcePathInfo.wildcardCount - 1, wildcardCount)),\n receiver, handler);\n if (sourceValue === value) {\n aliasGetterPathInfos.add(address.pathInfo);\n } else if (sourceValue === previous) {\n keepPreviousList(value, previous);\n }\n }\n } finally {\n handler.endUntrack();\n }\n}\n\nexport function getByAddress(\n target : object,\n address : IStateAddress,\n receiver : any,\n handler : IStateHandler\n): any {\n // 再帰 getter の遅延実体化(Phase B)。**キャッシュ参照より前**でなければならない。\n // 未定義のまま一度読まれると isCacheable が wildcardCount > 0 だけでキャッシュ可を\n // 返すので undefined が dirty:false で固定され、後からアクセサを生やしても恒久的に\n // 直らない(Phase A の A7)。宣言の無い state は boolean 判定 1 個で抜け、宣言のある\n // state も 2 回目からは PathInfo キーの記憶 1 回で抜ける(書き側と対称・第 5 サイクル)。\n checkDependency(handler, address);\n if (handler.stateElement.hasRecursion === true) {\n handler.stateElement.recursionRegistry!.materializeForPathInfo(handler.stateElement, address.pathInfo);\n }\n const stateElement = handler.stateElement;\n // 読み書き境界の hook(設計案 H1): 宣言が要求した機能の分だけ state に付いている。無ければ判定 1 回\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const readHooks = hooks.read;\n for (let i = 0; i < readHooks.length; i++) {\n const handled = readHooks[i](stateElement, address, receiver, handler);\n if (handled !== NOT_HANDLED) return handled;\n }\n }\n const cacheable = isCacheable(stateElement, address);\n if (cacheable) {\n return _getByAddressWithCache(target, address, receiver, handler, stateElement);\n } else {\n return _getByAddress(target, address, receiver, handler, stateElement);\n }\n}\n","/**\n * wildcardIndexes.ts\n *\n * ワイルドカードを含むパスから「解決済み添字タプルの集合」を列挙する共有走査。\n * `$getAll`(読み)と `$setAll`(書き)が**同じ展開規則・同じ順序**で動くための単一の正本\n * (docs/state-set-all-design.md §6-1)。\n *\n * 添字は**前方一致の接頭辞**で、足りない分は「その階層を全部展開する」という意味を持つ\n * (README の `$getAll(\"scores.*\", [])` がこれ)。返るタプルは常にワイルドカードの本数と\n * 同じ長さになるので、そのまま `$resolve` の厳密一致な添字として使える。\n *\n * 順序は**深さ優先・添字昇順**(ネストは添字タプルの辞書順)で決定的。\n * `$getAll(p, i)` の戻り順と `$setAll(p, i, …)` の適用順が一致する根拠がこれであり、\n * `$setAll` の `{ spread: true }` 形はこの順序に乗っている。\n *\n * Throws: LIST-201(インデックス未解決)、BIND-201(ワイルドカード情報不整合)\n */\n\nimport { liftAddress } from \"../../address/liftAddress\";\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { IAbsoluteStateAddress, IPathInfo } from \"../../address/types\";\nimport { getStateListBaseline, setStateListBaseline } from \"../../list/stateListBaseline\";\nimport { createListDiff } from \"../../list/createListDiff\";\nimport { IListIndex } from \"../../list/types\";\nimport { raiseError } from \"../../raiseError\";\nimport { getByAddress } from \"../methods/getByAddress\";\nimport { IStateHandler } from \"../types\";\n\n/**\n * 各ワイルドカード階層で最後に観測したリスト値は、state 側の共有基準\n * ([stateListBaseline](../../list/stateListBaseline.ts))に置く。ListIndex の同一性を\n * 跨いで保つための差分基準であり、読み・描画・依存ウォークが同じ「前回見た形」を見る\n * ことでリスト置換のたびに ListIndex を鋳造し直す事故を防ぐ。\n *\n * 書き(`$setAll`)はこの走査を借りるだけで記録を更新しない\n * (`commitDiffBaseline: false`。設計 §6-2)。\n */\n\nexport interface ICollectWildcardIndexesOptions {\n /**\n * 走査で観測したリスト値を差分基準として記録するか。\n * 読み(`$getAll`)だけが `true`。書き(`$setAll`)は読みの基準を動かさない。\n */\n readonly commitDiffBaseline: boolean;\n}\n\n/**\n * `pathInfo` のワイルドカードを `indexes`(前方一致の接頭辞)で絞り込みつつ展開し、\n * マッチする添字タプルを列挙する。\n *\n * 添字の本数検査(上限)は呼び出し側の責務 — API 名を診断メッセージに出すため。\n */\nexport function collectWildcardIndexes(\n target : object,\n receiver: any,\n handler : IStateHandler,\n pathInfo: IPathInfo,\n indexes : number[],\n options : ICollectWildcardIndexesOptions,\n): number[][] {\n const newValueByAddress: Map<IAbsoluteStateAddress, any> = new Map();\n\n const walkWildcardPattern = (\n wildcardParentPathInfos: IPathInfo[],\n wildcardIndexPos: number,\n listIndex: IListIndex | null,\n indexes: number[],\n indexPos: number,\n parentIndexes: number[],\n results: number[][]\n ) => {\n const wildcardParentPathInfo = wildcardParentPathInfos[wildcardIndexPos] ?? null;\n if (wildcardParentPathInfo === null) {\n results.push(parentIndexes);\n return;\n }\n const wildcardAddress = createStateAddress(wildcardParentPathInfo, listIndex);\n const wildcardAbsAddress = liftAddress(handler.stateElement, wildcardAddress);\n const oldValue = getStateListBaseline(wildcardAbsAddress);\n const newValue = getByAddress(target, wildcardAddress, receiver, handler);\n const listDiff = createListDiff(\n listIndex, oldValue, newValue);\n const listIndexes = listDiff.newIndexes;\n const index = indexes[indexPos] ?? null;\n newValueByAddress.set(wildcardAbsAddress, newValue);\n if (index === null) {\n for(let i = 0; i < listIndexes.length; i++) {\n const listIndex = listIndexes[i];\n walkWildcardPattern(\n wildcardParentPathInfos,\n wildcardIndexPos + 1,\n listIndex,\n indexes,\n indexPos + 1,\n parentIndexes.concat(listIndex.index),\n results);\n }\n } else {\n // 範囲外 index はリスト自体の不在と別原因なので index を含める\n // (docs/state-bind-component-nested-for-design.md §8.4)\n const listIndex = listIndexes[index] ??\n raiseError(`ListIndex not found at index ${index} of ${wildcardParentPathInfo.path}`);\n if ((wildcardIndexPos + 1) < wildcardParentPathInfos.length) {\n walkWildcardPattern(\n wildcardParentPathInfos,\n wildcardIndexPos + 1,\n listIndex,\n indexes,\n indexPos + 1,\n parentIndexes.concat(listIndex.index),\n results\n );\n } else {\n // 最終ワイルドカード層まで到達しているので、結果を確定\n results.push(parentIndexes.concat(listIndex.index));\n }\n }\n }\n\n const resultIndexes: number[][] = [];\n walkWildcardPattern(\n pathInfo.wildcardParentPathInfos,\n 0,\n null,\n indexes,\n 0,\n [],\n resultIndexes\n );\n if (options.commitDiffBaseline) {\n for(const [address, newValue] of newValueByAddress.entries()) {\n setStateListBaseline(address, Array.isArray(newValue) ? newValue : []);\n }\n }\n return resultIndexes;\n}\n","/**\n * getListIndexesByAddress.ts\n *\n * ワイルドカードの親アドレス(`items` / `groups.*.items`)にあるリスト値の行集合を、\n * 正本台帳(listIndexesByList)から引く。直接添字(`this[\"items.0.v\"]`)・`$postUpdate`\n * (getListIndex)と `$resolve` / `$setAll`(getListIndexByIndexes)が、添字から行を\n * 引くときの共有部分。\n *\n * 台帳を作るのは差分(createListDiff)だけで、差分を取るのは for の描画・依存ウォーク・\n * `$getAll` / `$setAll` の走査・再帰の走査。どれも経ていないリスト(for で描いておらず、\n * 走査もしていない)には台帳が無く、以前はここで `ListIndex not found` を投げていた —\n * README の「Direct index access」が一度も成立していなかった(#324)。台帳が無ければ、\n * その場で差分を取って生やす。\n *\n * 旧リストには `$getAll` の第 1 相(wildcardIndexes.ts)と同じ state 側の基準を渡し、\n * 行の再利用を `$getAll` と同じ規則に揃える。空を基準に行を鋳造すると、後でその基準から\n * 差分を取る側(`$getAll` / 依存ウォーク)が 2 つの台帳を同一性で突き合わせる経路\n * (calcDiffIndexes)に入り、変わっていない要素まで追加+削除として扱う。中身が同じ写しの\n * 配列なら台帳ごと基準側の行へ差し替わり、直接添字が書いた行のキャッシュが置き去りになる。\n * 生やしたら基準もこの値で確定する(`$getAll` の第 1 相・再帰の走査と同じ)。確定しないと、\n * 描いていないリストは依存ウォークも差分を取らないので、次にリストを写し替えても生やした行が\n * 退役せず、子リストの台帳が古い行にぶら下がったまま残る — 行の集計 getter が恒久的に古くなる\n * (読むだけの直接添字・DevTools の覗き見でも起きた)。確定はバッチの末尾まで保留される\n * (list/stateListBaseline.ts)。\n */\n\nimport { liftAddress } from \"../../address/liftAddress\";\nimport { IStateAddress } from \"../../address/types\";\nimport { createListDiff } from \"../../list/createListDiff\";\nimport { resolveListIndexesByList } from \"../../list/listIndexesByList\";\nimport { getStateListBaseline, setStateListBaseline } from \"../../list/stateListBaseline\";\nimport { IListIndex } from \"../../list/types\";\nimport { IStateHandler } from \"../types\";\n\nexport function getListIndexesByAddress(\n handler: IStateHandler,\n address: IStateAddress,\n value : any,\n): IListIndex[] {\n const listIndexes = resolveListIndexesByList(value, address.listIndex);\n if (listIndexes !== null) {\n return listIndexes;\n }\n const absAddress = liftAddress(handler.stateElement, address);\n const diff = createListDiff(address.listIndex, getStateListBaseline(absAddress), value);\n setStateListBaseline(absAddress, Array.isArray(value) ? value : []);\n return diff.newIndexes;\n}\n","/**\n * getListIndexByIndexes.ts\n *\n * 解決済みの添字タプル(ワイルドカード 1 段につき 1 個)から、対応する ListIndex を\n * **正本レジストリ**(listIndexesByList)経由で引き当てる。台帳が無いリスト(描画も走査も\n * 経ていない)はその場で台帳を生やす(getListIndexesByAddress、#324)。\n *\n * `$resolve` と `$setAll` の共有部分。列挙側(wildcardIndexes.ts)が走査中に生成した\n * ListIndex をそのまま書き込み先にせず、ここで引き直すことで、binding が使っている\n * ListIndex と同一の同一性に載る(docs/state-set-all-design.md §6-2)。\n *\n * 添字の本数がワイルドカードの本数と一致していることは呼び出し側の責務。\n */\n\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { IPathInfo } from \"../../address/types\";\nimport { IListIndex } from \"../../list/types\";\nimport { raiseError } from \"../../raiseError\";\nimport { IStateHandler } from \"../types\";\nimport { getByAddress } from \"./getByAddress\";\nimport { getListIndexesByAddress } from \"./getListIndexesByAddress\";\n\nexport function getListIndexByIndexes(\n target : object,\n receiver: any,\n handler : IStateHandler,\n pathInfo: IPathInfo,\n indexes : number[],\n): IListIndex | null {\n // ワイルドカード階層ごとにListIndexを解決していく\n let listIndex: IListIndex | null = null;\n for(let i = 0; i < pathInfo.wildcardParentPathInfos.length; i++) {\n const wildcardParentPathInfo = pathInfo.wildcardParentPathInfos[i];\n const wildcardAddress = createStateAddress(wildcardParentPathInfo, listIndex);\n const tmpValue = getByAddress(target, wildcardAddress, receiver, handler);\n const listIndexes = getListIndexesByAddress(handler, wildcardAddress, tmpValue);\n const index = indexes[i];\n // 範囲外 index は index を含めて投げる(docs/state-bind-component-nested-for-design.md §8.4)。\n // 値が配列でないリストも、行 0 件としてここで投げる\n listIndex = listIndexes[index] ??\n raiseError(`ListIndex not found at index ${index} of ${wildcardParentPathInfo.path}`);\n }\n return listIndex;\n}\n","/**\n * list/mergeKeyedList.ts\n *\n * `$listKeys` 宣言済みリストパスへの配列代入で、キーが一致する行の\n * 「オブジェクト強制・値展開」を行う(docs/state-list-key-design.md §2)。\n *\n * - キー突合し、一致行は**旧オブジェクトを据え置いた**ハイブリッド配列を作る\n * → 配列要素の参照が変わらないので for は行を再利用する(DOM・フォーカス・\n * 非バインド DOM 状態が保存される)\n * - 一致行の「変化したフィールド」だけを列挙して返す\n * → 呼び出し側が per-path 書き込みとして発行する(§7.0 の穴を塞ぐ正典イディオム)\n *\n * このモジュールは純粋な計算のみで、state への書き込みは行わない。\n */\n\nimport { STATE_LIST_KEYS_NAME } from \"../define\";\nimport { raiseError } from \"../raiseError\";\nimport type { ListKeySpec } from \"./listKeys\";\n\ntype Row = Record<string, unknown>;\n\n/** キーが一致し、旧オブジェクトへ値展開すべき行 */\nexport interface IKeyedRowMatch {\n /** ハイブリッド配列上の位置(= 新配列上の位置) */\n readonly position: number;\n /** 据え置かれる旧行オブジェクト(書き込み先) */\n readonly oldRow: Row;\n /** 値の供給元となる新行オブジェクト(格納はされない) */\n readonly newRow: Row;\n}\n\nexport interface IKeyedListMerge {\n /** 実際に格納すべきハイブリッド配列(一致行は旧オブジェクト) */\n readonly list: unknown[];\n /** 値展開が必要な一致行。空にはならない(空なら mergeKeyedList が null を返す) */\n readonly matched: readonly IKeyedRowMatch[];\n}\n\nexport interface IFieldWrite {\n readonly field: string;\n readonly value: unknown;\n}\n\n/**\n * 値展開は own enumerable データプロパティのコピーなので、プロトタイプや\n * アクセサを持つオブジェクトでは意味論が保てない。plain object 以外は即エラー(§5)。\n */\nfunction assertPlainRow(row: unknown, path: string, side: string, position: number): asserts row is Row {\n if (typeof row !== \"object\" || row === null) {\n raiseError(\n `${STATE_LIST_KEYS_NAME} list \"${path}\": ${side} row at index ${position} must be a plain object ` +\n `(got ${row === null ? \"null\" : typeof row}).`\n );\n }\n const proto = Object.getPrototypeOf(row);\n if (proto !== Object.prototype && proto !== null) {\n raiseError(\n `${STATE_LIST_KEYS_NAME} list \"${path}\": ${side} row at index ${position} must be a plain object ` +\n `(class instances and exotic objects cannot be value-expanded).`\n );\n }\n}\n\nfunction keyOf(row: Row, spec: ListKeySpec, path: string, side: string, position: number): unknown {\n const key = typeof spec === \"function\" ? spec(row) : row[spec];\n if (key === undefined || key === null) {\n raiseError(\n `${STATE_LIST_KEYS_NAME} list \"${path}\": ${side} row at index ${position} has no key ` +\n `(${typeof spec === \"function\" ? \"key function\" : `field \"${spec}\"`} returned ${String(key)}).`\n );\n }\n return key;\n}\n\n/** 行を検証しつつキーを抽出する。キー重複は即エラー(§5)。 */\nfunction extractKeys(list: readonly unknown[], spec: ListKeySpec, path: string, side: string): unknown[] {\n const keys: unknown[] = new Array(list.length);\n const seen = new Set<unknown>();\n for (let i = 0; i < list.length; i++) {\n const row = list[i];\n assertPlainRow(row, path, side, i);\n const key = keyOf(row, spec, path, side, i);\n if (seen.has(key)) {\n raiseError(`${STATE_LIST_KEYS_NAME} list \"${path}\": duplicate key ${JSON.stringify(key)} in ${side} list.`);\n }\n seen.add(key);\n keys[i] = key;\n }\n return keys;\n}\n\n/**\n * キー突合してハイブリッド配列を組む。値展開すべき一致行が 1 つも無ければ null\n * (呼び出し側は従来どおりの書き込みへ倒す)。\n *\n * 突合対象の旧配列は「最後に適用された配列」ではなく**現在格納されている配列**。\n * ハイブリッド構築が格納配列の参照を保存するため、同一マイクロタスク内の連続\n * 書き込みでも適用時の diff と transitive に整合する(§6)。\n */\nexport function mergeKeyedList(\n path: string,\n spec: ListKeySpec,\n oldValue: unknown,\n newList: readonly unknown[],\n): IKeyedListMerge | null {\n // 宣言済みパスなら初回代入(旧配列なし)でも新配列を検証する。\n // 「2 回目の代入で初めて重複キーが露見する」という不連続を避けるため。\n const newKeys = extractKeys(newList, spec, path, \"new\");\n if (!Array.isArray(oldValue) || oldValue.length === 0 || newList.length === 0) {\n return null;\n }\n const oldList: readonly unknown[] = oldValue;\n const oldKeys = extractKeys(oldList, spec, path, \"current\");\n const oldRowByKey = new Map<unknown, Row>();\n for (let i = 0; i < oldList.length; i++) {\n oldRowByKey.set(oldKeys[i], oldList[i] as Row);\n }\n\n const list: unknown[] = new Array(newList.length);\n const matched: IKeyedRowMatch[] = [];\n for (let i = 0; i < newList.length; i++) {\n const newRow = newList[i] as Row;\n const oldRow = oldRowByKey.get(newKeys[i]);\n if (typeof oldRow === \"undefined\" || oldRow === newRow) {\n // 追加行、または既に同一オブジェクト(生配列 in-place 変異 + コピー再代入の\n // イディオム)。後者は従来どおり walkDependency の全行フォールバックが担う。\n list[i] = newRow;\n continue;\n }\n list[i] = oldRow;\n matched.push({ position: i, oldRow, newRow });\n }\n return matched.length > 0 ? { list, matched } : null;\n}\n\n/**\n * 一致行について per-path 書き込みすべきフィールドを列挙する。\n *\n * - 変化したフィールドのみ(同値は書かない。無変化リフレッシュを完全なゼロコストに\n * するため — 全フィールド無条件書き込みだと §2.2 の利得が消える)\n * - 新行から消えた旧フィールドは **null** を書く(undefined ではない)\n *\n * 同値判定は Object.is。setByAddress の same-value guard と同じ基準にすることで、\n * 「発行したが guard に落とされる」無駄な書き込みを作らない。\n *\n * 消えたフィールドに null を使うのは、この処理系では undefined が\n * 「状態が値を持たない=無意見」であり applyChangeToProperty が書き込みごと\n * スキップするため(明示的なクリアの語彙は null)。undefined を書くと state 側は\n * 更新されるのに DOM だけ旧値のまま残り、まさに本機能が塞ごうとしている\n * stale を再導入してしまう。既に null / undefined のフィールドは DOM 上も\n * 空なので、クリア書き込み自体を発行しない。\n */\nexport function collectFieldWrites(oldRow: Row, newRow: Row): IFieldWrite[] {\n const writes: IFieldWrite[] = [];\n for (const field of Object.keys(newRow)) {\n if (!Object.is(oldRow[field], newRow[field])) {\n writes.push({ field, value: newRow[field] });\n }\n }\n for (const field of Object.keys(oldRow)) {\n if (!Object.hasOwn(newRow, field) && oldRow[field] != null) {\n writes.push({ field, value: null });\n }\n }\n return writes;\n}\n","import { IStateAddress } from \"../../address/types\";\nimport { WILDCARD } from \"../../define\";\nimport { IStateHandler } from \"../types\";\nimport { getByAddress } from \"./getByAddress\";\n\n/**\n * Reports whether an address has been initialized, independently of its value.\n * In particular, an own slot containing `undefined` is initialized while a\n * missing slot is not.\n */\nexport function hasByAddress(\n target: object,\n address: IStateAddress,\n receiver: unknown,\n handler: IStateHandler,\n): boolean {\n if (address.pathInfo.path in target) return true;\n const parentAddress = address.parentAddress;\n if (parentAddress === null) return false;\n const parentValue = getByAddress(target, parentAddress, receiver, handler);\n if (parentValue === null || (typeof parentValue !== \"object\" && typeof parentValue !== \"function\")) {\n return false;\n }\n const lastSegment = address.pathInfo.lastSegment;\n if (lastSegment === WILDCARD) {\n const index = address.listIndex?.index;\n return typeof index === \"number\" && index in parentValue;\n }\n return lastSegment in parentValue;\n}\n","import { disownListIndexes } from \"../../list/listIndexesByList\";\nimport { ISwapInfo } from \"./types\";\n\n/**\n * 要素書き込みで入れ替え中のリストの「書き込む前の並び」。キーはリストの配列そのもの —\n * 台帳(listIndexesByList)と同じ単位にそろえる。アドレスはパスと listIndex でキャッシュされ\n * `<wcs-state>` を区別しないので、アドレスをキーにすると、別の state 要素や置き換え前の配列で\n * 揃わなかった入れ替えの記録を拾ってしまう。\n */\nconst swapInfoByList: WeakMap<object, ISwapInfo> = new WeakMap();\n\nexport function getSwapInfoByList(list: object): ISwapInfo | null {\n return swapInfoByList.get(list) ?? null;\n}\n\nexport function setSwapInfoByList(list: object, swapInfo: ISwapInfo | null): void {\n if (swapInfo === null) {\n swapInfoByList.delete(list);\n } else {\n // 書き込む前の台帳として持つので、要素の書き込みはもうその場で書き換えない(listIndexesByList.ts)\n disownListIndexes(swapInfo.listIndexes);\n swapInfoByList.set(list, swapInfo);\n }\n}\n","import { liftAddress } from \"../address/liftAddress\";\nimport { calcWildcardLen } from \"../address/calcWildcardLen\";\nimport { getPathInfo } from \"../address/PathInfo\";\nimport { createStateAddress } from \"../address/StateAddress\";\nimport { IAbsoluteStateAddress, IPathInfo, IStateAddress } from \"../address/types\";\nimport { dirtyCacheEntryByAbsoluteStateAddress } from \"../cache/cacheEntryByAbsoluteStateAddress\";\nimport { IStateElement } from \"../components/types\";\nimport { config } from \"../config\";\nimport { DELIMITER, WILDCARD } from \"../define\";\nimport { createListDiff, isSameList } from \"../list/createListDiff\";\nimport { getListIndexesByList } from \"../list/listIndexesByList\";\nimport { getStateListBaseline, setStateListBaseline } from \"../list/stateListBaseline\";\nimport { IListDiff, IListIndex } from \"../list/types\";\nimport { listIndexAtWildcard } from \"../list/wildcardLevel\";\nimport { getByAddressSymbol } from \"../proxy/symbols\";\nimport { IStateProxy } from \"../proxy/types\";\nimport { raiseError } from \"../raiseError\";\nimport { takePendingKeyedWalk } from \"./keyedDependency\";\nimport { getTopologicalRanks } from \"./topologicalRank\";\nimport { SearchType } from \"./types\";\n\nconst MAX_DEPENDENCY_DEPTH = 1000;\n\nfunction getIndexes(listDiff: IListDiff, searchType: SearchType): Iterable<IListIndex> {\n switch (searchType) {\n case \"old\":\n return listDiff.oldIndexes;\n case \"new\":\n return listDiff.newIndexes;\n case \"add\":\n return listDiff.addIndexSet;\n case \"change\":\n return listDiff.changeIndexSet;\n case \"delete\":\n return listDiff.deleteIndexSet;\n default: \n if (config.debug) {\n console.log(`Invalid search type: ${searchType}`);\n }\n return [];\n }\n}\n\ntype ExpandContext = {\n readonly stateElement: IStateElement,\n /** ウォーク中に観測したリスト値。ウォーク完了後にまとめて基準へ確定する(E1)。 */\n readonly observedListValueByAbsAddress: Map<IAbsoluteStateAddress, readonly unknown[]>,\n readonly targetPathInfo: IPathInfo,\n readonly targetListIndexes: IListIndex[],\n readonly wildcardPaths: string[],\n readonly wildcardParentPaths: string[],\n readonly stateProxy: IStateProxy,\n readonly searchType: SearchType\n}\n\nfunction _walkExpandWildcard(\n context: ExpandContext, \n currentWildcardIndex: number,\n parentListIndex: IListIndex | null\n): void {\n const parentPath = context.wildcardParentPaths[currentWildcardIndex];\n const parentPathInfo = getPathInfo(parentPath);\n const parentAddress = createStateAddress(parentPathInfo, parentListIndex);\n const parentAbsAddress = liftAddress(context.stateElement, parentAddress);\n const lastValue = getStateListBaseline(parentAbsAddress);\n const newValue = context.stateProxy[getByAddressSymbol](parentAddress);\n const listDiff = createListDiff(\n parentAddress.listIndex, lastValue, newValue);\n context.observedListValueByAbsAddress.set(parentAbsAddress, Array.isArray(newValue) ? newValue : []);\n\n const loopIndexes = getIndexes(listDiff, context.searchType);\n if (currentWildcardIndex === context.wildcardPaths.length - 1) {\n context.targetListIndexes.push(...loopIndexes);\n } else {\n for(const listIndex of loopIndexes) {\n _walkExpandWildcard(\n context,\n currentWildcardIndex + 1,\n listIndex\n );\n }\n }\n}\n\n/**\n * 静的子展開(list → list.*)の展開範囲。\n * - \"full\": 新リストの全行を展開する(従来挙動)。\n * - \"diff\": 追加行(addIndexSet)と位置が変わった行(changeIndexSet)のみ展開する。\n * 未変更行は値が変わらないため dirty 化・再適用が不要(リスト置換のコストが\n * 既存行数に比例するスケーリング欠陥の解消。docs/list-replacement-dependency-scaling.md)。\n * 削除時の集計 getter は $getAll / $resolve がリスト本体(コンテナ)を読むことで\n * 登録される動的エッジ(list → 集計 getter)が担う。\n */\nexport type ListExpansion = \"full\" | \"diff\";\n\ntype Context = {\n readonly stateElement: IStateElement,\n /** ウォーク中に観測したリスト値。ウォーク完了後にまとめて基準へ確定する(E1)。 */\n readonly observedListValueByAbsAddress: Map<IAbsoluteStateAddress, readonly unknown[]>,\n readonly staticMap: Map<string, string[]>,\n readonly dynamicMap: Map<string, string[]>,\n readonly result: Set<IStateAddress>,\n readonly listPathSet: Set<string>,\n readonly visited: Set<IStateAddress>,\n readonly stateProxy: IStateProxy,\n readonly searchType: SearchType,\n readonly listExpansion: ListExpansion,\n /**\n * この書き込みでキー突合による値展開が成立したリストパス($listKeys)。\n * 変化フィールドは per-path 書き込みで個別に dirty 化済みなので、\n * 「diff に変化が見えない再代入」の全行フォールバックを適用しない\n * (docs/state-list-key-design.md §2.2)。\n */\n readonly keyedMergePath: string | null,\n /** パス → トポロジカル順位。訪問順の決定に使う(topologicalRank.ts 参照) */\n readonly ranks: ReadonlyMap<string, number>,\n /**\n * キャッシュを無効にするだけのアドレス(callback を呼ばない)。`for` で描いていないリストの行と、そこから\n * しか届かない先(#364)。書き込みの着地にすると、描いていないリストの行の `$watch` / `$scan` が配列の\n * 代入で発火する — README の「headless な行 watch には `$listKeys` が要る」と食い違う(S13)\n */\n readonly quiet: Set<IStateAddress>,\n}\n\n/** 依存先を積む。静かな経路からしか届かない先は静かなまま、ほかの経路でも届く先は callback に渡す */\nfunction pushDependency(context: Context, depAddress: IStateAddress, quiet: boolean, nextEntries: IStateAddress[]): void {\n if (!quiet) {\n context.quiet.delete(depAddress);\n } else if (!context.result.has(depAddress)) {\n context.quiet.add(depAddress);\n }\n context.result.add(depAddress);\n nextEntries.push(depAddress);\n}\n\n/**\n * 静的子展開の対象 listIndex 群。fullRows は行全体(list.* とその subtree)を展開する。\n * movedRows は「位置だけが変わった行」で、index 以外の入力が不変なため展開を\n * index 依存 getter の subtree(getMovedRowExpansionPaths)に限定できる。\n */\ntype ExpansionSelection = {\n readonly fullRows: Iterable<IListIndex>,\n readonly movedRows: Iterable<IListIndex> | null,\n}\n\nconst EMPTY_INDEXES: IListIndex[] = [];\n\n/**\n * 静的子展開で訪問する listIndex 群を選ぶ。\"diff\" でも次の場合は全行に倒す:\n * - diff に変化が一切見えない再代入(同一参照および内容同一コピーの再代入。\n * `arr[0].v = 5; s.items = [...arr]` のような in-place 変異後のリフレッシュ\n * イディオムは diff に映らないため、全行展開で従来挙動を保つ。\n * 削除だけの置換は除く — 残存行に変化は無く、集計はコンテナ動的エッジが担う)\n * - 他行を読む getter が検出されたリスト(隣接項目参照など。未変更行の派生値も変わりうる)\n * - `for` で描いていないリスト(ここに来るのは行を据え置いたまま中身が変わりうるときだけ — _collectDependencies)\n */\nfunction selectExpansionIndexes(\n context: Context,\n sourcePath: string,\n listDiff: IListDiff,\n): ExpansionSelection {\n if (context.listExpansion === \"full\" || !context.listPathSet.has(sourcePath)) {\n return { fullRows: listDiff.newIndexes, movedRows: null };\n }\n if (context.stateElement.crossRowListPaths?.has(sourcePath)) {\n return { fullRows: listDiff.newIndexes, movedRows: null };\n }\n if (listDiff.addIndexSet.size === 0 && listDiff.changeIndexSet.size === 0) {\n // 追加も移動も無い。削除も無ければ「変化が見えない再代入」= リフレッシュ意図\n if (listDiff.deleteIndexSet.size === 0) {\n // ただしキー突合による値展開が成立した書き込みでは、変化フィールドは\n // per-path 書き込みで個別に dirty 化済み。全行展開は純粋な無駄になる\n // (無変化ポーリングをゼロコストにする — 設計書 §2.2)。\n if (context.keyedMergePath === sourcePath) {\n return { fullRows: EMPTY_INDEXES, movedRows: null };\n }\n return { fullRows: listDiff.newIndexes, movedRows: null };\n }\n // 削除のみ: 残存行は位置も値も不変なので展開しない\n return { fullRows: EMPTY_INDEXES, movedRows: null };\n }\n return { fullRows: listDiff.addIndexSet, movedRows: listDiff.changeIndexSet };\n}\n\nconst EMPTY_PATH_INFOS: IPathInfo[] = [];\n\n/**\n * 位置だけが変わった行(movedRows)で展開すべきパス群を求める。\n * `${listPath}.*` 配下にある、$1 等を読んだ実績のある getter\n * (indexDependentGetterPaths)だけを返す。行の同一性・listIndex は保たれ\n * index 以外の入力が不変なので、index を読まない getter / 値パスは再評価不要。\n * 戻り値:\n * - IPathInfo[](空可): この各パスだけを行の listIndex で展開する\n * - null: ネストしたワイルドカード配下に index 依存 getter がある\n * (listIndex の階数が合わず個別展開できない)→ 呼び出し側で行全体展開に倒す\n *\n * 配下判定は staticMap の subtree 走査ではなく indexDependentGetterPaths 側の\n * プレフィックス照合で行う。静的依存グラフは `State.setPathInfo` が\n * 「バインドされたパスから親方向へ」張るため、DOM にバインドされていない中間\n * getter(`.label` だけを描画し `.rank` は `.label` からしか読まれない綴り)は\n * subtree に現れない。そこを走査すると index 依存 getter を取りこぼし、\n * 「index を読む getter が subtree に無い=位置のみ変わった行の値は不変」という\n * 呼び出し側の判断が偽になって、移動行の getter が古い値のまま残る。\n * この集合は $1 を読んだ getter の数しか持たないので、走査コストも subtree より小さい。\n */\nfunction getMovedRowExpansionPaths(\n context: Context,\n wildcardPath: string,\n depPathInfo: IPathInfo,\n): IPathInfo[] | null {\n const indexGetters = context.stateElement.indexDependentGetterPaths;\n if (!indexGetters || indexGetters.size === 0) {\n return EMPTY_PATH_INFOS;\n }\n let result: IPathInfo[] | null = null;\n const prefix = wildcardPath + DELIMITER;\n for (const path of indexGetters) {\n if (path !== wildcardPath && !path.startsWith(prefix)) {\n continue;\n }\n const pathInfo = getPathInfo(path);\n if (pathInfo.wildcardCount !== depPathInfo.wildcardCount) {\n return null;\n }\n (result ??= []).push(pathInfo);\n }\n return result ?? EMPTY_PATH_INFOS;\n}\n\nfunction _walkDependency(\n context: Context,\n startAddress: IStateAddress,\n callback: (address: IStateAddress) => void\n): void {\n // rank ごとのバケットで訪問する。辺 (u → v) では必ず rank(u) < rank(v) なので、\n // バケット r を処理する時点で rank < r のパスは全て dirty 化済みになる\n // = ここでリスト実体を読んでも入力が揃っている(topologicalRank.ts 参照)。\n const buckets: (IStateAddress[] | undefined)[] = [];\n const ranks = context.ranks;\n\n const enqueue = (address: IStateAddress, minRank: number): void => {\n let rank = ranks.get(address.pathInfo.path) ?? minRank;\n if (rank < minRank) {\n // 循環など rank が先行関係を表せないケース。現在のバケットに載せて\n // 同一ループ内で処理する(打ち切りは visited が担う)。\n rank = minRank;\n }\n (buckets[rank] ??= []).push(address);\n };\n\n enqueue(startAddress, 0);\n\n // 依存アドレスを収集するための一時バッファ(アドレスごとに使い回す)\n const nextEntries: IStateAddress[] = [];\n\n for (let rank = 0; rank < buckets.length; rank++) {\n const bucket = buckets[rank];\n if (bucket === undefined) {\n continue;\n }\n // 同一バケットへの push(循環時)で伸びるため length は都度読む\n for (let cursor = 0; cursor < bucket.length; cursor++) {\n const address = bucket[cursor];\n if (context.visited.has(address)) {\n continue;\n }\n context.visited.add(address);\n if (context.quiet.has(address)) {\n dirtyCacheEntryByAbsoluteStateAddress(liftAddress(context.stateElement, address));\n } else {\n callback(address);\n }\n nextEntries.length = 0;\n _collectDependencies(context, address, nextEntries);\n for (let i = 0; i < nextEntries.length; i++) {\n enqueue(nextEntries[i], rank + 1);\n }\n }\n }\n}\n\n/**\n * address の依存アドレスを nextEntries に集め、context.result にも登録する。\n * リスト展開(list → list.*)と動的依存のワイルドカード展開はここで値を読むが、\n * 呼び出し元がトポロジカル順を保証しているため入力は揃っている。\n */\nfunction _collectDependencies(\n context: Context,\n address: IStateAddress,\n nextEntries: IStateAddress[],\n): void {\n const sourcePath = address.pathInfo.path;\n const quiet = context.quiet.has(address);\n\n /**\n * パスから依存関係をたどる\n * users.*.name <= users.* <= users\n * ただし、users がリストであれば users.* の依存関係は展開する\n */\n const staticDeps = context.staticMap.get(sourcePath);\n if (staticDeps) {\n for(const dep of staticDeps) {\n const depPathInfo = getPathInfo(dep);\n if (depPathInfo.lastSegment === WILDCARD) {\n //expand indexes\n const newValue = context.stateProxy[getByAddressSymbol](address);\n // 配列でない値は空のリスト(createListDiff も同じに扱う)\n const newList: readonly unknown[] = Array.isArray(newValue) ? newValue : [];\n const absAddress = liftAddress(context.stateElement, address);\n const lastValue = getStateListBaseline(absAddress);\n const listed = context.listPathSet.has(sourcePath);\n // `for` で描いていないリスト(listPaths に無い)の行へ辺が張られるのは、`$watch` の宣言か、行の下の\n // 値がキャッシュに載ったとき(cacheEntryByAbsoluteStateAddress.ts・#364)。追加した行には描くものも\n // キャッシュも無いので、展開するのは行を据え置いたまま中身が変わりうるとき — `$postUpdate`(\"full\")と、\n // 行がもうある配列(台帳の行の数が要素の数と揃う — 同じ配列・前に使った配列に戻した)か同じ要素の並び\n // (写し)の代入 — だけで、それ以外は差分も取らない(読み手がいなければ台帳を作らない)。キー突合の\n // 書き込みは変化したフィールドを個別に書いている(selectExpansionIndexes と同じ)。展開した行は\n // キャッシュを無効にするだけ(context.quiet)\n if (!listed && context.listExpansion === \"diff\" && (context.keyedMergePath === sourcePath ||\n (getListIndexesByList(newList)?.length !== newList.length && !isSameList(lastValue, newList)))) {\n continue;\n }\n const listDiff = createListDiff(\n address.listIndex, lastValue, newList);\n context.observedListValueByAbsAddress.set(absAddress, newList);\n const selection = selectExpansionIndexes(context, sourcePath, listDiff);\n for(const listIndex of selection.fullRows) {\n pushDependency(context, createStateAddress(depPathInfo, listIndex), quiet || !listed, nextEntries);\n }\n // 行はそのままで要素が替わった行(#359。このバッチの間に差分が拾った分)も行ごと展開する\n for(const listIndex of listDiff.valueChangeIndexes ?? EMPTY_INDEXES) {\n pushDependency(context, createStateAddress(depPathInfo, listIndex), quiet || !listed, nextEntries);\n }\n if (selection.movedRows !== null) {\n const movedPathInfos = getMovedRowExpansionPaths(context, dep, depPathInfo);\n if (movedPathInfos === null) {\n // ネスト配下に index 依存 getter: 安全側で行全体を展開(従来挙動)\n for(const listIndex of selection.movedRows) {\n pushDependency(context, createStateAddress(depPathInfo, listIndex), quiet, nextEntries);\n }\n } else if (movedPathInfos.length > 0) {\n // 位置のみ変わった行は index 依存 getter のパスだけを展開する\n for(const listIndex of selection.movedRows) {\n for(const pathInfo of movedPathInfos) {\n pushDependency(context, createStateAddress(pathInfo, listIndex), quiet, nextEntries);\n }\n }\n }\n // movedPathInfos が空: index を読む getter が subtree に無い =\n // 位置のみ変わった行の値は不変。展開・dirty 化とも不要。\n }\n } else {\n pushDependency(context, createStateAddress(depPathInfo, address.listIndex), quiet, nextEntries);\n }\n }\n }\n /**\n * 動的依存関係をたどる\n * 動的依存関係は、getterの実行時に決定される\n *\n * source, target\n *\n * products.*.price => products.*.tax\n * get \"products.*.tax\"() { return this[\"products.*.price\"] * 0.1; }\n *\n * products.*.price => products.summary\n * get \"products.summary\"() { return this.$getAll(\"products.*.price\", []).reduce(sum); }\n *\n * categories.*.name => categories.*.products.*.categoryName\n * get \"categories.*.products.*.categoryName\"() { return this[\"categories.*.name\"]; }\n */\n const dynamicDeps = context.dynamicMap.get(sourcePath);\n if (dynamicDeps) {\n for(const dep of dynamicDeps) {\n const depPathInfo = getPathInfo(dep);\n const listIndexes: (IListIndex | null)[] = [];\n if (depPathInfo.wildcardCount > 0) {\n // ワイルドカードを含む依存関係の処理\n // 同じ親を持つかをパスの集合積で判定する\n // polyfills.tsにてSetのintersectionメソッドを定義している\n const wildcardLen = calcWildcardLen(address.pathInfo, depPathInfo);\n const expandable = (depPathInfo.wildcardCount - wildcardLen) >= 1;\n if (expandable) {\n let listIndex: IListIndex | null;\n if (wildcardLen > 0) {\n // categories.*.name => categories.*.products.*.categoryName\n // ワイルドカードを含む同じ親(products.*)を持つのが、\n // さらに下位にワイルドカードがあるので展開する\n if (address.listIndex === null) {\n raiseError(`Cannot expand dynamic dependency with wildcard for non-list address: ${address.pathInfo.path}`);\n }\n listIndex = listIndexAtWildcard(address.listIndex!, wildcardLen - 1, address.pathInfo.wildcardCount);\n } else {\n // selectedIndex => items.*.selected\n // 同じ親を持たない場合はnullから開始\n listIndex = null;\n }\n const expandContext: ExpandContext = {\n stateElement: context.stateElement,\n observedListValueByAbsAddress: context.observedListValueByAbsAddress,\n targetPathInfo: depPathInfo,\n targetListIndexes: [],\n wildcardPaths: depPathInfo.wildcardPaths,\n wildcardParentPaths: depPathInfo.wildcardParentPaths,\n stateProxy: context.stateProxy,\n searchType: context.searchType,\n };\n _walkExpandWildcard(expandContext, wildcardLen, listIndex);\n listIndexes.push(...expandContext.targetListIndexes);\n } else {\n // products.*.price => products.*.tax\n // ワイルドカードを含む同じ親(products.*)を持つので、リストインデックスは引き継ぐ\n if (address.listIndex === null) {\n raiseError(`Cannot expand dynamic dependency with wildcard for non-list address: ${address.pathInfo.path}`);\n }\n const listIndex = listIndexAtWildcard(address.listIndex, wildcardLen - 1, address.pathInfo.wildcardCount);\n listIndexes.push(listIndex);\n }\n } else {\n // products.*.tax => currentTaxRate\n // 同じ親を持たないので、リストインデックスはnull\n listIndexes.push(null);\n }\n for(const listIndex of listIndexes) {\n pushDependency(context, createStateAddress(depPathInfo, listIndex), quiet, nextEntries);\n }\n }\n }\n}\n\n/**\n * リスト差分が積んだ鍵付き購読者を、このウォークの続きとして辿る(要件 D7 の派生先)。\n *\n * 鍵付き購読は意図的に依存グラフに載らない(載せると選択の更新が全行へ広がる)ので、\n * 差分の 2 経路(`moveIndexWatchers` / `rekeyIndexSubscriptions`)は購読者のアドレスを直に\n * enqueue するだけだった。そこで止まると「鍵付き getter に依存する別の getter」が陳腐化する。\n *\n * 積む側(`dependency/keyedDependency.ts`)は proxy を持たないので積むだけにし、**proxy を\n * 持っているここ**が引き取る。`createListDiff` はこのウォークの中(リスト展開)から呼ばれるので、\n * その場で積まれたものをウォークの末尾で拾える — 書き込みは既に済んでおり、値は新しい。\n * `context.visited` を共有するので、既に訪問したアドレスは二度走らない。\n * 引き取った先の展開がさらに差分を起こすことがあるため、空になるまで回す。\n */\nfunction drainKeyedWalk(context: Context, callback: (address: IStateAddress) => void): void {\n for (let guard = 0; guard < MAX_DEPENDENCY_DEPTH; guard++) {\n const pending = takePendingKeyedWalk(context.stateElement);\n if (pending === null) {\n return;\n }\n pending.forEach((absAddress) => {\n _walkDependency(context, createStateAddress(absAddress.absolutePathInfo.pathInfo, absAddress.listIndex), callback);\n });\n }\n}\n\nexport function walkDependency(\n stateElement: IStateElement,\n startAddress: IStateAddress,\n staticDependency: Map<string, string[]>,\n dynamicDependency: Map<string, string[]>,\n listPathSet: Set<string>,\n stateProxy: IStateProxy,\n searchType: SearchType,\n callback: (address: IStateAddress) => void,\n options?: { listExpansion?: ListExpansion, keyedMergePath?: string | null }\n): IStateAddress[] {\n // 依存ゼロの葉パス(staticMap / dynamicMap にエントリ無し)は context や Set を\n // 割り当てず、開始アドレスの callback だけで完結する。リスト行の値書き込み\n // (update ホットパス)は set 毎にここを通る。開始アドレスへの callback は\n // 従来の walk 先頭と同一で、戻り値(依存アドレス群)も従来どおり空。\n //\n // ここは `drainKeyedWalk` を通らない。積むのは `createListDiff` の中だけで、この経路は\n // それを呼ばないので**自分が積んだ分を取り残すことはない**。理屈の上で残るのは\n // 「ウォークの外(`applyChangeToFor` / `collectWildcardIndexes`)で積まれ、そのバッチの\n // ウォークがこの fast path だけだった」場合に限られる。積む経路は 2 本あり、根拠は同じでない:\n // - `moveIndexWatchers`(`$eqIndex` 最内段)— 同じリストの 2 度目の `createListDiff` は\n // キャッシュに当たり、`oldIndexes === newIndexes` で早戻りして積まない。\n // - `rekeyIndexSubscriptions`(`$eqIndex` 外段)— `syncListIndexes` から呼ばれるので\n // **キャッシュ命中でも早戻りしない**。それでも取り残しが観測されないのは、積んだ直後の\n // バッチに必ず「その置換を起こした書き込み」のウォークが居て、そこで引き取られるから。\n // こちらは「構造上ありえない」ではなく「実測で 0」— だから下の番人が要る\n // (同一バッチ 2 回のリスト置換 × 外段 `$eqIndex` でも pending 0・描画も正常)。\n // ここに drain を足すなら保留の有無を見る `WeakMap#get` が 1 回増え、\n // 実測で **+3.3 ns/回**(この判定自体が 1.9 ns)— 起こせない事象のためにホットパスへ\n // 恒久的に乗せる取引としては割に合わないので置いていない。前提が崩れていないことは\n // `__tests__/dependency.keyedAncestorIndex.test.ts` の取り残し検査が見張っており、\n // そこが落ちたらここに drain を置くこと。\n const startPath = startAddress.pathInfo.path;\n if (!staticDependency.has(startPath) && !dynamicDependency.has(startPath)) {\n callback(startAddress);\n return [];\n }\n // パス単位のトポロジカル順位。値を一切読まないグラフ走査で毎回求める(キャッシュは\n // 持たない — topologicalRank.ts)。依存グラフは追記が基本だが、再帰の再セットでは\n // 旧世代の生成アクセサを指す辺が外れることがある(recursion/registry.ts の forgetGenerated)。\n const ranks = getTopologicalRanks(startPath, staticDependency, dynamicDependency, MAX_DEPENDENCY_DEPTH);\n const context: Context = {\n ranks: ranks,\n stateElement: stateElement,\n observedListValueByAbsAddress: new Map<IAbsoluteStateAddress, readonly unknown[]>(),\n staticMap: staticDependency,\n dynamicMap: dynamicDependency,\n result: new Set<IStateAddress>(),\n listPathSet: listPathSet,\n visited: new Set<IStateAddress>(),\n stateProxy: stateProxy,\n searchType: searchType,\n listExpansion: options?.listExpansion ?? \"full\",\n keyedMergePath: options?.keyedMergePath ?? null,\n quiet: new Set<IStateAddress>(),\n };\n _walkDependency(context, startAddress, callback);\n drainKeyedWalk(context, callback);\n // 観測したリスト値を state 側の基準として確定する(E1)。ウォークの最中に進めると\n // 同じウォーク内の 2 度目の観測が「変化なし」になるため、走査を終えてからまとめて書く\n // (`collectWildcardIndexes` の commitDiffBaseline と同じ形)。\n for (const [absAddress, value] of context.observedListValueByAbsAddress) {\n setStateListBaseline(absAddress, value);\n }\n return Array.from(context.result);\n}\n","/**\n * topologicalRank.ts — 依存グラフ(パス単位)のトポロジカル順位。\n *\n * 依存ウォークは list → list.* を展開するために途中でリスト実体を読む。この読み取りが\n * 正しい値を返すには「そのパスの入力(先行パス)がすべて dirty 化済み」である必要がある。\n * DFS ではダイヤモンド依存で片腕しか dirty 化していない段階で合流点を評価してしまうため、\n * パス単位の rank(= 最長経路長)を先に求め、rank の昇順で訪問する。\n *\n * rank の定義から、辺 (u → v) が存在すれば必ず rank(u) < rank(v) となる。したがって\n * rank r のバケットを処理する時点で rank < r のパスはすべて訪問(dirty 化)済みであり、\n * 同じバケット内のパス同士は互いに先行関係を持たない。\n *\n * 値を読まないグラフ走査なので、ウォーク 1 回あたりの追加コストは実測で誤差に\n * 収まる(メモ化しても差が出なかったため、キャッシュは持たない)。\n */\nimport { raiseError } from \"../raiseError\";\n\nexport function getTopologicalRanks(\n startPath: string,\n staticMap: Map<string, string[]>,\n dynamicMap: Map<string, string[]>,\n maxDepth: number,\n): ReadonlyMap<string, number> {\n // 1) startPath から到達可能なパス部分グラフと入次数を求める(値は一切読まない)\n const adjacency: Map<string, string[]> = new Map();\n const inDegree: Map<string, number> = new Map();\n const pending: string[] = [startPath];\n inDegree.set(startPath, 0);\n while (pending.length > 0) {\n const path = pending.pop()!;\n if (adjacency.has(path)) {\n continue;\n }\n const staticDeps = staticMap.get(path);\n const dynamicDeps = dynamicMap.get(path);\n let deps: string[];\n if (staticDeps === undefined) {\n deps = dynamicDeps ?? [];\n } else if (dynamicDeps === undefined) {\n deps = staticDeps;\n } else {\n deps = staticDeps.concat(dynamicDeps);\n }\n adjacency.set(path, deps);\n for (let i = 0; i < deps.length; i++) {\n const dep = deps[i];\n inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);\n if (!adjacency.has(dep)) {\n pending.push(dep);\n }\n }\n }\n\n // 2) Kahn 法。rank は最長経路長(rank[v] = max(rank[u]) + 1)。\n // 入次数が 0 に落ちて queue に入ったパスだけが「確定」で、緩和の途中で\n // 暫定値が入っただけのパス(= 循環の一部)は確定扱いにしない。\n const ranks: Map<string, number> = new Map();\n const settled: Set<string> = new Set();\n const queue: string[] = [];\n for (const [path, degree] of inDegree) {\n if (degree === 0) {\n ranks.set(path, 0);\n settled.add(path);\n queue.push(path);\n }\n }\n for (let i = 0; i < queue.length; i++) {\n const path = queue[i];\n const nextRank = ranks.get(path)! + 1;\n if (nextRank > maxDepth) {\n raiseError(`Maximum dependency depth of ${maxDepth} exceeded. Possible circular dependency detected at path: ${path}`);\n }\n const deps = adjacency.get(path)!;\n for (let j = 0; j < deps.length; j++) {\n const dep = deps[j];\n if (nextRank > (ranks.get(dep) ?? -1)) {\n ranks.set(dep, nextRank);\n }\n const remaining = inDegree.get(dep)! - 1;\n inDegree.set(dep, remaining);\n if (remaining === 0) {\n settled.add(dep);\n queue.push(dep);\n }\n }\n }\n\n // 3) 循環に含まれるパスは rank が決まらない(入次数が 0 に落ちない)。\n // そもそも正しい評価順が存在しないので、順序保証を諦めて確定済みの\n // 最大 rank の次にまとめる。打ち切りは従来どおり visited が担う。\n // 暫定値が残っていると確定パスとの前後関係を誤って表すため、必ず上書きする。\n if (settled.size !== adjacency.size) {\n let maxRank = -1;\n for (const path of settled) {\n const rank = ranks.get(path)!;\n if (rank > maxRank) {\n maxRank = rank;\n }\n }\n const cycleRank = maxRank + 1;\n for (const path of adjacency.keys()) {\n if (!settled.has(path)) {\n ranks.set(path, cycleRank);\n }\n }\n }\n return ranks;\n}\n\n","/**\n * setByAddress.ts\n *\n * Stateの内部APIとして、アドレス情報(IStateAddress)を指定して\n * 状態オブジェクト(target)に値を設定するための関数(setByAddress)の実装です。\n *\n * 主な役割:\n * - 指定されたパス・インデックスに対応するState値を設定(多重ループやワイルドカードにも対応)\n * - getter/setter経由で値設定時はpushAddressでスコープを一時設定\n * - 存在しない場合は親pathInfoやlistIndexを辿って再帰的に値を設定\n * - 設定後はupdater.enqueueUpdateAddressで更新情報を登録\n *\n * 設計ポイント:\n * - ワイルドカードや多重ループにも柔軟に対応し、再帰的な値設定を実現\n * - finallyで必ず更新情報を登録し、再描画や依存解決に利用\n * - getter/setter経由のスコープ切り替えも考慮した設計\n */\n\nimport { liftAddress, absoluteAddressOf } from \"../../address/liftAddress\";\nimport { IAbsoluteStateAddress, IStateAddress } from \"../../address/types\";\nimport { DELIMITER, WILDCARD } from \"../../define\";\nimport { createListIndex, getHomeParentListIndex, getRowCacheStamp, setListIndexValue } from \"../../list/createListIndex\";\nimport { clearRowSwapPending, getElementAliases, getListIndexesByList, holdListAtParent, markRowSwapPending, isOwnedListIndexes, releaseListAtParent, setListIndexesByList } from \"../../list/listIndexesByList\";\nimport { getAddressesByLastListValue, getLastListValueByAbsoluteStateAddress, hasRenderedList, markSwappedList, rebaseRenderedList, setLastListValueByAbsoluteStateAddress } from \"../../list/lastListValueByAbsoluteStateAddress\";\nimport { ISwapInfo } from \"./types\";\nimport { createListDiff, keepPreviousList, retireRows } from \"../../list/createListDiff\";\nimport { collectFieldWrites, IKeyedListMerge, mergeKeyedList } from \"../../list/mergeKeyedList\";\nimport { IListIndex } from \"../../list/types\";\nimport { getPathInfo } from \"../../address/PathInfo\";\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { wildcardScopeMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { getUpdater } from \"../../updater/updater\";\nimport { updateBatch } from \"../../updater/updateBatch\";\nimport { IStateHandler, IStateProxy } from \"../types\";\nimport { getByAddress, isAliasGetter } from \"./getByAddress\";\nimport { isCacheable } from \"./isCacheable\";\nimport { hasByAddress } from \"./hasByAddress\";\nimport { markSwapBaselineList } from \"../../list/swapBaselineList\";\nimport { getSwapInfoByList, setSwapInfoByList } from \"./swapInfo\";\nimport { walkDependency } from \"../../dependency/walkDependency\";\nimport { NOT_HANDLED } from \"../../core/addressHooks\";\nimport { hasKeyedDependents, hasKeyedDescendants, keyedDependents, keyedDescendantDependents, moveIndexWatchers } from \"../../dependency/keyedDependency\";\nimport { dirtyCacheEntryByAbsoluteStateAddress, setCacheEntryByAbsoluteStateAddress } from \"../../cache/cacheEntryByAbsoluteStateAddress\";\nimport { config } from \"../../config\";\nimport { devtoolsSink } from \"../../platform/devtoolsSink\";\nimport { beginPropagationTransaction, getCurrentPropagationContext } from \"../../propagation/propagation\";\nimport { consumeElementWrite } from \"../occurrenceWrite\";\nimport { listIndexAtWildcard } from \"../../list/wildcardLevel\";\nimport { getByAddressSymbol } from \"../symbols\";\n\n/**\n * 宣言済みパスの `prev` 台帳へ旧値を記録する。台帳を読むのは `$watch`\n * (docs/state-watch-hook-design.md §4-1)と `$scan` の `from`(docs/state-scan-design.md §2-1)。\n *\n * same-value guard が既に読んだ旧値だけを使い、そのための追加読みはしない。\n * 台帳の実体は watch/addressHooks.ts の writeObserve hook(`$watch` / `$scan` を宣言した state にだけ付く)。\n * 宣言の無い state は `addressHooks` の null 判定 1 個で抜ける。\n */\nfunction recordDeclaredPrevValue(\n stateElement: IStateHandler[\"stateElement\"],\n path: string,\n absAddress: IAbsoluteStateAddress,\n oldValue: unknown,\n hasOldValue: boolean,\n): void {\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const observers = hooks.writeObserve;\n for (let i = 0; i < observers.length; i++) {\n observers[i](stateElement, path, absAddress, oldValue, hasOldValue);\n }\n }\n}\n\n// 書き込み・入れ替えの後の通知(設計案 H1 の written / swapped): 観測面を持つ機能(DCC の\n// bindable イベント・watch の旧値台帳)が state に付けた hook だけを呼ぶ\nfunction notifyWritten(stateElement: IStateHandler[\"stateElement\"], pathInfo: IStateAddress[\"pathInfo\"], detail?: { readonly value: unknown }): void {\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const written = hooks.written;\n for (let i = 0; i < written.length; i++) {\n written[i](stateElement, pathInfo, detail);\n }\n }\n}\n\nfunction notifySwapped(stateElement: IStateHandler[\"stateElement\"], elementAbsAddress: IAbsoluteStateAddress, displacedAbsAddress: IAbsoluteStateAddress): void {\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const swapped = hooks.swapped;\n for (let i = 0; i < swapped.length; i++) {\n swapped[i](stateElement, elementAbsAddress, displacedAbsAddress);\n }\n }\n}\n\n// Phase 3: 書き込み時点の因果 context を update record に付与する。\n// binding 経由の書き込みは呼び出し元の dynamic scope から context を引き継ぎ、\n// binding 外からの API update は新しい transaction を開始する(設計書 §4 規則 1)。\n// 依存 walk で enqueue される派生アドレスも同じ書き込みの因果に属する。\n\n// 鍵付き購読(`$eq` 系、dependency/keyedDependency.ts)への通知。同値ガードが読んだ旧値と\n// 新値の鍵に登録された行だけを dirty 化して enqueue する。購読の無いパスは Map 参照 2 回で抜ける。\n// 祖先への書き込み(`$eq(\"sel.id\")` に対する `sel = {…}`)は配下の鍵付きパスへ知らせる。その旧値は\n// 同値ガードが読めなかったときだけ `readOld` で書き込み前に読む\nfunction notifyKeyed(\n stateElement: IStateHandler[\"stateElement\"],\n path: string,\n hasOldValue: boolean,\n oldValue: unknown,\n value: unknown,\n readOld: () => unknown,\n): IAbsoluteStateAddress[] | null {\n const direct = hasKeyedDependents(stateElement, path);\n const descendants = hasKeyedDescendants(stateElement, path);\n if (!direct && !descendants) {\n return null;\n }\n const subscribers: IAbsoluteStateAddress[] = [];\n const enqueue = createKeyedEnqueue(subscribers);\n if (direct) {\n keyedDependents(stateElement, path, hasOldValue, oldValue, value).forEach(enqueue);\n }\n if (descendants) {\n keyedDescendantDependents(stateElement, path, hasOldValue ? oldValue : readOld(), value).forEach(enqueue);\n }\n return subscribers;\n}\n\n/** 鍵付き通知の伝播 context(`createKeyedEnqueue` と `walkKeyedDependents` で 1 本にする) */\nfunction keyedPropagationContext(): ReturnType<typeof getCurrentPropagationContext> | null {\n return config.enablePropagationContext ? (getCurrentPropagationContext() ?? null) : null;\n}\n\n/** 集めた購読者を `collected` へ控える(依存ウォークの起点。`walkKeyedDependents` が書き込み後に使う) */\nfunction createKeyedEnqueue(collected: IAbsoluteStateAddress[]): (absAddress: IAbsoluteStateAddress) => void {\n const updater = getUpdater();\n const context = keyedPropagationContext();\n return (absAddress: IAbsoluteStateAddress): void => {\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n updater.enqueueAbsoluteAddress(absAddress, context);\n collected.push(absAddress);\n };\n}\n\n/**\n * 鍵付き購読の購読者から、その**依存先**へ通知を伝播する。\n *\n * 鍵付き購読(`$eq` 系)は意図的に依存グラフに載らない(載せると選択の更新が全行に広がる)。\n * その代わり `notifyKeyed` が購読者のアドレスを直に enqueue するのだが、**そこで止まっていた**ため\n * 「鍵付き getter に依存する別の getter / バインディング」が陳腐化していた(素のツリーで再現。\n * docs/state-keyed-derived-propagation.md)。通常の書き込みは `notifyWrite` が同じ enqueue の後に\n * `walkDependency` を回しており、鍵付きだけが非対称だった。\n *\n * **収集は書き込みの前・ウォークはこの関数で書き込みの後**に分ける。`notifyKeyed` が\n * `Reflect.set` より前に走るのは旧値の鍵で「前に選ばれていた行」を引くためで、一方\n * `walkDependency` はリスト展開で書き込み**後**の値を読む前提(`notifyWrite` が `finally` に\n * いるのと同じ理由)。前で walk すると書き込み前の配列で展開してしまう。\n *\n * ホットパス(R2): 鍵付き選択の存在理由は「選択の更新を 2 行に抑える」ことなので、購読者ごとに\n * 依存表を 2 回引くだけの短絡を先に置く。依存先を持つ購読者は稀で、持たなければ\n * `createStateAddress` の割り当ても `walkDependency` の呼び出しも起きない。\n */\nfunction walkKeyedDependents(\n subscribers: IAbsoluteStateAddress[] | null,\n receiver: any,\n handler: IStateHandler,\n): void {\n if (subscribers === null || subscribers.length === 0) {\n return;\n }\n const stateElement = handler.stateElement;\n const staticDependency = stateElement.staticDependency;\n const dynamicDependency = stateElement.dynamicDependency;\n const updater = getUpdater();\n const context = keyedPropagationContext();\n for (let i = 0; i < subscribers.length; i++) {\n const treePath = subscribers[i].absolutePathInfo;\n const path = treePath.pathInfo.path;\n // 依存先ゼロの購読者(大多数)は Map 参照 2 回で抜ける\n if (!staticDependency.has(path) && !dynamicDependency.has(path)) {\n continue;\n }\n const address = createStateAddress(treePath.pathInfo, subscribers[i].listIndex);\n walkDependency(\n stateElement,\n address,\n staticDependency,\n dynamicDependency,\n stateElement.listPaths,\n receiver as IStateProxy,\n \"new\",\n (depAddress: IStateAddress) => {\n // 起点(購読者自身)は createKeyedEnqueue が済ませている — 二重 enqueue を避ける\n if (depAddress === address) return;\n const absDepAddress = liftAddress(stateElement, depAddress);\n dirtyCacheEntryByAbsoluteStateAddress(absDepAddress);\n updater.enqueueAbsoluteAddress(absDepAddress, context);\n },\n // `notifyWrite` と同じ規準。購読者は普通リストではないので実質効かないが、\n // 万一リストでも未変更行まで展開しない\n { listExpansion: \"diff\" },\n );\n }\n}\n\n/**\n * `$postUpdate` の鍵付き通知(proxy/apis/postUpdate.ts)。\n *\n * in-place 変異を通知する正規の idiom なので、呼ばれた時点で**変異はもう起きている** —\n * `setByAddress` と違って旧値がどこにも無い。`hasOldKey = false` で引くと、台帳が控えている\n * 「最後に観測した鍵」(`lastValue`)が旧値の代わりになり、前に選ばれていた行も\n * 新しく選ばれる行も一緒に再評価される。これが無いと `raw.sel.id = 2; $postUpdate(\"sel.id\")` で\n * 前の行が真のまま残った(2.6.0 で `setByAddress` 側に入れた修正の取りこぼし)。\n *\n * 現在値の読みは購読があるときだけ行う(`readCurrent` の thunk)。\n */\nexport function notifyKeyedPostUpdate(\n stateElement: IStateHandler[\"stateElement\"],\n path: string,\n readCurrent: () => unknown,\n receiver: any,\n handler: IStateHandler,\n): void {\n const direct = hasKeyedDependents(stateElement, path);\n const descendants = hasKeyedDescendants(stateElement, path);\n if (!direct && !descendants) {\n return;\n }\n const current = readCurrent();\n const subscribers: IAbsoluteStateAddress[] = [];\n const enqueue = createKeyedEnqueue(subscribers);\n if (direct) {\n keyedDependents(stateElement, path, false, undefined, current).forEach(enqueue);\n }\n if (descendants) {\n keyedDescendantDependents(stateElement, path, undefined, current, false).forEach(enqueue);\n }\n // `$postUpdate` は変異が**もう起きた**後に呼ばれるので、収集とウォークを分ける必要がない\n // (`setByAddress` 側だけが `Reflect.set` を跨ぐ)。派生先へ届かない穴は両方にあった\n walkKeyedDependents(subscribers, receiver, handler);\n}\n\nfunction notifyWrite(\n address : IStateAddress,\n absAddress: IAbsoluteStateAddress,\n receiver : any,\n handler : IStateHandler,\n keyedMergePath: string | null,\n cacheable: boolean,\n listExpansion: \"diff\" | \"full\" = \"diff\"\n): void {\n const propagationContext = config.enablePropagationContext\n ? (getCurrentPropagationContext() ?? beginPropagationTransaction(-1))\n : null;\n const updater = getUpdater();\n const stateElement = handler.stateElement;\n updater.enqueueAbsoluteAddress(absAddress, propagationContext);\n // 書いたアドレス自身のキャッシュを、依存ウォークより先に無効化する(#274)。ウォークはリスト展開\n // (list → list.*)と動的依存の親リスト展開で、書いたパスの値を読む。ワイルドカードを含むリストパス\n // (`groups.*.items`)はキャッシュ対象なので、無効化しないと書き込み前の配列がヒットし、基準との差分が\n // 「変化なし」になって置き換える前の行だけを展開する(長い配列に置き換えた分の行が着地しない)。\n // 依存先は下の callback が訪問のたびに読む前に無効化するが、開始アドレスは callback が飛ばす\n // (二重 enqueue の防止)のでここで済ませる — 開始アドレスも callback で無効化する $postUpdate と同じ順序。\n // 値は直後の commitWriteCache が載せ直す。\n if (cacheable) {\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n }\n // 依存関係のあるキャッシュを無効化(ダーティ)、更新対象として登録\n const walk = (start: IStateAddress): IStateAddress[] => walkDependency(\n stateElement,\n start,\n stateElement.staticDependency,\n stateElement.dynamicDependency,\n stateElement.listPaths,\n receiver as IStateProxy,\n \"new\",\n (depAddress: IStateAddress) => {\n // キャッシュを無効化(ダーティ)\n if (depAddress === address) return;\n const absDepAddress = liftAddress(stateElement, depAddress);\n dirtyCacheEntryByAbsoluteStateAddress(absDepAddress);\n // 更新対象として登録\n updater.enqueueAbsoluteAddress(absDepAddress, propagationContext);\n },\n // リスト置換時は追加行・位置変更行のみ展開する(未変更行の再訪を省く。\n // $postUpdate の手動リフレッシュは従来通り全行展開のまま)\n { listExpansion, keyedMergePath }\n );\n walk(address);\n // 入れ子のリストの行の下への書き込みは、同じ要素オブジェクトを表す別の配列の行(共有された配列の写し)のアドレスにも知らせる\n // (#393)。描画だけをやり直させる — 着地はこの書き込みのアドレス 1 つで、依存ウォークもしない(同じバッチの差分が\n // 途中の配列に作った行も同じ要素を表すので、そこからリストを展開すると台帳の行の親をその行へ付け替えてしまう)\n if (address.pathInfo.lastSegment !== WILDCARD && address.listIndex !== null && address.listIndex.parentListIndex !== null) {\n const row = address.listIndex;\n const listPathInfo = address.pathInfo.wildcardParentPathInfos[row.position];\n const listAddress = createStateAddress(listPathInfo, row.parentListIndex);\n const readList = () => receiver[getByAddressSymbol](listAddress);\n const notify = (aliasAbsAddress: IAbsoluteStateAddress) => {\n dirtyCacheEntryByAbsoluteStateAddress(aliasAbsAddress);\n updater.enqueueRenderOnlyAddress(aliasAbsAddress);\n };\n for (const alias of getElementAliases(row, readList)) {\n notify(liftAddress(stateElement, createStateAddress(address.pathInfo, alias)));\n }\n // 同じ配列を別のパスの `for` も描いている(`{ items: A, alt: A }` の `alt`)なら、その `for` の同じ行の同じ葉にも知らせる\n // (描画の基準の逆引き — 描画だけ)。葉の書き込みの依存はパスごとなので、`alt` の `for` は描き直されなかった\n const leaf = address.pathInfo.path.slice(address.pathInfo.wildcardPaths[row.position].length);\n for (const drawn of getAddressesByLastListValue(liftAddress(stateElement, listAddress), readList())) {\n const drawnPathInfo = drawn.absolutePathInfo.pathInfo;\n if (drawnPathInfo !== listPathInfo && drawnPathInfo.wildcardCount === listPathInfo.wildcardCount) {\n notify(absoluteAddressOf(stateElement, getPathInfo(drawnPathInfo.path + DELIMITER + WILDCARD + leaf), row));\n }\n }\n }\n // 書いた行のリストを、別のパスの `for` が同じ配列として描いている(配列をそのまま返す getter —\n // TodoMVC の `get shown() { return this.filter === \"all\" ? this.todos : … }`)なら、そのパスの同じ行へも\n // 知らせる(#362)。行の台帳は配列ごとに 1 組なので 2 つのパスの行は同じ listIndex だが、キャッシュ・依存・\n // 束縛はパスごとで、`todos.*.done` の依存ウォークは `shown.*.done` に届かず、行は次にリストを描くまで\n // 古いままだった。候補は、書いたパスの各段のリストを読んだ getter のうち、`for` で描き、読んだパスの値を\n // そのまま返したことのあるもの(getByAddress の isAliasGetter)— 段ごとに依存の表を 1 回引くだけで、別名の\n // 無いページ(写しだけを返す getter のページを含む)の書き込みには値の読みを足さない。行の深さが同じ(getter の\n // ワイルドカードの数がその段と同じ)で、いまも値が同じ配列のときだけ別名とする。要素の書き込みは行が新しくなる\n // (renewReplacedRow・入れ替え)ので、別名の `for` も描き直させる\n const { path, lastSegment, wildcardCount, wildcardParentPaths, wildcardParentPathInfos } = address.pathInfo;\n const listIndex = address.listIndex;\n for (let level = 0; listIndex && level < wildcardCount; level++) {\n const parentListIndex = listIndexAtWildcard(listIndex, level - 1, wildcardCount);\n for (const aliasPath of stateElement.dynamicDependency.get(wildcardParentPaths[level]) ?? []) {\n const aliasPathInfo = getPathInfo(aliasPath);\n if (stateElement.listPaths.has(aliasPath) && aliasPathInfo.wildcardCount === level && isAliasGetter(aliasPathInfo) &&\n receiver[getByAddressSymbol](createStateAddress(aliasPathInfo, parentListIndex)) ===\n receiver[getByAddressSymbol](createStateAddress(wildcardParentPathInfos[level], parentListIndex))) {\n const aliasAddress = createStateAddress(getPathInfo(aliasPath + path.slice(wildcardParentPaths[level].length)), listIndex);\n walk(aliasAddress);\n if (lastSegment === WILDCARD) {\n updater.enqueueRenderOnlyAddress(liftAddress(stateElement, aliasAddress.parentAddress!));\n }\n }\n }\n }\n}\n\n/**\n * 書き込み完了後のキャッシュ整合(Issue #234)。\n *\n * ワイルドカードのデータパス(リスト行)は代入値がそのまま格納値なので、\n * 代入値を dirty:false で載せて次回の読みを省く。\n *\n * アクセサペア(getterPaths に載るパス)は getter が正本であり、setter は\n * 命令的な代入に過ぎない。代入値を getter の評価結果として固定すると\n * - setter が正規化・分配した結果と読みが食い違う\n * - getter が一度も評価されず動的依存が張られない → 依存先を書いても\n * walkDependency がこのキャッシュを dirty にできず、永続的に stale になる\n * (プリミティブ代入は同値ガードの旧値読みで偶然 getter が走るが、\n * オブジェクト代入は同値ガードを素通りするため救済がない)\n * ため、キャッシュを dirty にして次回の読みで getter を再評価させる。\n */\nfunction commitWriteCache(\n stateElement: IStateHandler[\"stateElement\"],\n path: string,\n absAddress: IAbsoluteStateAddress,\n value: unknown,\n cacheable: boolean,\n): void {\n if (!cacheable) {\n return;\n }\n if (stateElement.getterPaths.has(path)) {\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n return;\n }\n setCacheEntryByAbsoluteStateAddress(absAddress, {\n value: value,\n dirty: false,\n // 読み側(getByAddress)と同じ世代印・行の印を付ける — ヒットになるのは両方が一致する項目だけ\n // (cache/types.ts の `generation` / `rowStamp`)。行の印は書き込みの依存ウォークが進めた後の値\n generation: stateElement.stateGeneration,\n rowStamp: absAddress.absolutePathInfo.pathInfo.lastSegment === WILDCARD ? undefined : getRowCacheStamp(absAddress.listIndex)\n });\n}\n\n/**\n * 要素の書き込み(`items.0 = {…}`)でその位置の要素が別の値に替わるなら、その位置を新しい行にし、\n * 新しい行のアドレスを返す(#333)。`for` が描くリストの入れ替えの経路(`_setByAddressWithSwap`)と\n * 同じ同一性モデル — 行は要素に付き、別の要素は別の行。\n *\n * 行の下のパス(`items.*.name`・行 getter)はワイルドカードを含むので行の listIndex ごとに\n * キャッシュされる(isCacheable)。行を据え置くと、行から子へ静的な辺の無い(`for` で描いていない)\n * リストでは、依存ウォークが子に届かず古い値が返り続けた。新しい行には子のキャッシュが無いので、\n * どう読まれても(直接添字・`$getAll`・getter)書いた要素から読み直す。差し替えた行は退役させる —\n * `$watch` / `$scan` の着地はその行を捨てて新しい行で受け(rowLanding.ts)、要素と一緒に持ち越された\n * 入れ子のリストの行集合は、次の解決で新しい行へ付け替わる(#256)。\n * 要素パス自身の `$watch` の prev は、同じバッチでその位置の前の行が記録した値を引き継ぐ(入れ替えの\n * 経路の notifySwapped と同じ。引き継がないと、同じ位置を 2 回書いたとき 1 回目の値が prev になる)。\n * 同じ要素の書き込み(通知だけの再代入)は行を据え置く。台帳のその位置がこのアドレスの行でなければ\n * (台帳が無い・listIndex の無いアドレス)何もしない。\n */\nfunction renewReplacedRow(\n stateElement: IStateHandler[\"stateElement\"],\n address: IStateAddress,\n list: any,\n key: PropertyKey | undefined,\n value: unknown,\n): IStateAddress {\n const row = address.listIndex!;\n const listIndexes = getListIndexesByList(list);\n if (listIndexes?.[key as number] !== row || list[key as number] === value) {\n return address;\n }\n const renewed = createListIndex(row.parentListIndex, key as number, getHomeParentListIndex(row));\n // この配列を描いた `for` が描いたのは書き込む前の行。書き込む前の並びの写しに前の台帳を持たせ、描画の\n // 基準をそこへ移す(入れ替えの経路の notifySwappedList と同じ)。別のパスの `for`(配列をそのまま返す\n // getter・同じ配列を持つ別のキーや state)は台帳の差し替えを知らず、描いていない新しい行を描いたつもりで\n // 差分を取っていた。移すのは描いた後の最初の書き込みだけ。同じ配列の入れ替え(別のキーの `for` が描く)の\n // 途中なら、描いたのは入れ替えの前の並び — 配列もその途中の姿なので、入れ替えが控えた写しを使う\n if (hasRenderedList(list)) {\n const image = getSwapInfoByList(list) ?? { value: list.slice(), listIndexes: listIndexes! };\n setListIndexesByList(image.value, image.listIndexes);\n rebaseRenderedList(list, image.value);\n }\n // 台帳の配列を持つ別の持ち手(差分のキャッシュ・別の配列の台帳・上の写し・入れ替え・`$eqIndex` の監視)が\n // いれば、写してから差し替える — その場で書き換えると持ち手の行まで書き換わる(#335)。前の書き込みが\n // 写したまま誰も持っていない台帳は、その場で書き換える(listIndexesByList.ts の isOwnedListIndexes)。\n // `$eqIndex` の監視は台帳の配列に付くので一緒に移す(移した先は監視が持つので、所有を外す)\n const next = isOwnedListIndexes(listIndexes!) ? listIndexes! : listIndexes!.slice();\n next[key as number] = renewed;\n setListIndexesByList(list, next, true);\n moveIndexWatchers(listIndexes!, next);\n retireRows([row]);\n const renewedAddress = createStateAddress(address.pathInfo, renewed);\n notifySwapped(stateElement, liftAddress(stateElement, renewedAddress), liftAddress(stateElement, address));\n return renewedAddress;\n}\n\nfunction _setByAddress(\n target : object,\n address : IStateAddress,\n absAddress: IAbsoluteStateAddress,\n value : any,\n receiver : any,\n handler : IStateHandler,\n keyedMergePath: string | null,\n cacheable: boolean,\n // false なら書き込みだけ(入れ替えの経路は、どの行に着地させるかを書いた後で決める — _setByAddressWithSwap)\n notify = true,\n): any {\n try {\n if (address.pathInfo.path in target) {\n if (handler.stateElement.setterPaths.has(address.pathInfo.path)) {\n // setterの中で参照の可能性があるので、addressをプッシュする。\n // setter は命令的な代入であって派生(getter)ではないため、実行中の\n // 読み取り(同値ガードの旧値読み・$1 参照等)で依存を張らない。\n // アクセサペア(get/set 同名パス)では、抑止しないと setter 内の内部\n // 書き込みの同値ガード読みが「getter の依存」として誤登録される。\n handler.pushAddress(address);\n handler.beginUntrack();\n try {\n return Reflect.set(target, address.pathInfo.path, value, receiver);\n } finally {\n handler.endUntrack();\n handler.popAddress();\n }\n\n } else {\n return Reflect.set(target, address.pathInfo.path, value);\n }\n } else {\n const parentAddress = address.parentAddress;\n if (parentAddress === null) {\n return Reflect.set(target, address.pathInfo.path, value);\n }\n const parentValue = getByAddress(target, parentAddress, receiver, handler);\n const lastSegment = address.pathInfo.segments[address.pathInfo.segments.length - 1];\n if (lastSegment === WILDCARD) {\n // 読み取り側(getByAddress)と同じ取り違え。書き込みでも何段必要かを言う。\n const index = address.listIndex?.index ?? raiseError(\n wildcardScopeMessage(\n `path \"${address.pathInfo.path}\"`,\n address.pathInfo.wildcardCount,\n address.listIndex?.length ?? 0,\n ),\n );\n return Reflect.set(parentValue, index, value);\n } else {\n // 公開 getter への書き込み(X9)は setByAddressCore の fast path(親がオブジェクトの\n // 未存在キー)で dispatch 済み。ここに来るのは親が非オブジェクトの形だけ\n return Reflect.set(parentValue, lastSegment, value);\n }\n }\n } finally {\n if (notify) {\n notifyWrite(address, absAddress, receiver, handler, keyedMergePath, cacheable);\n }\n }\n}\n\nfunction _setByAddressWithSwap(\n target : object,\n address : IStateAddress,\n absAddress: IAbsoluteStateAddress,\n value : any,\n receiver : any,\n handler : IStateHandler,\n keyedMergePath: string | null,\n cacheable: boolean,\n elementWrite: number\n) {\n // elementsの場合はswapInfoを準備(キーはリストの配列そのもの — swapInfo.ts 参照)\n const parentAddress = address.parentAddress ?? raiseError(`address.parentAddress is undefined path: ${address.pathInfo.path}`);\n const parentValue = getByAddress(target, parentAddress, receiver, handler) ?? [];\n const swapInfo = getSwapInfoByList(parentValue);\n if (elementWrite) {\n // 要素から来た書き込み(行の要素が自分の行へ出す値)は、その行の値の更新で入れ替えではない\n // (proxy/occurrenceWrite.ts・#337)。行はそのまま、途中の入れ替えがあればその写しでもこの行の値にして、\n // 揃ったかの突き合わせがこの行を動かさないようにする\n if (swapInfo) {\n swapInfo.value[address.listIndex!.index] = value;\n }\n // 行はこの位置のまま書いた要素を映す。同じ行を持つ前の配列へ戻したとき、差分がこの行を描き直させる(#359)\n setListIndexValue(address.listIndex!, value);\n return _setByAddress(target, address, absAddress, value, receiver, handler, keyedMergePath, cacheable);\n }\n const row = address.listIndex!;\n // 書き込む前の並び。台帳の配列は書き換えないので写さない(下の matchSwappedListIndexes)\n const info = swapInfo ?? {\n value: [...parentValue], listIndexes: getListIndexesByList(parentValue) ?? [], written: new Map(),\n };\n try {\n // 通知は下で、入れ替えが揃ったかを見てから(揃うと行が動くので、着地させる行が変わる — #361)\n return _setByAddress(target, address, absAddress, value, receiver, handler, keyedMergePath, cacheable, false);\n } finally {\n const currentListIndexes = matchSwappedListIndexes(info, parentValue, parentAddress.listIndex);\n if (currentListIndexes === null) {\n setSwapInfoByList(parentValue, info);\n // 揃うまで行はこの位置のまま書いた要素を映す(#359 — 上の要素から来た書き込みと同じ)。この書き込みは\n // この行に着地する\n setListIndexValue(row, value);\n info.written.set(row, updateBatch);\n markRowSwapPending(row);\n notifyWrite(address, absAddress, receiver, handler, keyedMergePath, cacheable);\n } else {\n // 揃ったので swapInfo を削除し、台帳を新しい配列に差し替える。その場で書き換えると、同じ配列を\n // 持つ差分のキャッシュ(置き換えの差分の newIndexes)や、同じ中身の配列の台帳(createListDiff の\n // isSameList)まで書き換わり、`for` が描いていない行を描いたつもりで差分を取る(#335)\n setSwapInfoByList(parentValue, null);\n // このバッチで書いた位置 — この書き込みと、揃う前の書き込みの位置(行の index を振り直す前に控える・#361)。\n // 揃う前の書き込みで書いた値を映していた行は、自分の要素(書き込む前のその位置の要素)に戻す(#359。\n // 押し出された行に書いた値を残すと、着地の選別がその値の行と取り違える)\n const positions = [row.index];\n clearRowSwapPending(row);\n info.written.forEach((batch, written) => {\n clearRowSwapPending(written);\n setListIndexValue(written, info.value[written.index]);\n if (batch === updateBatch) {\n positions.push(written.index);\n }\n });\n // この書き込みの行はまだ着地していない — 揃う前に同じ行へ書いていても、その後の読み(同値ガード)が前の値を\n // キャッシュに載せ直しているので、書いた位置に残るなら通知し直す(notifySwappedList)\n info.written.delete(row);\n currentListIndexes.forEach((listIndex, i) => {\n listIndex.index = i;\n });\n setListIndexesByList(parentValue, currentListIndexes);\n // `$eqIndex` の監視は台帳の配列に付く(差分が付け替えるのと同じ)\n moveIndexWatchers(info.listIndexes, currentListIndexes);\n notifySwappedList(parentAddress, info, parentValue, currentListIndexes, receiver, handler, positions);\n }\n }\n}\n\n/**\n * 要素書き込みの入れ替えが揃ったかを見て、揃っていればいまの並びの台帳を返す(#4・#337)。\n *\n * 行は値に付いて動く: 値の変わらない位置はその行のまま、値の変わった位置には、その値を書き込む前に\n * 持っていて今は別の値になった行(動いてきた行)を充て、無ければ新しい行を作る。\n * 書き込む前の並びにあった値が、動いてきた行より多くの位置に現れているうちは入れ替えの途中(片側だけを\n * 書いた — 値がまだ元の位置にも残っている)で、null を返す。その間、台帳は書き込む前の行のままなので、\n * 位置の読み書きはその行の index で当たり、表示も位置どおりに正しい。\n * 揃った印は値が重複しないことではない(#337)。同じ値の行を含む並びの入れ替えも揃い、別の行と同じ値を\n * 書いて同じ値の行が増えた並び(入れ替えの片側と区別できない)は、揃わないまま位置どおりに描かれる。\n * 位置は台帳の行の分だけ見る(行の無い位置は書き込みの宛先にならない)。\n * 手間は 1 回の書き込みにつき O(n)(`$setAll` は n 回書く)。動いてきた行の無い値が書き込む前の並びに\n * あるかは、1 つ目は `includes`、2 つ目からは Set で引く(1 つずつ引くと、新しい値を多く書いた並びで\n * O(k·n) になる)。新しい行は、揃ったと決まってから作る。行の index の振り直しは呼び手がする(振り直す前の\n * 位置で、このバッチに書いた位置を控えるため)。\n */\nfunction matchSwappedListIndexes(swapInfo: ISwapInfo, list: unknown[], parentListIndex: IListIndex | null): IListIndex[] | null {\n const { value: before, listIndexes: rows } = swapInfo;\n const movedByValue = new Map<unknown, IListIndex[]>();\n rows.forEach((row, i) => {\n if (list[i] !== before[i]) {\n const moved = movedByValue.get(before[i]);\n if (moved) {\n moved.push(row);\n } else {\n movedByValue.set(before[i], [row]);\n }\n }\n });\n let lookups = 0;\n let beforeValues: Set<unknown> | undefined;\n const listIndexes: (IListIndex | undefined)[] = [];\n for (let i = 0; i < rows.length; i++) {\n const listIndex = list[i] === before[i] ? rows[i] : movedByValue.get(list[i])?.shift();\n if (!listIndex && (lookups++ ? (beforeValues ??= new Set(before)).has(list[i]) : before.includes(list[i]))) {\n return null;\n }\n listIndexes.push(listIndex);\n }\n return listIndexes.map((listIndex, i) => listIndex ?? createListIndex(parentListIndex, i));\n}\n\n/**\n * 要素書き込みの入れ替え(または行の置き換え)が揃ったとき、リストを「書き込む前の並び →\n * いまの並び」の置換として描画し直させる(#4 — 同一性モデル)。\n *\n * 台帳は上で「listIndex は値に付いて動く」形に組み替え済み。ところが `for` の描画基準\n * (lastListValue)はその場で書き換えられた同じ配列なので、差分に入れ替えが映らず、ブロックは\n * 動かないまま中身だけが書き換わっていた。基準を「書き込む前の並びの写し」とその台帳の写しに\n * すると、`for` は写しといまの配列の差分を listIndex の同一性で突き合わせ(createListDiff の\n * calcDiffIndexes)、ブロックを値と一緒に動かし、置き換えた行を作り直す。基準を写しに替えるのは、\n * 描画基準がいま入れ替えている配列そのもののときだけ — 同じバッチで配列を丸ごと書き換えた後なら、\n * 描画はまだその前の配列で、そちらとの差分が入れ替えも含む。\n *\n * 行ごとの扱い(書き込む前といまの台帳の位置を比べる):\n * - 位置が変わらない行: 何もしない。\n * - 新しい listIndex の行(書き込む前の台帳に無い): その位置の値の書き込みとして着地させる。差し替えられた\n * 行は `for` の差分で退役し、その行のアドレスの着地は `$watch` / `$scan` の選別で捨てられるので、\n * 着地は新しい行が持つ(#274 の「その位置のいまの値で 1 回」)。要素パス自身の prev は、書き込みがその位置の\n * 前の行のアドレスで記録した値を引き継ぐ(引き継がないと `$watch \"items.*\"` の prev が消える)。ブロックは\n * `for` が同じ位置で外す行の Content をその場で使い回す(applyChangeToFor の collectInPlaceContents)。\n * - 値と一緒に動いた行: 値は変わっていないので、依存を無効化して描画だけをやり直す。書き込みを別の\n * バッチに分けると、途中のバッチで別の値を描いた行が残る。\n * 書き込みの着地は書いた位置(#361)。このバッチで書いた位置(`positions` — 揃えた書き込みと、揃う前の書き込み)\n * にいま居る行のうち、このバッチでまだ着地していない行(書いた行のままの位置・動いてきた行)を、その位置の値の\n * 書き込みとして着地させる。prev は、その位置の書き込みが書いた行のアドレスで記録した値を引き継ぐ。揃う前の\n * 書き込みはその時点で位置に居た行に着地しており、揃うとその行は値に付いて動く — 同じバッチの書き込みだけで\n * 揃う入れ替えなら動いた先もこのバッチで書いた位置なので、その着地がそのまま当たる。前のバッチの書き込みと揃う\n * と、揃えた書き込みの行は前のバッチで書いた位置へ動く — そこはこのバッチでは変わっていないので着地させない。\n * リスト自身も描画だけを積む(updater の enqueueRenderOnlyAddress)。書き込みとして積むと、`items` の\n * `$watch` が配列の参照の変わらない入れ替えで発火する。\n */\n\nfunction notifySwappedList(\n parentAddress: IStateAddress,\n swapInfo: ISwapInfo,\n currentParentValue: unknown,\n currentListIndexes: readonly IListIndex[],\n receiver: any,\n handler: IStateHandler,\n positions: readonly number[],\n): void {\n const stateElement = handler.stateElement;\n const updater = getUpdater();\n const listAbsAddress = liftAddress(stateElement, parentAddress);\n setListIndexesByList(swapInfo.value, swapInfo.listIndexes);\n markSwapBaselineList(swapInfo.value);\n // この配列を描いた `for` が描いたのは書き込む前の並び。画面から外れていて今回は描かない `for` も、\n // 次に描くときは写しとの差分を取る(#320。下の記録は、今回描く `for` のためのもの)\n rebaseRenderedList(currentParentValue as readonly unknown[], swapInfo.value);\n if (getLastListValueByAbsoluteStateAddress(listAbsAddress) === currentParentValue) {\n setLastListValueByAbsoluteStateAddress(listAbsAddress, swapInfo.value);\n }\n updater.enqueueRenderOnlyAddress(listAbsAddress);\n // この配列を描いている `for` は、書いたリストのアドレスのものだけとは限らない — 同じ内側の配列を別の外側の行も\n // 持つ・同じ行の別のパスも持つ(#379。行の台帳は配列ごとに 1 組なので、同じ行を描いている)。その `for` にも\n // 知らせて描き直させる(描くときにまだこの配列なら、自分が描いた並び — 上で写しへ移した記録 — からの差分を取る)\n for (const absAddress of getAddressesByLastListValue(listAbsAddress, currentParentValue as readonly unknown[])) {\n if (markSwappedList(absAddress, currentParentValue as readonly unknown[])) {\n updater.enqueueRenderOnlyAddress(absAddress);\n }\n }\n\n const positionBefore = new Map<IListIndex, number>();\n swapInfo.listIndexes.forEach((listIndex, position) => positionBefore.set(listIndex, position));\n const elementPathInfo = getPathInfo(parentAddress.pathInfo.path + DELIMITER + WILDCARD);\n for (let position = 0; position < currentListIndexes.length; position++) {\n const listIndex = currentListIndexes[position];\n const before = positionBefore.get(listIndex);\n if (before === position) {\n continue;\n }\n const elementAddress = createStateAddress(elementPathInfo, listIndex);\n const elementAbsAddress = liftAddress(stateElement, elementAddress);\n if (typeof before === \"undefined\") {\n // 台帳は書き込む前の台帳と同じ長さで作る(matchSwappedListIndexes)\n const displacedAbsAddress = absoluteAddressOf(stateElement, elementPathInfo, swapInfo.listIndexes[position]);\n notifySwapped(stateElement, elementAbsAddress, displacedAbsAddress);\n // 置き換えで入った行は中身が丸ごと新しい。差分展開だと入れ子のリストの行(`items.*.tags.*`)が\n // 着地せず `$watch` / `$scan` が取り逃すので、この行の下だけ全行展開で通知する\n notifyWrite(\n elementAddress, elementAbsAddress, receiver, handler, null,\n isCacheable(stateElement, elementAddress), \"full\",\n );\n continue;\n }\n walkDependency(\n stateElement,\n elementAddress,\n stateElement.staticDependency,\n stateElement.dynamicDependency,\n stateElement.listPaths,\n receiver as IStateProxy,\n \"new\",\n (depAddress: IStateAddress) => {\n const depAbsAddress = liftAddress(stateElement, depAddress);\n dirtyCacheEntryByAbsoluteStateAddress(depAbsAddress);\n updater.enqueueRenderOnlyAddress(depAbsAddress);\n },\n { listExpansion: \"diff\" },\n );\n }\n // このバッチで書いた位置にいま居る、まだ着地していない行を着地させる(上の説明 — 新しい行は上で着地済み)。\n // 台帳に行の無い位置(台帳の無い配列への書き込み)には居ない\n for (const position of positions) {\n const listIndex = currentListIndexes[position];\n if (positionBefore.has(listIndex) && swapInfo.written.get(listIndex) !== updateBatch) {\n const elementAddress = createStateAddress(elementPathInfo, listIndex);\n const elementAbsAddress = liftAddress(stateElement, elementAddress);\n notifySwapped(stateElement, elementAbsAddress, absoluteAddressOf(stateElement, elementPathInfo, swapInfo.listIndexes[position]));\n notifyWrite(elementAddress, elementAbsAddress, receiver, handler, null, isCacheable(stateElement, elementAddress));\n }\n }\n}\n\n/**\n * `$listKeys` 宣言済みリストパスへの配列代入を「キー一致行のオブジェクト値展開」に\n * 変換する(docs/state-list-key-design.md §2)。\n *\n * 1. キー突合して、一致行は旧オブジェクトを据え置いたハイブリッド配列を作る\n * 2. ハイブリッド配列を通常の書き込み経路で格納する\n * 3. createListDiff で listIndex を確定し、変化フィールドだけを per-path 書き込みで発行\n *\n * 3 を格納後に行うのが要点。フィールド書き込みは `list.*.field` を親経由で解決する\n * ため、親(ハイブリッド配列)が既に格納されていなければ正しい行に届かない。\n * また per-path 書き込みは再び setByAddress に入るので、ネストしたリストパスが\n * 宣言されていればそのレベルのキー突合が再帰的に走る(§4)。\n *\n * 未宣言時のコストは stateElement.listKeys の null 判定 1 回のみ(§7-1)。\n */\nfunction setKeyedListByAddress(\n target : object,\n address : IStateAddress,\n merge : IKeyedListMerge,\n oldList : readonly unknown[],\n receiver : any,\n handler : IStateHandler\n): any {\n const listPath = address.pathInfo.path;\n // diff の基準は「マージ相手にした配列」= 書き込み直前に格納されていた配列。\n // 読み手(applyChangeToFor / $getAll / resolve)は現在格納されている配列の\n // listIndex 台帳(listIndexesByList)へ収束するため、同じ基準で引くことで\n // 書き込みが dirty 化・キャッシュするアドレスと読み手のアドレスが一致する。\n // lastValue(最後に *適用* された配列)を基準にすると、for が未マウントで\n // lastValue が空のときに別台帳を作ってしまい、値は入っているのにワイルドカード\n // 読みだけ旧値のまま残る(設計書 §8.1)。\n // 格納より前に引くのは、格納時の walkDependency(listExpansion: \"diff\")が\n // 先にハイブリッド配列の台帳を作ってしまうと、後から上書きした台帳との間で\n // 同じ分裂が起きるため。先に確定させておけば以降は全経路がこれに合流する。\n const listParentListIndex = address.listIndex;\n if (getListIndexesByList(oldList) === null) {\n // 一度も描画されていないリストは台帳自体が無い。先に生やしておかないと\n // isSameList 経路が空の oldIndexes をそのまま新台帳にしてしまう。\n createListDiff(listParentListIndex, null, oldList);\n }\n const diff = createListDiff(listParentListIndex, oldList, merge.list);\n const result = setByAddressCore(target, address, merge.list, receiver, handler, listPath);\n const elementPathInfo = getPathInfo(listPath + DELIMITER + WILDCARD);\n for (const match of merge.matched) {\n const fieldWrites = collectFieldWrites(match.oldRow, match.newRow);\n if (fieldWrites.length === 0) {\n continue;\n }\n // createListDiff の契約上 newIndexes の長さはハイブリッド配列と一致するため\n // 通常 undefined にはならない。仮に不変条件が破れても、per-path 書き込みを\n // 諦めるだけで値そのものは行オブジェクトへ反映する(skip すると state だけが\n // 旧値のまま残り、本機能が塞ごうとしている stale を作ってしまう)。\n const listIndex: IListIndex | undefined = diff.newIndexes[match.position];\n for (const write of fieldWrites) {\n if (typeof listIndex === \"undefined\") {\n match.oldRow[write.field] = write.value;\n continue;\n }\n const fieldPathInfo = getPathInfo(elementPathInfo.path + DELIMITER + write.field);\n const fieldAddress = createStateAddress(fieldPathInfo, listIndex);\n setByAddress(target, fieldAddress, write.value, receiver, handler);\n }\n }\n return result;\n}\n\nexport function setByAddress(\n target : object,\n address : IStateAddress,\n value : any,\n receiver : any,\n handler : IStateHandler\n): any {\n const listKeys = handler.stateElement.listKeys;\n if (listKeys != null && Array.isArray(value)) {\n const keySpec = listKeys.get(address.pathInfo.path);\n if (typeof keySpec !== \"undefined\") {\n const oldValue = getByAddress(target, address, receiver, handler);\n const merge = mergeKeyedList(address.pathInfo.path, keySpec, oldValue, value);\n if (merge !== null) {\n // merge が非 null なのは oldValue が非空配列のときだけ(mergeKeyedList 参照)\n return setKeyedListByAddress(target, address, merge, oldValue as readonly unknown[], receiver, handler);\n }\n }\n }\n return setByAddressCore(target, address, value, receiver, handler, null);\n}\n\nfunction setByAddressCore(\n target : object,\n address : IStateAddress,\n value : any,\n receiver : any,\n handler : IStateHandler,\n keyedMergePath: string | null\n): any {\n const stateElement = handler.stateElement;\n const path = address.pathInfo.path;\n // 読み書き境界の hook(設計案 H1、書き側)。無ければ判定 1 回\n const hooks = stateElement.addressHooks;\n if (hooks) {\n const writeHooks = hooks.write;\n for (let i = 0; i < writeHooks.length; i++) {\n const handled = writeHooks[i](stateElement, address, value, receiver, handler);\n if (handled !== NOT_HANDLED) return handled;\n }\n }\n // D22 後段(接ぎ木済みボリュームの親の丸ごと書き禁止)は webComponent/addressHooks.ts の write hook が担う\n // 再帰 getter への書き込み禁止([wcs/recursion-readonly])は recursion/addressHooks.ts の write hook が担う\n // occurrence(wc-bindable の `semantics: \"event\"`)由来の書き込みは、同値でも\n // 「もう一度起きた」ことを落としてはならないため same-value guard を 1 回だけ飛ばす。\n // トークンはここで消費されるので、この write の内側で走る他の書き込みには波及しない。\n // 要素から来た書き込み(proxy/occurrenceWrite.ts): 2 = occurrence。要素パスへ書いても入れ替えにしない\n const elementWrite = consumeElementWrite();\n const skipSameValueGuard = elementWrite > 1;\n\n // --- fast path: 宣言済み getter/setter でも swap 対象でもない、親を持つ葉パス ---\n // 従来は same-value guard の値読み・hasByAddress・実書き込みがそれぞれ親チェーンを\n // 解決していた(キャッシュヒットでも getByAddress 呼び出しの固定費 ×3)。\n // 親を 1 回だけ解決し、同じ親オブジェクトに対して guard 判定と Reflect.set を行う。\n // 非オブジェクト親などの例外形は従来経路へ倒し、挙動差を作らない。\n if (!(path in target) && address.parentAddress !== null && !stateElement.elementPaths.has(path)) {\n const parentValue = getByAddress(target, address.parentAddress, receiver, handler);\n if (typeof parentValue === \"object\" && parentValue !== null) {\n // ワイルドカード末尾で listIndex が無い不正アドレスは、従来どおり\n // 書き込み時(enqueue 済みの try 内)に raiseError する → key は undefined のまま持ち回す\n const lastSegment = address.pathInfo.lastSegment;\n const key: PropertyKey | undefined = lastSegment === WILDCARD\n ? address.listIndex?.index\n : lastSegment;\n let devOldValue: unknown;\n let devHasOldValue = false;\n if (!skipSameValueGuard && config.sameValueGuard && (value === null || typeof value !== \"object\")) {\n // hasByAddress と同じ「初期化済みスロットか」判定(undefined 格納と未初期化を区別)\n const has = key !== undefined && key in parentValue;\n const oldValue = key !== undefined ? (parentValue as Record<PropertyKey, unknown>)[key] : undefined;\n if (has && Object.is(oldValue, value)) {\n return true;\n }\n devOldValue = oldValue;\n devHasOldValue = true;\n }\n if (lastSegment === WILDCARD) {\n // 以降の通知・キャッシュ・prev の記録は、差し替えた後の行のアドレスで行う(#333)\n address = renewReplacedRow(stateElement, address, parentValue, key, value);\n }\n // key が undefined(listIndex の無い不正アドレス)なら読みは undefined — 書き込みが下で投げる\n // 購読者の収集は書き込みの**前**(旧値の鍵が要る)。そこからの依存ウォークは\n // 書き込みの**後**(下の finally の walkKeyedDependents)\n const keyedSubscribers = notifyKeyed(stateElement, path, devHasOldValue, devOldValue, value,\n () => (parentValue as Record<PropertyKey, unknown>)[key as PropertyKey]);\n const cacheable = isCacheable(stateElement, address);\n const absAddress = liftAddress(stateElement, address);\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"state:write\",\n absoluteAddress: absAddress,\n value,\n oldValue: devOldValue,\n hasOldValue: devHasOldValue,\n });\n }\n recordDeclaredPrevValue(stateElement, path, absAddress, devOldValue, devHasOldValue);\n let dispatchedExport = false;\n try {\n if (key === undefined) {\n // fast path 版の同じ取り違え(末尾ワイルドカードに listIndex が無い)。\n // 通常経路と同じ語彙で「何段必要か」を言う(pathDiagnostics.ts)。\n raiseError(wildcardScopeMessage(\n `path \"${path}\"`,\n address.pathInfo.wildcardCount,\n address.listIndex?.length ?? 0,\n ));\n }\n // 「親にそのキーが無い」書き込みは writeMissing hook(公開 getter への書き込み — X9)に先に聞く。\n // hook の無い state は判定 1 個で抜ける。hook が throw しても(setter の無い公開 getter)\n // 代入値をキャッシュに固定しないよう、呼ぶ前に印を立て、素通しなら戻す\n if (hooks && hooks.writeMissing.length !== 0 && lastSegment !== WILDCARD && !(key in parentValue)) {\n const missing = hooks.writeMissing;\n for (let i = 0; i < missing.length; i++) {\n dispatchedExport = true;\n const handled = missing[i](stateElement, address, parentValue, key, value, receiver, handler);\n if (handled !== NOT_HANDLED) {\n return handled;\n }\n dispatchedExport = false;\n }\n }\n if (lastSegment !== WILDCARD && address.listIndex !== null) {\n // 行の下のパス(外側の行の内側のリスト)が別の値に替わる。前の配列の行がこの行を親に持っていても、この行は\n // もうその配列を持たない — 台帳の付け替えの元にする(list/listIndexesByList.ts・#394)\n const previous = (parentValue as Record<PropertyKey, unknown>)[key];\n if (previous !== value) {\n if (releaseListAtParent(previous, address.listIndex, parentValue as Record<string, unknown>, lastSegment) && Array.isArray(value)) {\n keepPreviousList(value, previous);\n }\n holdListAtParent(value, address.listIndex);\n }\n }\n return Reflect.set(parentValue, key, value);\n } finally {\n notifyWrite(address, absAddress, receiver, handler, keyedMergePath, cacheable);\n walkKeyedDependents(keyedSubscribers, receiver, handler);\n if (dispatchedExport) {\n // Exported row paths are cacheable but absent from getterPaths. The\n // accessor may normalize or reject the input; never pin that input.\n dirtyCacheEntryByAbsoluteStateAddress(absAddress);\n } else {\n commitWriteCache(stateElement, path, absAddress, value, cacheable);\n }\n notifyWritten(stateElement, address.pathInfo, { value });\n }\n }\n }\n // --- end fast path ---\n\n // --- same-value guard (config.sameValueGuard・既定 ON) ---\n // primitive 値かつ Object.is 同値なら、set / enqueue / walkDependency / DOM 適用 /\n // $updatedCallback / DCC イベントを丸ごとスキップ(標準的なリアクティブ no-op)。\n // 参照型(object/array)は in-place mutation 取りこぼし防止のため素通し(ガードしない)。\n // devtools write イベント用: guard が既に取得した旧値のみ流用する\n // (参照型のために追加の get はしない — protocol §4.2)\n let devOldValue: unknown;\n let devHasOldValue = false;\n if (!skipSameValueGuard && config.sameValueGuard && (value === null || typeof value !== \"object\")) {\n const oldValue = getByAddress(target, address, receiver, handler);\n if (hasByAddress(target, address, receiver, handler) && Object.is(oldValue, value)) {\n return true;\n }\n devOldValue = oldValue;\n devHasOldValue = true;\n }\n // 購読者の収集は書き込みの**前**(旧値の鍵が要る)。ウォークは下の finally\n const keyedSubscribers = notifyKeyed(stateElement, path, devHasOldValue, devOldValue, value, () => getByAddress(target, address, receiver, handler));\n // --- end same-value guard ---\n const isSwappable = stateElement.elementPaths.has(address.pathInfo.path);\n const cacheable = isCacheable(stateElement, address);\n const absAddress = liftAddress(stateElement, address);\n if (devtoolsSink !== null) {\n devtoolsSink({\n type: \"state:write\",\n absoluteAddress: absAddress,\n value,\n oldValue: devOldValue,\n hasOldValue: devHasOldValue,\n });\n }\n recordDeclaredPrevValue(stateElement, path, absAddress, devOldValue, devHasOldValue);\n try {\n if (isSwappable) {\n return _setByAddressWithSwap(target, address, absAddress, value, receiver, handler, keyedMergePath, cacheable, elementWrite);\n } else {\n return _setByAddress(target, address, absAddress, value, receiver, handler, keyedMergePath, cacheable);\n }\n } finally {\n // 鍵付き購読の派生先(`notifyWrite` は `_setByAddress` の中で済んでいる)。書き込み後なので\n // リスト展開が新しい値を読む\n walkKeyedDependents(keyedSubscribers, receiver, handler);\n // 要素書き込み(#4)の代入値は、書き込んだアドレスのキャッシュに固定しない。入れ替えでは listIndex が\n // 値に付いて動くので、書き込んだ時点の listIndex がこの位置に残るとは限らない — 固定すると、台帳は\n // 入れ替わったのにキャッシュだけが位置のまま交差する。notifyWrite が無効化した項目を、次の読みが\n // 台帳に沿って読み直す\n if (!isSwappable) {\n commitWriteCache(stateElement, path, absAddress, value, cacheable);\n }\n notifyWritten(stateElement, address.pathInfo, { value });\n }\n}\n\n","/**\n * resolve.ts\n *\n * StateClassのAPIとして、パス(path)とインデックス(indexes)を指定して\n * Stateの値を取得・設定するための関数(resolve)の実装です。\n *\n * 主な役割:\n * - 文字列パス(path)とインデックス配列(indexes)から、該当するState値の取得・設定を行う\n * - ワイルドカードや多重ループを含むパスにも対応\n * - value未指定時は取得(getByRef)、指定時は設定(setByRef)を実行\n *\n * 設計ポイント:\n * - getStructuredPathInfoでパスを解析し、ワイルドカード階層ごとにリストインデックスを解決\n * - handler.engine.getListIndexesSetで各階層のリストインデックス集合を取得\n * - getByRef/setByRefで値の取得・設定を一元的に処理\n * - 柔軟なバインディングやAPI経由での利用が可能\n */\n\nimport { getPathInfo } from \"../../address/PathInfo\";\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { indexArityMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { assertWritable } from \"../assertWritable\";\nimport { getByAddress } from \"../methods/getByAddress\";\nimport { getListIndexByIndexes } from \"../methods/getListIndexByIndexes\";\nimport { setByAddress } from \"../methods/setByAddress\";\nimport { IStateHandler } from \"../types\";\n\ntype ResolveFunction = (path: string, indexes: number[], ...value: [value?: any]) => any;\n\nexport function resolve(\n target: object, \n _prop: PropertyKey, \n receiver: any,\n handler: IStateHandler\n): ResolveFunction {\n return (path: string, indexes: number[], ...value: [value?: any]): any => {\n // 添字が配列でない(省略・`null` 等)のは素の TypeError にせず、形の診断にする\n // (`$getAll` / `$setAll` と同じ語彙)。`$resolve` は添字を省略できない — 省略形は `$getAll`\n if (!Array.isArray(indexes)) {\n raiseError(\n `$resolve(\"${path}\") requires an explicit indexes array (pass [] when the path has no wildcards) — got ` +\n `${indexes === null ? \"null\" : typeof indexes}.`\n );\n }\n // 読み(2 引数)か書き(3 引数)だけ。4 つ目以降は黙って捨てられていた(要件 B7 の「範囲外の\n // 引数個数は throw」と不一致 — 書きのつもりの取り違えが readonly エラーでしか現れなかった)\n if (value.length > 1) {\n raiseError(\n `$resolve(\"${path}\") takes 2 arguments to read and 3 to write (path, indexes, value) — got ` +\n `${2 + value.length}.`\n );\n }\n const pathInfo = getPathInfo(path);\n if (handler.addressStackLength > 0) {\n const lastInfo = handler.lastAddressStack?.pathInfo ?? null;\n const stateElement = handler.stateElement;\n if (lastInfo !== null && lastInfo.path !== pathInfo.path) {\n // gettersに含まれる場合は依存関係を登録\n if (stateElement.getterPaths.has(lastInfo.path)) {\n stateElement.addDynamicDependency(pathInfo.path, lastInfo.path);\n }\n }\n }\n\n // 添字の本数はワイルドカードの本数と**厳密に一致**する必要がある。\n // 不足は元から throw していたが、超過は黙って無視されていた(余分な要素を\n // 誰も読まないため)= `$resolve(\"items.*.price\", [row, col])` のような\n // 「1 本しか無いのに 2 本渡す」取り違えが、間違った値を返したまま通っていた。\n if (indexes.length !== pathInfo.wildcardParentPathInfos.length) {\n raiseError(indexArityMessage(\"$resolve\", path, pathInfo.wildcardParentPathInfos.length, indexes.length));\n }\n // ワイルドカード階層ごとにListIndexを解決していく(`$setAll` と共有)\n const listIndex = getListIndexByIndexes(target, receiver, handler, pathInfo, indexes);\n\n // ToDo:WritableかReadonlyかを判定して適切なメソッドを呼び出す\n const address = createStateAddress(pathInfo, listIndex);\n // 読みか書きかは引数の**個数**で決める(要件 B7)。値で決めると undefined を書けない\n if (value.length === 0) {\n return getByAddress(target, address, receiver, handler);\n } else {\n assertWritable(handler);\n setByAddress(target, address, value[0], receiver, handler);\n }\n };\n} ","/**\n * getAllReadonly\n *\n * ワイルドカードを含む State パスから、対象となる全要素を配列で取得する。\n * 走査そのものは `$setAll` と共有する(wildcardIndexes.ts)。\n *\n * `indexes` 省略時の既定はループ文脈の添字 `[$1..$n]`。正確には「path と文脈が\n * 共有するワイルドカード連鎖の分だけ文脈の添字を接頭辞として敷く」(整合最長接頭辞)。\n * 共有が無いのに文脈が添字を持つ場合は throw する — 異なる文脈の添字は流用しない。\n *\n * Throws: LIST-201(インデックス未解決)、BIND-201(ワイルドカード情報不整合)、\n * 添字本数超過(wcs/index-arity)、省略時の文脈不整合(getAllContextMismatchMessage)\n */\n\nimport { getPathInfo } from \"../../address/PathInfo\";\nimport { getAllContextMismatchMessage, indexArityMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { getScopedIndexes } from \"../../list/wildcardLevel\";\nimport { getContextListIndex } from \"../methods/getContextListIndex\";\nimport { IStateHandler } from \"../types\";\nimport { collectWildcardIndexes } from \"./wildcardIndexes\";\nimport { resolve } from \"./resolve\";\n\ntype GetAllFunction = (path: string, indexes?: number[]) => any[];\n\nexport function getAll(\n target: object,\n prop: PropertyKey,\n receiver: any,\n handler: IStateHandler\n): GetAllFunction {\n const resolveFn = resolve(target, prop, receiver, handler);\n return (path: string, indexes?: number[]): any[] => {\n // オーサリング層の `**`(束縛・合併形)は recursion/addressHooks.ts の get hook が先に受ける\n const pathInfo = getPathInfo(path);\n // 渡された添字が配列でない(`null` 等)のは素の TypeError にせず、形の診断にする。\n // 省略(undefined)だけが「文脈の添字」を意味する。\n if (typeof indexes !== \"undefined\" && !Array.isArray(indexes)) {\n raiseError(\n `$getAll(\"${path}\") requires the indexes to be an array when given ` +\n `(omit them for the loop context, or pass [] to expand every level) — got ` +\n `${indexes === null ? \"null\" : typeof indexes}.`\n );\n }\n if (handler.addressStackLength > 0) {\n const lastInfo = handler.lastAddressStack?.pathInfo ?? null;\n const stateElement = handler.stateElement;\n if (lastInfo !== null && lastInfo.path !== pathInfo.path) {\n // gettersに含まれる場合は依存関係を登録\n if (stateElement.getterPaths.has(lastInfo.path)) {\n stateElement.addDynamicDependency(pathInfo.path, lastInfo.path);\n }\n }\n }\n\n // 明示的に渡された添字だけを検査する。`$getAll` の添字は**前方一致の接頭辞**で、\n // 足りない分は「その階層を全部展開する」という正しい意味を持つ(README の\n // `$getAll(\"scores.*\", [])` がこれ)。一方**超過は意味を持たず黙って捨てられ**、\n // ワイルドカードの本数を取り違えたまま部分集合が返っていた。\n // 省略時に下で導出する添字は文脈由来なので、この検査には掛けない。\n if (typeof indexes !== \"undefined\" && indexes.length > pathInfo.wildcardParentPathInfos.length) {\n raiseError(indexArityMessage(\"$getAll\", path, pathInfo.wildcardParentPathInfos.length, indexes.length));\n }\n if (typeof indexes === \"undefined\") {\n // 省略時の既定はループ文脈の添字 `[$1..$n]`。ただし敷けるのは path と文脈が\n // **共有するワイルドカード連鎖**の分だけなので、path のワイルドカードを\n // 内側(最深)から探し、最初に文脈にヒットした階層の scoped indexes を接頭辞にする。\n // ワイルドカードパスの序数はパス文字列自身の `*` の本数で決まるため、深い側が\n // ヒットすれば浅い側は必ず含まれ、これが整合する最長の接頭辞になる。文脈が\n // path より深い分は自然に切り詰められ、導出した接頭辞は path のワイルドカード\n // 本数を超えないので、上の本数検査には掛けない。\n for (let i = pathInfo.wildcardPaths.length - 1; i >= 0; i--) {\n const listIndex = getContextListIndex(handler, pathInfo.wildcardPaths[i]);\n if (listIndex) {\n indexes = getScopedIndexes(listIndex, listIndex.length);\n break;\n }\n }\n if (typeof indexes === \"undefined\") {\n // 共有ゼロ。文脈が自スコープの添字を実際に持っているなら、既定の `[...$n]` は\n // **異なる文脈の添字の流用(混入)**になるため、黙って全展開へ倒さず throw する。\n // 文脈そのものが無い(トップレベル getter / メソッド直下)なら全展開が既定。\n const lastAddress = handler.addressStackLength > 0 ? handler.lastAddressStack : null;\n const contextListIndex = lastAddress?.listIndex ?? null;\n if (pathInfo.wildcardCount > 0 && lastAddress !== null && contextListIndex !== null &&\n contextListIndex.length > 0) {\n raiseError(getAllContextMismatchMessage(path, lastAddress.pathInfo.path));\n }\n indexes = [];\n }\n }\n // 読みなので差分基準を更新する(固定 arity の `$setAll` は更新しない。設計 §6-2)\n const resultIndexes = collectWildcardIndexes(\n target, receiver, handler, pathInfo, indexes, { commitDiffBaseline: true });\n const resultValues: any[] = [];\n for(let i = 0; i < resultIndexes.length; i++) {\n resultValues.push(resolveFn(\n pathInfo.path,\n resultIndexes[i]\n ));\n }\n return resultValues;\n }\n }\n","/**\n * getListIndex.ts\n *\n * StateClassの内部APIとして、パス情報(IResolvedAddress)から\n * 対応するリストインデックス(IListIndex)を取得する関数です。\n *\n * 主な役割:\n * - パスのワイルドカード種別(context/all/partial/none)に応じてリストインデックスを解決\n * - context型は現在のループコンテキストからリストインデックスを取得\n * - all型は各階層のリストインデックス集合からインデックスを辿って取得\n * - partial型やnone型は未実装またはnullを返す\n *\n * 設計ポイント:\n * - ワイルドカードや多重ループ、ネストした配列バインディングに柔軟に対応\n * - getListIndexesByAddressで各階層のリストインデックス集合を取得(台帳が無いリストは\n * その場で台帳を生やす — for で描いていないリストの直接添字、#324)\n * - エラー時はraiseErrorで例外を投げる\n */\n\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { IResolvedAddress } from \"../../address/types\";\nimport { IListIndex } from \"../../list/types\";\nimport { raiseError } from \"../../raiseError\";\nimport { IStateHandler } from \"../types\";\nimport { getByAddress } from \"./getByAddress\";\nimport { getContextListIndex } from \"./getContextListIndex\";\nimport { getListIndexesByAddress } from \"./getListIndexesByAddress\";\n\nexport function getListIndex(\n target : object, \n resolvedAddress: IResolvedAddress, \n receiver: any,\n handler: IStateHandler\n): IListIndex | null {\n const pathInfo = resolvedAddress.pathInfo;\n switch (resolvedAddress.wildcardType) {\n case \"none\":\n return null;\n case \"context\": {\n const lastWildcardPath = pathInfo.wildcardPaths.at(-1) ?? \n raiseError(`lastWildcardPath is null: ${resolvedAddress.pathInfo.path}`);\n return getContextListIndex(handler, lastWildcardPath) ?? \n raiseError(`ListIndex not found: ${resolvedAddress.pathInfo.path}`);\n }\n case \"all\": {\n let parentListIndex: IListIndex | null = null;\n for(let i = 0; i < resolvedAddress.pathInfo.wildcardCount; i++) {\n const wildcardParentPathInfo = resolvedAddress.pathInfo.wildcardParentPathInfos[i] ?? \n raiseError(`wildcardParentPathInfo is null: ${resolvedAddress.pathInfo.path}`);\n const wildcardParentAddress = createStateAddress(wildcardParentPathInfo, parentListIndex);\n const wildcardParentValue = getByAddress(target, wildcardParentAddress, receiver, handler);\n const wildcardParentListIndexes = getListIndexesByAddress(handler, wildcardParentAddress, wildcardParentValue);\n const wildcardIndex = resolvedAddress.wildcardIndexes[i] ?? \n raiseError(`wildcardIndex is null: ${resolvedAddress.pathInfo.path}`);\n // 範囲外 index は、メッセージに index を含める。親パスだけを名指しすると\n // 「リスト自体が見つからない」と誤読させる(docs/state-bind-component-nested-for-design.md §8.4)。\n // 値が配列でないリストも、行 0 件としてここで投げる。\n parentListIndex = wildcardParentListIndexes[wildcardIndex] ??\n raiseError(`ListIndex not found at index ${wildcardIndex} of ${wildcardParentPathInfo.path}`);\n }\n return parentListIndex;\n }\n case \"partial\": {\n raiseError(`Partial wildcard type is not supported yet: ${resolvedAddress.pathInfo.path}`);\n }\n }\n}\n","/**\n * setAll.ts\n *\n * ワイルドカードを含む State パスにマッチする**全アドレスへ一括で書き込む**。\n * `$getAll`(読み)の対称形(docs/state-set-all-design.md)。\n *\n * 存在理由は糖衣ではなく「**リスト全置換の回避**」(設計 §1-1)。\n * `this.users = this.users.map(...)` は配列を作り直すので ListIndex・行 getter\n * キャッシュ・差分描画がまとめて作り直しになる。`$setAll` は意味としては一括更新、\n * 実体は in-place な個別書き込みで、同じことを差分に載せたまま行う。\n *\n * 3 つの形(設計 §2):\n * - ブロードキャスト `$setAll(path, indexes, value)`\n * - mapper(第一級) `$setAll(path, indexes, (current, ...indexes) => next)`\n * - spread `$setAll(path, indexes, values, { spread: true })`\n */\n\nimport { getPathInfo } from \"../../address/PathInfo\";\nimport { createStateAddress } from \"../../address/StateAddress\";\nimport { IStateAddress } from \"../../address/types\";\nimport { WILDCARD } from \"../../define\";\nimport { indexArityMessage, setAllSpreadArityMessage, setAllValueKindMessage } from \"../../pathDiagnostics\";\nimport { raiseError } from \"../../raiseError\";\nimport { assertWritable } from \"../assertWritable\";\nimport { getByAddress } from \"../methods/getByAddress\";\nimport { getListIndexByIndexes } from \"../methods/getListIndexByIndexes\";\nimport { setByAddress } from \"../methods/setByAddress\";\nimport { IStateHandler } from \"../types\";\nimport { collectWildcardIndexes } from \"./wildcardIndexes\";\n\nexport interface ISetAllOptions {\n /**\n * `values` を**マッチ順に 1 件ずつ配る**。既定(省略/false)では配列もそのまま\n * ブロードキャストされる — 対象プロパティ自体が配列型のとき区別がつかないため、\n * 配分は明示的にオプトインさせる(設計 §3)。\n */\n readonly spread?: boolean;\n}\n\ntype SetAllFunction = (\n path: string,\n indexes: number[],\n value: any,\n options?: ISetAllOptions,\n) => number;\n\nexport function setAll(\n target : object,\n _prop : PropertyKey,\n receiver: any,\n handler : IStateHandler\n): SetAllFunction {\n return (path: string, indexes: number[], value: any, options?: ISetAllOptions): number => {\n assertWritable(handler);\n // オーサリング層の `**`(ブロードキャスト形)は recursion/addressHooks.ts の get hook が先に受ける\n const pathInfo = getPathInfo(path);\n\n // 書き込み API に暗黙の文脈依存は持たせない。`for` の中で `[]` と書けば\n // 「現在行」ではなく「全行」を意味する(設計 §4-1)。\n if (!Array.isArray(indexes)) {\n raiseError(setAllValueKindMessage(path, \"requires an explicit indexes array (pass [] to expand every level).\"));\n }\n // 添字は前方一致の接頭辞なので不足は正当。超過だけを弾く(`$getAll` と同じ規則)。\n if (indexes.length > pathInfo.wildcardParentPathInfos.length) {\n raiseError(indexArityMessage(\"$setAll\", path, pathInfo.wildcardParentPathInfos.length, indexes.length));\n }\n\n const spread = options?.spread === true;\n const isMapper = typeof value === \"function\";\n if (spread && isMapper) {\n raiseError(setAllValueKindMessage(path, \"cannot combine { spread: true } with a mapper function.\"));\n }\n if (spread && !Array.isArray(value)) {\n raiseError(setAllValueKindMessage(path, \"requires an array as the value when { spread: true } is set.\"));\n }\n\n // --- 第 1 相: 書き込み先を全部確定する(設計 §6) ---\n // 走査しながら書くと書き込みが ListIndex 集合を動かしうる。\n // 差分基準(state 側の共有正本 stateListBaseline)は、固定 arity の `$setAll` は走査を\n // 借りるだけで確定しない(§6-2。再帰の `$setAll` は確定する — recursion/walk.ts)。\n const resultIndexes = collectWildcardIndexes(\n target, receiver, handler, pathInfo, indexes, { commitDiffBaseline: false });\n\n if (spread && (value as unknown[]).length !== resultIndexes.length) {\n raiseError(setAllSpreadArityMessage(path, resultIndexes.length, (value as unknown[]).length));\n }\n\n const addresses: IStateAddress[] = [];\n for(let i = 0; i < resultIndexes.length; i++) {\n const listIndex = getListIndexByIndexes(target, receiver, handler, pathInfo, resultIndexes[i]);\n addresses.push(createStateAddress(pathInfo, listIndex));\n }\n\n // --- 第 2 相: 確定したアドレスにだけ書く ---\n // 要素そのもの(`items.*`)へ書くときは、行を添字タプルから書く直前に引き直す。`for` が描くリストでは、\n // 先の書き込みが入れ替えを揃えると行が値に付いて動く(setByAddress の _setByAddressWithSwap)ので、第 1 相で\n // 確定した行は別の位置に居て、同じ位置に 2 回書き、書かない位置が残った\n const isElementPath = pathInfo.lastSegment === WILDCARD;\n let written = 0;\n for(let i = 0; i < addresses.length; i++) {\n const address = isElementPath\n ? createStateAddress(pathInfo, getListIndexByIndexes(target, receiver, handler, pathInfo, resultIndexes[i]))\n : addresses[i];\n let nextValue: any;\n if (isMapper) {\n // 現在値は書く直前に読む。先行する書き込みが getter 経由で他行に及ぶ場合、\n // mapper が見るべきなのは最新値。\n const currentValue = getByAddress(target, address, receiver, handler);\n nextValue = value(currentValue, ...resultIndexes[i]);\n } else if (spread) {\n nextValue = (value as unknown[])[i];\n } else {\n nextValue = value;\n }\n // undefined は常にスキップ(設計 §5)。mapper の return 忘れで全行を潰さないため、\n // かつ「この行は変えない」を表現できるようにするため。クリアは null。\n if (typeof nextValue === \"undefined\") {\n continue;\n }\n setByAddress(target, address, nextValue, receiver, handler);\n written++;\n }\n return written;\n };\n}\n"],"names":["registryByStateElement","WeakMap","getOrCreateCommandToken","stateElement","name","registry","get","Map","set","token","CommandToken","namespaceProxyByStateElement","getCommandNamespace","cached","proxy","Proxy","Object","create","_target","prop","commandTokenNames","has","ownKeys","Array","from","getOwnPropertyDescriptor","configurable","enumerable","value","raiseError","deleteProperty","clearCommandNamespace","delete","assertWritable","handler","mutability","isCacheable","address","hasMounts","pathInfo","lastSegment","charCodeAt","wildcardCount","getterPaths","path","readMissing","parentValue","receiver","hooks","addressHooks","missing","i","length","handled","NOT_HANDLED","_getByAddress","target","segments","STATE_COMMAND_NAMESPACE_NAME","namespace","Reflect","walkNamespace","parentAddress","missingRootPathMessage","getByAddress","WILDCARD","index","listIndex","wildcardScopeMessage","pushAddress","popAddress","_getByAddressWithCache","absAddress","liftAddress","cacheEntry","getCacheEntryByAbsoluteStateAddress","generation","stateGeneration","rowStamp","undefined","getRowCacheStamp","dirty","setCacheEntryByAbsoluteStateAddress","previous","isArray","beginUntrack","source","targets","dynamicDependency","sourcePathInfo","getPathInfo","includes","sourceValue","createStateAddress","listIndexAtWildcard","aliasGetterPathInfos","add","keepPreviousList","endUntrack","inspectGetterList","WeakSet","isAliasGetter","checkDependency","hasRecursion","recursionRegistry","materializeForPathInfo","readHooks","read","collectWildcardIndexes","indexes","options","newValueByAddress","walkWildcardPattern","wildcardParentPathInfos","wildcardIndexPos","indexPos","parentIndexes","results","wildcardParentPathInfo","push","wildcardAddress","wildcardAbsAddress","oldValue","getStateListBaseline","newValue","listIndexes","createListDiff","newIndexes","concat","resultIndexes","commitDiffBaseline","entries","setStateListBaseline","getListIndexesByAddress","resolveListIndexesByList","diff","getListIndexByIndexes","assertPlainRow","row","side","position","STATE_LIST_KEYS_NAME","proto","getPrototypeOf","prototype","keyOf","spec","key","String","extractKeys","list","keys","seen","Set","JSON","stringify","collectFieldWrites","oldRow","newRow","writes","field","is","hasOwn","hasByAddress","swapInfoByList","getSwapInfoByList","setSwapInfoByList","swapInfo","disownListIndexes","_walkExpandWildcard","context","currentWildcardIndex","parentListIndex","parentPath","wildcardParentPaths","parentPathInfo","parentAbsAddress","lastValue","stateProxy","getByAddressSymbol","listDiff","observedListValueByAbsAddress","loopIndexes","searchType","oldIndexes","addIndexSet","changeIndexSet","deleteIndexSet","config","debug","console","log","getIndexes","wildcardPaths","targetListIndexes","pushDependency","depAddress","quiet","nextEntries","result","EMPTY_INDEXES","selectExpansionIndexes","sourcePath","listExpansion","listPathSet","crossRowListPaths","fullRows","movedRows","size","keyedMergePath","EMPTY_PATH_INFOS","getMovedRowExpansionPaths","wildcardPath","depPathInfo","indexGetters","indexDependentGetterPaths","prefix","DELIMITER","startsWith","_walkDependency","startAddress","callback","buckets","ranks","enqueue","minRank","rank","bucket","cursor","visited","dirtyCacheEntryByAbsoluteStateAddress","_collectDependencies","staticDeps","staticMap","dep","newList","listed","getListIndexesByList","isSameList","selection","valueChangeIndexes","movedPathInfos","dynamicDeps","dynamicMap","wildcardLen","calcWildcardLen","expandContext","walkDependency","staticDependency","startPath","maxDepth","adjacency","inDegree","pending","pop","deps","settled","queue","degree","nextRank","j","remaining","maxRank","cycleRank","getTopologicalRanks","guard","takePendingKeyedWalk","forEach","absolutePathInfo","drainKeyedWalk","recordDeclaredPrevValue","hasOldValue","observers","writeObserve","notifyWritten","detail","written","notifySwapped","elementAbsAddress","displacedAbsAddress","swapped","notifyKeyed","readOld","direct","hasKeyedDependents","descendants","hasKeyedDescendants","subscribers","createKeyedEnqueue","keyedDependents","keyedDescendantDependents","keyedPropagationContext","enablePropagationContext","getCurrentPropagationContext","collected","updater","getUpdater","enqueueAbsoluteAddress","walkKeyedDependents","treePath","listPaths","absDepAddress","notifyKeyedPostUpdate","readCurrent","current","notifyWrite","cacheable","propagationContext","beginPropagationTransaction","walk","start","listPathInfo","listAddress","readList","notify","aliasAbsAddress","enqueueRenderOnlyAddress","alias","getElementAliases","leaf","slice","drawn","getAddressesByLastListValue","drawnPathInfo","absoluteAddressOf","level","aliasPath","aliasPathInfo","aliasAddress","commitWriteCache","_setByAddress","setterPaths","_setByAddressWithSwap","elementWrite","setListIndexValue","info","currentListIndexes","before","rows","movedByValue","moved","beforeValues","lookups","shift","map","createListIndex","matchSwappedListIndexes","updateBatch","markRowSwapPending","positions","clearRowSwapPending","batch","setListIndexesByList","moveIndexWatchers","currentParentValue","listAbsAddress","markSwapBaselineList","rebaseRenderedList","getLastListValueByAbsoluteStateAddress","setLastListValueByAbsoluteStateAddress","markSwappedList","positionBefore","elementPathInfo","elementAddress","depAbsAddress","notifySwappedList","setByAddress","listKeys","keySpec","merge","newKeys","oldList","oldKeys","oldRowByKey","matched","mergeKeyedList","listPath","listParentListIndex","setByAddressCore","match","fieldWrites","write","fieldPathInfo","setKeyedListByAddress","writeHooks","consumeElementWrite","skipSameValueGuard","elementPaths","devOldValue","devHasOldValue","sameValueGuard","renewed","getHomeParentListIndex","hasRenderedList","image","next","isOwnedListIndexes","retireRows","renewedAddress","renewReplacedRow","keyedSubscribers","devtoolsSink","type","absoluteAddress","dispatchedExport","writeMissing","releaseListAtParent","holdListAtParent","isSwappable","resolve","_prop","addressStackLength","lastInfo","lastAddressStack","addDynamicDependency","indexArityMessage","getAll","resolveFn","getContextListIndex","getScopedIndexes","lastAddress","contextListIndex","getAllContextMismatchMessage","resultValues","getListIndex","resolvedAddress","wildcardType","lastWildcardPath","at","wildcardParentAddress","wildcardParentListIndexes","wildcardIndex","wildcardIndexes","setAll","setAllValueKindMessage","spread","isMapper","setAllSpreadArityMessage","addresses","isElementPath","nextValue"],"mappings":"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"}
|