@wcstack/state 3.1.0 → 3.3.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.
Files changed (56) hide show
  1. package/README.ja.md +128 -90
  2. package/README.md +129 -91
  3. package/dist/auto.min.js +1 -1
  4. package/dist/auto.min.js.map +1 -1
  5. package/dist/define.d.ts +11 -7
  6. package/dist/index.d.ts +58 -15
  7. package/dist/index.esm.js +1 -1
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/manifest.d.ts +39 -5
  10. package/dist/manifest.esm.js +315 -253
  11. package/dist/parser.d.ts +16 -2
  12. package/dist/parser.esm.js +223 -50
  13. package/dist/split/chunks/binder.js +1 -1
  14. package/dist/split/chunks/binder.js.map +1 -1
  15. package/dist/split/chunks/checkDependency.js +1 -1
  16. package/dist/split/chunks/declarationAliases.js +2 -0
  17. package/dist/split/chunks/declarationAliases.js.map +1 -0
  18. package/dist/split/chunks/declarationHooks.js +2 -0
  19. package/dist/split/chunks/declarationHooks.js.map +1 -0
  20. package/dist/split/chunks/featureBridge.js +2 -0
  21. package/dist/split/chunks/featureBridge.js.map +1 -0
  22. package/dist/split/chunks/filterRegistry.js +1 -1
  23. package/dist/split/chunks/filterRegistry.js.map +1 -1
  24. package/dist/split/chunks/getAllPropertyDescriptors.js +1 -1
  25. package/dist/split/chunks/getAllPropertyDescriptors.js.map +1 -1
  26. package/dist/split/chunks/lifecycleHooks.js +1 -1
  27. package/dist/split/chunks/pathDiagnostics.js +1 -1
  28. package/dist/split/chunks/pathDiagnostics.js.map +1 -1
  29. package/dist/split/chunks/registerComponents.js +1 -1
  30. package/dist/split/chunks/registerComponents.js.map +1 -1
  31. package/dist/split/chunks/setAll.js +1 -1
  32. package/dist/split/chunks/setAll.js.map +1 -1
  33. package/dist/split/chunks/version.js +1 -1
  34. package/dist/split/core.d.ts +21 -9
  35. package/dist/split/core.js +1 -1
  36. package/dist/split/core.js.map +1 -1
  37. package/dist/split/features/devtools.js +1 -1
  38. package/dist/split/features/devtools.js.map +1 -1
  39. package/dist/split/features/diagnostics.js +1 -1
  40. package/dist/split/features/diagnostics.js.map +1 -1
  41. package/dist/split/features/formats.js +1 -1
  42. package/dist/split/features/formats.js.map +1 -1
  43. package/dist/split/features/recursion.js +1 -1
  44. package/dist/split/features/recursion.js.map +1 -1
  45. package/dist/split/features/scopes.js +1 -1
  46. package/dist/split/features/scopes.js.map +1 -1
  47. package/dist/split/features/ssr.js +1 -1
  48. package/dist/split/features/ssr.js.map +1 -1
  49. package/dist/split/features/temporal.js +1 -1
  50. package/dist/split/features/temporal.js.map +1 -1
  51. package/dist/wcs-manifest.json +98 -44
  52. package/package.json +1 -1
  53. package/dist/split/chunks/mount.js +0 -2
  54. package/dist/split/chunks/mount.js.map +0 -1
  55. package/dist/split/chunks/watchRuntime.js +0 -2
  56. package/dist/split/chunks/watchRuntime.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import{aD as t,I as a}from"./binder.js";function n(n,l){if(!n.untracking&&n.addressStackLength>0){const d=n.lastAddressStack,o=d?.pathInfo??null,s=n.stateElement;if(null!==o&&s.getterPaths.has(o.path)&&o.path!==l.pathInfo.path&&(s.addDynamicDependency(l.pathInfo.path,o.path),l.pathInfo.wildcardCount>0&&o.wildcardCount>0)){const n=t(l.pathInfo,o);if(n>0){let t=!1;const e=l.listIndex??null,i=d.listIndex??null;for(let d=0;d<n;d++){if((null!==e?a(e,d,l.pathInfo.wildcardCount):null)!==(null!==i?a(i,d,o.wildcardCount):null)){t=!0;break}}if(t)for(let t=0;t<n;t++)s.addCrossRowListPath?.(l.pathInfo.wildcardParentPaths[t])}}}}export{n as c};
1
+ import{aH as t,m as a}from"./binder.js";function n(n,l){if(!n.untracking&&n.addressStackLength>0){const d=n.lastAddressStack,o=d?.pathInfo??null,s=n.stateElement;if(null!==o&&s.getterPaths.has(o.path)&&o.path!==l.pathInfo.path&&(s.addDynamicDependency(l.pathInfo.path,o.path),l.pathInfo.wildcardCount>0&&o.wildcardCount>0)){const n=t(l.pathInfo,o);if(n>0){let t=!1;const e=l.listIndex??null,i=d.listIndex??null;for(let d=0;d<n;d++){if((null!==e?a(e,d,l.pathInfo.wildcardCount):null)!==(null!==i?a(i,d,o.wildcardCount):null)){t=!0;break}}if(t)for(let t=0;t<n;t++)s.addCrossRowListPath?.(l.pathInfo.wildcardParentPaths[t])}}}}export{n as c};
2
2
  //# sourceMappingURL=checkDependency.js.map
@@ -0,0 +1,2 @@
1
+ import{a as e,o as t}from"./pathDiagnostics.js";import{r as o,L as n}from"./errorGuidance.js";const s={$updatedCallback:t,$streams:e},a=new WeakSet;function r(e,t){let o=e;for(;null!==o&&!Object.prototype.hasOwnProperty.call(o,t);)o=Object.getPrototypeOf(o);return o}function c(e){if((null===e||"object"!=typeof e&&"function"!=typeof e)&&o(`The state must be an object, got ${null===e?"null":typeof e}. Check the source of the state element (json / src / the inline <script>).`),!a.has(e)){for(const t of Object.keys(s)){if(!(t in e))continue;const a=s[t];a in e&&o(`[wcs/declaration-alias] The state declares both "${t}" and "${a}". "${t}" is the old name of "${a}" (it works through 3.x) — keep "${a}".${n}`),Object.isExtensible(e)||o(`[wcs/declaration-alias] The state is not extensible, so the old name "${t}" cannot be rewritten to "${a}". Declare "${a}" directly (the old name works through 3.x only on an extensible state).${n}`);const c=r(e,t),i=Object.getOwnPropertyDescriptor(c,t);Object.defineProperty(e,a,{...i,configurable:!0}),c===e&&delete e[t]}a.add(e)}}export{c as n};
2
+ //# sourceMappingURL=declarationAliases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declarationAliases.js","sources":["../../../../../src/declarationAliases.ts"],"sourcesContent":["/**\n * declarationAliases.ts — 宣言キーの旧名 → 正式名(要件 B12・docs/state-3x-naming.ja.md V13 / V14)。\n *\n * `$updatedCallback` → `$renderedCallback`、`$streams` → `$stream`。旧名は 3.x の間は受け、4.0 で外す(D4)。\n * state オブジェクトがランタイムに入る入口(State の `_state` と `_loadStateFromSource`、マウント記録)で\n * 1 回だけ正規化し、以降のすべての読み手は正式名だけを見る。両方の綴りを宣言したらどちらが効くのか\n * 書き手に見えないので、名指しで落とす(D38)。\n */\nimport { STATE_STREAM_NAME, STATE_RENDERED_CALLBACK_NAME } from \"./define\";\nimport { LINT_HINT } from \"./errorGuidance\";\nimport { raiseError } from \"./raiseError\";\n\nexport const DECLARATION_ALIASES: Readonly<Record<string, string>> = {\n $updatedCallback: STATE_RENDERED_CALLBACK_NAME,\n $streams: STATE_STREAM_NAME,\n};\n\n/** 正規化済みの state オブジェクト(同じオブジェクトの再セット・ボリュームの 2 つの入口で二重に処理しない) */\nconst normalizedStates = new WeakSet<object>();\n\nfunction findOwner(value: object, key: string): object {\n let owner: object | null = value;\n while (owner !== null && !Object.prototype.hasOwnProperty.call(owner, key)) {\n owner = Object.getPrototypeOf(owner);\n }\n return owner!;\n}\n\n/**\n * 旧名で宣言されたキーを正式名へ写す。自前のプロパティなら旧名は消す。class の state でメソッドが\n * プロトタイプにある形(`$updatedCallback() {}`)は、インスタンスに正式名の定義を足すだけにする。\n */\nexport function normalizeDeclarationAliases(state: object): void {\n // state の出どころ(`src=\"./x.json\"` / `<script type=\"application/json\">` / インライン script)は\n // オブジェクト以外も返しうる(`JSON.parse(\"null\")` は `typeof` が \"object\")。ここは state が\n // ランタイムに入る最初の関門なので、`in` 演算子の素の TypeError ではなく形を名指しで落とす\n if (state === null || (typeof state !== \"object\" && typeof state !== \"function\")) {\n raiseError(\n `The state must be an object, got ${state === null ? \"null\" : typeof state}. ` +\n `Check the source of the state element (json / src / the inline <script>).`,\n );\n }\n if (normalizedStates.has(state)) {\n return;\n }\n for (const alias of Object.keys(DECLARATION_ALIASES)) {\n if (!(alias in state)) {\n continue;\n }\n const canonical = DECLARATION_ALIASES[alias];\n if (canonical in state) {\n raiseError(\n `[wcs/declaration-alias] The state declares both \"${alias}\" and \"${canonical}\". ` +\n `\"${alias}\" is the old name of \"${canonical}\" (it works through 3.x) — keep \"${canonical}\".${LINT_HINT}`,\n );\n }\n if (!Object.isExtensible(state)) {\n // 凍結・封印された state には正式名を足せない(`Object.defineProperty` が\n // \"object is not extensible\" で落ちる)。3.1 まで旧名のまま動いていた形なので、\n // 素の TypeError ではなく「正式名に書き換えよ」と名指しで案内する\n raiseError(\n `[wcs/declaration-alias] The state is not extensible, so the old name \"${alias}\" cannot be ` +\n `rewritten to \"${canonical}\". Declare \"${canonical}\" directly (the old name works through 3.x ` +\n `only on an extensible state).${LINT_HINT}`,\n );\n }\n const owner = findOwner(state, alias);\n const descriptor = Object.getOwnPropertyDescriptor(owner, alias)!;\n Object.defineProperty(state, canonical, { ...descriptor, configurable: true });\n if (owner === state) {\n delete (state as Record<string, unknown>)[alias];\n }\n }\n normalizedStates.add(state);\n}\n"],"names":["DECLARATION_ALIASES","$updatedCallback","STATE_RENDERED_CALLBACK_NAME","$streams","STATE_STREAM_NAME","normalizedStates","WeakSet","findOwner","value","key","owner","Object","prototype","hasOwnProperty","call","getPrototypeOf","normalizeDeclarationAliases","state","raiseError","has","alias","keys","canonical","LINT_HINT","isExtensible","descriptor","getOwnPropertyDescriptor","defineProperty","configurable","add"],"mappings":"8FAYO,MAAMA,EAAwD,CACnEC,iBAAkBC,EAClBC,SAAUC,GAINC,EAAmB,IAAIC,QAE7B,SAASC,EAAUC,EAAeC,GAChC,IAAIC,EAAuBF,EAC3B,KAAiB,OAAVE,IAAmBC,OAAOC,UAAUC,eAAeC,KAAKJ,EAAOD,IACpEC,EAAQC,OAAOI,eAAeL,GAEhC,OAAOA,CACT,CAMM,SAAUM,EAA4BC,GAU1C,IANc,OAAVA,GAAoC,iBAAVA,GAAuC,mBAAVA,IACzDC,EACE,oCAA8C,OAAVD,EAAiB,cAAgBA,iFAIrEZ,EAAiBc,IAAIF,GAAzB,CAGA,IAAK,MAAMG,KAAST,OAAOU,KAAKrB,GAAsB,CACpD,KAAMoB,KAASH,GACb,SAEF,MAAMK,EAAYtB,EAAoBoB,GAClCE,KAAaL,GACfC,EACE,oDAAoDE,WAAeE,QAC/DF,0BAA8BE,qCAA6CA,MAAcC,KAG5FZ,OAAOa,aAAaP,IAIvBC,EACE,yEAAyEE,8BACxDE,gBAAwBA,4EACTC,KAGpC,MAAMb,EAAQH,EAAUU,EAAOG,GACzBK,EAAad,OAAOe,yBAAyBhB,EAAOU,GAC1DT,OAAOgB,eAAeV,EAAOK,EAAW,IAAKG,EAAYG,cAAc,IACnElB,IAAUO,UACJA,EAAkCG,EAE9C,CACAf,EAAiBwB,IAAIZ,EA7BrB,CA8BF"}
@@ -0,0 +1,2 @@
1
+ function t(){const t=new Map;return{get:e=>t.get(e),set(e,n){t.set(e,n)}}}const e=new Map;let n=[],a=[];function r(t,r){e.set(t,r),n=Array.from(e.values()).sort((t,e)=>t.order-e.order),a=n.slice().reverse()}function o(t){return e.has(t)}function l(t,e,a){for(let r=0;r<n.length;r++)n[r].validateEarly?.(t,e,a)}function s(t,e,a){for(let r=0;r<n.length;r++)n[r].preCommit?.(t,e,a)}function f(t,e,a){for(let r=0;r<n.length;r++)n[r].validate?.(t,e,a)}function i(t,e,a){for(let r=0;r<n.length;r++)n[r].applyEarly?.(t,e,a)}function c(t,e,a){for(let r=0;r<n.length;r++)n[r].apply?.(t,e,a)}function u(t,e,a){for(let r=0;r<n.length;r++)n[r].register?.(t,e,a)}function g(t,e){for(let a=0;a<n.length;a++)n[a].activate?.(t,e)}function h(t){for(let e=0;e<a.length;e++)a[e].deactivate?.(t)}export{l as a,f as b,s as c,i as d,c as e,u as f,g,h,t as i,o as j,r};
2
+ //# sourceMappingURL=declarationHooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declarationHooks.js","sources":["../../../../../src/core/declarationHooks.ts"],"sourcesContent":["/**\n * core/declarationHooks.ts — 宣言の受け口(設計案 H4、S4)。\n *\n * `_state` セッターはこのパッケージで最も順序に敏感なコードで、どの検証が世代を進める前に走り\n * どれが後かがそのままテスト(`integration.stateGenerationReset.test.ts`)で固定されている。\n * だから受け口は「予約キーを走査して handler に渡す」1 点ではなく、**段(phase)**にした。\n * 機能は自分が要る段だけ実装し、core は各段を従来の分岐があった位置で呼ぶ。\n *\n * validateEarly core 自身のトークン / `$listKeys` の解析より前(`$recursion` はここで解析される)\n * validate 世代を進める前(`value` しか読まない検証。ここで throw した再セットは世代を進めない)\n * preCommit 検証がすべて済み、まだ世代を進めていない点(旧世代の後始末と差し替え)\n * applyEarly `__state` の差し替え直後・`$on` の配線より前(`$scan` の出力の実体化と購読)\n * apply 新しい getterPaths / setterPaths の収集後(`$streams` の衝突検査がそれを見る)\n * register `_rebuildPathInfo` と `$scan` の登録の後(依存グラフへの登録)\n * activate 接続中の再 set と、接続の末尾(起動の可否と二重起動ガードは機能側が持つ)\n * deactivate 切断\n *\n * apply / register / activate は `order` の昇順、**deactivate は降順**で聞く。\n * これが「watch は stream より先に起動し、後に停止する」を番号だけで保つ\n * (従来 `State` に直書きされていた順序契約)。\n *\n * **文脈袋**(`IDeclarationContext`): 段を跨いで機能どうしが値を渡す口。core は自分が作った値\n * (`$eventTokens` の名前・再帰レジストリ)を publish し、`$scan` の検証がそれを読む。解析した\n * エントリも袋に入れて validate → applyEarly → register を渡り歩く。1 回の set につき 1 つ作る。\n */\nimport type { IStateElement } from \"../components/types\";\nimport type { IState } from \"../types\";\n\n/** 1 回の `_state` set の間だけ生きる、機能どうしの受け渡し口 */\nexport interface IDeclarationContext {\n get<T>(key: string): T | undefined;\n set(key: string, value: unknown): void;\n}\n\nexport function createDeclarationContext(): IDeclarationContext {\n const values = new Map<string, unknown>();\n return {\n get<T>(key: string): T | undefined {\n return values.get(key) as T | undefined;\n },\n set(key: string, value: unknown): void {\n values.set(key, value);\n },\n };\n}\n\nexport interface IDeclarationHooks {\n /** 聞く順(watch 10 → streams 20。deactivate はこの逆順) */\n readonly order: number;\n readonly validateEarly?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly validate?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly preCommit?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly applyEarly?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly apply?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly register?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n /**\n * `captured` が null なら `_state` セッターからの起動(接続中の再 set)、\n * 数値なら接続の末尾からの起動で、その接続で捕捉した世代(陳腐な connect の再開を弾く)。\n */\n readonly activate?: (element: IStateElement, captured: number | null) => void;\n readonly deactivate?: (element: IStateElement) => void;\n}\n\nconst registry = new Map<string, IDeclarationHooks>();\nlet ordered: IDeclarationHooks[] = [];\nlet reversed: IDeclarationHooks[] = [];\n\n/** 機能の install が呼ぶ(冪等) */\nexport function registerDeclarationHooks(feature: string, hooks: IDeclarationHooks): void {\n registry.set(feature, hooks);\n ordered = Array.from(registry.values()).sort((a, b) => a.order - b.order);\n reversed = ordered.slice().reverse();\n}\n\n/**\n * 宣言の受け口が入っているか(readiness barrier の判定 — 要件 D13 / 設計案 H5)。\n *\n * 未 install の機能は段がすべて no-op になるだけなので、core 自身が「宣言は書かれているのに\n * 受け口が無い」を見ていないと `$watch` / `$scan` / `$stream` / `$recursion` が**黙って**\n * 素通りする。`components/State.ts` の `_state` セッターがこれで門を張る。\n */\nexport function isDeclarationFeatureRegistered(feature: string): boolean {\n return registry.has(feature);\n}\n\nexport function runValidateEarly(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].validateEarly?.(element, value, ctx);\n }\n}\n\nexport function runPreCommit(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].preCommit?.(element, value, ctx);\n }\n}\n\nexport function runValidate(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].validate?.(element, value, ctx);\n }\n}\n\nexport function runApplyEarly(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].applyEarly?.(element, value, ctx);\n }\n}\n\nexport function runApply(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].apply?.(element, value, ctx);\n }\n}\n\nexport function runRegister(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].register?.(element, value, ctx);\n }\n}\n\nexport function runActivate(element: IStateElement, captured: number | null): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].activate?.(element, captured);\n }\n}\n\n/** 停止は起動の逆順(stream を止めてから watch を外す) */\nexport function runDeactivate(element: IStateElement): void {\n for (let i = 0; i < reversed.length; i++) {\n reversed[i].deactivate?.(element);\n }\n}\n"],"names":["createDeclarationContext","values","Map","get","key","set","value","registry","ordered","reversed","registerDeclarationHooks","feature","hooks","Array","from","sort","a","b","order","slice","reverse","isDeclarationFeatureRegistered","has","runValidateEarly","element","ctx","i","length","validateEarly","runPreCommit","preCommit","runValidate","validate","runApplyEarly","applyEarly","runApply","apply","runRegister","register","runActivate","captured","activate","runDeactivate","deactivate"],"mappings":"SAkCgBA,IACd,MAAMC,EAAS,IAAIC,IACnB,MAAO,CACLC,IAAOC,GACEH,EAAOE,IAAIC,GAEpB,GAAAC,CAAID,EAAaE,GACfL,EAAOI,IAAID,EAAKE,EAClB,EAEJ,CAmBA,MAAMC,EAAW,IAAIL,IACrB,IAAIM,EAA+B,GAC/BC,EAAgC,GAG9B,SAAUC,EAAyBC,EAAiBC,GACxDL,EAASF,IAAIM,EAASC,GACtBJ,EAAUK,MAAMC,KAAKP,EAASN,UAAUc,KAAK,CAACC,EAAGC,IAAMD,EAAEE,MAAQD,EAAEC,OACnET,EAAWD,EAAQW,QAAQC,SAC7B,CASM,SAAUC,EAA+BV,GAC7C,OAAOJ,EAASe,IAAIX,EACtB,UAEgBY,EAAiBC,EAAwBlB,EAAemB,GACtE,IAAK,IAAIC,EAAI,EAAGA,EAAIlB,EAAQmB,OAAQD,IAClClB,EAAQkB,GAAGE,gBAAgBJ,EAASlB,EAAOmB,EAE/C,UAEgBI,EAAaL,EAAwBlB,EAAemB,GAClE,IAAK,IAAIC,EAAI,EAAGA,EAAIlB,EAAQmB,OAAQD,IAClClB,EAAQkB,GAAGI,YAAYN,EAASlB,EAAOmB,EAE3C,UAEgBM,EAAYP,EAAwBlB,EAAemB,GACjE,IAAK,IAAIC,EAAI,EAAGA,EAAIlB,EAAQmB,OAAQD,IAClClB,EAAQkB,GAAGM,WAAWR,EAASlB,EAAOmB,EAE1C,UAEgBQ,EAAcT,EAAwBlB,EAAemB,GACnE,IAAK,IAAIC,EAAI,EAAGA,EAAIlB,EAAQmB,OAAQD,IAClClB,EAAQkB,GAAGQ,aAAaV,EAASlB,EAAOmB,EAE5C,UAEgBU,EAASX,EAAwBlB,EAAemB,GAC9D,IAAK,IAAIC,EAAI,EAAGA,EAAIlB,EAAQmB,OAAQD,IAClClB,EAAQkB,GAAGU,QAAQZ,EAASlB,EAAOmB,EAEvC,UAEgBY,EAAYb,EAAwBlB,EAAemB,GACjE,IAAK,IAAIC,EAAI,EAAGA,EAAIlB,EAAQmB,OAAQD,IAClClB,EAAQkB,GAAGY,WAAWd,EAASlB,EAAOmB,EAE1C,CAEM,SAAUc,EAAYf,EAAwBgB,GAClD,IAAK,IAAId,EAAI,EAAGA,EAAIlB,EAAQmB,OAAQD,IAClClB,EAAQkB,GAAGe,WAAWjB,EAASgB,EAEnC,CAGM,SAAUE,EAAclB,GAC5B,IAAK,IAAIE,EAAI,EAAGA,EAAIjB,EAASkB,OAAQD,IACnCjB,EAASiB,GAAGiB,aAAanB,EAE7B"}
@@ -0,0 +1,2 @@
1
+ import{aB as n}from"./binder.js";import{r as t}from"./errorGuidance.js";let r=null;function e(n){r=n}function a(e){return r??t(n("watch",`"$watch" in <wcs-state mount="${e}">`))}let o=null;function s(n){o=n}const u=Object.freeze([]);function c(n){return null===o?u:o(n)}export{s as a,c as g,a as r,e as s};
2
+ //# sourceMappingURL=featureBridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"featureBridge.js","sources":["../../../../../src/bridge/featureBridge.ts"],"sourcesContent":["/**\n * bridge/featureBridge.ts — 機能どうしの受け口(要件 B13 / 配線設計 §7-1 の延長)。\n *\n * `core/*Hooks.ts` が「core → 機能」の受け口なのに対し、ここは **機能 → 別の機能** の受け口。\n * 分割エントリ(`@wcstack/state/features/*`)は 1 つの core チャンクを共有するが、機能どうしの\n * 静的 import は共有チャンクを作ってしまい、片方だけを入れたページがもう片方のコードごと\n * ダウンロードすることになる(実測: `features/scopes` → `watch/watchRuntime` の 1 本で\n * temporal ランタイムのほぼ全部、5.3 KB gzip が scopes に乗っていた)。\n *\n * 置く側は自分の `install()` で登録し、読む側は「無ければ何もしない / 名指しで落ちる」。\n * full(`@wcstack/state`)と `/auto` では `bootstrapState()` が全機能を入れるので挙動は変わらない。\n *\n * **このディレクトリはどの機能のものでもない**(`scripts/check-state-split.mjs` が\n * feature 間のコード混入を見るときの中立領域)。置けるのは受け口そのものだけで、\n * 実装は必ず機能側に置くこと。\n */\nimport type { IStateElement } from \"../components/types\";\nimport { featureNotInstalledMessage } from \"../core/featureEntries\";\nimport { raiseError } from \"../raiseError\";\nimport type { IWatchEntry } from \"../watch/types\";\nimport type { IMountOverlaySummary } from \"../devtools/types\";\n\n/**\n * ボリュームの `$watch` 接頭辞登録(`scopes` が読み・`temporal` が置く)。\n * ボリュームの state は `State._state` セッターを通らない(`loadStateFromSource` の戻り値を\n * そのまま接ぎ木する)ので、宣言の readiness barrier もここで張る。\n */\nexport interface IVolumeWatchSupport {\n /** `$watch` のキーがパスとして妥当か(`watch/processWatchDeclaration.assertValidWatchPath`) */\n readonly assertValidPath: (path: string) => void;\n /** 翻訳済みの entry をルートの台帳へ追記する(`watch/watchRegistry.addVolumeWatchEntries`) */\n readonly addEntries: (stateElement: IStateElement, entries: readonly IWatchEntry[]) => void;\n /** 発火対象として起動する(`watch/watchRuntime.startWatch`) */\n readonly start: (stateElement: IStateElement) => void;\n}\n\nlet volumeWatchSupport: IVolumeWatchSupport | null = null;\n\n/** `temporal` の install(`installWatchRuntime`)が呼ぶ。冪等 */\nexport function setVolumeWatchSupport(support: IVolumeWatchSupport): void {\n volumeWatchSupport = support;\n}\n\n/**\n * ボリュームが `$watch` を宣言していたときだけ呼ぶ。`temporal` が未 install のページは\n * 黙って素通りさせず、他の宣言の barrier(要件 D13)と同じ文言で落とす。\n */\nexport function requireVolumeWatchSupport(mountPath: string): IVolumeWatchSupport {\n return volumeWatchSupport\n ?? raiseError(featureNotInstalledMessage(\"watch\", `\"$watch\" in <wcs-state mount=\"${mountPath}\">`));\n}\n\n/** マウントのオーバーレイ要約(`devtools` が読み・`scopes` が置く)。未 install なら空。 */\nexport type MountOverlayProvider = (stateElement: IStateElement) => IMountOverlaySummary[];\n\nlet mountOverlayProvider: MountOverlayProvider | null = null;\n\n/** `scopes` の install(`installScopeHooks`)が呼ぶ。冪等 */\nexport function setMountOverlayProvider(provider: MountOverlayProvider): void {\n mountOverlayProvider = provider;\n}\n\n// 共有の空配列。**凍結する** — 呼び手が push すると、以後すべてのツリーがその 1 本を見る。\n// 宣言型は protocol の `overlays(): IMountOverlaySummary[]` に合わせたまま、実体だけ凍らせる\nconst NO_OVERLAYS = Object.freeze([]) as unknown as IMountOverlaySummary[];\n\n/** スコープ機能の入っていないページにマウントは存在しえないので、空で正しい */\nexport function getMountOverlays(stateElement: IStateElement): IMountOverlaySummary[] {\n return mountOverlayProvider === null ? NO_OVERLAYS : mountOverlayProvider(stateElement);\n}\n\n/** テスト用: 受け口を空へ戻す(barrier / 未 install の形を再現する)。 */\nexport function __resetFeatureBridgeForTest(): void {\n volumeWatchSupport = null;\n mountOverlayProvider = null;\n}\n"],"names":["volumeWatchSupport","setVolumeWatchSupport","support","requireVolumeWatchSupport","mountPath","raiseError","featureNotInstalledMessage","mountOverlayProvider","setMountOverlayProvider","provider","NO_OVERLAYS","Object","freeze","getMountOverlays","stateElement"],"mappings":"wEAoCA,IAAIA,EAAiD,KAG/C,SAAUC,EAAsBC,GACpCF,EAAqBE,CACvB,CAMM,SAAUC,EAA0BC,GACxC,OAAOJ,GACFK,EAAWC,EAA2B,QAAS,iCAAiCF,OACvF,CAKA,IAAIG,EAAoD,KAGlD,SAAUC,EAAwBC,GACtCF,EAAuBE,CACzB,CAIA,MAAMC,EAAcC,OAAOC,OAAO,IAG5B,SAAUC,EAAiBC,GAC/B,OAAgC,OAAzBP,EAAgCG,EAAcH,EAAqBO,EAC5E"}
@@ -1,2 +1,2 @@
1
- import{r as e,L as t,d as n}from"./errorGuidance.js";const a=Symbol.for("wcstack.ssr.snapshotBuilder");function o(){const e=document.documentElement;return!!e&&"orchestrated"===e.getAttribute("data-wcs-server")}function r(){const e=document.documentElement;return!!e&&e.hasAttribute("data-wcs-server")}const s={bindAttributeName:"data-wcs",commentTextPrefix:"wcs-text",commentForPrefix:"wcs-for",commentIfPrefix:"wcs-if",commentElseIfPrefix:"wcs-elseif",commentElsePrefix:"wcs-else",tagNames:{state:"wcs-state",ssr:"wcs-ssr"},locale:"en",debug:!1,enableMustache:!0,enableDirectionalInitialSync:!0,enablePropagationContext:!0,enableContractAnalyzer:!1,sameValueGuard:!0},i=s;function c(){return i}function l(e){e.tagNames&&Object.assign(s.tagNames,e.tagNames),"string"==typeof e.bindAttributeName&&(s.bindAttributeName=e.bindAttributeName),"string"==typeof e.commentTextPrefix&&(s.commentTextPrefix=e.commentTextPrefix),"string"==typeof e.commentForPrefix&&(s.commentForPrefix=e.commentForPrefix),"string"==typeof e.commentIfPrefix&&(s.commentIfPrefix=e.commentIfPrefix),"string"==typeof e.commentElseIfPrefix&&(s.commentElseIfPrefix=e.commentElseIfPrefix),"string"==typeof e.commentElsePrefix&&(s.commentElsePrefix=e.commentElsePrefix),"string"==typeof e.locale&&(s.locale=e.locale),"boolean"==typeof e.debug&&(s.debug=e.debug),"boolean"==typeof e.enableMustache&&(s.enableMustache=e.enableMustache),"boolean"==typeof e.enableDirectionalInitialSync&&(s.enableDirectionalInitialSync=e.enableDirectionalInitialSync),"boolean"==typeof e.enablePropagationContext&&(s.enablePropagationContext=e.enablePropagationContext),"boolean"==typeof e.enableContractAnalyzer&&(s.enableContractAnalyzer=e.enableContractAnalyzer),"boolean"==typeof e.sameValueGuard&&(s.sameValueGuard=e.sameValueGuard)}const f={not:()=>e=>!e},m={input:new Map,output:new Map},u={input:new Map,output:new Map},b=new Map;function g(e,t,n){const a=m[e],o=u[e];for(const e of Object.keys(t)){a.set(e,t[e]);const r=n?.[e];void 0===r?o.delete(e):o.set(e,r)}b.clear()}function p(a,o,r,s=o){const i=`${a}${JSON.stringify(s)}:${r}`,c=b.get(i);if(void 0!==c)return c;const l=m[r].get(a)??f[a];void 0===l&&e(`[wcs/filter-unknown] filter not found: ${a}.${n(a,function(e){return[...new Set([...Object.keys(f),...m[e].keys()])]}(r))}${t}`);const g=u[r].get(a);void 0!==g&&(o.length<g[0]||o.length>g[1])&&e(o.length<g[0]?`[wcs/filter-arity] filter "${a}" requires at least ${g[0]} argument(s) (${o.length} given).${t}`:`[wcs/filter-arity] filter "${a}" accepts at most ${g[1]} argument(s) (${o.length} given).${t}`);const p=l(o,s);return b.set(i,p),p}export{a as S,o as a,g as b,i as c,c as g,r as i,p as r,l as s};
1
+ import{r as e,L as t,d as n}from"./errorGuidance.js";const a=Symbol.for("wcstack.ssr.snapshotBuilder");function o(){const e=document.documentElement;return!!e&&"orchestrated"===e.getAttribute("data-wcs-server")}function r(){const e=document.documentElement;return!!e&&e.hasAttribute("data-wcs-server")}const s={bindAttributeName:"data-wcs",commentTextPrefix:"wcs-text",commentForPrefix:"wcs-for",commentIfPrefix:"wcs-if",commentElseIfPrefix:"wcs-elseif",commentElsePrefix:"wcs-else",tagNames:{state:"wcs-state",ssr:"wcs-ssr"},locale:"en",debug:!1,enableMustache:!0,enableDirectionalInitialSync:!0,enablePropagationContext:!0,enableContractAnalyzer:!1,sameValueGuard:!0},i=s;function c(){return i}function l(e){e.tagNames&&Object.assign(s.tagNames,e.tagNames),"string"==typeof e.bindAttributeName&&(s.bindAttributeName=e.bindAttributeName),"string"==typeof e.commentTextPrefix&&(s.commentTextPrefix=e.commentTextPrefix),"string"==typeof e.commentForPrefix&&(s.commentForPrefix=e.commentForPrefix),"string"==typeof e.commentIfPrefix&&(s.commentIfPrefix=e.commentIfPrefix),"string"==typeof e.commentElseIfPrefix&&(s.commentElseIfPrefix=e.commentElseIfPrefix),"string"==typeof e.commentElsePrefix&&(s.commentElsePrefix=e.commentElsePrefix),"string"==typeof e.locale&&(s.locale=e.locale),"boolean"==typeof e.debug&&(s.debug=e.debug),"boolean"==typeof e.enableMustache&&(s.enableMustache=e.enableMustache),"boolean"==typeof e.enableDirectionalInitialSync&&(s.enableDirectionalInitialSync=e.enableDirectionalInitialSync),"boolean"==typeof e.enablePropagationContext&&(s.enablePropagationContext=e.enablePropagationContext),"boolean"==typeof e.enableContractAnalyzer&&(s.enableContractAnalyzer=e.enableContractAnalyzer),"boolean"==typeof e.sameValueGuard&&(s.sameValueGuard=e.sameValueGuard)}function f(e,t){return`${JSON.stringify(e)}${JSON.stringify(t)}`}function m(e){if(0===e.length)return"";let t="";for(let n=0;n<e.length;n++){const a=e[n];n>0&&(t+="|"),t+=`${a.filterName}(${f(a.args,a.literals??a.args)})`}return t}const u=new Map([["not",()=>e=>!e]]),g=new Map([["not",[0,0]]]),b={input:new Map,output:new Map},p={input:new Map,output:new Map},d={input:new Map,output:new Map},y=new Map;function x(e,t,n,a){const o=b[e],r=p[e];for(const e of Object.keys(t)){o.set(e,t[e]);const a=n?.[e];void 0===a?r.delete(e):r.set(e,a)}const s=a??{},i=d[e];for(const[e,n]of[...i])Object.prototype.hasOwnProperty.call(t,n)&&s[e]!==n&&i.delete(e);for(const e of Object.keys(s))i.set(e,s[e]);y.clear()}function w(a,o,r,s=o){const i=d[r].get(a)??a,c=`${i}${f(o,s)}:${r}`,l=y.get(c);if(void 0!==l)return l;const m=b[r].get(i)??u.get(i);if(void 0===m){const o=0===b[r].size?' No formatting filters are installed — add them with installFeatures([...]) from "@wcstack/state/features/formats".':"";e(`[wcs/filter-unknown] filter not found: ${a}.${n(a,function(e){return[...new Set([...u.keys(),...b[e].keys()])]}(r))}${o}${t}`)}const x=p[r].get(i)??g.get(i);void 0!==x&&(o.length<x[0]||o.length>x[1])&&e(o.length<x[0]?`[wcs/filter-arity] filter "${a}" requires at least ${x[0]} argument(s) (${o.length} given).${t}`:`[wcs/filter-arity] filter "${a}" accepts at most ${x[1]} argument(s) (${o.length} given).${t}`);const w=m(o,s);return y.set(c,w),w}export{a as S,o as a,x as b,i as c,m as f,c as g,r as i,w as r,l as s};
2
2
  //# sourceMappingURL=filterRegistry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"filterRegistry.js","sources":["../../../../../src/protocol/ssrSnapshot.ts","../../../../../src/config.ts","../../../../../src/core/filterRegistry.ts"],"sourcesContent":["// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/ssr-snapshot.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// ssr-snapshot protocol — how the SSR renderer asks whoever owns reactive\n// state to build hydration snapshots (<wcs-ssr>) as a final pass, after every\n// DOM inserter (router route content, late custom elements) has settled.\n//\n// Without this, the snapshot is built inside <wcs-state>'s connectedCallback\n// and races DOM inserted by other packages: whether a route's structural\n// templates make it into the snapshot depends on document order and state's\n// load mechanism (docs/ssr-router-design.md §5).\n//\n// The provider (@wcstack/state) installs itself on a well-known global symbol\n// at bootstrap. The renderer (@wcstack/server) looks the builder up after\n// running bootstraps: if present it announces orchestration by setting\n// `data-wcs-server=\"orchestrated\"` on the document element BEFORE parsing, and\n// calls build() right before serialization. The provider keeps its inline\n// per-element fallback whenever the attribute value is anything else, so:\n// - old renderer + new provider -> inline build, yesterday's behavior\n// - new renderer + old provider -> no builder found, attribute stays \"\",\n// the old provider builds inline as before\n// - new renderer + new provider -> orchestrated: snapshots are built last\n// and therefore always see settled DOM\n//\n// The symbol (rather than a package import) also pins the builder to the state\n// copy that actually runs on the page — its module-scoped fragment registries\n// are the ones the snapshot must read.\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/ssr-snapshot.ts), then\n// run `node scripts/sync-protocol-types.mjs` to regenerate the per-package\n// copies (packages/<pkg>/src/protocol/ssrSnapshot.ts). Those copies are\n// generated — do not edit them.\n\n/**\n * Global key the snapshot builder installs itself under. `Symbol.for` so\n * independently loaded copies of this file (state's and server's) still agree.\n */\nexport const SSR_SNAPSHOT_BUILDER_KEY = Symbol.for(\"wcstack.ssr.snapshotBuilder\");\n\n/**\n * `data-wcs-server` attribute value announcing that the renderer will call the\n * builder as a final pass. Providers must skip their inline per-element build\n * when they see this value, and keep it for any other value (including \"\").\n */\nexport const SSR_ORCHESTRATED_VALUE = \"orchestrated\";\n\nexport interface IWcsSsrSnapshotBuilder {\n readonly protocol: \"wcs-ssr-snapshot\";\n /** Integer protocol version. All versions >= 1 are participant-compatible. */\n readonly version: number;\n /**\n * Build a hydration snapshot for every enable-ssr state element in `root`\n * that does not already have one. Called once per render, after all\n * waiting-protocol elements have settled and bindings are ready. Must be\n * idempotent with respect to already-snapshotted elements.\n */\n build(root: Document): void;\n}\n\n/**\n * The installed builder, or null when there is none or it speaks a shape this\n * reader does not.\n */\nexport function getSsrSnapshotBuilder(): IWcsSsrSnapshotBuilder | null {\n const candidate = (globalThis as Record<symbol, unknown>)[\n SSR_SNAPSHOT_BUILDER_KEY\n ] as IWcsSsrSnapshotBuilder | undefined;\n if (candidate === undefined || candidate === null) return null;\n if (candidate.protocol !== \"wcs-ssr-snapshot\") return null;\n if (typeof candidate.version !== \"number\" || candidate.version < 1) return null;\n if (typeof candidate.build !== \"function\") return null;\n return candidate;\n}\n","import { IConfig, IWritableConfig } from \"./types.js\";\nimport { SSR_ORCHESTRATED_VALUE } from \"./protocol/ssrSnapshot.js\";\n\n/**\n * サーバー主導スナップショット(orchestrated)の判定\n * (docs/ssr-router-design.md §5)。renderToString が snapshot builder を\n * 見つけたときだけ `data-wcs-server=\"orchestrated\"` を宣言する — 値が他の\n * もの(旧 server の \"\" を含む)なら inline 生成が従来どおり働く。\n * inSsr と同じ理由でキャッシュしない。\n */\nexport function isOrchestratedSsr(): boolean {\n const html = document.documentElement;\n return html ? html.getAttribute('data-wcs-server') === SSR_ORCHESTRATED_VALUE : false;\n}\n\nexport function inSsr(): boolean {\n // キャッシュしない: SSR モードはプロセスの属性ではなく「現在の document」の\n // 属性。@wcstack/server はグローバル document を差し替えてサーバーレンダリング\n // した後、同一プロセスでクライアント側ハイドレーションが走る(SSR→hydrate の\n // e2e が該当)。サーバーフェーズの判定をキャッシュするとクライアントフェーズが\n // SSR モード扱いになり、hydrateBindings の代わりに buildBindings が選ばれて\n // connectedCallbackPromise が永久に未解決になる。\n const html = document.documentElement;\n return html ? html.hasAttribute('data-wcs-server') : false;\n}\n\ninterface IInternalConfig {\n bindAttributeName: string;\n commentTextPrefix: string;\n commentForPrefix: string;\n commentIfPrefix: string;\n commentElseIfPrefix: string;\n commentElsePrefix: string;\n tagNames: {\n state: string;\n ssr: string;\n };\n locale: string;\n debug: boolean;\n enableMustache: boolean;\n enableDirectionalInitialSync: boolean;\n enablePropagationContext: boolean;\n enableContractAnalyzer: boolean;\n sameValueGuard: boolean;\n}\n\nconst _config: IInternalConfig = {\n bindAttributeName: 'data-wcs',\n commentTextPrefix: 'wcs-text',\n commentForPrefix: 'wcs-for',\n commentIfPrefix: 'wcs-if',\n commentElseIfPrefix: 'wcs-elseif',\n commentElsePrefix: 'wcs-else',\n tagNames: {\n state: 'wcs-state',\n ssr: 'wcs-ssr',\n },\n locale: 'en',\n debug: false,\n enableMustache: true,\n enableDirectionalInitialSync: true,\n enablePropagationContext: true,\n // Phase 5b の dev-time contract analyzer は意図的に explicit opt-in(既定 off)。\n // wcstack は buildless / zero-config で NODE_ENV 相当の確実な dev/prod 判定が無く、\n // hostname や minification の heuristic で auto-ON すると誤検出で prod にコストを\n // 乗せうるため、dev 既定 ON は採らない。利用側が setConfig で明示有効化する\n // (docs/architecture-hardening/10-defaulting-rollout-status.md §C)。\n enableContractAnalyzer: false,\n sameValueGuard: true,\n};\n\n// backward compatible export (read-only usage)\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n return config;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n if (typeof partialConfig.bindAttributeName === \"string\") {\n _config.bindAttributeName = partialConfig.bindAttributeName;\n }\n if (typeof partialConfig.commentTextPrefix === \"string\") {\n _config.commentTextPrefix = partialConfig.commentTextPrefix;\n }\n if (typeof partialConfig.commentForPrefix === \"string\") {\n _config.commentForPrefix = partialConfig.commentForPrefix;\n }\n if (typeof partialConfig.commentIfPrefix === \"string\") {\n _config.commentIfPrefix = partialConfig.commentIfPrefix;\n }\n if (typeof partialConfig.commentElseIfPrefix === \"string\") {\n _config.commentElseIfPrefix = partialConfig.commentElseIfPrefix;\n }\n if (typeof partialConfig.commentElsePrefix === \"string\") {\n _config.commentElsePrefix = partialConfig.commentElsePrefix;\n }\n if (typeof partialConfig.locale === \"string\") {\n _config.locale = partialConfig.locale;\n }\n if (typeof partialConfig.debug === \"boolean\") {\n _config.debug = partialConfig.debug;\n }\n if (typeof partialConfig.enableMustache === \"boolean\") {\n _config.enableMustache = partialConfig.enableMustache;\n }\n if (typeof partialConfig.enableDirectionalInitialSync === \"boolean\") {\n _config.enableDirectionalInitialSync = partialConfig.enableDirectionalInitialSync;\n }\n if (typeof partialConfig.enablePropagationContext === \"boolean\") {\n _config.enablePropagationContext = partialConfig.enablePropagationContext;\n }\n if (typeof partialConfig.enableContractAnalyzer === \"boolean\") {\n _config.enableContractAnalyzer = partialConfig.enableContractAnalyzer;\n }\n if (typeof partialConfig.sameValueGuard === \"boolean\") {\n _config.sameValueGuard = partialConfig.sameValueGuard;\n }\n}\n","/**\n * core/filterRegistry.ts — フィルタ実関数の登録簿(設計案 §4、要件 D16)。\n *\n * 文法(`path|filter(args)` の解析)は core に残り、**実関数は登録簿から束縛計画の段で引く**。\n * 解析の段は名前と引数しか作らない(`bindTextParser/parseFilters.ts`)ので、パーサだけを使う\n * tooling(`@wcstack/state/parser`)はフィルタの実装を 1 バイトも引き込まない。\n *\n * 書式フィルタ群(`uc` / `date` / `round` …)は `features/formats` が install で登録する。\n * core が自前で持つのは、エンジン自身が差し込む `not` だけ(`if` / `else` の反転 —\n * structural/notFilter.ts)。未知のフィルタは束縛計画の段で名指しで落ちる(従来は解析時)。\n */\nimport { didYouMean, LINT_HINT } from \"../errorGuidance\";\nimport type { FilterFn, FilterIOType, FilterWithOptions } from \"../filters/types\";\nimport { raiseError } from \"../raiseError\";\n\n/** `options` を受け取って実関数を返す工場(`filters/types.ts` の `FilterWithOptions` の要素) */\nexport type FilterFactory = (options?: string[], literals?: readonly unknown[]) => FilterFn;\n\n/**\n * エンジン自身が差し込むフィルタ。`if` / `else` の分岐は `not` を付けた束縛として組み立てられる\n * ので、`features/formats` の無いページでも必ず要る。\n */\nconst CORE_FILTERS: Record<string, FilterFactory> = {\n not: () => (value: unknown): boolean => !value,\n};\n\nconst registries: Record<FilterIOType, Map<string, FilterFactory>> = {\n input: new Map<string, FilterFactory>(),\n output: new Map<string, FilterFactory>(),\n};\n\n/** 受け付ける引数の個数 [最少, 最多]。登録した機能が渡したものだけ(要件 B3) */\nconst aritiesByIOType: Record<FilterIOType, Map<string, readonly [number, number]>> = {\n input: new Map<string, readonly [number, number]>(),\n output: new Map<string, readonly [number, number]>(),\n};\n\n/** 名前 + 引数 + 入出力ごとに解決済みの実関数(解決は 1 回だけ) */\nconst resolvedByKey = new Map<string, FilterFn>();\n\n/** 機能の install が呼ぶ(冪等 — 同じ名前は置き換え)。hot path には触れない */\nexport function registerFilters(\n filterIOType: FilterIOType,\n filters: FilterWithOptions,\n arity?: Readonly<Record<string, readonly [number, number]>>,\n): void {\n const registry = registries[filterIOType];\n const arities = aritiesByIOType[filterIOType];\n for (const name of Object.keys(filters)) {\n registry.set(name, filters[name] as FilterFactory);\n const bounds = arity?.[name];\n if (typeof bounds === \"undefined\") {\n arities.delete(name);\n } else {\n arities.set(name, bounds);\n }\n }\n // 登録が変われば解決済みの答えも変わりうる(同じページで 2 回 install することは無いが、\n // テストと tooling は登録簿を入れ替える)\n resolvedByKey.clear();\n}\n\n/** 登録済みの名前(core のものを含む)。診断の did-you-mean が読む */\nexport function knownFilterNames(filterIOType: FilterIOType): string[] {\n return [...new Set([...Object.keys(CORE_FILTERS), ...registries[filterIOType].keys()])];\n}\n\n/** 解決済みの答えを捨てる(tooling: `@wcstack/state/parser` の clearParserCaches) */\nexport function clearFilterResolutionCache(): void {\n resolvedByKey.clear();\n}\n\n/**\n * 実関数を引く(束縛計画の段)。未知のフィルタはここで落ちる — 解析の段では落とさない。\n * 文言は lint の `wcs/filter-unknown` と同じ語彙・同じ did-you-mean 規準(三面同語彙)。\n */\nexport function resolveFilterFn(\n filterName: string,\n args: string[],\n filterIOType: FilterIOType,\n literals: readonly unknown[] = args,\n): FilterFn {\n // 引数は型付きの値の構造のまま鍵にする(`join('a,b')` と `join(a,b)` — 要件 B3、`eq(1)` と\n // `eq('1')` — 要件 B9 を取り違えない)\n const key = `${filterName}${JSON.stringify(literals)}:${filterIOType}`;\n const resolved = resolvedByKey.get(key);\n if (typeof resolved !== \"undefined\") {\n return resolved;\n }\n const factory = registries[filterIOType].get(filterName) ?? CORE_FILTERS[filterName];\n if (typeof factory === \"undefined\") {\n raiseError(`[wcs/filter-unknown] filter not found: ${filterName}.${didYouMean(filterName, knownFilterNames(filterIOType))}${LINT_HINT}`);\n }\n const bounds = aritiesByIOType[filterIOType].get(filterName);\n if (typeof bounds !== \"undefined\" && (args.length < bounds[0] || args.length > bounds[1])) {\n // lint の wcs/filter-arity と同じ語彙\n raiseError(args.length < bounds[0]\n ? `[wcs/filter-arity] filter \"${filterName}\" requires at least ${bounds[0]} argument(s) (${args.length} given).${LINT_HINT}`\n : `[wcs/filter-arity] filter \"${filterName}\" accepts at most ${bounds[1]} argument(s) (${args.length} given).${LINT_HINT}`);\n }\n const filterFn = factory(args, literals);\n resolvedByKey.set(key, filterFn);\n return filterFn;\n}\n"],"names":["SSR_SNAPSHOT_BUILDER_KEY","Symbol","for","isOrchestratedSsr","html","document","documentElement","getAttribute","inSsr","hasAttribute","_config","bindAttributeName","commentTextPrefix","commentForPrefix","commentIfPrefix","commentElseIfPrefix","commentElsePrefix","tagNames","state","ssr","locale","debug","enableMustache","enableDirectionalInitialSync","enablePropagationContext","enableContractAnalyzer","sameValueGuard","config","getConfig","setConfig","partialConfig","Object","assign","CORE_FILTERS","not","value","registries","input","Map","output","aritiesByIOType","resolvedByKey","registerFilters","filterIOType","filters","arity","registry","arities","name","keys","set","bounds","delete","clear","resolveFilterFn","filterName","args","literals","key","JSON","stringify","resolved","get","factory","raiseError","didYouMean","Set","knownFilterNames","LINT_HINT","length","filterFn"],"mappings":"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"}
1
+ {"version":3,"file":"filterRegistry.js","sources":["../../../../../src/protocol/ssrSnapshot.ts","../../../../../src/config.ts","../../../../../src/binding/filterKey.ts","../../../../../src/core/filterRegistry.ts"],"sourcesContent":["// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/ssr-snapshot.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// ssr-snapshot protocol — how the SSR renderer asks whoever owns reactive\n// state to build hydration snapshots (<wcs-ssr>) as a final pass, after every\n// DOM inserter (router route content, late custom elements) has settled.\n//\n// Without this, the snapshot is built inside <wcs-state>'s connectedCallback\n// and races DOM inserted by other packages: whether a route's structural\n// templates make it into the snapshot depends on document order and state's\n// load mechanism (docs/ssr-router-design.md §5).\n//\n// The provider (@wcstack/state) installs itself on a well-known global symbol\n// at bootstrap. The renderer (@wcstack/server) looks the builder up after\n// running bootstraps: if present it announces orchestration by setting\n// `data-wcs-server=\"orchestrated\"` on the document element BEFORE parsing, and\n// calls build() right before serialization. The provider keeps its inline\n// per-element fallback whenever the attribute value is anything else, so:\n// - old renderer + new provider -> inline build, yesterday's behavior\n// - new renderer + old provider -> no builder found, attribute stays \"\",\n// the old provider builds inline as before\n// - new renderer + new provider -> orchestrated: snapshots are built last\n// and therefore always see settled DOM\n//\n// The symbol (rather than a package import) also pins the builder to the state\n// copy that actually runs on the page — its module-scoped fragment registries\n// are the ones the snapshot must read.\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/ssr-snapshot.ts), then\n// run `node scripts/sync-protocol-types.mjs` to regenerate the per-package\n// copies (packages/<pkg>/src/protocol/ssrSnapshot.ts). Those copies are\n// generated — do not edit them.\n\n/**\n * Global key the snapshot builder installs itself under. `Symbol.for` so\n * independently loaded copies of this file (state's and server's) still agree.\n */\nexport const SSR_SNAPSHOT_BUILDER_KEY = Symbol.for(\"wcstack.ssr.snapshotBuilder\");\n\n/**\n * `data-wcs-server` attribute value announcing that the renderer will call the\n * builder as a final pass. Providers must skip their inline per-element build\n * when they see this value, and keep it for any other value (including \"\").\n */\nexport const SSR_ORCHESTRATED_VALUE = \"orchestrated\";\n\nexport interface IWcsSsrSnapshotBuilder {\n readonly protocol: \"wcs-ssr-snapshot\";\n /** Integer protocol version. All versions >= 1 are participant-compatible. */\n readonly version: number;\n /**\n * Build a hydration snapshot for every enable-ssr state element in `root`\n * that does not already have one. Called once per render, after all\n * waiting-protocol elements have settled and bindings are ready. Must be\n * idempotent with respect to already-snapshotted elements.\n */\n build(root: Document): void;\n /**\n * Drop whatever the provider accumulated for **this render** in module-scoped\n * ledgers, so a long-lived rendering process does not grow one render at a time.\n * The renderer calls it once per render at the very end of its cleanup, after the\n * document is beyond use — never mid-render, because work still settling (bindings\n * finishing on a microtask chain) may read those ledgers.\n *\n * Optional and additive: a renderer must call it as `builder.reset?.()`, and a\n * provider that has nothing to drop may leave it out. Correctness of the *output*\n * must not depend on it — a provider scopes each snapshot to its own document\n * regardless — so an old renderer paired with a new provider only keeps memory\n * longer, it does not leak one render's content into another.\n *\n * It rides the protocol rather than a package import for the same reason `build`\n * does: the symbol pins it to the copy of the provider that actually ran, whose\n * module-scoped registries are the ones holding the garbage.\n */\n reset?(): void;\n}\n\n/**\n * The installed builder, or null when there is none or it speaks a shape this\n * reader does not.\n */\nexport function getSsrSnapshotBuilder(): IWcsSsrSnapshotBuilder | null {\n const candidate = (globalThis as Record<symbol, unknown>)[\n SSR_SNAPSHOT_BUILDER_KEY\n ] as IWcsSsrSnapshotBuilder | undefined;\n if (candidate === undefined || candidate === null) return null;\n if (candidate.protocol !== \"wcs-ssr-snapshot\") return null;\n if (typeof candidate.version !== \"number\" || candidate.version < 1) return null;\n if (typeof candidate.build !== \"function\") return null;\n return candidate;\n}\n","import { IConfig, IWritableConfig } from \"./types.js\";\nimport { SSR_ORCHESTRATED_VALUE } from \"./protocol/ssrSnapshot.js\";\n\n/**\n * サーバー主導スナップショット(orchestrated)の判定\n * (docs/ssr-router-design.md §5)。renderToString が snapshot builder を\n * 見つけたときだけ `data-wcs-server=\"orchestrated\"` を宣言する — 値が他の\n * もの(旧 server の \"\" を含む)なら inline 生成が従来どおり働く。\n * inSsr と同じ理由でキャッシュしない。\n */\nexport function isOrchestratedSsr(): boolean {\n const html = document.documentElement;\n return html ? html.getAttribute('data-wcs-server') === SSR_ORCHESTRATED_VALUE : false;\n}\n\nexport function inSsr(): boolean {\n // キャッシュしない: SSR モードはプロセスの属性ではなく「現在の document」の\n // 属性。@wcstack/server はグローバル document を差し替えてサーバーレンダリング\n // した後、同一プロセスでクライアント側ハイドレーションが走る(SSR→hydrate の\n // e2e が該当)。サーバーフェーズの判定をキャッシュするとクライアントフェーズが\n // SSR モード扱いになり、hydrateBindings の代わりに buildBindings が選ばれて\n // connectedCallbackPromise が永久に未解決になる。\n const html = document.documentElement;\n return html ? html.hasAttribute('data-wcs-server') : false;\n}\n\ninterface IInternalConfig {\n bindAttributeName: string;\n commentTextPrefix: string;\n commentForPrefix: string;\n commentIfPrefix: string;\n commentElseIfPrefix: string;\n commentElsePrefix: string;\n tagNames: {\n state: string;\n ssr: string;\n };\n locale: string;\n debug: boolean;\n enableMustache: boolean;\n enableDirectionalInitialSync: boolean;\n enablePropagationContext: boolean;\n enableContractAnalyzer: boolean;\n sameValueGuard: boolean;\n}\n\nconst _config: IInternalConfig = {\n bindAttributeName: 'data-wcs',\n commentTextPrefix: 'wcs-text',\n commentForPrefix: 'wcs-for',\n commentIfPrefix: 'wcs-if',\n commentElseIfPrefix: 'wcs-elseif',\n commentElsePrefix: 'wcs-else',\n tagNames: {\n state: 'wcs-state',\n ssr: 'wcs-ssr',\n },\n locale: 'en',\n debug: false,\n enableMustache: true,\n enableDirectionalInitialSync: true,\n enablePropagationContext: true,\n // Phase 5b の dev-time contract analyzer は意図的に explicit opt-in(既定 off)。\n // wcstack は buildless / zero-config で NODE_ENV 相当の確実な dev/prod 判定が無く、\n // hostname や minification の heuristic で auto-ON すると誤検出で prod にコストを\n // 乗せうるため、dev 既定 ON は採らない。利用側が setConfig で明示有効化する\n // (docs/architecture-hardening/10-defaulting-rollout-status.md §C)。\n enableContractAnalyzer: false,\n sameValueGuard: true,\n};\n\n// backward compatible export (read-only usage)\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n return config;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n if (typeof partialConfig.bindAttributeName === \"string\") {\n _config.bindAttributeName = partialConfig.bindAttributeName;\n }\n if (typeof partialConfig.commentTextPrefix === \"string\") {\n _config.commentTextPrefix = partialConfig.commentTextPrefix;\n }\n if (typeof partialConfig.commentForPrefix === \"string\") {\n _config.commentForPrefix = partialConfig.commentForPrefix;\n }\n if (typeof partialConfig.commentIfPrefix === \"string\") {\n _config.commentIfPrefix = partialConfig.commentIfPrefix;\n }\n if (typeof partialConfig.commentElseIfPrefix === \"string\") {\n _config.commentElseIfPrefix = partialConfig.commentElseIfPrefix;\n }\n if (typeof partialConfig.commentElsePrefix === \"string\") {\n _config.commentElsePrefix = partialConfig.commentElsePrefix;\n }\n if (typeof partialConfig.locale === \"string\") {\n _config.locale = partialConfig.locale;\n }\n if (typeof partialConfig.debug === \"boolean\") {\n _config.debug = partialConfig.debug;\n }\n if (typeof partialConfig.enableMustache === \"boolean\") {\n _config.enableMustache = partialConfig.enableMustache;\n }\n if (typeof partialConfig.enableDirectionalInitialSync === \"boolean\") {\n _config.enableDirectionalInitialSync = partialConfig.enableDirectionalInitialSync;\n }\n if (typeof partialConfig.enablePropagationContext === \"boolean\") {\n _config.enablePropagationContext = partialConfig.enablePropagationContext;\n }\n if (typeof partialConfig.enableContractAnalyzer === \"boolean\") {\n _config.enableContractAnalyzer = partialConfig.enableContractAnalyzer;\n }\n if (typeof partialConfig.sameValueGuard === \"boolean\") {\n _config.sameValueGuard = partialConfig.sameValueGuard;\n }\n}\n","/**\n * binding/filterKey.ts — フィルタの引数と並びを文字列の鍵にする(**唯一の基準**)。\n *\n * 鍵を作る場所は 2 つあり、規準がずれると必ず取り違えが起きる:\n * - `core/filterRegistry.ts` の解決済み実関数のキャッシュ\n * - ハンドラの共有キー(`event/twowayHandler.ts` / `radioHandler.ts` / `checkboxHandler.ts`)、\n * 束縛キー(`bindings/BindingSession.ts`)、devtools の宣言キー(`devtools/declaredBindings.ts`)\n *\n * どちらも `filterArgsKey` を通すことで、規準のずれを構造的に止める。\n */\n\n/**\n * 引数 1 組の鍵。**原文(`args`)と型付きの値(`literals`)の両方**を書き出す。\n *\n * - 原文だけだと `defaults(0)` と `defaults('0')` が同じ `[\"0\"]` になり、型の違う 2 つの\n * フィルタが同じ実関数・同じハンドラを共有する(要件 B9)。\n * - 型付きの値だけだと `toLiteral` の `Number()` 正規化で `1` / `1.0` / `01` / `+1` が\n * 同じ literal になり、原文を読む工場(`truncate` / `unit` / `join` / `ymd` / `padStart` …)が\n * 別の引数に対して同じ答えを引く。\n */\nexport function filterArgsKey(args: readonly string[], literals: readonly unknown[]): string {\n return `${JSON.stringify(args)}${JSON.stringify(literals)}`;\n}\n\n/** 鍵を作るのに要る最小の形(`IParsedFilter` / `IFilterInfo` と devtools の宣言情報の両方を受ける) */\ninterface IFilterKeySource {\n readonly filterName: string;\n readonly args: readonly string[];\n readonly literals?: readonly unknown[];\n}\n\n/**\n * フィルタの並びの鍵。`handlerByHandlerKey` はモジュール大域なので、ここで区別が付かないと\n * 後から配線された束縛が先の束縛のハンドラ(別のフィルタで畳まれた値を書くもの)を共有する。\n *\n * `literals` は束縛計画の段(`bindings/planFilters.ts`)が落とさずに持ち回している前提。\n * 省略された組み立て(devtools の宣言情報など)は原文で代用する。\n */\nexport function filterListKey(filters: readonly IFilterKeySource[]): string {\n if (filters.length === 0) {\n return \"\";\n }\n let key = \"\";\n for (let i = 0; i < filters.length; i++) {\n const filter = filters[i];\n if (i > 0) key += \"|\";\n key += `${filter.filterName}(${filterArgsKey(filter.args, filter.literals ?? filter.args)})`;\n }\n return key;\n}\n","/**\n * core/filterRegistry.ts — フィルタ実関数の登録簿(設計案 §4、要件 D16)。\n *\n * 文法(`path|filter(args)` の解析)は core に残り、**実関数は登録簿から束縛計画の段で引く**。\n * 解析の段は名前と引数しか作らない(`bindTextParser/parseFilters.ts`)ので、パーサだけを使う\n * tooling(`@wcstack/state/parser`)はフィルタの実装を 1 バイトも引き込まない。\n *\n * 書式フィルタ群(`uc` / `date` / `round` …)は `features/formats` が install で登録する。\n * core が自前で持つのは、エンジン自身が差し込む `not` だけ(`if` / `else` の反転 —\n * structural/notFilter.ts)。未知のフィルタは束縛計画の段で名指しで落ちる(従来は解析時)。\n */\nimport { filterArgsKey } from \"../binding/filterKey\";\nimport { didYouMean, LINT_HINT } from \"../errorGuidance\";\nimport type { FilterFn, FilterIOType, FilterWithOptions } from \"../filters/types\";\nimport { raiseError } from \"../raiseError\";\n\n/** `options` を受け取って実関数を返す工場(`filters/types.ts` の `FilterWithOptions` の要素) */\nexport type FilterFactory = (options?: string[], literals?: readonly unknown[]) => FilterFn;\n\n/**\n * エンジン自身が差し込むフィルタ。`if` / `else` の分岐は `not` を付けた束縛として組み立てられる\n * ので、`features/formats` の無いページでも必ず要る。\n *\n * `Map` であることに意味がある: 素のオブジェクトへのブラケット参照だと `Object.prototype` の\n * メンバがフィルタとして通り(`|toString` / `|constructor` / `|valueOf` / `|hasOwnProperty`)、\n * `[wcs/filter-unknown]` の代わりに意味不明な TypeError が出ていた。\n */\nconst CORE_FILTERS = new Map<string, FilterFactory>([\n [\"not\", () => (value: unknown): boolean => !value],\n]);\n\n/**\n * core が答えるフィルタの引数の個数(要件 B3)。`features/formats` を入れないページでも\n * `|not(1)` が名指しで落ちるように、登録簿とは別にここに持つ。\n */\nconst CORE_ARITIES = new Map<string, readonly [number, number]>([\n [\"not\", [0, 0]],\n]);\n\nconst registries: Record<FilterIOType, Map<string, FilterFactory>> = {\n input: new Map<string, FilterFactory>(),\n output: new Map<string, FilterFactory>(),\n};\n\n/** 受け付ける引数の個数 [最少, 最多]。登録した機能が渡したものだけ(要件 B3) */\nconst aritiesByIOType: Record<FilterIOType, Map<string, readonly [number, number]>> = {\n input: new Map<string, readonly [number, number]>(),\n output: new Map<string, readonly [number, number]>(),\n};\n\n/** 旧名 → 正式名(要件 B12)。解決・引数の個数は正式名で引く。登録した機能が渡したものだけ */\nconst aliasesByIOType: Record<FilterIOType, Map<string, string>> = {\n input: new Map<string, string>(),\n output: new Map<string, string>(),\n};\n\n/** 名前 + 引数 + 入出力ごとに解決済みの実関数(解決は 1 回だけ) */\nconst resolvedByKey = new Map<string, FilterFn>();\n\n/** 機能の install が呼ぶ(冪等 — 同じ名前は置き換え)。hot path には触れない */\nexport function registerFilters(\n filterIOType: FilterIOType,\n filters: FilterWithOptions,\n arity?: Readonly<Record<string, readonly [number, number]>>,\n aliases?: Readonly<Record<string, string>>,\n): void {\n const registry = registries[filterIOType];\n const arities = aritiesByIOType[filterIOType];\n for (const name of Object.keys(filters)) {\n registry.set(name, filters[name] as FilterFactory);\n const bounds = arity?.[name];\n if (typeof bounds === \"undefined\") {\n arities.delete(name);\n } else {\n arities.set(name, bounds);\n }\n }\n // 旧名も arity と同じ規則で掃除する(追加専用だと、登録簿を入れ替える tooling / テストに\n // 前の登録の旧名が残る)。「今回登録した正式名を指す旧名」だけを対象にするので、別の機能が\n // 登録した旧名は消さない\n const nextAliases = aliases ?? {};\n const aliasMap = aliasesByIOType[filterIOType];\n for (const [alias, canonical] of [...aliasMap]) {\n if (Object.prototype.hasOwnProperty.call(filters, canonical) && nextAliases[alias] !== canonical) {\n aliasMap.delete(alias);\n }\n }\n for (const alias of Object.keys(nextAliases)) {\n aliasMap.set(alias, nextAliases[alias]);\n }\n // 登録が変われば解決済みの答えも変わりうる(同じページで 2 回 install することは無いが、\n // テストと tooling は登録簿を入れ替える)\n resolvedByKey.clear();\n}\n\n/** 登録済みの名前(core のものを含む)。診断の did-you-mean が読む */\nexport function knownFilterNames(filterIOType: FilterIOType): string[] {\n return [...new Set([...CORE_FILTERS.keys(), ...registries[filterIOType].keys()])];\n}\n\n/** 解決済みの答えを捨てる(tooling: `@wcstack/state/parser` の clearParserCaches) */\nexport function clearFilterResolutionCache(): void {\n resolvedByKey.clear();\n}\n\n/**\n * 実関数を引く(束縛計画の段)。未知のフィルタはここで落ちる — 解析の段では落とさない。\n * 文言は lint の `wcs/filter-unknown` と同じ語彙・同じ did-you-mean 規準(三面同語彙)。\n */\nexport function resolveFilterFn(\n filterName: string,\n args: string[],\n filterIOType: FilterIOType,\n literals: readonly unknown[] = args,\n): FilterFn {\n // 旧名(`uc` / `fix` …)は正式名で引く — 3.x の間のエイリアス(要件 B12、4.0 で外す)。\n // 鍵も**正式名**で作るので、`uc` と `upper` は同じ実関数を共有する(旧名 1 つにつき\n // クロージャが 1 つ増えていた)\n const canonical = aliasesByIOType[filterIOType].get(filterName) ?? filterName;\n // 引数の鍵は `binding/filterKey.ts` の 1 本に集約する(原文 `args` と型付きの値 `literals` の\n // 両方 — 要件 B3 / B9)。ハンドラ共有キー側と同じ関数を通すことで、規準のずれを構造的に止める\n const key = `${canonical}${filterArgsKey(args, literals)}:${filterIOType}`;\n const resolved = resolvedByKey.get(key);\n if (typeof resolved !== \"undefined\") {\n return resolved;\n }\n const factory = registries[filterIOType].get(canonical) ?? CORE_FILTERS.get(canonical);\n if (typeof factory === \"undefined\") {\n // 書式フィルタ(`uc` / `date` …)は `features/formats` が install で登録する。1 つも\n // 登録されていないページは「打ち間違い」ではなく「機能の入れ忘れ」なので、そこまで案内する\n const missingFormats = registries[filterIOType].size === 0\n ? ` No formatting filters are installed — add them with installFeatures([...]) from \"@wcstack/state/features/formats\".`\n : \"\";\n raiseError(`[wcs/filter-unknown] filter not found: ${filterName}.${didYouMean(filterName, knownFilterNames(filterIOType))}${missingFormats}${LINT_HINT}`);\n }\n const bounds = aritiesByIOType[filterIOType].get(canonical) ?? CORE_ARITIES.get(canonical);\n if (typeof bounds !== \"undefined\" && (args.length < bounds[0] || args.length > bounds[1])) {\n // lint の wcs/filter-arity と同じ語彙\n raiseError(args.length < bounds[0]\n ? `[wcs/filter-arity] filter \"${filterName}\" requires at least ${bounds[0]} argument(s) (${args.length} given).${LINT_HINT}`\n : `[wcs/filter-arity] filter \"${filterName}\" accepts at most ${bounds[1]} argument(s) (${args.length} given).${LINT_HINT}`);\n }\n const filterFn = factory(args, literals);\n resolvedByKey.set(key, filterFn);\n return filterFn;\n}\n"],"names":["SSR_SNAPSHOT_BUILDER_KEY","Symbol","for","isOrchestratedSsr","html","document","documentElement","getAttribute","inSsr","hasAttribute","_config","bindAttributeName","commentTextPrefix","commentForPrefix","commentIfPrefix","commentElseIfPrefix","commentElsePrefix","tagNames","state","ssr","locale","debug","enableMustache","enableDirectionalInitialSync","enablePropagationContext","enableContractAnalyzer","sameValueGuard","config","getConfig","setConfig","partialConfig","Object","assign","filterArgsKey","args","literals","JSON","stringify","filterListKey","filters","length","key","i","filter","filterName","CORE_FILTERS","Map","value","CORE_ARITIES","registries","input","output","aritiesByIOType","aliasesByIOType","resolvedByKey","registerFilters","filterIOType","arity","aliases","registry","arities","name","keys","set","bounds","delete","nextAliases","aliasMap","alias","canonical","prototype","hasOwnProperty","call","clear","resolveFilterFn","get","resolved","factory","missingFormats","size","raiseError","didYouMean","Set","knownFilterNames","LINT_HINT","filterFn"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{r as e}from"./errorGuidance.js";import{az as t}from"./binder.js";const n=Symbol("wcs.notHandled"),r=["read","readMissing","write","writeMissing","writeObserve","written","swapped","get","indexShift","handlerScope","updated","suppressPathDiagnostic","rowReused"],s=new Map;function o(e,t){s.set(e,t)}function i(n,r){const o=s.get(n);return void 0===o&&e(t(n,`"${r}"`)),o}function a(){return{read:[],readMissing:[],write:[],writeMissing:[],writeObserve:[],written:[],swapped:[],get:[],indexShift:[],handlerScope:[],updated:[],suppressPathDiagnostic:[],rowReused:[]}}function c(e,t){for(let n=0;n<r.length;n++){const s=r[n],o=t[s];if(void 0===o)continue;const i=e[s];i.includes(o)||i.push(o)}}function l(){const e=new Map;return{get:t=>e.get(t),set(t,n){e.set(t,n)}}}const f=new Map;let u=[],p=[];function d(e,t){f.set(e,t),u=Array.from(f.values()).sort((e,t)=>e.order-t.order),p=u.slice().reverse()}function g(e,t,n){for(let r=0;r<u.length;r++)u[r].validateEarly?.(e,t,n)}function h(e,t,n){for(let r=0;r<u.length;r++)u[r].preCommit?.(e,t,n)}function w(e,t,n){for(let r=0;r<u.length;r++)u[r].validate?.(e,t,n)}function v(e,t,n){for(let r=0;r<u.length;r++)u[r].applyEarly?.(e,t,n)}function b(e,t,n){for(let r=0;r<u.length;r++)u[r].apply?.(e,t,n)}function m(e,t,n){for(let r=0;r<u.length;r++)u[r].register?.(e,t,n)}function y(e,t){for(let n=0;n<u.length;n++)u[n].activate?.(e,t)}function O(e){for(let t=0;t<p.length;t++)p[t].deactivate?.(e)}function j(e){const t=[];let n=e;for(;n&&n!==Object.prototype;)t.push(n),n=Object.getPrototypeOf(n);const r={};for(let e=t.length-1;e>=0;e--)Object.assign(r,Object.getOwnPropertyDescriptors(t[e]));return r}export{n as N,o as a,g as b,w as c,h as d,v as e,b as f,j as g,m as h,y as i,O as j,i as k,a as l,c as m,l as n,d as r};
1
+ import{r as e}from"./errorGuidance.js";import{aB as t}from"./binder.js";const s=Symbol("wcs.notHandled"),r=["read","readMissing","write","writeMissing","writeObserve","written","swapped","get","indexShift","handlerScope","updated","suppressPathDiagnostic","rowReused"],n=new Map;function i(e,t){n.set(e,t)}function o(s,r){const i=n.get(s);return void 0===i&&e(t(s,`"${r}"`)),i}function a(){return{read:[],readMissing:[],write:[],writeMissing:[],writeObserve:[],written:[],swapped:[],get:[],indexShift:[],handlerScope:[],updated:[],suppressPathDiagnostic:[],rowReused:[]}}function c(e,t){for(let s=0;s<r.length;s++){const n=r[s],i=t[n];if(void 0===i)continue;const o=e[n];o.includes(i)||o.push(i)}}function d(e){const t=[];let s=e;for(;s&&s!==Object.prototype;)t.push(s),s=Object.getPrototypeOf(s);const r={};for(let e=t.length-1;e>=0;e--)Object.assign(r,Object.getOwnPropertyDescriptors(t[e]));return r}export{s as N,o as a,c as b,a as c,d as g,i as r};
2
2
  //# sourceMappingURL=getAllPropertyDescriptors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getAllPropertyDescriptors.js","sources":["../../../../../src/core/addressHooks.ts","../../../../../src/core/declarationHooks.ts","../../../../../src/getAllPropertyDescriptors.ts"],"sourcesContent":["/**\n * core/addressHooks.ts — 読み書き境界の受け口(設計案 H1、S3)。\n *\n * 機能は `install()` でレジストリに hook 実装を置く(hot path には触れない)。state 要素は\n * 宣言が要求する機能の hook だけを `attachAddressHooks` で自分に付け、core の各受け口は\n * `stateElement.addressHooks` が null なら判定 1 回で抜ける\n * (調査 §10.8: 大域配列の走査は読み +40%、state ごとの門なら +0.1 ns)。\n * 宣言が要求する機能が未 install なら `requireFeature` が宣言時に throw する(readiness barrier、D13)。\n *\n * 受け口(core 側の呼び出し点):\n * read getByAddress の先頭(キャッシュより前)。名前空間・マーカーなど raw state に無い値を答える\n * readMissing getByAddress で「ツリーにそのキーが無い」と分かった点(親の値つき。親が無ければ null)\n * write setByAddress の先頭。書き込みを奪うか、禁止して throw する\n * writeMissing setByAddress の fast path で「親にそのキーが無い」と分かった点(公開 getter への書き込み)\n * writeObserve 旧値が分かった点(同値ガードの直後)。旧値の台帳を持つ機能が読む\n * written 書き込み・`$postUpdate` の後。観測面へ通知する機能が読む\n * swapped 要素の入れ替えで行が動いた点(旧値の台帳を行に追従させる)\n * get get トラップの文字列プロパティ先頭。API・名前空間・パスの翻訳を答える\n * indexShift `$n` の解決点。スコープ相対の段ずれを足す\n * handlerScope イベントハンドラの添字の段数を決める点\n * updated `$updatedCallback` の後。相対配送する機能が読む\n * suppressPathDiagnostic 束縛時の未宣言パス診断を黙らせるか(予約済みスロットの配下など)\n * rowReused その場で使い回した行(DOM から外れない)の点。行の中のスコープを新しい listIndex へ張り直す\n */\nimport type { IAbsoluteStateAddress, IPathInfo, IStateAddress } from \"../address/types\";\nimport type { IStateElement } from \"../components/types\";\nimport type { ILoopContext } from \"../list/types\";\nimport type { IStateHandler } from \"../proxy/types\";\nimport type { IContent } from \"../structural/types\";\nimport { raiseError } from \"../raiseError\";\nimport { featureNotInstalledMessage } from \"./featureEntries\";\n\nexport const NOT_HANDLED: unique symbol = Symbol(\"wcs.notHandled\");\nexport type ReadHook = (stateElement: IStateElement, address: IStateAddress, receiver: any, handler: IStateHandler) => unknown;\nexport type ReadMissingHook = (stateElement: IStateElement, address: IStateAddress, parentValue: object | null, receiver: any, handler: IStateHandler) => unknown;\nexport type WriteHook = (stateElement: IStateElement, address: IStateAddress, value: unknown, receiver: any, handler: IStateHandler) => unknown;\nexport type WriteMissingHook = (stateElement: IStateElement, address: IStateAddress, parentValue: object, key: PropertyKey, value: unknown, receiver: any, handler: IStateHandler) => unknown;\nexport type WriteObserveHook = (stateElement: IStateElement, path: string, absAddress: IAbsoluteStateAddress, oldValue: unknown, hasOldValue: boolean) => void;\nexport type WrittenHook = (stateElement: IStateElement, pathInfo: IPathInfo, detail?: { readonly value: unknown }) => void;\nexport type SwappedHook = (stateElement: IStateElement, elementAbsAddress: IAbsoluteStateAddress, displacedAbsAddress: IAbsoluteStateAddress) => void;\nexport type GetHook = (handler: IStateHandler, prop: string, receiver: any, target: object) => unknown;\nexport type IndexShiftHook = (handler: IStateHandler, lastAddress: IStateAddress) => number;\nexport type HandlerScopeHook = (stateElement: IStateElement, node: Node, rootNode: Node, loopContext: ILoopContext, wildcardCount: number) => number;\nexport type UpdatedHook = (stateElement: IStateElement, refs: IAbsoluteStateAddress[], receiver: any) => void;\nexport type SuppressPathDiagnosticHook = (stateElement: IStateElement, path: string) => boolean;\nexport type RowReusedHook = (stateElement: IStateElement, content: IContent) => void;\n\nexport interface IAddressHooks {\n readonly read?: ReadHook;\n readonly readMissing?: ReadMissingHook;\n readonly write?: WriteHook;\n readonly writeMissing?: WriteMissingHook;\n readonly writeObserve?: WriteObserveHook;\n readonly written?: WrittenHook;\n readonly swapped?: SwappedHook;\n readonly get?: GetHook;\n readonly indexShift?: IndexShiftHook;\n readonly handlerScope?: HandlerScopeHook;\n readonly updated?: UpdatedHook;\n readonly suppressPathDiagnostic?: SuppressPathDiagnosticHook;\n readonly rowReused?: RowReusedHook;\n}\n/** state 要素に付いた hook 群(種類ごとに、機能の登録順) */\nexport type IAttachedHooks = { readonly [K in keyof Required<IAddressHooks>]: NonNullable<IAddressHooks[K]>[] };\n\nconst HOOK_KINDS: readonly (keyof IAddressHooks)[] = [\n \"read\", \"readMissing\", \"write\", \"writeMissing\", \"writeObserve\", \"written\", \"swapped\",\n \"get\", \"indexShift\", \"handlerScope\", \"updated\", \"suppressPathDiagnostic\", \"rowReused\",\n];\n\nconst registry = new Map<string, IAddressHooks>();\n\n/** 機能の install が呼ぶ(冪等)。hot path には触れない */\nexport function registerFeatureHooks(feature: string, hooks: IAddressHooks): void {\n registry.set(feature, hooks);\n}\n\nexport function isFeatureRegistered(feature: string): boolean {\n return registry.has(feature);\n}\n\n/** 宣言 `declaration` が機能 `feature` を要求した: 未 install なら名指しで throw する(D13) */\nexport function requireFeature(feature: string, declaration: string): IAddressHooks {\n const hooks = registry.get(feature);\n if (typeof hooks === \"undefined\") {\n raiseError(featureNotInstalledMessage(feature, `\"${declaration}\"`));\n }\n return hooks;\n}\n\nexport function createAttachedHooks(): IAttachedHooks {\n return {\n read: [], readMissing: [], write: [], writeMissing: [], writeObserve: [], written: [], swapped: [],\n get: [], indexShift: [], handlerScope: [], updated: [], suppressPathDiagnostic: [], rowReused: [],\n };\n}\n\n/** `hooks` を `attached` に足す(同じ実装は 1 回だけ) */\nexport function appendHooks(attached: IAttachedHooks, hooks: IAddressHooks): void {\n for (let i = 0; i < HOOK_KINDS.length; i++) {\n const kind = HOOK_KINDS[i];\n const fn = hooks[kind];\n if (typeof fn === \"undefined\") continue;\n const list = attached[kind] as unknown[];\n if (!list.includes(fn)) list.push(fn);\n }\n}\n\n/** テスト・モック用: 機能の hook 群だけを持つ束を作る */\nexport function createAttachedHooksFrom(...hooksList: IAddressHooks[]): IAttachedHooks {\n const attached = createAttachedHooks();\n for (const hooks of hooksList) appendHooks(attached, hooks);\n return attached;\n}\n","/**\n * core/declarationHooks.ts — 宣言の受け口(設計案 H4、S4)。\n *\n * `_state` セッターはこのパッケージで最も順序に敏感なコードで、どの検証が世代を進める前に走り\n * どれが後かがそのままテスト(`integration.stateGenerationReset.test.ts`)で固定されている。\n * だから受け口は「予約キーを走査して handler に渡す」1 点ではなく、**段(phase)**にした。\n * 機能は自分が要る段だけ実装し、core は各段を従来の分岐があった位置で呼ぶ。\n *\n * validateEarly core 自身のトークン / `$listKeys` の解析より前(`$recursion` はここで解析される)\n * validate 世代を進める前(`value` しか読まない検証。ここで throw した再セットは世代を進めない)\n * preCommit 検証がすべて済み、まだ世代を進めていない点(旧世代の後始末と差し替え)\n * applyEarly `__state` の差し替え直後・`$on` の配線より前(`$scan` の出力の実体化と購読)\n * apply 新しい getterPaths / setterPaths の収集後(`$streams` の衝突検査がそれを見る)\n * register `_rebuildPathInfo` と `$scan` の登録の後(依存グラフへの登録)\n * activate 接続中の再 set と、接続の末尾(起動の可否と二重起動ガードは機能側が持つ)\n * deactivate 切断\n *\n * apply / register / activate は `order` の昇順、**deactivate は降順**で聞く。\n * これが「watch は stream より先に起動し、後に停止する」を番号だけで保つ\n * (従来 `State` に直書きされていた順序契約)。\n *\n * **文脈袋**(`IDeclarationContext`): 段を跨いで機能どうしが値を渡す口。core は自分が作った値\n * (`$eventTokens` の名前・再帰レジストリ)を publish し、`$scan` の検証がそれを読む。解析した\n * エントリも袋に入れて validate → applyEarly → register を渡り歩く。1 回の set につき 1 つ作る。\n */\nimport type { IStateElement } from \"../components/types\";\nimport type { IState } from \"../types\";\n\n/** 1 回の `_state` set の間だけ生きる、機能どうしの受け渡し口 */\nexport interface IDeclarationContext {\n get<T>(key: string): T | undefined;\n set(key: string, value: unknown): void;\n}\n\nexport function createDeclarationContext(): IDeclarationContext {\n const values = new Map<string, unknown>();\n return {\n get<T>(key: string): T | undefined {\n return values.get(key) as T | undefined;\n },\n set(key: string, value: unknown): void {\n values.set(key, value);\n },\n };\n}\n\nexport interface IDeclarationHooks {\n /** 聞く順(watch 10 → streams 20。deactivate はこの逆順) */\n readonly order: number;\n readonly validateEarly?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly validate?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly preCommit?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly applyEarly?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly apply?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n readonly register?: (element: IStateElement, value: IState, ctx: IDeclarationContext) => void;\n /**\n * `captured` が null なら `_state` セッターからの起動(接続中の再 set)、\n * 数値なら接続の末尾からの起動で、その接続で捕捉した世代(陳腐な connect の再開を弾く)。\n */\n readonly activate?: (element: IStateElement, captured: number | null) => void;\n readonly deactivate?: (element: IStateElement) => void;\n}\n\nconst registry = new Map<string, IDeclarationHooks>();\nlet ordered: IDeclarationHooks[] = [];\nlet reversed: IDeclarationHooks[] = [];\n\n/** 機能の install が呼ぶ(冪等) */\nexport function registerDeclarationHooks(feature: string, hooks: IDeclarationHooks): void {\n registry.set(feature, hooks);\n ordered = Array.from(registry.values()).sort((a, b) => a.order - b.order);\n reversed = ordered.slice().reverse();\n}\n\nexport function runValidateEarly(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].validateEarly?.(element, value, ctx);\n }\n}\n\nexport function runPreCommit(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].preCommit?.(element, value, ctx);\n }\n}\n\nexport function runValidate(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].validate?.(element, value, ctx);\n }\n}\n\nexport function runApplyEarly(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].applyEarly?.(element, value, ctx);\n }\n}\n\nexport function runApply(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].apply?.(element, value, ctx);\n }\n}\n\nexport function runRegister(element: IStateElement, value: IState, ctx: IDeclarationContext): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].register?.(element, value, ctx);\n }\n}\n\nexport function runActivate(element: IStateElement, captured: number | null): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].activate?.(element, captured);\n }\n}\n\n/** 停止は起動の逆順(stream を止めてから watch を外す) */\nexport function runDeactivate(element: IStateElement): void {\n for (let i = 0; i < reversed.length; i++) {\n reversed[i].deactivate?.(element);\n }\n}\n","/**\n * オブジェクトの自身+プロトタイプチェーン(Object.prototype 手前まで)の\n * property descriptor を 1 つの辞書に畳んで返す。\n *\n * state の getterPaths / setterPaths 収集(components/State.ts)と DCC の\n * アクセサ生成(dcc/defineDCC.ts)で共有する。両者が別々の走査をしていたため、\n * クラスインスタンスや Object.create(proto) の state で\n * 「getterPaths には載るのに DCC prototype にアクセサが生えない」という\n * 乖離が生じていた\n * (docs/architecture-hardening/15-state-component-mechanism-consistency.md §2.4)。\n *\n * 遠いプロトタイプから順に畳むので、同名は**手前(自身に近い側)が勝つ**\n * = プロパティ解決の実際の優先順位と一致する。名前の集合しか見ない\n * getterPaths / setterPaths には影響しないが、descriptor の中身を見て\n * アクセサを生やす DCC 側では優先順位が意味を持つ。\n *\n * オブジェクトリテラルの state では getPrototypeOf が即 Object.prototype になるため、\n * own descriptor のみを見るのと結果は変わらない。\n */\nexport type Descriptors = Record<string, PropertyDescriptor>;\n\nexport function getAllPropertyDescriptors(obj: object): Descriptors {\n const chain: object[] = [];\n let proto: object | null = obj;\n while (proto && proto !== Object.prototype) {\n chain.push(proto);\n proto = Object.getPrototypeOf(proto);\n }\n const descriptors: Descriptors = {};\n for (let i = chain.length - 1; i >= 0; i--) {\n Object.assign(descriptors, Object.getOwnPropertyDescriptors(chain[i]));\n }\n return descriptors;\n}\n"],"names":["NOT_HANDLED","Symbol","HOOK_KINDS","registry","Map","registerFeatureHooks","feature","hooks","set","requireFeature","declaration","get","raiseError","featureNotInstalledMessage","createAttachedHooks","read","readMissing","write","writeMissing","writeObserve","written","swapped","indexShift","handlerScope","updated","suppressPathDiagnostic","rowReused","appendHooks","attached","i","length","kind","fn","list","includes","push","createDeclarationContext","values","key","value","ordered","reversed","registerDeclarationHooks","Array","from","sort","a","b","order","slice","reverse","runValidateEarly","element","ctx","validateEarly","runPreCommit","preCommit","runValidate","validate","runApplyEarly","applyEarly","runApply","apply","runRegister","register","runActivate","captured","activate","runDeactivate","deactivate","getAllPropertyDescriptors","obj","chain","proto","Object","prototype","getPrototypeOf","descriptors","assign","getOwnPropertyDescriptors"],"mappings":"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"}
1
+ {"version":3,"file":"getAllPropertyDescriptors.js","sources":["../../../../../src/core/addressHooks.ts","../../../../../src/getAllPropertyDescriptors.ts"],"sourcesContent":["/**\n * core/addressHooks.ts — 読み書き境界の受け口(設計案 H1、S3)。\n *\n * 機能は `install()` でレジストリに hook 実装を置く(hot path には触れない)。state 要素は\n * 宣言が要求する機能の hook だけを `attachAddressHooks` で自分に付け、core の各受け口は\n * `stateElement.addressHooks` が null なら判定 1 回で抜ける\n * (調査 §10.8: 大域配列の走査は読み +40%、state ごとの門なら +0.1 ns)。\n * 宣言が要求する機能が未 install なら `requireFeature` が宣言時に throw する(readiness barrier、D13)。\n *\n * 受け口(core 側の呼び出し点):\n * read getByAddress の先頭(キャッシュより前)。名前空間・マーカーなど raw state に無い値を答える\n * readMissing getByAddress で「ツリーにそのキーが無い」と分かった点(親の値つき。親が無ければ null)\n * write setByAddress の先頭。書き込みを奪うか、禁止して throw する\n * writeMissing setByAddress の fast path で「親にそのキーが無い」と分かった点(公開 getter への書き込み)\n * writeObserve 旧値が分かった点(同値ガードの直後)。旧値の台帳を持つ機能が読む\n * written 書き込み・`$postUpdate` の後。観測面へ通知する機能が読む\n * swapped 要素の入れ替えで行が動いた点(旧値の台帳を行に追従させる)\n * get get トラップの文字列プロパティ先頭。API・名前空間・パスの翻訳を答える\n * indexShift `$n` の解決点。スコープ相対の段ずれを足す\n * handlerScope イベントハンドラの添字の段数を決める点\n * updated `$updatedCallback` の後。相対配送する機能が読む\n * suppressPathDiagnostic 束縛時の未宣言パス診断を黙らせるか(予約済みスロットの配下など)\n * rowReused その場で使い回した行(DOM から外れない)の点。行の中のスコープを新しい listIndex へ張り直す\n */\nimport type { IAbsoluteStateAddress, IPathInfo, IStateAddress } from \"../address/types\";\nimport type { IStateElement } from \"../components/types\";\nimport type { ILoopContext } from \"../list/types\";\nimport type { IStateHandler } from \"../proxy/types\";\nimport type { IContent } from \"../structural/types\";\nimport { raiseError } from \"../raiseError\";\nimport { featureNotInstalledMessage } from \"./featureEntries\";\n\nexport const NOT_HANDLED: unique symbol = Symbol(\"wcs.notHandled\");\nexport type ReadHook = (stateElement: IStateElement, address: IStateAddress, receiver: any, handler: IStateHandler) => unknown;\nexport type ReadMissingHook = (stateElement: IStateElement, address: IStateAddress, parentValue: object | null, receiver: any, handler: IStateHandler) => unknown;\nexport type WriteHook = (stateElement: IStateElement, address: IStateAddress, value: unknown, receiver: any, handler: IStateHandler) => unknown;\nexport type WriteMissingHook = (stateElement: IStateElement, address: IStateAddress, parentValue: object, key: PropertyKey, value: unknown, receiver: any, handler: IStateHandler) => unknown;\nexport type WriteObserveHook = (stateElement: IStateElement, path: string, absAddress: IAbsoluteStateAddress, oldValue: unknown, hasOldValue: boolean) => void;\nexport type WrittenHook = (stateElement: IStateElement, pathInfo: IPathInfo, detail?: { readonly value: unknown }) => void;\nexport type SwappedHook = (stateElement: IStateElement, elementAbsAddress: IAbsoluteStateAddress, displacedAbsAddress: IAbsoluteStateAddress) => void;\nexport type GetHook = (handler: IStateHandler, prop: string, receiver: any, target: object) => unknown;\nexport type IndexShiftHook = (handler: IStateHandler, lastAddress: IStateAddress) => number;\n/**\n * ハンドラが受け取る添字の段数を決める(`event/handler.ts`)。\n *\n * **合成は未定義** — この hook は畳み込み(前の hook の結果が次の `wildcardCount` になる)で\n * 呼ばれるが、現行唯一の実装(`webComponent/addressHooks.ts` の scopes)は「記録が引けて\n * shift が無ければ 0」を返す**吸収型**で、可換でも結合的でもない。2 つ目の実装が足されると\n * `0 - shift` のような負値になりうる。**実装は 1 つに保つこと**。2 つ目が要るなら、先に\n * 「答えを持たない hook は次へ渡す」規約(`NOT_HANDLED` を返す形。`read` / `write` と同じ)\n * へ寄せてから足す。\n */\nexport type HandlerScopeHook = (stateElement: IStateElement, node: Node, rootNode: Node, loopContext: ILoopContext, wildcardCount: number) => number;\nexport type UpdatedHook = (stateElement: IStateElement, refs: IAbsoluteStateAddress[], receiver: any) => void;\nexport type SuppressPathDiagnosticHook = (stateElement: IStateElement, path: string) => boolean;\nexport type RowReusedHook = (stateElement: IStateElement, content: IContent) => void;\n\nexport interface IAddressHooks {\n readonly read?: ReadHook;\n readonly readMissing?: ReadMissingHook;\n readonly write?: WriteHook;\n readonly writeMissing?: WriteMissingHook;\n readonly writeObserve?: WriteObserveHook;\n readonly written?: WrittenHook;\n readonly swapped?: SwappedHook;\n readonly get?: GetHook;\n readonly indexShift?: IndexShiftHook;\n readonly handlerScope?: HandlerScopeHook;\n readonly updated?: UpdatedHook;\n readonly suppressPathDiagnostic?: SuppressPathDiagnosticHook;\n readonly rowReused?: RowReusedHook;\n}\n/** state 要素に付いた hook 群(種類ごとに、機能の登録順) */\nexport type IAttachedHooks = { readonly [K in keyof Required<IAddressHooks>]: NonNullable<IAddressHooks[K]>[] };\n\nconst HOOK_KINDS: readonly (keyof IAddressHooks)[] = [\n \"read\", \"readMissing\", \"write\", \"writeMissing\", \"writeObserve\", \"written\", \"swapped\",\n \"get\", \"indexShift\", \"handlerScope\", \"updated\", \"suppressPathDiagnostic\", \"rowReused\",\n];\n\nconst registry = new Map<string, IAddressHooks>();\n\n/** 機能の install が呼ぶ(冪等)。hot path には触れない */\nexport function registerFeatureHooks(feature: string, hooks: IAddressHooks): void {\n registry.set(feature, hooks);\n}\n\nexport function isFeatureRegistered(feature: string): boolean {\n return registry.has(feature);\n}\n\n/** 宣言 `declaration` が機能 `feature` を要求した: 未 install なら名指しで throw する(D13) */\nexport function requireFeature(feature: string, declaration: string): IAddressHooks {\n const hooks = registry.get(feature);\n if (typeof hooks === \"undefined\") {\n raiseError(featureNotInstalledMessage(feature, `\"${declaration}\"`));\n }\n return hooks;\n}\n\nexport function createAttachedHooks(): IAttachedHooks {\n return {\n read: [], readMissing: [], write: [], writeMissing: [], writeObserve: [], written: [], swapped: [],\n get: [], indexShift: [], handlerScope: [], updated: [], suppressPathDiagnostic: [], rowReused: [],\n };\n}\n\n/** `hooks` を `attached` に足す(同じ実装は 1 回だけ) */\nexport function appendHooks(attached: IAttachedHooks, hooks: IAddressHooks): void {\n for (let i = 0; i < HOOK_KINDS.length; i++) {\n const kind = HOOK_KINDS[i];\n const fn = hooks[kind];\n if (typeof fn === \"undefined\") continue;\n const list = attached[kind] as unknown[];\n if (!list.includes(fn)) list.push(fn);\n }\n}\n\n/** テスト・モック用: 機能の hook 群だけを持つ束を作る */\nexport function createAttachedHooksFrom(...hooksList: IAddressHooks[]): IAttachedHooks {\n const attached = createAttachedHooks();\n for (const hooks of hooksList) appendHooks(attached, hooks);\n return attached;\n}\n","/**\n * オブジェクトの自身+プロトタイプチェーン(Object.prototype 手前まで)の\n * property descriptor を 1 つの辞書に畳んで返す。\n *\n * state の getterPaths / setterPaths 収集(components/State.ts)と DCC の\n * アクセサ生成(dcc/defineDCC.ts)で共有する。両者が別々の走査をしていたため、\n * クラスインスタンスや Object.create(proto) の state で\n * 「getterPaths には載るのに DCC prototype にアクセサが生えない」という\n * 乖離が生じていた\n * (docs/architecture-hardening/15-state-component-mechanism-consistency.md §2.4)。\n *\n * 遠いプロトタイプから順に畳むので、同名は**手前(自身に近い側)が勝つ**\n * = プロパティ解決の実際の優先順位と一致する。名前の集合しか見ない\n * getterPaths / setterPaths には影響しないが、descriptor の中身を見て\n * アクセサを生やす DCC 側では優先順位が意味を持つ。\n *\n * オブジェクトリテラルの state では getPrototypeOf が即 Object.prototype になるため、\n * own descriptor のみを見るのと結果は変わらない。\n */\nexport type Descriptors = Record<string, PropertyDescriptor>;\n\nexport function getAllPropertyDescriptors(obj: object): Descriptors {\n const chain: object[] = [];\n let proto: object | null = obj;\n while (proto && proto !== Object.prototype) {\n chain.push(proto);\n proto = Object.getPrototypeOf(proto);\n }\n const descriptors: Descriptors = {};\n for (let i = chain.length - 1; i >= 0; i--) {\n Object.assign(descriptors, Object.getOwnPropertyDescriptors(chain[i]));\n }\n return descriptors;\n}\n"],"names":["NOT_HANDLED","Symbol","HOOK_KINDS","registry","Map","registerFeatureHooks","feature","hooks","set","requireFeature","declaration","get","raiseError","featureNotInstalledMessage","createAttachedHooks","read","readMissing","write","writeMissing","writeObserve","written","swapped","indexShift","handlerScope","updated","suppressPathDiagnostic","rowReused","appendHooks","attached","i","length","kind","fn","list","includes","push","getAllPropertyDescriptors","obj","chain","proto","Object","prototype","getPrototypeOf","descriptors","assign","getOwnPropertyDescriptors"],"mappings":"8EAgCaA,EAA6BC,OAAO,kBA2C3CC,EAA+C,CACnD,OAAQ,cAAe,QAAS,eAAgB,eAAgB,UAAW,UAC3E,MAAO,aAAc,eAAgB,UAAW,yBAA0B,aAGtEC,EAAW,IAAIC,IAGf,SAAUC,EAAqBC,EAAiBC,GACpDJ,EAASK,IAAIF,EAASC,EACxB,CAOM,SAAUE,EAAeH,EAAiBI,GAC9C,MAAMH,EAAQJ,EAASQ,IAAIL,GAI3B,YAHqB,IAAVC,GACTK,EAAWC,EAA2BP,EAAS,IAAII,OAE9CH,CACT,UAEgBO,IACd,MAAO,CACLC,KAAM,GAAIC,YAAa,GAAIC,MAAO,GAAIC,aAAc,GAAIC,aAAc,GAAIC,QAAS,GAAIC,QAAS,GAChGV,IAAK,GAAIW,WAAY,GAAIC,aAAc,GAAIC,QAAS,GAAIC,uBAAwB,GAAIC,UAAW,GAEnG,CAGM,SAAUC,EAAYC,EAA0BrB,GACpD,IAAK,IAAIsB,EAAI,EAAGA,EAAI3B,EAAW4B,OAAQD,IAAK,CAC1C,MAAME,EAAO7B,EAAW2B,GAClBG,EAAKzB,EAAMwB,GACjB,QAAkB,IAAPC,EAAoB,SAC/B,MAAMC,EAAOL,EAASG,GACjBE,EAAKC,SAASF,IAAKC,EAAKE,KAAKH,EACpC,CACF,CC/FM,SAAUI,EAA0BC,GACxC,MAAMC,EAAkB,GACxB,IAAIC,EAAuBF,EAC3B,KAAOE,GAASA,IAAUC,OAAOC,WAC/BH,EAAMH,KAAKI,GACXA,EAAQC,OAAOE,eAAeH,GAEhC,MAAMI,EAA2B,CAAA,EACjC,IAAK,IAAId,EAAIS,EAAMR,OAAS,EAAGD,GAAK,EAAGA,IACrCW,OAAOI,OAAOD,EAAaH,OAAOK,0BAA0BP,EAAMT,KAEpE,OAAOc,CACT"}
@@ -1,2 +1,2 @@
1
- import{r as t}from"./errorGuidance.js";import{az as e}from"./binder.js";const n="https://github.com/wcstack/wcstack/blob/main/docs/csp.md";let r=0;async function i(t,e){let i=null;const o=`\n//# sourceURL=${e}#${++r}\n`;let a=!1;const c=t=>{t.effectiveDirective.startsWith("script-src")&&(a=!0)};document.addEventListener("securitypolicyviolation",c);try{if("function"==typeof URL.createObjectURL){const e=new Blob([t.text+o],{type:"application/javascript"}),n=URL.createObjectURL(e);try{i=await import(n)}finally{URL.revokeObjectURL(n)}}else{const e=btoa(String.fromCodePoint(...(new TextEncoder).encode(t.text+o)));i=await import(`data:application/javascript;base64,${e}`)}}catch(t){throw new Error(function(t,e,r){const i=e?.message??String(e);return r?`The inline <script> of state "${t}" was blocked by Content-Security-Policy. Inline state is evaluated through a blob: URL, so script-src must allow blob:. Prefer moving the state into an external file and loading it with src="./state.js", which requires no extra CSP directive. See ${n}`:`Failed to evaluate the inline <script> of state "${t}": ${i}. If this page sets a Content-Security-Policy, see ${n}`}(e,t,a),{cause:t})}finally{document.removeEventListener("securitypolicyviolation",c)}return i&&"object"==typeof i.default?i.default:{}}async function o(e){try{const t=await import(function(t){return new URL(t,document.baseURI).href}(e));return t.default||{}}catch(e){t(`Failed to load script file: ${e}`)}}const a=Promise.resolve(),c=new Map;let s=[];function l(t,e){c.set(t,e),s=Array.from(c.values()).sort((t,e)=>t.order-e.order)}function u(n,r){return t(e(n,r))}function f(t){for(let e=0;e<s.length;e++){const n=s[e].connecting?.(t);if(null!=n)return n}return null}function d(t){for(let e=0;e<s.length;e++){const n=s[e].preparing?.(t);if(null!=n)return n}return null}function p(t){for(let e=0;e<s.length;e++)if(!0===s[e].reconnecting?.(t))return!0;return!1}function h(t){for(let e=0;e<s.length;e++)s[e].replacingState?.(t)}function g(t,e,n){for(let r=0;r<s.length;r++)s[r].initializeFailed?.(t,e,n)}function m(t,e){for(let n=0;n<s.length;n++)s[n].initializeFailureCleared?.(t,e)}function y(t){for(let e=0;e<s.length;e++)if(!0===s[e].disconnecting?.(t))return!0;return!1}export{a as C,i as a,g as b,f as c,u as d,d as e,p as f,y as g,m as h,h as i,o as l,l as r};
1
+ import{r as t}from"./errorGuidance.js";import{aB as e}from"./binder.js";const n="https://github.com/wcstack/wcstack/blob/main/docs/csp.md";let r=0;async function i(t,e){let i=null;const o=`\n//# sourceURL=${e}#${++r}\n`;let a=!1;const c=t=>{t.effectiveDirective.startsWith("script-src")&&(a=!0)};document.addEventListener("securitypolicyviolation",c);try{if("function"==typeof URL.createObjectURL){const e=new Blob([t.text+o],{type:"application/javascript"}),n=URL.createObjectURL(e);try{i=await import(n)}finally{URL.revokeObjectURL(n)}}else{const e=btoa(String.fromCodePoint(...(new TextEncoder).encode(t.text+o)));i=await import(`data:application/javascript;base64,${e}`)}}catch(t){throw new Error(function(t,e,r){const i=e?.message??String(e);return r?`The inline <script> of state "${t}" was blocked by Content-Security-Policy. Inline state is evaluated through a blob: URL, so script-src must allow blob:. Prefer moving the state into an external file and loading it with src="./state.js", which requires no extra CSP directive. See ${n}`:`Failed to evaluate the inline <script> of state "${t}": ${i}. If this page sets a Content-Security-Policy, see ${n}`}(e,t,a),{cause:t})}finally{document.removeEventListener("securitypolicyviolation",c)}return i&&"object"==typeof i.default?i.default:{}}async function o(e){try{const t=await import(function(t){return new URL(t,document.baseURI).href}(e));return t.default||{}}catch(e){t(`Failed to load script file: ${e}`)}}const a=Promise.resolve(),c=new Map;let s=[];function l(t,e){c.set(t,e),s=Array.from(c.values()).sort((t,e)=>t.order-e.order)}function u(n,r){return t(e(n,r))}function f(t){for(let e=0;e<s.length;e++){const n=s[e].connecting?.(t);if(null!=n)return n}return null}function d(t){for(let e=0;e<s.length;e++){const n=s[e].preparing?.(t);if(null!=n)return n}return null}function p(t){for(let e=0;e<s.length;e++)if(!0===s[e].reconnecting?.(t))return!0;return!1}function h(t){for(let e=0;e<s.length;e++)s[e].replacingState?.(t)}function g(t,e,n){for(let r=0;r<s.length;r++)s[r].initializeFailed?.(t,e,n)}function m(t,e){for(let n=0;n<s.length;n++)s[n].initializeFailureCleared?.(t,e)}function y(t){for(let e=0;e<s.length;e++)if(!0===s[e].disconnecting?.(t))return!0;return!1}export{a as C,i as a,g as b,f as c,u as d,d as e,p as f,y as g,m as h,h as i,o as l,l as r};
2
2
  //# sourceMappingURL=lifecycleHooks.js.map
@@ -1,2 +1,2 @@
1
- import{r as t,L as e,d as a}from"./errorGuidance.js";const s=".",n="*",r=128,i=128,o=32,c=32,l=0,h=10,d=20,u=";",p=":",$="#",w="|",f="prevent",P="stop",m="ro",g="init",y="sync",b="else",v="...",x="on",S="eventToken",I="state",O="command",k="class",j="attr",W="style",A="$",C={};for(let t=0;t<128;t++)C[`$${t+1}`]=t;const T=Object.freeze(C),B=6e4,q="http://www.w3.org/2000/svg",z="$connectedCallback",D="$disconnectedCallback",E="$updatedCallback",G="$errorCallback",K="$stateReadyCallback",L="$bindables",M="$commands",N="$commandTokens",R="$command",F="$eventTokens",H="$on",J="$streams",Q="$watch",U="$scan",V="$recursion",X="**",Y="$listKeys",Z="$streamStatus",_="$streamError",tt="data-wc-definition",et=new Map;let at=0;function st(e){let a=et.get(e);return void 0!==a||(-1!==e.indexOf(X)&&t(`[wcs/recursion-unsupported] "${e}" uses "${X}", which is not accepted here. It is only meaningful in a $recursion declaration, in a recursive getter key, and in the path argument of $getAll / $setAll — and only when the state declares a $recursion anchor.`),a=Object.freeze(new nt(e)),et.set(e,a)),a}class nt{id=++at;path;segments;lastSegment;cumulativePaths;cumulativePathSet;cumulativePathInfos;cumulativePathInfoSet;parentPath;wildcardPaths;wildcardPathSet;indexByWildcardPath;wildcardPathInfos;wildcardPathInfoSet;wildcardParentPaths;wildcardParentPathSet;wildcardParentPathInfos;wildcardParentPathInfoSet;wildcardPositions;lastWildcardPath;lastWildcardInfo;wildcardCount;parentPathInfo;constructor(t){const e=e=>t===e?this:st(e),a=t.split("."),s=[],n=[],r=[],i={},o=[],c=[],l=[],h=[];let d="",u="",p=0;for(let t=0;t<a.length;t++)d+=a[t],"*"===a[t]&&(r.push(d),i[d]=p,o.push(e(d)),c.push(u),l.push(e(u)),h.push(t),p++),s.push(d),n.push(e(d)),u=d,d+=".";const $=r.length>0?r[r.length-1]:null,w=s.length>1?s[s.length-2]:null;this.path=t,this.segments=a,this.lastSegment=a[a.length-1],this.cumulativePaths=s,this.cumulativePathSet=new Set(s),this.cumulativePathInfos=n,this.cumulativePathInfoSet=new Set(n),this.wildcardPaths=r,this.wildcardPathSet=new Set(r),this.indexByWildcardPath=i,this.wildcardPathInfos=o,this.wildcardPathInfoSet=new Set(o),this.wildcardParentPaths=c,this.wildcardParentPathSet=new Set(c),this.wildcardParentPathInfos=l,this.wildcardParentPathInfoSet=new Set(l),this.wildcardPositions=h,this.lastWildcardPath=$,this.lastWildcardInfo=$?e($):null,this.parentPath=w,this.parentPathInfo=w?e(w):null,this.wildcardCount=p}}let rt=null;function it(t){rt=t}function ot(t,e){let a=t;for(;null!==a&&a!==Object.prototype;){const t=Object.getOwnPropertyDescriptor(a,e);if(void 0!==t)return t;a=Object.getPrototypeOf(a)}}function ct(t,e,a){const s=function(t){const e=[];let a=t;for(;null!==a&&a!==Object.prototype;){for(const t of Object.getOwnPropertyNames(a))e.push(t);a=Object.getPrototypeOf(a)}return e}(t),n=e.length>0?e+".":"";for(const t of a){if(n.length>0&&!t.startsWith(n))continue;const e=t.slice(n.length);e.length>0&&-1===e.indexOf(".")&&s.push(e)}return s}const lt={binding:"wcs/binding-path-missing",watch:"wcs/watch-path-missing",scan:"wcs/scan-path-missing"},ht={binding:"Bound path",watch:"$watch path",scan:"$scan path"};function dt(t,s,n){return`[${lt.binding}] Path "${t}" does not exist on the state tree.${a(t,ct(s,"",n))}${e}`}function ut(t,a,s,n){return`[wcs/index-arity] ${t}("${a}") requires ${"$resolve"===t?`exactly ${s}`:`at most ${s}`} index(es) ("*" appears ${s} time(s) in the path) but got ${n}.${e}`}function pt(t,e){return`[wcs/recursion-anchor] "${t}" does not match the declared recursion anchor "${e}". This version supports exactly one anchor per state, and "**" must be followed by a well-formed suffix (no second "**", no empty segment, no bare "*" right after "**").`}function $t(t,e){return`$getAll("${t}") was called without indexes inside the loop context of "${e}", but the path shares no wildcard level with that context, so the context indexes ($1..$n) do not apply. Pass indexes explicitly ([] expands every level).`}function wt(t,e,a){return`$setAll("${t}", …, { spread: true }) requires the values array to have exactly one entry per matched address (matched ${e}) but got ${a}. Did the list change between $getAll and $setAll?`}function ft(t,e){return`$setAll("${t}") ${e}`}function Pt(t,a,s){return`[wcs/wildcard-rank] ${t} needs ${a} enclosing loop level(s) but the current scope provides ${s}. Wrap it in that many "for" templates, or use $resolve(path, indexes) to name the row explicitly.${e}`}export{j as $,G as A,A as B,ot as C,s as D,dt as E,Pt as F,ut as G,$t as H,T as I,wt as J,l as K,it as L,r as M,B as N,q as O,$ as P,w as Q,X as R,U as S,p as T,b as U,I as V,n as W,v as X,S as Y,x as Z,k as _,J as a,W as a0,O as a1,u as a2,f as a3,P as a4,g as a5,y as a6,o as a7,ct as a8,lt as a9,ht as aa,F as b,Z as c,_ as d,d as e,L as f,st as g,M as h,tt as i,m as j,K as k,Q as l,Y as m,V as n,E as o,rt as p,h as q,c as r,pt as s,ft as t,i as u,N as v,R as w,H as x,z as y,D as z};
1
+ import{r as t,L as e,d as a}from"./errorGuidance.js";const s=".",n="*",r=128,i=128,o=32,c=32,l=0,h=10,d=20,u=";",p=":",$="#",f="|",w="prevent",P="stop",m="ro",g="init",y="sync",b="else",v="...",x="on",S="eventToken",I="state",O="command",k="class",j="attr",W="style",A="$",C={};for(let t=0;t<128;t++)C[`$${t+1}`]=t;const T=Object.freeze(C),q=6e4,B="http://www.w3.org/2000/svg",z="$connectedCallback",D="$disconnectedCallback",E="$renderedCallback",G="$errorCallback",K="$stateReadyCallback",L="$bindables",M="$commands",N="$commandTokens",R="$command",F="$eventTokens",H="$on",J="$stream",Q="$watch",U="$scan",V="$recursion",X="**",Y="$listKeys",Z="$streamStatus",_="$streamError",tt="data-wc-definition",et=new Map;let at=0;function st(e){let a=et.get(e);if(void 0!==a)return a;-1!==e.indexOf(X)&&t(`[wcs/recursion-unsupported] "${e}" uses "${X}", which is not accepted here. It is only meaningful in a $recursion declaration, in a recursive getter key, and in the path argument of $getAll / $setAll — and only when the state declares a $recursion anchor.`);const n=function(t){let e=1;for(let a=0;a<t.length;a++)t[a]===s&&e++;return e}(e);return n>512&&t(`[wcs/binding-syntax] "${e}" has ${n} path segments — the limit is 512. Every prefix of a path is interned, so the cost grows with the square of the depth.`),a=Object.freeze(new nt(e)),et.set(e,a),a}class nt{id=++at;path;segments;lastSegment;cumulativePaths;cumulativePathSet;cumulativePathInfos;cumulativePathInfoSet;parentPath;wildcardPaths;wildcardPathSet;indexByWildcardPath;wildcardPathInfos;wildcardPathInfoSet;wildcardParentPaths;wildcardParentPathSet;wildcardParentPathInfos;wildcardParentPathInfoSet;wildcardPositions;lastWildcardPath;lastWildcardInfo;wildcardCount;parentPathInfo;constructor(t){const e=e=>t===e?this:st(e),a=t.split("."),s=[],n=[],r=[],i={},o=[],c=[],l=[],h=[];let d="",u="",p=0;for(let t=0;t<a.length;t++)d+=a[t],"*"===a[t]&&(r.push(d),i[d]=p,o.push(e(d)),c.push(u),l.push(e(u)),h.push(t),p++),s.push(d),n.push(e(d)),u=d,d+=".";const $=r.length>0?r[r.length-1]:null,f=s.length>1?s[s.length-2]:null;this.path=t,this.segments=a,this.lastSegment=a[a.length-1],this.cumulativePaths=s,this.cumulativePathSet=new Set(s),this.cumulativePathInfos=n,this.cumulativePathInfoSet=new Set(n),this.wildcardPaths=r,this.wildcardPathSet=new Set(r),this.indexByWildcardPath=i,this.wildcardPathInfos=o,this.wildcardPathInfoSet=new Set(o),this.wildcardParentPaths=c,this.wildcardParentPathSet=new Set(c),this.wildcardParentPathInfos=l,this.wildcardParentPathInfoSet=new Set(l),this.wildcardPositions=h,this.lastWildcardPath=$,this.lastWildcardInfo=$?e($):null,this.parentPath=f,this.parentPathInfo=f?e(f):null,this.wildcardCount=p}}let rt=null;function it(t){rt=t}function ot(t,e){let a=t;for(;null!==a&&a!==Object.prototype;){const t=Object.getOwnPropertyDescriptor(a,e);if(void 0!==t)return t;a=Object.getPrototypeOf(a)}}function ct(t,e,a){const n=function(t){const e=[];let a=t;for(;null!==a&&a!==Object.prototype;){for(const t of Object.getOwnPropertyNames(a))e.push(t);a=Object.getPrototypeOf(a)}return e}(t),r=e.length>0?e+s:"";for(const t of a){if(r.length>0&&!t.startsWith(r))continue;const e=t.slice(r.length);e.length>0&&-1===e.indexOf(s)&&n.push(e)}return n}const lt={binding:"wcs/binding-path-missing",watch:"wcs/watch-path-missing",scan:"wcs/scan-path-missing"},ht={binding:"Bound path",watch:"$watch path",scan:"$scan path"};function dt(t,s,n){return`[${lt.binding}] Path "${t}" does not exist on the state tree.${a(t,ct(s,"",n))}${e}`}function ut(t,a,s,n){return`[wcs/index-arity] ${t}("${a}") requires ${"$resolve"===t?`exactly ${s}`:`at most ${s}`} index(es) ("*" appears ${s} time(s) in the path) but got ${n}.${e}`}function pt(t,e){return`[wcs/recursion-anchor] "${t}" does not match the declared recursion anchor "${e}". This version supports exactly one anchor per state, and "**" must be followed by a well-formed suffix (no second "**", no empty segment, no bare "*" right after "**").`}function $t(t,e){return`$getAll("${t}") was called without indexes inside the loop context of "${e}", but the path shares no wildcard level with that context, so the context indexes ($1..$n) do not apply. Pass indexes explicitly ([] expands every level).`}function ft(t,e,a){return`$setAll("${t}", …, { spread: true }) requires the values array to have exactly one entry per matched address (matched ${e}) but got ${a}. Did the list change between $getAll and $setAll?`}function wt(t,e){return`$setAll("${t}") ${e}`}function Pt(t,a,s){return`[wcs/wildcard-rank] ${t} needs ${a} enclosing loop level(s) but the current scope provides ${s}. Wrap it in that many "for" templates, or use $resolve(path, indexes) to name the row explicitly.${e}`}export{j as $,G as A,A as B,ot as C,s as D,dt as E,Pt as F,ut as G,$t as H,T as I,ft as J,l as K,it as L,r as M,q as N,B as O,$ as P,f as Q,X as R,U as S,b as T,v as U,I as V,n as W,S as X,x as Y,p as Z,k as _,J as a,W as a0,O as a1,u as a2,w as a3,P as a4,g as a5,y as a6,o as a7,ct as a8,lt as a9,ht as aa,F as b,Z as c,rt as d,_ as e,d as f,st as g,Q as h,h as i,c as j,L as k,M as l,tt as m,m as n,E as o,K as p,Y as q,V as r,pt as s,wt as t,i as u,N as v,R as w,H as x,z as y,D as z};
2
2
  //# sourceMappingURL=pathDiagnostics.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pathDiagnostics.js","sources":["../../../../../src/define.ts","../../../../../src/address/PathInfo.ts","../../../../../src/platform/devtoolsSink.ts","../../../../../src/pathDiagnostics.ts"],"sourcesContent":["export const DELIMITER = '.';\nexport const WILDCARD = '*';\nexport const MAX_WILDCARD_DEPTH = 128;\nexport const MAX_LOOP_DEPTH = 128;\n// 因果伝播(Phase 3)の 1 transaction あたり hop 上限。超過分の未処理 record は\n// quarantine し(適用済みの値は戻さない)、updater から例外は投げない。\nexport const MAX_PROPAGATION_HOPS = 32;\n\n// `$watch` ハンドラ起点の書き込み連鎖の打ち切り深さ(docs/state-watch-hook-design.md §7-2)。\n// watch ハンドラ内の書き込みは新しい microtask バッチを作るため MAX_PROPAGATION_HOPS の\n// ガードが効かず、書き込み先が動的なので `$streams` のような静的な自己依存検出もできない。\n// 値は MAX_PROPAGATION_HOPS と同値だが、別の打ち切り機構なので定数は共有しない。\nexport const MAX_WATCH_CHAIN_DEPTH = 32;\n\n// updater の drain 終了リスナーの実行順(昇順に呼ばれる。設計書 §3-2 層 1)。\n// watch が先なのは、watch ハンドラの書き込みが同じバッチの stream restart 判定に\n// 影響しないようにするため(watch → restart の一方向)。import 順に順序を持たせると\n// 無関係な import 整理で静かに壊れるため、明示的な優先度で固定する。\n//\n// devtools が最も先なのは、`state:update-batch` が「そのバッチに何が載ったか」の\n// 観測であり、watch / restart の副作用が乗る前の生の集合を報告すべきだから。\n// 既定値 0 のまま暗黙に先頭へ入るのに任せず、意図として定数で固定する\n// (docs/devtools-hook-protocol.md §4.3)。\nexport const DEVTOOLS_LISTENER_PRIORITY = 0;\nexport const WATCH_LISTENER_PRIORITY = 10;\nexport const STREAM_LISTENER_PRIORITY = 20;\n\n// data-wcs バインディング構文 `[prop][#mod]: [path][|filter...]` の区切り文字(単一正本・`@state` は v2 で撤去)。\n// これらは「死守の壁(構文契約)」であり値は不変。manifest.syntax.delimiters で公開される。\nexport const BINDING_SEPARATOR = ';'; // 複数バインディングの区切り\nexport const PROP_VALUE_SEPARATOR = ':'; // 左辺(prop)と右辺(path)の区切り\nexport const MODIFIER_SEPARATOR = '#'; // prop と修飾子の区切り\nexport const FILTER_SEPARATOR = '|'; // フィルタパイプの区切り\n\n// 修飾子(`#` 後)の語彙(単一正本)。manifest.syntax.modifiers で公開される。\n// フラグ形(`#prevent` — 値を取らない)とキー値形(`#init=element` — `=` で値を取る)。\n// 消費箇所(event/handler・BindingSession・twowayHandler・bindings/initialSync)は\n// この定数を参照する — 文字列リテラルの散在は tooling への収載漏れの温床だった\n// (docs/static-wiring-dx-design.md §2-2)。\nexport const MODIFIER_PREVENT = 'prevent';\nexport const MODIFIER_STOP = 'stop';\nexport const MODIFIER_READONLY = 'ro';\nexport const MODIFIER_FLAGS: readonly string[] = Object.freeze([\n MODIFIER_PREVENT, MODIFIER_STOP, MODIFIER_READONLY,\n]);\nexport const MODIFIER_KEY_INIT = 'init';\nexport const MODIFIER_KEY_SYNC = 'sync';\nexport const MODIFIER_KEYS: readonly string[] = Object.freeze([\n MODIFIER_KEY_INIT, MODIFIER_KEY_SYNC,\n]);\n\n// bindingType 判別と左辺 namespace の語彙(単一正本)。manifest.syntax.bindingTypes で\n// 公開される。パーサ(parseBindTextsForElement)とイベント層はこの定数に分岐する。\n// apply 層のディスパッチマップ(apply/applyChange.ts の applyChangeByFirstSegment)の\n// キー集合との一致は __tests__/manifest.test.ts の drift テストが強制する —\n// manifest エントリ(DOM 非依存)から apply 層を import しないための分離。\nexport const ELSE_KEYWORD = 'else';\nexport const SPREAD_PROP = '...';\nexport const EVENT_PROP_PREFIX = 'on';\nexport const EVENT_TOKEN_NAMESPACE = 'eventToken';\n/**\n * `<wcs-state mount>` の左辺 `state.<key>: path` — ボリュームの注入口(要件 B14③・3.x 計画 D28)。\n * 束縛ではなくマウントの宣言なので、束縛の収集(getParseBindTextResults)は作らず、ボリュームが接ぎ木の時に読む\n */\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// リストインデックス参照名(`$1`..`$N`)の接頭辞(単一正本)。\n// manifest.syntax.indexParam で公開される。\nexport const INDEX_PARAM_PREFIX = '$';\n\n/**\n * stackIndexByIndexName\n * インデックス名からスタックインデックスへのマッピング\n * $1 => 0\n * $2 => 1\n * :\n * ${i + 1} => i\n * i < MAX_WILDCARD_DEPTH\n */\nconst tmpIndexByIndexName: { [key: PropertyKey]: number } = {};\nfor (let i = 0; i < MAX_WILDCARD_DEPTH; i++) {\n tmpIndexByIndexName[`${INDEX_PARAM_PREFIX}${i+1}`] = i;\n}\nexport const INDEX_BY_INDEX_NAME: { [key: PropertyKey]: number } = Object.freeze(tmpIndexByIndexName);\n\nexport const NO_SET_TIMEOUT = 60 * 1000; // 1分\n\nexport const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n\nexport const STATE_CONNECTED_CALLBACK_NAME = \"$connectedCallback\";\nexport const STATE_DISCONNECTED_CALLBACK_NAME = \"$disconnectedCallback\";\nexport const STATE_UPDATED_CALLBACK_NAME = \"$updatedCallback\";\nexport const STATE_ERROR_CALLBACK_NAME = \"$errorCallback\";\n\nexport const WEBCOMPONENT_STATE_READY_CALLBACK_NAME = \"$stateReadyCallback\";\n\nexport const STATE_BINDABLES_NAME = \"$bindables\";\nexport const STATE_COMMANDS_NAME = \"$commands\";\nexport const STATE_COMMAND_TOKENS_NAME = \"$commandTokens\";\nexport const STATE_COMMAND_NAMESPACE_NAME = \"$command\";\nexport const STATE_EVENT_TOKENS_NAME = \"$eventTokens\";\nexport const STATE_ON_NAME = \"$on\";\nexport const STATE_STREAMS_NAME = \"$streams\";\nexport const STATE_WATCH_NAME = \"$watch\";\nexport const STATE_SCAN_NAME = \"$scan\";\nexport const STATE_RECURSION_NAME = \"$recursion\";\n\n/**\n * 再帰ワイルドカード。オーサリング層($recursion 宣言・getter キー・API 引数)にだけ\n * 現れ、PathInfo には決して降ろさない — wildcardCount が不定になると ListIndex 連鎖長・\n * $1..$n・$resolve の厳密一致・走査の段数が同時に壊れる\n * (docs/state-recursive-path-design.md §2-1)。\n */\nexport const RECURSION_WILDCARD = \"**\";\nexport const STATE_LIST_KEYS_NAME = \"$listKeys\";\nexport const STATE_STREAM_STATUS_NAMESPACE_NAME = \"$streamStatus\";\nexport const STATE_STREAM_ERROR_NAMESPACE_NAME = \"$streamError\";\nexport const DCC_DEFINITION_ATTRIBUTE = \"data-wc-definition\";\n","import { RECURSION_WILDCARD, WILDCARD } from \"../define.js\";\nimport { raiseError } from \"../raiseError.js\";\nimport { IPathInfo } from \"./types.js\";\n\nconst _cache: Map<string, IPathInfo> = new Map();\n\n/**\n * **tooling 専用**(`@wcstack/state/parser` の clearParserCaches からのみ呼ぶ)。\n * ランタイム文脈で呼んではならない — PathInfo のインスタンス同一性は正規化キー\n * (依存グラフ・アドレス比較)の前提であり、クリアすると同一パスの新旧インスタンスが\n * 併存して identity 比較が黙って壊れる。言語サーバー等の長時間プロセスが、編集中の\n * 中間パス(`user.n` 等)の恒久 intern によるメモリ単調増加を断つための出口。\n */\nexport function clearPathInfoCacheForTooling(): void {\n _cache.clear();\n}\n\nlet id: number = 0;\nexport function getPathInfo(path: string): IPathInfo {\n let pathInfo = _cache.get(path);\n if (typeof pathInfo !== \"undefined\") {\n return pathInfo;\n }\n // 再帰ワイルドカードはオーサリング層の記号で、ここへ降りてきてはならない\n // (降ろすと wildcardCount が不定になり ListIndex 連鎖長・$1..$n・$resolve の\n // 厳密一致・走査の段数が同時に壊れる。設計書 D2)。到達したということは、\n // `**` を解釈しない消費者に `**` パスが渡ったということ。通常のパスはこの検査を\n // 初回 intern のときにしか払わない(`**` パスは intern されないので読むたびに落ちる)。\n if (path.indexOf(RECURSION_WILDCARD) !== -1) {\n raiseError(\n `[wcs/recursion-unsupported] \"${path}\" uses \"${RECURSION_WILDCARD}\", which is not accepted here. ` +\n `It is only meaningful in a $recursion declaration, in a recursive getter key, and in the path ` +\n `argument of $getAll / $setAll — and only when the state declares a $recursion anchor.`\n );\n }\n pathInfo = Object.freeze(new PathInfo(path));\n _cache.set(path, pathInfo);\n return pathInfo;\n}\n\nclass PathInfo implements IPathInfo {\n readonly id: number = ++id;\n readonly path: string;\n readonly segments: string[];\n readonly lastSegment: string;\n readonly cumulativePaths: string[];\n readonly cumulativePathSet: Set<string>;\n readonly cumulativePathInfos: IPathInfo[];\n readonly cumulativePathInfoSet: Set<IPathInfo>;\n readonly parentPath: string | null;\n readonly wildcardPaths: string[];\n readonly wildcardPathSet: Set<string>;\n readonly indexByWildcardPath: Record<string, number>;\n readonly wildcardPathInfos: IPathInfo[];\n readonly wildcardPathInfoSet: Set<IPathInfo>;\n readonly wildcardParentPaths: string[];\n readonly wildcardParentPathSet: Set<string>;\n readonly wildcardParentPathInfos: IPathInfo[];\n readonly wildcardParentPathInfoSet: Set<IPathInfo>;\n readonly wildcardPositions: number[];\n readonly lastWildcardPath: string | null;\n readonly lastWildcardInfo: IPathInfo | null;\n readonly wildcardCount: number;\n readonly parentPathInfo: IPathInfo | null;\n constructor(path: string) {\n // Helper to get or create StructuredPathInfo instances, avoiding redundant creation for self-reference\n const getPattern = (_path: string): IPathInfo => {\n return (path === _path) ? this : getPathInfo(_path);\n };\n \n // Split the pattern into individual path segments (e.g., \"items.*.name\" → [\"items\", \"*\", \"name\"])\n const segments = path.split(\".\");\n \n // Arrays to track all cumulative paths from root to each segment\n const cumulativePaths = [];\n const cumulativePathInfos: IPathInfo[] = [];\n \n // Arrays to track wildcard-specific information\n const wildcardPaths = [];\n const indexByWildcardPath: Record<string, number> = {}; // Maps wildcard path to its index position\n const wildcardPathInfos = [];\n const wildcardParentPaths = []; // Paths of parent segments for each wildcard\n const wildcardParentPathInfos = [];\n const wildcardPositions = [];\n \n let currentPatternPath = \"\", prevPatternPath = \"\";\n let wildcardCount = 0;\n \n // Iterate through each segment to build cumulative paths and identify wildcards\n for(let i = 0; i < segments.length; i++) {\n currentPatternPath += segments[i];\n \n // If this segment is a wildcard, track it with all wildcard-specific metadata\n if (segments[i] === WILDCARD) {\n wildcardPaths.push(currentPatternPath);\n indexByWildcardPath[currentPatternPath] = wildcardCount; // Store wildcard's ordinal position\n wildcardPathInfos.push(getPattern(currentPatternPath));\n wildcardParentPaths.push(prevPatternPath); // Parent path is the previous cumulative path\n wildcardParentPathInfos.push(getPattern(prevPatternPath));\n wildcardPositions.push(i);\n wildcardCount++;\n }\n \n // Track all cumulative paths for hierarchical navigation (e.g., \"items\", \"items.*\", \"items.*.name\")\n cumulativePaths.push(currentPatternPath);\n cumulativePathInfos.push(getPattern(currentPatternPath));\n \n // Save current path as previous for next iteration, then add separator\n prevPatternPath = currentPatternPath;\n currentPatternPath += \".\";\n }\n \n // Determine the deepest (last) wildcard path and the parent path of the entire pattern\n const lastWildcardPath = wildcardPaths.length > 0 ? wildcardPaths[wildcardPaths.length - 1] : null;\n const parentPath = cumulativePaths.length > 1 ? cumulativePaths[cumulativePaths.length - 2] : null;\n \n // Assign all analyzed data to readonly properties\n this.path = path;\n this.segments = segments;\n this.lastSegment = segments[segments.length - 1];\n this.cumulativePaths = cumulativePaths;\n this.cumulativePathSet = new Set(cumulativePaths); // Set for fast lookup\n this.cumulativePathInfos = cumulativePathInfos;\n this.cumulativePathInfoSet = new Set(cumulativePathInfos);\n this.wildcardPaths = wildcardPaths;\n this.wildcardPathSet = new Set(wildcardPaths);\n this.indexByWildcardPath = indexByWildcardPath;\n this.wildcardPathInfos = wildcardPathInfos;\n this.wildcardPathInfoSet = new Set(wildcardPathInfos);\n this.wildcardParentPaths = wildcardParentPaths;\n this.wildcardParentPathSet = new Set(wildcardParentPaths);\n this.wildcardParentPathInfos = wildcardParentPathInfos;\n this.wildcardParentPathInfoSet = new Set(wildcardParentPathInfos);\n this.wildcardPositions = wildcardPositions;\n this.lastWildcardPath = lastWildcardPath;\n this.lastWildcardInfo = lastWildcardPath ? getPattern(lastWildcardPath) : null;\n this.parentPath = parentPath;\n this.parentPathInfo = parentPath ? getPattern(parentPath) : null;\n this.wildcardCount = wildcardCount;\n }\n}\n","/**\n * platform/devtoolsSink.ts(旧 devtools/sink.ts。core 側に置き、devtools/bridge.ts がこちらを import する)\n *\n * 計装点が参照するホットパス唯一の接点。依存ゼロの葉モジュールにすることで、\n * 計装される側(stateElementByName / setByAddress / binding / token)と\n * bridge の間の循環 import を避ける。\n *\n * コスト規範(protocol §1-1): フック未接続時、計装点のコストは\n * `devtoolsSink !== null` の分岐 1 個。イベントオブジェクトの生成は\n * 必ずこのチェックの内側で行うこと。\n */\n\nimport type { DevtoolsSink } from \"../devtools/types\";\n\n/** live binding としてエクスポート。計装点は `if (devtoolsSink !== null)` で参照する */\nexport let devtoolsSink: DevtoolsSink | null = null;\n\nexport function setDevtoolsSink(sink: DevtoolsSink | null): void {\n devtoolsSink = sink;\n}\n","/**\n * pathDiagnostics.ts — パスに関する**エラーの文言**(throw する側)と、診断の両面が共有する部品。\n *\n * 束縛時の存在検査(`user.nmae` のような打ち間違いを console.warn で知らせる開発時の診断)は\n * `features/diagnostics` へ分けた(diagnostics/pathChecks.ts)。core に残るのは、実行を止める\n * エラーの文言と、その did-you-mean が使う候補の集め方だけ。エラーは機能の有無に関わらず\n * 読める文言で落ちなければならないので、ここは core から外せない。\n *\n * 診断 code はコンソール → lint → IDE の三面で共有する(errorGuidance.ts の規約)。\n */\n\nimport { DELIMITER } from \"./define\";\nimport { didYouMean, LINT_HINT } from \"./errorGuidance\";\n\n/** `setPathInfo` の呼び出し元の種別。診断 code と適用範囲がこれで変わる */\nexport type PathInfoSource =\n /** data-wcs / mustache / コメントバインディング */\n | \"binding\"\n /** `$watch` の宣言キー */\n | \"watch\"\n /** `$scan` の `from` / `resetOn`(docs/state-scan-design.md §2-4) */\n | \"scan\"\n /** ランタイム内部のパス翻訳(mapped な bind-component の外向き伝播)。検査しない */\n | \"internal\";\n\n/**\n * `obj` 自身+プロトタイプチェーン(Object.prototype 手前まで)から descriptor を引く。\n * 打ち切り位置は getAllPropertyDescriptors と同じ — 「state が宣言したもの」だけを\n * 存在とみなし、`toString` 等の Object.prototype 由来を存在扱いしない。\n *\n * `State.findStateDescriptor`(再帰アクセサの衝突検査)も同じ走査を使う。打ち切り位置が\n * 2 本に分かれると、片方だけが `Object.prototype` を存在扱いするようなずれ方をする。\n */\nexport function findDescriptor(obj: object, key: string): PropertyDescriptor | undefined {\n let proto: object | null = obj;\n while (proto !== null && proto !== Object.prototype) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, key);\n if (typeof descriptor !== \"undefined\") {\n return descriptor;\n }\n proto = Object.getPrototypeOf(proto);\n }\n return undefined;\n}\n\n/** `obj` 自身+プロトタイプチェーンのキー名(did-you-mean の候補集合) */\nfunction ownKeys(obj: object): string[] {\n const keys: string[] = [];\n let proto: object | null = obj;\n while (proto !== null && proto !== Object.prototype) {\n for (const key of Object.getOwnPropertyNames(proto)) {\n keys.push(key);\n }\n proto = Object.getPrototypeOf(proto);\n }\n return keys;\n}\n\n/**\n * 失敗した階層の兄弟候補。生オブジェクトのキーに加え、その階層にフラット宣言\n * (ドットパス getter)されているものも混ぜる — `cart.items.*.subtotl` の正解\n * `subtotal` は行オブジェクトには無く getterPaths にしか居ないため。\n */\nexport function collectCandidates(\n container: object,\n parentPrefix: string,\n declaredPaths: Iterable<string>,\n): string[] {\n const candidates = ownKeys(container);\n const prefix = parentPrefix.length > 0 ? parentPrefix + DELIMITER : \"\";\n for (const declared of declaredPaths) {\n if (prefix.length > 0 && !declared.startsWith(prefix)) {\n continue;\n }\n const rest = declared.slice(prefix.length);\n // 直下の 1 セグメントだけを候補にする(孫は別階層の名前なので提案しない)\n if (rest.length > 0 && rest.indexOf(DELIMITER) === -1) {\n candidates.push(rest);\n }\n }\n return candidates;\n}\n\n/** 診断 code は lint / IDE と同一語彙(errorGuidance.ts の三面共有規約) */\nexport const DIAGNOSTIC_CODE: Readonly<Record<\"binding\" | \"watch\" | \"scan\", string>> = {\n binding: \"wcs/binding-path-missing\",\n watch: \"wcs/watch-path-missing\",\n scan: \"wcs/scan-path-missing\",\n};\n\nexport const SUBJECT: Readonly<Record<\"binding\" | \"watch\" | \"scan\", string>> = {\n binding: \"Bound path\",\n watch: \"$watch path\",\n scan: \"$scan path\",\n};\n\n/**\n * ルート直下(単一セグメント)のパスが state に無いときのエラーメッセージ。\n *\n * この形だけは親アドレスを辿れないので読み取りが throw する = 元から loud だが、\n * 文面が `address.parentAddress is undefined path: cout` という内部実装の言葉で、\n * 「打ち間違い」だと分からず did-you-mean も lint 誘導も無かった。深いパスの\n * `console.warn` と同じ語彙に揃える。\n */\nexport function missingRootPathMessage(\n path: string,\n target: object,\n declaredPaths: Iterable<string>,\n): string {\n return `[${DIAGNOSTIC_CODE.binding}] Path \"${path}\" does not exist on the state tree.` +\n `${didYouMean(path, collectCandidates(target, \"\", declaredPaths))}${LINT_HINT}`;\n}\n\n/**\n * `$resolve` / `$getAll` に渡した添字の本数がワイルドカードの本数と噛み合わない。\n *\n * 不足(`$resolve`)は元から throw していたが、**超過は両 API とも黙って無視**され、\n * 取り違えた添字のまま「もっともらしい値」を返していた。本数はパス文字列から\n * 決まるので、噛み合わないことは常にプログラマのミス。\n */\nexport function indexArityMessage(\n api: \"$resolve\" | \"$getAll\" | \"$setAll\",\n path: string,\n wildcardCount: number,\n actual: number,\n): string {\n // `$getAll` / `$setAll` の添字は前方一致の接頭辞なので上限、`$resolve` だけが厳密一致\n // (docs/state-set-all-design.md §4)。\n const requirement = api === \"$resolve\"\n ? `exactly ${wildcardCount}`\n : `at most ${wildcardCount}`;\n return `[wcs/index-arity] ${api}(\"${path}\") requires ${requirement} index(es) ` +\n `(\"*\" appears ${wildcardCount} time(s) in the path) but got ${actual}.${LINT_HINT}`;\n}\n\n/**\n * `**` を含むパスが宣言済みの再帰アンカーと合致しない(綴り違い・2 つ目の `**`)。\n * 束縛形(bind.ts)・合併形(getAllRecursive.ts)・ブロードキャスト(setAllRecursive.ts)の\n * 3 入口が同じ文面で報告する。\n */\nexport function recursionAnchorMismatchMessage(path: string, recursiveAnchor: string): string {\n return `[wcs/recursion-anchor] \"${path}\" does not match the declared recursion anchor ` +\n `\"${recursiveAnchor}\". This version supports exactly one anchor per state, and \"**\" must be followed ` +\n `by a well-formed suffix (no second \"**\", no empty segment, no bare \"*\" right after \"**\").`;\n}\n\n/**\n * `$getAll(path)`(添字省略)の既定値はループ文脈の添字 `[$1..$n]` だが、それを\n * 敷けるのは path と文脈がワイルドカード連鎖を共有している場合だけ。共有ゼロなのに\n * 文脈が添字を持っている場合、黙って全展開に倒すと「文脈で絞られている」という\n * 書き手の期待と食い違い、異なる文脈の添字の流用とも区別が付かないため throw する。\n *\n * 実行時の評価文脈に依存する(`$setAll` の spread 長と同種)ので lint へは誘導しない。\n */\nexport function getAllContextMismatchMessage(path: string, contextPath: string): string {\n return `$getAll(\"${path}\") was called without indexes inside the loop context of ` +\n `\"${contextPath}\", but the path shares no wildcard level with that context, ` +\n `so the context indexes ($1..$n) do not apply. ` +\n `Pass indexes explicitly ([] expands every level).`;\n}\n\n/**\n * `$setAll(path, indexes, values, { spread: true })` の配列長がマッチ件数と噛み合わない。\n *\n * 静的には件数が分からない(実行時のリスト長に依存する)ので lint へは誘導しない。\n * 黙って切り詰める/余りを捨てると誤配が通ってしまうため throw する\n * (docs/state-set-all-design.md §3-3)。\n */\nexport function setAllSpreadArityMessage(\n path: string,\n matched: number,\n actual: number,\n): string {\n return `$setAll(\"${path}\", …, { spread: true }) requires the values array to have ` +\n `exactly one entry per matched address (matched ${matched}) but got ${actual}. ` +\n `Did the list change between $getAll and $setAll?`;\n}\n\n/**\n * `$setAll` の値と `options` の組み合わせが意味を成さない。\n * (docs/state-set-all-design.md §3-1)\n */\nexport function setAllValueKindMessage(path: string, reason: string): string {\n return `$setAll(\"${path}\") ${reason}`;\n}\n\n/**\n * ワイルドカードを解決するループ文脈が足りない(=パスの階数 > スコープの階数)。\n *\n * `matrix.*.*` を 1 段の `for` の中で読む、`$2` を 1 段のループの中で読む、といった\n * 取り違えがこれ。元の文面は `address.listIndex?.index is undefined path: matrix.*` /\n * `Index not found at position 1 for loopContext:` という内部実装の言葉で、\n * **何を間違えたのかが書かれていなかった**。\n */\nexport function wildcardScopeMessage(subject: string, needed: number, available: number): string {\n return `[wcs/wildcard-rank] ${subject} needs ${needed} enclosing loop level(s) but the current ` +\n `scope provides ${available}. Wrap it in that many \"for\" templates, or use $resolve(path, indexes) ` +\n `to name the row explicitly.${LINT_HINT}`;\n}\n\n"],"names":["DELIMITER","WILDCARD","MAX_WILDCARD_DEPTH","MAX_LOOP_DEPTH","MAX_PROPAGATION_HOPS","MAX_WATCH_CHAIN_DEPTH","DEVTOOLS_LISTENER_PRIORITY","WATCH_LISTENER_PRIORITY","STREAM_LISTENER_PRIORITY","BINDING_SEPARATOR","PROP_VALUE_SEPARATOR","MODIFIER_SEPARATOR","FILTER_SEPARATOR","MODIFIER_PREVENT","MODIFIER_STOP","MODIFIER_READONLY","MODIFIER_KEY_INIT","MODIFIER_KEY_SYNC","ELSE_KEYWORD","SPREAD_PROP","EVENT_PROP_PREFIX","EVENT_TOKEN_NAMESPACE","VOLUME_INJECTION_PROP","COMMAND_NAMESPACE","CLASS_NAMESPACE","ATTR_NAMESPACE","STYLE_NAMESPACE","INDEX_PARAM_PREFIX","tmpIndexByIndexName","i","INDEX_BY_INDEX_NAME","Object","freeze","NO_SET_TIMEOUT","SVG_NAMESPACE","STATE_CONNECTED_CALLBACK_NAME","STATE_DISCONNECTED_CALLBACK_NAME","STATE_UPDATED_CALLBACK_NAME","STATE_ERROR_CALLBACK_NAME","WEBCOMPONENT_STATE_READY_CALLBACK_NAME","STATE_BINDABLES_NAME","STATE_COMMANDS_NAME","STATE_COMMAND_TOKENS_NAME","STATE_COMMAND_NAMESPACE_NAME","STATE_EVENT_TOKENS_NAME","STATE_ON_NAME","STATE_STREAMS_NAME","STATE_WATCH_NAME","STATE_SCAN_NAME","STATE_RECURSION_NAME","RECURSION_WILDCARD","STATE_LIST_KEYS_NAME","STATE_STREAM_STATUS_NAMESPACE_NAME","STATE_STREAM_ERROR_NAMESPACE_NAME","DCC_DEFINITION_ATTRIBUTE","_cache","Map","id","getPathInfo","path","pathInfo","get","indexOf","raiseError","PathInfo","set","segments","lastSegment","cumulativePaths","cumulativePathSet","cumulativePathInfos","cumulativePathInfoSet","parentPath","wildcardPaths","wildcardPathSet","indexByWildcardPath","wildcardPathInfos","wildcardPathInfoSet","wildcardParentPaths","wildcardParentPathSet","wildcardParentPathInfos","wildcardParentPathInfoSet","wildcardPositions","lastWildcardPath","lastWildcardInfo","wildcardCount","parentPathInfo","constructor","getPattern","_path","this","split","currentPatternPath","prevPatternPath","length","push","Set","devtoolsSink","setDevtoolsSink","sink","findDescriptor","obj","key","proto","prototype","descriptor","getOwnPropertyDescriptor","getPrototypeOf","collectCandidates","container","parentPrefix","declaredPaths","candidates","keys","getOwnPropertyNames","ownKeys","prefix","declared","startsWith","rest","slice","DIAGNOSTIC_CODE","binding","watch","scan","SUBJECT","missingRootPathMessage","target","didYouMean","LINT_HINT","indexArityMessage","api","actual","recursionAnchorMismatchMessage","recursiveAnchor","getAllContextMismatchMessage","contextPath","setAllSpreadArityMessage","matched","setAllValueKindMessage","reason","wildcardScopeMessage","subject","needed","available"],"mappings":"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"}
1
+ {"version":3,"file":"pathDiagnostics.js","sources":["../../../../../src/define.ts","../../../../../src/address/PathInfo.ts","../../../../../src/platform/devtoolsSink.ts","../../../../../src/pathDiagnostics.ts"],"sourcesContent":["export const DELIMITER = '.';\nexport const WILDCARD = '*';\nexport const MAX_WILDCARD_DEPTH = 128;\n/**\n * 1 本のパスが持てるセグメント数の上限(`getPathInfo` が初回 intern のときだけ検査する)。\n *\n * `PathInfo` は自分の**全ての接頭辞**を intern するので、深さ N のパス 1 本で N 個の\n * `PathInfo` ができ、それぞれが長さ k の配列と Set を持つ = 時間もメモリも O(N²)。\n * 実測(Node 22・パス 1 本)で depth 400 → 145ms / 61MB、800 → 1162ms / 424MB、\n * 2000 → 既定 4GB ヒープで OOM。**約 4KB の `data-wcs` 属性値 1 つでタブを落とせた。**\n * ここで打ち切ると最悪でも 256² ≒ 65k 単位に収まる。\n *\n * 値は `MAX_WILDCARD_DEPTH`(128 = `$1..$128` の表の大きさ)を**使い切れる**ことから決めた:\n * `$recursion` の展開(`recursion/expand.ts`)が深さ 128 で作るパスは `a.*.b.*.…` の形で\n * 257 セグメントを超える。そこを割ると、ドキュメント済みの再帰深さが打ち切られてしまう。\n * 512 なら最悪でも 512² ≒ 262k 単位で、上の実測の 400 段(145ms / 61MB)の延長に収まる。\n * 実用のパスは 10 段に満たない。\n */\nexport const MAX_PATH_SEGMENTS = 512;\nexport const MAX_LOOP_DEPTH = 128;\n// 因果伝播(Phase 3)の 1 transaction あたり hop 上限。超過分の未処理 record は\n// quarantine し(適用済みの値は戻さない)、updater から例外は投げない。\nexport const MAX_PROPAGATION_HOPS = 32;\n\n// `$watch` ハンドラ起点の書き込み連鎖の打ち切り深さ(docs/state-watch-hook-design.md §7-2)。\n// watch ハンドラ内の書き込みは新しい microtask バッチを作るため MAX_PROPAGATION_HOPS の\n// ガードが効かず、書き込み先が動的なので `$streams` のような静的な自己依存検出もできない。\n// 値は MAX_PROPAGATION_HOPS と同値だが、別の打ち切り機構なので定数は共有しない。\nexport const MAX_WATCH_CHAIN_DEPTH = 32;\n\n// updater の drain 終了リスナーの実行順(昇順に呼ばれる。設計書 §3-2 層 1)。\n// watch が先なのは、watch ハンドラの書き込みが同じバッチの stream restart 判定に\n// 影響しないようにするため(watch → restart の一方向)。import 順に順序を持たせると\n// 無関係な import 整理で静かに壊れるため、明示的な優先度で固定する。\n//\n// devtools が最も先なのは、`state:update-batch` が「そのバッチに何が載ったか」の\n// 観測であり、watch / restart の副作用が乗る前の生の集合を報告すべきだから。\n// 既定値 0 のまま暗黙に先頭へ入るのに任せず、意図として定数で固定する\n// (docs/devtools-hook-protocol.md §4.3)。\nexport const DEVTOOLS_LISTENER_PRIORITY = 0;\nexport const WATCH_LISTENER_PRIORITY = 10;\nexport const STREAM_LISTENER_PRIORITY = 20;\n\n// data-wcs バインディング構文 `[prop][#mod]: [path][|filter...]` の区切り文字(単一正本・`@state` は v2 で撤去)。\n// これらは「死守の壁(構文契約)」であり値は不変。manifest.syntax.delimiters で公開される。\nexport const BINDING_SEPARATOR = ';'; // 複数バインディングの区切り\nexport const PROP_VALUE_SEPARATOR = ':'; // 左辺(prop)と右辺(path)の区切り\nexport const MODIFIER_SEPARATOR = '#'; // prop と修飾子の区切り\nexport const FILTER_SEPARATOR = '|'; // フィルタパイプの区切り\n\n// 修飾子(`#` 後)の語彙(単一正本)。manifest.syntax.modifiers で公開される。\n// フラグ形(`#prevent` — 値を取らない)とキー値形(`#init=element` — `=` で値を取る)。\n// 消費箇所(event/handler・BindingSession・twowayHandler・bindings/initialSync)は\n// この定数を参照する — 文字列リテラルの散在は tooling への収載漏れの温床だった\n// (docs/static-wiring-dx-design.md §2-2)。\nexport const MODIFIER_PREVENT = 'prevent';\nexport const MODIFIER_STOP = 'stop';\nexport const MODIFIER_READONLY = 'ro';\nexport const MODIFIER_FLAGS: readonly string[] = Object.freeze([\n MODIFIER_PREVENT, MODIFIER_STOP, MODIFIER_READONLY,\n]);\nexport const MODIFIER_KEY_INIT = 'init';\nexport const MODIFIER_KEY_SYNC = 'sync';\nexport const MODIFIER_KEYS: readonly string[] = Object.freeze([\n MODIFIER_KEY_INIT, MODIFIER_KEY_SYNC,\n]);\n\n// bindingType 判別と左辺 namespace の語彙(単一正本)。manifest.syntax.bindingTypes で\n// 公開される。パーサ(parseBindTextsForElement)とイベント層はこの定数に分岐する。\n// apply 層のディスパッチマップ(apply/applyChange.ts の applyChangeByFirstSegment)の\n// キー集合との一致は __tests__/manifest.test.ts の drift テストが強制する —\n// manifest エントリ(DOM 非依存)から apply 層を import しないための分離。\nexport const ELSE_KEYWORD = 'else';\nexport const SPREAD_PROP = '...';\nexport const EVENT_PROP_PREFIX = 'on';\nexport const EVENT_TOKEN_NAMESPACE = 'eventToken';\n/**\n * `<wcs-state mount>` の左辺 `state.<key>: path` — ボリュームの注入口(要件 B14③・3.x 計画 D28)。\n * 束縛ではなくマウントの宣言なので、束縛の収集(getParseBindTextResults)は作らず、ボリュームが接ぎ木の時に読む\n */\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// リストインデックス参照名(`$1`..`$N`)の接頭辞(単一正本)。\n// manifest.syntax.indexParam で公開される。\nexport const INDEX_PARAM_PREFIX = '$';\n\n/**\n * stackIndexByIndexName\n * インデックス名からスタックインデックスへのマッピング\n * $1 => 0\n * $2 => 1\n * :\n * ${i + 1} => i\n * i < MAX_WILDCARD_DEPTH\n */\nconst tmpIndexByIndexName: { [key: PropertyKey]: number } = {};\nfor (let i = 0; i < MAX_WILDCARD_DEPTH; i++) {\n tmpIndexByIndexName[`${INDEX_PARAM_PREFIX}${i+1}`] = i;\n}\nexport const INDEX_BY_INDEX_NAME: { [key: PropertyKey]: number } = Object.freeze(tmpIndexByIndexName);\n\nexport const NO_SET_TIMEOUT = 60 * 1000; // 1分\n\nexport const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n\nexport const STATE_CONNECTED_CALLBACK_NAME = \"$connectedCallback\";\nexport const STATE_DISCONNECTED_CALLBACK_NAME = \"$disconnectedCallback\";\n/** 旧名 `$updatedCallback` は 3.x の間のエイリアス(要件 B12・declarationAliases.ts) */\nexport const STATE_RENDERED_CALLBACK_NAME = \"$renderedCallback\";\nexport const STATE_ERROR_CALLBACK_NAME = \"$errorCallback\";\n\nexport const WEBCOMPONENT_STATE_READY_CALLBACK_NAME = \"$stateReadyCallback\";\n\nexport const STATE_BINDABLES_NAME = \"$bindables\";\nexport const STATE_COMMANDS_NAME = \"$commands\";\nexport const STATE_COMMAND_TOKENS_NAME = \"$commandTokens\";\nexport const STATE_COMMAND_NAMESPACE_NAME = \"$command\";\nexport const STATE_EVENT_TOKENS_NAME = \"$eventTokens\";\nexport const STATE_ON_NAME = \"$on\";\n/** 旧名 `$streams` は 3.x の間のエイリアス(要件 B12・declarationAliases.ts) */\nexport const STATE_STREAM_NAME = \"$stream\";\nexport const STATE_WATCH_NAME = \"$watch\";\nexport const STATE_SCAN_NAME = \"$scan\";\nexport const STATE_RECURSION_NAME = \"$recursion\";\n\n/**\n * 再帰ワイルドカード。オーサリング層($recursion 宣言・getter キー・API 引数)にだけ\n * 現れ、PathInfo には決して降ろさない — wildcardCount が不定になると ListIndex 連鎖長・\n * $1..$n・$resolve の厳密一致・走査の段数が同時に壊れる\n * (docs/state-recursive-path-design.md §2-1)。\n */\nexport const RECURSION_WILDCARD = \"**\";\nexport const STATE_LIST_KEYS_NAME = \"$listKeys\";\nexport const STATE_STREAM_STATUS_NAMESPACE_NAME = \"$streamStatus\";\nexport const STATE_STREAM_ERROR_NAMESPACE_NAME = \"$streamError\";\nexport const DCC_DEFINITION_ATTRIBUTE = \"data-wc-definition\";\n","import { DELIMITER, MAX_PATH_SEGMENTS, RECURSION_WILDCARD, WILDCARD } from \"../define.js\";\nimport { raiseError } from \"../raiseError.js\";\nimport { IPathInfo } from \"./types.js\";\n\nconst _cache: Map<string, IPathInfo> = new Map();\n\n/**\n * **tooling 専用**(`@wcstack/state/parser` の clearParserCaches からのみ呼ぶ)。\n * ランタイム文脈で呼んではならない — PathInfo のインスタンス同一性は正規化キー\n * (依存グラフ・アドレス比較)の前提であり、クリアすると同一パスの新旧インスタンスが\n * 併存して identity 比較が黙って壊れる。言語サーバー等の長時間プロセスが、編集中の\n * 中間パス(`user.n` 等)の恒久 intern によるメモリ単調増加を断つための出口。\n */\nexport function clearPathInfoCacheForTooling(): void {\n _cache.clear();\n}\n\nlet id: number = 0;\nexport function getPathInfo(path: string): IPathInfo {\n let pathInfo = _cache.get(path);\n if (typeof pathInfo !== \"undefined\") {\n return pathInfo;\n }\n // 再帰ワイルドカードはオーサリング層の記号で、ここへ降りてきてはならない\n // (降ろすと wildcardCount が不定になり ListIndex 連鎖長・$1..$n・$resolve の\n // 厳密一致・走査の段数が同時に壊れる。設計書 D2)。到達したということは、\n // `**` を解釈しない消費者に `**` パスが渡ったということ。通常のパスはこの検査を\n // 初回 intern のときにしか払わない(`**` パスは intern されないので読むたびに落ちる)。\n if (path.indexOf(RECURSION_WILDCARD) !== -1) {\n raiseError(\n `[wcs/recursion-unsupported] \"${path}\" uses \"${RECURSION_WILDCARD}\", which is not accepted here. ` +\n `It is only meaningful in a $recursion declaration, in a recursive getter key, and in the path ` +\n `argument of $getAll / $setAll — and only when the state declares a $recursion anchor.`\n );\n }\n // 深さの上限(初回 intern のときだけ払う)。`PathInfo` は**全ての接頭辞**を intern するので\n // 深さ N のパス 1 本で時間もメモリも O(N²) になり、上限が無いと約 4KB の属性値 1 つで\n // タブが落ちた(実測値は `MAX_PATH_SEGMENTS` の注記)。\n //\n // **ワイルドカードの段数はここでは見ない。** 段数の上限(`MAX_WILDCARD_DEPTH` = manifest の\n // `indexParam.maxDepth`)は `$1..$N` の表が引けるかという別の話で、`recursion/expand.ts` の\n // `[wcs/recursion-depth-exceeded]` と `proxy/traps/get.ts` の `$N` 範囲外診断が、原因を\n // 名指しできる場所で受け持っている(番人: `integration.recursionPrerequisites.test.ts` が\n // 「PathInfo 自体には段数の上限が無い」を固定している)。ここで先に落とすと、深さ超過か\n // 循環かの切り分けが効かなくなる\n const segmentCount = countSegments(path);\n if (segmentCount > MAX_PATH_SEGMENTS) {\n raiseError(\n `[wcs/binding-syntax] \"${path}\" has ${segmentCount} path segments — the limit is ${MAX_PATH_SEGMENTS}. ` +\n `Every prefix of a path is interned, so the cost grows with the square of the depth.`,\n );\n }\n pathInfo = Object.freeze(new PathInfo(path));\n _cache.set(path, pathInfo);\n return pathInfo;\n}\n\n/** `.` の数 + 1。`split` の配列を作らずに数える(初回 intern のときだけ通る) */\nfunction countSegments(path: string): number {\n let count = 1;\n for (let i = 0; i < path.length; i++) {\n if (path[i] === DELIMITER) {\n count++;\n }\n }\n return count;\n}\n\nclass PathInfo implements IPathInfo {\n readonly id: number = ++id;\n readonly path: string;\n readonly segments: string[];\n readonly lastSegment: string;\n readonly cumulativePaths: string[];\n readonly cumulativePathSet: Set<string>;\n readonly cumulativePathInfos: IPathInfo[];\n readonly cumulativePathInfoSet: Set<IPathInfo>;\n readonly parentPath: string | null;\n readonly wildcardPaths: string[];\n readonly wildcardPathSet: Set<string>;\n readonly indexByWildcardPath: Record<string, number>;\n readonly wildcardPathInfos: IPathInfo[];\n readonly wildcardPathInfoSet: Set<IPathInfo>;\n readonly wildcardParentPaths: string[];\n readonly wildcardParentPathSet: Set<string>;\n readonly wildcardParentPathInfos: IPathInfo[];\n readonly wildcardParentPathInfoSet: Set<IPathInfo>;\n readonly wildcardPositions: number[];\n readonly lastWildcardPath: string | null;\n readonly lastWildcardInfo: IPathInfo | null;\n readonly wildcardCount: number;\n readonly parentPathInfo: IPathInfo | null;\n constructor(path: string) {\n // Helper to get or create StructuredPathInfo instances, avoiding redundant creation for self-reference\n const getPattern = (_path: string): IPathInfo => {\n return (path === _path) ? this : getPathInfo(_path);\n };\n \n // Split the pattern into individual path segments (e.g., \"items.*.name\" → [\"items\", \"*\", \"name\"])\n const segments = path.split(\".\");\n \n // Arrays to track all cumulative paths from root to each segment\n const cumulativePaths = [];\n const cumulativePathInfos: IPathInfo[] = [];\n \n // Arrays to track wildcard-specific information\n const wildcardPaths = [];\n const indexByWildcardPath: Record<string, number> = {}; // Maps wildcard path to its index position\n const wildcardPathInfos = [];\n const wildcardParentPaths = []; // Paths of parent segments for each wildcard\n const wildcardParentPathInfos = [];\n const wildcardPositions = [];\n \n let currentPatternPath = \"\", prevPatternPath = \"\";\n let wildcardCount = 0;\n \n // Iterate through each segment to build cumulative paths and identify wildcards\n for(let i = 0; i < segments.length; i++) {\n currentPatternPath += segments[i];\n \n // If this segment is a wildcard, track it with all wildcard-specific metadata\n if (segments[i] === WILDCARD) {\n wildcardPaths.push(currentPatternPath);\n indexByWildcardPath[currentPatternPath] = wildcardCount; // Store wildcard's ordinal position\n wildcardPathInfos.push(getPattern(currentPatternPath));\n wildcardParentPaths.push(prevPatternPath); // Parent path is the previous cumulative path\n wildcardParentPathInfos.push(getPattern(prevPatternPath));\n wildcardPositions.push(i);\n wildcardCount++;\n }\n \n // Track all cumulative paths for hierarchical navigation (e.g., \"items\", \"items.*\", \"items.*.name\")\n cumulativePaths.push(currentPatternPath);\n cumulativePathInfos.push(getPattern(currentPatternPath));\n \n // Save current path as previous for next iteration, then add separator\n prevPatternPath = currentPatternPath;\n currentPatternPath += \".\";\n }\n \n // Determine the deepest (last) wildcard path and the parent path of the entire pattern\n const lastWildcardPath = wildcardPaths.length > 0 ? wildcardPaths[wildcardPaths.length - 1] : null;\n const parentPath = cumulativePaths.length > 1 ? cumulativePaths[cumulativePaths.length - 2] : null;\n \n // Assign all analyzed data to readonly properties\n this.path = path;\n this.segments = segments;\n this.lastSegment = segments[segments.length - 1];\n this.cumulativePaths = cumulativePaths;\n this.cumulativePathSet = new Set(cumulativePaths); // Set for fast lookup\n this.cumulativePathInfos = cumulativePathInfos;\n this.cumulativePathInfoSet = new Set(cumulativePathInfos);\n this.wildcardPaths = wildcardPaths;\n this.wildcardPathSet = new Set(wildcardPaths);\n this.indexByWildcardPath = indexByWildcardPath;\n this.wildcardPathInfos = wildcardPathInfos;\n this.wildcardPathInfoSet = new Set(wildcardPathInfos);\n this.wildcardParentPaths = wildcardParentPaths;\n this.wildcardParentPathSet = new Set(wildcardParentPaths);\n this.wildcardParentPathInfos = wildcardParentPathInfos;\n this.wildcardParentPathInfoSet = new Set(wildcardParentPathInfos);\n this.wildcardPositions = wildcardPositions;\n this.lastWildcardPath = lastWildcardPath;\n this.lastWildcardInfo = lastWildcardPath ? getPattern(lastWildcardPath) : null;\n this.parentPath = parentPath;\n this.parentPathInfo = parentPath ? getPattern(parentPath) : null;\n this.wildcardCount = wildcardCount;\n }\n}\n","/**\n * platform/devtoolsSink.ts(旧 devtools/sink.ts。core 側に置き、devtools/bridge.ts がこちらを import する)\n *\n * 計装点が参照するホットパス唯一の接点。依存ゼロの葉モジュールにすることで、\n * 計装される側(stateElementByName / setByAddress / binding / token)と\n * bridge の間の循環 import を避ける。\n *\n * コスト規範(protocol §1-1): フック未接続時、計装点のコストは\n * `devtoolsSink !== null` の分岐 1 個。イベントオブジェクトの生成は\n * 必ずこのチェックの内側で行うこと。\n */\n\nimport type { DevtoolsSink } from \"../devtools/types\";\n\n/** live binding としてエクスポート。計装点は `if (devtoolsSink !== null)` で参照する */\nexport let devtoolsSink: DevtoolsSink | null = null;\n\nexport function setDevtoolsSink(sink: DevtoolsSink | null): void {\n devtoolsSink = sink;\n}\n","/**\n * pathDiagnostics.ts — パスに関する**エラーの文言**(throw する側)と、診断の両面が共有する部品。\n *\n * 束縛時の存在検査(`user.nmae` のような打ち間違いを console.warn で知らせる開発時の診断)は\n * `features/diagnostics` へ分けた(diagnostics/pathChecks.ts)。core に残るのは、実行を止める\n * エラーの文言と、その did-you-mean が使う候補の集め方だけ。エラーは機能の有無に関わらず\n * 読める文言で落ちなければならないので、ここは core から外せない。\n *\n * 診断 code はコンソール → lint → IDE の三面で共有する(errorGuidance.ts の規約)。\n */\n\nimport { DELIMITER } from \"./define\";\nimport { didYouMean, LINT_HINT } from \"./errorGuidance\";\n\n/** `setPathInfo` の呼び出し元の種別。診断 code と適用範囲がこれで変わる */\nexport type PathInfoSource =\n /** data-wcs / mustache / コメントバインディング */\n | \"binding\"\n /** `$watch` の宣言キー */\n | \"watch\"\n /** `$scan` の `from` / `resetOn`(docs/state-scan-design.md §2-4) */\n | \"scan\"\n /** ランタイム内部のパス翻訳(mapped な bind-component の外向き伝播)。検査しない */\n | \"internal\";\n\n/**\n * `obj` 自身+プロトタイプチェーン(Object.prototype 手前まで)から descriptor を引く。\n * 打ち切り位置は getAllPropertyDescriptors と同じ — 「state が宣言したもの」だけを\n * 存在とみなし、`toString` 等の Object.prototype 由来を存在扱いしない。\n *\n * `State.findStateDescriptor`(再帰アクセサの衝突検査)も同じ走査を使う。打ち切り位置が\n * 2 本に分かれると、片方だけが `Object.prototype` を存在扱いするようなずれ方をする。\n */\nexport function findDescriptor(obj: object, key: string): PropertyDescriptor | undefined {\n let proto: object | null = obj;\n while (proto !== null && proto !== Object.prototype) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, key);\n if (typeof descriptor !== \"undefined\") {\n return descriptor;\n }\n proto = Object.getPrototypeOf(proto);\n }\n return undefined;\n}\n\n/** `obj` 自身+プロトタイプチェーンのキー名(did-you-mean の候補集合) */\nfunction ownKeys(obj: object): string[] {\n const keys: string[] = [];\n let proto: object | null = obj;\n while (proto !== null && proto !== Object.prototype) {\n for (const key of Object.getOwnPropertyNames(proto)) {\n keys.push(key);\n }\n proto = Object.getPrototypeOf(proto);\n }\n return keys;\n}\n\n/**\n * 失敗した階層の兄弟候補。生オブジェクトのキーに加え、その階層にフラット宣言\n * (ドットパス getter)されているものも混ぜる — `cart.items.*.subtotl` の正解\n * `subtotal` は行オブジェクトには無く getterPaths にしか居ないため。\n */\nexport function collectCandidates(\n container: object,\n parentPrefix: string,\n declaredPaths: Iterable<string>,\n): string[] {\n const candidates = ownKeys(container);\n const prefix = parentPrefix.length > 0 ? parentPrefix + DELIMITER : \"\";\n for (const declared of declaredPaths) {\n if (prefix.length > 0 && !declared.startsWith(prefix)) {\n continue;\n }\n const rest = declared.slice(prefix.length);\n // 直下の 1 セグメントだけを候補にする(孫は別階層の名前なので提案しない)\n if (rest.length > 0 && rest.indexOf(DELIMITER) === -1) {\n candidates.push(rest);\n }\n }\n return candidates;\n}\n\n/** 診断 code は lint / IDE と同一語彙(errorGuidance.ts の三面共有規約) */\nexport const DIAGNOSTIC_CODE: Readonly<Record<\"binding\" | \"watch\" | \"scan\", string>> = {\n binding: \"wcs/binding-path-missing\",\n watch: \"wcs/watch-path-missing\",\n scan: \"wcs/scan-path-missing\",\n};\n\nexport const SUBJECT: Readonly<Record<\"binding\" | \"watch\" | \"scan\", string>> = {\n binding: \"Bound path\",\n watch: \"$watch path\",\n scan: \"$scan path\",\n};\n\n/**\n * ルート直下(単一セグメント)のパスが state に無いときのエラーメッセージ。\n *\n * この形だけは親アドレスを辿れないので読み取りが throw する = 元から loud だが、\n * 文面が `address.parentAddress is undefined path: cout` という内部実装の言葉で、\n * 「打ち間違い」だと分からず did-you-mean も lint 誘導も無かった。深いパスの\n * `console.warn` と同じ語彙に揃える。\n */\nexport function missingRootPathMessage(\n path: string,\n target: object,\n declaredPaths: Iterable<string>,\n): string {\n return `[${DIAGNOSTIC_CODE.binding}] Path \"${path}\" does not exist on the state tree.` +\n `${didYouMean(path, collectCandidates(target, \"\", declaredPaths))}${LINT_HINT}`;\n}\n\n/**\n * `$resolve` / `$getAll` に渡した添字の本数がワイルドカードの本数と噛み合わない。\n *\n * 不足(`$resolve`)は元から throw していたが、**超過は両 API とも黙って無視**され、\n * 取り違えた添字のまま「もっともらしい値」を返していた。本数はパス文字列から\n * 決まるので、噛み合わないことは常にプログラマのミス。\n */\nexport function indexArityMessage(\n api: \"$resolve\" | \"$getAll\" | \"$setAll\",\n path: string,\n wildcardCount: number,\n actual: number,\n): string {\n // `$getAll` / `$setAll` の添字は前方一致の接頭辞なので上限、`$resolve` だけが厳密一致\n // (docs/state-set-all-design.md §4)。\n const requirement = api === \"$resolve\"\n ? `exactly ${wildcardCount}`\n : `at most ${wildcardCount}`;\n return `[wcs/index-arity] ${api}(\"${path}\") requires ${requirement} index(es) ` +\n `(\"*\" appears ${wildcardCount} time(s) in the path) but got ${actual}.${LINT_HINT}`;\n}\n\n/**\n * `**` を含むパスが宣言済みの再帰アンカーと合致しない(綴り違い・2 つ目の `**`)。\n * 束縛形(bind.ts)・合併形(getAllRecursive.ts)・ブロードキャスト(setAllRecursive.ts)の\n * 3 入口が同じ文面で報告する。\n */\nexport function recursionAnchorMismatchMessage(path: string, recursiveAnchor: string): string {\n return `[wcs/recursion-anchor] \"${path}\" does not match the declared recursion anchor ` +\n `\"${recursiveAnchor}\". This version supports exactly one anchor per state, and \"**\" must be followed ` +\n `by a well-formed suffix (no second \"**\", no empty segment, no bare \"*\" right after \"**\").`;\n}\n\n/**\n * `$getAll(path)`(添字省略)の既定値はループ文脈の添字 `[$1..$n]` だが、それを\n * 敷けるのは path と文脈がワイルドカード連鎖を共有している場合だけ。共有ゼロなのに\n * 文脈が添字を持っている場合、黙って全展開に倒すと「文脈で絞られている」という\n * 書き手の期待と食い違い、異なる文脈の添字の流用とも区別が付かないため throw する。\n *\n * 実行時の評価文脈に依存する(`$setAll` の spread 長と同種)ので lint へは誘導しない。\n */\nexport function getAllContextMismatchMessage(path: string, contextPath: string): string {\n return `$getAll(\"${path}\") was called without indexes inside the loop context of ` +\n `\"${contextPath}\", but the path shares no wildcard level with that context, ` +\n `so the context indexes ($1..$n) do not apply. ` +\n `Pass indexes explicitly ([] expands every level).`;\n}\n\n/**\n * `$setAll(path, indexes, values, { spread: true })` の配列長がマッチ件数と噛み合わない。\n *\n * 静的には件数が分からない(実行時のリスト長に依存する)ので lint へは誘導しない。\n * 黙って切り詰める/余りを捨てると誤配が通ってしまうため throw する\n * (docs/state-set-all-design.md §3-3)。\n */\nexport function setAllSpreadArityMessage(\n path: string,\n matched: number,\n actual: number,\n): string {\n return `$setAll(\"${path}\", …, { spread: true }) requires the values array to have ` +\n `exactly one entry per matched address (matched ${matched}) but got ${actual}. ` +\n `Did the list change between $getAll and $setAll?`;\n}\n\n/**\n * `$setAll` の値と `options` の組み合わせが意味を成さない。\n * (docs/state-set-all-design.md §3-1)\n */\nexport function setAllValueKindMessage(path: string, reason: string): string {\n return `$setAll(\"${path}\") ${reason}`;\n}\n\n/**\n * ワイルドカードを解決するループ文脈が足りない(=パスの階数 > スコープの階数)。\n *\n * `matrix.*.*` を 1 段の `for` の中で読む、`$2` を 1 段のループの中で読む、といった\n * 取り違えがこれ。元の文面は `address.listIndex?.index is undefined path: matrix.*` /\n * `Index not found at position 1 for loopContext:` という内部実装の言葉で、\n * **何を間違えたのかが書かれていなかった**。\n */\nexport function wildcardScopeMessage(subject: string, needed: number, available: number): string {\n return `[wcs/wildcard-rank] ${subject} needs ${needed} enclosing loop level(s) but the current ` +\n `scope provides ${available}. Wrap it in that many \"for\" templates, or use $resolve(path, indexes) ` +\n `to name the row explicitly.${LINT_HINT}`;\n}\n\n"],"names":["DELIMITER","WILDCARD","MAX_WILDCARD_DEPTH","MAX_LOOP_DEPTH","MAX_PROPAGATION_HOPS","MAX_WATCH_CHAIN_DEPTH","DEVTOOLS_LISTENER_PRIORITY","WATCH_LISTENER_PRIORITY","STREAM_LISTENER_PRIORITY","BINDING_SEPARATOR","PROP_VALUE_SEPARATOR","MODIFIER_SEPARATOR","FILTER_SEPARATOR","MODIFIER_PREVENT","MODIFIER_STOP","MODIFIER_READONLY","MODIFIER_KEY_INIT","MODIFIER_KEY_SYNC","ELSE_KEYWORD","SPREAD_PROP","EVENT_PROP_PREFIX","EVENT_TOKEN_NAMESPACE","VOLUME_INJECTION_PROP","COMMAND_NAMESPACE","CLASS_NAMESPACE","ATTR_NAMESPACE","STYLE_NAMESPACE","INDEX_PARAM_PREFIX","tmpIndexByIndexName","i","INDEX_BY_INDEX_NAME","Object","freeze","NO_SET_TIMEOUT","SVG_NAMESPACE","STATE_CONNECTED_CALLBACK_NAME","STATE_DISCONNECTED_CALLBACK_NAME","STATE_RENDERED_CALLBACK_NAME","STATE_ERROR_CALLBACK_NAME","WEBCOMPONENT_STATE_READY_CALLBACK_NAME","STATE_BINDABLES_NAME","STATE_COMMANDS_NAME","STATE_COMMAND_TOKENS_NAME","STATE_COMMAND_NAMESPACE_NAME","STATE_EVENT_TOKENS_NAME","STATE_ON_NAME","STATE_STREAM_NAME","STATE_WATCH_NAME","STATE_SCAN_NAME","STATE_RECURSION_NAME","RECURSION_WILDCARD","STATE_LIST_KEYS_NAME","STATE_STREAM_STATUS_NAMESPACE_NAME","STATE_STREAM_ERROR_NAMESPACE_NAME","DCC_DEFINITION_ATTRIBUTE","_cache","Map","id","getPathInfo","path","pathInfo","get","indexOf","raiseError","segmentCount","count","length","countSegments","PathInfo","set","segments","lastSegment","cumulativePaths","cumulativePathSet","cumulativePathInfos","cumulativePathInfoSet","parentPath","wildcardPaths","wildcardPathSet","indexByWildcardPath","wildcardPathInfos","wildcardPathInfoSet","wildcardParentPaths","wildcardParentPathSet","wildcardParentPathInfos","wildcardParentPathInfoSet","wildcardPositions","lastWildcardPath","lastWildcardInfo","wildcardCount","parentPathInfo","constructor","getPattern","_path","this","split","currentPatternPath","prevPatternPath","push","Set","devtoolsSink","setDevtoolsSink","sink","findDescriptor","obj","key","proto","prototype","descriptor","getOwnPropertyDescriptor","getPrototypeOf","collectCandidates","container","parentPrefix","declaredPaths","candidates","keys","getOwnPropertyNames","ownKeys","prefix","declared","startsWith","rest","slice","DIAGNOSTIC_CODE","binding","watch","scan","SUBJECT","missingRootPathMessage","target","didYouMean","LINT_HINT","indexArityMessage","api","actual","recursionAnchorMismatchMessage","recursiveAnchor","getAllContextMismatchMessage","contextPath","setAllSpreadArityMessage","matched","setAllValueKindMessage","reason","wildcardScopeMessage","subject","needed","available"],"mappings":"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"}