@wcstack/state 4.10.0 → 4.11.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 +27 -7
- package/README.md +28 -7
- package/dist/auto.min.js +1 -1
- package/dist/auto.min.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/split/auto.js +1 -1
- package/dist/split/chunks/{chunk-JCQTA35B.js → chunk-AKTGQ6TC.js} +2 -2
- package/dist/split/chunks/chunk-CYMUD7KV.js +2 -0
- package/dist/split/chunks/chunk-CYMUD7KV.js.map +1 -0
- package/dist/split/chunks/chunk-E3XSBW55.js +2 -0
- package/dist/split/chunks/chunk-IYPAK7PO.js +2 -0
- package/dist/split/chunks/chunk-IYPAK7PO.js.map +1 -0
- package/dist/split/chunks/{chunk-FFXJVUTT.js → chunk-JJYM4JVZ.js} +2 -2
- package/dist/split/chunks/chunk-KBQKAD3I.js +2 -0
- package/dist/split/chunks/{chunk-PTFWXISY.js.map → chunk-KBQKAD3I.js.map} +1 -1
- package/dist/split/chunks/{chunk-SJRJALR4.js → chunk-LPJFTEVT.js} +2 -2
- package/dist/split/chunks/chunk-NAV7FBTI.js +2 -0
- package/dist/split/chunks/{chunk-MZVF2WEY.js.map → chunk-NAV7FBTI.js.map} +1 -1
- package/dist/split/chunks/{chunk-FT7OW7CG.js → chunk-R6RHIIR4.js} +2 -2
- package/dist/split/chunks/chunk-REB4RMZ3.js +2 -0
- package/dist/split/chunks/{chunk-65B2K2XD.js.map → chunk-REB4RMZ3.js.map} +1 -1
- package/dist/split/chunks/chunk-SJ552B3B.js +2 -0
- package/dist/split/chunks/{chunk-TB52U4QV.js.map → chunk-SJ552B3B.js.map} +1 -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/list-keys.js +1 -1
- package/dist/split/features/native-commands.js +1 -1
- package/dist/split/features/recursion.js +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/package.json +1 -1
- package/dist/split/chunks/chunk-65B2K2XD.js +0 -2
- package/dist/split/chunks/chunk-GU7IAIWW.js +0 -2
- package/dist/split/chunks/chunk-GU7IAIWW.js.map +0 -1
- package/dist/split/chunks/chunk-IWY3I2DG.js +0 -2
- package/dist/split/chunks/chunk-IWY3I2DG.js.map +0 -1
- package/dist/split/chunks/chunk-MZVF2WEY.js +0 -2
- package/dist/split/chunks/chunk-PTFWXISY.js +0 -2
- package/dist/split/chunks/chunk-TB52U4QV.js +0 -2
- package/dist/split/chunks/chunk-UE6JK2ZA.js +0 -2
- /package/dist/split/chunks/{chunk-JCQTA35B.js.map → chunk-AKTGQ6TC.js.map} +0 -0
- /package/dist/split/chunks/{chunk-UE6JK2ZA.js.map → chunk-E3XSBW55.js.map} +0 -0
- /package/dist/split/chunks/{chunk-FFXJVUTT.js.map → chunk-JJYM4JVZ.js.map} +0 -0
- /package/dist/split/chunks/{chunk-SJRJALR4.js.map → chunk-LPJFTEVT.js.map} +0 -0
- /package/dist/split/chunks/{chunk-FT7OW7CG.js.map → chunk-R6RHIIR4.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["cacheFilterInfos","Map","STRUCTURAL_BINDING_TYPE_SET","Set","KEYWORDS_WITHOUT_MODIFIERS","ELSE_KEYWORD","EXPLICIT_PROPERTY_REJECTED_HEADS","CLASS_NAMESPACE","ATTR_NAMESPACE","STYLE_NAMESPACE","COMMAND_NAMESPACE","EVENT_TOKEN_NAMESPACE","VOLUME_INJECTION_PROP","parseBindTextsForElement","bindText","results","splitOutsideQuotes","splitBindTexts","map","trimFn","filter","s","length","separatorIndex","indexOfOutsideQuotes","raise","propPart","slice","trim","statePart","keyword","split","has","stateResult","statePathName","outFilters","parseStatePart","propName","propSegments","propModifiers","inFilters","bindingType","propResult","propText","filters","splitFilters","modifierParts","propModifiersText","some","segment","parsePropPart","head","includes","join","startsWith","r","TRUSTED_TYPES_POLICY_SLOT","Symbol","for","getTrustedTypesPolicy","value","globalThis","setTrustedTypesPolicy","policy","isHtmlSink","prop","trustHtml","trustedTypes","isHTML","String","create","createHTML","call","StateRow","constructor","list","index","item","this","cache","view","bindings","eqSubs","children","alive","StateList","pattern","parentRow","arr","rows","extra","queued","stale","shared","depth","EMPTY","Token","name","subscribers","size","subscribe","fn","add","delete","unsubscribe","emit","args","push","error","report","text","readNames","key","reserved","Array","isArray","seen","TRANSITION_RUNNER_KEY","getTransitionRunner","source","candidate","protocol","version","run","accepts","runTransition","mutate","types","runner","DECLARATIONS","BEHAVIOR_KEYS","unbound","path","recursionUnsupported","evals","MAX_DRAIN_PASSES","MAX_RENDER_CHAIN","upsert","m","k","make","v","get","set","newSet","newArray","twice","WeakMap","isThenable","then","sameValueZero","a","b","unsubEq","sub","dig","segs","i","rowAt","row","ctxRow","ctx","p","lists","Engine","target","strategy","slotCount","readonlyDepth","dropped","delegated","blockKey","element","errors","rendered","frames","depthNow","top","rootLists","rootBindings","queue","dirtyLists","staleLists","scheduled","draining","listsByArray","chain","carried","held","inApply","unsettled","fedBack","codeWrote","feeding","unchainFn","renderedFn","rp","rr","drainFn","drain","deliverFn","handler","proxy","rootEqSubs","loose","api","$untracked","f","untracked","$eqIndex","level","getter","underGetter","watchIndex","read","g","watchers","eqIndexWatchers","w","listP","eqIndexKeys","readUntracked","$eq","eq","$eqPath","keyPath","kp","$dependOn","resolve","track","$getAll","indexes","getAll","$setAll","options","setAll","$resolve","checkArity","rowOf","write","$postUpdate","last","resetRow","touched","mirror","rekeyEqUnder","landed","patterns","PatternTable","onPatternCreated","loadTarget","engine","getOwnPropertyDescriptor","_t","d","Reflect","configurable","receiver","t","charCodeAt","dollar","indexOf","peek","bound","trap","Proxy","pinned","registerAccessors","o","Object","prototype","getPrototypeOf","getOwnPropertyNames","setter","slot","all","parent","markupAccessor","INDEX_PARAM","test","findIndex","j","markup","childList","l","sync","trySync","failAt","anchor","unfile","old","next","hooks","n","start","oe","ne","rowRemoved","end","byItem","pop","values","indexChanged","reconcile","same","x","listSynced","schedule","keys","sel","before","after","invalidateUnder","onIndexChange","subs","e","was","splice","parsed","parsePath","idx","readData","tail","readGetter","addDependent","mark","epoch","reads","Math","min","crossSources","evalGetter","frame","outer","prev","prune","sources","rootValue","unlink","dropDependent","sweep","c","parents","dead","dependents","drop","q","indexWatchers","commands","subscribeEq","forSubtree","rest","rekeyEqIndex","invalidate","occurrence","beforeWrite","callAt","guard","is","syncListsUnder","sharing","direct","suffix","dup","holdsTwice","land","mp","down","deps","DIRTY","up","forListsUnder","enqueueBound","ls","isUnder","forAllLists","forRowsUnder","written","changed","onWrite","delegate","type","known","root","addEventListener","parentNode","cancelBubble","block","dispatch","reset","bs","enqueue","resetList","watchRendered","feature","requireFeature","$features","$behavior","mustache","directional","ns","$commandTokens","freeze","commandNamespace","events","deliver","tokens","$eventTokens","on","$on","entries","token","eventTokens","declare","forget","indexesOf","out","unshift","fireEventToken","event","command","emitCommand","invoke","apply","slots","enqueueSlots","fv","rv","walkDependents","visit","visitGetter","forAllRows","getterReached","register","unregister","queueMicrotask","dropWork","cutLoop","id","max","paths","noticed","maxDepth","setTimeout","pass","ran","update","owner","applyBinding","settled","pending","drained","fail","node","typeName","noteRendered","$renderedCallback","callHook","hook","$errorCallback","binding","failed","kind","forMatches","walk","lp","targets","spread","exact","Ot","gt","wt","St","Xt","at","xt","Jt","Qt","Zt"],"sources":["../../../src/parser/parsePropPart.ts","../../../src/parser/types.ts","../../../src/parser/parseBindTextsForElement.ts","../../../src/trustedTypes.ts","../../../src/list.ts","../../../src/token.ts","../../../src/protocol/transitionRunner.ts","../../../src/engine.ts"],"sourcesContent":["import { DELIMITER, MODIFIER_SEPARATOR } from \"./define\";\nimport { splitFilters } from \"./parseFilters\";\nimport { raise, M } from \"../messages\";\nimport { ParsedBinding, ParsedFilter } from \"./types\";\nimport { trimFn } from \"./utils\";\n\n// 解析の段の形(フィルタは名前と引数だけ — 実関数はエンジンが引く。要件 D16)\nexport type PropPartParseResult = Pick<ParsedBinding, 'propName' | 'propSegments' | 'propModifiers' | 'inFilters'>;\n\n/**\n * 入力フィルタ列の解析結果のキャッシュ(鍵は `|` より後ろの原文)。同じ原文は**同じ配列**を返す —\n * 消費側は返された `inFilters` を変更しないこと。落ちた解析は載らない。\n * (`@wcstack/state` の tooling 専用の解放口 `clearPropPartCacheForTooling` は移植しない)\n */\nconst cacheFilterInfos = new Map<string, ParsedFilter[]>();\n/** Tooling (`clearParserCaches`): a long-running process drops what it parsed. */\nexport const clearPropPartCache = (): void => cacheFilterInfos.clear();\n\n// format: propName#moodifier1,modifier2\n// propName-format: path.to.property (e.g., textContent, style.color, not include :)\n// special path:\n// 'attr.attributeName' for attributes (e.g., attr.href, attr.data-id)\n// 'style.propertyName' for style properties (e.g., style.backgroundColor, style.fontSize)\n// 'class.className' for class names (e.g., class.active, class.hidden)\n// 'onclick', 'onchange' etc. for event listeners\n\n/** Port of `@wcstack/state` `src/bindTextParser/parsePropPart.ts` (behaviour unchanged). */\nexport function parsePropPart(propPart: string): PropPartParseResult {\n const [propText, filters] = splitFilters(propPart, \"input\", cacheFilterInfos);\n\n // **不変条件**: ここから下の `split` は素で走らせてよい。`propText` は「引用符外の最初の `|`\n // より前」のスライスであり、引用符を含みうるのは入力フィルタの引数(`|` の後ろ)だけなので、\n // `#` も `,` も `.` も引用符の中に現れない。**修飾子の値に引用符を許す拡張(例\n // `value#fmt('a,b'): x`)を入れるなら、この 3 つも `splitOutsideQuotes` に替えること**。\n const modifierParts = propText.split(MODIFIER_SEPARATOR).map(trimFn);\n if (modifierParts.length > 2) {\n // 修飾子の並びは 1 つだけ(要件 B2)。`value#ro#wo` は以前 `ro` だけを残して黙って捨てていた\n raise(M.OneModifierList, [propText]);\n }\n const [propName, propModifiersText] = modifierParts;\n const propSegments = propName.split(DELIMITER).map(trimFn);\n // 明示のプロパティ形(`.name:` — 要件 B5 / D34)だけは先頭の空セグメントが正しい形。\n // それ以外で空のセグメントが残るのは書き間違い: 左辺が空(`\": x\"` / `\"#ro: x\"` / `\"|trim: x\"`)だと\n // `element[\"\"] = value` の expando ができて完全に沈黙し、末尾が空(`\"foo.: x\"`)だと適用の段で\n // 素の TypeError になる。どちらも解析の段で名指しで落とす(`.: x` 等は D34 の検査が受け持つ)\n const isExplicitProperty = propSegments.length > 1 && propSegments[0] === '';\n if (!isExplicitProperty && (propName.length === 0 || propSegments.some((segment) => segment.length === 0))) {\n raise(M.NoPropertyName, [propPart]);\n }\n const propModifiers = propModifiersText\n ? propModifiersText.split(',').map(trimFn)\n : [];\n return {\n propName,\n propSegments,\n propModifiers,\n inFilters: filters,\n };\n}\n","export type BindingType = 'text' | 'prop' | 'event' | 'for' | 'if' | 'elseif' | 'else' | 'radio' | 'checkbox' | 'spread';\n\n/** Left side (input) or right side (output) of a binding — only used to pick the diagnostic wording. */\nexport type FilterIOType = 'input' | 'output';\n\n/**\n * A filter as the grammar reads it: name and arguments only. The filter function is resolved\n * later by the engine (the parser never looks names up, so unknown names pass here).\n *\n * Field names are the ones of `@wcstack/state`'s `IParsedFilter`:\n * - `filterName` — the name as written (no alias resolution).\n * - `args` — the raw argument texts, quotes removed (format filters read these).\n * - `literals` — the typed value of each argument (requirement B9): unquoted `true` / `false` /\n * `null` / numbers are typed, everything else (and every quoted argument) is the string.\n * Always the same length and order as `args`.\n */\nexport interface ParsedFilter {\n filterName: string;\n args: string[];\n literals: unknown[];\n}\n\n/** Parse result of one binding (DOM independent). */\nexport interface ParsedBinding {\n propName: string;\n propSegments: string[];\n propModifiers: string[];\n statePathName: string;\n inFilters: ParsedFilter[];\n outFilters: ParsedFilter[];\n bindingType: BindingType;\n}\n\n/** Bindings that must be the only binding of their attribute value. */\nexport const STRUCTURAL_BINDING_TYPE_SET: ReadonlySet<BindingType> = new Set<BindingType>([\n 'if',\n 'elseif',\n 'else',\n 'for',\n]);\n","import {\n ATTR_NAMESPACE,\n BINDING_SEPARATOR,\n CLASS_NAMESPACE,\n COMMAND_NAMESPACE,\n DELIMITER,\n ELSE_KEYWORD,\n EVENT_PROP_PREFIX,\n EVENT_TOKEN_NAMESPACE,\n FILTER_SEPARATOR,\n MODIFIER_SEPARATOR,\n PROP_VALUE_SEPARATOR,\n SPREAD_PROP,\n STYLE_NAMESPACE,\n VOLUME_INJECTION_PROP,\n} from \"./define\";\nimport { parsePropPart } from \"./parsePropPart\";\nimport { parseStatePart, type StatePartParseResult } from \"./parseStatePart\";\nimport { raise, M } from \"../messages\";\nimport { ParsedBinding, STRUCTURAL_BINDING_TYPE_SET } from \"./types\";\nimport { indexOfOutsideQuotes, splitOutsideQuotes, trimFn } from \"./utils\";\n\n// format: propPart:statePart; propPart:statePart; ...\n// special-propPart:\n// if: statePart (single binding for conditional rendering)\n// else: (single binding for conditional rendering, and statePart is ignored)\n// elseif: statePart only (single binding for conditional rendering)\n// for: statePart only (single binding for loop rendering)\n// onclick: statePart, onchange: statePart etc. (event listeners)\n// ...: statePart (spread — the engine expands it into the target's wcBindable properties)\n\n/** 左辺に修飾子も入力フィルタも取らない束縛(構造ディレクティブと spread)— 付いていれば拒否する(要件 B4) */\nconst KEYWORDS_WITHOUT_MODIFIERS = new Set<string>([ELSE_KEYWORD, 'if', 'elseif', 'for', SPREAD_PROP]);\n\n/**\n * 明示のプロパティ形(`.name:`)の先頭に置けない語 — 名前空間として読まれる語(要件 B5)。\n * `state`(`VOLUME_INJECTION_PROP`)も含む: `<wcs-state mount>` 上の左辺 `state.<key>:` は\n * 注入の宣言(要件 B14③)なので、`.state.taxRate:` はプロパティか注入か曖昧になる。\n */\nconst EXPLICIT_PROPERTY_REJECTED_HEADS = new Set<string>([\n CLASS_NAMESPACE, ATTR_NAMESPACE, STYLE_NAMESPACE, COMMAND_NAMESPACE, EVENT_TOKEN_NAMESPACE,\n VOLUME_INJECTION_PROP,\n]);\n\n/**\n * `data-wcs` の値をバインディングごとに区切る(前後の空白は残す — tooling が位置を数えられるように)。\n * 引用符の中の `;` は区切りではない(要件 B1 — `join(';')`)。\n */\nexport function splitBindTexts(bindText: string): string[] {\n return splitOutsideQuotes(bindText, BINDING_SEPARATOR);\n}\n\n/**\n * `data-wcs` 属性値 1 つを解析する。Port of `@wcstack/state`\n * `src/bindTextParser/parseBindTextsForElement.ts` — same signature (text only: no decision\n * here needs the element), same results minus `statePathInfo`, same diagnostics.\n *\n * The parser does NOT: expand the loop-relative shorthand (`.name` / `.`), expand `...:`\n * spread into the target's properties, resolve filter names/functions, or check the\n * `if`/`elseif`/`else` sibling order — the engine does those.\n */\nexport function parseBindTextsForElement(bindText: string): ParsedBinding[] {\n const bindTexts = splitBindTexts(bindText).map(trimFn).filter(s => s.length > 0);\n const results = bindTexts.map((bindText): ParsedBinding => {\n // 左辺と右辺の区切りも引用符の外だけで探す(要件 B1)。`value|defaults(':'): path` の\n // 引数の中の `:` を区切りとして拾っていた\n const separatorIndex = indexOfOutsideQuotes(bindText, PROP_VALUE_SEPARATOR);\n if (separatorIndex === -1) {\n raise(M.BindTextNoColon, [bindText]);\n }\n const propPart = bindText.slice(0, separatorIndex).trim();\n const statePart = bindText.slice(separatorIndex + 1).trim();\n // 種別は修飾子・入力フィルタより前の名前で決める(要件 B4)。以前は左辺全体との完全一致で\n // 判定していたので、`radio#ro:` が汎用プロパティに落ちていた。\n // **不変条件**: ここは素の `split` でよい — 取り出すのは最初の区切りより前の**先頭**片で、\n // 引用符を含みうるのは入力フィルタの引数(引用符外の最初の `|` より後ろ)だけなので、\n // `#` も `|` も引用符の中では出会わない。**修飾子の値に引用符を許す拡張を入れるなら\n // `indexOfOutsideQuotes` に替えること**(`parsePropPart.ts` の同じ注記と対)。\n const keyword = propPart.split(MODIFIER_SEPARATOR)[0].split(FILTER_SEPARATOR)[0].trim();\n if (KEYWORDS_WITHOUT_MODIFIERS.has(keyword)) {\n if (keyword !== propPart) {\n raise(M.StructuralTakesNoModifiers, [bindText, keyword]);\n }\n let stateResult: StatePartParseResult;\n if (keyword === ELSE_KEYWORD) {\n if (statePart.length > 0) {\n // else は値を取らない(要件 B2)。以前は右辺を黙って捨てていた\n raise(M.ElseTakesNoValue, [bindText]);\n }\n stateResult = { statePathName: '#else', outFilters: [] };\n } else if (keyword === SPREAD_PROP) {\n // 空の右辺は spread 専用の語彙で先に落とす。`parseStatePart` の一般の空パス診断\n // (「the right side of a binding must name a state path」)より、ここでは\n // 「spread target path is required」のほうが直し方を指している\n if (statePart.length === 0) {\n raise(M.SpreadNoPath, [bindText]);\n }\n stateResult = parseStatePart(statePart);\n if (stateResult.outFilters.length > 0) {\n raise(M.SpreadNoFilters, [bindText]);\n }\n } else {\n stateResult = parseStatePart(statePart);\n // a row of `for: p` is `p.<index>`: the rows of a filtered list would name other elements (#370)\n if (keyword === 'for' && stateResult.outFilters.length > 0) {\n raise(M.ForNoFilters, [bindText]);\n }\n }\n return {\n propName: keyword,\n propSegments: [keyword],\n propModifiers: [],\n inFilters: [],\n ...stateResult,\n bindingType: keyword === SPREAD_PROP ? 'spread' : keyword as ParsedBinding['bindingType'],\n };\n }\n // `class` / `attr` は名前を伴ってはじめて束縛になる(`class.done:` / `attr.href:`)。名前の無い\n // `class:` / `attr:` は要素の(存在しない)`class` / `attr` プロパティへの書き込みになり、何も起きず\n // 何も報告されなかった(`.class:` は B5 で拒否済み)。`style:` は `el.style = \"…\"` が cssText に\n // 届くので受ける\n if (keyword === CLASS_NAMESPACE || keyword === ATTR_NAMESPACE) {\n raise(M.NamespaceNeedsName, [bindText, keyword]);\n }\n const stateResult = parseStatePart(statePart);\n const propResult = parsePropPart(propPart);\n const [head] = propResult.propSegments;\n // 左辺の先頭ドット(`.online:`)は明示のプロパティ形(要件 B5・3.x 計画 D34)。ドットの無い形と\n // 同じ束縛だが、`on` で始まってもイベントにはならない(`online:` は \"line\" イベントを待つ)。\n // 名前空間の語(`.class.x` / `.command.x` …)はプロパティか名前空間か曖昧なので受けない\n if (head === '' && propResult.propSegments.length > 1) {\n const propSegments = propResult.propSegments.slice(1);\n if (propSegments.includes('') || EXPLICIT_PROPERTY_REJECTED_HEADS.has(propSegments[0])) {\n raise(M.LeadingDotNamespace, [propPart]);\n }\n return {\n ...propResult,\n propName: propSegments.join(DELIMITER),\n propSegments,\n ...stateResult,\n bindingType: 'prop',\n };\n }\n return {\n ...propResult,\n ...stateResult,\n // 修飾子(`#ro`・`#onchange` …)と入力フィルタは radio / checkbox のハンドラが読む(要件 B4)。\n // eventToken.<prop>: <name> は要素 dispatch を state へ流す pub/sub 配線。\n // 値適用ではないため bindingType 'event' として listener attach 経路に乗せる。\n bindingType: keyword === 'radio' || keyword === 'checkbox' ? keyword\n : head === EVENT_TOKEN_NAMESPACE || head.startsWith(EVENT_PROP_PREFIX) ? 'event' : 'prop',\n };\n });\n // check for sigle binding for 'if', 'elseif', 'else', 'for'\n if (results.length > 1) {\n const isIncludeSingleBinding = results.some(r => STRUCTURAL_BINDING_TYPE_SET.has(r.bindingType));\n if (isIncludeSingleBinding) {\n // lint 側の単独バインディング検査(bindingValidator の structuralMustBeSingle)が\n // 同じケースを検出するため誘導を付ける(三面同語彙)。\n raise(M.StructuralNotSingle, [bindText]);\n }\n }\n return results;\n}\n","/**\n * Trusted Types for the HTML sinks (`html:`, `innerHTML:`, `outerHTML:`, `srcdoc:`).\n * The policy lives on the same global slot as @wcstack/state, so a page that installed\n * one for the current engine keeps working:\n * globalThis[Symbol.for(\"wcstack.trustedTypes.policy\")] = trustedTypes.createPolicy(…)\n * No identity policy is ever created here — that would defeat the CSP.\n */\nexport interface TrustedTypesPolicy {\n createHTML?(input: string): unknown;\n}\n\nexport const TRUSTED_TYPES_POLICY_SLOT = Symbol.for(\"wcstack.trustedTypes.policy\");\n\ntype Slot = { [key: symbol]: unknown };\n\nexport function getTrustedTypesPolicy(): TrustedTypesPolicy | null {\n const value = (globalThis as Slot)[TRUSTED_TYPES_POLICY_SLOT];\n return value !== null && typeof value === \"object\" ? (value as TrustedTypesPolicy) : null;\n}\n\nexport function setTrustedTypesPolicy(policy: TrustedTypesPolicy | null): void {\n (globalThis as Slot)[TRUSTED_TYPES_POLICY_SLOT] = policy;\n}\n\nexport function isHtmlSink(prop: string): boolean {\n return prop === \"innerHTML\" || prop === \"outerHTML\" || prop === \"srcdoc\";\n}\n\n/**\n * A value for an HTML sink: a TrustedHTML (the page made it with its own policy) as it is, anything\n * else — an array or another object too, which the sink would turn into markup — as a string\n * (null / undefined: empty) passed through the installed policy (if any).\n */\nexport function trustHtml(value: unknown): unknown {\n if ((globalThis as any).trustedTypes?.isHTML(value)) return value;\n const s = value == null ? \"\" : String(value);\n const policy = getTrustedTypesPolicy();\n const create = policy?.createHTML;\n return typeof create === \"function\" ? create.call(policy, s) : s;\n}\n","import type { Pattern } from \"./pattern\";\nimport type { Binding, ForView, RowView } from \"./dom/view\";\n\n/**\n * One element of a list, owned by its StateList. The row is the whole address of\n * everything under `list.*`: the value (`item`), the position (`index`), the getter\n * cache and the bindings that render it hang off this object — no ledger keyed by an\n * address. Dropping the row drops all of it.\n */\nexport class StateRow {\n readonly list: StateList;\n index: number;\n item: unknown;\n /** Getter cache by slot (row-level getters of this engine). */\n cache: unknown[] | null = null;\n /** The rendering of this row by its list's first for view (see StateList.extra for the others). */\n view: RowView | null = null;\n /**\n * Binding objects whose location is in this row (pattern depth = this row's depth), wherever\n * they render. Row views' slot bindings are not here: they are reached through the views.\n */\n bindings: Binding[] | null = null;\n /** `$eq` subscriptions of getters evaluated at this row (dropped with the row). */\n eqSubs: import(\"./engine\").EqEntry[] | null = null;\n /** Nested lists under this row, by list pattern. */\n children: Map<Pattern, StateList> | null = null;\n alive = true;\n\n constructor(list: StateList, index: number, item: unknown) {\n this.list = list;\n this.index = index;\n this.item = item;\n }\n}\n\nexport class StateList {\n readonly pattern: Pattern;\n readonly parentRow: StateRow | null;\n /** Depth of this list's rows (1 for a root list). */\n readonly depth: number;\n /** The array the rows were last reconciled against. */\n arr: unknown[] | null = null;\n rows: StateRow[] = [];\n /** The first for view that renders this list, if any (its row views are on row.view). */\n view: ForView | null = null;\n /** Further for views rendering the same list (each keeps its row views by row). */\n extra: ForView[] | null = null;\n /** Queued for a view update in the current drain. */\n queued = false;\n /** Its pattern reads through a getter that changed: re-synced at the next drain pass. */\n stale = false;\n /** Another list has the same array (a getter returning it, an index path): writes reach both. */\n shared = false;\n\n constructor(pattern: Pattern, parentRow: StateRow | null) {\n this.pattern = pattern;\n this.parentRow = parentRow;\n this.depth = pattern.depth + 1;\n }\n}\n\nexport interface ReconcileHooks {\n /** A kept row changed position. */\n indexChanged(row: StateRow): void;\n /** A row left the list (it marks it dead). */\n rowRemoved(row: StateRow): void;\n}\n\ntype Bucket = StateRow | StateRow[];\n\n/**\n * Brings `list.rows` in line with `next`, reusing rows by item identity.\n * Returns the previous rows (for $eqIndex re-keying) or null when nothing changed.\n * DOM is not touched here; the list's view catches up in the drain.\n */\nexport function reconcile(list: StateList, next: unknown, hooks: ReconcileHooks): StateRow[] | null {\n const arr = Array.isArray(next) ? next : EMPTY;\n if (arr === list.arr) return null;\n const old = list.rows;\n const n = arr.length;\n const o = old.length;\n const rows: StateRow[] = new Array(n);\n\n let start = 0;\n while (start < n && start < o && old[start].item === arr[start]) {\n rows[start] = old[start];\n start++;\n }\n let oe = o - 1;\n let ne = n - 1;\n while (oe >= start && ne >= start && old[oe].item === arr[ne]) {\n rows[ne] = old[oe];\n oe--;\n ne--;\n }\n\n if (start > oe) {\n for (let i = start; i <= ne; i++) rows[i] = new StateRow(list, i, arr[i]);\n } else if (start > ne) {\n for (let i = start; i <= oe; i++) hooks.rowRemoved(old[i]);\n } else {\n // a row whose item is where it was keeps its place: among equal items (a board of 0 / 1), handing\n // the rows out in order would move every one after the first change\n const end = oe < ne ? oe : ne;\n for (let i = start; i <= end; i++) if (old[i].item === arr[i]) rows[i] = old[i];\n const byItem = new Map<unknown, Bucket>();\n // filled from the end, so a bucket hands out its first row with pop(): shift() moves the whole\n // array, and over a long run of equal items the reconcile went quadratic\n for (let i = oe; i >= start; i--) {\n const row = old[i];\n if (i <= end && rows[i] === row) continue;\n const b = byItem.get(row.item);\n if (b === undefined) byItem.set(row.item, row);\n else if (Array.isArray(b)) b.push(row);\n else byItem.set(row.item, [b, row]);\n }\n for (let i = start; i <= ne; i++) {\n if (rows[i] !== undefined) continue;\n const item = arr[i];\n const b = byItem.get(item);\n let row: StateRow | undefined;\n if (b !== undefined) {\n if (Array.isArray(b)) {\n row = b.pop();\n if (b.length === 0) byItem.delete(item);\n } else {\n row = b;\n byItem.delete(item);\n }\n }\n rows[i] = row ?? new StateRow(list, i, item);\n }\n for (const b of byItem.values()) {\n if (Array.isArray(b)) for (const r of b) hooks.rowRemoved(r);\n else hooks.rowRemoved(b);\n }\n }\n\n // positions: only rows from `start` on can have moved\n for (let i = start; i < n; i++) {\n const row = rows[i];\n if (row.index !== i) {\n row.index = i;\n hooks.indexChanged(row);\n }\n }\n list.rows = rows;\n list.arr = arr;\n return old;\n}\n\n/** What a list whose value is not an array reconciles against (engine: an index there is a key). */\nexport const EMPTY: unknown[] = [];\n","/**\n * The command-token / event-token pub/sub primitive (the same shape as @wcstack/state's\n * `Token`). A subscriber that throws is reported and the others still receive the call.\n */\nimport { raise, M, text } from \"./messages\";\nimport { report } from \"./parser/raiseError\";\n\nexport type TokenSubscriber = (...args: unknown[]) => unknown;\n\nexport class Token {\n readonly name: string;\n private readonly subscribers = new Set<TokenSubscriber>();\n\n constructor(name: string) {\n this.name = name;\n }\n\n get size(): number {\n return this.subscribers.size;\n }\n\n subscribe(fn: TokenSubscriber): () => void {\n this.subscribers.add(fn);\n return () => {\n this.subscribers.delete(fn);\n };\n }\n\n unsubscribe(fn: TokenSubscriber): boolean {\n return this.subscribers.delete(fn);\n }\n\n emit(...args: unknown[]): unknown[] {\n const results: unknown[] = [];\n for (const fn of this.subscribers) {\n try {\n results.push(fn(...args));\n } catch (error) {\n results.push(undefined);\n report(error, `[@wcstack/state] ${text(M.TokenSubscriberThrew, [this.name])}`);\n }\n }\n return results;\n }\n}\n\nfunction readNames(value: unknown, key: string, reserved?: string): string[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) raise(M.TokenListNotArray, [key]);\n const seen = new Set<string>();\n for (const name of value) {\n if (typeof name !== \"string\" || name === \"\") raise(M.TokenEntryEmpty, [key]);\n if (name === reserved) raise(M.TokenEntryReserved, [key, name, reserved]);\n if (seen.has(name)) raise(M.TokenEntryDuplicated, [key, name]);\n seen.add(name);\n }\n return value as string[];\n}\n\n/**\n * `$commandTokens` → the frozen `$command` namespace (name → Token). On a re-set, a name\n * the previous state declared keeps its token: elements subscribed to it keep receiving.\n */\nexport function commandNamespace(target: Record<string, any>, prev?: Readonly<Record<string, Token>>): Readonly<Record<string, Token>> {\n const ns: Record<string, Token> = {};\n for (const name of readNames(target.$commandTokens, \"$commandTokens\", \"$command\")) ns[name] = prev?.[name] ?? new Token(name);\n return Object.freeze(ns);\n}\n\n/**\n * `$eventTokens` + `$on` → name → Token, with each `$on` handler subscribed as\n * `(state, event, ...listIndexes)` through `deliver`.\n */\nexport function eventTokens(\n target: Record<string, any>,\n deliver: (handler: (...args: unknown[]) => unknown, args: unknown[]) => unknown,\n): Map<string, Token> {\n const tokens = new Map<string, Token>();\n for (const name of readNames(target.$eventTokens, \"$eventTokens\")) tokens.set(name, new Token(name));\n const on = target.$on;\n if (on === undefined) return tokens;\n if (on === null || typeof on !== \"object\") raise(M.OnNotObject);\n for (const [name, handler] of Object.entries(on)) {\n const token = tokens.get(name);\n if (token === undefined) raise(M.OnEntryUndeclared, [name]);\n if (typeof handler !== \"function\") raise(M.OnEntryNotFunction, [name]);\n token.subscribe((...args) => deliver(handler as (...a: unknown[]) => unknown, args));\n }\n return tokens;\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/transition-runner.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// transition-runner protocol — how a package that mutates the DOM hands that\n// mutation to whoever is arbitrating view transitions on the page.\n//\n// @wcstack/state and @wcstack/router must not depend on @wcstack/view-transition\n// (zero runtime dependencies, independently publishable), so the arbiter installs\n// itself on a well-known global symbol and the participants look it up lazily.\n// No arbiter installed means the mutation is invoked directly, synchronously —\n// byte-for-byte the behavior these packages had before the protocol existed.\n//\n// docs/view-transition-design.md §4 is the normative description.\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/transition-runner.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/transitionRunner.ts). Those copies are generated — do not edit them.\n\n/**\n * Global key the arbiter installs itself under. `Symbol.for` so independently\n * loaded copies of this file (two CDN bundles on one page) still agree.\n */\nexport const TRANSITION_RUNNER_KEY = Symbol.for(\"wcstack.transition-runner\");\n\n/** Who is asking. Backs the arbiter's `for=` participant gate. */\nexport type TransitionSource = \"router\" | \"state\";\n\n/** `view-transition-name` assignment policy the arbiter declares for participants. */\nexport type TransitionNaming = \"manual\" | \"auto\";\n\nexport interface IWcsTransitionRunOptions {\n /** Participant id, for the `for=` gate and for diagnostics. */\n readonly source?: string;\n /** Transition types, where the environment supports `startViewTransition({ types })`. */\n readonly types?: readonly string[];\n}\n\nexport interface IWcsTransitionRunner {\n readonly protocol: \"wcs-transition-runner\";\n /** Integer protocol version. All versions >= 1 are participant-compatible. */\n readonly version: number;\n /** `\"auto\"` licenses a participant to assign `view-transition-name` itself. */\n readonly naming: TransitionNaming;\n /** Upper bound on auto-assigned names; past it a participant stops naming. */\n readonly namingLimit: number;\n /** Whether this participant animates at all. */\n accepts(source: string): boolean;\n /**\n * Invoke `mutate` inside a view transition when one is possible.\n *\n * Contract (docs/view-transition-design.md §4):\n * - `mutate` is invoked exactly once, whatever happens to the transition.\n * - The promise resolves once `mutate` has run — never waits for the animation.\n * - When no transition is started, `mutate` runs synchronously inside `run()`.\n * - It rejects only if `mutate` threw.\n */\n run(mutate: () => void, options?: IWcsTransitionRunOptions): Promise<void>;\n}\n\n/**\n * The installed arbiter, or null when there is none, it speaks a version this\n * reader does not, or it does not accept this participant.\n *\n * Looked up on every call rather than cached: the tag can be added, removed, or\n * reconfigured at any point in a page's life, and a stale cache would either\n * animate what the author just switched off or miss what they switched on.\n */\nexport function getTransitionRunner(source: string): IWcsTransitionRunner | null {\n const candidate = (globalThis as Record<symbol, unknown>)[TRANSITION_RUNNER_KEY] as\n | IWcsTransitionRunner\n | undefined;\n if (candidate === undefined || candidate === null) return null;\n if (candidate.protocol !== \"wcs-transition-runner\") return null;\n if (typeof candidate.version !== \"number\" || candidate.version < 1) return null;\n if (typeof candidate.run !== \"function\") return null;\n if (typeof candidate.accepts !== \"function\" || !candidate.accepts(source)) return null;\n return candidate;\n}\n\n/**\n * Run `mutate` under the installed arbiter, or directly when there is none.\n *\n * Returns `undefined` in the no-arbiter case instead of a resolved promise: the\n * state drain calls this on every batch, and awaiting is a caller's choice, not\n * an allocation the common path should pay for. `await` accepts both.\n */\nexport function runTransition(\n source: string,\n mutate: () => void,\n types?: readonly string[],\n): Promise<void> | undefined {\n const runner = getTransitionRunner(source);\n if (runner === null) {\n mutate();\n return undefined;\n }\n return runner.run(mutate, { source, types });\n}\n","import { DIRTY, Pattern, PatternTable, parsePath, WILDCARD, type EqSub } from \"./pattern\";\nimport { StateList, StateRow, reconcile, EMPTY, type ReconcileHooks } from \"./list\";\nimport type { Strategy } from \"./strategy/types\";\nimport type { Binding } from \"./dom/view\";\nimport { commandNamespace, eventTokens, type Token } from \"./token\";\nimport { runTransition } from \"./protocol/transitionRunner\";\nimport { raise, M, text } from \"./messages\";\nimport { recursionUnsupported } from \"./parser/parseStatePart\";\nimport { hooks, requireFeature } from \"./hooks\";\nimport { INDEX_PARAM, MAX_INDEX_PARAM } from \"./parser/define\";\nimport { report } from \"./parser/raiseError\";\n\n/** Declarations an add-on serves: without it installed they fail instead of doing nothing. */\nconst DECLARATIONS: [string, string][] = [[\"$watch\", \"temporal\"], [\"$stream\", \"temporal\"], [\"$listKeys\", \"list-keys\"], [\"$recursion\", \"recursion\"]];\n\n/**\n * The options of `$behavior` (each true by default): what an engine reads them as is `mustache` / `guard` / `directional`.\n * The tooling manifest publishes the same list (`behaviorOptions`, public/manifest.ts — public-surface.test.ts pins\n * them equal; the manifest does not import the engine).\n */\nexport const BEHAVIOR_KEYS: readonly string[] = [\"enableMustache\", \"sameValueGuard\", \"enableDirectionalInitialSync\"];\n\n/** `**` binds a depth only where a path is read: an assignment, $resolve, $postUpdate and $dependOn refuse it. */\nfunction unbound(path: string): string {\n if (path.includes(\"**\")) recursionUnsupported(path);\n return path;\n}\n\n/** `$1` … `$128`, no leading zero (parser/define.ts — the tooling manifest reads them there too). */\nexport { INDEX_PARAM, MAX_INDEX_PARAM };\n\ninterface Frame {\n getter: Pattern;\n row: StateRow | null;\n untracked: number;\n /** The evaluation this frame runs (`$eq` tells its keys from an earlier evaluation's). */\n epoch: number;\n /** What a root getter's evaluation read (Engine.prune). */\n reads: Pattern[];\n}\n\n/** Getter evaluations so far (each frame takes the next: an evaluation's identity). */\nlet evals = 0;\n\n/** A `$eq` subscription of a getter occurrence, kept on its row (or the engine, at the root). */\nexport interface EqEntry {\n source: Pattern;\n key: unknown;\n sub: EqSub;\n epoch: number;\n}\n\n/** A drain that keeps producing work this many times in a row is an update loop. */\nexport const MAX_DRAIN_PASSES = 32;\n/**\n * Drains in a row that rendering itself started (an element's write-back, a write in\n * `$renderedCallback`) beyond this many are an update loop (as @wcstack/state 3.3.x).\n */\nexport const MAX_RENDER_CHAIN = 100;\n/** Nested getter evaluations deeper than this are a runaway chain. */\nconst MAX_GETTER_DEPTH = 128;\n\nexport type Visit = (getter: Pattern, row: StateRow | null) => boolean;\n\n/** The value of `k` in `m`, made and set first when there is none (`make`: a shared factory, not a closure per call). */\nfunction upsert<K, V>(m: { get(k: K): V | undefined; set(k: K, v: V): unknown }, k: K, make: () => V): V {\n let v = m.get(k);\n if (v === undefined) m.set(k, (v = make()));\n return v;\n}\nconst newSet = <T>(): Set<T> => new Set<T>();\nconst newArray = <T>(): T[] => [];\n\n/**\n * Whether an array holds one object at two positions (F26, `items: [o, o]`), found when a write into a\n * row's object first needs it: once per array, so the writes after it stay O(1). An element written in\n * place drops the answer.\n */\nconst twice = new WeakMap<unknown[], boolean>();\nfunction holdsTwice(arr: unknown[]): boolean {\n let v = twice.get(arr);\n if (v === undefined) {\n const seen = new Set<unknown>();\n twice.set(arr, v = arr.some((x) => Object(x) === x && (seen.has(x) || !seen.add(x))));\n }\n return v;\n}\n\n/** A promise, or anything with a then(). */\nexport function isThenable(r: any): r is PromiseLike<unknown> {\n return r !== null && typeof r === \"object\" && typeof r.then === \"function\";\n}\n\n/** Map-key equality: Object.is, except +0 and -0 are equal (keys of a Map). */\nfunction sameValueZero(a: unknown, b: unknown): boolean {\n return a === b || (a !== a && b !== b);\n}\n\n/** Drops a `$eq` subscription; a key nobody waits for any more leaves the map (it may be a row's item). */\nfunction unsubEq(source: Pattern, key: unknown, sub: EqSub): void {\n const set = source.eqSubs?.get(key);\n if (set !== undefined && set.delete(sub) && set.size === 0) source.eqSubs!.delete(key);\n}\n\nfunction dig(v: any, segs: readonly string[]): unknown {\n for (let i = 0; i < segs.length; i++) {\n if (v == null) return undefined;\n v = v[segs[i]];\n }\n return v;\n}\n\n/** The row at `depth` on the chain of `row` (itself or an ancestor), or null. */\nexport function rowAt(row: StateRow | null, depth: number): StateRow | null {\n while (row !== null && row.list.depth > depth) row = row.list.parentRow;\n return row !== null && row.list.depth === depth ? row : null;\n}\n\n/** The context row of `p`'s list at depth `k` — null when the context is a row of another list. */\nfunction ctxRow(ctx: StateRow | null, p: Pattern, k: number): StateRow | null {\n const r = rowAt(ctx, k);\n return r !== null && r.list.pattern === p.lists[k] ? r : null;\n}\n\n/**\n * One engine per <wcs-state>. It owns everything reachable from its state: the\n * patterns, the lists and their rows, the bindings, the update queue. Nothing is keyed\n * by the state element, because nothing is shared between engines.\n */\nexport class Engine implements ReconcileHooks {\n target!: Record<string, any>;\n /** `$behavior` (fixed at construction): `{{ }}` text, the same-value guard, direction-aware initial sync. */\n mustache!: boolean;\n guard!: boolean;\n directional!: boolean;\n readonly patterns: PatternTable;\n readonly strategy: Strategy;\n readonly proxy: Record<string, any>;\n /** Number of row-level getter slots. */\n slotCount = 0;\n /** Evaluation context: the row a getter / method / setter runs for. */\n ctx: StateRow | null = null;\n /** Writes throw while > 0: a readonly createState callback, or a getter being evaluated. */\n readonlyDepth = 0;\n /**\n * Top-level keys a re-set dropped (the old state had them, the new one lacks them): they read as\n * undefined, not as keys never declared (read; the diagnostics add-on reads it too). Kept here — the\n * author's state object is not written to (it may be frozen, or a Proxy that refuses).\n */\n readonly dropped = new Set<string>();\n /** The node the bindings were mounted on (delegated listeners live here); none before the mount. */\n root?: Node;\n /** Delegated event types → the property (per engine) their element handlers are stored under. */\n private readonly delegated = new Map<string, symbol>();\n /** Property (per engine) on a block's top node(s) holding the block, for delegated events. */\n readonly blockKey = Symbol(\"wcs.block\");\n /** The <wcs-state> element (`this.$stateElement`). */\n element: unknown = null;\n /**\n * A mounted component's (scopes add-on): a function read off the proxy itself, made to run on it\n * when called detached — the proxy is `element.state`, and `const { toggle } = element.state`\n * works (3.x #331). Undefined (or no answer): as it is.\n */\n declare bound?: (fn: (...args: any[]) => unknown) => unknown;\n /** `$command`: the command tokens declared in `$commandTokens`. */\n commands!: Readonly<Record<string, Token>>;\n /** The event tokens declared in `$eventTokens`, with the `$on` handlers subscribed. */\n events!: Map<string, Token>;\n /** Binding failures of the current drain, reported after it (`$errorCallback` or console). */\n private errors: [unknown, Binding][] = [];\n /** Paths applied in the current drain, for `$renderedCallback` (collected only when declared). */\n rendered: Map<string, number[][]> | null = null;\n private frames: Frame[] = [];\n private depthNow = 0;\n private top: Frame | null = null;\n readonly rootLists = new Map<Pattern, StateList>();\n readonly rootBindings = new Map<Pattern, Set<Binding>>();\n private queue: Binding[] = [];\n private dirtyLists: StateList[] = [];\n /** Lists over a changed getter, re-synced at the start of the next drain pass. */\n private staleLists: StateList[] = [];\n private scheduled = false;\n private draining = false;\n /** The lists over each array (only while more than one list has it do writes mirror). */\n private readonly listsByArray = new WeakMap<unknown[], StateList[]>();\n /** Drains in a row that rendering started (MAX_RENDER_CHAIN); a pause between tasks ends it. */\n private chain = 0;\n /**\n * For the drain the write-backs of an apply an arbiter deferred start: its place in that apply's\n * chain (0: none). The pause before the apply ends the task's chain, not this one. Only what the\n * apply writes synchronously is carried: an async `$renderedCallback` writing after an `await`\n * starts a task chain again, so such a loop runs one lap per arbiter task and is never cut.\n */\n private carried = 0;\n /**\n * Applies an arbiter is holding for its transition: until the last has run, what follows a drain\n * (`$watch`, the diagnostics) waits, so it sees the page the update produced, as without one — a\n * `$watch` that navigated ran before `<wcs-storage>` saved (docs/seam-apps.md, city-library).\n */\n private held = 0;\n /** Draining inside such an apply: its passes are applied at once, in the arbiter's transition. */\n private inApply = 0;\n /** This chain was reported as not settling within a drain (#11): reported once a chain. */\n private unsettled = false;\n /** Since the last drain started: a write rendering fed back / a write from code (which ends a chain). */\n private fedBack = false;\n private codeWrote = false;\n /**\n * Inside `$renderedCallback` (until an async one settles) or a `$watch` handler: its writes are\n * reactions, fed back like an element's (MAX_RENDER_CHAIN).\n */\n feeding = 0;\n private readonly unchainFn = () => {\n this.chain = 0;\n this.unsettled = false;\n };\n private readonly renderedFn = () => {\n this.feeding--;\n };\n // out-parameters of resolve()\n private rp: Pattern | null = null;\n private rr: StateRow | null = null;\n\n private readonly drainFn = () => {\n // (drained already, inside an arbiter's apply)\n if (this.scheduled) this.drain();\n };\n private readonly deliverFn = (handler: (...a: unknown[]) => unknown, args: unknown[]) => handler(this.proxy, ...args);\n /** `$eq` subscriptions of root-level getters. */\n private readonly rootEqSubs: EqEntry[] = [];\n /** Patterns made, or no longer read by a root getter, since the last sweep: what it looks at. */\n private loose: Pattern[] = [];\n /** The `$` functions of the state (`this.$eq`, …), by name. */\n private readonly api: Record<string, unknown> = {\n $untracked: (fn: () => unknown) => {\n const f = this.top;\n if (f === null) return fn();\n f.untracked++;\n try {\n return fn();\n } finally {\n f.untracked--;\n }\n },\n $eqIndex: (path: string, level = 1) => {\n const row = rowAt(this.ctx, level);\n if (row === null) raise(M.EqIndexNoRow, [path]);\n const source = this.pattern(path);\n // a getter (or a path under one) changes without a write: an ordinary tracked read, and the\n // row's index is read as `$1` reads it (a moved row compares again)\n if (source.getter !== null || source.underGetter) {\n this.watchIndex(level);\n return row.index === this.read(source, null);\n }\n const f = this.top;\n if (f !== null) {\n const g = f.getter;\n const watchers = source.eqIndexWatchers ?? (source.eqIndexWatchers = []);\n if (!watchers.some((w) => w.getter === g && w.level === level)) {\n watchers.push({ getter: g, level });\n const listP = g.lists[level]!;\n (listP.eqIndexKeys ?? (listP.eqIndexKeys = [])).push({ source, getter: g });\n }\n }\n return row.index === this.readUntracked(source, null);\n },\n $eq: (path: string, key: unknown) => this.eq(path, key),\n $eqPath: (path: string, keyPath: string) => {\n const kp = this.pattern(keyPath);\n return this.eq(path, this.readUntracked(kp, rowAt(this.ctx, kp.depth)));\n },\n $dependOn: (path: string) => {\n this.resolve(unbound(path), this.ctx);\n if (this.top !== null && this.top.untracked === 0) this.track(this.rp!, this.rr, this.top);\n },\n $getAll: (path: string, indexes?: number[]) => this.getAll(path, indexes),\n $setAll: (path: string, indexes: number[], value: unknown, options?: { spread?: boolean }) =>\n this.setAll(path, indexes, value, options),\n // $resolve(path, indexes) reads; $resolve(path, indexes, value) writes (the argument count decides)\n $resolve: (...args: unknown[]) => {\n const path = unbound(args[0] as string);\n const indexes = (args[1] ?? []) as number[];\n const p = this.pattern(path, true);\n this.checkArity(\"$resolve\", path, p, indexes, true);\n const row = this.rowOf(p, indexes, null);\n if (args.length < 3) return this.read(p, row);\n this.write(p, row, args[2]);\n },\n $postUpdate: (path: string) => {\n this.resolve(unbound(path), this.ctx);\n const p = this.rp!;\n const row = this.rr;\n // changed in place: an element is what its array holds now\n if (p.last === WILDCARD && row !== null) {\n row.item = row.list.arr![row.index];\n twice.delete(row.list.arr!);\n this.strategy.resetRow(row);\n }\n this.touched(p, row);\n if (row !== null) this.mirror(row, p, undefined, row.item, false);\n // the value before is not known: the `$eq` / `$eqIndex` occurrences under every key change\n if (p.depth === 0) this.rekeyEqUnder(p, undefined, undefined, true);\n this.landed(p, row, undefined, undefined, false);\n },\n };\n\n constructor(target: Record<string, any>, strategy: Strategy) {\n this.strategy = strategy;\n this.patterns = new PatternTable((p) => {\n this.loose.push(p);\n this.onPatternCreated(p);\n });\n this.loadTarget(target);\n const engine = this;\n // the handler reads engine.target, not the proxy's target (a stand-in): a re-set swaps the state.\n // So do `in`, `delete`, `Object.keys(this)`, `instanceof` (the forwarded traps below); a descriptor\n // is reported configurable, as the stand-in has none (a frozen state's would break the invariants)\n const handler: ProxyHandler<object> = {\n getOwnPropertyDescriptor(_t, key) {\n const d = Reflect.getOwnPropertyDescriptor(engine.target, key);\n if (d) d.configurable = true;\n return d;\n },\n get(_t, key, receiver) {\n const t = engine.target;\n if (typeof key === \"symbol\") return Reflect.get(t, key);\n if (key.charCodeAt(0) === 36 /* $ */) return engine.dollar(key);\n if (key.indexOf(\".\") < 0) {\n const p = engine.patterns.peek(key);\n if (p === undefined || p.getter === null) {\n const v = t[key];\n // (a view of the proxy — the readonly createStateAsync's — gets it as it is)\n if (typeof v === \"function\") return (receiver === engine.proxy && engine.bound?.(v)) || v;\n }\n // a known top-level key: no path to parse\n if (p !== undefined && p.depth === 0) return engine.read(p, null);\n }\n engine.resolve(key, engine.ctx);\n return engine.read(engine.rp!, engine.rr);\n },\n set(_t, key, value) {\n if (typeof key === \"symbol\") return Reflect.set(engine.target, key, value);\n engine.resolve(unbound(key), engine.ctx);\n engine.write(engine.rp!, engine.rr, value);\n return true;\n },\n };\n for (const trap of [\"has\", \"ownKeys\", \"deleteProperty\", \"defineProperty\", \"getPrototypeOf\"]) {\n (handler as any)[trap] = (_t: object, ...a: unknown[]) => (Reflect as any)[trap](engine.target, ...a);\n }\n this.proxy = new Proxy({}, handler);\n }\n\n // ---------------------------------------------------------------- patterns\n\n /**\n * The pattern of `path`, pinned: whoever asks keeps it (a binding, a list, an add-on). `loose`: a\n * path read or written (the proxy, `$resolve`, `$getAll`), swept once it holds nothing.\n */\n pattern(path: string, loose?: boolean): Pattern {\n const p = this.patterns.get(path);\n if (!loose) p.pinned = true;\n return p;\n }\n\n private registerAccessors(target: object): void {\n const seen = new Set<string>();\n for (let o: object | null = target; o !== null && o !== Object.prototype; o = Object.getPrototypeOf(o)) {\n for (const key of Object.getOwnPropertyNames(o)) {\n if (seen.has(key)) continue;\n seen.add(key);\n const d = Object.getOwnPropertyDescriptor(o, key)!;\n if (d.get === undefined && d.set === undefined) continue;\n const p = this.pattern(key);\n p.getter = d.get ?? null;\n p.setter = d.set ?? null;\n if (p.getter !== null && p.depth > 0) p.slot = this.slotCount++;\n }\n }\n // accessors registered after their descendants were created: recompute\n for (const p of this.patterns.all()) this.onPatternCreated(p);\n }\n\n private onPatternCreated(p: Pattern): void {\n // (the recursion add-on makes its `**` templates without this, while the state registers)\n if (p.path.includes(\"**\")) recursionUnsupported(p.path);\n // a path through an object's prototype would read and write every object's (once per path)\n if (p.last === \"__proto__\" || p.last === \"prototype\") raise(M.UnsafeSegment, [p.path]);\n const parent = p.parent;\n p.underGetter = parent !== null && p.last !== WILDCARD && parent.depth === p.depth &&\n (parent.getter !== null || parent.underGetter);\n if (p.getter === null) this.markupAccessor(p);\n }\n\n /**\n * Markup names two things the tree does not hold, as `this[...]` reads them: an explicit index\n * (`items.0.v`, the row at that index now) and a loop index (`items.*.$1`, `$1` in a row).\n * Their patterns (only markup makes them: the proxy parses an index into a row) read — and an\n * index path writes — as the proxy resolves them, so the reads are tracked like a getter's.\n * Where a number is a key of an object (`sales.2024.total`), the path resolves to the pattern\n * itself (rowOf): it is read and written through its parent.\n */\n private markupAccessor(p: Pattern): void {\n const path = p.path;\n const last = p.last;\n if (INDEX_PARAM.test(last)) {\n p.getter = function (this: any) {\n return this[last];\n };\n } else {\n const segs = path.split(\".\");\n // (a leading numeric segment is a root key, not an index: parsePath)\n const i = segs.findIndex((s, j) => j > 0 && s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57);\n // none, or a `*` after it: a row of a list over the index path (`for: groups.0.items`) reads its\n // own item, and a write through the index reaches it as a list with the same array (mirror)\n if (i < 0 || segs.indexOf(WILDCARD, i) >= 0) return;\n // (the parent read from the context row: the occurrence's, the setter's — at p.depth)\n p.getter = () => {\n this.resolve(path, this.ctx);\n if (this.rp !== p) return this.read(this.rp!, this.rr);\n return (this.read(p.parent!, this.ctx) as any)?.[last];\n };\n p.setter = (v: unknown) => {\n this.resolve(path, this.ctx);\n if (this.rp !== p) return this.write(this.rp!, this.rr, v);\n const o = this.read(p.parent!, this.ctx) as any;\n if (o == null) raise(M.ParentNotObject, [path, o]);\n o[last] = v;\n };\n }\n p.markup = true;\n if (p.depth > 0) p.slot = this.slotCount++;\n }\n\n // ---------------------------------------------------------------- lists\n\n /** The list of list pattern `p` in `row` (null: a root list), made on first use, synced. */\n childList(row: StateRow | null, p: Pattern): StateList {\n const m = row === null ? this.rootLists : (row.children ??= new Map());\n let l = m.get(p);\n if (l === undefined) m.set(p, (l = new StateList(p, row)));\n // (the list holds it: a path's read made it loose, `users.3.name` through `users`)\n p.pinned = true;\n this.sync(l);\n return l;\n }\n\n /** Syncs `l`; a failure (a missing key, a getter that throws) is its for binding's, and it keeps its rows. */\n private trySync(l: StateList): void {\n try {\n this.sync(l);\n } catch (error) {\n this.failAt(error, l.pattern.path, l.view?.anchor ?? null, \"for\");\n }\n }\n\n /** Reconciles a list's rows with the current value of its pattern. */\n sync(l: StateList): void {\n const value = this.readUntracked(l.pattern, l.parentRow);\n const before = l.arr;\n if (value === before) return;\n // out of the lists over its array before (filed again under the new one below)\n this.unfile(l);\n const old = reconcile(l, value, this);\n if (old === null) return;\n // filed under its array: lists that share an array mirror writes\n // (a value that is not an array reconciles against a stand-in: nothing to share)\n if (l.arr === value) {\n const same = upsert(this.listsByArray, value as unknown[], newArray<StateList>);\n same.push(l);\n // (the rows it kept are up to date: a write into an object reached every list showing it, F26)\n if (same.length > 1) for (const x of same) x.shared = true;\n }\n hooks.listSynced?.(this, l, old);\n if ((l.view !== null || l.extra !== null) && !l.queued) {\n l.queued = true;\n this.dirtyLists.push(l);\n this.schedule();\n }\n const keys = l.pattern.eqIndexKeys;\n if (keys !== null) {\n for (const { source, getter } of keys) {\n const sel = this.readUntracked(source, null) as number;\n const before = old[sel];\n const after = l.rows[sel];\n if (before === after) continue;\n if (before !== undefined && before.alive) this.invalidateUnder(getter, before);\n if (after !== undefined) this.invalidateUnder(getter, after);\n }\n }\n }\n\n indexChanged(row: StateRow): void {\n this.strategy.onIndexChange(this, row);\n }\n\n rowRemoved(row: StateRow): void {\n row.alive = false;\n const subs = row.eqSubs;\n if (subs !== null) {\n for (const e of subs) unsubEq(e.source, e.key, e.sub);\n row.eqSubs = null;\n }\n // the rows of its nested lists go with it, and the lists leave the ledger of their arrays\n if (row.children !== null) {\n for (const l of row.children.values()) {\n this.unfile(l);\n for (const r of l.rows) this.rowRemoved(r);\n }\n }\n }\n\n /** Takes `l` out of the lists over its array; one left alone with it no longer mirrors. */\n private unfile(l: StateList): void {\n const was = this.listsByArray.get(l.arr!);\n if (was === undefined) return;\n was.splice(was.indexOf(l) >>> 0, 1);\n l.shared = false;\n if (was.length === 1) was[0].shared = false;\n }\n\n // ---------------------------------------------------------------- resolve / read\n\n /** Splits a concrete path into (pattern, row) — written to this.rp / this.rr. */\n resolve(path: string, ctx: StateRow | null): void {\n const parsed = parsePath(path);\n const p = (this.rp = this.pattern(parsed.pattern, true));\n const idx = parsed.indexes;\n this.rr = p.depth === 0 ? null : idx === null ? ctxRow(ctx, p, p.depth) : this.rowOf(p, idx, ctx, path);\n }\n\n /**\n * The row at p.depth addressed by `idx` (one index per `*`; -1 takes the one of `ctx`). The pattern\n * it is at goes to this.rp — set last: finding the row can sync a list over a getter, whose\n * evaluation resolves paths too. An index of `path` (the proxy's) into an object that is not an\n * array (`sales.2024.total`) is a key: the pattern keeps it as written (into null or a string, it\n * has no row).\n */\n private rowOf(p: Pattern, idx: readonly number[], ctx: StateRow | null, path?: string): StateRow | null {\n let row: StateRow | null = null;\n for (let k = 1, j = 0, v; k <= p.depth; k++) {\n const listP = p.lists[k]!;\n const list = this.childList(row, listP);\n let i = idx[j++];\n if (i < 0) i = ctxRow(ctx, p, k)?.index ?? -1;\n else if (path && list.arr === EMPTY && Object((v = this.readUntracked(listP, row))) === v) {\n const segs = p.path.split(\".\");\n const n = listP.path.split(\".\").length;\n segs[n] = path.split(\".\")[n];\n p = this.pattern(segs.join(\".\"), true);\n k--;\n continue;\n }\n row = list.rows[i] ?? null;\n if (row === null) break;\n }\n this.rp = p;\n return row;\n }\n\n /** Raw data read (no getter, no tracking). `row` is the row at p.depth. */\n readData(p: Pattern, row: StateRow | null): unknown {\n return p.depth === 0 ? dig(this.target, p.tail) : row === null ? undefined : dig(row.item, p.tail);\n }\n\n /** Tracked read. `row` is the row at p.depth (null at the root). */\n read(p: Pattern, row: StateRow | null): unknown {\n const f = this.top;\n if (f !== null && f.untracked === 0) this.track(p, row, f);\n if (p.getter !== null) return this.strategy.readGetter(this, p, row);\n if (p.underGetter) {\n const parent = this.read(p.parent!, row) as any;\n return parent == null ? undefined : parent[p.last];\n }\n // (`then` / `toJSON` are probes — await, JSON.stringify — not reads of the state: undefined)\n if (p.parent === null && !(p.last in this.target) && !this.dropped.has(p.last) && p.last !== \"then\" && p.last !== \"toJSON\") {\n raise(M.PathMissing, [p.path], p.last, Object.keys(this.target));\n }\n return this.readData(p, row);\n }\n\n readUntracked(p: Pattern, row: StateRow | null): unknown {\n const f = this.top;\n if (f === null) return this.read(p, row);\n f.untracked++;\n try {\n return this.read(p, row);\n } finally {\n f.untracked--;\n }\n }\n\n private track(p: Pattern, row: StateRow | null, f: Frame): void {\n const g = f.getter;\n p.addDependent(g);\n // a root getter's reads (once each, but around a nested one): what it no longer reads goes (prune)\n if (g.depth === 0) {\n if (p.mark !== f.epoch) {\n p.mark = f.epoch;\n f.reads.push(p);\n }\n } else if (p.depth > 0 && rowAt(row, Math.min(p.depth, g.depth)) !== rowAt(f.row, Math.min(p.depth, g.depth))) {\n (g.crossSources ?? (g.crossSources = new Set())).add(p);\n }\n }\n\n /** Evaluates a getter occurrence with dependency tracking. Caching is the strategy's. */\n evalGetter(g: Pattern, row: StateRow | null): unknown {\n // frames are reused by depth: an evaluation allocates nothing of its own\n for (let i = 0; i < this.depthNow; i++) {\n const f = this.frames[i];\n if (f.getter === g && f.row === row) raise(M.GetterCycle, [g.path]);\n }\n if (this.depthNow >= MAX_GETTER_DEPTH) raise(M.GetterDepth, [g.path]);\n const depth = this.depthNow++;\n this.readonlyDepth++;\n const frame = (this.frames[depth] ??= { getter: g, row, untracked: 0, epoch: 0, reads: [] });\n frame.getter = g;\n frame.row = row;\n frame.untracked = 0;\n frame.epoch = ++evals;\n frame.reads.length = 0;\n const outer = this.top;\n this.top = frame;\n const prev = this.ctx;\n this.ctx = row;\n try {\n const v = g.getter!.call(this.proxy);\n if (g.depth === 0) this.prune(g, frame);\n return v;\n } finally {\n this.readonlyDepth--;\n this.depthNow--;\n this.top = outer;\n this.ctx = prev;\n frame.row = null;\n }\n }\n\n /**\n * A root getter evaluated (without throwing): the top-level sources it did not read this time are no\n * longer its sources. Its one occurrence is the whole getter, so what it reads is what it depends on\n * (a row getter's sources stay the union over its rows). A key built from data it read before\n * (`this[\"users.\" + this.selectedId]`) then holds nothing, and is swept. One holding an array stays:\n * a write into an object that array shares with the one the getter returns reaches the rows of the\n * list over the getter through it (mirror — F26, 3.x #362).\n */\n private prune(g: Pattern, f: Frame): void {\n const e = f.epoch;\n for (const s of f.reads) s.mark = e;\n g.sources = g.sources.filter((s) => s.mark === e || s.depth > 0 ||\n (!s.underGetter && Array.isArray(s.getter !== null ? s.rootValue : this.readData(s, null))) || this.unlink(s, g));\n }\n\n /** `getter` reads `s` no more (its side is the caller's): `s` may hold nothing now. False (filtered out). */\n private unlink(s: Pattern, getter: Pattern): false {\n s.dropDependent(getter);\n this.loose.push(s);\n return false;\n }\n\n /**\n * After a drain: the patterns only a path made that hold nothing now leave the table, so it grows\n * with the state's shape, not with every key a path was ever built with. A pattern stays while it\n * is pinned (Engine.pattern: `$eqIndex`'s source among them), at the top level (the state's own\n * keys), has children, is read by a getter, is `$eq`'s source, or has an accessor that is not the\n * engine's own for an index path at the top level (one in a row has a cache slot).\n */\n private sweep(): void {\n for (let c = this.loose; c.length > 0; c = this.loose) {\n this.loose = [];\n const parents = new Set<Pattern>();\n for (const p of c) {\n if (p.pinned || p.dead || p.parent === null || p.children.length > 0 || p.dependents.length > 0 ||\n (p.getter !== null && !(p.markup && p.slot < 0)) || p.eqSubs !== null) continue;\n p.dead = true;\n this.patterns.drop(p);\n parents.add(p.parent);\n // an index path's accessor read its parent\n for (const s of p.sources) this.unlink(s, p);\n }\n for (const q of parents) if (!(q.children = q.children.filter((x) => !x.dead)).length) this.loose.push(q);\n }\n }\n\n /** The getter evaluating now reads the index of its row at level `n`: a move of that row re-evaluates it. */\n private watchIndex(n: number): void {\n const f = this.top;\n if (f !== null && f.untracked === 0) {\n const g = f.getter;\n const listP = g.lists[n];\n if (listP) {\n const w = listP.indexWatchers ?? (listP.indexWatchers = []);\n if (!w.includes(g)) w.push(g);\n }\n }\n }\n\n private dollar(key: string): unknown {\n const c = key.charCodeAt(1);\n if (c >= 48 && c <= 57) {\n const n = key.length === 2 ? c - 48 : INDEX_PARAM.test(key) ? +key.slice(1) : 0;\n if (n < 1 || n > MAX_INDEX_PARAM) {\n raise(M.IndexParamRange, [key]);\n }\n this.watchIndex(n);\n return rowAt(this.ctx, n)?.index;\n }\n const fn = this.api[key];\n if (fn !== undefined) return fn;\n // (the 3.x names 4.0 removed, $trackDependency and $untrackDependency, are the diagnostics add-on's)\n switch (key) {\n case \"$stateElement\":\n return this.element;\n case \"$command\":\n return this.commands;\n }\n return hooks.dollar?.(this, key);\n }\n\n /**\n * `$eq(path, key)`: is the value of `path` equal to `key`? Inside a getter the occurrence\n * subscribes under `key` instead of depending on `path`: a write to `path` re-evaluates\n * only the occurrences keyed under its old and its new value. A `path` that is a getter\n * (or under one) changes without a write, so it falls back to an ordinary tracked read.\n */\n private eq(path: string, key: unknown): boolean {\n this.resolve(path, this.ctx);\n const source = this.rp!;\n const row = this.rr;\n if (source.getter !== null || source.underGetter || source.depth > 0) return sameValueZero(this.read(source, row), key);\n const f = this.top;\n if (f !== null && f.untracked === 0) this.subscribeEq(source, key, f);\n return sameValueZero(this.readUntracked(source, null), key);\n }\n\n /**\n * Subscribes the occurrence evaluating in `f` under `key`. A key it subscribed in an earlier\n * evaluation and not in this one moved; one of this evaluation stays (`$eq(p, a) || $eq(p, b)`).\n */\n private subscribeEq(source: Pattern, key: unknown, f: Frame): void {\n const getter = f.getter;\n const row = f.row;\n const list = row === null ? this.rootEqSubs : (row.eqSubs ?? (row.eqSubs = []));\n for (let i = 0; i < list.length; i++) {\n const e = list[i];\n if (e.sub.getter !== getter || e.source !== source) continue;\n if (sameValueZero(e.key, key)) {\n e.epoch = f.epoch;\n return;\n }\n if (e.epoch !== f.epoch) {\n unsubEq(source, e.key, e.sub);\n list.splice(i--, 1);\n }\n }\n const sub: EqSub = { getter, row };\n upsert((source.eqSubs ??= new Map()), key, newSet<EqSub>).add(sub);\n list.push({ source, key, sub, epoch: f.epoch });\n }\n\n /**\n * A root write to `p` (or an object above a `$eq` / `$eqIndex` source): re-key every source at or\n * under it. `all` (`$postUpdate`, which knows no value before): every key.\n */\n private rekeyEqUnder(p: Pattern, before: unknown, after: unknown, all?: boolean): void {\n this.forSubtree(p, (q) => {\n const map = q.eqSubs;\n if (map === null && q.eqIndexWatchers === null) return;\n const rest = q === p ? [] : q.path.slice(p.path.length + 1).split(\".\");\n const b = dig(before, rest);\n const a = dig(after, rest);\n if (q.eqIndexWatchers !== null) this.rekeyEqIndex(q, b, a, all);\n // the occurrences keyed under the value before and the value after\n if (map !== null) for (const k of all ? map.keys() : [b, a]) {\n const set = map.get(k);\n if (set === undefined) continue;\n for (const sub of set) {\n if (sub.row !== null && !sub.row.alive) {\n unsubEq(q, k, sub);\n continue;\n }\n this.strategy.invalidate(this, sub.getter, sub.row);\n }\n }\n });\n }\n\n // ---------------------------------------------------------------- write\n\n /**\n * `occurrence`: an event-semantics write, applied even when equal to the current value.\n * `element`: an element wrote it back (a two-way input, a wc-bindable event), not code.\n */\n write(p: Pattern, row: StateRow | null, value: unknown, occurrence = false, element = false): void {\n if (this.readonlyDepth > 0) raise(M.Readonly);\n if (element || this.feeding > 0) this.fedBack = true;\n else this.codeWrote = true;\n if (hooks.beforeWrite?.(this, p, row, value, element)) return;\n // a setter's write is not a data write: the add-ons hear of it without old and new values\n if (p.setter !== null) {\n // a setter that throws after it wrote: what it wrote still lands (3.x #361), and the error\n // propagates. One that throws before writing anything lands as well, as one that returns\n // without writing does (3.x notifies in `finally` too): `$watch` hears of it, a getter recomputes\n try {\n this.callAt(p.setter, row, [value]);\n } finally {\n this.landed(p, row, undefined, undefined, false, element);\n }\n return;\n }\n if (p.getter !== null) raise(M.GetterWithoutSetter, [p.path]);\n if (p.depth > 0 && row === null) raise(M.NoRow, [p.path]);\n // under a getter, the value before is read through it (the data has no such path)\n const old = p.underGetter ? this.readUntracked(p, row) : this.readData(p, row);\n if (!occurrence && this.guard && Object.is(old, value) && Object(value) !== value) return;\n if (p.last === WILDCARD) {\n // element write: the position keeps its row, the row takes the new value\n const r = row!;\n (r.list.arr as unknown[])[r.index] = value;\n twice.delete(r.list.arr!);\n r.item = value;\n this.strategy.resetRow(r);\n } else {\n const parent = (p.tail.length === 1\n ? (p.depth === 0 ? this.target : row!.item)\n : this.readUntracked(p.parent!, row)) as any;\n if (parent == null) raise(M.ParentNotObject, [p.path, parent]);\n parent[p.last] = value;\n }\n this.syncListsUnder(p, row);\n if (row !== null) this.mirror(row, p, old, value);\n if (p.depth === 0) this.rekeyEqUnder(p, old, value);\n this.landed(p, row, old, value, true, element);\n }\n\n /** The lists over `l`'s array now (`l` among them), none of a removed row. */\n private sharing(l: StateList): StateList[] {\n return (this.listsByArray.get(l.arr!) ?? []).filter((m) => m.arr === l.arr && (m.parentRow === null || m.parentRow.alive));\n }\n\n /**\n * A write into row `row` of a list whose array another list has too (`for: shown` over a getter\n * returning `todos`, `for: groups.0.items`): the other list's row at the same position shows it.\n *\n * A write into the row's object (not the element) reaches it wherever else it is (F26, `get\n * shown()` filtering `todos`). From the array holding it (the list's own, or one its getter read\n * at a data path), the write goes to the getters that read that array and returned one holding the\n * object (a filter, a sort, a slice: evaluated again), on down their dependents, and to the rows\n * holding the object in the lists over those arrays. A getter whose array does not hold the object\n * is not reached: it read the array, not the object (the dependency boundary).\n */\n private mirror(row: StateRow, p: Pattern, old: unknown, value: unknown, direct = true): void {\n const l = row.list;\n const suffix = p.path.slice(l.pattern.path.length + 2);\n // a write into the row's object, which its array holds at another position too (F26): those rows show it\n const dup = suffix !== \"\" && holdsTwice(l.arr!);\n // another list has its array, or it is over a getter or a getter reads it: its object may be in\n // another array too. A plain list pays these checks only\n if (!dup && !l.shared && l.pattern.getter === null && !l.pattern.dependents.length) return;\n const o = row.item;\n const land = (m: StateList, r: StateRow | undefined): void => {\n if (r === undefined || r === row) return;\n const mp = this.pattern(`${m.pattern.path}.*${suffix}`, true);\n if (suffix === \"\") {\n r.item = value;\n this.strategy.resetRow(r);\n }\n if (direct) this.syncListsUnder(mp, r);\n else this.touched(mp, r);\n this.landed(mp, r, old, value, direct);\n };\n for (const m of this.sharing(l)) {\n land(m, m.rows[row.index]);\n if (dup) for (const r of m.rows) if (r.item === o && r.index !== row.index) land(m, r);\n }\n if (suffix === \"\") return;\n // (a leaf write: the row's item is an object. The lists over its own array were reached above)\n const seen = new Set<unknown>([l.arr]);\n const has = (a: unknown): a is unknown[] => Array.isArray(a) && a.includes(o);\n const down = (arr: unknown, deps: Pattern[]): void => {\n if (!seen.has(arr) && seen.add(arr)) for (const m of this.listsByArray.get(arr as unknown[]) ?? []) for (const r of m.rows) if (r.item === o) land(m, r);\n // each getter once (a cycle across evaluations ends). One passing the array on (`get shown()\n // { return this.todos }`) is not evaluated again: the lists over it were reached already. One\n // reached before (earlier in the batch, or just now through a getter it reads) is evaluated again\n // in the drain, its list synced then: the rows it keeps are those its list shows now\n for (const g of deps) {\n let v = g.rootValue;\n const stale = v === DIRTY;\n if (stale) v = this.rootLists.get(g)?.arr;\n if ((stale || has(v)) && !seen.has(g.dependents) && seen.add(g.dependents)) {\n if (!stale && v !== arr) this.strategy.invalidate(this, g, null);\n down(v, g.dependents);\n }\n }\n };\n const up = (g: Pattern): void => {\n for (const s of g.sources) {\n if (seen.has(s) || !seen.add(s)) continue;\n if (s.getter !== null) up(s);\n else if (!s.underGetter) {\n const a = this.readData(s, null);\n if (has(a)) down(a, s.dependents);\n }\n }\n };\n if (l.pattern.getter !== null) up(l.pattern);\n else down(l.arr!, l.pattern.dependents);\n }\n\n /**\n * `$postUpdate`: what is at `p` changed in place. Its lists are synced as a write syncs them, and\n * their rows (and the rows of the lists over the same arrays) show it again: a write reaches a\n * row's bindings through the row it replaced, an in-place change through none.\n */\n private touched(p: Pattern, row: StateRow | null): void {\n this.forListsUnder(p, row, (l) => {\n this.sync(l);\n for (const m of l.shared ? this.sharing(l) : [l]) {\n const e = this.pattern(`${m.pattern.path}.*`);\n for (const r of m.rows) {\n this.enqueueBound(e, r);\n this.touched(e, r);\n }\n }\n });\n }\n\n private syncListsUnder(p: Pattern, row: StateRow | null): void {\n const ls = row === null ? this.rootLists : row.children;\n if (ls !== null) for (const l of ls.values()) if (l.pattern.isUnder(p)) this.sync(l);\n }\n\n /** The lists of `row` (the root lists at null) whose pattern is `p` or under it. */\n private forListsUnder(p: Pattern, row: StateRow | null, fn: (l: StateList) => void): void {\n const ls = row === null ? this.rootLists : row.children;\n if (ls !== null) for (const l of ls.values()) if (l.pattern.isUnder(p)) fn(l);\n }\n\n /**\n * `$eqIndex(source, level)` compares the index of the row at `level`: when `source` changes, the\n * getter's occurrences under the rows at that level with the old or the new index change (`all`:\n * under every row).\n */\n private rekeyEqIndex(source: Pattern, before: unknown, after: unknown, all?: boolean): void {\n for (const { getter, level } of source.eqIndexWatchers!) {\n this.forAllLists(getter.lists[level]!, (l) => {\n for (const k of all ? l.rows.keys() : [before, after]) {\n const r = typeof k === \"number\" ? l.rows[k] : undefined;\n if (r !== undefined) this.invalidateUnder(getter, r);\n }\n });\n }\n }\n\n /** Invalidates getter `g`'s occurrences at or under `row` (row.depth <= g.depth). */\n private invalidateUnder(g: Pattern, row: StateRow): void {\n if (row.list.depth === g.depth) this.strategy.invalidate(this, g, row);\n else this.forRowsUnder(row, g, (r) => this.strategy.invalidate(this, g, r));\n }\n\n /** A write landed at (p, row): the add-ons hear of it, then its dependents. */\n private landed(p: Pattern, row: StateRow | null, old: unknown, value: unknown, direct: boolean, element?: boolean): void {\n hooks.written?.(this, p, row, old, value, direct, element);\n this.changed(p, row);\n }\n\n changed(p: Pattern, row: StateRow | null): void {\n this.strategy.onWrite(this, p, row);\n this.schedule();\n }\n\n /**\n * One listener per event type on the root, dispatching to the delegated element handlers.\n * Returns the property the element's handler is stored under (one symbol per engine and\n * type, so two engines never run each other's handlers).\n */\n delegate(type: string): symbol {\n const known = this.delegated.get(type);\n if (known !== undefined) return known;\n const key = Symbol(`wcs.on${type}`);\n this.delegated.set(type, key);\n const root = this.root!;\n const blockKey = this.blockKey;\n root.addEventListener(type, (e) => {\n for (let n = e.target as any; n !== null && n !== root; n = n.parentNode) {\n // a handler stored on the element (a root-level one, or one a block pinned)\n const fn = n[key];\n if (fn !== undefined) {\n fn(e);\n if (e.cancelBubble) return;\n }\n // a block's top node: the handlers of the block's elements the event passed\n const block = n[blockKey];\n if (block !== undefined && block.alive && block.dispatch(type, e)) return;\n }\n });\n return key;\n }\n\n // ---------------------------------------------------------------- re-set\n\n /**\n * `setInitialState` on an initialized element: the state is replaced whole and every\n * binding is re-applied to it before this returns. Not a write: no `$renderedCallback`.\n * Everything learned from the old state goes (accessors, dependencies, caches, `$eq`\n * keys); rows are kept where their list's array is the same instance.\n */\n reset(target: Record<string, any>): void {\n const old = this.target;\n // a key the old state had (or an earlier re-set dropped) and this one lacks is empty (B8), as a\n // missing path under a key is — not a key never declared, which fails on read: its bindings, lists\n // and getters read undefined, until it is written. Its accessors too: those on a class state's\n // prototype, which for…in does not list, are the top-level patterns with a getter\n const dropped = this.dropped;\n for (const p of this.patterns.all()) if (p.parent === null && p.getter !== null) dropped.add(p.last);\n this.loadTarget(target);\n for (const k in old) if (k[0] !== \"$\") dropped.add(k);\n for (const k of dropped) if (k in target) dropped.delete(k);\n for (const bs of this.rootBindings.values()) for (const b of bs) this.enqueue(b);\n for (const l of this.rootLists.values()) this.resetList(l);\n this.rendered = null;\n try {\n this.drain();\n } finally {\n this.watchRendered();\n }\n hooks.element?.(this, \"reset\");\n }\n\n /** Takes in a state object: at construction, and on a re-set (everything learned from the old one goes). */\n private loadTarget(target: Record<string, any>): void {\n for (const [key, feature] of DECLARATIONS) if (target[key] !== undefined) requireFeature(feature, key);\n // (the 3.x declarations 4.0 removed — $scan, $streams, $updatedCallback — are the diagnostics add-on's)\n const f = target.$features;\n if (f !== undefined) {\n if (!Array.isArray(f)) raise(M.FeaturesNotArray);\n for (const name of f) requireFeature(name, \"$features\");\n }\n // an options object: null and an array are not one (as for bootstrapState's options)\n const c = target.$behavior === undefined ? {} : target.$behavior;\n if (typeof c !== \"object\" || !c || Array.isArray(c)) raise(M.OptionInvalid, [\"state\", \"$behavior\"]);\n for (const key in c) if (!BEHAVIOR_KEYS.includes(key) || typeof c[key] !== \"boolean\") raise(M.OptionInvalid, [\"$behavior\", key]);\n const [mustache, guard, directional] = BEHAVIOR_KEYS.map((key) => c[key] ?? true);\n // a re-set keeps the engine, and what was built by the old options\n if (this.target !== undefined && (mustache !== this.mustache || guard !== this.guard || directional !== this.directional)) raise(M.BehaviorChanged);\n // (read before anything is taken in: a malformed declaration leaves a re-set's old state in place)\n const commands = commandNamespace(target, this.commands);\n const events = eventTokens(target, this.deliverFn);\n this.mustache = mustache;\n this.guard = guard;\n this.directional = directional;\n hooks.declare?.(this, target);\n this.target = target;\n this.slotCount = 0;\n for (const p of this.patterns.all()) p.forget();\n this.rootEqSubs.length = 0;\n this.registerAccessors(target);\n this.commands = commands;\n this.events = events;\n }\n\n private resetList(l: StateList): void {\n // a list that cannot be read (its getter throws) fails alone: the re-set goes on (and ends with its hook)\n this.trySync(l);\n const element = this.pattern(`${l.pattern.path}.*`);\n for (const row of l.rows) {\n row.cache = null;\n row.eqSubs = null;\n this.enqueueBound(element, row);\n if (row.children !== null) for (const c of row.children.values()) this.resetList(c);\n }\n }\n\n // ---------------------------------------------------------------- tokens\n\n /** The loop indexes of `row`, outermost first (`$1`, `$2`, …). */\n indexesOf(row: StateRow | null): number[] {\n const out: number[] = [];\n for (let r = row; r !== null; r = r.list.parentRow) out.unshift(r.index);\n return out;\n }\n\n /** An element event wired with `eventToken.<prop>: <name>` — the token is resolved at fire time. */\n fireEventToken(name: string, event: Event, row: StateRow | null): void {\n const token = this.events.get(name);\n if (token === undefined) raise(M.EventTokenUndeclared, [name], name, this.events.keys());\n token.emit(event, ...this.indexesOf(row));\n }\n\n /** The `$command.<name>` token (declared in `$commandTokens`). */\n command(name: string): Token {\n const token = this.commands[name];\n if (token === undefined) raise(M.CommandTokenUndeclared, [name], name, Object.keys(this.commands));\n return token;\n }\n\n /** `onclick: $command.<name>` — emits the token with (event, ...listIndexes). */\n emitCommand(name: string, event: Event, row: StateRow | null): void {\n this.command(name).emit(event, ...this.indexesOf(row));\n }\n\n // ---------------------------------------------------------------- methods\n\n invoke(name: string, event: Event, row: StateRow | null): unknown {\n // a dotted name is a path (a volume method lives under its mount path)\n const fn = name.includes(\".\") ? this.readUntracked(this.pattern(name), null) : this.target[name];\n if (typeof fn !== \"function\") raise(M.NotAMethod, [name]);\n return this.callAt(fn, row, [event, ...this.indexesOf(row)]);\n }\n\n /** Calls `fn` on the proxy with the evaluation context at `row`. */\n private callAt(fn: (...args: any[]) => unknown, row: StateRow | null, args: unknown[]): unknown {\n const prev = this.ctx;\n this.ctx = row;\n try {\n return fn.apply(this.proxy, args);\n } finally {\n this.ctx = prev;\n }\n }\n\n // ---------------------------------------------------------------- change walk\n\n /** Queues the bindings on `p` (and patterns under it) in the scope of `row`. */\n enqueueBound(p: Pattern, row: StateRow | null): void {\n // a list over a getter (or under one) is re-synced in the drain: a data write syncs its\n // lists right away, but a getter's value is only known when it is read again\n if (p.getter !== null) {\n const ls = row === null ? this.rootLists : row.children;\n if (ls !== null) {\n for (const l of ls.values()) {\n if (!l.stale && l.pattern.isUnder(p)) {\n l.stale = true;\n this.staleLists.push(l);\n }\n }\n }\n }\n if (row === null) {\n this.forSubtree(p, (q) => {\n const bs = this.rootBindings.get(q);\n if (bs !== undefined) for (const b of bs) this.enqueue(b);\n });\n return;\n }\n const bs = row.bindings;\n if (bs !== null) for (let i = 0; i < bs.length; i++) if (bs[i].pattern.isUnder(p)) this.enqueue(bs[i]);\n // slot bindings of the row's renderings\n const view = row.view;\n if (view !== null && view.slots !== null) view.enqueueSlots(this, p);\n const extra = row.list.extra;\n if (extra !== null) {\n for (const fv of extra) {\n const rv = fv.map!.get(row);\n if (rv !== undefined && rv.slots !== null) rv.enqueueSlots(this, p);\n }\n }\n }\n\n /** Reaches every getter occurrence that read `p` (or a pattern under it) at `row`. */\n walkDependents(p: Pattern, row: StateRow | null, visit: Visit): void {\n this.forSubtree(p, (q) => {\n const deps = q.dependents;\n for (let i = 0; i < deps.length; i++) {\n const g = deps[i];\n if (g.depth === 0) this.visitGetter(g, null, visit);\n else if (row === null || q.depth === 0 || g.lists[1] !== q.lists[1] || (g.crossSources !== null && g.crossSources.has(q))) {\n this.forAllRows(g.lists[g.depth]!, (r) => this.visitGetter(g, r, visit));\n } else if (g.depth <= q.depth) {\n const r = rowAt(row, g.depth);\n if (r !== null) this.visitGetter(g, r, visit);\n } else this.forRowsUnder(row, g, (r) => this.visitGetter(g, r, visit));\n }\n });\n }\n\n visitGetter(g: Pattern, row: StateRow | null, visit: Visit): void {\n if (!visit(g, row)) return;\n hooks.getterReached?.(this, g, row);\n this.enqueueBound(g, row);\n this.walkDependents(g, row, visit);\n }\n\n forSubtree(p: Pattern, fn: (q: Pattern) => void): void {\n fn(p);\n const c = p.children;\n for (let i = 0; i < c.length; i++) this.forSubtree(c[i], fn);\n }\n\n /** Every row of every list instance of list pattern `listP`. */\n forAllRows(listP: Pattern, fn: (row: StateRow) => void): void {\n this.forAllLists(listP, (l) => {\n for (const r of l.rows) fn(r);\n });\n }\n\n /** Every list instance of list pattern `listP`. */\n private forAllLists(listP: Pattern, fn: (l: StateList) => void): void {\n if (listP.depth === 0) {\n const l = this.rootLists.get(listP);\n if (l !== undefined) fn(l);\n return;\n }\n this.forAllRows(listP.lists[listP.depth]!, (parent) => {\n const l = parent.children?.get(listP);\n if (l !== undefined) fn(l);\n });\n }\n\n /** Rows at g.depth at or under `row` (row.depth <= g.depth). */\n forRowsUnder(row: StateRow, g: Pattern, fn: (row: StateRow) => void): void {\n if (row.list.depth === g.depth) return fn(row);\n const l = row.children?.get(g.lists[row.list.depth + 1]!);\n if (l !== undefined) for (const r of l.rows) this.forRowsUnder(r, g, fn);\n }\n\n // ---------------------------------------------------------------- bindings & drain\n\n /** Registers a binding where a change of its location finds it: its row, or the root table. */\n register(b: Binding): void {\n const row = b.row;\n if (row !== null) {\n (row.bindings ?? (row.bindings = [])).push(b);\n return;\n }\n upsert(this.rootBindings, b.pattern, newSet<Binding>).add(b);\n }\n\n unregister(b: Binding): void {\n const row = b.row;\n if (row === null) {\n this.rootBindings.get(b.pattern)?.delete(b);\n return;\n }\n // a row that left its list takes its registrations with it\n const bs = row.bindings;\n if (row.alive && bs !== null) bs.splice(bs.indexOf(b) >>> 0, 1);\n }\n\n enqueue(b: Binding): void {\n if (b.queued) return;\n b.queued = true;\n this.queue.push(b);\n this.schedule();\n }\n\n schedule(): void {\n if (this.scheduled) return;\n this.scheduled = true;\n queueMicrotask(this.drainFn);\n }\n\n /** Drops the queued work of a cut update loop: what it would have shown waits for the next change. */\n private dropWork(): void {\n for (const b of this.queue) b.queued = false;\n for (const l of this.dirtyLists) l.queued = false;\n for (const l of this.staleLists) l.stale = false;\n this.queue = [];\n this.dirtyLists = [];\n this.staleLists = [];\n this.strategy.dropped(this);\n }\n\n /**\n * Cuts an update loop past `max` (`id`: its message): reported with the paths its queued work\n * would have rendered (the console, and DevTools as `state:render-chain-limit`), then dropped.\n */\n private cutLoop(id: M, max: number): void {\n const paths = [...new Set([...this.queue, ...this.dirtyLists, ...this.staleLists].map((x) => x.pattern.path))];\n report(paths, `[@wcstack/state] ${text(id)}`);\n hooks.noticed?.(this, { \"type\": \"state:render-chain-limit\", \"maxDepth\": max, \"paths\": paths });\n this.dropWork();\n }\n\n drain(): void {\n this.scheduled = false;\n // a drain only rendering fed (no write from code since the last) continues a chain: the carried\n // one of a deferred apply, or the task's\n const carried = this.carried;\n this.carried = 0;\n let chain = 0;\n if (!this.fedBack || this.codeWrote) this.unchainFn();\n else if (carried > 0) chain = carried;\n else if ((chain = ++this.chain) === 1) setTimeout(this.unchainFn, 0);\n this.fedBack = this.codeWrote = false;\n if (chain > MAX_RENDER_CHAIN) {\n if (chain === MAX_RENDER_CHAIN + 1) this.cutLoop(M.RenderChain, MAX_RENDER_CHAIN);\n else this.dropWork();\n return;\n }\n this.draining = true;\n try {\n for (let pass = 0; this.queue.length > 0 || this.dirtyLists.length > 0 || this.staleLists.length > 0; pass++) {\n if (pass >= MAX_DRAIN_PASSES) {\n // (once a chain: a reaction that starts the same loop again in each drain is not reported again)\n if (this.unsettled) this.dropWork();\n else this.cutLoop(M.DrainNotSettled, MAX_DRAIN_PASSES);\n this.unsettled = true;\n break;\n }\n const stale = this.staleLists;\n if (stale.length > 0) {\n this.staleLists = [];\n for (const l of stale) {\n l.stale = false;\n this.trySync(l);\n }\n }\n const lists = this.dirtyLists;\n const q = this.queue;\n this.dirtyLists = [];\n this.queue = [];\n // a pass that changes structure — a list's rows, an `if` branch — goes to the page's\n // view-transition arbiter, if any (transition-runner protocol); one that only updates\n // values is applied right here, as with no arbiter (a value change is CSS transitions'\n // job, and a transition per keystroke left the page unclickable — docs/seam-apps.md,\n // router-admin). Queued entries stay marked until applied, so a write meanwhile folds\n // into them\n let ran = false;\n const apply = (): void => {\n ran = true;\n // list views first (they build rows), then bindings\n for (const l of lists) {\n l.queued = false;\n for (const v of [l.view, ...(l.extra ?? [])]) {\n if (v === null || !v.alive) continue;\n // a row that fails to build (a binding refused as it is attached) fails this view\n // alone: the rest of the pass is still applied (nothing stays queued)\n try {\n v.update();\n } catch (error) {\n this.failAt(error, l.pattern.path, v.anchor, \"for\");\n }\n }\n }\n // `if` / `elseif` conditions first: a branch one closes takes its bindings with it, so\n // they are not applied with the value that closes it (a condition over a getter is\n // queued after the bindings on the path it reads — docs/seam-apps.md, router-auth)\n for (let k = 0; k < 2; k++) {\n for (let i = 0; i < q.length; i++) {\n const b = q[i];\n // applied since it was queued (a row slot, when its row was built)\n if (!b.queued || (b.chain === null) === (k === 0)) continue;\n b.queued = false;\n if (b.owner === null || b.owner.alive) this.applyBinding(b);\n }\n }\n // applied later by the arbiter, outside any drain: report its failures now. What that\n // apply and the `$watch` after it write (a write-back, `$renderedCallback`, a copied list)\n // is drained here, the next of this drain's chain, and applied in the same transition — a\n // frame of its own showed the loading line gone over the old rows (router-admin)\n if (!this.draining) {\n this.report();\n if (--this.held === 0) this.settled();\n if (this.scheduled) {\n this.carried = chain + 1;\n this.inApply++;\n try {\n while (this.scheduled) this.drain();\n } finally {\n this.inApply--;\n }\n }\n }\n };\n const pending = (lists.length > 0 || q.some((b) => b.chain !== null)) && this.inApply === 0 ? runTransition(\"state\", apply) : apply();\n if (!ran) this.held++;\n if (pending !== undefined) pending.then(undefined, report);\n }\n } finally {\n this.draining = false;\n }\n // (writes made while applying are this drain's own passes)\n this.fedBack = this.codeWrote = false;\n this.report();\n if (this.held === 0) this.settled();\n // (as is the one a carried drain's reactions start)\n if (carried > 0 && this.scheduled) this.carried = chain + 1;\n }\n\n /** What follows a drain once its page is applied (`held`): `$watch`, the diagnostics, the sweep. */\n private settled(): void {\n hooks.drained?.(this);\n this.sweep();\n }\n\n // ---------------------------------------------------------------- apply, hooks, reports\n\n /** A binding that failed to apply: reported after the drain. */\n fail(error: unknown, b: Binding): void {\n this.errors.push([error, b]);\n }\n\n /**\n * A failure of what has no Binding object, reported like a binding's: a list that failed to sync\n * or render (its `for`), a binding refused as it was attached in a row.\n */\n failAt(error: unknown, path: string, node: Node | null, type: string): void {\n this.fail(error, { pattern: { path }, node, typeName: () => type } as unknown as Binding);\n }\n\n applyBinding(b: Binding): void {\n try {\n b.apply();\n } catch (error) {\n this.errors.push([error, b]);\n return;\n }\n if (this.rendered !== null) this.noteRendered(b.pattern, b.row);\n }\n\n /** Records an applied binding for `$renderedCallback`. */\n noteRendered(p: Pattern, row: StateRow | null): void {\n const list = upsert(this.rendered!, p.path, newArray<number[]>);\n if (row !== null) list.push(this.indexesOf(row));\n }\n\n /** Starts collecting applied paths when the state declares `$renderedCallback`. */\n watchRendered(): void {\n this.rendered = typeof this.target.$renderedCallback === \"function\" ? new Map() : null;\n }\n\n /** `$renderedCallback` for the paths applied since the last report, then binding failures. */\n report(): void {\n const rendered = this.rendered;\n if (rendered !== null && rendered.size > 0) {\n this.rendered = new Map();\n const paths = [...rendered.keys()];\n const indexes: Record<string, number[][]> = {};\n for (const [p, l] of rendered) if (l.length > 0) indexes[p] = l;\n this.feeding++;\n let r: any;\n try {\n r = this.callHook(\"$renderedCallback\", [paths, indexes]);\n } catch (e) {\n report(e);\n }\n if (isThenable(r)) {\n r.then(this.renderedFn, (e: unknown) => {\n this.renderedFn();\n report(e);\n });\n } else {\n this.feeding--;\n }\n }\n if (this.errors.length === 0) return;\n const errors = this.errors;\n this.errors = [];\n const hook = this.target.$errorCallback;\n for (const [error, binding] of errors) {\n hooks.failed?.(this, error, binding);\n const path = binding.pattern.path;\n const type = binding.typeName();\n if (typeof hook === \"function\") {\n // quoted keys: the author reads them (mangle.mjs shortens the unquoted ones)\n try {\n const r = this.callHook(\"$errorCallback\", [error, { \"path\": path, \"bindingType\": type, \"node\": binding.node }]) as any;\n if (isThenable(r)) r.then(undefined, report);\n } catch (e) {\n report(e);\n }\n } else {\n // (the binding's member and kind name it as written; the node points at it)\n report(error, `[@wcstack/state] ${text(M.BindingFailed, binding.name ? [type, path, binding.name, binding.kind] : [type, path])}`, binding.node);\n }\n }\n }\n\n /** Runs a lifecycle hook with the writable proxy; returns its result (awaited by the caller or not). */\n callHook(name: string, args: unknown[] = []): unknown {\n const fn = this.target[name];\n return typeof fn === \"function\" ? this.callAt(fn, null, args) : undefined;\n }\n\n // ---------------------------------------------------------------- $getAll / $setAll / $resolve\n\n /** Calls fn for every row at p.depth that matches `indexes` (a prefix over p's wildcards). */\n private forMatches(p: Pattern, indexes: readonly number[], fn: (row: StateRow | null, idx: number[]) => void): void {\n if (p.depth === 0) {\n fn(null, []);\n return;\n }\n const idx: number[] = [];\n const walk = (k: number, parent: StateRow | null): void => {\n const lp = p.lists[k]!;\n // the list itself is read too: a getter over $getAll sees the first row of an empty list\n this.read(lp, parent);\n const list = this.childList(parent, lp);\n const visit = (r: StateRow): void => {\n idx.push(r.index);\n if (k === p.depth) fn(r, idx);\n else walk(k + 1, r);\n idx.pop();\n };\n for (const r of k - 1 < indexes.length ? [list.rows[indexes[k - 1]]] : list.rows) if (r !== undefined) visit(r);\n };\n walk(1, null);\n }\n\n private getAll(path: string, indexes?: number[]): unknown[] {\n const p = this.pattern(path, true);\n if (indexes !== undefined) this.checkArity(\"$getAll\", path, p, indexes, false);\n // by default the loop context, on the wildcard levels the path shares with it\n let idx = indexes;\n if (idx === undefined) {\n idx = [];\n const ctx = this.ctx;\n if (ctx !== null && p.depth > 0) {\n for (let k = 1; k <= p.depth; k++) {\n const r = ctxRow(ctx, p, k);\n if (r === null) break;\n idx.push(r.index);\n }\n if (idx.length === 0) raise(M.GetAllNoCommonLevel, [path]);\n }\n }\n const out: unknown[] = [];\n this.forMatches(p, idx, (row) => out.push(this.read(p, row)));\n return out;\n }\n\n private setAll(path: string, indexes: number[], value: unknown, options?: { spread?: boolean }): number {\n if (!Array.isArray(indexes)) raise(M.SetAllNeedsIndexes, [path]);\n if (this.readonlyDepth > 0) raise(M.Readonly);\n const p = this.pattern(path, true);\n this.checkArity(\"$setAll\", path, p, indexes, false);\n const targets: [StateRow | null, number[]][] = [];\n this.forMatches(p, indexes, (row, idx) => targets.push([row, idx.slice()]));\n const spread = options?.spread === true;\n if (spread && (!Array.isArray(value) || value.length !== targets.length)) {\n raise(M.SetAllSpreadLength, [path, targets.length]);\n }\n let written = 0;\n for (let i = 0; i < targets.length; i++) {\n const [row, idx] = targets[i];\n const v = typeof value === \"function\"\n ? (value as (cur: unknown, ...i: number[]) => unknown)(this.readUntracked(p, row), ...idx)\n : spread ? (value as unknown[])[i] : value;\n if (v === undefined) continue;\n this.write(p, row, v);\n written++;\n }\n return written;\n }\n\n /** `$resolve` takes exactly one index per `*`; `$getAll` / `$setAll` at most one (fewer expands the rest). */\n private checkArity(api: string, path: string, p: Pattern, indexes: readonly number[], exact: boolean): void {\n const n = indexes.length;\n if (n > p.depth || (exact && n < p.depth)) {\n raise(exact ? M.IndexArityExact : M.IndexArityAtMost, [api, path, p.depth, n]);\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{e as t}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=chunk-
|
|
1
|
+
import{e as t}from"./chunk-AKTGQ6TC.js";import{b as n}from"./chunk-E3XSBW55.js";function r(t){n(26,[t])}function e(t){n(27,[t])}function o(t,r){n(52,[t,r])}function a(t){n(53,[t])}function f(t,r){n(28,[t,r])}function u(t,r){n(29,[t,r])}function i(t){n(30,[t])}function y(t){return!(!t||isNaN(Number(t)))}function c(t,n){return y(t)||e(n),Number(t)}function s(t,n,e){return c(t?.[n]??r(e),e)}function l(t,n){return void 0!==n&&n.length>0?n[0]:t}var m=(t,n)=>({factory:r=>{let e=s(r,0,t);return r=>("number"!=typeof r&&f(t,r),n(r,e))},arity:[1,1]}),b={eq:{factory:(t,n)=>{let o=t?.[0]??r("eq"),a=l(o,n);return t=>"number"==typeof t?"string"!=typeof a?t===a:(y(o)||e("eq"),t===Number(o)):"string"==typeof t?t===o:t===a},arity:[1,1]},ne:{factory:(t,n)=>{let o=t?.[0]??r("ne"),a=l(o,n);return t=>"number"==typeof t?"string"!=typeof a?t!==a:(y(o)||e("ne"),t!==Number(o)):"string"==typeof t?t!==o:t!==a},arity:[1,1]},not:{factory:()=>t=>!t,arity:[0,0]},lt:m("lt",(t,n)=>t<n),le:m("le",(t,n)=>t<=n),gt:m("gt",(t,n)=>t>n),ge:m("ge",(t,n)=>t>=n),falsy:{factory:()=>t=>!t,arity:[0,0]},truthy:{factory:()=>t=>!!t,arity:[0,0]},boolean:{factory:()=>t=>!!t,arity:[0,0]}},g=!1;function p(){g||(g=!0,t(b))}export{r as a,o as b,a as c,f as d,u as e,i as f,c as g,s as h,l as i,m as j,b as k,p as l};
|
|
2
|
+
//# sourceMappingURL=chunk-JJYM4JVZ.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{b as t}from"./chunk-E3XSBW55.js";var e="else",l="eventToken",n="state",s="command",r="class",i="attr",u="style",a=/^\$[1-9]\d{0,2}$/,c=t=>t.trim();function o(t,e){let l=[],n=null;for(let s=0;s<t.length;s++){let r=t[s];null!==n?r===n&&(n=null):"'"===r||'"'===r?n=r:r===e&&l.push(s)}return l}var f=(t,e)=>o(t,e)[0]??-1;function h(t,e){let l=[],n=0;for(let s of o(t,e))l.push(t.slice(n,s)),n=s+1;return l.push(t.slice(n)),l}var g=/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/;function m(e){let l=[],n=[],s="",r=null,i=!1,u=-1,a=-1,c=t=>{let e=function(t,e,l){let n=-1===e?t.length:e,s=-1===l?0:l;return t.slice(n-t.slice(0,n).trimStart().length,s+t.slice(s).trimEnd().length)}(s,u,a);(!t||e||i)&&(l.push(e),n.push(function(t,e){return e?t:"true"===t||"false"!==t&&("null"===t?null:g.test(t)?Number(t):t)}(e,i))),s="",i=!1,u=-1,a=-1};for(let t=0;t<e.length;t++){let l=e[t];r?l===r?r=null:(-1===u&&(u=s.length),s+=l,a=s.length):'"'===l||"'"===l?(r=l,i=!0):","===l?c():s+=l}return null!==r&&t(107,[r,e]),c(!0),{args:l,literals:n}}function p(e,l,n){let s=f(e,"|");if(-1===s)return[e.trim(),[]];let r=e.slice(s+1).trim(),i=n.get(r);return void 0===i&&(i=function(e,l,n){let s=n??e.join("|");return e.map(e=>{let n=f(e,"("),r=(t=>o(t,")").pop()??-1)(e);if(-1===r&&(r=e.lastIndexOf(")")),-1!==n&&-1===r&&t(108,[e]),-1!==r&&-1===n&&t(109,[e]),-1!==r&&r<n&&t(110,[e]),-1!==r&&e.slice(r+1).trim().length>0){let l=e.slice(r+1).trim();t(111,[e,l])}let i=(-1===n?e:e.substring(0,n)).trim();if(0===i.length&&t(112,[s]),i.includes("#")){let[,e]=i.split("#");t("input"===l?113:114,[i,e])}return-1===n?{Kn:i,args:[],literals:[]}:{Kn:i,...m(e.substring(n+1,r))}})}(h(r,"|").map(c),l,e),n.set(r,i)),[e.slice(0,s).trim(),i]}var d=new Map;function v(e){t(1101,[e])}function b(e){let[l,n]=p(e,"output",d);l.includes("@")&&t(32,[l]);let s=l,r=s.startsWith("."),i=r?s.slice(1):s;return(i.length>0&&i.split(".").some(t=>0===t.length)||!r&&0===i.length)&&t(119,[e]),function(e){e.includes("**")&&v(e);let l=e.split(".").length;l>512&&t(117,[e,l])}(s),{et:s,tt:n}}export{e as a,l as b,n as c,s as d,r as e,i as f,u as g,a as h,c as i,f as j,h as k,p as l,v as m,b as n};
|
|
2
|
+
//# sourceMappingURL=chunk-KBQKAD3I.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ELSE_KEYWORD","EVENT_TOKEN_NAMESPACE","VOLUME_INJECTION_PROP","COMMAND_NAMESPACE","CLASS_NAMESPACE","ATTR_NAMESPACE","STYLE_NAMESPACE","INDEX_PARAM","NUMBER_LITERAL","parseFilterArgsWithLiterals","argsText","args","literals","current","inQuote","hasQuote","firstQuoteStart","lastQuoteEnd","flush","last","arg","text","startLimit","length","endLimit","slice","trimStart","trimEnd","finalizeArg","push","quoted","test","Number","toLiteral","i","char","raise","trimFn","s","trim","outsideQuotes","found","quote","c","indexOfOutsideQuotes","splitOutsideQuotes","separator","parts","start","splitFilters","part","filterIOType","cache","pos","filtersText","filters","get","filterTextList","sourceText","source","join","map","filterText","openParenIndex","closeParenIndex","pop","lastIndexOfOutsideQuotes","lastIndexOf","trailing","filterName","substring","includes","modifiers","split","parseFilters","set","cacheFilterInfos","Map","recursionUnsupported","path","parseStatePart","statePart","stateAndPath","statePathName","isLoopRelative","startsWith","body","some","segment","segmentCount","checkPathLikeGetPathInfo","outFilters","b","x","y","Q","U","k","v","W","P","m","R","S","D","J"],"sources":["../../../src/parser/define.ts","../../../src/parser/parseFilterArgs.ts","../../../src/parser/utils.ts","../../../src/parser/parseFilters.ts","../../../src/parser/parseStatePart.ts"],"sourcesContent":["/**\n * Constants of the `data-wcs` binding grammar, copied from `@wcstack/state`\n * (`src/define.ts` / `src/errorGuidance.ts`). The values are the syntax contract\n * (`[prop][#mod]: [path][|filter...]`) and must stay identical to the current engine.\n */\n\n/** Path segment delimiter. */\nexport const DELIMITER = '.';\n/** Separator between the bindings of one attribute value. */\nexport const BINDING_SEPARATOR = ';';\n/** Separator between the left side (property) and the right side (path). */\nexport const PROP_VALUE_SEPARATOR = ':';\n/** Separator between the property and its modifier list. */\nexport const MODIFIER_SEPARATOR = '#';\n/** Separator of the filter pipeline. */\nexport const FILTER_SEPARATOR = '|';\n\nexport const ELSE_KEYWORD = 'else';\nexport const SPREAD_PROP = '...';\nexport const EVENT_PROP_PREFIX = 'on';\nexport const EVENT_TOKEN_NAMESPACE = 'eventToken';\n/** `<wcs-state mount>` left side `state.<key>: path` (volume injection). */\nexport const VOLUME_INJECTION_PROP = 'state';\nexport const COMMAND_NAMESPACE = 'command';\nexport const CLASS_NAMESPACE = 'class';\nexport const ATTR_NAMESPACE = 'attr';\nexport const STYLE_NAMESPACE = 'style';\n\n/**\n * Segment-count ceiling of one path. The current engine enforces it in `getPathInfo`\n * (first intern only) with a `[wcs/binding-syntax]` diagnostic; the parser port keeps the\n * same check inline on the string.\n */\nexport const MAX_PATH_SEGMENTS = 512;\n\n/** `$1` … `$128`, no leading zero: a loop index parameter (anything else after the `$` is not one). */\nexport const INDEX_PARAM = /^\\$[1-9]\\d{0,2}$/;\nexport const MAX_INDEX_PARAM = 128;\n\n/** Recursive wildcard — only meaningful in `$recursion` declarations, never in a binding path. */\nexport const RECURSION_WILDCARD = '**';\n","/**\n * フィルタ引数リストのパース。`filter(a, b)` の `a, b` 部分を受け取る。\n *\n * トリムの規則は「**クォートの外側だけ**」。`fix( 2 )` のような書き癖を吸収するために\n * 素の引数は前後をトリムするが、クォートは「ここは literal」という宣言なので中身の\n * 空白は残す。両方まとめてトリムしていたため `pad(5, ' ')` が空文字パディング\n * (=無変化)に化けており、空白区切りの `join(' / ')` も指定できなかった。\n *\n * Port of `@wcstack/state` `src/bindTextParser/parseFilterArgs.ts` (behaviour unchanged).\n */\nimport { raise, M } from \"../messages\";\n\n/** 引数 1 つを確定する。クォート由来の文字が入った範囲より外側だけをトリムする。 */\nfunction finalizeArg(text: string, firstQuoteStart: number, lastQuoteEnd: number): string {\n // 先頭側: 最初のクォート文字より前だけが削れる(クォートが無ければ全体が対象)\n const startLimit = firstQuoteStart === -1 ? text.length : firstQuoteStart;\n // 末尾側: 最後のクォート文字より後ろだけが削れる(クォートが無ければ全体が対象)\n const endLimit = lastQuoteEnd === -1 ? 0 : lastQuoteEnd;\n // (`trim` removes what `\\s` matches: WhiteSpace and LineTerminator)\n return text.slice(startLimit - text.slice(0, startLimit).trimStart().length, endLimit + text.slice(endLimit).trimEnd().length);\n}\n\n/** 引用符の無い引数の型(要件 B9): true / false / null / 数値は型付き、それ以外は文字列 */\nconst NUMBER_LITERAL = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/;\nfunction toLiteral(text: string, quoted: boolean): unknown {\n if (quoted) return text;\n if (text === \"true\") return true;\n if (text === \"false\") return false;\n if (text === \"null\") return null;\n return NUMBER_LITERAL.test(text) ? Number(text) : text;\n}\n\n/**\n * 引数の原文と、その型付きの値(要件 B9)を一緒に返す。原文は引用符を外したもの。\n *\n * 末尾の空引数だけが落ちる(`\"a,\"` → 1 個、`\",a\"` → 2 個、`\",\"` → 1 個)。`filter()` を\n * 「引数 0 個」と読むための規則で、先頭・中間の空引数は位置を保つために残す。\n */\nexport function parseFilterArgsWithLiterals(argsText: string): { args: string[]; literals: unknown[] } {\n const args: string[] = [];\n const literals: unknown[] = [];\n let current = '';\n let inQuote: string | null = null;\n let hasQuote = false;\n let firstQuoteStart = -1;\n let lastQuoteEnd = -1;\n\n /** Ends an argument; only the last one is dropped when empty (and not quoted). */\n const flush = (last?: boolean): void => {\n const arg = finalizeArg(current, firstQuoteStart, lastQuoteEnd);\n if (!last || arg || hasQuote) {\n args.push(arg);\n literals.push(toLiteral(arg, hasQuote));\n }\n current = '';\n hasQuote = false;\n firstQuoteStart = -1;\n lastQuoteEnd = -1;\n };\n\n for (let i = 0; i < argsText.length; i++) {\n const char = argsText[i];\n\n if (inQuote) {\n if (char === inQuote) {\n inQuote = null;\n } else {\n if (firstQuoteStart === -1) {\n firstQuoteStart = current.length;\n }\n current += char;\n lastQuoteEnd = current.length;\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char;\n hasQuote = true;\n } else if (char === ',') {\n flush();\n } else {\n current += char;\n }\n }\n\n if (inQuote !== null) {\n // 閉じていない引用符は受理しない(要件 B2)。以前は黙って閉じたことにしていた\n raise(M.UnterminatedQuote, [inQuote, argsText]);\n }\n flush(true);\n\n return { args, literals };\n}\n","export const trimFn = (s: string): string => s.trim();\n\n/**\n * The positions of `char` in `text` that are outside quotes (`'` / `\"`), in order (要件 B1).\n * 閉じていない引用符はそのまま末尾まで続く扱い — 不正な引用符はフィルタ引数の段で名指しで落ちる。\n */\nfunction outsideQuotes(text: string, char: string): number[] {\n const found: number[] = [];\n let quote: string | null = null;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quote !== null) {\n if (c === quote) quote = null;\n } else if (c === \"'\" || c === '\"') {\n quote = c;\n } else if (c === char) {\n found.push(i);\n }\n }\n return found;\n}\n\n/** `text` の中で、引用符(`'` / `\"`)の外にある最初の `char` の位置。無ければ -1(要件 B1)。 */\nexport const indexOfOutsideQuotes = (text: string, char: string): number => outsideQuotes(text, char)[0] ?? -1;\n\n/**\n * `text` の中で、引用符の外にある**最後の** `char` の位置。無ければ -1(要件 B1)。\n * フィルタの閉じ括弧を探す用(`a|foo(')')` の引用符内の `)` を終端と誤認しないため)。\n */\nexport const lastIndexOfOutsideQuotes = (text: string, char: string): number => outsideQuotes(text, char).pop() ?? -1;\n\n/**\n * `separator` で区切る。ただし引用符の中は区切らない(要件 B1): `join(';')` や `join('|')` の\n * 区切り文字は引数であって、バインディングやフィルタの区切りではない。\n */\nexport function splitOutsideQuotes(text: string, separator: string): string[] {\n const parts: string[] = [];\n let start = 0;\n for (const i of outsideQuotes(text, separator)) {\n parts.push(text.slice(start, i));\n start = i + 1;\n }\n parts.push(text.slice(start));\n return parts;\n}\n","import { FILTER_SEPARATOR, MODIFIER_SEPARATOR } from \"./define\";\nimport { parseFilterArgsWithLiterals } from \"./parseFilterArgs\";\nimport { raise, M } from \"../messages\";\nimport { FilterIOType, ParsedFilter } from \"./types\";\nimport { indexOfOutsideQuotes, lastIndexOfOutsideQuotes, splitOutsideQuotes, trimFn } from \"./utils\";\n\n// format: filterName(arg1,arg2) or filterName\n\n/**\n * 文法の段(要件 D16): 名前と引数だけを読む。**実関数は引かない** — フィルタ名の解決\n * (別名も含む)はエンジン側の仕事。未知のフィルタもここでは落とさない。\n *\n * Port of `@wcstack/state` `src/bindTextParser/parseFilters.ts` (behaviour unchanged; the\n * tooling-only `clearFilterFnCacheForTooling` is dropped).\n *\n * @param filterTextList 個々のフィルタの原文(`|` で切った後)\n * @param filterIOType 入力(左辺)/ 出力(右辺)。実関数は引かないが、助言の出し分けに使う\n * @param sourceText 診断に埋める原文。呼び出し側は**その辺の全文**(`propPart` / `statePart`)を\n * 渡すこと。`|` より後ろだけを渡すと、`textContent: a|` のように末尾が空の形で\n * 空文字になり、つなぎ直し(`filterTextList.join(\"|\")`)と同じで文脈が消える。\n * 省略時のつなぎ直しは、原文を持たない直接の呼び出し用のフォールバック\n */\nexport function parseFilters(filterTextList: string[], filterIOType: FilterIOType, sourceText?: string): ParsedFilter[] {\n const source = sourceText ?? filterTextList.join(\"|\");\n return filterTextList.map((filterText) => {\n // 括弧も引用符の外だけで探す(要件 B1)。素の `indexOf` / `lastIndexOf` だと\n // `foo(')')` の引用符内の `)` を終端に取り、「閉じ括弧が無い」ではなく\n // 「引用符が閉じていない」という見当違いの診断になっていた\n const openParenIndex = indexOfOutsideQuotes(filterText, '(');\n let closeParenIndex = lastIndexOfOutsideQuotes(filterText, ')');\n if (closeParenIndex === -1) {\n // 引用符の外に閉じ括弧が無い = 引用符が閉じていない形(`join('x)`)か、本当に無いか。\n // 前者で「閉じ括弧が無い」と言うのは見当違いなので素の探索へ落とし、引数の段の\n // `[wcs/binding-syntax] unterminated ' quote` に診断させる\n closeParenIndex = filterText.lastIndexOf(')');\n }\n // check parentheses\n if (openParenIndex !== -1 && closeParenIndex === -1) {\n raise(M.FilterUnclosed, [filterText]);\n }\n if (closeParenIndex !== -1 && openParenIndex === -1) {\n raise(M.FilterUnopened, [filterText]);\n }\n if (closeParenIndex !== -1 && closeParenIndex < openParenIndex) {\n // `foo)1(` — 以前は `substring` が start > end で引数を入れ替えるため、フィルタ名\n // `foo)1` として受理されていた\n raise(M.FilterParenOrder, [filterText]);\n }\n if (closeParenIndex !== -1 && filterText.slice(closeParenIndex + 1).trim().length > 0) {\n // 閉じ括弧の後ろの残余を**黙って捨てていた**。`n|fix(2)uc` は `uc` が消えて診断ゼロで\n // 通っていた。実害は「`|` の打ち忘れでフィルタが 1 本消えても無診断」\n const trailing = filterText.slice(closeParenIndex + 1).trim();\n raise(M.FilterTrailing, [filterText, trailing]);\n }\n const filterName = (openParenIndex === -1 ? filterText : filterText.substring(0, openParenIndex)).trim();\n if (filterName.length === 0) {\n // 空のフィルタ(`x|`・`x||y`・`x|(1)`)は文法の誤り。解析の段で名指しで落とす — 未知の\n // フィルタとは別物で、実関数の解決まで持ち越すと tooling の解析が素通りする\n raise(M.FilterEmpty, [source]);\n }\n if (filterName.includes(MODIFIER_SEPARATOR)) {\n // フィルタ名に `#` が飲まれた形。`[wcs/filter-unknown] filter not found: trim#ro` だと\n // 診断が指す先が実際の誤りと違う(要件 B4 の並び)。\n // 助言は辺で分ける — **修飾子は左辺にしか存在しない**ので、右辺で「修飾子をフィルタより\n // 前に書け」と言うと成立しない直し方(`textContent#ro|trim: x`)を勧めることになる\n const [, modifiers] = filterName.split(MODIFIER_SEPARATOR);\n raise(filterIOType === \"input\" ? M.FilterNameHasModifiersInput : M.FilterNameHasModifiersOutput, [filterName, modifiers]);\n }\n if (openParenIndex === -1) {\n // no arguments\n return { filterName, args: [], literals: [] };\n }\n const argsText = filterText.substring(openParenIndex + 1, closeParenIndex);\n return { filterName, ...parseFilterArgsWithLiterals(argsText) };\n });\n}\n\n/**\n * One side of a binding split at its first `|` outside quotes: the text before it (trimmed) and its\n * parsed filters. `cache` is keyed by the text after the `|`: the same text gives **the same array**\n * (callers must not change it); a failed parse is not cached. The diagnostics quote the whole side\n * (`part`): the text after the `|` alone is empty for `a|`.\n */\nexport function splitFilters(part: string, filterIOType: FilterIOType, cache: Map<string, ParsedFilter[]>): [string, ParsedFilter[]] {\n // 引用符の中の `|` はフィルタの区切りではない(要件 B1 — `join('|')`)\n const pos = indexOfOutsideQuotes(part, FILTER_SEPARATOR);\n if (pos === -1) return [part.trim(), []];\n const filtersText = part.slice(pos + 1).trim();\n let filters = cache.get(filtersText);\n if (filters === undefined) {\n filters = parseFilters(splitOutsideQuotes(filtersText, FILTER_SEPARATOR).map(trimFn), filterIOType, part);\n cache.set(filtersText, filters);\n }\n return [part.slice(0, pos).trim(), filters];\n}\n","import { DELIMITER, MAX_PATH_SEGMENTS, RECURSION_WILDCARD } from \"./define\";\nimport { splitFilters } from \"./parseFilters\";\nimport { raise, M } from \"../messages\";\nimport { ParsedBinding, ParsedFilter } from \"./types\";\n\n// 解析の段の形(フィルタは名前と引数だけ — 実関数はエンジンが引く。要件 D16)。\n// `@wcstack/state` はここで `statePathInfo`(`getPathInfo` の intern 結果)も返していたが、\n// 新エンジンはパスを自分で解決するので文字列だけを返す。\nexport type StatePartParseResult = Pick<ParsedBinding, 'statePathName' | 'outFilters'>;\n\n/**\n * 出力フィルタ列の解析結果のキャッシュ(鍵は `|` より後ろの原文)。同じ原文は**同じ配列**を返す —\n * 消費側は返された `outFilters` を変更しないこと。落ちた解析は載らない。\n * (`@wcstack/state` の tooling 専用の解放口 `clearStatePartCacheForTooling` は移植しない)\n */\nconst cacheFilterInfos = new Map<string, ParsedFilter[]>();\n/** Tooling (`clearParserCaches`): a long-running process drops what it parsed. */\nexport const clearStatePartCache = (): void => cacheFilterInfos.clear();\n\n/**\n * `getPathInfo` が初回 intern で行っていた文字列だけで決まる検査の移植(順序も同じ:\n * `**` → セグメント数)。`getPathInfo` は `**` のパスを intern しないので毎回落ち、\n * 上限超えのパスも intern されないので毎回落ちる — 状態を持たない検査と同値。\n */\nfunction checkPathLikeGetPathInfo(path: string): void {\n if (path.includes(RECURSION_WILDCARD)) {\n recursionUnsupported(path);\n }\n const segmentCount = path.split(DELIMITER).length;\n if (segmentCount > MAX_PATH_SEGMENTS) {\n raise(M.TooManySegments, [path, segmentCount]);\n }\n}\n\n// format: statePath|filter|filter\n// statePath-format: path.to.property (e.g., user.name.first, users.*.name, users.0.name, not include @)\n// filters-format: filterName or filterName(arg1,arg2)\n\n/** Port of `@wcstack/state` `src/bindTextParser/parseStatePart.ts` (no `statePathInfo`). */\n/** `**` outside the places a `$recursion` declaration gives it meaning. */\nexport function recursionUnsupported(path: string): never {\n raise(M.RecursionUnsupported, [path]);\n}\n\nexport function parseStatePart(statePart: string): StatePartParseResult {\n const [stateAndPath, filters] = splitFilters(statePart, \"output\", cacheFilterInfos);\n if (stateAndPath.includes(\"@\")) {\n // 名前次元は v2 で撤去(docs/state-mount-design.md D16 / §9)。パスは 1 本のツリー。\n raise(M.SelectorRemoved, [stateAndPath]);\n }\n const statePathName = stateAndPath;\n // 右辺も左辺(`parsePropPart`)と同じ規準で空セグメントを弾く(要件 B1)。\n //\n // **判定の前にループ相対の短縮形を正規化する。** `.` で始まる右辺は `for` 行の相対パスで\n // (展開はエンジンの仕事 — パーサは展開前の原文をそのまま返す)、先頭の空セグメント 1 つは正当。\n // とくに **`.` 単独は「行そのもの」を指す正規の書き方**(`state: .`)— 「先頭は許すが末尾は拒否」と\n // 素朴に書くと `\".\"` は `[\"\", \"\"]` = 先頭かつ末尾なので落ちる。取り除いた残りが空でも通すこと\n const isLoopRelative = statePathName.startsWith(DELIMITER);\n const body = isLoopRelative ? statePathName.slice(DELIMITER.length) : statePathName;\n const hasEmptySegment = body.length > 0 && body.split(DELIMITER).some((segment) => segment.length === 0);\n if (hasEmptySegment || (!isLoopRelative && body.length === 0)) {\n raise(M.EmptySegment, [statePart]);\n }\n checkPathLikeGetPathInfo(statePathName);\n return {\n statePathName,\n outFilters: filters,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["ELSE_KEYWORD","EVENT_TOKEN_NAMESPACE","VOLUME_INJECTION_PROP","COMMAND_NAMESPACE","CLASS_NAMESPACE","ATTR_NAMESPACE","STYLE_NAMESPACE","INDEX_PARAM","trimFn","s","trim","outsideQuotes","text","char","found","quote","i","length","c","push","indexOfOutsideQuotes","splitOutsideQuotes","separator","parts","start","slice","NUMBER_LITERAL","parseFilterArgsWithLiterals","argsText","args","literals","current","inQuote","hasQuote","firstQuoteStart","lastQuoteEnd","flush","last","arg","startLimit","endLimit","trimStart","trimEnd","finalizeArg","quoted","test","Number","toLiteral","raise","splitFilters","part","filterIOType","cache","pos","filtersText","filters","get","filterTextList","sourceText","source","join","map","filterText","openParenIndex","closeParenIndex","pop","lastIndexOfOutsideQuotes","lastIndexOf","trailing","filterName","substring","includes","modifiers","split","parseFilters","set","cacheFilterInfos","Map","recursionUnsupported","path","parseStatePart","statePart","stateAndPath","statePathName","isLoopRelative","startsWith","body","some","segment","segmentCount","checkPathLikeGetPathInfo","outFilters","b","x","y","Q","U","k","v","W","E","m","P","S","D","J"],"sources":["../../../src/parser/define.ts","../../../src/parser/utils.ts","../../../src/parser/parseFilterArgs.ts","../../../src/parser/parseFilters.ts","../../../src/parser/parseStatePart.ts"],"sourcesContent":["/**\n * Constants of the `data-wcs` binding grammar, copied from `@wcstack/state`\n * (`src/define.ts` / `src/errorGuidance.ts`). The values are the syntax contract\n * (`[prop][#mod]: [path][|filter...]`) and must stay identical to the current engine.\n */\n\n/** Path segment delimiter. */\nexport const DELIMITER = '.';\n/** Separator between the bindings of one attribute value. */\nexport const BINDING_SEPARATOR = ';';\n/** Separator between the left side (property) and the right side (path). */\nexport const PROP_VALUE_SEPARATOR = ':';\n/** Separator between the property and its modifier list. */\nexport const MODIFIER_SEPARATOR = '#';\n/** Separator of the filter pipeline. */\nexport const FILTER_SEPARATOR = '|';\n\nexport const ELSE_KEYWORD = 'else';\nexport const SPREAD_PROP = '...';\nexport const EVENT_PROP_PREFIX = 'on';\nexport const EVENT_TOKEN_NAMESPACE = 'eventToken';\n/** `<wcs-state mount>` left side `state.<key>: path` (volume injection). */\nexport const VOLUME_INJECTION_PROP = 'state';\nexport const COMMAND_NAMESPACE = 'command';\nexport const CLASS_NAMESPACE = 'class';\nexport const ATTR_NAMESPACE = 'attr';\nexport const STYLE_NAMESPACE = 'style';\n\n/**\n * Segment-count ceiling of one path. The current engine enforces it in `getPathInfo`\n * (first intern only) with a `[wcs/binding-syntax]` diagnostic; the parser port keeps the\n * same check inline on the string.\n */\nexport const MAX_PATH_SEGMENTS = 512;\n\n/** `$1` … `$128`, no leading zero: a loop index parameter (anything else after the `$` is not one). */\nexport const INDEX_PARAM = /^\\$[1-9]\\d{0,2}$/;\nexport const MAX_INDEX_PARAM = 128;\n\n/** Recursive wildcard — only meaningful in `$recursion` declarations, never in a binding path. */\nexport const RECURSION_WILDCARD = '**';\n","export const trimFn = (s: string): string => s.trim();\n\n/**\n * The positions of `char` in `text` that are outside quotes (`'` / `\"`), in order (要件 B1).\n * 閉じていない引用符はそのまま末尾まで続く扱い — 不正な引用符はフィルタ引数の段で名指しで落ちる。\n */\nfunction outsideQuotes(text: string, char: string): number[] {\n const found: number[] = [];\n let quote: string | null = null;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quote !== null) {\n if (c === quote) quote = null;\n } else if (c === \"'\" || c === '\"') {\n quote = c;\n } else if (c === char) {\n found.push(i);\n }\n }\n return found;\n}\n\n/** `text` の中で、引用符(`'` / `\"`)の外にある最初の `char` の位置。無ければ -1(要件 B1)。 */\nexport const indexOfOutsideQuotes = (text: string, char: string): number => outsideQuotes(text, char)[0] ?? -1;\n\n/**\n * `text` の中で、引用符の外にある**最後の** `char` の位置。無ければ -1(要件 B1)。\n * フィルタの閉じ括弧を探す用(`a|foo(')')` の引用符内の `)` を終端と誤認しないため)。\n */\nexport const lastIndexOfOutsideQuotes = (text: string, char: string): number => outsideQuotes(text, char).pop() ?? -1;\n\n/**\n * `separator` で区切る。ただし引用符の中は区切らない(要件 B1): `join(';')` や `join('|')` の\n * 区切り文字は引数であって、バインディングやフィルタの区切りではない。\n */\nexport function splitOutsideQuotes(text: string, separator: string): string[] {\n const parts: string[] = [];\n let start = 0;\n for (const i of outsideQuotes(text, separator)) {\n parts.push(text.slice(start, i));\n start = i + 1;\n }\n parts.push(text.slice(start));\n return parts;\n}\n","/**\n * フィルタ引数リストのパース。`filter(a, b)` の `a, b` 部分を受け取る。\n *\n * トリムの規則は「**クォートの外側だけ**」。`fix( 2 )` のような書き癖を吸収するために\n * 素の引数は前後をトリムするが、クォートは「ここは literal」という宣言なので中身の\n * 空白は残す。両方まとめてトリムしていたため `pad(5, ' ')` が空文字パディング\n * (=無変化)に化けており、空白区切りの `join(' / ')` も指定できなかった。\n *\n * Port of `@wcstack/state` `src/bindTextParser/parseFilterArgs.ts` (behaviour unchanged).\n */\nimport { raise, M } from \"../messages\";\n\n/** 引数 1 つを確定する。クォート由来の文字が入った範囲より外側だけをトリムする。 */\nfunction finalizeArg(text: string, firstQuoteStart: number, lastQuoteEnd: number): string {\n // 先頭側: 最初のクォート文字より前だけが削れる(クォートが無ければ全体が対象)\n const startLimit = firstQuoteStart === -1 ? text.length : firstQuoteStart;\n // 末尾側: 最後のクォート文字より後ろだけが削れる(クォートが無ければ全体が対象)\n const endLimit = lastQuoteEnd === -1 ? 0 : lastQuoteEnd;\n // (`trim` removes what `\\s` matches: WhiteSpace and LineTerminator)\n return text.slice(startLimit - text.slice(0, startLimit).trimStart().length, endLimit + text.slice(endLimit).trimEnd().length);\n}\n\n/** 引用符の無い引数の型(要件 B9): true / false / null / 数値は型付き、それ以外は文字列 */\nconst NUMBER_LITERAL = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/;\nfunction toLiteral(text: string, quoted: boolean): unknown {\n if (quoted) return text;\n if (text === \"true\") return true;\n if (text === \"false\") return false;\n if (text === \"null\") return null;\n return NUMBER_LITERAL.test(text) ? Number(text) : text;\n}\n\n/**\n * 引数の原文と、その型付きの値(要件 B9)を一緒に返す。原文は引用符を外したもの。\n *\n * 末尾の空引数だけが落ちる(`\"a,\"` → 1 個、`\",a\"` → 2 個、`\",\"` → 1 個)。`filter()` を\n * 「引数 0 個」と読むための規則で、先頭・中間の空引数は位置を保つために残す。\n */\nexport function parseFilterArgsWithLiterals(argsText: string): { args: string[]; literals: unknown[] } {\n const args: string[] = [];\n const literals: unknown[] = [];\n let current = '';\n let inQuote: string | null = null;\n let hasQuote = false;\n let firstQuoteStart = -1;\n let lastQuoteEnd = -1;\n\n /** Ends an argument; only the last one is dropped when empty (and not quoted). */\n const flush = (last?: boolean): void => {\n const arg = finalizeArg(current, firstQuoteStart, lastQuoteEnd);\n if (!last || arg || hasQuote) {\n args.push(arg);\n literals.push(toLiteral(arg, hasQuote));\n }\n current = '';\n hasQuote = false;\n firstQuoteStart = -1;\n lastQuoteEnd = -1;\n };\n\n for (let i = 0; i < argsText.length; i++) {\n const char = argsText[i];\n\n if (inQuote) {\n if (char === inQuote) {\n inQuote = null;\n } else {\n if (firstQuoteStart === -1) {\n firstQuoteStart = current.length;\n }\n current += char;\n lastQuoteEnd = current.length;\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char;\n hasQuote = true;\n } else if (char === ',') {\n flush();\n } else {\n current += char;\n }\n }\n\n if (inQuote !== null) {\n // 閉じていない引用符は受理しない(要件 B2)。以前は黙って閉じたことにしていた\n raise(M.UnterminatedQuote, [inQuote, argsText]);\n }\n flush(true);\n\n return { args, literals };\n}\n","import { FILTER_SEPARATOR, MODIFIER_SEPARATOR } from \"./define\";\nimport { parseFilterArgsWithLiterals } from \"./parseFilterArgs\";\nimport { raise, M } from \"../messages\";\nimport { FilterIOType, ParsedFilter } from \"./types\";\nimport { indexOfOutsideQuotes, lastIndexOfOutsideQuotes, splitOutsideQuotes, trimFn } from \"./utils\";\n\n// format: filterName(arg1,arg2) or filterName\n\n/**\n * 文法の段(要件 D16): 名前と引数だけを読む。**実関数は引かない** — フィルタ名の解決\n * (別名も含む)はエンジン側の仕事。未知のフィルタもここでは落とさない。\n *\n * Port of `@wcstack/state` `src/bindTextParser/parseFilters.ts` (behaviour unchanged; the\n * tooling-only `clearFilterFnCacheForTooling` is dropped).\n *\n * @param filterTextList 個々のフィルタの原文(`|` で切った後)\n * @param filterIOType 入力(左辺)/ 出力(右辺)。実関数は引かないが、助言の出し分けに使う\n * @param sourceText 診断に埋める原文。呼び出し側は**その辺の全文**(`propPart` / `statePart`)を\n * 渡すこと。`|` より後ろだけを渡すと、`textContent: a|` のように末尾が空の形で\n * 空文字になり、つなぎ直し(`filterTextList.join(\"|\")`)と同じで文脈が消える。\n * 省略時のつなぎ直しは、原文を持たない直接の呼び出し用のフォールバック\n */\nexport function parseFilters(filterTextList: string[], filterIOType: FilterIOType, sourceText?: string): ParsedFilter[] {\n const source = sourceText ?? filterTextList.join(\"|\");\n return filterTextList.map((filterText) => {\n // 括弧も引用符の外だけで探す(要件 B1)。素の `indexOf` / `lastIndexOf` だと\n // `foo(')')` の引用符内の `)` を終端に取り、「閉じ括弧が無い」ではなく\n // 「引用符が閉じていない」という見当違いの診断になっていた\n const openParenIndex = indexOfOutsideQuotes(filterText, '(');\n let closeParenIndex = lastIndexOfOutsideQuotes(filterText, ')');\n if (closeParenIndex === -1) {\n // 引用符の外に閉じ括弧が無い = 引用符が閉じていない形(`join('x)`)か、本当に無いか。\n // 前者で「閉じ括弧が無い」と言うのは見当違いなので素の探索へ落とし、引数の段の\n // `[wcs/binding-syntax] unterminated ' quote` に診断させる\n closeParenIndex = filterText.lastIndexOf(')');\n }\n // check parentheses\n if (openParenIndex !== -1 && closeParenIndex === -1) {\n raise(M.FilterUnclosed, [filterText]);\n }\n if (closeParenIndex !== -1 && openParenIndex === -1) {\n raise(M.FilterUnopened, [filterText]);\n }\n if (closeParenIndex !== -1 && closeParenIndex < openParenIndex) {\n // `foo)1(` — 以前は `substring` が start > end で引数を入れ替えるため、フィルタ名\n // `foo)1` として受理されていた\n raise(M.FilterParenOrder, [filterText]);\n }\n if (closeParenIndex !== -1 && filterText.slice(closeParenIndex + 1).trim().length > 0) {\n // 閉じ括弧の後ろの残余を**黙って捨てていた**。`n|fix(2)uc` は `uc` が消えて診断ゼロで\n // 通っていた。実害は「`|` の打ち忘れでフィルタが 1 本消えても無診断」\n const trailing = filterText.slice(closeParenIndex + 1).trim();\n raise(M.FilterTrailing, [filterText, trailing]);\n }\n const filterName = (openParenIndex === -1 ? filterText : filterText.substring(0, openParenIndex)).trim();\n if (filterName.length === 0) {\n // 空のフィルタ(`x|`・`x||y`・`x|(1)`)は文法の誤り。解析の段で名指しで落とす — 未知の\n // フィルタとは別物で、実関数の解決まで持ち越すと tooling の解析が素通りする\n raise(M.FilterEmpty, [source]);\n }\n if (filterName.includes(MODIFIER_SEPARATOR)) {\n // フィルタ名に `#` が飲まれた形。`[wcs/filter-unknown] filter not found: trim#ro` だと\n // 診断が指す先が実際の誤りと違う(要件 B4 の並び)。\n // 助言は辺で分ける — **修飾子は左辺にしか存在しない**ので、右辺で「修飾子をフィルタより\n // 前に書け」と言うと成立しない直し方(`textContent#ro|trim: x`)を勧めることになる\n const [, modifiers] = filterName.split(MODIFIER_SEPARATOR);\n raise(filterIOType === \"input\" ? M.FilterNameHasModifiersInput : M.FilterNameHasModifiersOutput, [filterName, modifiers]);\n }\n if (openParenIndex === -1) {\n // no arguments\n return { filterName, args: [], literals: [] };\n }\n const argsText = filterText.substring(openParenIndex + 1, closeParenIndex);\n return { filterName, ...parseFilterArgsWithLiterals(argsText) };\n });\n}\n\n/**\n * One side of a binding split at its first `|` outside quotes: the text before it (trimmed) and its\n * parsed filters. `cache` is keyed by the text after the `|`: the same text gives **the same array**\n * (callers must not change it); a failed parse is not cached. The diagnostics quote the whole side\n * (`part`): the text after the `|` alone is empty for `a|`.\n */\nexport function splitFilters(part: string, filterIOType: FilterIOType, cache: Map<string, ParsedFilter[]>): [string, ParsedFilter[]] {\n // 引用符の中の `|` はフィルタの区切りではない(要件 B1 — `join('|')`)\n const pos = indexOfOutsideQuotes(part, FILTER_SEPARATOR);\n if (pos === -1) return [part.trim(), []];\n const filtersText = part.slice(pos + 1).trim();\n let filters = cache.get(filtersText);\n if (filters === undefined) {\n filters = parseFilters(splitOutsideQuotes(filtersText, FILTER_SEPARATOR).map(trimFn), filterIOType, part);\n cache.set(filtersText, filters);\n }\n return [part.slice(0, pos).trim(), filters];\n}\n","import { DELIMITER, MAX_PATH_SEGMENTS, RECURSION_WILDCARD } from \"./define\";\nimport { splitFilters } from \"./parseFilters\";\nimport { raise, M } from \"../messages\";\nimport { ParsedBinding, ParsedFilter } from \"./types\";\n\n// 解析の段の形(フィルタは名前と引数だけ — 実関数はエンジンが引く。要件 D16)。\n// `@wcstack/state` はここで `statePathInfo`(`getPathInfo` の intern 結果)も返していたが、\n// 新エンジンはパスを自分で解決するので文字列だけを返す。\nexport type StatePartParseResult = Pick<ParsedBinding, 'statePathName' | 'outFilters'>;\n\n/**\n * 出力フィルタ列の解析結果のキャッシュ(鍵は `|` より後ろの原文)。同じ原文は**同じ配列**を返す —\n * 消費側は返された `outFilters` を変更しないこと。落ちた解析は載らない。\n * (`@wcstack/state` の tooling 専用の解放口 `clearStatePartCacheForTooling` は移植しない)\n */\nconst cacheFilterInfos = new Map<string, ParsedFilter[]>();\n/** Tooling (`clearParserCaches`): a long-running process drops what it parsed. */\nexport const clearStatePartCache = (): void => cacheFilterInfos.clear();\n\n/**\n * `getPathInfo` が初回 intern で行っていた文字列だけで決まる検査の移植(順序も同じ:\n * `**` → セグメント数)。`getPathInfo` は `**` のパスを intern しないので毎回落ち、\n * 上限超えのパスも intern されないので毎回落ちる — 状態を持たない検査と同値。\n */\nfunction checkPathLikeGetPathInfo(path: string): void {\n if (path.includes(RECURSION_WILDCARD)) {\n recursionUnsupported(path);\n }\n const segmentCount = path.split(DELIMITER).length;\n if (segmentCount > MAX_PATH_SEGMENTS) {\n raise(M.TooManySegments, [path, segmentCount]);\n }\n}\n\n// format: statePath|filter|filter\n// statePath-format: path.to.property (e.g., user.name.first, users.*.name, users.0.name, not include @)\n// filters-format: filterName or filterName(arg1,arg2)\n\n/** Port of `@wcstack/state` `src/bindTextParser/parseStatePart.ts` (no `statePathInfo`). */\n/** `**` outside the places a `$recursion` declaration gives it meaning. */\nexport function recursionUnsupported(path: string): never {\n raise(M.RecursionUnsupported, [path]);\n}\n\nexport function parseStatePart(statePart: string): StatePartParseResult {\n const [stateAndPath, filters] = splitFilters(statePart, \"output\", cacheFilterInfos);\n if (stateAndPath.includes(\"@\")) {\n // 名前次元は v2 で撤去(docs/state-mount-design.md D16 / §9)。パスは 1 本のツリー。\n raise(M.SelectorRemoved, [stateAndPath]);\n }\n const statePathName = stateAndPath;\n // 右辺も左辺(`parsePropPart`)と同じ規準で空セグメントを弾く(要件 B1)。\n //\n // **判定の前にループ相対の短縮形を正規化する。** `.` で始まる右辺は `for` 行の相対パスで\n // (展開はエンジンの仕事 — パーサは展開前の原文をそのまま返す)、先頭の空セグメント 1 つは正当。\n // とくに **`.` 単独は「行そのもの」を指す正規の書き方**(`state: .`)— 「先頭は許すが末尾は拒否」と\n // 素朴に書くと `\".\"` は `[\"\", \"\"]` = 先頭かつ末尾なので落ちる。取り除いた残りが空でも通すこと\n const isLoopRelative = statePathName.startsWith(DELIMITER);\n const body = isLoopRelative ? statePathName.slice(DELIMITER.length) : statePathName;\n const hasEmptySegment = body.length > 0 && body.split(DELIMITER).some((segment) => segment.length === 0);\n if (hasEmptySegment || (!isLoopRelative && body.length === 0)) {\n raise(M.EmptySegment, [statePart]);\n }\n checkPathLikeGetPathInfo(statePathName);\n return {\n statePathName,\n outFilters: filters,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var r={};function t(r,t){return null==r?t:(...e)=>{r(...e),t(...e)}}function e(r,t,e){return null==t?e:(...o)=>{let a=t(...o);return r(a)?a:e(...o)}}var o=r=>!0===r,a=r=>void 0!==r,n=r=>null!=r,s=new Set;function f(t){for(let e of t)if(!s.has(e.name)){if(e.hooks!==r)throw new Error(`[@wcstack/state] [wcs/feature-foreign] The add-on "${e.name}" is from another copy of @wcstack/state (another version, or another URL): load the core and its add-ons from one build`);s.add(e.name),e.install()}}function i(t){let e=t.$features;if(null!=r
|
|
2
|
-
//# sourceMappingURL=chunk-
|
|
1
|
+
var r={};function t(r,t){return null==r?t:(...e)=>{r(...e),t(...e)}}function e(r,t,e){return null==t?e:(...o)=>{let a=t(...o);return r(a)?a:e(...o)}}var o=r=>!0===r,a=r=>void 0!==r,n=r=>null!=r,s=new Set;function f(t){for(let e of t)if(!s.has(e.name)){if(e.hooks!==r)throw new Error(`[@wcstack/state] [wcs/feature-foreign] The add-on "${e.name}" is from another copy of @wcstack/state (another version, or another URL): load the core and its add-ons from one build`);s.add(e.name),e.install()}}function i(t){let e=t.$features;if(null!=r.$t&&Array.isArray(e)){let t=e.filter(r=>!s.has(r));if(t.length>0)return r.$t(t)}}function c(r,t){if(!s.has(r))throw new Error(`[@wcstack/state] [wcs/feature-not-installed] ${t} needs the add-on @wcstack/state/features/${r}`)}function u(t,e,o){throw new Error(`[@wcstack/state] ${t}${r.Vo?.(t,e,o)??""}`)}function l(r,t,...e){"function"!=typeof reportError?console.error(...void 0===t?[r]:[t,r],...e):reportError(void 0===t?r:new Error(`${t} ${r}`,{cause:r}))}export{r as a,t as b,e as c,o as d,a as e,n as f,f as g,i as h,c as i,u as j,l as k};
|
|
2
|
+
//# sourceMappingURL=chunk-LPJFTEVT.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var t=class{constructor(t,l,e){this.u=[],this.getter=null,this.ce=null,this.ue=!1,this.M=[],this.Z=[],this.yt=null,this.O=-1,this.G=s,this.je=null,this.Bt=null,this.Wt=null,this.V=null,this.mn=!1,this.hn=!1,this.gn=!1,this.ee=0,this.wt=new Set,this.t=t,this.c=e,this.s=l;let i=null===e?[null]:e.h.slice(),h="*"===l;h&&i.push(e),this.n=i.length-1,this.Y=h?[]:null===e?[l]:[...e.Y,l],this.h=i}Hn(t){this.wt.has(t)||(this.wt.add(t),this.M.push(t),t.Z.push(this))}Wo(t){this.wt.delete(t);let s=this.M;s.splice(s.indexOf(t),1)}Mo(){this.getter=null,this.ce=null,this.O=-1,this.G=s,this.M.length=0,this.wt.clear(),this.Z.length=0,this.yt=null,this.je=null,this.Bt=null,this.Wt=null,this.V=null}te(t){let s=this;for(;null!==s;){if(s===t)return!0;s=s.c}return!1}},s=Symbol("unset"),l=Symbol("dirty"),e=Symbol("failed"),i=class{constructor(t=null){this.bt=new Map,this.Un=t}vt(t){return this.bt.get(t)}get(s){let l=this.bt.get(s);if(void 0!==l)return l;let e=s.lastIndexOf("."),i=e<0?null:this.get(s.slice(0,e));return l=new t(s,s.slice(e+1),i),this.Un?.(l),this.bt.set(s,l),i&&i.u.push(l),l}all(){return this.bt.values()}Mt(t){this.bt.delete(t.t)}},h=new Map;function n(t){let s=h.get(t);if(void 0!==s)return s;let l=!0,e=t.split("."),i=[];for(let t=0;t<e.length;t++){let s=e[t],h=s.charCodeAt(0);t>0&&h>=48&&h<=57?(l=!1,i.push(Number(s)),e[t]="*"):"*"===s&&i.push(-1)}if(!l)return{o:e.join("."),indexes:i};let n={o:t,indexes:null};return h.size>4095&&h.clear(),h.set(t,n),n}export{s as a,l as b,e as c,i as d,n as e};
|
|
2
|
+
//# sourceMappingURL=chunk-NAV7FBTI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Pattern","constructor","path","last","parent","this","children","getter","setter","underGetter","dependents","sources","crossSources","slot","rootValue","UNSET","eqIndexWatchers","eqIndexKeys","indexWatchers","eqSubs","pinned","dead","markup","mark","dependentSet","Set","lists","slice","w","push","depth","length","tail","addDependent","has","add","dropDependent","delete","d","splice","indexOf","forget","clear","isUnder","ancestor","p","Symbol","DIRTY","FAILED","PatternTable","onCreate","byPath","Map","peek","get","i","lastIndexOf","set","all","values","drop","literalCache","parsePath","cached","literal","segs","split","indexes","s","c","charCodeAt","Number","pattern","join","parsed","size","P","f","g"],"sources":["../../../src/pattern.ts"],"sourcesContent":["/**\n * Path patterns.\n *\n * A pattern is the authoring-level path with every list position written as `*`\n * (`data.*.label`). Each engine interns its patterns once; everything at run time\n * refers to the Pattern object, never to a path string. A concrete location is a\n * pattern plus the row that owns its last wildcard — there is no address object.\n */\n\nexport const WILDCARD = \"*\";\n\nexport class Pattern {\n readonly path: string;\n readonly parent: Pattern | null;\n readonly last: string;\n /** Number of `*` segments. 0 = a location on the root, n = a location inside a depth-n row. */\n readonly depth: number;\n /** Segments after the last `*` (all segments when depth is 0). Read from the row item / the root. */\n readonly tail: readonly string[];\n /** `lists[k]` is the list pattern whose rows the k-th wildcard (1-based) ranges over. */\n readonly lists: readonly (Pattern | null)[];\n children: Pattern[] = [];\n\n // --- filled in by the engine ---\n getter: (() => unknown) | null = null;\n setter: ((value: unknown) => void) | null = null;\n /** true when some proper ancestor is an accessor (read through it instead of walking data). */\n underGetter = false;\n /** Getter patterns whose evaluation read this pattern. */\n readonly dependents: Pattern[] = [];\n /** Patterns this getter read (union over its evaluations). */\n sources: Pattern[] = [];\n /** Sources read from a row other than the evaluating row's own chain (fan out on change). */\n crossSources: Set<Pattern> | null = null;\n /** Cache slot of a row-level getter on its rows. -1 when not a row-level getter. */\n slot = -1;\n /** Root-level getter cache (depth 0). */\n rootValue: unknown = UNSET;\n /** `$eqIndex(this path)` watchers: getters keyed on the index of their row at `level`. */\n eqIndexWatchers: { getter: Pattern; level: number }[] | null = null;\n /** On a list pattern: the `$eqIndex` registrations over its rows (re-keyed on reorder). */\n eqIndexKeys: { source: Pattern; getter: Pattern }[] | null = null;\n /** On a list pattern: getters that read the index (`$k`) of this list's rows. */\n indexWatchers: Pattern[] | null = null;\n /** `$eq(this path, key)` subscriptions: getter occurrences keyed by the value they wait for. */\n eqSubs: Map<unknown, Set<EqSub>> | null = null;\n /**\n * Something outside a path's read or write holds it (a binding, a list, an add-on: Engine.pattern):\n * never swept. A pattern only a path made (`this[\"users.\" + id]`) goes when it holds nothing (Engine.sweep).\n */\n pinned = false;\n /** Swept: out of the table (a later use of its path makes a new one). */\n dead = false;\n /** Its accessor is the engine's own for an index path (Engine.markupAccessor), not the author's or an add-on's. */\n markup = false;\n /** Scratch of Engine.prune: the evaluation that read it. */\n mark = 0;\n\n private readonly dependentSet = new Set<Pattern>();\n\n constructor(path: string, last: string, parent: Pattern | null) {\n this.path = path;\n this.parent = parent;\n this.last = last;\n // the parent's list table, plus our own when we are a wildcard segment\n const lists: (Pattern | null)[] = parent === null ? [null] : parent.lists.slice();\n const w = last === WILDCARD;\n if (w) lists.push(parent);\n this.depth = lists.length - 1;\n this.tail = w ? [] : parent === null ? [last] : [...parent.tail, last];\n this.lists = lists;\n }\n\n addDependent(getter: Pattern): void {\n if (this.dependentSet.has(getter)) return;\n this.dependentSet.add(getter);\n this.dependents.push(getter);\n getter.sources.push(this);\n }\n\n /** `getter` reads this no more (its side, `sources`, is the caller's). */\n dropDependent(getter: Pattern): void {\n this.dependentSet.delete(getter);\n const d = this.dependents;\n d.splice(d.indexOf(getter), 1);\n }\n\n /** A re-set replaced the state: forget its accessors and everything learned from them. */\n forget(): void {\n this.getter = null;\n this.setter = null;\n this.slot = -1;\n this.rootValue = UNSET;\n this.dependents.length = 0;\n this.dependentSet.clear();\n this.sources.length = 0;\n this.crossSources = null;\n this.eqIndexWatchers = null;\n this.eqIndexKeys = null;\n this.indexWatchers = null;\n this.eqSubs = null;\n }\n\n /** true when `this` is `ancestor` or lies under it. */\n isUnder(ancestor: Pattern): boolean {\n let p: Pattern | null = this;\n while (p !== null) {\n if (p === ancestor) return true;\n p = p.parent;\n }\n return false;\n }\n}\n\n/** One getter occurrence subscribed under a key of a `$eq` source. */\nexport interface EqSub {\n getter: Pattern;\n row: import(\"./list\").StateRow | null;\n}\n\n/** Sentinel for \"no cached value\". */\nexport const UNSET: unique symbol = Symbol(\"unset\") as never;\n/** Sentinel for \"cached value is stale\" (dirty strategy). */\nexport const DIRTY: unique symbol = Symbol(\"dirty\") as never;\n/**\n * Sentinel for \"evaluated, but it threw\" (or stale with its readers dropped by a cut drain):\n * someone read it, so a change of its sources must reach it.\n */\nexport const FAILED: unique symbol = Symbol(\"failed\") as never;\n\nexport class PatternTable {\n private readonly byPath = new Map<string, Pattern>();\n private readonly onCreate: ((p: Pattern) => void) | null;\n\n constructor(onCreate: ((p: Pattern) => void) | null = null) {\n this.onCreate = onCreate;\n }\n\n peek(path: string): Pattern | undefined {\n return this.byPath.get(path);\n }\n\n get(path: string): Pattern {\n let p = this.byPath.get(path);\n if (p !== undefined) return p;\n const i = path.lastIndexOf(\".\");\n const parent = i < 0 ? null : this.get(path.slice(0, i));\n p = new Pattern(path, path.slice(i + 1), parent);\n this.onCreate?.(p);\n this.byPath.set(path, p);\n if (parent) parent.children.push(p);\n return p;\n }\n\n all(): IterableIterator<Pattern> {\n return this.byPath.values();\n }\n\n drop(p: Pattern): void {\n this.byPath.delete(p.path);\n }\n}\n\n/**\n * A concrete path (`data.3.label`, `data.*.label`, `selectedIndex`) split into its\n * pattern and the explicit indexes it carries. `*` segments take their index from the\n * evaluation context, so they are returned as `-1`. A leading numeric segment is a key of\n * the root (`2024.total`), never an index: the root is not a list.\n */\nexport interface ParsedPath {\n pattern: string;\n indexes: number[] | null;\n}\n\nconst literalCache = new Map<string, ParsedPath>();\n\nexport function parsePath(path: string): ParsedPath {\n const cached = literalCache.get(path);\n if (cached !== undefined) return cached;\n let literal = true;\n const segs = path.split(\".\");\n const indexes: number[] = [];\n for (let i = 0; i < segs.length; i++) {\n const s = segs[i];\n const c = s.charCodeAt(0);\n if (i > 0 && c >= 48 && c <= 57) {\n literal = false;\n indexes.push(Number(s));\n segs[i] = WILDCARD;\n } else if (s === WILDCARD) indexes.push(-1);\n }\n if (!literal) return { pattern: segs.join(\".\"), indexes };\n const parsed: ParsedPath = { pattern: path, indexes: null };\n // literal paths (no explicit index) are few and reused: keep them — up to a bound, as a key built\n // from data (`this[\"users.\" + id]`) makes a new one each time\n if (literalCache.size > 4095) literalCache.clear();\n literalCache.set(path, parsed);\n return parsed;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["Pattern","constructor","path","last","parent","this","children","getter","setter","underGetter","dependents","sources","crossSources","slot","rootValue","UNSET","eqIndexWatchers","eqIndexKeys","indexWatchers","eqSubs","pinned","dead","markup","mark","dependentSet","Set","lists","slice","w","push","depth","length","tail","addDependent","has","add","dropDependent","delete","d","splice","indexOf","forget","clear","isUnder","ancestor","p","Symbol","DIRTY","FAILED","PatternTable","onCreate","byPath","Map","peek","get","i","lastIndexOf","set","all","values","drop","literalCache","parsePath","cached","literal","segs","split","indexes","s","c","charCodeAt","Number","pattern","join","parsed","size","P","f","g"],"sources":["../../../src/pattern.ts"],"sourcesContent":["/**\n * Path patterns.\n *\n * A pattern is the authoring-level path with every list position written as `*`\n * (`data.*.label`). Each engine interns its patterns once; everything at run time\n * refers to the Pattern object, never to a path string. A concrete location is a\n * pattern plus the row that owns its last wildcard — there is no address object.\n */\n\nexport const WILDCARD = \"*\";\n\nexport class Pattern {\n readonly path: string;\n readonly parent: Pattern | null;\n readonly last: string;\n /** Number of `*` segments. 0 = a location on the root, n = a location inside a depth-n row. */\n readonly depth: number;\n /** Segments after the last `*` (all segments when depth is 0). Read from the row item / the root. */\n readonly tail: readonly string[];\n /** `lists[k]` is the list pattern whose rows the k-th wildcard (1-based) ranges over. */\n readonly lists: readonly (Pattern | null)[];\n children: Pattern[] = [];\n\n // --- filled in by the engine ---\n getter: (() => unknown) | null = null;\n setter: ((value: unknown) => void) | null = null;\n /** true when some proper ancestor is an accessor (read through it instead of walking data). */\n underGetter = false;\n /** Getter patterns whose evaluation read this pattern. */\n readonly dependents: Pattern[] = [];\n /** Patterns this getter read (union over its evaluations). */\n sources: Pattern[] = [];\n /** Sources read from a row other than the evaluating row's own chain (fan out on change). */\n crossSources: Set<Pattern> | null = null;\n /** Cache slot of a row-level getter on its rows. -1 when not a row-level getter. */\n slot = -1;\n /** Root-level getter cache (depth 0). */\n rootValue: unknown = UNSET;\n /** `$eqIndex(this path)` watchers: getters keyed on the index of their row at `level`. */\n eqIndexWatchers: { getter: Pattern; level: number }[] | null = null;\n /** On a list pattern: the `$eqIndex` registrations over its rows (re-keyed on reorder). */\n eqIndexKeys: { source: Pattern; getter: Pattern }[] | null = null;\n /** On a list pattern: getters that read the index (`$k`) of this list's rows. */\n indexWatchers: Pattern[] | null = null;\n /** `$eq(this path, key)` subscriptions: getter occurrences keyed by the value they wait for. */\n eqSubs: Map<unknown, Set<EqSub>> | null = null;\n /**\n * Something outside a path's read or write holds it (a binding, a list, an add-on: Engine.pattern):\n * never swept. A pattern only a path made (`this[\"users.\" + id]`) goes when it holds nothing (Engine.sweep).\n */\n pinned = false;\n /** Swept: out of the table (a later use of its path makes a new one). */\n dead = false;\n /** Its accessor is the engine's own for an index path (Engine.markupAccessor), not the author's or an add-on's. */\n markup = false;\n /** Scratch of Engine.prune: the evaluation that read it. */\n mark = 0;\n\n private readonly dependentSet = new Set<Pattern>();\n\n constructor(path: string, last: string, parent: Pattern | null) {\n this.path = path;\n this.parent = parent;\n this.last = last;\n // the parent's list table, plus our own when we are a wildcard segment\n const lists: (Pattern | null)[] = parent === null ? [null] : parent.lists.slice();\n const w = last === WILDCARD;\n if (w) lists.push(parent);\n this.depth = lists.length - 1;\n this.tail = w ? [] : parent === null ? [last] : [...parent.tail, last];\n this.lists = lists;\n }\n\n addDependent(getter: Pattern): void {\n if (this.dependentSet.has(getter)) return;\n this.dependentSet.add(getter);\n this.dependents.push(getter);\n getter.sources.push(this);\n }\n\n /** `getter` reads this no more (its side, `sources`, is the caller's). */\n dropDependent(getter: Pattern): void {\n this.dependentSet.delete(getter);\n const d = this.dependents;\n d.splice(d.indexOf(getter), 1);\n }\n\n /** A re-set replaced the state: forget its accessors and everything learned from them. */\n forget(): void {\n this.getter = null;\n this.setter = null;\n this.slot = -1;\n this.rootValue = UNSET;\n this.dependents.length = 0;\n this.dependentSet.clear();\n this.sources.length = 0;\n this.crossSources = null;\n this.eqIndexWatchers = null;\n this.eqIndexKeys = null;\n this.indexWatchers = null;\n this.eqSubs = null;\n }\n\n /** true when `this` is `ancestor` or lies under it. */\n isUnder(ancestor: Pattern): boolean {\n let p: Pattern | null = this;\n while (p !== null) {\n if (p === ancestor) return true;\n p = p.parent;\n }\n return false;\n }\n}\n\n/** One getter occurrence subscribed under a key of a `$eq` source. */\nexport interface EqSub {\n getter: Pattern;\n row: import(\"./list\").StateRow | null;\n}\n\n/** Sentinel for \"no cached value\". */\nexport const UNSET: unique symbol = Symbol(\"unset\") as never;\n/** Sentinel for \"cached value is stale\" (dirty strategy). */\nexport const DIRTY: unique symbol = Symbol(\"dirty\") as never;\n/**\n * Sentinel for \"evaluated, but it threw\" (or stale with its readers dropped by a cut drain):\n * someone read it, so a change of its sources must reach it.\n */\nexport const FAILED: unique symbol = Symbol(\"failed\") as never;\n\nexport class PatternTable {\n private readonly byPath = new Map<string, Pattern>();\n private readonly onCreate: ((p: Pattern) => void) | null;\n\n constructor(onCreate: ((p: Pattern) => void) | null = null) {\n this.onCreate = onCreate;\n }\n\n peek(path: string): Pattern | undefined {\n return this.byPath.get(path);\n }\n\n get(path: string): Pattern {\n let p = this.byPath.get(path);\n if (p !== undefined) return p;\n const i = path.lastIndexOf(\".\");\n const parent = i < 0 ? null : this.get(path.slice(0, i));\n p = new Pattern(path, path.slice(i + 1), parent);\n this.onCreate?.(p);\n this.byPath.set(path, p);\n if (parent) parent.children.push(p);\n return p;\n }\n\n all(): IterableIterator<Pattern> {\n return this.byPath.values();\n }\n\n drop(p: Pattern): void {\n this.byPath.delete(p.path);\n }\n}\n\n/**\n * A concrete path (`data.3.label`, `data.*.label`, `selectedIndex`) split into its\n * pattern and the explicit indexes it carries. `*` segments take their index from the\n * evaluation context, so they are returned as `-1`. A leading numeric segment is a key of\n * the root (`2024.total`), never an index: the root is not a list.\n */\nexport interface ParsedPath {\n pattern: string;\n indexes: number[] | null;\n}\n\nconst literalCache = new Map<string, ParsedPath>();\n\nexport function parsePath(path: string): ParsedPath {\n const cached = literalCache.get(path);\n if (cached !== undefined) return cached;\n let literal = true;\n const segs = path.split(\".\");\n const indexes: number[] = [];\n for (let i = 0; i < segs.length; i++) {\n const s = segs[i];\n const c = s.charCodeAt(0);\n if (i > 0 && c >= 48 && c <= 57) {\n literal = false;\n indexes.push(Number(s));\n segs[i] = WILDCARD;\n } else if (s === WILDCARD) indexes.push(-1);\n }\n if (!literal) return { pattern: segs.join(\".\"), indexes };\n const parsed: ParsedPath = { pattern: path, indexes: null };\n // literal paths (no explicit index) are few and reused: keep them — up to a bound, as a key built\n // from data (`this[\"users.\" + id]`) makes a new one each time\n if (literalCache.size > 4095) literalCache.clear();\n literalCache.set(path, parsed);\n return parsed;\n}\n"],"mappings":"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","ignoreList":[]}
|