@wcstack/devtools 2.6.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -95,6 +95,24 @@ interface IMountOverlaySummaryLike {
95
95
  /** マーカーパスに載る getter のキー */
96
96
  readonly getterKeys: readonly string[];
97
97
  }
98
+ /**
99
+ * 鍵付き購読(`$eq` / `$eqPath` / `$eqIndex`)の path 1 つ分の要約(keyedSubscriptions の要素 —
100
+ * protocol v2 追補・要件 D17)。取り出した時点の数え。
101
+ */
102
+ interface IKeyedSubscriptionSummaryLike {
103
+ /** `$eq` 系の第 1 引数(選択を持つパス) */
104
+ readonly path: string;
105
+ /** path が getter 由来で鍵付きで購読できず、追跡付きの読みに落ちた(変わるたびに読む getter が全部再評価される) */
106
+ readonly tracked: boolean;
107
+ /** 行ごとの購読の数 */
108
+ readonly rows: number;
109
+ /** 行ごとの購読が使っている鍵の数 */
110
+ readonly keys: number;
111
+ /** `$eqIndex` の最内段のリスト単位の監視の数 */
112
+ readonly lists: number;
113
+ /** path の最後に見た値(見ていなければ undefined)。生値 */
114
+ readonly lastValue: unknown;
115
+ }
98
116
  /**
99
117
  * 宣言レベルのバインディング 1 件(getDeclaredBindings の要素・protocol v1 追補)。
100
118
  * ランタイム正本パーサの結果が構造的に流れる。宣言タプルで dedupe 済みの
@@ -232,6 +250,12 @@ interface IDevtoolsSourceLike {
232
250
  * v2 より前のランタイムには無いため、無ければ UI はセクションごと出さない。
233
251
  */
234
252
  overlays?(rootNode: Node): IMountOverlaySummaryLike[];
253
+ /**
254
+ * protocol v2 追補 API(optional 扱いで呼ぶ・要件 D17)。rootNode のツリーの鍵付き購読の
255
+ * path ごとの要約。`$eq` 系が一度も評価されていなければ空配列。3.0 より前の state には無いため、
256
+ * 無ければ UI はセクションごと出さない。
257
+ */
258
+ keyedSubscriptions?(rootNode: Node): IKeyedSubscriptionSummaryLike[];
235
259
  read(rootNode: Node, path: string, indexes?: number[]): unknown;
236
260
  write(rootNode: Node, path: string, value: unknown, indexes?: number[]): void;
237
261
  /**
@@ -405,6 +429,11 @@ declare class DevtoolsCore {
405
429
  * 出さない(後方互換)。マウントが無いツリーは空配列。
406
430
  */
407
431
  overlaysOf(entry: IRosterEntry): IMountOverlaySummaryLike[] | null;
432
+ /**
433
+ * roster entry のツリーの鍵付き購読(keyedSubscriptions — protocol v2 追補・要件 D17)。
434
+ * 実装しないランタイム(3.0 より前の state)では null — UI はセクションごと出さない。
435
+ */
436
+ keyedSubscriptionsOf(entry: IRosterEntry): IKeyedSubscriptionSummaryLike[] | null;
408
437
  readValue(entry: IRosterEntry, path: string, indexes?: number[]): unknown;
409
438
  writeValue(entry: IRosterEntry, path: string, value: unknown, indexes?: number[]): void;
410
439
  private _notify;
@@ -484,6 +513,17 @@ declare class WcsDevtools extends HTMLElement {
484
513
  private _rosterKey;
485
514
  private _selectedRoster;
486
515
  private _renderStatePane;
516
+ /**
517
+ * 選択ツリーの鍵付き購読セクション(keyedSubscriptions — protocol v2 追補・要件 D17)。
518
+ * `$eq` / `$eqPath` / `$eqIndex` の購読は依存グラフの動的な変化で、上の状態ツリーにも
519
+ * Wiring の台帳にも現れない。path ごとに購読の数と最後の値を出し、getter 由来の path で
520
+ * 追跡付きの読みに落ちたもの(変わるたびに読む getter が全部再評価される)を warn で目立たせる。
521
+ * 未提供の旧ランタイム(null)と `$eq` 系が一度も評価されていないツリー(空配列)では出さない。
522
+ * pull の時機は Overlays と同じく State ペインの再描画に乗る。
523
+ */
524
+ private _renderKeyedSection;
525
+ /** 鍵付き購読 1 path の描画(path・購読の数・最後の値、または追跡付きへの落ち)。 */
526
+ private _keyedRow;
487
527
  /**
488
528
  * 選択ツリーのマウント記録セクション(overlays — protocol v2・D20 の可視化)。
489
529
  * マウントの私有キー・getter はオーバーレイ専用アドレス空間(マーカー `#m<id>`)に
package/dist/index.esm.js CHANGED
@@ -561,6 +561,17 @@ class DevtoolsCore {
561
561
  }
562
562
  return source.overlays(entry.rootNode);
563
563
  }
564
+ /**
565
+ * roster entry のツリーの鍵付き購読(keyedSubscriptions — protocol v2 追補・要件 D17)。
566
+ * 実装しないランタイム(3.0 より前の state)では null — UI はセクションごと出さない。
567
+ */
568
+ keyedSubscriptionsOf(entry) {
569
+ const source = this._sources.get(entry.sourceId);
570
+ if (source === undefined || typeof source.keyedSubscriptions !== "function") {
571
+ return null;
572
+ }
573
+ return source.keyedSubscriptions(entry.rootNode);
574
+ }
564
575
  readValue(entry, path, indexes) {
565
576
  const source = this._sources.get(entry.sourceId);
566
577
  if (source === undefined) {
@@ -1131,6 +1142,9 @@ header .spacer { flex: 1; }
1131
1142
  .overlay-row .prop { color: #b7f0c0; }
1132
1143
  .overlay-row .path { color: #9fd0ff; }
1133
1144
  .overlay-row .detail { color: #6f88a3; }
1145
+ .keyed-row { padding: 1px 0; white-space: nowrap; }
1146
+ .keyed-row .path { color: #9fd0ff; }
1147
+ .keyed-row .detail { color: #6f88a3; }
1134
1148
  .wiring-tabs { padding: 0 0 4px; }
1135
1149
  .wiring-tabs button { font: inherit; cursor: pointer; margin-right: 4px; opacity: 0.6; }
1136
1150
  .wiring-tabs button.active { opacity: 1; font-weight: bold; }
@@ -1514,12 +1528,67 @@ class WcsDevtools extends HTMLElement {
1514
1528
  body.append(this._emptyRow("no readable keys (runtime without keys() API?)"));
1515
1529
  // keys が読めないランタイムでも overlays は独立に読める可能性があるため出す
1516
1530
  this._renderOverlaysSection(body, selected);
1531
+ this._renderKeyedSection(body, selected);
1517
1532
  return;
1518
1533
  }
1519
1534
  for (const key of keys) {
1520
1535
  this._renderTreeNode(body, selected, { path: key, indexes: [] }, key, 0);
1521
1536
  }
1522
1537
  this._renderOverlaysSection(body, selected);
1538
+ this._renderKeyedSection(body, selected);
1539
+ }
1540
+ /**
1541
+ * 選択ツリーの鍵付き購読セクション(keyedSubscriptions — protocol v2 追補・要件 D17)。
1542
+ * `$eq` / `$eqPath` / `$eqIndex` の購読は依存グラフの動的な変化で、上の状態ツリーにも
1543
+ * Wiring の台帳にも現れない。path ごとに購読の数と最後の値を出し、getter 由来の path で
1544
+ * 追跡付きの読みに落ちたもの(変わるたびに読む getter が全部再評価される)を warn で目立たせる。
1545
+ * 未提供の旧ランタイム(null)と `$eq` 系が一度も評価されていないツリー(空配列)では出さない。
1546
+ * pull の時機は Overlays と同じく State ペインの再描画に乗る。
1547
+ */
1548
+ _renderKeyedSection(body, entry) {
1549
+ const summaries = this._core.keyedSubscriptionsOf(entry);
1550
+ if (summaries === null || summaries.length === 0) {
1551
+ return;
1552
+ }
1553
+ const heading = document.createElement("h3");
1554
+ heading.className = "overlays-heading";
1555
+ heading.textContent = `Keyed selection (${summaries.length} path${summaries.length === 1 ? "" : "s"})`;
1556
+ body.append(heading);
1557
+ for (const summary of summaries) {
1558
+ body.append(this._keyedRow(summary));
1559
+ }
1560
+ }
1561
+ /** 鍵付き購読 1 path の描画(path・購読の数・最後の値、または追跡付きへの落ち)。 */
1562
+ _keyedRow(summary) {
1563
+ const row = document.createElement("div");
1564
+ row.className = "keyed-row";
1565
+ const path = document.createElement("span");
1566
+ path.className = "path";
1567
+ path.textContent = summary.path;
1568
+ row.append(path);
1569
+ if (summary.tracked) {
1570
+ const badge = document.createElement("span");
1571
+ badge.className = "badge-tag warn";
1572
+ badge.textContent = "tracked";
1573
+ badge.title = "the path is a getter or under one, so $eq cannot subscribe by key: every getter that reads it re-evaluates when it changes";
1574
+ row.append(document.createTextNode(" "), badge);
1575
+ }
1576
+ const details = [];
1577
+ // 空になった鍵は台帳から消えるので、鍵があれば行もある
1578
+ if (summary.rows > 0) {
1579
+ details.push(`rows ${summary.rows} · keys ${summary.keys}`);
1580
+ }
1581
+ if (summary.lists > 0) {
1582
+ details.push(`list watchers ${summary.lists}`);
1583
+ }
1584
+ if (!summary.tracked) {
1585
+ details.push(`last ${formatValue(summary.lastValue, 1)}`);
1586
+ }
1587
+ const detail = document.createElement("span");
1588
+ detail.className = "detail";
1589
+ detail.textContent = details.length > 0 ? ` ${details.join(" · ")}` : "";
1590
+ row.append(detail);
1591
+ return row;
1523
1592
  }
1524
1593
  /**
1525
1594
  * 選択ツリーのマウント記録セクション(overlays — protocol v2・D20 の可視化)。