@wcstack/typescript 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -572,7 +572,7 @@ function loadSchemaCore() {
572
572
  return cached;
573
573
  }
574
574
 
575
- var version = "4.2.0";
575
+ var version = "4.3.0";
576
576
  var pkg = {
577
577
  version: version};
578
578
 
@@ -68,12 +68,15 @@ var WcsDiagnosticCode = {
68
68
  NestedAssign: "wcs/nested-assign",
69
69
  // --- 意味論(構文・存在検査では捕まらない取り違え。service/semanticValidator.ts) ---
70
70
  // `$getAll` / `$setAll` / `$resolve` の添字の本数がパスの `*` の本数と噛み合わない。
71
- // ランタイムは同じ code で raiseError する(超過は以前は黙って無視されていた)。
71
+ // ランタイムは #901 / #902 で throw する(diagnostics の後付けがあれば同じ code の文面。超過は 3.x では
72
+ // 黙って無視されていた)。error。
72
73
  IndexArity: "wcs/index-arity",
73
74
  // ワイルドカードの階数がスコープの段数を超える(`matrix.*.*` を 1 段の for で読む、
74
75
  // `$2` を 1 段のループで読む。ランタイムの #1401)。既存の「for の外」検査の深さ方向の一般化。
75
76
  // 4.0 は各段の `*` が**その段で囲む for のリスト**の行であることも確かめる(#1403・F32 — `for: a`
76
- // の行の中の `b.*.y` は投げる)。静的側も囲む for の一覧と段ごとに比べて同じ code で報告する。
77
+ // の行の中の `b.*.y` は投げる)。静的側も囲む for の一覧と段ごとに比べて同じ code で報告する
78
+ // (ランタイムの文面に code が付くのは diagnostics の後付けがあるとき)。for のスコープを組み直しきれない
79
+ // ので、ランタイムは初期化を失敗させるが warning のまま(vscode-wcs の README の重大度の例外)。
77
80
  WildcardRank: "wcs/wildcard-rank",
78
81
  // ループの添字の範囲(`$1`〜`$128`。上限は manifest の `syntax.indexParam.maxDepth`)の外。ランタイムと同じ code:
79
82
  // for の中のマークアップの `$129`(バインディングが失敗する)と、スクリプトの `this.$0` / `this.$129` / `this.$1000`
@@ -81,7 +84,8 @@ var WcsDiagnosticCode = {
81
84
  // `wcs/binding-path-missing`(ただしけっして動かないので error)。for の外の `$129` はランタイムでは #1401 なので
82
85
  // 従来どおり「for の外のループ添字」(`wcs/template-syntax`)で報告する。
83
86
  IndexParamRange: "wcs/index-param-range",
84
- // パス getter どうしの循環参照。ランタイムはアドレススタック上限まで再帰してから落ちる。
87
+ // パス getter どうしの循環参照。4.0 のランタイムは評価の時点で #701 として throw し、その getter を読む
88
+ // 束縛はすべて失敗する(3.x はアドレススタック上限まで再帰してから落ちた)。error。
85
89
  GetterCycle: "wcs/getter-cycle",
86
90
  // `$renderedCallback`(3.x の旧名 `$updatedCallback`)が、どのバインディングにも現れないパスを判定に使っている。
87
91
  // 同コールバックは **binding 駆動**(live binding が適用された path しか報告しない)
@@ -96,8 +100,9 @@ var WcsDiagnosticCode = {
96
100
  GetterUntrackedRead: "wcs/getter-untracked-read",
97
101
  OnHandlerThis: "wcs/on-handler-this",
98
102
  // --- <wcs-state> script: $watch declaration ---
99
- // ランタイム(watch/processWatchDeclaration.ts)が raiseError で落とす宣言。
100
- // 越境 `@` / `$` 始まり / 空キー・空セグメント / 明らかな非関数ハンドラ。
103
+ // temporal の後付け(state の temporal/watch.ts)が読み込みで throw する宣言: 越境 `@` / `$` 始まり /
104
+ // 空キー / 明らかな非関数ハンドラ。空の段(`a..b`)はランタイムが調べず、その watch は黙って発火しない
105
+ // (lint だけが知らせる — docs/mistake-catalogue.md)。
101
106
  WatchDeclarationInvalid: "wcs/watch-declaration-invalid",
102
107
  // `$watch` のキーが状態定義に存在しない。バインディング側と違い黙って発火しない
103
108
  // だけなので気づけない。severity は binding-path-missing に揃える(warning)。
@@ -116,8 +121,8 @@ var WcsDiagnosticCode = {
116
121
  //
117
122
  // `**` を解釈しない場所へ `**` が渡った(data-wcs / mustache / $watch キー / $listKeys
118
123
  // キー / $resolve / $postUpdate / $dependOn(旧名 $trackDependency) / 代入)、または `$recursion` 宣言が
119
- // 無いのに `**` を使った。runtime は PathInfo の不変条件として raiseError するか
120
- //(API 経由)、getter を黙って無視する(宣言なしの `**` getter)。
124
+ // 無いのに `**` を使った。4.0 の runtime はどれも #1101 で throw する — 宣言なしの `**` getter も、
125
+ // アクセサを登録する時点で(3.x は黙って無視した)。error。
121
126
  RecursionUnsupported: "wcs/recursion-unsupported",
122
127
  // 宣言済みアンカーと合致しない `**`(綴り違い・2 つ目の `**`)、または `**` の後ろが
123
128
  // 整形されていない(空セグメント・`**` 直後の素の `*`)。
@@ -155,7 +160,8 @@ var WcsDiagnosticCode = {
155
160
  // ドットアクセスを含むチェーン代入は NestedAssign の担当(相補・二重報告なし)。
156
161
  ArrayIndexAssign: "wcs/array-index-assign",
157
162
  // --- built-in wcs-* tag contract (generated/builtinTags.generated.ts が正本) ---
158
- // 未知メンバーへのバインド(プロパティ / command. / eventToken. キー)。黙って無視される。
163
+ // 未知メンバーへのバインド(プロパティ / command. / eventToken. キー)。4.0 のランタイムは #38 / #1203 /
164
+ // #1204 で拒み、root では初期化が、行では束縛が失敗する(3.x の「黙って無視」ではない)。error。
159
165
  TagMemberUnknown: "wcs/tag-member-unknown",
160
166
  // タグのメンバー名が "on" で始まる(`once` 等)のに先頭ドット無しで束縛した: ランタイムはイベント束縛にして
161
167
  // "ce" イベントを待ち、値は届かない。明示のプロパティ形 `.once:` を提案する(@wcstack/state 3.1・要件 B5 / 3.x 計画 D36)
@@ -217,7 +223,8 @@ var WcsDiagnosticCode = {
217
223
  // (error 昇格時は packages/lint/scripts/smoke-test.mjs の対ケース更新が必須)。
218
224
  AriaAttrUnknown: "wcs/aria-attr-unknown",
219
225
  // --- document-level load configuration ---
220
- // @wcstack/state/auto より後に他 wcstack /auto が読まれている。
226
+ // @wcstack/state/auto より後に @wcstack/devtools/auto が読まれている。info: 4.0 は後から付いた DevTools に
227
+ // 既存の束縛を送り直すので、欠けるのは付く前のタイムラインだけ。
221
228
  ScriptOrder: "wcs/script-order",
222
229
  // router/auto があるのに <base href> がない(SPA の basename 誤導出)。
223
230
  BaseHrefMissing: "wcs/base-href-missing",
@@ -2056,6 +2063,61 @@ function extractAttribute(tagContent, attrName) {
2056
2063
  if (!match) return null;
2057
2064
  return match[1] ?? match[2] ?? match[3] ?? null;
2058
2065
  }
2066
+ var IGNORE_VOID_ELEMENTS = /* @__PURE__ */ new Set([
2067
+ "area",
2068
+ "base",
2069
+ "br",
2070
+ "col",
2071
+ "embed",
2072
+ "hr",
2073
+ "img",
2074
+ "input",
2075
+ "link",
2076
+ "meta",
2077
+ "param",
2078
+ "source",
2079
+ "track",
2080
+ "wbr"
2081
+ ]);
2082
+ function findIgnoredRanges(html, bindAttribute) {
2083
+ const marker = asciiLowerCase(`${bindAttribute}-ignore`);
2084
+ const lower2 = asciiLowerCase(html);
2085
+ if (!lower2.includes(marker)) return [];
2086
+ const out = [];
2087
+ const stack = [];
2088
+ const tag = /<!--[\s\S]*?(?:-->|$)|<(\/?)([a-zA-Z][^\s/>]*)((?:[^>"']|"[^"]*"|'[^']*')*)>/g;
2089
+ let match;
2090
+ while ((match = tag.exec(html)) !== null) {
2091
+ if (match[2] === void 0) continue;
2092
+ const name = asciiLowerCase(match[2]);
2093
+ const end = match.index + match[0].length;
2094
+ if (match[1] === "/") {
2095
+ for (let i = stack.length - 1; i >= 0; i--) {
2096
+ if (stack[i].name !== name) continue;
2097
+ for (const open of stack.slice(i)) if (open.start !== null) out.push([open.start, end]);
2098
+ stack.length = i;
2099
+ break;
2100
+ }
2101
+ continue;
2102
+ }
2103
+ const ignored = parseAttributeNames(match[3]).has(marker) ? match.index : null;
2104
+ if (IGNORE_VOID_ELEMENTS.has(name)) {
2105
+ if (ignored !== null) out.push([ignored, end]);
2106
+ continue;
2107
+ }
2108
+ if (RAW_TEXT_ELEMENTS.has(name)) {
2109
+ const close = name === "plaintext" ? -1 : lower2.indexOf(`</${name}`, end);
2110
+ const closeEnd = close === -1 ? html.length : html.indexOf(">", close) + 1 || html.length;
2111
+ if (ignored !== null) out.push([ignored, closeEnd]);
2112
+ if (close === -1) break;
2113
+ tag.lastIndex = closeEnd;
2114
+ continue;
2115
+ }
2116
+ stack.push({ name, start: ignored });
2117
+ }
2118
+ for (const open of stack) if (open.start !== null) out.push([open.start, html.length]);
2119
+ return out;
2120
+ }
2059
2121
 
2060
2122
  // src/core/parser/quoteAware.ts
2061
2123
  var isQuote = (c) => c === "'" || c === '"';
@@ -2563,10 +2625,11 @@ var builtinFilterMeta = {
2563
2625
  // `not` は真偽性(truthy / falsy)の反転。`if:` が `Boolean()` で寄せるのと同じ規則で、
2564
2626
  // `else:` はこのフィルタを足した束縛として組み立てられる(structural/createNotFilter.ts)
2565
2627
  not: { description: "\u771F\u507D\u6027\u3092\u53CD\u8EE2\uFF08falsy \u2192 true\uFF09", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
2566
- lt: { description: "\u3088\u308A\u5C0F\u3055\u3044\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
2567
- le: { description: "\u4EE5\u4E0B\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
2568
- gt: { description: "\u3088\u308A\u5927\u304D\u3044\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
2569
- ge: { description: "\u4EE5\u4E0A\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
2628
+ // 比較は数値だけを受ける(filters/core.ts の `numeric` は数値以外の値で #28。3.x も同じで、"string" は誤りだった)
2629
+ lt: { description: "\u3088\u308A\u5C0F\u3055\u3044\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
2630
+ le: { description: "\u4EE5\u4E0B\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
2631
+ gt: { description: "\u3088\u308A\u5927\u304D\u3044\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
2632
+ ge: { description: "\u4EE5\u4E0A\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
2570
2633
  // 算術
2571
2634
  add: { description: "\u52A0\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
2572
2635
  sub: { description: "\u6E1B\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
@@ -11253,15 +11316,15 @@ var ja = {
11253
11316
  watchKeyEmptySegment: (k) => `$watch \u306E\u30AD\u30FC "${k}" \u306B\u7A7A\u306E\u30D1\u30B9\u30BB\u30B0\u30E1\u30F3\u30C8\u304C\u3042\u308A\u307E\u3059`,
11254
11317
  watchHandlerNotFunction: (k) => `$watch \u306E\u30A8\u30F3\u30C8\u30EA "${k}" \u306E\u5024\u306F\u95A2\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059`,
11255
11318
  watchPathMissing: (k) => `$watch \u306E\u30AD\u30FC "${k}" \u306F\u72B6\u614B\u5B9A\u7FA9\u306B\u5B58\u5728\u3057\u307E\u305B\u3093\uFF08\u4E00\u5EA6\u3082\u767A\u706B\u3057\u307E\u305B\u3093\uFF09`,
11256
- scanRemoved: (mountPath) => mountPath === null ? `$scan \u306F 4.0 \u3067\u5916\u308C\u307E\u3057\u305F\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u8AAD\u307F\u8FBC\u307F\u6642\u306B throw \u3057\u307E\u3059\uFF09\u3002\u30D1\u30B9\u306E\u5909\u5316\u3092\u7573\u3080\u306A\u3089 $watch\u3001\u30A4\u30D9\u30F3\u30C8\u3092\u7573\u3080\u306A\u3089 $on \u306E\u30CF\u30F3\u30C9\u30E9\u3067\u3001\u51FA\u529B\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u3078\u66F8\u3044\u3066\u304F\u3060\u3055\u3044` : `$scan \u306F 4.0 \u3067\u5916\u308C\u307E\u3057\u305F\u3002\u30DC\u30EA\u30E5\u30FC\u30E0\uFF08mount="${mountPath}"\uFF09\u3067\u306F\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u63A5\u304E\u6728\u3092\u62D2\u3093\u3067 console.error \u3067\u5831\u544A\u3057\u307E\u3059\uFF08\u3053\u306E state \u306F\u6728\u306B\u8F09\u308A\u307E\u305B\u3093\uFF09\u3002root \u306E state \u306E $watch \u304B $on \u306E\u30CF\u30F3\u30C9\u30E9\u3067\u7573\u3093\u3067\u304F\u3060\u3055\u3044`,
11319
+ scanRemoved: (mountPath) => mountPath === null ? `$scan \u306F 4.0 \u3067\u5916\u308C\u307E\u3057\u305F\uFF08diagnostics \u306E\u5F8C\u4ED8\u3051\u3092\u5165\u308C\u305F\u5165\u53E3 \u2014 /auto \u306A\u3069 \u2014 \u306F\u8AAD\u307F\u8FBC\u307F\u6642\u306B throw \u3057\u3001/core \u3060\u3051\u3067\u306F\u9ED9\u3063\u3066\u7121\u8996\u3057\u307E\u3059\uFF09\u3002\u30D1\u30B9\u306E\u5909\u5316\u3092\u7573\u3080\u306A\u3089 $watch\u3001\u30A4\u30D9\u30F3\u30C8\u3092\u7573\u3080\u306A\u3089 $on \u306E\u30CF\u30F3\u30C9\u30E9\u3067\u3001\u51FA\u529B\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u3078\u66F8\u3044\u3066\u304F\u3060\u3055\u3044` : `$scan \u306F 4.0 \u3067\u5916\u308C\u307E\u3057\u305F\u3002\u30DC\u30EA\u30E5\u30FC\u30E0\uFF08mount="${mountPath}"\uFF09\u3067\u306F\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u63A5\u304E\u6728\u3092\u62D2\u3093\u3067 console.error \u3067\u5831\u544A\u3057\u307E\u3059\uFF08\u3053\u306E state \u306F\u6728\u306B\u8F09\u308A\u307E\u305B\u3093\uFF09\u3002root \u306E state \u306E $watch \u304B $on \u306E\u30CF\u30F3\u30C9\u30E9\u3067\u7573\u3093\u3067\u304F\u3060\u3055\u3044`,
11257
11320
  typeAnnotationIncompatible: (vt, rt) => `\u578B "${vt}" \u306F @type {${rt}} \u3068\u4E92\u63DB\u6027\u304C\u3042\u308A\u307E\u305B\u3093`,
11258
11321
  arrayMutation: (m, alt) => `\u914D\u5217\u306E\u7834\u58CA\u7684\u30E1\u30BD\u30C3\u30C9 "${m}" \u306F\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u66F4\u65B0\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u305B\u3093\uFF08\u540C\u4E00\u53C2\u7167\u306E\u81EA\u5DF1\u518D\u4EE3\u5165\u3067\u3082\u8981\u7D20\u306E\u8FFD\u52A0\u30FB\u524A\u9664\u306F\u53CD\u6620\u3055\u308C\u307E\u305B\u3093\uFF09\u3002\u975E\u7834\u58CA\u30E1\u30BD\u30C3\u30C9\u3068\u518D\u4EE3\u5165\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: ${alt}\uFF09\u3002`,
11259
11322
  arrayIndexAssign: (sp) => `\u914D\u5217\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3078\u306E\u76F4\u63A5\u4EE3\u5165\u306F\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u66F4\u65B0\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u305B\u3093\u3002this["${sp}"] \u306E\u3088\u3046\u306A\u30C9\u30C3\u30C8\u30D1\u30B9\u4EE3\u5165\u3001\u307E\u305F\u306F with() \u3068\u518D\u4EE3\u5165\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002`,
11260
11323
  inPlaceAlias: (a, src, t) => `"${a}" \u306F ${src}\uFF08state \u306E\u5024\u305D\u306E\u3082\u306E\uFF09\u3067\u3059\u3002\u305D\u308C\u3092\u901A\u3057\u305F\u5909\u66F4\u306F\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u66F4\u65B0\u3092\u30C8\u30EA\u30AC\u30FC\u305B\u305A\u3001\u540C\u3058\u5024\u3092\u66F8\u304D\u623B\u3057\u3066\u3082\u4E00\u89A7\u306E\u884C\u306F\u8FFD\u52A0\u30FB\u524A\u9664\u30FB\u7F6E\u304D\u63DB\u3048\u3055\u308C\u307E\u305B\u3093\u3002\u65B0\u3057\u3044\u5024\u3092\u4F5C\u3063\u3066 ${t} \u306B\u4EE3\u5165\u3057\u3066\u304F\u3060\u3055\u3044\uFF08${a}.with(i, item) / [...${a}, item] / { ...${a}, key: value }\uFF09`,
11261
11324
  inPlaceChange: (src, t) => `${src} \u306F state \u306E\u5024\u3092\u305D\u306E\u5834\u3067\u5909\u3048\u308B\u306E\u3067\u3001\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u66F4\u65B0\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u305B\u3093\u3002\u65B0\u3057\u3044\u5024\u3092\u4F5C\u3063\u3066 ${t} \u306B\u4EE3\u5165\u3057\u3066\u304F\u3060\u3055\u3044`,
11262
- tagMemberUnknown: (prop, tag) => `"${prop}" \u306F <${tag}> \u306E wcBindable \u30E1\u30F3\u30D0\u30FC\u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF08\u672A\u77E5\u30E1\u30F3\u30D0\u30FC\u3078\u306E\u30D0\u30A4\u30F3\u30C9\u306F\u9ED9\u3063\u3066\u7121\u8996\u3055\u308C\u307E\u3059\uFF09`,
11325
+ tagMemberUnknown: (prop, tag) => `"${prop}" \u306F <${tag}> \u306E wcBindable \u30E1\u30F3\u30D0\u30FC\u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u5BA3\u8A00\u306B\u7121\u3044\u30E1\u30F3\u30D0\u30FC\u3078\u306E\u675F\u7E1B\u3092 #38 \u3067\u62D2\u307F\u3001root \u3067\u306F state \u304C\u521D\u671F\u5316\u306B\u5931\u6557\u3057\u307E\u3059\uFF09`,
11263
11326
  nameAlias: (written, canonical) => `"${written}" \u306F 4.0 \u3067\u5916\u308C\u307E\u3057\u305F\uFF08"${canonical}" \u306E 3.x \u306E\u65E7\u540D\u3067\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u8AAD\u3093\u3060\u6642\u70B9\u3067 throw \u3057\u307E\u3059\uFF09\u3002"${canonical}" \u3068\u66F8\u3044\u3066\u304F\u3060\u3055\u3044`,
11264
- declarationAliasRead: (alias, canonical) => `"${alias}" \u306F 4.0 \u3067\u5916\u308C\u305F\u5BA3\u8A00\u30AD\u30FC\uFF08"${canonical}" \u306E 3.x \u306E\u65E7\u540D\uFF09\u306A\u306E\u3067\u3001this["${alias}"] \u306F undefined \u306B\u306A\u308A\u307E\u3059\u3002"${canonical}" \u3092\u8AAD\u3093\u3067\u304F\u3060\u3055\u3044`,
11327
+ declarationAliasRead: (alias, canonical) => `"${alias}" \u306F 4.0 \u3067\u5916\u308C\u305F\u5BA3\u8A00\u30AD\u30FC\uFF08"${canonical}" \u306E 3.x \u306E\u65E7\u540D\uFF09\u306A\u306E\u3067\u3001this["${alias}"] \u306F undefined \u306B\u306A\u308A\u307E\u3059\u3002\u5BA3\u8A00\u306F this \u3092\u901A\u3057\u3066\u8AAD\u3081\u307E\u305B\u3093 \u2014 "${canonical}" \u3092\u8AAD\u3093\u3067\u3082 undefined \u3067\u3059${canonical === "$stream" ? "\uFF08\u30B9\u30C8\u30EA\u30FC\u30E0\u306E\u72B6\u614B\u306F $streamStatus\u30FB$streamError \u3067\u8AAD\u307F\u307E\u3059\uFF09" : ""}`,
11265
11328
  declarationAlias: (alias, canonical) => `\u5BA3\u8A00\u30AD\u30FC "${alias}" \u306F 4.0 \u3067\u5916\u308C\u307E\u3057\u305F\uFF08"${canonical}" \u306E 3.x \u306E\u65E7\u540D\u3067\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u8AAD\u307F\u8FBC\u307F\u6642\u306B throw \u3057\u307E\u3059\uFF09\u3002"${canonical}" \u3068\u66F8\u3044\u3066\u304F\u3060\u3055\u3044`,
11266
11329
  declarationAliasInVolume: (alias, canonical, mountPath) => `\u5BA3\u8A00\u30AD\u30FC "${alias}" \u306F 4.0 \u3067\u5916\u308C\u307E\u3057\u305F\uFF08"${canonical}" \u306E 3.x \u306E\u65E7\u540D\uFF09\u3002\u30DC\u30EA\u30E5\u30FC\u30E0\uFF08mount="${mountPath}"\uFF09\u3067\u306F\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u63A5\u304E\u6728\u3092\u62D2\u3093\u3067 console.error \u3067\u5831\u544A\u3057\u307E\u3059\uFF08\u3053\u306E state \u306F\u6728\u306B\u8F09\u308A\u307E\u305B\u3093\uFF09\u3002"${canonical}" \u3082\u30DC\u30EA\u30E5\u30FC\u30E0\u3067\u306F\u5BA3\u8A00\u3067\u304D\u306A\u3044\u306E\u3067\u3001root \u306E state \u306B\u5BA3\u8A00\u3057\u3066\u304F\u3060\u3055\u3044`,
11267
11330
  behaviorNotObject: (keys) => `$behavior \u306F { ${keys.map((k) => `${k}?`).join(", ")} } \u306E\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u8AAD\u307F\u8FBC\u307F\u6642\u306B throw \u3057\u307E\u3059\uFF09`,
@@ -11291,7 +11354,7 @@ var ja = {
11291
11354
  storagePairClobber: (path) => `<wcs-storage> \u306E value \u3092 #init=element \u306A\u3057\u3067\u30A2\u30AF\u30BB\u30B5\u30DA\u30A2 "${path}" \u306B\u675F\u306D\u3066\u3044\u307E\u3059\u3002state \u306E\u5074\u304C\u5148\u306B\u66F8\u304F\u306E\u3067\u3001\u8AAD\u307F\u8FBC\u307F\u306E\u305F\u3073\u306B getter \u306E\u6700\u521D\u306E\u5024\u304C\u4FDD\u5B58\u5024\u306E\u4E0A\u306B\u4FDD\u5B58\u3055\u308C\u3001setter \u306F\u4FDD\u5B58\u5024\u3092\u53D7\u3051\u53D6\u308C\u307E\u305B\u3093 \u2014 #init=element \u3092\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044\uFF08\`value#init=element: ${path}\`\uFF09`,
11292
11355
  inputNestedWrite: (tag, input, path, example) => `<${tag}> \u306E\u5165\u529B "${input}" \u306B "${path}" \u3092\u675F\u306D\u3066\u3044\u307E\u3059\u304C\u3001\u30DA\u30FC\u30B8\u306F\u305D\u306E\u4E0B\uFF08"${example}"\uFF09\u3078\u66F8\u304D\u8FBC\u3093\u3067\u3044\u307E\u3059\u3002\u675F\u7E1B\u306F "${path}" \u81EA\u8EAB\u3078\u306E\u4EE3\u5165\u3067\u3057\u304B\u5F53\u3066\u76F4\u3055\u308C\u306A\u3044\u306E\u3067\u3001\u4E0B\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306F <${tag}> \u306B\u5C4A\u304D\u307E\u305B\u3093 \u2014 \u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u30D1\u30B9\u3067\u8AAD\u3093\u3067\u65B0\u3057\u3044\u5024\u3092\u8FD4\u3059 getter\uFF08\`this["${example}"]\`\u30FB\`$getAll\`\uFF09\u3092\u675F\u306D\u308B\u304B\u3001\u4E0B\u3078\u66F8\u304B\u305A\u306B "${path}" \u3092\u5DEE\u3057\u66FF\u3048\u3066\u304F\u3060\u3055\u3044`,
11293
11356
  inputNestedWriteOneShot: (tag, input, path, example) => `<${tag}> \u306E\u5165\u529B "${input}" \u306B "${path}" \u3092\u675F\u306D\u3066\u3044\u307E\u3059\u304C\u3001\u30DA\u30FC\u30B8\u306F\u305D\u306E\u4E0B\uFF08"${example}"\uFF09\u3078\u66F8\u304D\u8FBC\u3093\u3067\u3044\u307E\u3059\u3002\u675F\u7E1B\u306F "${path}" \u81EA\u8EAB\u3078\u306E\u4EE3\u5165\u3067\u3057\u304B\u5F53\u3066\u76F4\u3055\u308C\u305A\u3001<${tag}> \u306F\u8981\u6C42\u306E\u305F\u3073\u306B "${input}" \u3092 null \u306B\u623B\u3059\u306E\u3067\u3001\u6B21\u306E\u8981\u6C42\u306F "${input}" \u306A\u3057\u3067\u9001\u3089\u308C\u307E\u3059 \u2014 \u8981\u6C42\u3092\u59CB\u3081\u308B\u30CF\u30F3\u30C9\u30E9\u3067\u65B0\u3057\u3044\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u4F5C\u3063\u3066\u4EE3\u5165\u3057\uFF08\`this.submitBody = { \u2026 }\`\uFF09\u3001\u305D\u308C\u3092\u675F\u306D\u3066\u304F\u3060\u3055\u3044`,
11294
- devtoolsAfterState: () => `@wcstack/devtools/auto \u306F @wcstack/state/auto \u3088\u308A\u5148\u306B\u8AAD\u307F\u8FBC\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u5F8C\u3060\u3068\u914D\u7DDA\u53F0\u5E33\u304C\u30E9\u30A4\u30D6\u3067 captured \u3055\u308C\u307E\u305B\u3093\uFF09`,
11357
+ devtoolsAfterState: () => `@wcstack/devtools/auto \u306F @wcstack/state/auto \u3088\u308A\u5148\u306B\u8AAD\u307F\u8FBC\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u5F8C\u304B\u3089\u3060\u3068\u3001DevTools \u306E\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u306F\u4ED8\u3044\u305F\u6642\u70B9\u304B\u3089\u59CB\u307E\u308A\u307E\u3059\u3002\u65E2\u306B\u3042\u308B\u914D\u7DDA\u306F 4.0 \u304C\u9001\u308A\u76F4\u3057\u307E\u3059\uFF09`,
11295
11358
  baseHrefMissing: () => `@wcstack/router \u3092\u4F7F\u3046 SPA \u306B\u306F <head> \u5185\u306E <base href="/"> \u304C\u5FC5\u8981\u3067\u3059\uFF08\u7121\u3044\u3068\u30C7\u30A3\u30FC\u30D7\u30EA\u30F3\u30AF\u3067 basename \u304C\u8AA4\u5C0E\u51FA\u3055\u308C\u307E\u3059\uFF09`,
11296
11359
  routerOutletMisplaced: () => `\u3053\u306E <wcs-outlet> \u306F <wcs-router> \u306E\u76F4\u5F8C\u306B\u7121\u3044\u306E\u3067\u3001\u3069\u306E router \u3082\u4F7F\u3044\u307E\u305B\u3093\u3002router \u306F\u81EA\u5206\u306E\u76F4\u5F8C\u306E\u8981\u7D20\u3060\u3051\u3092 outlet \u3068\u3057\u3066\u4F7F\u3044\u3001\u305D\u3053\u306B <wcs-outlet> \u304C\u7121\u3051\u308C\u3070\u81EA\u524D\u306E outlet \u3092\u4F5C\u308A\u307E\u3059\u3002\u30EB\u30FC\u30C8\u306F router \u306E\u76F4\u5F8C\u306B\u63CF\u304B\u308C\u3001\u3053\u306E outlet \u306F\u7A7A\u306E\u307E\u307E\u3067\u3059 \u2014 <wcs-router> \u306E\u76F4\u5F8C\u3078\u79FB\u3057\u3066\u304F\u3060\u3055\u3044`,
11297
11360
  signalsDualEntry: () => `@wcstack/signals \u3068 @wcstack/signals/dom \u304C\u540C\u4E00\u30DA\u30FC\u30B8\u304B\u3089 import \u3055\u308C\u3066\u3044\u307E\u3059\u3002CDN \u3067\u306F\u5404\u30A8\u30F3\u30C8\u30EA\u304C\u81EA\u5DF1\u5B8C\u7D50\u30D0\u30F3\u30C9\u30EB\u306E\u305F\u3081\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u30B3\u30A2\u304C\u4E8C\u91CD\u5316\u3057\u3001\u5883\u754C\u3067\u53CD\u5FDC\u304C\u58CA\u308C\u307E\u3059 \u2014 \u3059\u3079\u3066 /dom \u30A8\u30F3\u30C8\u30EA\u304B\u3089 import \u3057\u3066\u304F\u3060\u3055\u3044`,
@@ -11303,13 +11366,15 @@ var ja = {
11303
11366
  mountPathInvalid: (problem, mountPath) => {
11304
11367
  switch (problem) {
11305
11368
  case "empty":
11306
- return `"mount" \u306B\u306F\u7A7A\u3067\u306A\u3044\u30C4\u30EA\u30FC\u30D1\u30B9\u304C\u5FC5\u8981\u3067\u3059\uFF08runtime: "mount" requires a non-empty tree path.\uFF09`;
11369
+ return `"mount" \u306B\u306F\u7A7A\u3067\u306A\u3044\u9759\u7684\u306A\u30D1\u30B9\u304C\u5FC5\u8981\u3067\u3059\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u30DC\u30EA\u30E5\u30FC\u30E0\u3092\u62D2\u307F\u307E\u3059: has an invalid mount path\uFF09`;
11307
11370
  case "emptySegment":
11308
- return `"mount" \u30D1\u30B9 "${mountPath}" \u306B\u7A7A\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u304C\u3042\u308A\u307E\u3059\uFF08runtime: has an empty segment.\uFF09`;
11371
+ return `"mount" \u30D1\u30B9 "${mountPath}" \u306B\u7A7A\u306E\u6BB5\u304C\u3042\u308A\u307E\u3059\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u30DC\u30EA\u30E5\u30FC\u30E0\u3092\u62D2\u307F\u307E\u3059: has an invalid mount path\uFF09`;
11309
11372
  case "wildcard":
11310
- return `"mount" \u30D1\u30B9 "${mountPath}" \u306F\u9759\u7684\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 \u2014 \u30EF\u30A4\u30EB\u30C9\u30AB\u30FC\u30C9\u306F\u4F7F\u3048\u307E\u305B\u3093\uFF08runtime: must be static.\uFF09`;
11373
+ return `"mount" \u30D1\u30B9 "${mountPath}" \u306F\u9759\u7684\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 \u2014 "*" \u306F\u4F7F\u3048\u307E\u305B\u3093\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u30DC\u30EA\u30E5\u30FC\u30E0\u3092\u62D2\u307F\u307E\u3059: has an invalid mount path\uFF09`;
11374
+ case "whitespace":
11375
+ return `"mount" \u30D1\u30B9 "${mountPath}" \u306B\u7A7A\u767D\u306F\u4F7F\u3048\u307E\u305B\u3093\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u30DC\u30EA\u30E5\u30FC\u30E0\u3092\u62D2\u307F\u307E\u3059: has an invalid mount path\uFF09`;
11311
11376
  default:
11312
- return `"mount" \u30D1\u30B9 "${mountPath}" \u306B\u4E88\u7D04\u6587\u5B57\uFF08$, #, @\uFF09\u306F\u4F7F\u3048\u307E\u305B\u3093\uFF08runtime: must not use reserved characters.\uFF09`;
11377
+ return `"mount" \u30D1\u30B9 "${mountPath}" \u306B\u4E88\u7D04\u6587\u5B57\uFF08$, #, @\uFF09\u306F\u4F7F\u3048\u307E\u305B\u3093\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u30DC\u30EA\u30E5\u30FC\u30E0\u3092\u62D2\u307F\u307E\u3059: has an invalid mount path\uFF09`;
11313
11378
  }
11314
11379
  },
11315
11380
  recursionUnsupported: (p, where) => {
@@ -11331,7 +11396,7 @@ var ja = {
11331
11396
  case "listKeys":
11332
11397
  return `$listKeys \u306E\u30AD\u30FC "${p}" \u306B "**" \u306F\u4F7F\u3048\u307E\u305B\u3093\u3002\u30AD\u30FC\u4ED8\u304D\u30EA\u30B9\u30C8\u306F 1 \u672C\u306E\u5177\u4F53\u30EA\u30B9\u30C8\u30D1\u30B9\u3067\u3059 \u2014 \u6DF1\u3055\u3054\u3068\u306B\u5BA3\u8A00\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: "nodes.*.children"\uFF09`;
11333
11398
  default:
11334
- return `"${p}" \u306F "**" \u3092\u542B\u307F\u307E\u3059\u304C\u3001\u3053\u306E state \u306B\u306F $recursion \u5BA3\u8A00\u304C\u3042\u308A\u307E\u305B\u3093\u3002$recursion = { "<anchor>": "<repeat>" }\uFF08\u4F8B: { "nodes.*": "children.*" }\uFF09\u3092\u5BA3\u8A00\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u5BA3\u8A00\u304C\u7121\u3044\u3068 "**" \u306E\u30AD\u30FC\u306F\u9ED9\u3063\u3066\u7121\u8996\u3055\u308C\u307E\u3059\uFF09`;
11399
+ return `"${p}" \u306F "**" \u3092\u542B\u307F\u307E\u3059\u304C\u3001\u3053\u306E state \u306B\u306F $recursion \u5BA3\u8A00\u304C\u3042\u308A\u307E\u305B\u3093\u3002$recursion = { "<anchor>": "<repeat>" }\uFF08\u4F8B: { "nodes.*": "children.*" }\uFF09\u3092\u5BA3\u8A00\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u5BA3\u8A00\u304C\u7121\u3044\u3068\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u8AAD\u307F\u8FBC\u307F\u6642\u306B #1101 \u3067 throw \u3057\u3001state \u306F\u521D\u671F\u5316\u306B\u5931\u6557\u3057\u307E\u3059\uFF09`;
11335
11400
  }
11336
11401
  },
11337
11402
  recursionAnchorMismatch: (p, anchor) => `"${p}" \u306F\u5BA3\u8A00\u6E08\u307F\u306E\u518D\u5E30\u30A2\u30F3\u30AB\u30FC "${anchor}" \u3068\u5408\u81F4\u3057\u307E\u305B\u3093\uFF08\u521D\u7248\u306F state \u3054\u3068\u306B 1 \u3064\u306E\u81EA\u5DF1\u518D\u5E30\u306E\u307F\u3002"**" \u306E\u5F8C\u308D\u306F\u6574\u5F62\u3055\u308C\u305F\u63A5\u5C3E\u8F9E \u2014 2 \u3064\u76EE\u306E "**"\u30FB\u7A7A\u30BB\u30B0\u30E1\u30F3\u30C8\u30FB"**" \u76F4\u5F8C\u306E\u7D20\u306E "*" \u306F\u7F6E\u3051\u307E\u305B\u3093\uFF09`,
@@ -11452,15 +11517,15 @@ var en = {
11452
11517
  watchKeyEmptySegment: (k) => `$watch key "${k}" has an empty path segment`,
11453
11518
  watchHandlerNotFunction: (k) => `The value of $watch entry "${k}" must be a function`,
11454
11519
  watchPathMissing: (k) => `$watch key "${k}" does not exist in the state definition (it will never fire)`,
11455
- scanRemoved: (mountPath) => mountPath === null ? `$scan was removed in 4.0 (the runtime throws at load time). Fold a path's changes in a $watch handler, or events in an $on handler, and write the output property there` : `$scan was removed in 4.0. In a volume (mount="${mountPath}") the runtime refuses to graft it and reports that with console.error (this state is not on the tree). Fold in a $watch or $on handler on the root state`,
11520
+ scanRemoved: (mountPath) => mountPath === null ? `$scan was removed in 4.0 (the entries with the diagnostics add-on, such as /auto, throw at load; /core alone ignores it). Fold a path's changes in a $watch handler, or events in an $on handler, and write the output property there` : `$scan was removed in 4.0. In a volume (mount="${mountPath}") the runtime refuses to graft it and reports that with console.error (this state is not on the tree). Fold in a $watch or $on handler on the root state`,
11456
11521
  typeAnnotationIncompatible: (vt, rt) => `Type "${vt}" is not compatible with @type {${rt}}`,
11457
11522
  arrayMutation: (m, alt) => `Destructive array method "${m}" does not trigger a reactive update (re-assigning the same reference does not reflect added/removed elements either). Use a non-destructive method with reassignment (e.g. ${alt}).`,
11458
11523
  arrayIndexAssign: (sp) => `Assigning directly to an array index does not trigger a reactive update. Use a dot-path assignment like this["${sp}"], or with() plus reassignment.`,
11459
11524
  inPlaceAlias: (a, src, t) => `"${a}" is ${src} \u2014 the state's own value. A change through it does not trigger a reactive update, and writing the same value back does not add, remove or replace a list's rows. Build a new value and assign it to ${t} (${a}.with(i, item), [...${a}, item], { ...${a}, key: value })`,
11460
11525
  inPlaceChange: (src, t) => `${src} changes the state's value in place, which does not trigger a reactive update. Build a new value and assign it to ${t}`,
11461
- tagMemberUnknown: (prop, tag) => `"${prop}" is not a wcBindable member of <${tag}> (bindings to unknown members are silently ignored)`,
11526
+ tagMemberUnknown: (prop, tag) => `"${prop}" is not a wcBindable member of <${tag}> (the runtime refuses a binding to an undeclared member with #38; at the root the state fails to initialize)`,
11462
11527
  nameAlias: (written, canonical) => `"${written}" was removed in 4.0 (the 3.x old name of "${canonical}"; the runtime throws when it is read) \u2014 write "${canonical}"`,
11463
- declarationAliasRead: (alias, canonical) => `"${alias}" is a declaration key 4.0 removed (the 3.x old name of "${canonical}"), so this["${alias}"] is undefined. Read "${canonical}" instead`,
11528
+ declarationAliasRead: (alias, canonical) => `"${alias}" is a declaration key 4.0 removed (the 3.x old name of "${canonical}"), so this["${alias}"] is undefined. A declaration cannot be read through this \u2014 reading "${canonical}" is undefined too${canonical === "$stream" ? " (read a stream's state from $streamStatus / $streamError)" : ""}`,
11464
11529
  declarationAlias: (alias, canonical) => `The declaration key "${alias}" was removed in 4.0 (the 3.x old name of "${canonical}"; the runtime throws at load time) \u2014 write "${canonical}"`,
11465
11530
  declarationAliasInVolume: (alias, canonical, mountPath) => `The declaration key "${alias}" was removed in 4.0 (the 3.x old name of "${canonical}"). In a volume (mount="${mountPath}") the runtime refuses to graft it and reports that with console.error (this state is not on the tree). "${canonical}" cannot be declared in a volume either \u2014 declare it on the root state`,
11466
11531
  behaviorNotObject: (keys) => `$behavior must be an object { ${keys.map((k) => `${k}?`).join(", ")} } (the runtime throws at load time)`,
@@ -11490,7 +11555,7 @@ var en = {
11490
11555
  storagePairClobber: (path) => `The <wcs-storage> value is bound to the accessor pair "${path}" without #init=element. The state's side goes first, so on every load the getter's starting value is saved over the stored one, and the setter never receives it \u2014 add #init=element (\`value#init=element: ${path}\`)`,
11491
11556
  inputNestedWrite: (tag, input, path, example) => `"${path}" is bound to the input "${input}" of <${tag}>, but the page writes below it ("${example}"). A binding is re-applied only when "${path}" itself is assigned, so those writes never reach <${tag}> \u2014 bind a getter that reads the fields by path (\`this["${example}"]\`, \`$getAll\`) and returns a new value, or replace "${path}" instead of writing below it`,
11492
11557
  inputNestedWriteOneShot: (tag, input, path, example) => `"${path}" is bound to the input "${input}" of <${tag}>, but the page writes below it ("${example}"). A binding is re-applied only when "${path}" itself is assigned, and <${tag}> resets "${input}" to null after every request, so the next request goes without it \u2014 build a new object in the handler that starts the request (\`this.submitBody = { \u2026 }\`) and bind that`,
11493
- devtoolsAfterState: () => `Load @wcstack/devtools/auto BEFORE @wcstack/state/auto (otherwise the wiring ledger is not captured live)`,
11558
+ devtoolsAfterState: () => `Load @wcstack/devtools/auto before @wcstack/state/auto (loaded later, the DevTools timeline starts when it attaches; 4.0 sends it the wiring that is there already)`,
11494
11559
  baseHrefMissing: () => `An SPA using @wcstack/router needs <base href="/"> in <head> (without it, deep links misderive the basename)`,
11495
11560
  routerOutletMisplaced: () => `This <wcs-outlet> is not right after a <wcs-router>, so no router uses it: a router uses only the element right after it as its outlet, and makes an outlet of its own there when that is not a <wcs-outlet>. The routes render right after the router and this outlet stays empty \u2014 move it right after the <wcs-router>`,
11496
11561
  signalsDualEntry: () => `Both @wcstack/signals and @wcstack/signals/dom are imported on this page. On a CDN each entry is a self-contained bundle, so the reactive core is duplicated and reactivity breaks at the seam \u2014 import everything from the single /dom entry`,
@@ -11502,13 +11567,15 @@ var en = {
11502
11567
  mountPathInvalid: (problem, mountPath) => {
11503
11568
  switch (problem) {
11504
11569
  case "empty":
11505
- return `"mount" requires a non-empty tree path.`;
11570
+ return `"mount" needs a non-empty static path (the runtime refuses the volume: "has an invalid mount path").`;
11506
11571
  case "emptySegment":
11507
- return `"mount" path "${mountPath}" has an empty segment.`;
11572
+ return `"mount" path "${mountPath}" has an empty segment (the runtime refuses the volume: "has an invalid mount path").`;
11508
11573
  case "wildcard":
11509
- return `"mount" path "${mountPath}" must be static (wildcards are not allowed).`;
11574
+ return `"mount" path "${mountPath}" must be static \u2014 no "*" (the runtime refuses the volume: "has an invalid mount path").`;
11575
+ case "whitespace":
11576
+ return `"mount" path "${mountPath}" must not contain whitespace (the runtime refuses the volume: "has an invalid mount path").`;
11510
11577
  default:
11511
- return `"mount" path "${mountPath}" must not use reserved characters ($, #, @).`;
11578
+ return `"mount" path "${mountPath}" must not use the reserved characters $, #, @ (the runtime refuses the volume: "has an invalid mount path").`;
11512
11579
  }
11513
11580
  },
11514
11581
  recursionUnsupported: (p, where) => {
@@ -11530,7 +11597,7 @@ var en = {
11530
11597
  case "listKeys":
11531
11598
  return `$listKeys key "${p}" cannot contain "**" \u2014 a keyed list is one concrete list path. Declare the key per depth instead (for example "nodes.*.children")`;
11532
11599
  default:
11533
- return `"${p}" contains "**" but this state declares no $recursion anchor. Declare $recursion = { "<anchor>": "<repeat>" } (for example { "nodes.*": "children.*" }) \u2014 without it a "**" key is silently ignored`;
11600
+ return `"${p}" contains "**" but this state declares no $recursion anchor. Declare $recursion = { "<anchor>": "<repeat>" } (for example { "nodes.*": "children.*" }) \u2014 without it the runtime throws #1101 at load and the state fails to initialize`;
11534
11601
  }
11535
11602
  },
11536
11603
  recursionAnchorMismatch: (p, anchor) => `"${p}" does not match the declared recursion anchor "${anchor}" (this version supports exactly one self-recursive anchor per state, and "**" must be followed by a well-formed suffix: no second "**", no empty segment, no bare "*" right after "**")`,
@@ -11761,11 +11828,6 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale2, f
11761
11828
  const pathIndex = getStatePathIndex(html, stateTagName, fileReader);
11762
11829
  const statePaths = mergeSchemaCandidates(pathIndex.paths, applicationSchema);
11763
11830
  const attrs = findAllBindAttributes(html, attrName);
11764
- let structuralTemplates = null;
11765
- const getStructuralTemplates = () => {
11766
- structuralTemplates ??= collectStructuralTemplates(html, attrName);
11767
- return structuralTemplates;
11768
- };
11769
11831
  const outerCandidates = [];
11770
11832
  const currentTargetCandidates = [];
11771
11833
  let currentTargetHandlers = null;
@@ -11925,7 +11987,8 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale2, f
11925
11987
  start: pathStart,
11926
11988
  end: pathStart + tokenPath.length,
11927
11989
  message: msgs.commandRhsFormat(),
11928
- severity: "warning"
11990
+ // ランタイムは束縛の計画で #1201 として throw し、root では初期化が失敗する
11991
+ severity: "error"
11929
11992
  });
11930
11993
  } else if (commandNames.size > 0 && !commandNames.has(tokenPath)) {
11931
11994
  diagnostics.push({
@@ -11933,7 +11996,9 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale2, f
11933
11996
  start: pathStart,
11934
11997
  end: pathStart + tokenPath.length,
11935
11998
  message: msgs.commandTokenUndeclared(tokenPath),
11936
- severity: "warning"
11999
+ // ランタイムは取り付けで #1302 として throw し、root では初期化が失敗する
12000
+ // (eventToken. と `on*: $command.x` はイベントのたびに #1301 を記録するだけなので warning のまま)
12001
+ severity: "error"
11937
12002
  });
11938
12003
  }
11939
12004
  }
@@ -12103,10 +12168,7 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale2, f
12103
12168
  const typePath = candidateKeyOf(pathTrimmed, (c) => scopedPathSet.has(c));
12104
12169
  const resultType = resolveResultType(typePath, parsed.filters, scopedPaths);
12105
12170
  if (resultType !== null) {
12106
- const typeReq = getExpectedType(
12107
- parsed.property,
12108
- () => isNegatedByElseChain(getStructuralTemplates(), attr.valueStart)
12109
- );
12171
+ const typeReq = getExpectedType(parsed.property);
12110
12172
  if (typeReq && resultType !== typeReq.expected) {
12111
12173
  const pathOffset = binding.indexOf(parsed.path);
12112
12174
  const pathStart = bindingStart + pathOffset;
@@ -12264,14 +12326,16 @@ function validateFilterUsage(filter, bindingStart, msgs) {
12264
12326
  for (let i = 0; i < Math.min(argCount, info.argTypes.length); i++) {
12265
12327
  const expectedArgType = info.argTypes[i];
12266
12328
  if (expectedArgType === "any") continue;
12267
- const actualArgType = inferArgType(filter.args[i]);
12268
- if (actualArgType !== expectedArgType) {
12329
+ const arg = filter.args[i];
12330
+ const numericFails = expectedArgType === "number" && !readsAsNumber(arg);
12331
+ const actualArgType = inferArgType(arg);
12332
+ if (expectedArgType === "number" ? numericFails : actualArgType !== expectedArgType) {
12269
12333
  diagnostics.push({
12270
12334
  code: WcsDiagnosticCode.FilterArgType,
12271
12335
  start: bindingStart + filter.argsOffset,
12272
12336
  end: bindingStart + filter.argsOffset + filter.name.length,
12273
- message: msgs.filterArgType(filter.name, i + 1, expectedArgType, filter.args[i], actualArgType),
12274
- severity: "warning"
12337
+ message: msgs.filterArgType(filter.name, i + 1, expectedArgType, arg, actualArgType),
12338
+ severity: numericFails ? "error" : "warning"
12275
12339
  });
12276
12340
  }
12277
12341
  }
@@ -12336,57 +12400,11 @@ function validateSchemaPathExistence(checkPath, displayPath, scopedPaths, scoped
12336
12400
  }
12337
12401
  return null;
12338
12402
  }
12339
- function collectStructuralTemplates(html, attrName) {
12340
- const escaped = attrName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12341
- const attrRegex = new RegExp(`${escaped}\\s*=\\s*(["'])`, "i");
12342
- const tagRegex = /<template(?:\s[^>]*)?>|<\/template\s*>/gi;
12343
- const templates = [];
12344
- let depth = 0;
12345
- let match;
12346
- while ((match = tagRegex.exec(html)) !== null) {
12347
- if (match[0].startsWith("</")) {
12348
- depth = Math.max(0, depth - 1);
12349
- continue;
12350
- }
12351
- const attrMatch = attrRegex.exec(match[0]);
12352
- if (attrMatch) {
12353
- const quote = attrMatch[1];
12354
- const valueStart = match.index + attrMatch.index + attrMatch[0].length;
12355
- const valueEnd = html.indexOf(quote, valueStart);
12356
- if (valueEnd !== -1) {
12357
- const first = splitBindingExpressions(html.slice(valueStart, valueEnd))[0] ?? "";
12358
- const firstColon = indexOfOutsideQuotes2(first, ":");
12359
- const prop = (firstColon === -1 ? first : first.slice(0, firstColon)).replace(/#.*$/, "").trim();
12360
- const type = prop === "if" || prop === "elseif" || prop === "else" ? prop : "other";
12361
- templates.push({ valueStart, depth, type });
12362
- }
12363
- }
12364
- depth++;
12365
- }
12366
- return templates;
12367
- }
12368
- function isNegatedByElseChain(templates, valueStart) {
12369
- const index = templates.findIndex((t) => t.valueStart === valueStart);
12370
- if (index === -1) return false;
12371
- const selfDepth = templates[index].depth;
12372
- for (let i = index + 1; i < templates.length; i++) {
12373
- const next = templates[i];
12374
- if (next.depth > selfDepth) continue;
12375
- if (next.depth < selfDepth) return false;
12376
- if (next.type === "elseif" || next.type === "else") return true;
12377
- if (next.type === "if") return false;
12378
- }
12379
- return false;
12380
- }
12381
- function getExpectedType(property, isNegatedIf) {
12403
+ function getExpectedType(property) {
12382
12404
  const prop = property.replace(/#.*$/, "");
12383
12405
  if (prop === "for") {
12384
12406
  return { label: "for", expected: "array", severity: "error" };
12385
12407
  }
12386
- if (prop === "if" || prop === "elseif") {
12387
- if (!isNegatedIf()) return null;
12388
- return { label: prop, expected: "boolean", severity: "warning" };
12389
- }
12390
12408
  if (prop.startsWith("class.")) {
12391
12409
  return { label: prop, expected: "boolean", severity: "warning" };
12392
12410
  }
@@ -12442,6 +12460,10 @@ function inferArgType(arg) {
12442
12460
  if (/^-?\d+(\.\d+)?$/.test(v)) return "number";
12443
12461
  return "string";
12444
12462
  }
12463
+ function readsAsNumber(arg) {
12464
+ const v = arg.trim().replace(/^(["'])([\s\S]*)\1$/, "$2");
12465
+ return v !== "" && !Number.isNaN(Number(v));
12466
+ }
12445
12467
  function isLiteral(value) {
12446
12468
  return /^-?\d/.test(value) || /^["'`]/.test(value) || value === "true" || value === "false" || value === "null";
12447
12469
  }
@@ -14366,20 +14388,7 @@ var BUILTIN_TAGS = {
14366
14388
  };
14367
14389
 
14368
14390
  // src/service/ioNodeValidator.ts
14369
- var DOM_COMMON_PROPERTIES = /* @__PURE__ */ new Set([
14370
- "textContent",
14371
- "innerHTML",
14372
- "innerText",
14373
- "hidden",
14374
- "title",
14375
- "id",
14376
- "slot",
14377
- "dir",
14378
- "lang",
14379
- "role",
14380
- "tabIndex",
14381
- "className"
14382
- ]);
14391
+ var HTML_SINK_PROPERTIES = /* @__PURE__ */ new Set(["html", "innerHTML", "outerHTML", "srcdoc"]);
14383
14392
  var STRUCTURAL_DIRECTIVES3 = /* @__PURE__ */ new Set(["for", "if", "elseif", "else"]);
14384
14393
  var EXPLICIT_PROPERTY_REJECTED_HEADS2 = /* @__PURE__ */ new Set([
14385
14394
  ...Object.values(getWcsManifest().syntax.bindingTypes.propNamespaces),
@@ -14481,7 +14490,7 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
14481
14490
  code: WcsDiagnosticCode.TagMemberUnknown,
14482
14491
  start,
14483
14492
  end,
14484
- severity: "warning",
14493
+ severity: "error",
14485
14494
  tag: tagName,
14486
14495
  member: name,
14487
14496
  message: msgs.tagCommandUnknown(name, tagName, contract.commands.join(", ") || msgs.none()) + suggestion(name, contract.commands, msgs)
@@ -14496,7 +14505,7 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
14496
14505
  code: WcsDiagnosticCode.TagMemberUnknown,
14497
14506
  start,
14498
14507
  end,
14499
- severity: "warning",
14508
+ severity: "error",
14500
14509
  tag: tagName,
14501
14510
  member: name,
14502
14511
  message: msgs.tagEventTokenKeyUnknown(name, tagName, contract.properties.join(", ")) + suggestion(name, contract.properties, msgs)
@@ -14504,13 +14513,13 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
14504
14513
  }
14505
14514
  return;
14506
14515
  }
14507
- if (!contract.properties.includes(property) && !(property in contract.inputs) && !DOM_COMMON_PROPERTIES.has(property)) {
14516
+ if (!contract.properties.includes(property) && !(property in contract.inputs) && !HTML_SINK_PROPERTIES.has(property)) {
14508
14517
  const members = [...contract.properties, ...inputNames];
14509
14518
  diagnostics.push({
14510
14519
  code: WcsDiagnosticCode.TagMemberUnknown,
14511
14520
  start,
14512
14521
  end,
14513
- severity: "warning",
14522
+ severity: "error",
14514
14523
  tag: tagName,
14515
14524
  member: property,
14516
14525
  message: msgs.tagMemberUnknown(property, tagName) + suggestion(property, members, msgs)
@@ -14715,7 +14724,7 @@ function validateDocumentEnv(html, locale2) {
14715
14724
  code: WcsDiagnosticCode.ScriptOrder,
14716
14725
  start: later.start,
14717
14726
  end: later.end,
14718
- severity: "warning",
14727
+ severity: "info",
14719
14728
  message: msgs.devtoolsAfterState()
14720
14729
  });
14721
14730
  }
@@ -15411,7 +15420,7 @@ function validateRecursiveGetters(script, offset2, spec, undeclared, msgs, out)
15411
15420
  start,
15412
15421
  end,
15413
15422
  msgs.recursionUnsupported(span.name, "undeclared"),
15414
- "warning"
15423
+ "error"
15415
15424
  );
15416
15425
  }
15417
15426
  continue;
@@ -15935,7 +15944,8 @@ function findMountPathProblem(mountPath) {
15935
15944
  if (mountPath.length === 0) return "empty";
15936
15945
  for (const segment of mountPath.split(".")) {
15937
15946
  if (segment.length === 0) return "emptySegment";
15938
- if (segment === "*") return "wildcard";
15947
+ if (segment.includes("*")) return "wildcard";
15948
+ if (/\s/.test(segment)) return "whitespace";
15939
15949
  if (segment.includes("$") || segment.includes("#") || segment.includes("@")) return "reserved";
15940
15950
  }
15941
15951
  return null;
@@ -16307,7 +16317,7 @@ function validateIndexArity(script, scriptStart, locale2) {
16307
16317
  start: scriptStart + parsed.starts[1] + leading,
16308
16318
  end: scriptStart + parsed.starts[1] + argText.trimEnd().length,
16309
16319
  message: msgs.indexArity(api, path, requirement, wildcardCount, actual),
16310
- severity: "warning"
16320
+ severity: "error"
16311
16321
  });
16312
16322
  }
16313
16323
  return out;
@@ -16363,7 +16373,7 @@ function validateGetterCycles(script, scriptStart, locale2) {
16363
16373
  start: scriptStart + getter.start,
16364
16374
  end: scriptStart + getter.end,
16365
16375
  message: msgs.getterCycle(cycle),
16366
- severity: "warning"
16376
+ severity: "error"
16367
16377
  });
16368
16378
  }
16369
16379
  return out;
@@ -16475,7 +16485,7 @@ function validateInputNestedWrites(html, stateTagName, bindAttrName, nestedWrite
16475
16485
  code: WcsDiagnosticCode.InputNestedWrite,
16476
16486
  start: occ.pathRange.start,
16477
16487
  end: occ.pathRange.end,
16478
- severity: "warning",
16488
+ severity: "error",
16479
16489
  tag: tag.tagName,
16480
16490
  statePath: occ.path,
16481
16491
  message
@@ -16769,7 +16779,9 @@ function validateDocument(text3, options = {}) {
16769
16779
  for (const d of validateNestedAssigns(text3, stateTagName, locale2)) {
16770
16780
  out.push({ code: WcsDiagnosticCode.NestedAssign, start: d.start, end: d.end, message: d.message, severity: d.severity });
16771
16781
  }
16772
- return sortDiagnostics(out);
16782
+ const ignored = findIgnoredRanges(text3, bindAttribute);
16783
+ const kept = ignored.length === 0 ? out : out.filter((d) => !ignored.some(([start, end]) => d.start >= start && d.start < end));
16784
+ return sortDiagnostics(kept);
16773
16785
  }
16774
16786
  // Annotate the CommonJS export names for ESM import in node:
16775
16787
  0 && (module.exports = {
package/dist/tsc-core.cjs CHANGED
@@ -687,10 +687,11 @@ var builtinFilterMeta = {
687
687
  // `not` は真偽性(truthy / falsy)の反転。`if:` が `Boolean()` で寄せるのと同じ規則で、
688
688
  // `else:` はこのフィルタを足した束縛として組み立てられる(structural/createNotFilter.ts)
689
689
  not: { description: "\u771F\u507D\u6027\u3092\u53CD\u8EE2\uFF08falsy \u2192 true\uFF09", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
690
- lt: { description: "\u3088\u308A\u5C0F\u3055\u3044\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
691
- le: { description: "\u4EE5\u4E0B\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
692
- gt: { description: "\u3088\u308A\u5927\u304D\u3044\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
693
- ge: { description: "\u4EE5\u4E0A\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
690
+ // 比較は数値だけを受ける(filters/core.ts の `numeric` は数値以外の値で #28。3.x も同じで、"string" は誤りだった)
691
+ lt: { description: "\u3088\u308A\u5C0F\u3055\u3044\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
692
+ le: { description: "\u4EE5\u4E0B\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
693
+ gt: { description: "\u3088\u308A\u5927\u304D\u3044\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
694
+ ge: { description: "\u4EE5\u4E0A\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
694
695
  // 算術
695
696
  add: { description: "\u52A0\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
696
697
  sub: { description: "\u6E1B\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
@@ -573,7 +573,7 @@ function loadSchemaCore() {
573
573
  return cached;
574
574
  }
575
575
 
576
- var version = "4.2.0";
576
+ var version = "4.3.0";
577
577
  var pkg = {
578
578
  version: version};
579
579
 
package/dist/wcs-tsc.mjs CHANGED
@@ -5,7 +5,7 @@ import { tmpdir } from 'node:os';
5
5
  import { dirname, join, isAbsolute, resolve, basename } from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
7
 
8
- var version = "4.2.0";
8
+ var version = "4.3.0";
9
9
  var pkg = {
10
10
  version: version};
11
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/typescript",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "description": "TypeScript tooling for wcstack apps: wcs-schema generates the sidecar stateSchema from a typed state file, so wcs-validate checks data-wcs paths against real types in CI and every editor.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",