@wcstack/state 3.4.0 → 3.5.1
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 +60 -20
- package/README.md +60 -20
- package/dist/auto.min.js +1 -1
- package/dist/auto.min.js.map +1 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/split/chunks/binder.js +1 -1
- package/dist/split/chunks/binder.js.map +1 -1
- package/dist/split/chunks/declarationAliases.js.map +1 -1
- package/dist/split/chunks/filterRegistry.js.map +1 -1
- package/dist/split/chunks/lifecycleHooks.js +1 -1
- package/dist/split/chunks/lifecycleHooks.js.map +1 -1
- package/dist/split/chunks/registerComponents.js +1 -1
- package/dist/split/chunks/registerComponents.js.map +1 -1
- package/dist/split/chunks/version.js +1 -1
- package/dist/split/core.d.ts +23 -1
- package/dist/split/features/formats.js.map +1 -1
- package/dist/split/features/scopes.js +1 -1
- package/dist/split/features/scopes.js.map +1 -1
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> 🤖 **AI coding agents**: This README is a package-level reference, not the primary entry point for building a wcstack application. If you have not already done so, first read the repository [README](https://github.com/wcstack/wcstack#readme) and [AGENTS.md](https://github.com/wcstack/wcstack/blob/main/AGENTS.md), then use the [wcstack-app skill](https://github.com/wcstack/wcstack-skill).
|
|
4
4
|
|
|
5
|
+
> **4.0 への準備**: 4.0 はまだリリースされていません。何が変わり、3.x のうちに何ができるかは [3.x → 4.0 移行ガイド(プレビュー)](https://github.com/wcstack/wcstack/blob/main/docs/migration-v4.ja.md) にまとめています。
|
|
6
|
+
|
|
5
7
|
**これは便利な既存FWの別実装ではありません。パスがビューとモデルの契約になる——フロントエンドの外で確立した系譜を、Web標準の上に持ち込む試みです。**
|
|
6
8
|
|
|
7
9
|
多くのライブラリは、UI・状態・コンポーネントの結合点を JavaScript の中に置きます。`@wcstack/state` はそこを選びません。仮想DOMも、コンパイルも、hook も、selector も前提にせず、HTML とパス文字列だけを契約として UI と状態を結びつけます。
|
|
@@ -137,7 +139,7 @@
|
|
|
137
139
|
| **コンポーネント** | 排他的な 2 方式 — JavaScript クラス+`bind-component` か、HTML だけの DCC か | [機構の選び方](#コンポーネント機構の選び方) |
|
|
138
140
|
| **他要素との配線** | wc-bindable プロトコル、spread(`...: obj`)、`#init=` / `#sync=` の authority、プロパティ→属性ミラー | [バインディング authority](#バインディング-authority-init--sync) · [Spread](#spread-バインディング) · [Inputs](#inputs-と属性ミラー) |
|
|
139
141
|
| **トークン** | command token が state から要素のメソッドを呼び、event token が要素のイベントを state へ戻す | [Command token](#command-tokenメソッドバインディング) · [Event token](#event-tokenイベントバインディング) |
|
|
140
|
-
| **時間** | `$stream` が非同期ソースを fold し、`$watch` が headless に反応し、`$scan`
|
|
142
|
+
| **時間** | `$stream` が非同期ソースを fold し、`$watch` が headless に反応し、`$scan` が両者を越えて残る累積値を持つ(`$scan` は 3.5 で警告が出て 4.0 で外れる — [4.0 への準備](#40-への準備wcsv4-migration)) | [時間を扱う機構の選び方](#時間を扱う機構の選び方) |
|
|
141
143
|
| **初期化とライフサイクル** | state の供給は 6 通り。`$connectedCallback` 〜 `$stateReadyCallback`、`bootstrapState()` / `createState()` | [状態の初期化](#状態の初期化) · [ライフサイクルフック](#ライフサイクルフック) · [API リファレンス](#api-リファレンス) |
|
|
142
144
|
| **診断** | 解決しないパス・添字の本数・階数・getter の循環を報告する。失敗はそのバインディング 1 本に閉じ、値も DOM も巻き戻さない | [診断と失敗の扱い](#診断と失敗の扱い) |
|
|
143
145
|
| **配布** | ランタイム依存ゼロ、ビルド不要、ESM、CDN の `/auto` 1 タグ。`unsafe-eval` 不要で Trusted Types 対応 | [インストール](#インストール) · [docs/csp.ja.md](../../docs/csp.ja.md) |
|
|
@@ -186,15 +188,15 @@
|
|
|
186
188
|
<script type="importmap">
|
|
187
189
|
{
|
|
188
190
|
"imports": {
|
|
189
|
-
"@wcstack/state/core": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.
|
|
190
|
-
"@wcstack/state/features/temporal": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.
|
|
191
|
-
"@wcstack/state/features/scopes": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.
|
|
191
|
+
"@wcstack/state/core": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.5.1/dist/split/core.js",
|
|
192
|
+
"@wcstack/state/features/temporal": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.5.1/dist/split/features/temporal.js",
|
|
193
|
+
"@wcstack/state/features/scopes": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.5.1/dist/split/features/scopes.js"
|
|
192
194
|
}
|
|
193
195
|
}
|
|
194
196
|
</script>
|
|
195
197
|
<script type="module">
|
|
196
198
|
import { bootstrapState, installFeatures } from '@wcstack/state/core';
|
|
197
|
-
import temporal from '@wcstack/state/features/temporal'; // $watch / $scan
|
|
199
|
+
import temporal from '@wcstack/state/features/temporal'; // $watch / $stream($scan は 3.5 で警告、4.0 で外れる)
|
|
198
200
|
import scopes from '@wcstack/state/features/scopes'; // bind-component・mount=・DCC
|
|
199
201
|
|
|
200
202
|
installFeatures([temporal, scopes]);
|
|
@@ -218,7 +220,7 @@
|
|
|
218
220
|
| エントリ | 足されるもの |
|
|
219
221
|
|---|---|
|
|
220
222
|
| `@wcstack/state/core` | バインディングの本体: `data-wcs`・`for` / `if`・パス getter・フィルタ・イベント・`$command` / `$on`・`bootstrapState`・`installFeatures` |
|
|
221
|
-
| `@wcstack/state/features/temporal` | `$watch`・`$scan
|
|
223
|
+
| `@wcstack/state/features/temporal` | `$watch`・`$scan`(3.5 で警告、4.0 で外れる — [4.0 への準備](#40-への準備wcsv4-migration))・`$stream` |
|
|
222
224
|
| `@wcstack/state/features/scopes` | `bind-component`・`mount=` のボリューム・オーバーレイの公開 getter・DCC(`data-wc-definition`) |
|
|
223
225
|
| `@wcstack/state/features/recursion` | `$recursion` と `**` パス |
|
|
224
226
|
| `@wcstack/state/features/ssr` | `enable-ssr`: サーバー描画とハイドレーション |
|
|
@@ -328,7 +330,9 @@ install 時に埋める受け口を通ります)。
|
|
|
328
330
|
|
|
329
331
|
解決順序: `state` → `src` (.json / .js) → `json` → 内包 `<script>` → `setInitialState()` 待機。
|
|
330
332
|
|
|
331
|
-
|
|
333
|
+
5 番の `<script type="module">` はブラウザ自身も評価します(`<wcs-state>` の中にあっても止まりません)。export はどこにも届かないので state には影響しませんが、トップレベルのコードは 2 回走ります(ブラウザが 1 回、state が 1 回)。トップレベルに副作用(リクエスト・ログ出力・グローバルへの代入)を置かないでください。CSP 下では下の注記を参照してください。
|
|
334
|
+
|
|
335
|
+
> **Content-Security-Policy 下では:** 5 番(内包 `<script type="module">`)は `blob:` URL 経由で評価されるため、state を読み込む `<script>` にページの nonce を付けるか(blob: の import がその nonce を引き継ぎます)、`script-src blob:` が必要です。厳格な CSP を敷く場合は 4 番(`src="./state.js"`)を使ってください。追加ディレクティブは不要です。なお 5 番の `<script>` はブラウザ自身も評価します。CSP 下では、その `<script>` にも nonce を付けない限りコンソールに違反が 1 件出ます。nonce を付けた場合や CSP が無い場合は、トップレベルのコードが 2 回走ります(副作用を置かないこと)。詳細は [docs/csp.ja.md](../../docs/csp.ja.md)。
|
|
332
336
|
|
|
333
337
|
### 追加の状態をマウントする(`mount=`)
|
|
334
338
|
|
|
@@ -1568,7 +1572,7 @@ export default {
|
|
|
1568
1572
|
| `capitalize`(`cap`) | 先頭大文字 | `name\|capitalize` |
|
|
1569
1573
|
| `trim` | 空白除去 | `text\|trim` |
|
|
1570
1574
|
| `slice(n)` | 文字列スライス | `text\|slice(5)` |
|
|
1571
|
-
| `substr(start, length)` | 部分文字列(引数は 2
|
|
1575
|
+
| `substr(start, length)` | 部分文字列(引数は 2 つとも必須)。3.5 で警告が出て 4.0 で外れる: `slice(start, start + length)` と書く — [4.0 への準備](#40-への準備wcsv4-migration) | `text\|substr(0,10)` |
|
|
1572
1576
|
| `padStart(n, char?)`(`pad`) | 先頭を埋める(既定 `0`) | `id\|padStart(5,0)` → `"00001"` |
|
|
1573
1577
|
| `padEnd(n, char?)` | 末尾を埋める(既定は空白。3.2) | `code\|padEnd(8)` |
|
|
1574
1578
|
| `repeat(n)`(`rep`) | 繰り返し | `text\|repeat(3)` |
|
|
@@ -2185,7 +2189,7 @@ event token は command token と同じ `Token` pub/sub プリミティブを共
|
|
|
2185
2189
|
| [パス getter](#パス-getter算出プロパティ) | その値が現在の state から見て**何であるか** | 持たない(アドレス単位で再計算・キャッシュ) | 評価需要が読んだときに遅延評価 | 小計、分類、集計 |
|
|
2186
2190
|
| [`$stream`](#streamstream) | 非同期の供給元と、**1 回の実行の中で** fold される値 | 持つ(出力は runtime の所有) | chunk ごと。`args` が変われば `initial` に戻して restart | フィード、ソケット、継続的な観測 |
|
|
2187
2191
|
| [`$watch`](#watchwatch) | 変更への反応 | 持たない | 変化したアドレスごとにバッチ 1 回、scan の書き込みの後 | 副作用、「条件が成立したとき」 |
|
|
2188
|
-
| [`$scan`](#scanscan) | 時間をまたぐ累積値と、それを戻す条件 | 持つ(出力は runtime の所有) | 着地ごと(`from`)またはイベントごと(`on`) |
|
|
2192
|
+
| [`$scan`](#scanscan) | 時間をまたぐ累積値と、それを戻す条件 | 持つ(出力は runtime の所有) | 着地ごと(`from`)またはイベントごと(`on`) | ページ蓄積、履歴、件数。3.5 で警告が出て 4.0 で外れる: `$watch`(state のパス)か `$on`(イベントトークン)で畳む — [4.0 への準備](#40-への準備wcsv4-migration) |
|
|
2189
2193
|
|
|
2190
2194
|
混乱のほとんどは、次の 2 点で解けます。
|
|
2191
2195
|
|
|
@@ -2308,9 +2312,9 @@ $renderedCallback(paths) {
|
|
|
2308
2312
|
}
|
|
2309
2313
|
```
|
|
2310
2314
|
|
|
2311
|
-
**規則:** 描画に依存させたくないロジックは、`$watch`・`$scan`・`$stream` の `args` のどれかに根を置いてください。`$renderedCallback`
|
|
2315
|
+
**規則:** 描画に依存させたくないロジックは、`$watch`・`$scan`・`$stream` の `args` のどれかに根を置いてください。`$renderedCallback` は「描かれたものに追随する」用途に限ります。(`$scan` は 3.5 で警告が出て 4.0 で外れます。同じことは `$watch` か `$on` のハンドラで書けます — [4.0 への準備](#40-への準備wcsv4-migration)。)
|
|
2312
2316
|
|
|
2313
|
-
上の例はいまは `$
|
|
2317
|
+
上の例はいまは stream の値に付けた `$watch` で着地したページを feed へ畳み(sentinel の再武装は feed の `$watch`)、`<b>` は表示専用に戻っています。この形(`$renderedCallback` が、どのバインディングにも現れないパスを判定に使っている)は **`wcs/updated-callback-unbound`** として静的に検出されます。
|
|
2314
2318
|
|
|
2315
2319
|
### 残る制約
|
|
2316
2320
|
|
|
@@ -2385,6 +2389,8 @@ $renderedCallback(paths) {
|
|
|
2385
2389
|
|
|
2386
2390
|
## Scan(`$scan`)
|
|
2387
2391
|
|
|
2392
|
+
> **`$scan` は 3.5 で警告が出て、4.0 で外れます。** state のパスは累積値を書く `$watch` のハンドラで、イベントトークンは `$on` のハンドラで畳み、reset の条件もハンドラに書いてください。[4.0 への準備](#40-への準備wcsv4-migration)を参照。
|
|
2393
|
+
|
|
2388
2394
|
`$stream` が畳むのは 1 回の run の**内側**で、restart のたびに値は `initial` へ戻ります。`$watch` は値を所有しません。**`$scan`** はその両方を跨いで残る値 —— 時間軸方向の累積 —— を、持ち主・発火単位・reset 条件つきで宣言します。
|
|
2389
2395
|
|
|
2390
2396
|
```html
|
|
@@ -2843,6 +2849,39 @@ this.$getAll("matrix.*.*", [row]);
|
|
|
2843
2849
|
| 描画中の書き込みの連鎖 | 100 | そのバッチのバインディング適用をスキップ |
|
|
2844
2850
|
| バインディングの適用失敗 | — | その 1 本のみスキップ |
|
|
2845
2851
|
|
|
2852
|
+
### 4.0 への準備(`wcs/v4-migration`)
|
|
2853
|
+
|
|
2854
|
+
3.5 は 3.x の最後の minor です。4.0 が外す・移す名前と設定を名指しで知らせ、動きは 3.x のままにします。警告はコード `wcs/v4-migration` の `console.warn` で、名前ごとにページで 1 回だけ出ます。4.0 での扱いと書き換え先を示します:
|
|
2855
|
+
|
|
2856
|
+
```
|
|
2857
|
+
[@wcstack/state] [wcs/v4-migration] filter "uc" is removed in 4.0: write "upper" (its name since 3.2).
|
|
2858
|
+
See "Preparing for 4.0" in the @wcstack/state README.
|
|
2859
|
+
```
|
|
2860
|
+
|
|
2861
|
+
| 書き方 | 3.x | 4.0 | 書き換え先 |
|
|
2862
|
+
|---|---|---|---|
|
|
2863
|
+
| 3.2 で改名したフィルタの旧名: `inc` `dec` `fix` `uc` `lc` `cap` `rep` `rev` `pad` `null` | エイリアス | `[wcs/filter-unknown]` | `add` `sub` `toFixed` `upper` `lower` `capitalize` `repeat` `reverse` `padStart` `nullIfEmpty` |
|
|
2864
|
+
| `$trackDependency` / `$untrackDependency` | エイリアス | `[wcs/name-alias]` を投げる | `$dependOn` / `$untracked` |
|
|
2865
|
+
| `$updatedCallback` / `$streams` | エイリアス | `[wcs/declaration-alias]` を投げる | `$renderedCallback` / `$stream` |
|
|
2866
|
+
| `substr(start, length)` | 動く | `[wcs/filter-unknown]` | `slice(start, start + length)`(第 2 引数は長さではなく終わりの位置) |
|
|
2867
|
+
| `$scan` | 動く | 投げる | state のパスは `$watch`、イベントトークンは `$on` |
|
|
2868
|
+
| `bootstrapState({ debug })`・`commentTextPrefix`・`enablePropagationContext` | 動く | 投げる | 消す。4.0 のコメント束縛は `<!--@@: path-->` と `<!--@@wcs-text: path-->` だけ |
|
|
2869
|
+
| `bootstrapState({ enableMustache })`・`sameValueGuard`・`enableDirectionalInitialSync` | ページ全体の設定 | 投げる。state の木ごとに `$behavior` で宣言する | 3.x の間はそのまま。上げるときに、ルートとコンポーネントの各 state の `$behavior` へ移す(コンポーネントはホストのものを継がない。ボリュームには書けない) |
|
|
2870
|
+
| `bootstrapState` の知らないキー・型の違う値(`null`、配列、文字列でないタグ名、`state` / `ssr` 以外の `tagNames` のキー) | 無視 | 投げる | 消すか直す |
|
|
2871
|
+
| state のキー `$behavior` | ただのデータ(3.x は読まない) | その state の振る舞いの設定 | 3.x が動かしている設定と値が違うとき、4.0 が投げる形のときだけ警告 |
|
|
2872
|
+
| state のキー `$features` | ただのデータ | その state が要る後付け | 4.0 が投げる形(後付けの名前の配列でない)のときだけ警告 |
|
|
2873
|
+
| `$watch`・`$listKeys`・`$renderedCallback`(`$updatedCallback`)を宣言したボリューム(`<wcs-state mount>`) | マウントパスに相対で動く | 接ぎ木しない(`console.error`) | ルートの state へ移し、パスを絶対にする |
|
|
2874
|
+
| ルートのパスを注入するボリューム(`data-wcs="state.<key>: …"`) | 動く(3.1) | 接ぎ木しない(`console.error`) | ルートの getter でルートのパスを読む |
|
|
2875
|
+
| `$behavior` / `$features` を宣言したボリューム | ただのデータとして接ぎ木 | 接ぎ木しない(`console.error`) | ルートの state に書く |
|
|
2876
|
+
|
|
2877
|
+
出る時点: 宣言キーの旧名・`$scan`・`$behavior`・`$features` は state オブジェクトを読み込んだとき(ボリュームは接ぎ木したとき)、フィルタの旧名と `substr` はそれを使うバインディングを組み立てたとき、`bootstrapState` の設定は `bootstrapState()` を呼んだとき、`$trackDependency` / `$untrackDependency` はそれを読んだとき。検査は旧い書き方を解決する箇所にあるので、正式名で書いたページの動きは何も変わりません。実行するものの差は、フィルタを組み立てるときと `$dependOn` / `$untracked` を読むときの比較 1 つずつで、計測できる差はありません。
|
|
2878
|
+
|
|
2879
|
+
警告は全部入りの入口(`@wcstack/state` と `/auto`)だけが持ちます。分割の入口(`@wcstack/state/core` と `features/*`)のページには出ません。それ以外の切り替えはありません(2.6 と同じ)。警告は旧い書き方に実際に届いた経路でだけ出るので、コンソールが静かでも、ページが通らなかった経路については何も分かりません。`npx @wcstack/lint <file>` と VS Code 拡張は旧名を静的に報告します(`wcs/name-alias`、info、3.2 から)。
|
|
2880
|
+
|
|
2881
|
+
`$behavior` へ移る 3 つの設定は、ページが渡している間は警告が出続けます。3.x はこの設定を `bootstrapState` からしか読まないので、上げる前に変えるところはありません。`$behavior` を先に書いても害はなく、3.x が動かしている設定と照らし合わせて検査されます。4.0 の規則のうち 1 つは 3.5 で警告しません: 再セット(初期化済みの要素への `setInitialState()`)で `$behavior` を変えることはできず、4.0 は投げます(#45)。要素を作り直してください。
|
|
2882
|
+
|
|
2883
|
+
`on*#direct:` は 3.x でもう書けます。4.0 は `on*:` をルートへ委譲し、要素に直接付ける修飾子 `#direct` を足します。3.x はどの `on*:` も要素に付け、`#direct` は何も言わずに受け取ります。要素に付くことが要る束縛には今から書いておけます: `onclick#direct,stop:` は祖先に付けた自前のリスナーを止め、祖先が `stopPropagation()` してもハンドラは呼ばれます。
|
|
2884
|
+
|
|
2846
2885
|
## 設定
|
|
2847
2886
|
|
|
2848
2887
|
`bootstrapState()` に部分的な設定オブジェクトを渡します:
|
|
@@ -2852,8 +2891,7 @@ import { bootstrapState } from '@wcstack/state';
|
|
|
2852
2891
|
|
|
2853
2892
|
bootstrapState({
|
|
2854
2893
|
locale: 'ja-JP',
|
|
2855
|
-
|
|
2856
|
-
enableMustache: false,
|
|
2894
|
+
bindAttributeName: 'data-wcs',
|
|
2857
2895
|
tagNames: { state: 'my-state' },
|
|
2858
2896
|
});
|
|
2859
2897
|
```
|
|
@@ -2866,12 +2904,14 @@ bootstrapState({
|
|
|
2866
2904
|
| `tagNames.state` | `'wcs-state'` | 状態要素のタグ名 |
|
|
2867
2905
|
| `tagNames.ssr` | `'wcs-ssr'` | SSR ハイドレーションデータ要素のタグ名 |
|
|
2868
2906
|
| `locale` | `<html lang>`、無ければ `'en'` | ロケール依存フィルタ(`locale` / `date` / `time` / `datetime`)のロケール — [ロケール](#ロケール)を参照 |
|
|
2869
|
-
| `debug` | `false` |
|
|
2870
|
-
| `enableMustache` | `true` | `{{ }}`
|
|
2871
|
-
| `enableDirectionalInitialSync` | `true` | 方向認識のバインディング authority(`#init=` / `#sync=` バインド modifier)— [バインディング authority](#バインディング-authority-init--sync) 参照。既定 on。`false` で opt-out |
|
|
2872
|
-
| `enablePropagationContext` | `true` | バインド間の因果伝播トラッキング(echo/diamond のループ防止)。既定 on。`false` で opt-out |
|
|
2907
|
+
| `debug` | `false` | デバッグモード。4.0 で外れる(3.5 は警告) |
|
|
2908
|
+
| `enableMustache` | `true` | `{{ }}` 構文の有効化。4.0 で state の `$behavior` へ移る(3.5 は警告) |
|
|
2909
|
+
| `enableDirectionalInitialSync` | `true` | 方向認識のバインディング authority(`#init=` / `#sync=` バインド modifier)— [バインディング authority](#バインディング-authority-init--sync) 参照。既定 on。`false` で opt-out。4.0 で state の `$behavior` へ移る(3.5 は警告) |
|
|
2910
|
+
| `enablePropagationContext` | `true` | バインド間の因果伝播トラッキング(echo/diamond のループ防止)。既定 on。`false` で opt-out。4.0 で外れる(3.5 は警告) |
|
|
2873
2911
|
| `enableContractAnalyzer` | `false` | opt-in の開発時 contract analyzer(`analyzeContract` を公開) |
|
|
2874
|
-
| `sameValueGuard` | `true` | 現在値と `Object.is` で同値なプリミティブ書き込みを enqueue 前に落とす — バインディングと `$watch` は実質「変化時のみ」発火する(参照型は常に通す)。`false` で同値書き込みを通し、`$watch` の `prev` は `undefined`
|
|
2912
|
+
| `sameValueGuard` | `true` | 現在値と `Object.is` で同値なプリミティブ書き込みを enqueue 前に落とす — バインディングと `$watch` は実質「変化時のみ」発火する(参照型は常に通す)。`false` で同値書き込みを通し、`$watch` の `prev` は `undefined` になる。4.0 で state の `$behavior` へ移る(3.5 は警告) |
|
|
2913
|
+
|
|
2914
|
+
4.0 は `debug`・`commentTextPrefix`・`enablePropagationContext` を外し、`enableMustache`・`enableDirectionalInitialSync`・`sameValueGuard` を state の `$behavior` へ移します。3.5 はページがこれらを渡すと警告します — [4.0 への準備](#40-への準備wcsv4-migration)を参照。
|
|
2875
2915
|
|
|
2876
2916
|
### ロケール
|
|
2877
2917
|
|
|
@@ -3102,7 +3142,7 @@ bootstrapState();
|
|
|
3102
3142
|
| 属性 | 説明 |
|
|
3103
3143
|
|---|---|
|
|
3104
3144
|
| `mount` | この state をルートツリーへ**ボリューム**として接ぎ木する静的ツリーパス(v2 — 撤去された `name` 属性の後継。ツリーは 1 root に 1 本) |
|
|
3105
|
-
| `state` | `<script type="application/json">` 要素の ID |
|
|
3145
|
+
| `state` | document 内の `<script type="application/json">` 要素の ID(`document.getElementById` で探すので、shadow root の中の script は見つかりません) |
|
|
3106
3146
|
| `src` | `.json` または `.js` ファイルの URL |
|
|
3107
3147
|
| `json` | インライン JSON 文字列 |
|
|
3108
3148
|
| `bind-component` | Web Component バインディングのプロパティ名 |
|
|
@@ -3113,7 +3153,7 @@ bootstrapState();
|
|
|
3113
3153
|
| プロパティ / メソッド | 説明 |
|
|
3114
3154
|
|---|---|
|
|
3115
3155
|
| `initializePromise` | 状態の完全な初期化時に解決される Promise —— **初期化に失敗したときも解決**します(1 要素の失敗がページの他のバインディングを止めないため)。エラーは `connectedCallbackPromise` に届きます |
|
|
3116
|
-
| `connectedCallbackPromise` | `connectedCallback` の完了(state のロードと `$connectedCallback` の実行)で解決される Promise — テストのレシピが await するもの。**ルート**要素が初期化に失敗すると、**元のエラーのまま reject** し、`console.error` にも 1 件報告します(`$` 宣言の不正・ソースのロード失敗・SSR データの merge 失敗・DCC や `bind-component` の設定エラー・同じ root node に 2 本目のルート `<wcs-state>`。2 本目は登録されないまま読み込んだ state を保持するので取り除いてください。健全な要素の DOM
|
|
3156
|
+
| `connectedCallbackPromise` | `connectedCallback` の完了(state のロードと `$connectedCallback` の実行)で解決される Promise — テストのレシピが await するもの。**ルート**要素が初期化に失敗すると、**元のエラーのまま reject** し、`console.error` にも 1 件報告します(`$` 宣言の不正・ソースのロード失敗・SSR データの merge 失敗・DCC や `bind-component` の設定エラー・同じ root node に 2 本目のルート `<wcs-state>`。2 本目は登録されないまま読み込んだ state を保持するので取り除いてください。健全な要素の DOM 移動は二重登録ではなく、拒否しません)。ただし 3.x では次の 2 つのソースを失敗として扱わず、この Promise を解決します: 取得またはパースできない `src="*.json"`(URL と、HTTP ステータスまたはエラーを `console.error` に記録し、空の state で始まります。ボリュームなら `{}` を接ぎ木します)と、その id の `<script type="application/json">` が document に無い `state="<id>"`(`console.warn` を 1 回出し、空の state で始まります。探すのは `document.getElementById` なので、shadow root の中の script は見つかりません)。4.0 はどちらの場合も reject します。`state=` については要素自身のルートを先に、次に document を探し、どちらにも無いときだけ reject します。**ボリューム**(`<wcs-state mount="…">`)はこの Promise を**拒否しません** —— ボリュームの失敗は解決し、種類によっては自分では何も報告しません。その場合エラーはカスタム要素リアクションが捨てる `connectedCallback` の戻り Promise として出ていき、ブラウザのコンソールには "Uncaught (in promise)" と出ますが、promise を待つ側(テストのレシピや `renderToString()`)には届きません。ロード中に切断された要素は reject しません —— その接続が黙って終わるだけで、付け直せば(行プール)通常どおり初期化して解決します。個々の失敗箇所の正確な挙動は `__tests__/integration.initFailureDiagnostics.test.ts` が固定しています |
|
|
3117
3157
|
| `listPaths` | `for` ループで使用されるパスの Set |
|
|
3118
3158
|
| `getterPaths` | getter として定義されたパスの Set |
|
|
3119
3159
|
| `setterPaths` | setter として定義されたパスの Set |
|
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> 🤖 **AI coding agents**: This README is a package-level reference, not the primary entry point for building a wcstack application. If you have not already done so, first read the repository [README](https://github.com/wcstack/wcstack#readme) and [AGENTS.md](https://github.com/wcstack/wcstack/blob/main/AGENTS.md), then use the [wcstack-app skill](https://github.com/wcstack/wcstack-skill).
|
|
4
4
|
|
|
5
|
+
> **Preparing for 4.0**: 4.0 is not released yet. What changes, and what you can already do on 3.x, is in the [3.x → 4.0 migration guide (preview)](https://github.com/wcstack/wcstack/blob/main/docs/migration-v4.md).
|
|
6
|
+
|
|
5
7
|
**This is not another convenient frontend framework. It brings a lineage established outside frontend development — the one where a path string is the contract between view and model — onto web standards.**
|
|
6
8
|
|
|
7
9
|
Most libraries place the coupling point between UI, state, and components inside JavaScript. `@wcstack/state` does not. It assumes no virtual DOM, no compilation step, no hooks, no selectors. UI and state are connected by HTML and path strings alone.
|
|
@@ -137,7 +139,7 @@ Every row is a section of this README. Unless it appears under [Where the neighb
|
|
|
137
139
|
| **Components** | Two mutually exclusive mechanisms: a JavaScript class with `bind-component`, or HTML-only DCC | [Choosing a mechanism](#choosing-a-component-mechanism) |
|
|
138
140
|
| **Wiring to other elements** | The wc-bindable protocol, spread (`...: obj`), `#init=` / `#sync=` authority, property-to-attribute mirroring | [Binding authority](#binding-authority-init--sync) · [Spread](#spread-binding) · [Inputs](#inputs-and-attribute-mirror) |
|
|
139
141
|
| **Tokens** | Command tokens call an element's methods from state; event tokens carry the element's events back | [Command token](#command-token-method-binding) · [Event token](#event-token-event-binding) |
|
|
140
|
-
| **Time** | `$stream` folds an async source, `$watch` reacts headlessly, `$scan` owns an accumulation that outlives both | [Choosing a time mechanism](#choosing-a-time-mechanism) |
|
|
142
|
+
| **Time** | `$stream` folds an async source, `$watch` reacts headlessly, `$scan` owns an accumulation that outlives both (`$scan` warns in 3.5 and is removed in 4.0 — [Preparing for 4.0](#preparing-for-40-wcsv4-migration)) | [Choosing a time mechanism](#choosing-a-time-mechanism) |
|
|
141
143
|
| **Initialization and lifecycle** | Six ways to supply the state; `$connectedCallback` … `$stateReadyCallback`; `bootstrapState()` / `createState()` | [State initialization](#state-initialization) · [Lifecycle hooks](#lifecycle-hooks) · [API reference](#api-reference) |
|
|
142
144
|
| **Diagnostics** | Unresolved paths, index arity, wildcard rank and getter cycles are reported; one failing binding stays confined, and neither values nor the DOM are rolled back | [Diagnostics](#diagnostics-and-failure-handling) |
|
|
143
145
|
| **Delivery** | Zero runtime dependencies, no build step, ESM, one CDN `/auto` tag; no `unsafe-eval`, Trusted Types supported | [Installation](#installation) · [docs/csp.md](../../docs/csp.md) |
|
|
@@ -187,15 +189,15 @@ leaves features out, it can compose them instead:
|
|
|
187
189
|
<script type="importmap">
|
|
188
190
|
{
|
|
189
191
|
"imports": {
|
|
190
|
-
"@wcstack/state/core": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.
|
|
191
|
-
"@wcstack/state/features/temporal": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.
|
|
192
|
-
"@wcstack/state/features/scopes": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.
|
|
192
|
+
"@wcstack/state/core": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.5.1/dist/split/core.js",
|
|
193
|
+
"@wcstack/state/features/temporal": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.5.1/dist/split/features/temporal.js",
|
|
194
|
+
"@wcstack/state/features/scopes": "https://cdn.jsdelivr.net/npm/@wcstack/state@3.5.1/dist/split/features/scopes.js"
|
|
193
195
|
}
|
|
194
196
|
}
|
|
195
197
|
</script>
|
|
196
198
|
<script type="module">
|
|
197
199
|
import { bootstrapState, installFeatures } from '@wcstack/state/core';
|
|
198
|
-
import temporal from '@wcstack/state/features/temporal'; // $watch / $scan
|
|
200
|
+
import temporal from '@wcstack/state/features/temporal'; // $watch / $stream (and $scan: warns in 3.5, removed in 4.0)
|
|
199
201
|
import scopes from '@wcstack/state/features/scopes'; // bind-component, mount=, DCC
|
|
200
202
|
|
|
201
203
|
installFeatures([temporal, scopes]);
|
|
@@ -220,7 +222,7 @@ so the browser evaluates the engine once. Integrity for this form: [docs/sri.md
|
|
|
220
222
|
| Entry | What it adds |
|
|
221
223
|
|---|---|
|
|
222
224
|
| `@wcstack/state/core` | The binding engine: `data-wcs`, `for` / `if`, path getters, filters, events, `$command` / `$on`, `bootstrapState`, `installFeatures` |
|
|
223
|
-
| `@wcstack/state/features/temporal` | `$watch`, `$scan
|
|
225
|
+
| `@wcstack/state/features/temporal` | `$watch`, `$scan` (warns in 3.5, removed in 4.0 — [Preparing for 4.0](#preparing-for-40-wcsv4-migration)), `$stream` |
|
|
224
226
|
| `@wcstack/state/features/scopes` | `bind-component`, `mount=` volumes, overlay exports, DCC (`data-wc-definition`) |
|
|
225
227
|
| `@wcstack/state/features/recursion` | `$recursion` and `**` paths |
|
|
226
228
|
| `@wcstack/state/features/ssr` | `enable-ssr`: server rendering and hydration |
|
|
@@ -330,7 +332,9 @@ a feature never carries a second copy of the engine, and never a copy of another
|
|
|
330
332
|
|
|
331
333
|
Resolution order: `state` → `src` (.json / .js) → `json` → inner `<script>` → wait for `setInitialState()`.
|
|
332
334
|
|
|
333
|
-
|
|
335
|
+
The browser also evaluates form 5's `<script type="module">` itself — being inside `<wcs-state>` does not stop it. Its export goes nowhere, so the state is unaffected, but its top-level code runs twice (once by the browser, once by state). Keep side effects (requests, logging, assignments to globals) out of the top level; under a CSP, see the note below.
|
|
336
|
+
|
|
337
|
+
> **Under a Content-Security-Policy:** form 5 (inline `<script type="module">`) is evaluated through a `blob:` URL and therefore requires either the page's nonce on the `<script>` that loads state (the blob: import inherits it) or `script-src blob:`. If you enforce a strict CSP, use form 4 (`src="./state.js"`) instead — it needs no extra directive. Note that the browser evaluates form 5's `<script>` itself as well: under a CSP that shows up as one violation in the console unless that `<script>` carries the nonce too, and otherwise (with that nonce, or with no CSP) its top-level code runs twice — keep side effects out of it. See [docs/csp.md](../../docs/csp.md).
|
|
334
338
|
|
|
335
339
|
### Mounting Additional State (`mount=`)
|
|
336
340
|
|
|
@@ -1571,7 +1575,7 @@ export default {
|
|
|
1571
1575
|
| `capitalize` (`cap`) | Capitalize | `name\|capitalize` |
|
|
1572
1576
|
| `trim` | Trim whitespace | `text\|trim` |
|
|
1573
1577
|
| `slice(n)` | Slice string | `text\|slice(5)` |
|
|
1574
|
-
| `substr(start, length)` | Substring (both arguments required) | `text\|substr(0,10)` |
|
|
1578
|
+
| `substr(start, length)` | Substring (both arguments required). Warns in 3.5 and is removed in 4.0: write `slice(start, start + length)` — [Preparing for 4.0](#preparing-for-40-wcsv4-migration) | `text\|substr(0,10)` |
|
|
1575
1579
|
| `padStart(n, char?)` (`pad`) | Pad the start (default `0`) | `id\|padStart(5,0)` → `"00001"` |
|
|
1576
1580
|
| `padEnd(n, char?)` | Pad the end (default a space; 3.2) | `code\|padEnd(8)` |
|
|
1577
1581
|
| `repeat(n)` (`rep`) | Repeat | `text\|repeat(3)` |
|
|
@@ -2191,7 +2195,7 @@ The next four sections answer four different questions, and the usual mistake is
|
|
|
2191
2195
|
| [Path getter](#path-getters-computed-properties) | What a value **is**, in terms of the current state | No — it is recomputed and cached per address | Lazily, when a demand root reads it | Subtotals, classification, aggregates |
|
|
2192
2196
|
| [`$stream`](#streams-stream) | An async producer, and the value folded **within one run** | Yes — the runtime owns the output | Per chunk; restarts, back to `initial`, when `args` change | Feeds, sockets, continuous observation |
|
|
2193
2197
|
| [`$watch`](#watch-watch) | A reaction to a change | No | Once per batch per changed address, after the scan write | Side effects, "when this becomes true" |
|
|
2194
|
-
| [`$scan`](#scan-scan) | An accumulation over time, and what resets it | Yes — the runtime owns the output | Once per landing (`from`) or once per event (`on`) | Paging accumulation, history, counters |
|
|
2198
|
+
| [`$scan`](#scan-scan) | An accumulation over time, and what resets it | Yes — the runtime owns the output | Once per landing (`from`) or once per event (`on`) | Paging accumulation, history, counters. Warns in 3.5 and is removed in 4.0: fold in a `$watch` (state paths) or `$on` (event tokens) — [Preparing for 4.0](#preparing-for-40-wcsv4-migration) |
|
|
2195
2199
|
|
|
2196
2200
|
Two rules cut most of the confusion:
|
|
2197
2201
|
|
|
@@ -2314,9 +2318,9 @@ $renderedCallback(paths) {
|
|
|
2314
2318
|
}
|
|
2315
2319
|
```
|
|
2316
2320
|
|
|
2317
|
-
**The rule:** logic that must not depend on what is rendered belongs on a `$watch`, a `$scan`, or a `$stream` `args`. Keep `$renderedCallback` for "follow what was drawn".
|
|
2321
|
+
**The rule:** logic that must not depend on what is rendered belongs on a `$watch`, a `$scan`, or a `$stream` `args`. Keep `$renderedCallback` for "follow what was drawn". (`$scan` warns in 3.5 and is removed in 4.0; a `$watch` or an `$on` handler covers the same ground — [Preparing for 4.0](#preparing-for-40-wcsv4-migration).)
|
|
2318
2322
|
|
|
2319
|
-
That example now
|
|
2323
|
+
That example now folds each landed page into its feed from a `$watch` on the stream's value (and re-arms the sentinel from a `$watch` on the feed), and the `<b>` is display-only again. This shape — `$renderedCallback` testing a path that is not bound anywhere — is detected statically as **`wcs/updated-callback-unbound`**.
|
|
2320
2324
|
|
|
2321
2325
|
### The limitation that remains
|
|
2322
2326
|
|
|
@@ -2391,6 +2395,8 @@ Key rules:
|
|
|
2391
2395
|
|
|
2392
2396
|
## Scan (`$scan`)
|
|
2393
2397
|
|
|
2398
|
+
> **`$scan` warns in 3.5 and is removed in 4.0.** Fold a state path from a `$watch` handler that writes the accumulated value, and an event token from an `$on` handler; keep the reset condition in the handler. See [Preparing for 4.0](#preparing-for-40-wcsv4-migration).
|
|
2399
|
+
|
|
2394
2400
|
`$stream` folds *within* one run — every restart resets the value to `initial` — and `$watch` owns no value. **`$scan`** declares the value that has to outlive both: an accumulation over time, with an owner, a firing unit and a reset condition.
|
|
2395
2401
|
|
|
2396
2402
|
```html
|
|
@@ -2849,6 +2855,39 @@ Every failure mode reports and continues; nothing already applied is reverted:
|
|
|
2849
2855
|
| Render write chain | 100 | Skip applying bindings for that batch |
|
|
2850
2856
|
| Binding apply failure | — | Skip that one binding |
|
|
2851
2857
|
|
|
2858
|
+
### Preparing for 4.0 (`wcs/v4-migration`)
|
|
2859
|
+
|
|
2860
|
+
3.5 is the last 3.x minor. It names each name and option that 4.0 removes or moves, and still runs it the 3.x way. Each warning is a `console.warn` under the code `wcs/v4-migration`, printed once per name per page. It says what 4.0 does and what to write instead:
|
|
2861
|
+
|
|
2862
|
+
```
|
|
2863
|
+
[@wcstack/state] [wcs/v4-migration] filter "uc" is removed in 4.0: write "upper" (its name since 3.2).
|
|
2864
|
+
See "Preparing for 4.0" in the @wcstack/state README.
|
|
2865
|
+
```
|
|
2866
|
+
|
|
2867
|
+
| Form | 3.x | 4.0 | Write instead |
|
|
2868
|
+
|---|---|---|---|
|
|
2869
|
+
| The filter names 3.2 renamed: `inc` `dec` `fix` `uc` `lc` `cap` `rep` `rev` `pad` `null` | Aliases | `[wcs/filter-unknown]` | `add` `sub` `toFixed` `upper` `lower` `capitalize` `repeat` `reverse` `padStart` `nullIfEmpty` |
|
|
2870
|
+
| `$trackDependency` / `$untrackDependency` | Aliases | Throws `[wcs/name-alias]` | `$dependOn` / `$untracked` |
|
|
2871
|
+
| `$updatedCallback` / `$streams` | Aliases | Throws `[wcs/declaration-alias]` | `$renderedCallback` / `$stream` |
|
|
2872
|
+
| `substr(start, length)` | Works | `[wcs/filter-unknown]` | `slice(start, start + length)` (the end index, not a length) |
|
|
2873
|
+
| `$scan` | Works | Throws | `$watch` for state paths, `$on` for event tokens |
|
|
2874
|
+
| `bootstrapState({ debug })`, `commentTextPrefix`, `enablePropagationContext` | Work | Throw | Remove them. 4.0 reads comment bindings as `<!--@@: path-->` and `<!--@@wcs-text: path-->` only |
|
|
2875
|
+
| `bootstrapState({ enableMustache })`, `sameValueGuard`, `enableDirectionalInitialSync` | Page-wide options | Throw; each state tree declares them in `$behavior` | Keep them in 3.x. When you upgrade, move them to `$behavior` in each root and component state (a component does not inherit its host's; a volume may not declare one) |
|
|
2876
|
+
| An unknown `bootstrapState` key, or a value of another type (`null`, an array, a non-string tag name, a `tagNames` key other than `state` / `ssr`) | Ignored | Throws | Remove or fix it |
|
|
2877
|
+
| A state key `$behavior` | Plain data; 3.x does not read it | The state's behavior options | Warned only when its value differs from the option 3.x runs with, or has a shape 4.0 throws on |
|
|
2878
|
+
| A state key `$features` | Plain data | The add-ons the state needs | Warned only when 4.0 would throw on it (not an array of add-on names) |
|
|
2879
|
+
| A volume (`<wcs-state mount>`) that declares `$watch`, `$listKeys` or `$renderedCallback` (`$updatedCallback`) | Run relative to the mount path | The volume is not grafted (`console.error`) | Move them to the root state, with absolute paths |
|
|
2880
|
+
| A volume that injects root paths (`data-wcs="state.<key>: …"`) | Works (3.1) | The volume is not grafted (`console.error`) | Read the root path in a root getter |
|
|
2881
|
+
| A volume that declares `$behavior` / `$features` | Plain data, grafted | The volume is not grafted (`console.error`) | Declare them on the root state |
|
|
2882
|
+
|
|
2883
|
+
Where each fires: an old declaration key, `$scan`, `$behavior` and `$features` when the state object is loaded (a volume's when it is grafted); an old filter name and `substr` when a binding that uses it is set up; a `bootstrapState` option when `bootstrapState()` is called; `$trackDependency` / `$untrackDependency` when they are read. The checks sit where an old form is resolved, so a page that writes the canonical names behaves exactly as before; what it runs differs by one comparison where a filter is set up and one where `$dependOn` / `$untracked` is read, with no measurable difference.
|
|
2884
|
+
|
|
2885
|
+
The warnings ship in the full entries (`@wcstack/state` and `/auto`). A page on the split entries (`@wcstack/state/core` with `features/*`) prints none. There is no other switch, as in 2.6. A warning fires only on the path that reaches the old form, so a clean console proves nothing about the paths the page did not run. `npx @wcstack/lint <file>` and the VS Code extension report the old names statically (`wcs/name-alias`, info, since 3.2).
|
|
2886
|
+
|
|
2887
|
+
The three options that move to `$behavior` keep warning while a page passes them: 3.x reads them only from `bootstrapState`, so there is nothing to change before the upgrade. Writing `$behavior` early is harmless and is checked against the options 3.x runs with. One 4.0 rule has no 3.5 warning: a re-set (`setInitialState()` on an initialized element) may not change `$behavior` — 4.0 throws (#45), so create the element again instead.
|
|
2888
|
+
|
|
2889
|
+
`on*#direct:` works in 3.x already. 4.0 delegates `on*:` to the root and adds `#direct` to attach the listener to the element. 3.x attaches every `on*:` to its element and accepts the `#direct` modifier silently. Write it now where the element-attached behavior matters: `onclick#direct,stop:` stops your own listeners on the ancestors, and the handler still runs when an ancestor calls `stopPropagation()`.
|
|
2890
|
+
|
|
2852
2891
|
## Configuration
|
|
2853
2892
|
|
|
2854
2893
|
Pass a partial configuration object to `bootstrapState()`:
|
|
@@ -2858,8 +2897,7 @@ import { bootstrapState } from '@wcstack/state';
|
|
|
2858
2897
|
|
|
2859
2898
|
bootstrapState({
|
|
2860
2899
|
locale: 'ja-JP',
|
|
2861
|
-
|
|
2862
|
-
enableMustache: false,
|
|
2900
|
+
bindAttributeName: 'data-wcs',
|
|
2863
2901
|
tagNames: { state: 'my-state' },
|
|
2864
2902
|
});
|
|
2865
2903
|
```
|
|
@@ -2872,12 +2910,14 @@ All options with defaults:
|
|
|
2872
2910
|
| `tagNames.state` | `'wcs-state'` | State element tag name |
|
|
2873
2911
|
| `tagNames.ssr` | `'wcs-ssr'` | Tag name of the SSR hydration-data element |
|
|
2874
2912
|
| `locale` | `<html lang>`, else `'en'` | Locale for the locale-dependent filters (`locale` / `date` / `time` / `datetime`) — see [Locale](#locale) |
|
|
2875
|
-
| `debug` | `false` | Debug mode |
|
|
2876
|
-
| `enableMustache` | `true` | Enable `{{ }}` syntax |
|
|
2877
|
-
| `enableDirectionalInitialSync` | `true` | Direction-aware binding authority (`#init=` / `#sync=` binding modifiers) — see [Binding Authority](#binding-authority-init--sync). Default on; set `false` to opt out |
|
|
2878
|
-
| `enablePropagationContext` | `true` | Causal propagation tracking across bindings (echo/diamond loop prevention). Default on; set `false` to opt out |
|
|
2913
|
+
| `debug` | `false` | Debug mode. Removed in 4.0 (3.5 warns) |
|
|
2914
|
+
| `enableMustache` | `true` | Enable `{{ }}` syntax. Moves to the state's `$behavior` in 4.0 (3.5 warns) |
|
|
2915
|
+
| `enableDirectionalInitialSync` | `true` | Direction-aware binding authority (`#init=` / `#sync=` binding modifiers) — see [Binding Authority](#binding-authority-init--sync). Default on; set `false` to opt out. Moves to the state's `$behavior` in 4.0 (3.5 warns) |
|
|
2916
|
+
| `enablePropagationContext` | `true` | Causal propagation tracking across bindings (echo/diamond loop prevention). Default on; set `false` to opt out. Removed in 4.0 (3.5 warns) |
|
|
2879
2917
|
| `enableContractAnalyzer` | `false` | Opt-in dev-time contract analyzer (exposes `analyzeContract`) |
|
|
2880
|
-
| `sameValueGuard` | `true` | Drop a primitive write whose value is `Object.is`-equal to the current one before anything is enqueued — bindings and `$watch` effectively fire on change only; reference types always pass. `false` lets equal writes through and makes `$watch`'s `prev` `undefined` |
|
|
2918
|
+
| `sameValueGuard` | `true` | Drop a primitive write whose value is `Object.is`-equal to the current one before anything is enqueued — bindings and `$watch` effectively fire on change only; reference types always pass. `false` lets equal writes through and makes `$watch`'s `prev` `undefined`. Moves to the state's `$behavior` in 4.0 (3.5 warns) |
|
|
2919
|
+
|
|
2920
|
+
4.0 removes `debug`, `commentTextPrefix` and `enablePropagationContext`, and moves `enableMustache`, `enableDirectionalInitialSync` and `sameValueGuard` to the state's `$behavior`. 3.5 warns when a page passes them — see [Preparing for 4.0](#preparing-for-40-wcsv4-migration).
|
|
2881
2921
|
|
|
2882
2922
|
### Locale
|
|
2883
2923
|
|
|
@@ -3112,7 +3152,7 @@ Subpath entries for tooling: `@wcstack/state/parser` (the `data-wcs` parser as a
|
|
|
3112
3152
|
| Attribute | Description |
|
|
3113
3153
|
|---|---|
|
|
3114
3154
|
| `mount` | Static tree path to graft this state onto the root tree as a **volume** (v2 — replaces the removed `name` attribute; one state tree per root) |
|
|
3115
|
-
| `state` | ID of a `<script type="application/json">` element |
|
|
3155
|
+
| `state` | ID of a `<script type="application/json">` element in the document (looked up with `document.getElementById`, so a script inside a shadow root is not found) |
|
|
3116
3156
|
| `src` | URL to `.json` or `.js` file |
|
|
3117
3157
|
| `json` | Inline JSON string |
|
|
3118
3158
|
| `bind-component` | Property name for web component binding |
|
|
@@ -3123,7 +3163,7 @@ Subpath entries for tooling: `@wcstack/state/parser` (the `data-wcs` parser as a
|
|
|
3123
3163
|
| Property / Method | Description |
|
|
3124
3164
|
|---|---|
|
|
3125
3165
|
| `initializePromise` | Resolves when state is fully initialized — and also **when initialization fails**, so one element's failure never blocks the rest of the page's bindings; the error is delivered on `connectedCallbackPromise` |
|
|
3126
|
-
| `connectedCallbackPromise` | Resolves once `connectedCallback` has completed (state loaded, `$connectedCallback` run) — what the testing recipes await. A **root** element that fails to initialize **rejects** it with the original error, unwrapped, and reports the failure once with `console.error`: an invalid `$` declaration, a source it cannot load, the SSR data merge, a DCC or `bind-component` setup error, or a second root `<wcs-state>` on the same root node (that second element stays unregistered but keeps the state it loaded, so remove it; moving a healthy element in the DOM is not a duplicate and is never refused). A **volume** (`<wcs-state mount="…">`) never rejects it — a volume failure resolves it instead, and some volume failures report nothing of their own: the error leaves as the `connectedCallback` promise that custom-element reactions discard, which a browser console shows as "Uncaught (in promise)" but nothing awaiting these promises (a test recipe, `renderToString()`) ever sees. Detaching an element while its source is still loading rejects nothing — that connection just ends, and re-appending the element (row pooling) initializes it and resolves normally. For the exact behaviour of any single failure site, read `__tests__/integration.initFailureDiagnostics.test.ts`: it pins every case |
|
|
3166
|
+
| `connectedCallbackPromise` | Resolves once `connectedCallback` has completed (state loaded, `$connectedCallback` run) — what the testing recipes await. A **root** element that fails to initialize **rejects** it with the original error, unwrapped, and reports the failure once with `console.error`: an invalid `$` declaration, a source it cannot load, the SSR data merge, a DCC or `bind-component` setup error, or a second root `<wcs-state>` on the same root node (that second element stays unregistered but keeps the state it loaded, so remove it; moving a healthy element in the DOM is not a duplicate and is never refused). Two sources are not failures in 3.x and resolve it instead: a `src="*.json"` that cannot be fetched or parsed (logged with `console.error`, with its URL and the HTTP status or the error; the element starts with an empty state, and a volume grafts `{}`), and a `state="<id>"` with no `<script type="application/json">` of that id in the document (one `console.warn`; the state starts empty — the lookup is `document.getElementById`, so a script inside a shadow root is not found). 4.0 rejects in both cases; for `state=` it searches the element's own root first, then the document, and rejects only when the id is in neither. A **volume** (`<wcs-state mount="…">`) never rejects it — a volume failure resolves it instead, and some volume failures report nothing of their own: the error leaves as the `connectedCallback` promise that custom-element reactions discard, which a browser console shows as "Uncaught (in promise)" but nothing awaiting these promises (a test recipe, `renderToString()`) ever sees. Detaching an element while its source is still loading rejects nothing — that connection just ends, and re-appending the element (row pooling) initializes it and resolves normally. For the exact behaviour of any single failure site, read `__tests__/integration.initFailureDiagnostics.test.ts`: it pins every case |
|
|
3127
3167
|
| `listPaths` | Set of paths used in `for` loops |
|
|
3128
3168
|
| `getterPaths` | Set of paths defined as getters |
|
|
3129
3169
|
| `setterPaths` | Set of paths defined as setters |
|