@wcstack/state 2.6.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +112 -45
- package/README.md +114 -45
- package/dist/auto.min.js +1 -1
- package/dist/auto.min.js.map +1 -1
- package/dist/define.d.ts +295 -0
- package/dist/define.js +1 -0
- package/dist/index.d.ts +254 -94
- package/dist/index.esm.js +1 -23477
- package/dist/index.esm.js.map +1 -1
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.esm.js +22 -37
- package/dist/parser.d.ts +37 -39
- package/dist/parser.esm.js +172 -1153
- package/dist/split/chunks/binder.js +2 -0
- package/dist/split/chunks/binder.js.map +1 -0
- package/dist/split/chunks/checkDependency.js +2 -0
- package/dist/split/chunks/checkDependency.js.map +1 -0
- package/dist/split/chunks/diagnosticsHooks.js +2 -0
- package/dist/split/chunks/diagnosticsHooks.js.map +1 -0
- package/dist/split/chunks/errorGuidance.js +2 -0
- package/dist/split/chunks/errorGuidance.js.map +1 -0
- package/dist/split/chunks/features.d.ts +29 -0
- package/dist/split/chunks/filterRegistry.js +2 -0
- package/dist/split/chunks/filterRegistry.js.map +1 -0
- package/dist/split/chunks/getAllPropertyDescriptors.js +2 -0
- package/dist/split/chunks/getAllPropertyDescriptors.js.map +1 -0
- package/dist/split/chunks/lifecycleHooks.js +2 -0
- package/dist/split/chunks/lifecycleHooks.js.map +1 -0
- package/dist/split/chunks/mount.js +2 -0
- package/dist/split/chunks/mount.js.map +1 -0
- package/dist/split/chunks/pathDiagnostics.js +2 -0
- package/dist/split/chunks/pathDiagnostics.js.map +1 -0
- package/dist/split/chunks/registerComponents.js +2 -0
- package/dist/split/chunks/registerComponents.js.map +1 -0
- package/dist/split/chunks/setAll.js +2 -0
- package/dist/split/chunks/setAll.js.map +1 -0
- package/dist/split/chunks/version.js +2 -0
- package/dist/split/chunks/version.js.map +1 -0
- package/dist/split/chunks/watchRuntime.js +2 -0
- package/dist/split/chunks/watchRuntime.js.map +1 -0
- package/dist/split/core.d.ts +1417 -0
- package/dist/split/core.js +2 -0
- package/dist/split/core.js.map +1 -0
- package/dist/split/features/devtools.d.ts +9 -0
- package/dist/split/features/devtools.js +2 -0
- package/dist/split/features/devtools.js.map +1 -0
- package/dist/split/features/diagnostics.d.ts +11 -0
- package/dist/split/features/diagnostics.js +2 -0
- package/dist/split/features/diagnostics.js.map +1 -0
- package/dist/split/features/formats.d.ts +10 -0
- package/dist/split/features/formats.js +2 -0
- package/dist/split/features/formats.js.map +1 -0
- package/dist/split/features/recursion.d.ts +9 -0
- package/dist/split/features/recursion.js +2 -0
- package/dist/split/features/recursion.js.map +1 -0
- package/dist/split/features/scopes.d.ts +10 -0
- package/dist/split/features/scopes.js +2 -0
- package/dist/split/features/scopes.js.map +1 -0
- package/dist/split/features/ssr.d.ts +9 -0
- package/dist/split/features/ssr.js +2 -0
- package/dist/split/features/ssr.js.map +1 -0
- package/dist/split/features/temporal.d.ts +9 -0
- package/dist/split/features/temporal.js +2 -0
- package/dist/split/features/temporal.js.map +1 -0
- package/dist/wcs-manifest.json +1 -0
- package/package.json +13 -1
|
@@ -0,0 +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};
|
|
2
|
+
//# sourceMappingURL=checkDependency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkDependency.js","sources":["../../../../../src/proxy/methods/checkDependency.ts"],"sourcesContent":["import { calcWildcardLen } from \"../../address/calcWildcardLen\";\nimport { IStateAddress } from \"../../address/types\";\nimport { listIndexAtWildcard } from \"../../list/wildcardLevel\";\nimport { IStateHandler } from \"../types\";\n\nexport function checkDependency(\n handler: IStateHandler,\n address: IStateAddress,\n): void {\n // $untrackDependency スコープ中/setter 実行中は依存を張らない\n if (handler.untracking) {\n return;\n }\n // 動的依存関係の登録\n if (handler.addressStackLength > 0) {\n const lastAddress = handler.lastAddressStack;\n const lastInfo = lastAddress?.pathInfo ?? null;\n const stateElement = handler.stateElement;\n if (lastInfo !== null) {\n if (stateElement.getterPaths.has(lastInfo.path) &&\n lastInfo.path !== address.pathInfo.path) {\n // lastInfo.pathはgetterの名前であり、address.pathInfo.pathは\n // そのgetterが参照している値のパスである\n stateElement.addDynamicDependency(address.pathInfo.path, lastInfo.path);\n // 他行読み取りの検出: 評価中の getter と読み取り先が同じワイルドカード親\n // (リスト)を共有し、その階層の listIndex が異なる場合、この getter は\n // 自行の外に依存する(隣接項目参照など)。該当リストを crossRowListPaths に\n // 記録し、walkDependency の diff-filter 展開を全行展開へフォールバックさせる。\n if (address.pathInfo.wildcardCount > 0 && lastInfo.wildcardCount > 0) {\n const sharedLen = calcWildcardLen(address.pathInfo, lastInfo);\n if (sharedLen > 0) {\n // 共有ワイルドカード段の突き合わせ。base 深さ Δ を持つ子スコープでは\n // 先頭起点だと Δ 段目(=親子で常に同一の base)を比べてしまい、\n // 本物の他行読み取りを取りこぼす。末尾起点で数える(list/wildcardLevel.ts)\n let crossRow = false;\n const hereChain = address.listIndex ?? null;\n const thereChain = lastAddress!.listIndex ?? null;\n for (let level = 0; level < sharedLen; level++) {\n const here = hereChain !== null\n ? listIndexAtWildcard(hereChain, level, address.pathInfo.wildcardCount) : null;\n const there = thereChain !== null\n ? listIndexAtWildcard(thereChain, level, lastInfo.wildcardCount) : null;\n if (here !== there) {\n crossRow = true;\n break;\n }\n }\n if (crossRow) {\n for (let level = 0; level < sharedLen; level++) {\n stateElement.addCrossRowListPath?.(address.pathInfo.wildcardParentPaths[level]);\n }\n }\n }\n }\n }\n }\n }\n}"],"names":["checkDependency","handler","address","untracking","addressStackLength","lastAddress","lastAddressStack","lastInfo","pathInfo","stateElement","getterPaths","has","path","addDynamicDependency","wildcardCount","sharedLen","calcWildcardLen","crossRow","hereChain","listIndex","thereChain","level","listIndexAtWildcard","addCrossRowListPath","wildcardParentPaths"],"mappings":"wCAKM,SAAUA,EACdC,EACAC,GAGA,IAAID,EAAQE,YAIRF,EAAQG,mBAAqB,EAAG,CAClC,MAAMC,EAAcJ,EAAQK,iBACtBC,EAAWF,GAAaG,UAAY,KACpCC,EAAeR,EAAQQ,aAC7B,GAAiB,OAAbF,GACEE,EAAaC,YAAYC,IAAIJ,EAASK,OACxCL,EAASK,OAASV,EAAQM,SAASI,OAGnCH,EAAaI,qBAAqBX,EAAQM,SAASI,KAAML,EAASK,MAK9DV,EAAQM,SAASM,cAAgB,GAAKP,EAASO,cAAgB,GAAG,CACpE,MAAMC,EAAYC,EAAgBd,EAAQM,SAAUD,GACpD,GAAIQ,EAAY,EAAG,CAIjB,IAAIE,GAAW,EACf,MAAMC,EAAYhB,EAAQiB,WAAa,KACjCC,EAAaf,EAAac,WAAa,KAC7C,IAAK,IAAIE,EAAQ,EAAGA,EAAQN,EAAWM,IAAS,CAK9C,IAJ2B,OAAdH,EACTI,EAAoBJ,EAAWG,EAAOnB,EAAQM,SAASM,eAAiB,SAC/C,OAAfM,EACVE,EAAoBF,EAAYC,EAAOd,EAASO,eAAiB,MACjD,CAClBG,GAAW,EACX,KACF,CACF,CACA,GAAIA,EACF,IAAK,IAAII,EAAQ,EAAGA,EAAQN,EAAWM,IACrCZ,EAAac,sBAAsBrB,EAAQM,SAASgB,oBAAoBH,GAG9E,CACF,CAGN,CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnosticsHooks.js","sources":["../../../../../src/core/diagnosticsHooks.ts"],"sourcesContent":["/**\n * core/diagnosticsHooks.ts — 開発時の診断の受け口(@wcstack/state/features/diagnostics)。\n *\n * 束縛時のパス存在検査(打ち間違いの console.warn)は、動作には関わらない開発時の診断\n * なので機能として分けた。core は呼び出し点だけを持ち、置かれていなければ何もしない —\n * readiness barrier は無い(診断が無いのは壊れた宣言ではなく、静かな本番形)。\n * full / auto の `bootstrapState()` は入れるので、従来のページは今までどおり警告を受け取る。\n *\n * 呼び出し点:\n * check パス情報の登録(State.setPathInfo — 束縛・`$watch`・`$scan`)\n * reset state の世代が進んだとき(`_state` 再セット)\n * markExported マウントの公開 getter が生えたとき(webComponent/exportIndex.ts)\n */\nimport type { IStateElement } from \"../components/types\";\nimport type { PathInfoSource } from \"../pathDiagnostics\";\n\nexport interface IPathDiagnostics {\n check(stateElement: IStateElement, state: object | undefined, path: string, source: PathInfoSource): void;\n reset(stateElement: IStateElement): void;\n markExported(stateElement: IStateElement, path: string): void;\n}\n\n/** 置かれていなければ null(診断を出さない) */\nexport let pathDiagnostics: IPathDiagnostics | null = null;\n\n/** 機能の install が呼ぶ(冪等 — 置き換え) */\nexport function setPathDiagnostics(diagnostics: IPathDiagnostics | null): void {\n pathDiagnostics = diagnostics;\n}\n"],"names":["pathDiagnostics","setPathDiagnostics","diagnostics"],"mappings":"AAuBO,IAAIA,EAA2C,KAGhD,SAAUC,EAAmBC,GACjCF,EAAkBE,CACpB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function t(t){throw new Error(`[@wcstack/state] ${t}`)}function n(t,n,e){if(Math.abs(t.length-n.length)>e)return e+1;const r=new Array(n.length+1),l=new Array(n.length+1);for(let t=0;t<=n.length;t++)r[t]=t;for(let e=1;e<=t.length;e++){l[0]=e;for(let o=1;o<=n.length;o++){const a=t[e-1]===n[o-1]?0:1;l[o]=Math.min(r[o]+1,l[o-1]+1,r[o-1]+a)}for(let t=0;t<=n.length;t++)r[t]=l[t]}return r[n.length]}function e(t,e){if(0===t.length)return"";const r=t.toLowerCase();let l=null,o=3;for(const t of e){const e=n(r,t.toLowerCase(),2);e<o&&(l=t,o=e)}return null!==l?` Did you mean "${l}"?`:""}const r=" Validate statically: npx @wcstack/lint <file>.";export{r as L,e as d,t as r};
|
|
2
|
+
//# sourceMappingURL=errorGuidance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorGuidance.js","sources":["../../../../../src/raiseError.ts","../../../../../src/errorGuidance.ts"],"sourcesContent":["\nexport function raiseError(message: string): never {\n throw new Error(`[@wcstack/state] ${message}`);\n}","/**\n * errorGuidance.ts — エラーメッセージへの self-fix 誘導(GTM 2-5 /\n * docs/static-wiring-dx-design.md §3)。\n *\n * コンソールは「書き手(人間・AI とも)が誤った瞬間に必ず読む面」なので、\n * (a) did-you-mean 候補 (b) lint への誘導 をエラーメッセージ自体に埋め込む。\n * ここの関数は全て**エラーパスでのみ**呼ばれる — 正常系のコストはゼロ。\n * auto.min.js に同梱されるため文字列は最小限に保つ(エラーパス専用モジュールの\n * 遅延 import は `src/auto.ts` の SRI 自己完結制約で不可)。\n *\n * 診断 code の語彙はコンソール → lint → IDE の三面で共有する:\n * メッセージ先頭の `[wcs/...]` は wcstack-intellisense / @wcstack/lint の\n * 安定診断 code(packages/vscode-wcs/src/core/diagnostics.ts)と同一。\n */\n\n/** 挿入・削除・置換の編集距離。長さ差が max を超えたら早期に max+1 を返す。 */\nfunction editDistance(a: string, b: string, max: number): number {\n if (Math.abs(a.length - b.length) > max) {\n return max + 1;\n }\n const prev: number[] = new Array(b.length + 1);\n const curr: number[] = new Array(b.length + 1);\n for (let j = 0; j <= b.length; j++) {\n prev[j] = j;\n }\n for (let i = 1; i <= a.length; i++) {\n curr[0] = i;\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost);\n }\n for (let j = 0; j <= b.length; j++) {\n prev[j] = curr[j];\n }\n }\n return prev[b.length];\n}\n\n/**\n * 候補集合から編集距離 2 以内の最近傍を探し、` Did you mean \"<best>\"?` を返す。\n * 該当なしは空文字。規準(距離 2・同距離は先勝ち・大小文字は畳んで比較)は\n * lint の did-you-mean(ioNodeValidator の suggestion)と同じ — 三面で提案が\n * 割れないように揃えている。動的キー等で候補が列挙できないサイトでは呼ばない\n * = 誘導文のみに縮退(設計 §3 の縮退)。\n */\nexport function didYouMean(input: string, candidates: Iterable<string>): string {\n // 空入力(`a|` の末尾パイプ等)に短い候補を提案しても無意味なので出さない。\n if (input.length === 0) {\n return \"\";\n }\n const folded = input.toLowerCase();\n let best: string | null = null;\n let bestDistance = 3;\n for (const candidate of candidates) {\n const distance = editDistance(folded, candidate.toLowerCase(), 2);\n if (distance < bestDistance) {\n best = candidate;\n bestDistance = distance;\n }\n }\n return best !== null ? ` Did you mean \"${best}\"?` : \"\";\n}\n\n/**\n * lint への誘導(誘導付きメッセージ共通の一文)。\n * **lint が実際にそのケースを検出するサイトにだけ付ける** — 検出しないケースに\n * 付けると「エラー → lint 実行 → clean」の空振りで検証ループの信頼を毀損する。\n * 現在 lint 未検出のため付けないもの: DCC 宣言・watch の空キー / Object.prototype\n * 継承名 / ワイルドカード深度超過。\n * なお hint 付きサイト内でも被覆は部分的でありうる(例: `$watch: ident` の実体が\n * 非オブジェクトだった場合、ランタイムは評価後の値で raise するが lint は宣言 shape\n * から断定できず沈黙する)。サイト粒度の hint ではこの残余は構造的に避けられない。\n */\nexport const LINT_HINT = \" Validate statically: npx @wcstack/lint <file>.\";\n"],"names":["raiseError","message","Error","editDistance","a","b","max","Math","abs","length","prev","Array","curr","j","i","cost","min","didYouMean","input","candidates","folded","toLowerCase","best","bestDistance","candidate","distance","LINT_HINT"],"mappings":"AACM,SAAUA,EAAWC,GACzB,MAAM,IAAIC,MAAM,oBAAoBD,IACtC,CCaA,SAASE,EAAaC,EAAWC,EAAWC,GAC1C,GAAIC,KAAKC,IAAIJ,EAAEK,OAASJ,EAAEI,QAAUH,EAClC,OAAOA,EAAM,EAEf,MAAMI,EAAiB,IAAIC,MAAMN,EAAEI,OAAS,GACtCG,EAAiB,IAAID,MAAMN,EAAEI,OAAS,GAC5C,IAAK,IAAII,EAAI,EAAGA,GAAKR,EAAEI,OAAQI,IAC7BH,EAAKG,GAAKA,EAEZ,IAAK,IAAIC,EAAI,EAAGA,GAAKV,EAAEK,OAAQK,IAAK,CAClCF,EAAK,GAAKE,EACV,IAAK,IAAID,EAAI,EAAGA,GAAKR,EAAEI,OAAQI,IAAK,CAClC,MAAME,EAAOX,EAAEU,EAAI,KAAOT,EAAEQ,EAAI,GAAK,EAAI,EACzCD,EAAKC,GAAKN,KAAKS,IAAIN,EAAKG,GAAK,EAAGD,EAAKC,EAAI,GAAK,EAAGH,EAAKG,EAAI,GAAKE,EACjE,CACA,IAAK,IAAIF,EAAI,EAAGA,GAAKR,EAAEI,OAAQI,IAC7BH,EAAKG,GAAKD,EAAKC,EAEnB,CACA,OAAOH,EAAKL,EAAEI,OAChB,CASM,SAAUQ,EAAWC,EAAeC,GAExC,GAAqB,IAAjBD,EAAMT,OACR,MAAO,GAET,MAAMW,EAASF,EAAMG,cACrB,IAAIC,EAAsB,KACtBC,EAAe,EACnB,IAAK,MAAMC,KAAaL,EAAY,CAClC,MAAMM,EAAWtB,EAAaiB,EAAQI,EAAUH,cAAe,GAC3DI,EAAWF,IACbD,EAAOE,EACPD,EAAeE,EAEnB,CACA,OAAgB,OAATH,EAAgB,kBAAkBA,MAAW,EACtD,CAYO,MAAMI,EAAY"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/features.ts — 分割エントリの install(設計案 §4、要件 D15)。
|
|
3
|
+
*
|
|
4
|
+
* 機能のエントリは「名前と install を持つ記述子」を export し、ページは要るものだけを入れる:
|
|
5
|
+
*
|
|
6
|
+
* ```js
|
|
7
|
+
* import { bootstrapState, installFeatures } from "@wcstack/state/core";
|
|
8
|
+
* import temporal from "@wcstack/state/features/temporal";
|
|
9
|
+
* installFeatures([temporal]);
|
|
10
|
+
* bootstrapState();
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* full(`@wcstack/state`)と `/auto` は `bootstrapState()` が全機能を入れるので、利用者から見た
|
|
14
|
+
* 挙動は変わらない。
|
|
15
|
+
*
|
|
16
|
+
* **冪等は機能側の `install` が持つ**(どれも `installed` フラグで 2 回目を弾く)。ここで名前を
|
|
17
|
+
* 覚えて重複を弾く手もあるが、同じことを 2 箇所で持つだけで、しかも「`bootstrapState()` を
|
|
18
|
+
* 2 回呼ぶと 2 回目は機能の install に届かない」という観測できる差が増える。core は素直に並べた順に呼ぶ。
|
|
19
|
+
*/
|
|
20
|
+
interface IStateFeature {
|
|
21
|
+
/** 機能の名前(受け口のレジストリのキーと同じ。barrier の文言が使う) */
|
|
22
|
+
readonly name: string;
|
|
23
|
+
/** 受け口へこの機能の実装を置く。**冪等であること** — core は 2 回呼ぶことがある */
|
|
24
|
+
install(): void;
|
|
25
|
+
}
|
|
26
|
+
declare function installFeatures(features: readonly IStateFeature[]): void;
|
|
27
|
+
|
|
28
|
+
export { installFeatures as i };
|
|
29
|
+
export type { IStateFeature as I };
|
|
@@ -0,0 +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};
|
|
2
|
+
//# sourceMappingURL=filterRegistry.js.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +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};
|
|
2
|
+
//# sourceMappingURL=getAllPropertyDescriptors.js.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +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};
|
|
2
|
+
//# sourceMappingURL=lifecycleHooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycleHooks.js","sources":["../../../../../src/stateLoader/loadFromInnerScript.ts","../../../../../src/stateLoader/loadFromScriptFile.ts","../../../../../src/core/lifecycleHooks.ts"],"sourcesContent":["import { IState } from \"../types\";\n\ntype ScriptModule = { default?: unknown };\n\nconst CSP_GUIDE = \"https://github.com/wcstack/wcstack/blob/main/docs/csp.md\";\n\n/**\n * インライン `<script>` の評価失敗を、原因の分かるメッセージに変換する。\n *\n * CSP にブロックされた動的 import の rejection は\n * \"Failed to fetch dynamically imported module\" としか言わず、CSP には一切言及しない。\n * ブロックされた事実は securitypolicyviolation イベントでしか観測できないため、\n * その観測結果を `cspBlocked` で受け取る。\n *\n * 真ならブロック確定として対処方法まで書く。偽のときは構文エラー等と区別できないので、\n * 元のエラーを主にして CSP は参照先を添えるに留める(誤誘導を避ける)。\n */\nfunction describeImportFailure(name: string, error: unknown, cspBlocked: boolean): string {\n const detail = (error as Error)?.message ?? String(error);\n if (cspBlocked) {\n return `The inline <script> of state \"${name}\" was blocked by Content-Security-Policy. ` +\n `Inline state is evaluated through a blob: URL, so script-src must allow blob:. ` +\n `Prefer moving the state into an external file and loading it with src=\"./state.js\", ` +\n `which requires no extra CSP directive. See ${CSP_GUIDE}`;\n }\n return `Failed to evaluate the inline <script> of state \"${name}\": ${detail}. ` +\n `If this page sets a Content-Security-Policy, see ${CSP_GUIDE}`;\n}\n\n/**\n * ロードごとに増える通し番号。`data:` URL フォールバック(createObjectURL の無い\n * テスト / SSR 環境)では URL がスクリプト本文そのものなので、同じ本文を 2 度\n * 読み込むと ESM ローダーのキャッシュに当たり **同じモジュール = 同じ default export\n * オブジェクト** が返る — 2 つ目の `<wcs-state>` が 1 つ目の state を共有してしまう\n * (テストでは前のテストの書き込みが次のテストに漏れ、SSR では同一テンプレートの\n * 再描画で state が共有される)。blob: URL は生成のたびに一意なのでブラウザでは\n * 起きない。sourceURL コメントに番号を混ぜて本文を毎回変え、両経路を揃える。\n */\nlet loadSequence = 0;\n\nexport async function loadFromInnerScript(script: HTMLScriptElement, sourceLabel: string): Promise<IState> {\n let scriptModule: ScriptModule | null = null;\n const uniq_comment = `\\n//# sourceURL=${sourceLabel}#${++loadSequence}\\n`;\n // import() が失敗した理由が CSP かどうかを判別するために、評価の間だけ違反を購読する。\n let cspBlocked = false;\n const onViolation = (event: Event) => {\n if ((event as SecurityPolicyViolationEvent).effectiveDirective.startsWith(\"script-src\")) {\n cspBlocked = true;\n }\n };\n document.addEventListener(\"securitypolicyviolation\", onViolation);\n try {\n if (typeof URL.createObjectURL === 'function') {\n // Create a blob URL for the script and dynamically import it\n const blob = new Blob([script.text + uniq_comment], { type: \"application/javascript\" });\n const url = URL.createObjectURL(blob);\n try {\n scriptModule = await import(url) as ScriptModule;\n } finally {\n // Clean up blob URL to prevent memory leak\n URL.revokeObjectURL(url);\n }\n } else {\n // Fallback: Base64 encoding method (for test environment)\n // Convert script to Base64 and import via data: URL\n const b64 = btoa(String.fromCodePoint(...new TextEncoder().encode(script.text + uniq_comment)));\n scriptModule = await import(`data:application/javascript;base64,${b64}`) as ScriptModule;\n }\n } catch (e) {\n // 呼び出し元(State._initialize / _initializeDCC)が raiseError で\n // `[@wcstack/state]` を付けるため、ここでは prefix を重ねない。\n throw new Error(describeImportFailure(sourceLabel, e, cspBlocked), { cause: e });\n } finally {\n document.removeEventListener(\"securitypolicyviolation\", onViolation);\n }\n return (scriptModule && typeof scriptModule.default === 'object') ? scriptModule.default as IState : {};\n}\n","import { raiseError } from \"../raiseError\";\nimport { IState } from \"../types\";\n\n/**\n * `src` の値を **document の base URL** に対して解決する。\n *\n * `import(url)` の相対解決は「import を書いたモジュール」を基準にする。ここは\n * `@wcstack/state` の中なので、素の `import(url)` は `<wcs-state src>` を\n * **state パッケージの所在**から解決してしまう。同一オリジンに置いたページでは\n * たまたま一致して見えるが、CDN 一発(`https://esm.run/@wcstack/state/auto`)で\n * 読み込んだ瞬間に `src=\"/app.js\"` が CDN 側の URL を指して 404 になる。\n *\n * `src` は HTML 属性なので、正しい基準は document の base URL である\n * (`src=\"*.json\"` 側は `fetch` がそう解決しており、同じ属性が形式によって\n * 違う基準で解決されていた)。絶対 URL・`data:`・`blob:` は URL 解決で\n * そのまま素通りするため、既存の使い方は影響を受けない。\n */\nexport function resolveAgainstDocument(url: string): string {\n return new URL(url, document.baseURI).href;\n}\n\nexport async function loadFromScriptFile(url: string): Promise<IState> {\n try {\n const module = await import(/* @vite-ignore */ resolveAgainstDocument(url));\n return module.default || {};\n } catch (e) {\n raiseError(`Failed to load script file: ${e}`);\n }\n}\n","/**\n * core/lifecycleHooks.ts — ライフサイクルの受け口(設計案 H3・H5、S4)。\n *\n * `connectedCallback` / `disconnectedCallback` の「この要素は自分のものだ」という分岐\n * (ボリューム `mount=`・DCC・bind-component)を機能側へ移すための受け口。機能は\n * `install()` で `registerLifecycleHooks` を呼び、core は登録順ではなく `order` の昇順で聞く\n * (install の順に依存させない — 従来の分岐順が契約なので、番号でそれを固定する)。\n *\n * `connecting` は「引き取らない」を **null** で返す。引き取るときだけ Promise を返すので、\n * 引き取り手の無い素の state(大多数)に microtask の境界を 1 つも足さない。\n */\nimport type { IStateElement } from \"../components/types\";\nimport { raiseError } from \"../raiseError\";\nimport { featureNotInstalledMessage } from \"./featureEntries\";\n\n/** 引き取ったが待つものが無いときの返り値 */\nexport const CLAIMED: Promise<void> = /*#__PURE__*/ Promise.resolve();\n\n/** 引き取るなら「この接続の初期化」の Promise、引き取らないなら null */\nexport type ConnectingHook = (element: IStateElement) => Promise<void> | null;\n/** 引き取って切断を処理したなら true */\nexport type DisconnectingHook = (element: IStateElement) => boolean;\n/**\n * 接続の前処理。「興味が無い」は null、あるなら「この要素を丸ごと引き取ったか」を解決する Promise。\n * `bind-component` のように「必ず走るが、引き取るのは条件つき」という機能のための段。\n */\nexport type PreparingHook = (element: IStateElement) => Promise<boolean> | null;\n/** 初期化済みの要素の再接続を引き取ったなら true */\nexport type ReconnectingHook = (element: IStateElement) => boolean;\n/** ルート要素の初期化が失敗した(このルートノードを待っている機能に知らせる) */\nexport type InitializeFailedHook = (element: IStateElement, rootNode: Node, error: unknown) => void;\n/** 失敗したルート要素自身が DOM から消えた(「このルートにルートは来ない」はもう成り立たない) */\nexport type InitializeFailureClearedHook = (element: IStateElement, rootNode: Node) => void;\n/** state の差し替えを拒むなら throw する(拒まないなら何もしない) */\nexport type ReplacingStateHook = (element: IStateElement) => void;\n\nexport interface ILifecycleHooks {\n /** 聞く順(従来の分岐順: DCC 10 → ボリューム 20 → bind-component 30) */\n readonly order: number;\n readonly connecting?: ConnectingHook;\n readonly preparing?: PreparingHook;\n readonly disconnecting?: DisconnectingHook;\n readonly reconnecting?: ReconnectingHook;\n readonly replacingState?: ReplacingStateHook;\n readonly initializeFailed?: InitializeFailedHook;\n readonly initializeFailureCleared?: InitializeFailureClearedHook;\n}\n\nconst registry = new Map<string, ILifecycleHooks>();\nlet ordered: ILifecycleHooks[] = [];\n\n/** 機能の install が呼ぶ(冪等) */\nexport function registerLifecycleHooks(feature: string, hooks: ILifecycleHooks): void {\n registry.set(feature, hooks);\n ordered = Array.from(registry.values()).sort((a, b) => a.order - b.order);\n}\n\n/**\n * 宣言(属性)が機能を要求したのに誰も引き取らなかった: 未 install として名指しで throw する\n * (readiness barrier、H5 / D13)。full / auto は `bootstrapState()` が install するので起きない。\n */\nexport function requireLifecycleFeature(feature: string, declaration: string): never {\n return raiseError(featureNotInstalledMessage(feature, declaration));\n}\n\n/** 接続を引き取る機能を探す。引き取り手が無ければ null(core が通常の初期化を続ける) */\nexport function runConnecting(element: IStateElement): Promise<void> | null {\n for (let i = 0; i < ordered.length; i++) {\n const claimed = ordered[i].connecting?.(element);\n if (claimed != null) {\n return claimed;\n }\n }\n return null;\n}\n\n/**\n * 接続の前処理を持つ機能を探す。1 つも無ければ null(素の state に microtask の境界を足さない)。\n * 解決値が true なら、その機能がこの要素を丸ごと引き取っている。\n */\nexport function runPreparing(element: IStateElement): Promise<boolean> | null {\n for (let i = 0; i < ordered.length; i++) {\n const prepared = ordered[i].preparing?.(element);\n if (prepared != null) {\n return prepared;\n }\n }\n return null;\n}\n\n/** 初期化済みの要素の再接続を引き取る機能を探す。引き取られたら true */\nexport function runReconnecting(element: IStateElement): boolean {\n for (let i = 0; i < ordered.length; i++) {\n if (ordered[i].reconnecting?.(element) === true) {\n return true;\n }\n }\n return false;\n}\n\n/** state の差し替えを拒む機能に聞く(拒む機能は throw する) */\nexport function runReplacingState(element: IStateElement): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].replacingState?.(element);\n }\n}\n\nexport function runInitializeFailed(element: IStateElement, rootNode: Node, error: unknown): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].initializeFailed?.(element, rootNode, error);\n }\n}\n\nexport function runInitializeFailureCleared(element: IStateElement, rootNode: Node): void {\n for (let i = 0; i < ordered.length; i++) {\n ordered[i].initializeFailureCleared?.(element, rootNode);\n }\n}\n\n/** 切断を引き取る機能を探す。引き取られたら true(core の後始末は走らない) */\nexport function runDisconnecting(element: IStateElement): boolean {\n for (let i = 0; i < ordered.length; i++) {\n if (ordered[i].disconnecting?.(element) === true) {\n return true;\n }\n }\n return false;\n}\n"],"names":["CSP_GUIDE","loadSequence","async","loadFromInnerScript","script","sourceLabel","scriptModule","uniq_comment","cspBlocked","onViolation","event","effectiveDirective","startsWith","document","addEventListener","URL","createObjectURL","blob","Blob","text","type","url","import","revokeObjectURL","b64","btoa","String","fromCodePoint","TextEncoder","encode","e","Error","name","error","detail","message","describeImportFailure","cause","removeEventListener","default","loadFromScriptFile","module","baseURI","href","resolveAgainstDocument","raiseError","CLAIMED","Promise","resolve","registry","Map","ordered","registerLifecycleHooks","feature","hooks","set","Array","from","values","sort","a","b","order","requireLifecycleFeature","declaration","featureNotInstalledMessage","runConnecting","element","i","length","claimed","connecting","runPreparing","prepared","preparing","runReconnecting","reconnecting","runReplacingState","replacingState","runInitializeFailed","rootNode","initializeFailed","runInitializeFailureCleared","initializeFailureCleared","runDisconnecting","disconnecting"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{D as t,j as e,g as n,W as r,R as o}from"./pathDiagnostics.js";import{aS as s}from"./binder.js";import{r as a}from"./errorGuidance.js";function i(t,e){if(e.length>t.length)return!1;for(let n=0;n<e.length;n++)if(t[n]!==e[n])return!1;return!0}function c(t,e){for(const n of t)if(i(e,n.innerSegments))return n;return null}function l(e,n){const r=n.slice(e.innerSegments.length);return 0===r.length?e.outerPathInfo.path:e.outerPathInfo.path+t+r.join(t)}let u=0;const d=["$watch","$streams","$scan","$listKeys","$updatedCallback","$commandTokens","$eventTokens","$on","$recursion","$errorCallback"],f=new Set;function h(t){const e=d.filter(e=>void 0!==t.stateObject[e]);for(const n of t.getterKeys)-1!==n.indexOf(o)&&e.push(`"${n}"`);if(0===e.length)return;const n=`${t.component.tagName.toLowerCase()}|${t.stateProp}`;f.has(n)||(f.add(n),console.warn(`[@wcstack/state] [wcs/mount-dollar-declaration] <${n.split("|")[0]}>.${t.stateProp} declares ${e.join(", ")}, which mounted components do not run. Declare them on the root state instead (a volume <wcs-state mount="..."> can host $watch / $listKeys / $updatedCallback; $recursion and "**" getters expand against the root tree). See docs/state-mount-design.md §4-6.`))}function m(t,e){const n=t.stateObject[e];if("function"==typeof n)try{const r=t.component[t.stateProp],o=n.call(r);o instanceof Promise&&o.catch(n=>{console.error(`[@wcstack/state] mounted <${t.component.tagName.toLowerCase()}> ${e} failed.`,n)})}catch(n){console.error(`[@wcstack/state] mounted <${t.component.tagName.toLowerCase()}> ${e} failed.`,n)}}function p(n,r,o,s,i,c=new Set){0===o.length&&a(`Cannot build a mount record without host bindings for "${r}".`);const l=[],d=new Set;let f=null;for(const n of o){const r=n.propSegments.slice(1),o=r.join(t);d.has(o)&&a("Duplicate mapping rule for web component."),d.add(o);const s={innerSegments:r,outerPathInfo:n.statePathInfo,readonly:!0===n.propModifiers?.includes(e)};l.push(s),0===r.length&&(f=s)}l.sort((t,e)=>e.innerSegments.length-t.innerSegments.length);const h=++u,m=`#m${h}`,{getterKeys:p,setterKeys:g}=function(t){const e=new Set,n=new Set,r=Object.getOwnPropertyDescriptors(t);for(const[t,o]of Object.entries(r))"function"==typeof o.get&&e.add(t),"function"==typeof o.set&&n.add(t);return{getterKeys:e,setterKeys:n}}(i),y=new Set;for(const t of l)t.innerSegments.length>0&&y.add(t.innerSegments[0]);const w={};for(const t of Object.keys(i))t.startsWith("$")||p.has(t)||g.has(t)||"function"!=typeof i[t]&&(c.has(t)||y.has(t)||(w[t]=i[t]));return{id:h,marker:m,component:n,stateProp:r,parentStateElement:s,entries:l,rootEntry:f,delta:null===f?0:f.outerPathInfo.wildcardCount,markerBasePath:null===f?m:f.outerPathInfo.path+t+m,stateObject:i,getterKeys:p,setterKeys:g,injectedKeys:c,mappedKeys:y,privateSnapshot:w,accessorBySuffixByMarkerParent:new Map,indexShiftByLoopElementPath:new Map,addedGetterPaths:new Set,exports:new Map}}function g(e){const n=e.indexOf(t);return-1===n?e:e.slice(0,n)}function y(t,e){const n=c(t.entries,e);return null===n?null:l(n,e)}function w(e,n){return e.markerBasePath+t+n}function $(e,r,o,s){let a=e.accessorBySuffixByMarkerParent.get(r);void 0===a&&(a=new Map,e.accessorBySuffixByMarkerParent.set(r,a));const i=r+t+o;a.set(o,{accessorName:s,indexShift:n(i).wildcardCount-n(s).wildcardCount}),e.getterKeys.has(s)&&(e.parentStateElement.getterPaths?.add(i),e.addedGetterPaths.add(i))}function P(t,e){return!t.injectedKeys.has(e)&&!t.mappedKeys.has(e)&&("function"==typeof t.stateObject[e]&&!t.getterKeys.has(e)||Object.prototype.hasOwnProperty.call(t.stateObject,e)&&!t.getterKeys.has(e)&&!t.setterKeys.has(e))}function k(e,n){return`Path "${n}" in <${e.component.tagName.toLowerCase()}> does not resolve: it is not an own key of the component state and no mount entry covers it (mounted prefixes: ${e.entries.filter(t=>t.innerSegments.length>0).map(e=>e.innerSegments.join(t)).join(", ")}). Mount it from the host ("${e.stateProp}: path" / "${e.stateProp}.${g(n)}: path") or declare the key on the component state.`}const S=/^\$(\d+)$/;function v(e,n){const r=n[0];if("$"===r||"#"===r)return null;if(e.getterKeys.has(n)||e.setterKeys.has(n))return null;const o=g(n);if(e.getterKeys.has(o)||e.setterKeys.has(o)||P(e,o))return null;const s=function(t,e){return c(t.entries,e)}(e,n.split(t));return null!==s&&s.readonly?s:null}function b(n,r){const o=v(n,r);if(null!==o){const s=0===o.innerSegments.length?"":t+o.innerSegments.join(t);a(`[wcs/mount-readonly] <${n.component.tagName.toLowerCase()}> cannot write "${r}": it is mounted read-only ("${n.stateProp}${s}#${e}: ${o.outerPathInfo.path}"). Write it on the host, or drop #${e} from the mount.`)}return K(n,r)}function K(e,n){const o=n[0];if("$"===o||"#"===o)return n;if(e.getterKeys.has(n)||e.setterKeys.has(n))return function(e,n){const o=n.split(t);let s=-1;for(let t=o.length-1;t>=0;t--)if(o[t]===r){s=t;break}if(-1===s)return $(e,e.markerBasePath,n,n),w(e,n);if(P(e,o[0]))return $(e,e.markerBasePath,n,n),w(e,n);const i=o.slice(0,s+1),c=o.slice(s+1),l=y(e,i);null===l&&a(k(e,n)),0===c.length&&a(`Wildcard-terminal accessor "${n}" on mounted <${e.component.tagName.toLowerCase()}> is not supported: it translates to a marker-terminal path where the mount overlay would shadow the accessor. Declare the row value as a getter on the host tree, or back it with a component-own array (a private key makes the whole path private).`);const u=l+t+e.marker;return $(e,u,c.join(t),n),u+t+c.join(t)}(e,n);const s=g(n);if(e.getterKeys.has(s)||e.setterKeys.has(s))return w(e,n);if(P(e,s))return w(e,n);const i=y(e,n.split(t));if(null!==i)return i;a(k(e,n))}function j(o,s,a){let i;const c=S.exec(s.statePathName);if(null!==c){const t=function(t,e){if(void 0===e)return t.delta;const r=K(t,e);return n(r).wildcardCount-n(e).wildcardCount}(o,a);i=0===t?s.statePathName:`$${Number(c[1])+t}`}else if(i=K(o,s.statePathName),"for"===s.bindingType){const e=n(i).wildcardCount-s.statePathInfo.wildcardCount;o.indexShiftByLoopElementPath.set(i+t+r,e)}const l=s.propModifiers,u=null===c&&Array.isArray(l)&&!l.includes(e)&&null!==v(o,s.statePathName);return i!==s.statePathName||u?{...s,statePathName:i,statePathInfo:n(i),...u?{propModifiers:[...l,e]}:{}}:s}function x(e,n){const r=n.lastIndexOf("#");if(-1===r)return e.delta;const o=n.indexOf(t,r);if((-1===o?n.slice(r):n.slice(r,o))!==e.marker)return e.delta;const s=-1===o?n:n.slice(0,o),a=-1===o?"":n.slice(o+1),i=e.accessorBySuffixByMarkerParent.get(s)?.get(a);return void 0!==i?i.indexShift:e.delta}function M(t,e,r,o,s){if(void 0===o)return;const i=n(r).wildcardCount-n(e).wildcardCount;return 0===i?o:(s.length<i&&a(`Cannot resolve "${e}" from this mount: the mounted prefix has ${i} wildcard(s) but the host context provides only ${s.length} index(es).`),[...s.slice(0,i),...o])}const C=new WeakMap,O=new WeakMap;function N(t,e){return O.get(t)?.get(e)??null}const B=new WeakMap;const I=new FinalizationRegistry(function(t){const e=t.byMarker.get(t.marker);if(void 0!==e&&void 0===e.deref()&&t.byMarker.delete(t.marker),void 0!==t.getterPaths)for(const e of t.addedGetterPaths)t.getterPaths.delete(e)}),E=new WeakMap;function W(t){return E.get(t)??null}let L=!1;function D(t,e){L||(L=!0,s(t=>C.has(t)?t.host:null)),C.set(t,e),E.set(e,t);let n=B.get(e.parentStateElement);void 0===n&&(n=new Map,B.set(e.parentStateElement,n)),n.set(e.marker,new WeakRef(e));let r=O.get(e.component);void 0===r&&(r=new Map,O.set(e.component,r));const o=r.get(e.stateProp)!==e;r.set(e.stateProp,e),o&&I.register(e,{byMarker:n,marker:e.marker,getterPaths:e.parentStateElement.getterPaths,addedGetterPaths:e.addedGetterPaths}),e.parentStateElement.markHasMounts?.()}function G(t){return C.get(t)??null}function R(t,e){let n=t;for(;null!==n&&n!==e;){const t=C.get(n);if(void 0!==t)return t;n=n.parentNode}return C.get(e)??null}function T(t){const e=B.get(t);if(void 0===e)return[];const n=[];for(const t of e.values()){const e=t.deref();void 0!==e&&n.push(e)}return n}function z(t){const e=B.get(t);return void 0!==e&&e.size>0}function A(e,n){const r=n.lastIndexOf("#");if(-1===r)return null;const o=B.get(e);if(void 0===o)return null;const s=n.indexOf(t,r),a=-1===s?n.slice(r):n.slice(r,s),i=o.get(a);if(void 0===i)return null;const c=i.deref();return void 0===c?(o.delete(a),null):c}export{K as a,b,M as c,W as d,G as e,c as f,T as g,j as h,R as i,A as j,x as k,m as l,N as m,p as n,D as r,z as s,l as t,h as w};
|
|
2
|
+
//# sourceMappingURL=mount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.js","sources":["../../../../../src/webComponent/mountEntries.ts","../../../../../src/webComponent/mount.ts"],"sourcesContent":["/**\n * webComponent/mountEntries.ts — マウントのエントリ表(内側接頭辞 → 外側パス)と、その一致。\n *\n * コンポーネントのマウント記録(mount.ts)とボリュームの注入口(volumeShared.ts、要件 B14③)が\n * 同じ表と同じ一致規則を使う。書き込み翻訳の単一点(要件 §3.4)はこの 2 つの関数に集まる —\n * 読み取り専用(`#ro`)の判定もエントリが持つ。\n */\nimport { IPathInfo } from \"../address/types\";\nimport { DELIMITER } from \"../define\";\n\nexport interface IMountEntry {\n /** 内側接頭辞のセグメント(ルートエントリは 0 個 — あらゆる内側パスに一致する) */\n readonly innerSegments: readonly string[];\n readonly outerPathInfo: IPathInfo;\n /**\n * `#ro` が付いたか(`state#ro: user` / `state.name#ro: user.name`、要件 B14 ①)。\n * 真なら、内側からこのエントリを通るツリーへの書き込みは拒否される(外側自身の書き込みは止めない)。\n */\n readonly readonly: boolean;\n}\n\nfunction startsWithSegments(segments: readonly string[], prefix: readonly string[]): boolean {\n if (prefix.length > segments.length) return false;\n for (let i = 0; i < prefix.length; i++) {\n if (segments[i] !== prefix[i]) return false;\n }\n return true;\n}\n\n/** 最長接頭辞のエントリ(entries は内側接頭辞の長い順に並べておくこと)。一致しなければ null。 */\nexport function findMountEntry(entries: readonly IMountEntry[], segments: readonly string[]): IMountEntry | null {\n for (const entry of entries) {\n if (startsWithSegments(segments, entry.innerSegments)) {\n return entry;\n }\n }\n return null;\n}\n\n/** 一致したエントリで内側パスを外側の絶対パスへ書き換える(`segments` は entry に一致していること)。 */\nexport function translateByMountEntry(entry: IMountEntry, segments: readonly string[]): string {\n const rest = segments.slice(entry.innerSegments.length);\n return rest.length === 0\n ? entry.outerPathInfo.path\n : entry.outerPathInfo.path + DELIMITER + rest.join(DELIMITER);\n}\n","import { getPathInfo } from \"../address/PathInfo\";\nimport { IPathInfo } from \"../address/types\";\nimport { IStateElement } from \"../components/types\";\nimport { setMountedScopeHost } from \"../list/loopContextByNode\";\nimport { DELIMITER, MODIFIER_READONLY, RECURSION_WILDCARD, WILDCARD } from \"../define\";\nimport { raiseError } from \"../raiseError\";\nimport { IBindingInfo } from \"../types\";\nimport { findMountEntry, IMountEntry, translateByMountEntry } from \"./mountEntries\";\n\n/**\n * webComponent/mount.ts — マウント記録(Phase 2・docs/state-mount-design.md §5、impl-plan §3-0)。\n *\n * v2 の不変条件「マウントされたコンポーネントのバインディングは、その位置にテンプレートを\n * 展開してパスに接頭辞を付けたものと区別できない」を、**バインディングの変換**として実装する。\n * マウントされたスコープのバインディングは登録時にここの `translateInnerPath` で\n * 親ツリーの絶対パスへ書き換えられ、以後は台帳・依存グラフ・キャッシュ・LIS・プールの\n * どれから見ても「親スコープにインラインで書かれた binding」と同一になる。\n *\n * 例外は私有キーと getter / メソッド(展開したテンプレートには存在しないもの)で、\n * これらは **予約セグメント**(D20・`#m<id>` — `#` はパス文法で書けない)を挟んだ\n * 絶対アドレスに載る。ツリーのアドレスと構造的に衝突せず、親 handler のオーバーレイ\n * dispatch はマーカーを含む読み書きだけに掛かる。D10(スコープ外から見えない)は\n * このアドレス空間の帰結になる。\n *\n * マーカーの位置は「ワイルドカード接頭辞の直後」:\n * - 単純な getter / 私有キー(`display` / `editing`)→ `<rootOuter>.#m.display`\n * (ルートエントリが無い部分マウントのみの形では `#m.display`)\n * - ツリーのリストの上のワイルドカード getter(`get \"children.*.label\"`、`state: group`)\n * → `group.children.*.#m.label` — ワイルドカード親がツリーのリストと一致するので、\n * ループ文脈の解決(indexByWildcardPath)と listIndex の arity が素の getter と同じに保たれる\n * - 私有配列の上のワイルドカード getter(`state = { drafts: [] }` + `get \"drafts.*.title\"`)\n * → `<rootOuter>.#m.drafts.*.title` — 配列ごと私有側に閉じる\n */\n\nexport type { IMountEntry } from \"./mountEntries\";\n\nexport interface IMountRecord {\n readonly id: number;\n /** D20 の予約セグメント(`#m<id>`) */\n readonly marker: string;\n readonly component: Element;\n readonly stateProp: string;\n readonly parentStateElement: IStateElement;\n /** マウント表(内側接頭辞の長い順 — 最長接頭辞一致は先頭ヒットで決まる) */\n readonly entries: readonly IMountEntry[];\n /** ルートエントリ(`state: path`)。無ければ null(部分マウントのみ) */\n readonly rootEntry: IMountEntry | null;\n /** Δ = ルート接頭辞のワイルドカード数(`$n` のスコープ補正が読む唯一の値) */\n readonly delta: number;\n /** 私有キー・単純 getter を載せるマーカーパス(`users.*.#m3` / `#m3`) */\n readonly markerBasePath: string;\n /** 作者の state オブジェクト(私有キー・getter・メソッドの実体) */\n readonly stateObject: Record<string, any>;\n readonly getterKeys: ReadonlySet<string>;\n readonly setterKeys: ReadonlySet<string>;\n /**\n * 完了前の親の初期適用(積み)が作者のオブジェクトに**注入した**キー\n * (webComponent/preCompletionWrites.ts)。作者のものではないので私有にしない\n * (v2 は厳格 R1: 作者が宣言した own data key は部分マウントに覆われていても私有 —\n * 設計書 §4-1 規則 2。1.x の「マッピングが勝つ」からの反転は D19 が予告済み)。\n */\n readonly injectedKeys: ReadonlySet<string>;\n /** 部分エントリが明示したキー(先頭セグメント)。同名の own data key より優先する(要件 B14 ②) */\n readonly mappedKeys: ReadonlySet<string>;\n /**\n * 私有データの初期スナップショット(own data key の浅い複製・D21)。\n * マウントインスタンス(listIndex)ごとの私有オブジェクトはここから複製される。\n */\n readonly privateSnapshot: Readonly<Record<string, unknown>>;\n /**\n * マーカーの親パス(翻訳後) → { 接尾キー → 作者のアクセサ情報 }。\n * `display` は markerBase の親に `display → display`、\n * ワイルドカード getter `\"children.*.label\"` は `group.children.*` に `label → children.*.label`。\n * `indexShift` は翻訳で増えたワイルドカード数(アクセサ内の `$n` のスコープ補正が読む)。\n * translateInnerPath のマーカー化で遅延登録され、オーバーレイの get とトラップが引く。\n */\n readonly accessorBySuffixByMarkerParent: Map<string, Map<string, IAccessorEntry>>;\n /**\n * 翻訳された `for` のループ要素パス(`groups.*.children.*`)→ 翻訳で増えた\n * ワイルドカード数。イベントハンドラの「スコープ相対の添字」(§4-4 / P2-9)が\n * 引く — 添字列の末尾から (総数 − shift) 本だけが作者の見える添字。\n * translateParsedForMount が for の翻訳時に埋める。\n */\n readonly indexShiftByLoopElementPath: Map<string, number>;\n /**\n * この記録が親の getterPaths に追加したマーカーパス(recordAccessorSuffix)。\n * 記録の恒久破棄時に cleanupCollectedMountRecord が親から回収する。\n * record の外の消費者(FinalizationRegistry の held 値)も参照するため、\n * record 本体が回収された後も held 経由で読める独立オブジェクトにしてある。\n */\n readonly addedGetterPaths: Set<string>;\n /**\n * 公開 getter(docs/state-overlay-export-design.md X2 / X3): 公開パス(マーカー無し・\n * `users.*.display`)→ マーカー親パス・接尾キー・マーカーパス。registerExports が\n * 初回登録で getter / setter キーから作る(翻訳できないアクセサは載らない)。\n */\n readonly exports: Map<string, IExportEntry>;\n}\n\nexport interface IExportEntry {\n /** マーカーで終わるパス(`users.*.#m7` — overlay.ts の「マーカー親」。accessorBySuffixByMarkerParent の鍵) */\n readonly markerTerminalPath: string;\n readonly suffix: string;\n readonly markerPath: string;\n readonly exportedPath: string;\n}\n\nexport interface IAccessorEntry {\n readonly accessorName: string;\n readonly indexShift: number;\n}\n\nlet nextMountId = 0;\n\nconst MOUNT_DOLLAR_DECLARATIONS = [\n \"$watch\", \"$streams\", \"$scan\", \"$listKeys\", \"$updatedCallback\", \"$commandTokens\", \"$eventTokens\", \"$on\",\n // $errorCallback もルート専用(要件 B11 — 以前は無言で無視していた)\n \"$recursion\", \"$errorCallback\",\n] as const;\nconst dollarDeclarationWarned = new Set<string>();\n\n/** テスト用: 宣言 warn の 1 回性台帳を空にする。 */\nexport function clearMountDollarWarnsForTesting(): void {\n dollarDeclarationWarned.clear();\n}\n\n/**\n * マウントされたコンポーネントは宣言面(`$watch` / `$streams` / `$listKeys` /\n * `$updatedCallback` / `$commandTokens` / `$eventTokens` / `$on`)を実行しない\n * (v1 の mapped も同じ — innerState が `$` を遮っていた)。無言に捨てず、\n * (tag, prop) につき 1 回だけ「ルート(または対応する宣言はボリューム)に宣言する」\n * 誘導を出す。テンプレート側の `$command.*` の**参照**(バインディングのパス)は\n * ルート宣言のトークンに解決される(`$` 頭のパスは翻訳しない — translateInnerPath)。\n * `$connectedCallback` / `$disconnectedCallback` / `$stateReadyCallback` は要素の\n * ライフサイクルとしてスコープごとに残る(設計書 §4-6)。\n */\nexport function warnMountedDollarDeclarations(record: IMountRecord): void {\n const declared: string[] = MOUNT_DOLLAR_DECLARATIONS.filter(\n (name) => typeof (record.stateObject as Record<string, unknown>)[name] !== \"undefined\",\n );\n // `**` getter(`get \"node.**.total\"()`)も同じ扱い。`markerizeAccessorPath` は `*` セグメントしか\n // 探さないので `**` を含むキーは私有アンカーに落ち、参照されないまま永久に登録されない\n // (ボリュームは接ぎ木前に拒否し、`$recursion` はこの誘導が出るのに、`**` getter だけが\n // 無言だった — 第 3 サイクルのレビューで実測)。\n for (const accessor of record.getterKeys) {\n if (accessor.indexOf(RECURSION_WILDCARD) !== -1) {\n declared.push(`\"${accessor}\"`);\n }\n }\n if (declared.length === 0) {\n return;\n }\n const key = `${record.component.tagName.toLowerCase()}|${record.stateProp}`;\n if (dollarDeclarationWarned.has(key)) {\n return;\n }\n dollarDeclarationWarned.add(key);\n console.warn(\n `[@wcstack/state] [wcs/mount-dollar-declaration] <${key.split(\"|\")[0]}>.${record.stateProp} declares ` +\n `${declared.join(\", \")}, which mounted components do not run. Declare them on the root state instead ` +\n `(a volume <wcs-state mount=\"...\"> can host $watch / $listKeys / $updatedCallback; $recursion and ` +\n `\"**\" getters expand against the root tree). See docs/state-mount-design.md §4-6.`,\n );\n}\n\n/**\n * マウントされたコンポーネントのライフサイクル呼び出し(`$connectedCallback` /\n * `$disconnectedCallback`)。`this` は公開 chroot(`element[stateProp]`)。\n * 例外・reject は 1 コンポーネントに閉じる(切断時は親も切断中でありうる)。\n */\nexport function callMountLifecycleCallback(record: IMountRecord, name: string): void {\n const callback = (record.stateObject as Record<string, unknown>)[name];\n if (typeof callback !== \"function\") {\n return;\n }\n try {\n const chroot = (record.component as unknown as Record<string, unknown>)[record.stateProp];\n const result = (callback as (this: unknown) => unknown).call(chroot);\n if (result instanceof Promise) {\n result.catch((error) => {\n console.error(`[@wcstack/state] mounted <${record.component.tagName.toLowerCase()}> ${name} failed.`, error);\n });\n }\n } catch (error) {\n console.error(`[@wcstack/state] mounted <${record.component.tagName.toLowerCase()}> ${name} failed.`, error);\n }\n}\n\n/** テスト用: マーカー id を初期化する(マーカー文字列の安定化) */\nexport function resetMountIdForTesting(): void {\n nextMountId = 0;\n}\n\nfunction collectAccessorKeys(stateObject: Record<string, any>): { getterKeys: Set<string>, setterKeys: Set<string> } {\n const getterKeys = new Set<string>();\n const setterKeys = new Set<string>();\n const descriptors = Object.getOwnPropertyDescriptors(stateObject);\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (typeof descriptor.get === \"function\") getterKeys.add(key);\n if (typeof descriptor.set === \"function\") setterKeys.add(key);\n }\n return { getterKeys, setterKeys };\n}\n\n/**\n * ホストの `state[.sub]: path` バインディング群からマウント記録を組む。\n * `bindings` は propSegments[0] === stateProp で選別済みであること\n * (bindWebComponent が v1 の buildPrimaryMappingRule に渡すものと同じ集合)。\n */\nexport function buildMountRecord(\n component: Element,\n stateProp: string,\n bindings: readonly IBindingInfo[],\n parentStateElement: IStateElement,\n stateObject: Record<string, any>,\n injectedKeys: ReadonlySet<string> = new Set<string>(),\n): IMountRecord {\n if (bindings.length === 0) {\n raiseError(`Cannot build a mount record without host bindings for \"${stateProp}\".`);\n }\n const entries: IMountEntry[] = [];\n const seenInnerPaths = new Set<string>();\n let rootEntry: IMountEntry | null = null;\n for (const binding of bindings) {\n const innerSegments = binding.propSegments.slice(1);\n const innerPath = innerSegments.join(DELIMITER);\n if (seenInnerPaths.has(innerPath)) {\n // 同じ内側パスを 2 つの規則が指す形はどちらが勝つか書き手に見えない(M6・Phase 1 と同じ)\n raiseError('Duplicate mapping rule for web component.');\n }\n seenInnerPaths.add(innerPath);\n const entry: IMountEntry = {\n innerSegments,\n outerPathInfo: binding.statePathInfo,\n readonly: binding.propModifiers?.includes(MODIFIER_READONLY) === true,\n };\n entries.push(entry);\n if (innerSegments.length === 0) {\n rootEntry = entry;\n }\n }\n entries.sort((a, b) => b.innerSegments.length - a.innerSegments.length);\n const id = ++nextMountId;\n const marker = `#m${id}`;\n const { getterKeys, setterKeys } = collectAccessorKeys(stateObject);\n // ホストが部分エントリで明示したキー(`state.theme: theme`)は、同名の own data key があっても\n // 私有にしない — 明示した配線が作者の既定値に勝つ(要件 B14 ②。以前は own key が勝ち、\n // ホストの値が届かなかった)\n const mappedKeys = new Set<string>();\n for (const entry of entries) {\n if (entry.innerSegments.length > 0) mappedKeys.add(entry.innerSegments[0]);\n }\n const privateSnapshot: Record<string, unknown> = {};\n for (const key of Object.keys(stateObject)) {\n if (key.startsWith(\"$\")) continue;\n if (getterKeys.has(key) || setterKeys.has(key)) continue;\n if (typeof stateObject[key] === \"function\") continue;\n if (injectedKeys.has(key)) continue;\n if (mappedKeys.has(key)) continue;\n privateSnapshot[key] = stateObject[key];\n }\n return {\n id,\n marker,\n component,\n stateProp,\n parentStateElement,\n entries,\n rootEntry,\n delta: rootEntry === null ? 0 : rootEntry.outerPathInfo.wildcardCount,\n markerBasePath: rootEntry === null ? marker : rootEntry.outerPathInfo.path + DELIMITER + marker,\n stateObject,\n getterKeys,\n setterKeys,\n injectedKeys,\n mappedKeys,\n privateSnapshot,\n accessorBySuffixByMarkerParent: new Map(),\n indexShiftByLoopElementPath: new Map(),\n addedGetterPaths: new Set(),\n exports: new Map(),\n };\n}\n\nfunction firstSegmentOf(path: string): string {\n const dot = path.indexOf(DELIMITER);\n return dot === -1 ? path : path.slice(0, dot);\n}\n\n/** 規則 3 の一致: 最長接頭辞のエントリ(entries は長い順)。一致しなければ null。 */\nfunction findTreeEntry(record: IMountRecord, segments: readonly string[]): IMountEntry | null {\n return findMountEntry(record.entries, segments);\n}\n\n/** 規則 3: 最長接頭辞一致でツリーの絶対パスへ翻訳する。一致しなければ null。 */\nfunction translateTreePath(record: IMountRecord, segments: readonly string[]): string | null {\n const entry = findMountEntry(record.entries, segments);\n return entry === null ? null : translateByMountEntry(entry, segments);\n}\n\n/** 私有アンカー: パス全体をマーカーの下に置く(`users.*.#m.editing` / `users.*.#m.drafts.*.title`) */\nfunction markerizePrivate(record: IMountRecord, innerPath: string): string {\n return record.markerBasePath + DELIMITER + innerPath;\n}\n\n/**\n * アクセサの逆引き(マーカー親 → 接尾キー → 作者のアクセサ名と $n シフト)を登録する。\n * suffix は常に非空(ワイルドカード終端アクセサは markerizeAccessorPath が raise 済み —\n * 空を許すと trailing dot の不正パスが getterPaths に載る)。\n */\nfunction recordAccessorSuffix(record: IMountRecord, markerParentPath: string, suffix: string, accessorName: string): void {\n let bySuffix = record.accessorBySuffixByMarkerParent.get(markerParentPath);\n if (typeof bySuffix === \"undefined\") {\n bySuffix = new Map();\n record.accessorBySuffixByMarkerParent.set(markerParentPath, bySuffix);\n }\n const translatedPath = markerParentPath + DELIMITER + suffix;\n bySuffix.set(suffix, {\n accessorName,\n indexShift: getPathInfo(translatedPath).wildcardCount - getPathInfo(accessorName).wildcardCount,\n });\n if (record.getterKeys.has(accessorName)) {\n // マーカーパスを親の getterPaths に載せる。checkDependency(評価中の読み →\n // このアクセサの動的エッジ登録)と isCacheable(getter 値のキャッシュ)が\n // getterPaths を正本にしているため、載せないと再評価もキャッシュも効かない。\n // モック互換のため optional に扱う。追加分は記録の恒久破棄時に回収する\n // ため addedGetterPaths にも控える(cleanupCollectedMountRecord)。\n // suffix 空を素朴に結合すると trailing dot の不正パスになる — translatedPath を使う\n (record.parentStateElement.getterPaths as Set<string> | undefined)?.add(translatedPath);\n record.addedGetterPaths.add(translatedPath);\n }\n}\n\n/**\n * ワイルドカードを含む getter / setter のマーカー位置決め。ワイルドカード接頭辞が\n * ツリーに翻訳できるなら、その直後にマーカーを挟む(ループ文脈と listIndex の arity を\n * 素の wildcard getter と同一に保つ)。先頭セグメントが私有ならパスごと私有アンカー。\n */\nfunction markerizeAccessorPath(record: IMountRecord, innerPath: string): string {\n const segments = innerPath.split(DELIMITER);\n let lastWildcard = -1;\n for (let i = segments.length - 1; i >= 0; i--) {\n if (segments[i] === WILDCARD) {\n lastWildcard = i;\n break;\n }\n }\n if (lastWildcard === -1) {\n recordAccessorSuffix(record, record.markerBasePath, innerPath, innerPath);\n return markerizePrivate(record, innerPath);\n }\n const first = segments[0];\n if (isPrivateAnchor(record, first)) {\n recordAccessorSuffix(record, record.markerBasePath, innerPath, innerPath);\n return markerizePrivate(record, innerPath);\n }\n const treeSegments = segments.slice(0, lastWildcard + 1);\n const rest = segments.slice(lastWildcard + 1);\n const translated = translateTreePath(record, treeSegments);\n if (translated === null) {\n // 部分マウントのみで、どの接頭辞にも含まれないツリー部(§4-1 の 4b)\n raiseError(noMountEntryMessage(record, innerPath));\n }\n if (rest.length === 0) {\n // ワイルドカード終端アクセサ(行 getter `get \"tags.*\"()`)がツリーのリストへ翻訳される形:\n // 翻訳結果がマーカー終端パス(`users.*.tags.*.#m`)になり、getByAddress のオーバーレイ\n // dispatch が getter 評価より先に掛かってオーバーレイ proxy が値として返る\n // (作者の getter は評価されない)。無言で壊れる形なのでサポート外として loud に落とす\n raiseError(\n `Wildcard-terminal accessor \"${innerPath}\" on mounted <${record.component.tagName.toLowerCase()}> ` +\n `is not supported: it translates to a marker-terminal path where the mount overlay would shadow ` +\n `the accessor. Declare the row value as a getter on the host tree, or back it with a ` +\n `component-own array (a private key makes the whole path private).`,\n );\n }\n const markerParent = translated + DELIMITER + record.marker;\n recordAccessorSuffix(record, markerParent, rest.join(DELIMITER), innerPath);\n return markerParent + DELIMITER + rest.join(DELIMITER);\n}\n\n/** 先頭セグメントが「作者のもの」(own data key・メソッド。積みで注入されたキーは除く)か */\nfunction isPrivateAnchor(record: IMountRecord, firstSegment: string): boolean {\n if (record.injectedKeys.has(firstSegment) || record.mappedKeys.has(firstSegment)) {\n return false;\n }\n if (typeof record.stateObject[firstSegment] === \"function\" && !record.getterKeys.has(firstSegment)) {\n return true;\n }\n return Object.prototype.hasOwnProperty.call(record.stateObject, firstSegment)\n && !record.getterKeys.has(firstSegment)\n && !record.setterKeys.has(firstSegment);\n}\n\nfunction noMountEntryMessage(record: IMountRecord, innerPath: string): string {\n return `Path \"${innerPath}\" in <${record.component.tagName.toLowerCase()}> does not resolve: ` +\n `it is not an own key of the component state and no mount entry covers it ` +\n `(mounted prefixes: ${record.entries.filter(e => e.innerSegments.length > 0).map(e => e.innerSegments.join(DELIMITER)).join(\", \")}). ` +\n `Mount it from the host (\"${record.stateProp}: path\" / \"${record.stateProp}.${firstSegmentOf(innerPath)}: path\") or declare the key on the component state.`;\n}\n\n/**\n * コンポーネントスコープの内側パスを、親ツリーの絶対パスへ翻訳する(設計書 §4-1)。\n *\n * 1. getter / setter(完全一致・またはワイルドカード getter)→ マーカーパス(chroot 評価)\n * 2. own data key(部分規則が覆わないもの)・メソッド → マーカーパス(私有)\n * 3. それ以外 → 最長接頭辞一致でツリーへ\n * 4. 一致なし: ルートエントリがあれば必ず 3 で一致する。無ければ throw(4b)\n *\n * `$`(予約名前空間・`$1` 等)と `#`(構造プレースホルダ)で始まるパスは翻訳しない。\n */\nconst INDEX_PATH_REGEX = /^\\$(\\d+)$/;\n\n/**\n * `$n` バインディングのスコープ補正量(D9・設計書 §4-4)。\n * 囲む `for` の内側なら「その for パスが翻訳で得たワイルドカード数」— 行マウント\n * (`state: .`)の `for: tags` は `users.*.tags` になり +1、部分マウント\n * `state.items: groups.*.children` の `for: items` も +1。for の外(スコープ直下)は\n * ルート接頭辞の Δ。翻訳がワイルドカードを増やさないマウント(`state: user`)は 0。\n */\nexport function getIndexShiftForScope(record: IMountRecord, forPath: string | undefined): number {\n if (typeof forPath === \"undefined\") {\n return record.delta;\n }\n const translated = translateInnerPath(record, forPath);\n return getPathInfo(translated).wildcardCount - getPathInfo(forPath).wildcardCount;\n}\n\n/**\n * `innerPath` がツリーへ翻訳され、その先のエントリが読み取り専用(`#ro`)か(要件 B14 ①)。\n * 私有キー・アクセサ・`$` / `#` で始まるパスはコンポーネント自身のものなので対象外。\n */\nfunction isReadonlyTreePath(record: IMountRecord, innerPath: string): IMountEntry | null {\n const head = innerPath[0];\n if (head === \"$\" || head === \"#\") return null;\n if (record.getterKeys.has(innerPath) || record.setterKeys.has(innerPath)) return null;\n const first = firstSegmentOf(innerPath);\n if (record.getterKeys.has(first) || record.setterKeys.has(first) || isPrivateAnchor(record, first)) return null;\n const entry = findTreeEntry(record, innerPath.split(DELIMITER));\n return entry !== null && entry.readonly ? entry : null;\n}\n\n/**\n * 書き込みの翻訳(要件 B14 ①)。`translateInnerPath` と同じ行き先を返すが、読み取り専用で\n * マウントされたエントリ(`state#ro: user`)を通るツリーへの書き込みは名指しで拒否する。\n * コンポーネント側の書き込みの入口(`element.state`・オーバーレイ・`$setAll` / `$resolve`)が呼ぶ。\n */\nexport function translateInnerWritePath(record: IMountRecord, innerPath: string): string {\n const readonlyEntry = isReadonlyTreePath(record, innerPath);\n if (readonlyEntry !== null) {\n const suffix = readonlyEntry.innerSegments.length === 0 ? \"\" : DELIMITER + readonlyEntry.innerSegments.join(DELIMITER);\n raiseError(\n `[wcs/mount-readonly] <${record.component.tagName.toLowerCase()}> cannot write \"${innerPath}\": ` +\n `it is mounted read-only (\"${record.stateProp}${suffix}#${MODIFIER_READONLY}: ${readonlyEntry.outerPathInfo.path}\"). ` +\n `Write it on the host, or drop #${MODIFIER_READONLY} from the mount.`,\n );\n }\n return translateInnerPath(record, innerPath);\n}\n\nexport function translateInnerPath(record: IMountRecord, innerPath: string): string {\n const head = innerPath[0];\n if (head === \"$\" || head === \"#\") {\n // `$` の予約名前空間はパスとしては翻訳しない(`$n` のスコープ補正は\n // translateParsedForMount が囲む for の文脈で行う。getter 内の `this.$1` は\n // 親トラップがアクセサの indexShift で補正する)\n return innerPath;\n }\n // 規則 1: 完全一致の getter / setter(`display`・`\"children.*.label\"`)\n if (record.getterKeys.has(innerPath) || record.setterKeys.has(innerPath)) {\n return markerizeAccessorPath(record, innerPath);\n }\n const first = firstSegmentOf(innerPath);\n // 規則 1'/2: 先頭セグメントが getter / setter / メソッド / own data key → マーカー配下\n if (record.getterKeys.has(first) || record.setterKeys.has(first)) {\n return markerizePrivate(record, innerPath);\n }\n if (isPrivateAnchor(record, first)) {\n return markerizePrivate(record, innerPath);\n }\n // 規則 3: ツリー\n const translated = translateTreePath(record, innerPath.split(DELIMITER));\n if (translated !== null) {\n return translated;\n }\n // 規則 4b: 部分マウントのみで一致なし\n raiseError(noMountEntryMessage(record, innerPath));\n}\n\ninterface ITranslatable {\n readonly statePathName: string;\n readonly statePathInfo: IPathInfo;\n}\n\n/**\n * パース結果 / バインディングをマウント先の形へ変換した複製を返す\n * (パース結果キャッシュは触らない)。解決サイト(applyChangeFromBindings /\n * getAbsoluteStateAddressByBinding / fragmentInfoByUUID)は rootNode で\n * state element を引く — スコープ根は台帳エイリアスで親ツリーに到達する。\n */\nexport function translateParsedForMount<T extends ITranslatable>(record: IMountRecord, parsed: T, forPath?: string): T {\n let translated: string;\n const indexMatch = INDEX_PATH_REGEX.exec(parsed.statePathName);\n if (indexMatch !== null) {\n // `$n` はスコープ相対(D9・§4-4): 囲む for の翻訳で増えたワイルドカード数だけ繰り上げる\n const shift = getIndexShiftForScope(record, forPath);\n translated = shift === 0 ? parsed.statePathName : `$${Number(indexMatch[1]) + shift}`;\n } else {\n translated = translateInnerPath(record, parsed.statePathName);\n if ((parsed as { bindingType?: string }).bindingType === \"for\") {\n // スコープ相対の添字(P2-9)用: この for の行に立つループ文脈の要素パスと、\n // 翻訳で増えたワイルドカード数を控える。shift 0(Δ=0 の丸ごとマウント\n // `state: user` や同名翻訳の部分マウント)でも必ず載せる —\n // event/handler.ts は台帳に無いループ文脈を「外側スコープの借用行=\n // 添字 0 本」と解釈するため、登録漏れは自スコープの for の添字を\n // 丸ごと落とす(§4-4 違反)\n const shift = getPathInfo(translated).wildcardCount - parsed.statePathInfo.wildcardCount;\n record.indexShiftByLoopElementPath.set(translated + DELIMITER + WILDCARD, shift);\n }\n }\n // 読み取り専用のマウント(要件 B14 ①)を通る束縛は、要素 → state の書き戻しを止める(`#ro` と同じ)\n const modifiers = (parsed as { propModifiers?: readonly string[] }).propModifiers;\n const forceReadonly = indexMatch === null && Array.isArray(modifiers)\n && !modifiers.includes(MODIFIER_READONLY)\n && isReadonlyTreePath(record, parsed.statePathName) !== null;\n if (translated === parsed.statePathName && !forceReadonly) {\n return parsed;\n }\n return {\n ...parsed,\n statePathName: translated,\n statePathInfo: getPathInfo(translated),\n ...(forceReadonly ? { propModifiers: [...modifiers!, MODIFIER_READONLY] } : {}),\n };\n}\n\nexport function translateBindingForMount(record: IMountRecord, binding: IBindingInfo, forPath?: string): IBindingInfo {\n return translateParsedForMount(record, binding, forPath);\n}\n\n/**\n * マーカーパスのアクセサ評価中の `$n` シフト(トラップの補正が引く)。\n * アクセサとして登録されたパスならその indexShift、そうでなければルートの Δ。\n */\nexport function getIndexShiftForMarkerPath(record: IMountRecord, markerPath: string): number {\n // 末尾マーカーをセグメント単位で正確に切り出す(getMountRecordByPath と同じ規則)。\n // indexOf(record.marker) の前方一致だと `#m2` が別記録の `#m21` の中に誤ヒットし、\n // 親パスをセグメント途中で切って登録簿の照会を外す(Δ への誤フォールバック)\n const hashIndex = markerPath.lastIndexOf(\"#\");\n if (hashIndex === -1) {\n return record.delta;\n }\n const end = markerPath.indexOf(DELIMITER, hashIndex);\n const marker = end === -1 ? markerPath.slice(hashIndex) : markerPath.slice(hashIndex, end);\n if (marker !== record.marker) {\n return record.delta;\n }\n const parent = end === -1 ? markerPath : markerPath.slice(0, end);\n const suffix = end === -1 ? \"\" : markerPath.slice(end + 1);\n const entry = record.accessorBySuffixByMarkerParent.get(parent)?.get(suffix);\n return typeof entry !== \"undefined\" ? entry.indexShift : record.delta;\n}\n\n/**\n * `$getAll` / `$setAll` / `$resolve` の接頭辞翻訳(§4-6 / P2-9): 作者のスコープ相対\n * indexes の先頭に、翻訳で増えたワイルドカード分の文脈添字を合成する。\n * contextIndexes はホスト要素(chroot)またはマーカーアドレス(オーバーレイ)の\n * listIndex 添字列。プレフィックスが増えないパス(Δ=0 の翻訳)は素通し。\n */\nexport function composeMountIndexes(\n record: IMountRecord,\n innerPath: string,\n translatedPath: string,\n indexes: readonly number[] | undefined,\n contextIndexes: readonly number[],\n): readonly number[] | undefined {\n if (typeof indexes === \"undefined\") {\n return undefined;\n }\n const prefixWildcards = getPathInfo(translatedPath).wildcardCount - getPathInfo(innerPath).wildcardCount;\n if (prefixWildcards === 0) {\n return indexes;\n }\n if (contextIndexes.length < prefixWildcards) {\n raiseError(\n `Cannot resolve \"${innerPath}\" from this mount: the mounted prefix has ${prefixWildcards} wildcard(s) ` +\n `but the host context provides only ${contextIndexes.length} index(es).`,\n );\n }\n return [...contextIndexes.slice(0, prefixWildcards), ...indexes];\n}\n\n// ---------------------------------------------------------------------------\n// 登録簿\n// ---------------------------------------------------------------------------\n\n/**\n * スコープ根 → マウント記録。キーは Shadow DOM 形ならコンポーネントの shadowRoot、\n * Light DOM 形ならコンポーネント要素自身(そのサブツリーがスコープ)。\n */\nconst mountRecordByScopeRoot = new WeakMap<Node, IMountRecord>();\n\n/**\n * コンポーネント要素 → stateProp → マウント記録。\n * connectedCallback で shadow の innerHTML を張り直す作りのコンポーネントでは、\n * 再接続のたびに新しい <wcs-state> が同じ shadowRoot に入り、スコープが再初期化される。\n * 記録を要素単位で再利用することでマーカーが安定し、親側の登録簿\n * (byMarker・getterPaths)が再接続のたびに増えない。stateObject はクラスフィールド\n * なので要素と同寿命 — 記録の前提(作者のオブジェクトの同一性)が保たれる。\n */\nconst mountRecordByComponent = new WeakMap<Element, Map<string, IMountRecord>>();\n\n/** 再初期化用: この要素の stateProp に対して登録済みの記録を引く。 */\nexport function getRegisteredMountRecord(component: Element, stateProp: string): IMountRecord | null {\n return mountRecordByComponent.get(component)?.get(stateProp) ?? null;\n}\n\n/**\n * 親 state element → マーカー → マウント記録(オーバーレイ dispatch と Δ 補正が引く)。\n *\n * 値は **WeakRef**(B6)。記録への強参照は要素キーの WeakMap\n * (mountRecordByComponent / mountRecordByScopeRoot)だけが持つので、記録は\n * コンポーネント要素と同寿命になる — プール返却では要素が生きているので記録も生き、\n * 恒久破棄(route swap / `if` で捨てた形)では要素ごと回収可能になる。\n * ここを強参照にすると、長寿命の親 state 要素に破棄済み要素(と Shadow サブツリー)が\n * 際限なく蓄積する。\n */\nconst mountRecordsByStateElement = new WeakMap<IStateElement, Map<string, WeakRef<IMountRecord>>>();\n\n/** FinalizationRegistry の held 値: 記録が回収された後に台帳から掃除するもの。 */\nexport interface ICollectedMountLedgers {\n readonly byMarker: Map<string, WeakRef<IMountRecord>>;\n readonly marker: string;\n readonly getterPaths: Set<string> | undefined;\n readonly addedGetterPaths: ReadonlySet<string>;\n}\n\n/**\n * 恒久破棄されたマウント記録の台帳掃除(FinalizationRegistry のコールバック本体)。\n * マーカーは記録ごとに一意(`#m<id>` 単調増加)なので、発火時点でこのマーカーの\n * エントリは死んだ WeakRef のはず — 生きていれば触らない(防御)。\n * エクスポートしているのは GC を強制できないテスト環境で直接検証するため。\n */\nexport function cleanupCollectedMountRecord(held: ICollectedMountLedgers): void {\n const ref = held.byMarker.get(held.marker);\n if (typeof ref !== \"undefined\" && typeof ref.deref() === \"undefined\") {\n held.byMarker.delete(held.marker);\n }\n if (typeof held.getterPaths !== \"undefined\") {\n for (const path of held.addedGetterPaths) {\n held.getterPaths.delete(path);\n }\n }\n}\n\nconst collectedMountRegistry = new FinalizationRegistry<ICollectedMountLedgers>(cleanupCollectedMountRecord);\n\n/** マウント記録 → スコープ根。行 content をその場で使い回したときの張り直しが引く(#4) */\nconst scopeRootByMountRecord: WeakMap<IMountRecord, Node> = new WeakMap();\n\nexport function getScopeRootByMountRecord(record: IMountRecord): Node | null {\n return scopeRootByMountRecord.get(record) ?? null;\n}\n\n// ループ文脈の探索がマウントされた ShadowRoot でホストへ抜ける受け口(list/loopContextByNode.ts)。\n// 最初の記録の登録で 1 回だけ注入する(マウントの無いページでは探索は境界で止まったまま)\nlet scopeHostInstalled = false;\nfunction installMountedScopeHost(): void {\n if (scopeHostInstalled) return;\n scopeHostInstalled = true;\n setMountedScopeHost((root) => mountRecordByScopeRoot.has(root) ? root.host : null);\n}\n\nexport function registerMountRecord(scopeRoot: Node, record: IMountRecord): void {\n installMountedScopeHost();\n mountRecordByScopeRoot.set(scopeRoot, record);\n scopeRootByMountRecord.set(record, scopeRoot);\n let byMarker = mountRecordsByStateElement.get(record.parentStateElement);\n if (typeof byMarker === \"undefined\") {\n byMarker = new Map();\n mountRecordsByStateElement.set(record.parentStateElement, byMarker);\n }\n byMarker.set(record.marker, new WeakRef(record));\n let byProp = mountRecordByComponent.get(record.component);\n if (typeof byProp === 'undefined') {\n byProp = new Map();\n mountRecordByComponent.set(record.component, byProp);\n }\n const isFirstRegistration = byProp.get(record.stateProp) !== record;\n byProp.set(record.stateProp, record);\n if (isFirstRegistration) {\n // 恒久破棄で台帳(byMarker・親 getterPaths への追加分)を回収する(B6)。\n // 再初期化(同一 record の再登録 — マーカー安定のための再利用)では二重登録しない\n collectedMountRegistry.register(record, {\n byMarker,\n marker: record.marker,\n getterPaths: record.parentStateElement.getterPaths as Set<string> | undefined,\n addedGetterPaths: record.addedGetterPaths,\n });\n }\n // D18: マウントの無い state はオーバーレイ dispatch を boolean 1 個で抜ける\n record.parentStateElement.markHasMounts?.();\n}\n\nexport function getMountRecordByScopeRoot(scopeRoot: Node): IMountRecord | null {\n return mountRecordByScopeRoot.get(scopeRoot) ?? null;\n}\n\n/**\n * ノードから最も近いマウントスコープ根の記録を引く(event/handler.ts のスコープ相対\n * 添字が使う)。Light DOM 形はスコープ根=**コンポーネント要素自身**(D7・\n * mountScope.ts)で rootNode の内側に入れ子になりうる(Shadow 形のスコープの中の\n * Light DOM マウント)ため、**祖先を先に**辿って最初のスコープ根を探す — rootNode\n * 直ヒットを先に返すと外側の記録を取り違える。祖先に無ければ rootNode 自身\n * (Shadow DOM 形のスコープ根=shadowRoot)で引く。入れ子マウントでは\n * 最も内側(=そのノードのバインディングを翻訳した記録)が返る。\n * `hasMounts` が真のときだけ呼ぶこと(無マウントの経路にこの走査を載せない — D18)。\n */\nexport function findMountRecordForNode(node: Node, rootNode: Node): IMountRecord | null {\n let current: Node | null = node;\n while (current !== null && current !== rootNode) {\n const record = mountRecordByScopeRoot.get(current);\n if (typeof record !== \"undefined\") {\n return record;\n }\n current = current.parentNode;\n }\n return mountRecordByScopeRoot.get(rootNode) ?? null;\n}\n\n/** この state element に登録済みのマウント記録を列挙する(devtools の overlays が読む)。 */\nexport function getMountRecordsForStateElement(stateElement: IStateElement): IMountRecord[] {\n const byMarker = mountRecordsByStateElement.get(stateElement);\n if (typeof byMarker === \"undefined\") {\n return [];\n }\n const records: IMountRecord[] = [];\n for (const ref of byMarker.values()) {\n const record = ref.deref();\n if (typeof record !== \"undefined\") {\n records.push(record);\n }\n }\n return records;\n}\n\n/** 親 state element がマウントを 1 つでも持つか(D18: 無ければ dispatch は分岐 1 つで抜ける) */\nexport function stateElementHasMounts(stateElement: IStateElement): boolean {\n const byMarker = mountRecordsByStateElement.get(stateElement);\n return typeof byMarker !== \"undefined\" && byMarker.size > 0;\n}\n\n/**\n * パスに含まれるマーカーからマウント記録を引く。`hasMounts` が真のときだけ呼ぶこと。\n * `#` を含まないパス(圧倒的多数)は lastIndexOf 1 回で抜ける。\n * 入れ子マウント(外側の私有キーの上に内側マウントが載る形)ではパスに複数の\n * マーカーが並ぶ(`users.*.#m1.drafts.#m2`)— オーバーレイ dispatch と $n 補正が\n * 要るのは**末尾**のマーカーの記録なので、先頭でなく最後の `#` で切る\n * (先頭で切ると外側の記録が返り誤翻訳する)。\n */\nexport function getMountRecordByPath(stateElement: IStateElement, path: string): IMountRecord | null {\n const hashIndex = path.lastIndexOf(\"#\");\n if (hashIndex === -1) {\n return null;\n }\n const byMarker = mountRecordsByStateElement.get(stateElement);\n if (typeof byMarker === \"undefined\") {\n return null;\n }\n const end = path.indexOf(DELIMITER, hashIndex);\n const marker = end === -1 ? path.slice(hashIndex) : path.slice(hashIndex, end);\n const ref = byMarker.get(marker);\n if (typeof ref === \"undefined\") {\n return null;\n }\n const record = ref.deref();\n if (typeof record === \"undefined\") {\n // 記録は回収済み(finalizer 発火前の窓)— 遅延 prune\n byMarker.delete(marker);\n return null;\n }\n return record;\n}\n\n/** テスト用: マーカー台帳の WeakRef を差し替える(GC を強制できない環境で死んだ参照を再現する)。 */\nexport function _setMountRecordRefForTesting(\n stateElement: IStateElement,\n marker: string,\n ref: WeakRef<IMountRecord>,\n): void {\n mountRecordsByStateElement.get(stateElement)?.set(marker, ref);\n}\n"],"names":["startsWithSegments","segments","prefix","length","i","findMountEntry","entries","entry","innerSegments","translateByMountEntry","rest","slice","outerPathInfo","path","DELIMITER","join","nextMountId","MOUNT_DOLLAR_DECLARATIONS","dollarDeclarationWarned","Set","warnMountedDollarDeclarations","record","declared","filter","name","stateObject","accessor","getterKeys","indexOf","RECURSION_WILDCARD","push","key","component","tagName","toLowerCase","stateProp","has","add","console","warn","split","callMountLifecycleCallback","callback","chroot","result","call","Promise","catch","error","buildMountRecord","bindings","parentStateElement","injectedKeys","raiseError","seenInnerPaths","rootEntry","binding","propSegments","innerPath","statePathInfo","readonly","propModifiers","includes","MODIFIER_READONLY","sort","a","b","id","marker","setterKeys","descriptors","Object","getOwnPropertyDescriptors","descriptor","get","set","collectAccessorKeys","mappedKeys","privateSnapshot","keys","startsWith","delta","wildcardCount","markerBasePath","accessorBySuffixByMarkerParent","Map","indexShiftByLoopElementPath","addedGetterPaths","exports","firstSegmentOf","dot","translateTreePath","markerizePrivate","recordAccessorSuffix","markerParentPath","suffix","accessorName","bySuffix","translatedPath","indexShift","getPathInfo","getterPaths","isPrivateAnchor","firstSegment","prototype","hasOwnProperty","noMountEntryMessage","e","map","INDEX_PATH_REGEX","isReadonlyTreePath","head","first","findTreeEntry","translateInnerWritePath","readonlyEntry","translateInnerPath","lastWildcard","WILDCARD","treeSegments","translated","markerParent","markerizeAccessorPath","translateParsedForMount","parsed","forPath","indexMatch","exec","statePathName","shift","getIndexShiftForScope","Number","bindingType","modifiers","forceReadonly","Array","isArray","getIndexShiftForMarkerPath","markerPath","hashIndex","lastIndexOf","end","parent","composeMountIndexes","indexes","contextIndexes","prefixWildcards","mountRecordByScopeRoot","WeakMap","mountRecordByComponent","getRegisteredMountRecord","mountRecordsByStateElement","collectedMountRegistry","FinalizationRegistry","held","ref","byMarker","deref","delete","scopeRootByMountRecord","getScopeRootByMountRecord","scopeHostInstalled","registerMountRecord","scopeRoot","setMountedScopeHost","root","host","WeakRef","byProp","isFirstRegistration","register","markHasMounts","getMountRecordByScopeRoot","findMountRecordForNode","node","rootNode","current","parentNode","getMountRecordsForStateElement","stateElement","records","values","stateElementHasMounts","size","getMountRecordByPath"],"mappings":"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"}
|
|
@@ -0,0 +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};
|
|
2
|
+
//# sourceMappingURL=pathDiagnostics.js.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{i as t,c as e,a as s}from"./filterRegistry.js";import{l as n,a,b as i,c as o,d as r,e as l,f as d,g as h,h as c,i as u}from"./lifecycleHooks.js";import{r as p,d as f}from"./errorGuidance.js";import{d as _,k as m,l as g,af as y,c as b,x as k,I as S,ag as w,H as P,ah as v,ai as $,aj as C,ak as x,al as I,am as A,an as N,ao as E,ap as z,G as D,j as L,y as R,o as j,aq as H,ar as O,as as T,at as G,au as M,g as F,av as U,aw as W,ax as V,ay as q}from"./binder.js";import{u as K,v as B,w as J,b as Q,x as X,m as Y,D as Z,W as tt,R as et,y as st,z as nt,o as at,A as it,I as ot,B as rt,M as lt,c as dt,d as ht,g as ct,N as ut,i as pt,l as ft,C as _t,f as mt}from"./pathDiagnostics.js";import{d as gt,e as yt,w as bt,f as kt,r as St,c as wt,b as Pt,g as vt,s as $t,h as Ct,a as xt,i as It}from"./setAll.js";import{N as At,g as Nt,b as Et,c as zt,d as Dt,e as Lt,f as Rt,h as jt,i as Ht,j as Ot,k as Tt,l as Gt,m as Mt,n as Ft}from"./getAllPropertyDescriptors.js";import{p as Ut}from"./diagnosticsHooks.js";class Wt{_loopContextStack=Array(K).fill(void 0);_length=0;createLoopContext(t,e){null===t.listIndex&&p("Cannot create loop context for a state address that does not have a list index.");const s=t;this._length>=K&&p(`Exceeded maximum loop context stack depth of ${K}. Possible infinite loop.`);const n=this._loopContextStack[this._length-1];if(void 0!==n){n.pathInfo.wildcardCount+1!==s.pathInfo.wildcardCount&&p("Cannot push loop context for a list whose wildcard count is not exactly one more than the current active loop context.");const t=s.pathInfo.wildcardPathInfos[s.pathInfo.wildcardPathInfos.length-2];n.pathInfo!==t&&p("Cannot push loop context for a list whose parent wildcard path info does not match the current active loop context.")}else s.listIndex.length!==s.pathInfo.wildcardCount&&p(`Cannot push loop context when there is no active loop context: the list index chain (length ${s.listIndex.length}) does not cover the wildcard path (wildcard count ${s.pathInfo.wildcardCount}).`);let a;this._loopContextStack[this._length]=s,this._length++;try{a=e(s)}finally{a instanceof Promise?a.finally(()=>{this._length--,this._loopContextStack[this._length]=void 0}):(this._length--,this._loopContextStack[this._length]=void 0)}return a}}function Vt(t,e){const s=t.getterPaths;if(0===s.size)return!1;for(const t of ct(e).cumulativePaths)if(s.has(t))return!0;return!1}const qt=/^\$\d+$/,Kt=`${dt}${Z}`,Bt=`${ht}${Z}`,Jt=new WeakMap;function Qt(t,e,s,n){const a=ot[e];if(void 0===a&&"string"==typeof e&&36===e.charCodeAt(0)&&qt.test(e)&&p(`[wcs/index-param-range] "${e}" is not a valid list index parameter: they run from ${rt}1 to ${rt}${lt}, with no leading zeros.`),void 0!==a){0===n.addressStackLength&&p(`No active state reference to get list index for "${e.toString()}".`);const t=n.lastAddressStack,s=t?.pathInfo;s&&!n.untracking&&n.stateElement?.getterPaths.has(s.path)&&n.stateElement.addIndexDependentGetterPath?.(s.path);const i=t?.listIndex;null==i&&p(`ListIndex not found: ${e.toString()}`);let o=a;const r=t.pathInfo,l=n.stateElement?.addressHooks;if(l){const e=l.indexShift;for(let s=0;s<e.length;s++)o+=e[s](n,t)}const d=S(i,o,r.wildcardCount);return d?.index??p(`ListIndex not found: ${e.toString()}`)}if("string"==typeof e){const a=n.stateElement?.addressHooks;if(a){const i=a.get;for(let a=0;a<i.length;a++){const o=i[a](n,e,s,t);if(o!==At)return o}}if("$"===e[0]){switch(e){case"$stateElement":return n.stateElement;case"$getAll":return(a,i)=>Pt(t,e,s,n)(a,i);case"$setAll":return(a,i,o,r)=>wt(t,e,s,n)(a,i,o,r);case"$postUpdate":return e=>function(t,e,s,n){const a=n.stateElement;return e=>{const i=gt(e),o=yt(t,i,s,n),r=m(i.pathInfo,o),l=g(a,r),d=b();d.enqueueAbsoluteAddress(l),bt(n.stateElement,r,n.stateElement.staticDependency,n.stateElement.dynamicDependency,n.stateElement.listPaths,s,"new",t=>{const e=g(a,t);y(e),d.enqueueAbsoluteAddress(e)});const h=a.addressHooks;if(h){const t=h.written;for(let e=0;e<t.length;e++)t[e](a,r.pathInfo)}}}(t,0,s,n)(e);case"$resolve":return(a,i,...o)=>St(t,e,s,n)(a,i,...o);case"$trackDependency":return t=>function(t,e,s,n){return t=>{-1!==t.indexOf(et)&&p(`[wcs/recursion-unsupported] $trackDependency("${t}") cannot take "**" — a dependency is registered against a concrete path (a fixed number of "*"). Track the concrete depth, or read the path through this[...] / $getAll inside the getter so the dependency is recorded automatically.`),0===n.addressStackLength&&p(`No active state reference to track dependency for path "${t}".`);const e=n.lastAddressStack?.pathInfo??p("Internal error: lastAddressStack is null"),s=n.stateElement;n.stateElement.getterPaths.has(e.path)&&e.path!==t&&s.addDynamicDependency(t,e.path)}}(0,0,0,n)(t);case"$eq":return(t,e)=>{const a=n.addressStackLength>0?n.lastAddressStack:null;if(Vt(n.stateElement,t))return null!==a&&n.stateElement.getterPaths.has(a.pathInfo.path)&&w(n.stateElement,t),Object.is(s[t],e);let i;n.beginUntrack();try{i=s[t]}finally{n.endUntrack()}return null!==a&&n.stateElement.getterPaths.has(a.pathInfo.path)&&C(n.stateElement,t,e,g(n.stateElement,a),i),Object.is(i,e)};case"$eqPath":return(t,e)=>{const a=n.addressStackLength>0?n.lastAddressStack:null,i=Vt(n.stateElement,t);let o,r=i?s[t]:void 0;n.beginUntrack();try{i||(r=s[t]),o=s[e]}finally{n.endUntrack()}return null!==a&&n.stateElement.getterPaths.has(a.pathInfo.path)&&(i?w(n.stateElement,t):C(n.stateElement,t,o,g(n.stateElement,a),r)),Object.is(r,o)};case"$eqIndex":return(t,e=1)=>{const a=n.addressStackLength>0?n.lastAddressStack:null;null!==a&&null!==a.listIndex||p(`$eqIndex("${t}") needs a list row scope.`);const i=S(a.listIndex,e-1,a.pathInfo.wildcardCount);if(null===i&&p(`$eqIndex("${t}", ${e}): no list index at that level.`),Vt(n.stateElement,t))return n.stateElement.getterPaths.has(a.pathInfo.path)&&w(n.stateElement,t),Object.is(s[t],i.index);const o=e===a.pathInfo.wildcardCount;let r,l;n.beginUntrack();try{r=s[t],o&&(l=s[a.pathInfo.wildcardParentPaths[e-1]])}finally{n.endUntrack()}if(n.stateElement.getterPaths.has(a.pathInfo.path)){const e=o?P(l):null;null!==e?v(n.stateElement,t,a.pathInfo,e,r):$(n.stateElement,t,i,g(n.stateElement,a),r)}return Object.is(r,i.index)};case"$untrackDependency":return t=>function(t,e,s,n){return t=>{n.beginUntrack();try{return t()}finally{n.endUntrack()}}}(0,0,0,n)(t);case J:return kt(n.stateElement)}if(!e.startsWith(Kt)&&!e.startsWith(Bt))return}const i=gt(e),o=yt(t,i,s,n),r=m(i.pathInfo,o);return vt(t,r,s,n)}if("symbol"==typeof e){const a=function(t){let e=Jt.get(t);return void 0===e&&(e=new Map,Jt.set(t,e)),e}(n),i=a.get(e);if(void 0!==i)return i;let o;switch(e){case L:o=(t,e=()=>{})=>function(t,e,s){void 0!==t.loopContext&&p("already in loop context"),t.setLoopContext(e);try{t.pushAddress(e);try{return s()}finally{t.popAddress()}}finally{t.clearLoopContext()}}(n,t,e);break;case D:o=e=>vt(t,e,s,n);break;case z:o=e=>Ct(t,e,s,n);break;case E:o=(e,a)=>$t(t,e,a,s,n);break;case N:o=()=>async function(t,e,s){const n=Reflect.get(t,st);"function"==typeof n&&await n.call(s)}(t,0,s);break;case A:o=()=>function(t,e,s){const n=Reflect.get(t,nt);"function"==typeof n&&n.call(s)}(t,0,s);break;case I:o=e=>function(t,e,s,n){const a=Reflect.get(t,at);let i;if("function"==typeof a){const t=new Set,o={};for(const s of e){if(s.absolutePathInfo.stateElement!==n.stateElement)continue;const e=s.absolutePathInfo.pathInfo,a=e.path;if(-1===a.indexOf("#")&&(t.add(a),e.wildcardCount>0)){const t=k(s.listIndex,e.wildcardCount),n=o[a];void 0===n?o[a]=[t]:n.push(t)}}i=a.call(s,Array.from(t),o)}const o=n.stateElement?.addressHooks;if(o){const t=o.updated;for(let a=0;a<t.length;a++)t[a](n.stateElement,e,s)}return i}(t,e,s,n);break;case x:o=(e,n)=>function(t,e,s,n){const a=Reflect.get(t,it);"function"==typeof a&&a.call(n,e,s)}(t,e,n,s);break;default:return Reflect.get(t,e,s)}return a.set(e,o),o}}class Xt{_stateElement;_addressStack=Array(K).fill(void 0);_addressStackIndex=-1;_loopContext;_mutability;_untrackDepth=0;constructor(t,e){const s=R(t);null===s&&p("StateHandler: no state tree found on this root."),this._stateElement=s,this._mutability=e}get stateElement(){return this._stateElement}get mutability(){return this._mutability}get lastAddressStack(){let t;return this._addressStackIndex>=0&&(t=this._addressStack[this._addressStackIndex]),void 0===t&&p("Last address stack is undefined."),t}get addressStackLength(){return this._addressStackIndex+1}get loopContext(){return this._loopContext}pushAddress(t){this._addressStackIndex+1>=K&&(this._hasRepeatedAddress()&&p(`[wcs/getter-cycle] Exceeded maximum address stack depth of ${K}. Possible circular dependency between path getters: ${this._describeAddressCycle()}`),p(`[wcs/getter-depth-exceeded] Exceeded maximum address stack depth of ${K} with no address visited twice — the data is simply nested deeper than the engine evaluates in one pass. Deepest path first: ${this._describeAddressCycle()}`)),this._addressStackIndex++,this._addressStack[this._addressStackIndex]=t}_hasRepeatedAddress(){const t=new Set;for(let e=0;e<=this._addressStackIndex;e++){const s=this._addressStack[e];if(s){if(t.has(s))return!0;t.add(s)}}return!1}_tailAddressPaths(){const t=[];for(let e=this._addressStackIndex;e>=0&&t.length<8;e--){const s=this._addressStack[e];s&&t.push(s.pathInfo.path)}return t}_describeAddressCycle(){const t=this._tailAddressPaths();return`${Array.from(new Set(t)).reverse().join(" -> ")} -> ...`}popAddress(){if(this._addressStackIndex<0)return null;const t=this._addressStack[this._addressStackIndex];return void 0===t&&p(`Address stack at index ${this._addressStackIndex} is undefined.`),this._addressStack[this._addressStackIndex]=void 0,this._addressStackIndex--,t}setLoopContext(t){this._loopContext=t}clearLoopContext(){this._loopContext=void 0}get untracking(){return this._untrackDepth>0}beginUntrack(){this._untrackDepth++}endUntrack(){this._untrackDepth--}get(t,e,s){return Qt(t,e,s,this)}set(t,e,s,n){return xt(this),function(t,e,s,n,a){if("string"==typeof e){const i=gt(e),o=yt(t,i,n,a),r=m(i.pathInfo,o);return $t(t,r,s,n,a)}return Reflect.set(t,e,s,n)}(t,e,s,n,this)}has(t,e){return Reflect.has(t,e)}}const Yt="undefined"==typeof HTMLElement?class{}:HTMLElement;const Zt=new Set(["for","if","elseif","else"]);function te(e,s,n){const a=new Map;for(const t of n){const e=ct(t);if(null===e.lastWildcardPath)continue;const s=a.get(e.lastWildcardPath);void 0===s?a.set(e.lastWildcardPath,[e]):s.push(e)}const i=[],o=new Set,r=t=>{const s=g(e,t);if(o.has(s))return;o.add(s);const n=G(s);if(n instanceof Set?i.push(...n):void 0!==n&&i.push(n),null!==t.listIndex){const e=a.get(t.pathInfo.path);if(void 0!==e)for(const s of e)r(m(s,t.listIndex))}};M();try{if(e.createState("readonly",t=>{for(const n of s){const s=m(ct(n),null);r(s);try{bt(e,s,e.staticDependency,e.dynamicDependency,e.listPaths,t,"new",r)}catch{}}}),0===i.length)return;const n=function(t){const e=[],s=[];for(const n of t)Zt.has(n.bindingType)?e.push(n):s.push(n);return e.sort((t,e)=>0!==(t.replaceNode.compareDocumentPosition(e.replaceNode)&Node.DOCUMENT_POSITION_FOLLOWING)?-1:1),e.concat(s)}(i),a=()=>{j(n,void 0,{updatedCallback:!1})};if(t())return void a();const o=H("state",a);void 0!==o&&o.catch(O)}finally{T()}}class ee extends Yt{static hasConnectedCallbackPromise=!0;static getBindingsReady(t){return F(t)}static get observedAttributes(){return["mount"]}__state;_hasUpdatedCallback=!1;_hasErrorCallback=!1;_hydratedFromSsr=!1;_crossRowListPaths=new Set;_indexDependentGetterPaths=new Set;_initialized=!1;_initializeFailed=!1;_initializationLanded=!1;_initializePromise;_resolveInitialize=null;_connectedCallbackPromise;_resolveConnectedCallback=null;_rejectConnectedCallback=null;_loadingPromise;_resolveLoading=null;_setStatePromise=null;_resolveSetState=null;_listPaths=new Set;_listKeys=null;_recursionRegistry=null;_elementPaths=new Set;_getterPaths=new Set;_setterPaths=new Set;_loopContextStack=function(){return new Wt}();_dynamicDependency=new Map;_staticDependency=new Map;_pathSet=new Set;_stateGeneration=0;_pathRegistrations=new Map;_pendingReapplyPaths=null;_generatedPaths=new Set;_watchPaths=null;_scanPaths=null;_version=0;_rootNode=null;_boundComponent=null;_boundComponentStateProp=null;_hasMounts=!1;_hasGraftedVolumes=!1;_addressHooks=null;_bindableEventMap={};_commandTokenNames=new Set;_eventTokenNames=new Set;_treeless=!1;_connectGeneration=0;constructor(){super(),this._initializePromise=new Promise(t=>{this._resolveInitialize=t}),this._connectedCallbackPromise=new Promise((t,e)=>{this._resolveConnectedCallback=t,this._rejectConnectedCallback=e}),this._loadingPromise=new Promise(t=>{this._resolveLoading=t}),this._setStatePromise=new Promise(t=>{this._resolveSetState=t})}get _state(){return void 0===this.__state&&p(`${e.tagNames.state} _state is not initialized yet.`),this.__state}set _state(t){const e=this.__state,s=Ft();s.set("previousState",e),Et(this,t,s);const n=function(t){const e=new Set,s=t[B];if(void 0===s)return e;Array.isArray(s)||p(`${B} must be an array of strings.`);for(const t of s)"string"==typeof t&&0!==t.length||p(`${B} entries must be non-empty strings.`),t===J&&p(`${B} entry "${t}" conflicts with the reserved namespace name "${J}".`),e.has(t)&&p(`${B} entry "${t}" is duplicated.`),e.add(t);return e}(t),a=function(t){const e=new Set,s=t[Q];if(void 0===s)return e;Array.isArray(s)||p(`${Q} must be an array of strings.`);for(const t of s)"string"==typeof t&&0!==t.length||p(`${Q} entries must be non-empty strings.`),e.has(t)&&p(`${Q} entry "${t}" is duplicated.`),e.add(t);return e}(t),i=function(t){const e=t[Y];if(void 0===e)return null;"object"==typeof e&&null!==e||p(`${Y} must be an object mapping list paths to key specs.`);const s=new Map;for(const[t,n]of Object.entries(e)){0===t.length&&p(`${Y} entry path must be a non-empty string.`);const e=t.split(Z);e.some(t=>0===t.length)&&p(`${Y} entry "${t}" must not contain empty path segments.`),e[e.length-1]===tt&&p(`${Y} entry "${t}" must be the list path itself, not the element path (drop the trailing "${Z}${tt}").`),-1!==t.indexOf(et)&&p(`[wcs/recursion-unsupported] ${Y} entry "${t}" uses "${et}", which ${Y} does not interpret — a keyed list is one concrete list path. Declare the key per depth instead (for example "nodes${Z}${tt}${Z}children").`),"function"!=typeof n?("string"!=typeof n&&p(`${Y} entry "${t}" key spec must be a field name (string) or a function.`),0===n.length&&p(`${Y} entry "${t}" key field name must be a non-empty string.`),(n.includes(Z)||n.includes(tt))&&p(`${Y} entry "${t}" key field name "${n}" must be a flat property name ("${Z}" / "${tt}" are not allowed).`),n in Object.prototype&&p(`${Y} entry "${t}" key field name "${n}" must not be a property name inherited from Object.prototype (e.g. "__proto__", "constructor").`),s.set(t,n)):s.set(t,n)}return s.size>0?s:null}(t);s.set("eventTokenNames",a),zt(this,t,s),Dt(this,t,s),this._commandTokenNames=n,this._eventTokenNames=a,this._stateGeneration++,this.__state=t,void 0!==e&&Ut?.reset(this),this._hasUpdatedCallback=at in t,this._hasErrorCallback=it in t,U(this),Lt(this,t,s),function(t,e,s){const n=e[X];if(void 0!==n){"object"==typeof n&&null!==n||p(`${X} must be an object mapping event-token names to handler functions.`);for(const[e,a]of Object.entries(n))s.has(e)||p(`${X} entry "${e}" is not declared in $eventTokens.${f(e,s)}`),"function"!=typeof a&&p(`${X} entry "${e}" must be a function.`),_(t,e).subscribe(a)}}(this,t,this._eventTokenNames),this._listPaths.clear(),this._elementPaths.clear(),this._getterPaths.clear(),this._setterPaths.clear(),this._pathSet.clear();const o=function(t){const e=new Set,s=new Set,n=Nt(t);for(const[t,a]of Object.entries(n))"function"==typeof a.get&&e.add(t),"function"==typeof a.set&&s.add(t);return{getterPaths:e,setterPaths:s}}(t);for(const t of o.getterPaths)this._getterPaths.add(t);for(const t of o.setterPaths)this._setterPaths.add(t);Rt(this,t,s),this._listKeys=i,this._rebuildPathInfo(),jt(this,t,s),Ht(this,null),this._resolveLoading?.()}attributeChangedCallback(t,s,n){this._initialized&&s!==n&&console.warn(`[@wcstack/state] Changing the "mount" attribute after initialization is not supported and is ignored (was ${null===s?"absent":`"${s}"`}, now ${null===n?"absent":`"${n}"`}). Remove this <${e.tagNames.state}> element and create a new one with the desired mount path instead.`)}_loadFromSsrElement(){return this.hasAttribute("enable-ssr")?W('the "enable-ssr" attribute').loadState(this):null}async _loadStateFromSource(){try{if(this.hasAttribute("state")){return function(t){const e=document.getElementById(t);if(e&&"application/json"===e.type)try{return JSON.parse(e.textContent||"{}")}catch(t){p("Failed to parse JSON from script element:"+t)}return{}}(this.getAttribute("state"))}if(!this.hasAttribute("src")){if(this.hasAttribute("json")){const t=this.getAttribute("json");return JSON.parse(t)}{const t=this.querySelector('script[type="module"]');if(t)return await a(t,e.tagNames.state);{const t=setTimeout(()=>{console.warn(`[@wcstack/state] Warning: No state source found for <${e.tagNames.state}> element.`)},ut),s=await this._setStatePromise;return clearTimeout(t),s}}}{const t=this.getAttribute("src");if(t&&t.endsWith(".json"))return await async function(t){try{const e=await fetch(t);return e.ok||p(`Failed to fetch JSON file: ${e.statusText}`),await e.json()}catch(t){return console.error("Failed to load JSON file:",t),{}}}(t);if(t&&t.endsWith(".js"))return await n(t);p(`Unsupported src file type: ${t}`)}}catch(t){p(`Failed to initialize state: ${t}`)}}async _initialize(){const e=t()?null:this._loadFromSsrElement();if(null!==e&&(this._hydratedFromSsr=!0),this._state=await this._loadStateFromSource(),null!==e&&this.__state)for(const[t,s]of Object.entries(e)){if(t in this.__state){const e=Object.getOwnPropertyDescriptor(this.__state,t);if(e&&(e.get||e.set))continue;if("function"==typeof this.__state[t])continue}this.__state[t]=s}return await this._loadingPromise,null!==this._rootNode&&(V(this._rootNode,this),!0)}_failInitialization(t){this._initializationLanded=!0,this._resolveInitialize?.(),this._resolveLoading?.(),this._resolveConnectedCallback?.(),p(t)}_failInitializeLoudly(t,s=!0){if(this._initializationLanded)throw t;throw this._initializeFailed=!0,console.error(`[@wcstack/state] <${e.tagNames.state}> failed to initialize.`,t),this._resolveInitialize?.(),this._resolveLoading?.(),this._connectedCallbackPromise.catch(()=>{}),this._rejectConnectedCallback?.(t),s&&null!==this._rootNode&&null===R(this._rootNode)&&(q(this._rootNode,t),i(this,this._rootNode,t)),t}async _callStateConnectedCallback(){await this.createStateAsync("writable",async t=>{st in t&&await t[N]()})}_callStateDisconnectedCallback(){this.createState("writable",t=>{nt in t&&t[A]()})}async connectedCallback(){this._rootNode=this.getRootNode();const n=++this._connectGeneration;if(this._initializationLanded=!1,this._initialized){if(d(this))return void this._resolveConnectedCallback?.();this._treeless||R(this._rootNode)===this||V(this._rootNode,this)}else{this.hasAttribute("name")&&this._failInitialization(this.hasAttribute("mount")?'"mount" replaces "name" — a volume has no name of its own. Remove the name attribute.':`The "name" attribute was removed in v2 — there is a single state tree per root. Mount this state onto the tree instead: <wcs-state mount="${this.getAttribute("name")}" ...> and read it as "${this.getAttribute("name")}.<path>".`);const t=o(this);if(null!==t)return void await t;const s=this.parentNode;if(s instanceof ShadowRoot&&s.host.hasAttribute(pt))try{r("dcc",`a <${e.tagNames.state}> inside a [${pt}] host`)}catch(t){this._failInitializeLoudly(t)}if(this.hasAttribute("mount"))try{r("scopes",'the "mount" attribute')}catch(t){this._failInitializeLoudly(t,!1)}let n=!1;try{const t=l(this);null===t&&this.hasAttribute("bind-component")&&r("scopes",'the "bind-component" attribute'),n=await(t??!1)}catch(t){this._failInitializeLoudly(t)}if(n)return;let a=!1;try{a=await this._initialize()}catch(t){this._failInitializeLoudly(t)}if(!a)return;this._initialized=!0,this._resolveInitialize?.()}if(null!==this._pendingReapplyPaths){const t=this._pendingReapplyPaths;this._pendingReapplyPaths=null,this._reapplyBindings(t)}if(this.hasAttribute("enable-ssr")&&!t()||n!==this._connectGeneration||await this._callStateConnectedCallback(),t()&&this.hasAttribute("enable-ssr")&&!s())try{await W('the "enable-ssr" attribute').emitSnapshot(this)}catch(t){throw this._rejectConnectedCallback?.(t),t}Ht(this,n),this._resolveConnectedCallback?.()}disconnectedCallback(){if(!h(this)&&null!==this._rootNode){if(!this._initialized)return this._initializeFailed&&c(this,this._rootNode),void(this._rootNode=null);try{this._callStateDisconnectedCallback()}finally{V(this.rootNode,null),It(this),Ot(this),this._rootNode=null}}}get initialized(){return this._initialized}get connectedRootNode(){return this._rootNode}clearConnectedRootNode(){this._rootNode=null}markInitialized(){this._initialized=!0}settleInitialization(){this._resolveInitialize?.(),this._resolveLoading?.(),this._resolveConnectedCallback?.()}loadStateFromSource(){return this._loadStateFromSource()}markTreeless(){this._treeless=!0}failInitializeLoudly(t){return this._failInitializeLoudly(t)}get connectGeneration(){return this._connectGeneration}setWatchPaths(t){this._watchPaths=t}setScanPaths(t){this._scanPaths=t}landInitialization(){this._initializationLanded=!0,this._resolveInitialize?.(),this._resolveLoading?.(),this._resolveConnectedCallback?.()}setRecursionRegistry(t){this._recursionRegistry=t}addGeneratedPath(t){this._generatedPaths.add(t)}setBoundComponent(t,e){this._boundComponent=t,this._boundComponentStateProp=e}get initializePromise(){return this._initializePromise}get connectedCallbackPromise(){return this._connectedCallbackPromise}get listPaths(){return this._listPaths}get listKeys(){return this._listKeys}get hasRecursion(){return null!==this._recursionRegistry}get recursionRegistry(){return this._recursionRegistry}get watchPaths(){return this._watchPaths}get scanPaths(){return this._scanPaths}get elementPaths(){return this._elementPaths}addVolumeWatchPaths(t){if(0===t.size)return;const e=new Set(this._watchPaths??[]);for(const s of t)e.add(s);this._watchPaths=e,this.attachAddressHooks("watch",ft)}mergeVolumeListKeys(t){if(0===t.size)return;const e=new Map(this._listKeys??[]);for(const[s,n]of t)e.has(s)&&p(`$listKeys entry "${s}" is declared by both the root and a volume (or two volumes). Keep exactly one.`),e.set(s,n);this._listKeys=e}enableUpdatedCallback(){this._hasUpdatedCallback=!0}get hydratedFromSsr(){return this._hydratedFromSsr}addListPath(t){this._listPaths.add(t)}findStateDescriptor(t){return _t(this._state,t)}defineTreeAccessor(t,e){Object.defineProperty(this._state,t,e),"function"==typeof e.get&&this._getterPaths.add(t),"function"==typeof e.set&&this._setterPaths.add(t),this.setPathInfo(t,"prop","internal")}get getterPaths(){return this._getterPaths}get setterPaths(){return this._setterPaths}get loopContextStack(){return this._loopContextStack}get dynamicDependency(){return this._dynamicDependency}get staticDependency(){return this._staticDependency}get version(){return this._version}get stateGeneration(){return this._stateGeneration}get rootNode(){return null===this._rootNode&&p("State rootNode is not available."),this._rootNode}get boundComponentStateProp(){return this._boundComponentStateProp}get hasMounts(){return this._hasMounts}markHasMounts(){this._hasMounts=!0,this._attachScopeHooks("bind-component")}get hasGraftedVolumes(){return this._hasGraftedVolumes}get addressHooks(){return this._addressHooks}attachAddressHooks(t,e){const s=Tt(t,e);null===this._addressHooks&&(this._addressHooks=Gt()),Mt(this._addressHooks,s)}markHasGraftedVolumes(){this._hasGraftedVolumes=!0,this._attachScopeHooks("mount")}markHasVolume(){this._attachScopeHooks("mount")}_attachScopeHooks(t){this.attachAddressHooks("scopes",t)}get bindableEventMap(){return this._bindableEventMap}get commandTokenNames(){return this._commandTokenNames}get eventTokenNames(){return this._eventTokenNames}setBindableEventMap(t){this._bindableEventMap=t,this.attachAddressHooks("dcc",mt)}_addDependency(t,e,s){const n=t.get(e);return void 0===n?(t.set(e,[s]),!0):!n.includes(s)&&(n.push(s),!0)}addDynamicDependency(t,e){return this._addDependency(this._dynamicDependency,t,e)}addStaticDependency(t,e){return this._addDependency(this._staticDependency,t,e)}setPathInfo(t,e,s="binding"){if("internal"!==s){const n=this._pathRegistrations.get(t);void 0===n?this._pathRegistrations.set(t,{bindingType:e,bound:"binding"===s}):"for"!==n.bindingType&&this._pathRegistrations.set(t,{bindingType:e,bound:n.bound||"binding"===s})}if("for"===e&&(this._listPaths.add(t),this._elementPaths.add(t+"."+tt)),!this._pathSet.has(t)){const e=ct(t);if(this._pathSet.add(t),Ut?.check(this,this.__state,t,s),null!==e.parentPath){let t=e;for(;null!==t.parentPath&&this.addStaticDependency(t.parentPath,t.path);)t=ct(t.parentPath)}}}_rebuildPathInfo(){for(const[t,e]of Array.from(this._pathRegistrations))e.bound&&!this._generatedPaths.has(t)&&this.setPathInfo(t,e.bindingType)}_createState(t,e,s){try{const n=function(t,e,s){const n=new Xt(t,s);return new Proxy(e,n)}(t,this._state,e);return s(n)}finally{}}async createStateAsync(t,e){return await this._createState(this.rootNode,t,e)}createState(t,e){this._createState(this.rootNode,t,e)}nextVersion(){return this._version++,this._version}get hasUpdatedCallback(){return this._hasUpdatedCallback}get hasErrorCallback(){return this._hasErrorCallback}get crossRowListPaths(){return this._crossRowListPaths}addCrossRowListPath(t){this._crossRowListPaths.add(t)}get indexDependentGetterPaths(){return this._indexDependentGetterPaths}addIndexDependentGetterPath(t){this._indexDependentGetterPaths.add(t)}setInitialState(t){if(!this._initialized)return this._initializeFailed&&p(`<${e.tagNames.state}> failed to initialize (the diagnostic was reported when it connected), so its state cannot be replaced. Remove this element and create a new one with the corrected state.`),void this._resolveSetState?.(t);u(this),(this._hasGraftedVolumes||this._hasMounts)&&p("Cannot replace the whole state of a tree that has grafted volumes or mounted components: re-setting would silently drop grafted data, tree accessors and mount ledgers (D22). Write the changed paths instead.");const s=this.__state;this._state=t;const n=function(t){const e=new Set;for(const s of t)if(void 0!==s)for(const[t,n]of Object.entries(Nt(s)))t.startsWith("$")||t.includes(tt)||"function"==typeof n.value||e.add(t);return e}([s,t]);null!==this._rootNode?this._reapplyBindings(n):this._pendingReapplyPaths=new Set([...this._pendingReapplyPaths??[],...n])}_reapplyBindings(t){te(this,t,this._pathRegistrations.keys())}}const se=[];function ne(t){se.includes(t)||se.push(t)}function ae(t=customElements){for(let e=0;e<se.length;e++)se[e](t);t.get(e.tagNames.state)||t.define(e.tagNames.state,ee)}export{Yt as H,ne as a,ae as r};
|
|
2
|
+
//# sourceMappingURL=registerComponents.js.map
|