@wcstack/devtools 1.24.0 → 1.26.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/auto.min.js CHANGED
@@ -1,3 +1,2 @@
1
- import { bootstrapDevtools } from "./index.esm.min.js";
2
-
3
- bootstrapDevtools();
1
+ const e="__WCSTACK_DEVTOOLS_HOOK__";function t(){const t=globalThis,n=t[e];if(void 0!==n)return 1!==n.version&&console.warn(`[wcstack/devtools] hook registry version mismatch: found ${n.version}, expected 1. Keeping the existing registry (first-wins).`),n;const i=function(){const e=new Map,t=new Set,n=e=>{if(0===t.size)return void e._setSink(null);const n=e.id;e._setSink(e=>{for(const i of t)i.onEvent?.(n,e)})};return{version:1,sources:e,register(i){if(!e.has(i.id)){e.set(i.id,i),n(i);for(const e of t)e.onSourceRegistered?.(i)}},unregister(n){const i=e.get(n);if(void 0!==i){i._setSink(null),e.delete(n);for(const e of t)e.onSourceUnregistered?.(n)}},addListener(i){t.add(i);for(const t of e.values())n(t),i.onSourceRegistered?.(t);return()=>{if(t.delete(i))for(const t of e.values())n(t)}}}}();return t[e]=i,i}function n(e,t=2){switch(typeof e){case"string":return`"${e.length>80?e.slice(0,80)+"…":e}"`;case"number":case"boolean":case"bigint":return String(e);case"symbol":return e.toString();case"undefined":return"undefined";case"function":return"[[Function]]"}if(null===e)return"null";const i=e;if(Array.isArray(i)){if(t<=0)return`[[Array(${i.length})]]`;const e=i.slice(0,3).map(e=>n(e,t-1)),s=i.length>3?`, …(${i.length})`:"";return`[${e.join(", ")}${s}]`}if(function(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(i)){if(t<=0)return"[[Object]]";const e=Object.keys(i),s=e.slice(0,3).map(e=>`${e}: ${n(i[e],t-1)}`),o=e.length>3?`, …(${e.length})`:"";return`{${s.join(", ")}${o}}`}return`[[${function(e){const t=e.constructor,n=t?.name;return"string"==typeof n&&n.length>0?n:"Object"}(i)}]]`}function i(e){if(0===e.length)return"";const t=e.slice(0,3).map(e=>{const t=n(e,1);return t.length>80?t.slice(0,80)+"…":t}),i=e.length>3?`, …(${e.length})`:"";return`${t.join(", ")}${i}`}function s(e,t){return e+"\0"+t}class o{_timelineCapacity;_hiddenStateNames;_removeListener=null;_sources=new Map;_roster=new Map;_wiringByPathKey=new Map;_wiringEntryByBinding=new WeakMap;_timeline=[];_seq=0;_paused=!1;_changeListeners=new Set;constructor(e){this._timelineCapacity=e?.timelineCapacity??500,this._hiddenStateNames=new Set(e?.hiddenStateNames??[])}get connected(){return null!==this._removeListener}get paused(){return this._paused}set paused(e){this._paused=e}isHiddenStateName(e){return null!==e&&(e.startsWith("wcs-devtools")||this._hiddenStateNames.has(e))}connect(){if(null!==this._removeListener)return;const e=t();this._removeListener=e.addListener({onSourceRegistered:e=>{this._sources.set(e.id,e),this._refreshRosterOf(e),this._notify("sources")},onSourceUnregistered:e=>{this._sources.delete(e),this._roster.delete(e),this._notify("sources"),this._notify("roster")},onEvent:(e,t)=>{this._ingest(e,t)}})}disconnect(){null!==this._removeListener&&(this._removeListener(),this._removeListener=null,this._sources.clear(),this._roster.clear(),this._wiringByPathKey.clear(),this._wiringEntryByBinding=new WeakMap,this._notify("sources"),this._notify("roster"),this._notify("wiring"))}onChange(e){return this._changeListeners.add(e),()=>{this._changeListeners.delete(e)}}getSources(){return[...this._sources.values()]}getRoster(){const e=[];for(const t of this._roster.values())e.push(...t);return e}refreshRoster(){for(const e of this._sources.values())this._refreshRosterOf(e);this._notify("roster")}getTimeline(){return this._timeline}clearTimeline(){this._timeline=[],this._notify("timeline")}getWiringForPath(e,t){const n=this._wiringByPathKey.get(s(e,t));return void 0===n?[]:this._collectAlive(n)}getAllWiring(){const e=[];for(const t of this._wiringByPathKey.values())e.push(...this._collectAlive(t));return e}getWiringForNode(e){const t=[];for(const n of this._wiringByPathKey.values())for(const i of this._collectAlive(n)){const n=i.bindingRef.deref();(n.node===e||n.replaceNode===e||e.contains(n.node)||e.contains(n.replaceNode))&&t.push(i)}return t}keysOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.keys?[]:t.keys(e.name,e.rootNode)}readValue(e,t,n){const i=this._sources.get(e.sourceId);if(void 0!==i)return i.read(e.name,e.rootNode,t,n)}writeValue(e,t,n,i){const s=this._sources.get(e.sourceId);void 0!==s&&s.write(e.name,e.rootNode,t,n,i)}_notify(e){for(const t of this._changeListeners)t(e)}_refreshRosterOf(e){const t=[];for(const n of e.getStateElements())this.isHiddenStateName(n.name)||t.push({sourceId:e.id,name:n.name,rootNode:n.rootNode,summary:n});this._roster.set(e.id,t)}_collectAlive(e){const t=[];for(const n of e)void 0!==n.bindingRef.deref()?t.push(n):e.delete(n);return t}_appendTimeline(e){if(this._paused)return;this._timeline.push({...e,seq:this._seq++,time:performance.now()});const t=this._timeline.length-this._timelineCapacity;t>0&&this._timeline.splice(0,t),this._notify("timeline")}_labelOf(e){const t=e.listIndex?.indexes,n=e.absolutePathInfo.pathInfo.path;return void 0!==t?`${n}[${t.join(",")}]`:n}_ingest(e,t){switch(t.type){case"state:element-registered":{if(this.isHiddenStateName(t.name))return;const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-registered",stateName:t.name,label:t.name,detail:"",subscriberCount:null})}case"state:element-unregistered":{if(this.isHiddenStateName(t.name))return;const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-unregistered",stateName:t.name,label:t.name,detail:"",subscriberCount:null})}case"state:write":{const i=t.absoluteAddress.absolutePathInfo.stateName;if(this.isHiddenStateName(i))return;const s=t.hasOldValue?`${n(t.value)} (was ${n(t.oldValue)})`:n(t.value);return void this._appendTimeline({sourceId:e,kind:"write",stateName:i,label:this._labelOf(t.absoluteAddress),detail:s,subscriberCount:null})}case"state:update-batch":{const n=[];let i=0;for(const e of t.addresses)this.isHiddenStateName(e.absolutePathInfo.stateName)||(i++,n.length<3&&n.push(this._labelOf(e)));if(0===i)return;const s=i>n.length?`, …(${i})`:"";return void this._appendTimeline({sourceId:e,kind:"batch",stateName:null,label:`${i} address${1===i?"":"es"}`,detail:`${n.join(", ")}${s}`,subscriberCount:null})}case"state:binding-added":{const n=t.absoluteAddress.absolutePathInfo.stateName;if(this.isHiddenStateName(n))return;const i=t.absoluteAddress.absolutePathInfo.pathInfo.path,o=s(n,i);let r=this._wiringByPathKey.get(o);void 0===r&&(r=new Set,this._wiringByPathKey.set(o,r));const a={sourceId:e,stateName:n,path:i,propName:t.binding.propName,bindingType:t.binding.bindingType,bindingRef:new WeakRef(t.binding)};return r.add(a),this._wiringEntryByBinding.set(t.binding,a),void this._notify("wiring")}case"state:binding-removed":{const e=this._wiringEntryByBinding.get(t.binding);if(void 0===e)return;this._wiringEntryByBinding.delete(t.binding);const n=s(e.stateName,e.path),i=this._wiringByPathKey.get(n);return void 0!==i&&(i.delete(e),0===i.size&&this._wiringByPathKey.delete(n)),void this._notify("wiring")}case"state:binding-cleared":{const e=s(t.absoluteAddress.absolutePathInfo.stateName,t.absoluteAddress.absolutePathInfo.pathInfo.path);return void(this._wiringByPathKey.delete(e)&&this._notify("wiring"))}case"state:token-emit":if(this.isHiddenStateName(t.stateName))return;return void this._appendTimeline({sourceId:e,kind:t.kind,stateName:t.stateName,label:t.tokenName,detail:i(t.args),subscriberCount:t.subscriberCount})}}}const r=["wcs-text","wcs-for","wcs-if","wcs-elseif","wcs-else"];function a(e,t,n){const i=t.trim();if(0===i.length)return null;const s=i.indexOf(":");if(s<0)return null;const o=i.slice(0,s).trim(),r=i.slice(s+1).trim();if(0===o.length||0===r.length)return null;const[a,...l]=r.split("|").map(e=>e.trim());let d=a,c="default";const h=a.lastIndexOf("@");return h>0&&(d=a.slice(0,h).trim(),c=a.slice(h+1).trim()),{element:e,propName:o,path:d,stateName:c,filters:l.filter(e=>e.length>0),origin:n,raw:i}}class l extends HTMLElement{static get observedAttributes(){return["open","dock","hotkey"]}_core=null;_removeCoreListener=null;_panel=null;_badge=null;_stateSelect=null;_paneElements={};_highlightLayer=null;_dirtyPanes=new Set;_renderScheduled=!1;_selectedRosterKey=null;_selectedPath=null;_pickedNode=null;_pickMode=!1;_expanded=new Set;_hotkeyHandler=null;_pickHandler=null;get core(){return this._core}connectedCallback(){if(document.documentElement.hasAttribute("data-wcs-server"))return;null===this.shadowRoot&&this._buildShadow();const e=Number(this.getAttribute("buffer")??""),t=(this.getAttribute("hidden-states")??"").split(",").map(e=>e.trim()).filter(e=>e.length>0);this._core=new o({timelineCapacity:Number.isFinite(e)&&e>0?e:void 0,hiddenStateNames:t}),this._removeCoreListener=this._core.onChange(e=>{"roster"===e||"sources"===e?(this._markDirty("state"),this._markDirty("wiring")):"wiring"===e?this._markDirty("wiring"):this._markDirty("timeline")}),this._core.connect(),this._applyDock(),this._applyOpen(),this._installHotkey(),this._markDirty("state"),this._markDirty("wiring"),this._markDirty("timeline")}disconnectedCallback(){this._removeCoreListener?.(),this._removeCoreListener=null,this._core?.disconnect(),this._core=null,this._uninstallHotkey(),this._exitPickMode()}attributeChangedCallback(e){null!==this.shadowRoot&&("open"===e?this._applyOpen():"dock"===e?this._applyDock():"hotkey"===e&&(this._uninstallHotkey(),this._installHotkey()))}__flushRenderForTest(){this._renderDirty()}_buildShadow(){const e=this.attachShadow({mode:"open"}),t=document.createElement("style");t.textContent='\n:host {\n all: initial;\n position: fixed;\n z-index: 2147483647;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n inset: auto 0 0 auto;\n}\n* { box-sizing: border-box; }\n.badge {\n position: fixed;\n right: 12px;\n bottom: 12px;\n width: 40px;\n height: 40px;\n border-radius: 20px;\n border: 1px solid #2b4f78;\n background: #10263f;\n color: #9fd0ff;\n font-weight: 700;\n cursor: pointer;\n}\n.panel {\n position: fixed;\n display: flex;\n flex-direction: column;\n background: #0d1b2a;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n box-shadow: 0 0 24px rgba(0,0,0,.5);\n}\n.panel.dock-bottom { left: 0; right: 0; bottom: 0; height: 45vh; }\n.panel.dock-right { top: 0; right: 0; bottom: 0; width: 420px; }\n.panel[hidden] { display: none; }\nheader {\n display: flex;\n gap: 6px;\n align-items: center;\n padding: 6px 8px;\n border-bottom: 1px solid #2b4f78;\n background: #10263f;\n}\nheader .title { font-weight: 700; color: #9fd0ff; margin-right: 4px; }\nheader select, header button {\n font: inherit;\n background: #16324f;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n border-radius: 4px;\n padding: 2px 8px;\n cursor: pointer;\n}\nheader button[aria-pressed="true"] { background: #2b5d8f; }\nheader .spacer { flex: 1; }\n.panes { display: flex; flex: 1; min-height: 0; }\n.pane { flex: 1; min-width: 0; overflow: auto; padding: 6px 8px; border-right: 1px solid #1d3a5c; }\n.pane:last-child { border-right: none; }\n.pane h3 {\n margin: 0 0 6px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: .08em;\n color: #7ba7d4;\n}\n.tree-row { display: flex; gap: 6px; padding: 1px 0; align-items: baseline; white-space: nowrap; }\n.tree-row .toggle { width: 14px; cursor: pointer; color: #7ba7d4; user-select: none; }\n.tree-row .key { color: #9fd0ff; cursor: pointer; }\n.tree-row .value { color: #ffd9a0; overflow: hidden; text-overflow: ellipsis; }\n.tree-row .value.editable { cursor: pointer; }\n.tree-row input { font: inherit; background: #16324f; color: #ffd9a0; border: 1px solid #2b4f78; }\n.badge-tag {\n display: inline-block;\n padding: 0 4px;\n border-radius: 3px;\n font-size: 10px;\n background: #26456a;\n color: #a8c6e8;\n}\n.badge-tag.warn { background: #6a3326; color: #ffb3a0; }\n.badge-tag.declared { background: #4a4426; color: #efe3a0; }\n.wiring-row, .timeline-row { padding: 1px 0; white-space: nowrap; }\n.wiring-row .prop { color: #b7f0c0; }\n.wiring-row .path { color: #9fd0ff; }\n.timeline-row .t { color: #6f88a3; }\n.timeline-row .label { color: #9fd0ff; }\n.timeline-row .detail { color: #ffd9a0; }\n.timeline-row .kind { display: inline-block; min-width: 52px; text-align: center; }\n.empty { color: #6f88a3; font-style: italic; padding: 4px 0; }\n.notice { color: #efe3a0; padding: 2px 0 6px; }\n.notice button { font: inherit; margin-left: 6px; cursor: pointer; }\n.hl-box {\n position: fixed;\n pointer-events: none;\n border: 1px solid #58c2ff;\n background: rgba(88,194,255,.18);\n}\n',e.append(t);const n=document.createElement("button");n.className="badge",n.title="wcstack DevTools",n.textContent="WCS",n.addEventListener("click",()=>this.toggle()),e.append(n),this._badge=n;const i=document.createElement("div");i.className="panel dock-bottom",i.hidden=!0;const s=document.createElement("header"),o=document.createElement("span");o.className="title",o.textContent="wcstack devtools",s.append(o);const r=document.createElement("select");r.title="state element",r.addEventListener("change",()=>{this._selectedRosterKey=r.value||null,this._selectedPath=null,this._expanded.clear(),this._markDirty("state"),this._markDirty("wiring")}),s.append(r),this._stateSelect=r;const a=this._headerButton(s,"⌖ pick","pick a page element");a.addEventListener("click",()=>{this._pickMode?this._exitPickMode():this._enterPickMode(),a.setAttribute("aria-pressed",String(this._pickMode))}),a.dataset.role="pick";const l=this._headerButton(s,"⏸","pause timeline");l.addEventListener("click",()=>{const e=this._core;null!==e&&(e.paused=!e.paused,l.setAttribute("aria-pressed",String(e.paused)))}),l.dataset.role="pause";const d=this._headerButton(s,"🗑","clear timeline");d.addEventListener("click",()=>{this._core?.clearTimeline()}),d.dataset.role="clear";const c=document.createElement("span");c.className="spacer",s.append(c);const h=this._headerButton(s,"dock","toggle dock position");h.addEventListener("click",()=>{const e="bottom"===(this.getAttribute("dock")??"bottom")?"right":"bottom";this.setAttribute("dock",e)}),h.dataset.role="dock";const u=this._headerButton(s,"×","close");u.addEventListener("click",()=>this.toggle(!1)),u.dataset.role="close",i.append(s);const p=document.createElement("div");p.className="panes";for(const[e,t]of[["state","State"],["wiring","Wiring"],["timeline","Timeline"]]){const n=document.createElement("section");n.className=`pane pane-${e}`;const i=document.createElement("h3");i.textContent=t;const s=document.createElement("div");s.className="pane-body",n.append(i,s),p.append(n),this._paneElements[e]=s}i.append(p),e.append(i),this._panel=i;const m=document.createElement("div");m.className="hl-layer",e.append(m),this._highlightLayer=m}_headerButton(e,t,n){const i=document.createElement("button");return i.textContent=t,i.title=n,i.setAttribute("aria-pressed","false"),e.append(i),i}get open(){return this.hasAttribute("open")}toggle(e){e??!this.open?this.setAttribute("open",""):this.removeAttribute("open")}_applyOpen(){this._panel.hidden=!this.open,this._badge.hidden=this.open,this.open&&(this._markDirty("state"),this._markDirty("wiring"),this._markDirty("timeline"))}_applyDock(){const e="right"===this.getAttribute("dock")?"right":"bottom";this._panel.classList.toggle("dock-right","right"===e),this._panel.classList.toggle("dock-bottom","bottom"===e)}_installHotkey(){const e=this.getAttribute("hotkey")??"Alt+Shift+D";if("none"===e)return;const t=e.split("+").map(e=>e.trim().toLowerCase()),n=t[t.length-1],i=t.includes("alt"),s=t.includes("shift"),o=t.includes("ctrl"),r=t.includes("meta");this._hotkeyHandler=e=>{e.key.toLowerCase()===n&&e.altKey===i&&e.shiftKey===s&&e.ctrlKey===o&&e.metaKey===r&&(e.preventDefault(),this.toggle())},window.addEventListener("keydown",this._hotkeyHandler)}_uninstallHotkey(){null!==this._hotkeyHandler&&(window.removeEventListener("keydown",this._hotkeyHandler),this._hotkeyHandler=null)}_enterPickMode(){this._pickMode=!0,this._pickHandler=e=>{const t=e.target;t.getRootNode()!==this.shadowRoot&&t!==this&&(e.preventDefault(),e.stopPropagation(),this._pickedNode=t,this._selectedPath=null,this._exitPickMode(),this._markDirty("wiring"))},document.addEventListener("click",this._pickHandler,{capture:!0})}_exitPickMode(){null!==this._pickHandler&&(document.removeEventListener("click",this._pickHandler,{capture:!0}),this._pickHandler=null),this._pickMode=!1;const e=this.shadowRoot?.querySelector('button[data-role="pick"]');e?.setAttribute("aria-pressed","false")}_markDirty(e){this._dirtyPanes.add(e),this._renderScheduled||(this._renderScheduled=!0,requestAnimationFrame(()=>{this._renderDirty()}))}_renderDirty(){if(this._renderScheduled=!1,null===this._core||null===this.shadowRoot)return void this._dirtyPanes.clear();const e=this._dirtyPanes;this._dirtyPanes=new Set,e.has("state")&&this._renderStatePane(),e.has("wiring")&&this._renderWiringPane(),e.has("timeline")&&this._renderTimelinePane()}_rosterKey(e){return`${e.sourceId}:${e.name}`}_selectedRoster(){const e=this._core.getRoster();if(0===e.length)return null;return e.find(e=>this._rosterKey(e)===this._selectedRosterKey)??e[0]}_renderStatePane(){const e=this._core,t=this._paneElements.state,n=this._stateSelect,i=e.getRoster(),s=this._selectedRoster();if(n.replaceChildren(...i.map(e=>{const t=document.createElement("option");return t.value=this._rosterKey(e),t.textContent=`${e.name} (${e.sourceId.slice(0,12)})`,t.selected=null!==s&&this._rosterKey(e)===this._rosterKey(s),t})),t.replaceChildren(),null===s)return void t.append(this._emptyRow("no <wcs-state> elements observed"));this._selectedRosterKey=this._rosterKey(s);const o=e.keysOf(s);if(0!==o.length)for(const e of o)this._renderTreeNode(t,s,{path:e,indexes:[]},e,0);else t.append(this._emptyRow("no readable keys (runtime without keys() API?)"))}_renderTreeNode(e,t,i,s,o){const r=this._core;let a,l=!0;try{a=r.readValue(t,i.path,i.indexes)}catch{l=!1}const d=document.createElement("div");d.className="tree-row",d.style.paddingLeft=14*o+"px";const c=l&&function(e){if(Array.isArray(e))return!0;if(null===e||"object"!=typeof e)return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(a),h=function(e){return`${e.path}#${e.indexes.join(",")}`}(i),u=c&&this._expanded.has(h),p=document.createElement("span");p.className="toggle",p.textContent=c?u?"▾":"▸":"",c&&p.addEventListener("click",()=>{this._expanded.has(h)?this._expanded.delete(h):this._expanded.add(h),this._markDirty("state")}),d.append(p);const m=document.createElement("span");m.className="key",m.textContent=`${s}:`,m.title=i.path,m.addEventListener("click",()=>{this._selectedPath=i.path,this._pickedNode=null,this._markDirty("wiring"),this._highlightPath(t,i.path)}),d.append(m);const g=document.createElement("span");if(g.className="value",l){g.textContent=n(a,1);(null===a||"object"!=typeof a)&&"function"!=typeof a&&(g.classList.add("editable"),g.title="click to edit",g.addEventListener("click",()=>{this._beginEdit(d,g,t,i,a)}))}else g.textContent="(unreadable getter)";if(d.append(g),e.append(d),u)if(Array.isArray(a)){const n=Math.min(a.length,20);for(let s=0;s<n;s++)this._renderTreeNode(e,t,{path:`${i.path}.*`,indexes:[...i.indexes,s]},`[${s}]`,o+1);if(a.length>n){const t=this._emptyRow(`…(${a.length} items)`);t.style.paddingLeft=14*(o+1)+"px",e.append(t)}}else for(const n of Object.keys(a))this._renderTreeNode(e,t,{path:`${i.path}.${n}`,indexes:i.indexes},n,o+1)}_beginEdit(e,t,n,i,s){const o=document.createElement("input");o.value="string"==typeof s?s:String(s);const r=()=>{this._core?.writeValue(n,i.path,function(e){const t=e.trim();try{return JSON.parse(t)}catch{return e}}(o.value),i.indexes),this._markDirty("state")};o.addEventListener("keydown",e=>{"Enter"===e.key?r():"Escape"===e.key&&this._markDirty("state")}),e.replaceChild(o,t),o.focus()}_renderWiringPane(){const e=this._core,t=this._paneElements.wiring;let n,i;if(t.replaceChildren(),null!==this._pickedNode){n=e.getWiringForNode(this._pickedNode);const t=this._pickedNode;i=t instanceof Element?`<${t.tagName.toLowerCase()}>`:t.nodeName}else if(null!==this._selectedPath){const t=this._selectedRoster();n=null!==t?e.getWiringForPath(t.name,this._selectedPath):[],i=this._selectedPath}else n=e.getAllWiring(),i="all";const s=document.createElement("div");if(s.textContent=`context: ${i} — ${n.length} live binding${1===n.length?"":"s"}`,t.append(s),n.length>0){for(const e of n)t.append(this._wiringRow(e));return}const o=this._selectedRoster(),l=null!==o?function(e,t="data-wcs"){const n=[];for(const i of e.querySelectorAll(`[${t}]`)){const e=i.getAttribute(t);for(const t of e.split(";")){const e=a(i,t,"attribute");null!==e&&n.push(e)}}const i=(e.ownerDocument??e).createTreeWalker(e,NodeFilter.SHOW_COMMENT);let s=i.nextNode();for(;null!==s;){const e=s.textContent.trim(),t=r.find(t=>e===t||e.startsWith(t+":"));if(void 0!==t){const i=s.parentNode instanceof Element?s.parentNode:null;if(null!==i){const s=e===t?"":e.slice(t.length+1).trim();if(s.length>0){const e="wcs-text"===t?"textContent":t.slice(4);n.push(a(i,`${e}: ${s}`,"comment"))}}}s=i.nextNode()}return n}(this._scanRootOf(o)):[];if(0===l.length)return void t.append(this._emptyRow("no bindings observed"));const d=document.createElement("div");d.className="notice";const c=document.createElement("span");c.className="badge-tag declared",c.textContent="declared",d.append(c,document.createTextNode(" attached late — reload to capture live bindings "));const h=document.createElement("button");h.textContent="reload",h.addEventListener("click",()=>{location.reload()}),d.append(h),t.append(d);for(const e of l)t.append(this._declaredRow(e))}_scanRootOf(e){const t=e.rootNode;return t.nodeType===Node.DOCUMENT_NODE||t.nodeType===Node.DOCUMENT_FRAGMENT_NODE?t:document}_wiringRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="prop",n.textContent=e.propName;const i=document.createTextNode(" ← "),s=document.createElement("span");s.className="path",s.textContent=`${e.path}@${e.stateName}`;const o=document.createElement("span");return o.className="badge-tag",o.textContent=e.bindingType,t.append(o,document.createTextNode(" "),n,i,s),t.addEventListener("click",()=>{const t=e.bindingRef.deref();void 0!==t&&this._highlightNodes([t.node,t.replaceNode])}),t}_declaredRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="badge-tag declared",n.textContent=e.origin;const i=document.createElement("span");i.className="prop",i.textContent=e.propName;const s=document.createElement("span");return s.className="path",s.textContent=`${e.path}@${e.stateName}`,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),s),t.addEventListener("click",()=>{this._highlightNodes([e.element])}),t}_renderTimelinePane(){const e=this._core,t=this._paneElements.timeline,n=e.getTimeline(),i=Math.max(0,n.length-200),s=[];i>0&&s.push(this._emptyRow(`…(${i} earlier entries)`));for(let e=i;e<n.length;e++)s.push(this._timelineRow(n[e]));0===s.length&&s.push(this._emptyRow("no activity yet")),t.replaceChildren(...s),t.scrollTop=t.scrollHeight}_timelineRow(e){const t=document.createElement("div");t.className="timeline-row";const n=document.createElement("span");n.className="t",n.textContent=`${(e.time/1e3).toFixed(3)}s `;const i=document.createElement("span");i.className="badge-tag kind",i.textContent=e.kind,0===e.subscriberCount&&(i.classList.add("warn"),i.title="emitted with no subscribers");const s=document.createElement("span");s.className="label";const o=null!==e.stateName?`@${e.stateName}`:"";s.textContent=` ${e.label}${o} `;const r=document.createElement("span");return r.className="detail",r.textContent=e.detail,t.append(n,i,s,r),t}_emptyRow(e){const t=document.createElement("div");return t.className="empty",t.textContent=e,t}_highlightPath(e,t){const n=this._core,i=[];for(const s of n.getWiringForPath(e.name,t)){const e=s.bindingRef.deref();void 0!==e&&i.push(e.node,e.replaceNode)}this._highlightNodes(i)}_highlightNodes(e){const t=this._highlightLayer;t.replaceChildren();const n=new Set;for(const i of e){const e=i instanceof Element?i:i.parentElement;if(null===e||n.has(e)||!e.isConnected)continue;n.add(e);const s=e.getBoundingClientRect(),o=document.createElement("div");o.className="hl-box",o.style.left=`${s.left}px`,o.style.top=`${s.top}px`,o.style.width=`${s.width}px`,o.style.height=`${s.height}px`,t.append(o)}setTimeout(()=>{t.replaceChildren()},2e3)}}const d="wcs-devtools";function c(){null===document.querySelector(d)&&document.body.appendChild(document.createElement(d))}document.documentElement.hasAttribute("data-wcs-server")||(customElements.get(d)||customElements.define(d,l),null!==document.body?c():document.addEventListener("DOMContentLoaded",c,{once:!0}));
2
+ //# sourceMappingURL=auto.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto.min.js","sources":["../src/protocol/types.ts","../src/protocol/registry.ts","../src/core/formatValue.ts","../src/core/DevtoolsCore.ts","../src/core/declaredScan.ts","../src/shell/WcsDevtools.ts","../src/bootstrapDevtools.ts"],"sourcesContent":["/**\n * protocol/types.ts\n *\n * DevTools Hook Protocol (docs/devtools-hook-protocol.md) の devtools 側型定義。\n *\n * ランタイム(@wcstack/state)側の内部型は import しない — プロトコルは\n * 「文書化された構造」への構造的型付けで両側が独立に実装する(protocol §2)。\n * そのためランタイム内部オブジェクトは *Like インターフェースとして、\n * devtools が実際に触るプロパティだけを宣言する。\n */\n\n/** グローバル registry のプロパティ名 */\nexport const DEVTOOLS_HOOK_GLOBAL = \"__WCSTACK_DEVTOOLS_HOOK__\";\n\n/** プロトコル版。additive change では上げない(protocol §2) */\nexport const DEVTOOLS_PROTOCOL_VERSION = 1;\n\nexport interface IPathInfoLike {\n readonly path: string;\n}\n\nexport interface IAbsolutePathInfoLike {\n readonly stateName: string;\n readonly pathInfo: IPathInfoLike;\n}\n\nexport interface IListIndexLike {\n readonly index: number;\n readonly indexes: number[];\n}\n\nexport interface IAbsoluteAddressLike {\n readonly absolutePathInfo: IAbsolutePathInfoLike;\n readonly listIndex: IListIndexLike | null;\n}\n\nexport interface IBindingLike {\n readonly propName: string;\n readonly statePathName: string;\n readonly stateName: string;\n readonly bindingType: string;\n readonly node: Node;\n readonly replaceNode: Node;\n}\n\nexport interface IStateElementSummaryLike {\n readonly name: string;\n readonly rootNode: Node;\n readonly element: unknown;\n readonly paths: {\n readonly list: ReadonlySet<string>;\n readonly element: ReadonlySet<string>;\n readonly getter: ReadonlySet<string>;\n readonly setter: ReadonlySet<string>;\n };\n readonly commandTokenNames: ReadonlySet<string>;\n readonly eventTokenNames: ReadonlySet<string>;\n readonly staticDependency: ReadonlyMap<string, readonly string[]>;\n readonly dynamicDependency: ReadonlyMap<string, readonly string[]>;\n}\n\nexport type DevtoolsEventLike =\n | {\n readonly type: \"state:element-registered\";\n readonly name: string;\n readonly rootNode: Node;\n readonly element: unknown;\n }\n | {\n readonly type: \"state:element-unregistered\";\n readonly name: string;\n readonly rootNode: Node;\n readonly element: unknown;\n }\n | {\n readonly type: \"state:write\";\n readonly absoluteAddress: IAbsoluteAddressLike;\n readonly value: unknown;\n readonly oldValue: unknown;\n readonly hasOldValue: boolean;\n }\n | {\n readonly type: \"state:update-batch\";\n readonly addresses: ReadonlySet<IAbsoluteAddressLike>;\n }\n | {\n readonly type: \"state:binding-added\";\n readonly absoluteAddress: IAbsoluteAddressLike;\n readonly binding: IBindingLike;\n }\n | {\n readonly type: \"state:binding-removed\";\n readonly absoluteAddress: IAbsoluteAddressLike;\n readonly binding: IBindingLike;\n }\n | {\n readonly type: \"state:binding-cleared\";\n readonly absoluteAddress: IAbsoluteAddressLike;\n }\n | {\n readonly type: \"state:token-emit\";\n readonly kind: \"command\" | \"event\";\n readonly stateName: string | null;\n readonly tokenName: string;\n readonly args: readonly unknown[];\n readonly subscriberCount: number;\n };\n\nexport type DevtoolsSinkLike = (event: DevtoolsEventLike) => void;\n\nexport interface IDevtoolsSourceLike {\n readonly id: string;\n readonly kind: string;\n readonly packageVersion: string;\n getStateElements(): IStateElementSummaryLike[];\n /** protocol v1 追補 API。古いランタイムには無い可能性があるため optional 扱いで呼ぶ */\n keys?(name: string, rootNode: Node): string[];\n read(name: string, rootNode: Node, path: string, indexes?: number[]): unknown;\n write(name: string, rootNode: Node, path: string, value: unknown, indexes?: number[]): void;\n _setSink(sink: DevtoolsSinkLike | null): void;\n}\n\nexport interface IDevtoolsListenerLike {\n onSourceRegistered?(source: IDevtoolsSourceLike): void;\n onSourceUnregistered?(sourceId: string): void;\n onEvent?(sourceId: string, event: DevtoolsEventLike): void;\n}\n\nexport interface IDevtoolsHookRegistryLike {\n readonly version: number;\n readonly sources: Map<string, IDevtoolsSourceLike>;\n register(source: IDevtoolsSourceLike): void;\n unregister(sourceId: string): void;\n addListener(listener: IDevtoolsListenerLike): () => void;\n}\n","/**\n * protocol/registry.ts\n *\n * registry 最小実装の devtools 側コピー(protocol §2)。\n * ロード順非依存にするため、ランタイム側(@wcstack/state の bridge)と\n * devtools 側の両方が同一仕様の最小実装を持ち、先にロードされた方が\n * globalThis に置く(先勝ち・振る舞い差し替えなし)。\n */\n\nimport {\n DEVTOOLS_HOOK_GLOBAL,\n DEVTOOLS_PROTOCOL_VERSION,\n IDevtoolsHookRegistryLike,\n IDevtoolsListenerLike,\n IDevtoolsSourceLike,\n} from \"./types\";\n\nfunction createMinimalRegistry(): IDevtoolsHookRegistryLike {\n const sources = new Map<string, IDevtoolsSourceLike>();\n const listeners = new Set<IDevtoolsListenerLike>();\n const applySink = (source: IDevtoolsSourceLike): void => {\n if (listeners.size === 0) {\n source._setSink(null);\n return;\n }\n const sourceId = source.id;\n source._setSink((event) => {\n for (const listener of listeners) {\n listener.onEvent?.(sourceId, event);\n }\n });\n };\n return {\n version: DEVTOOLS_PROTOCOL_VERSION,\n sources,\n register(source: IDevtoolsSourceLike): void {\n if (sources.has(source.id)) {\n return;\n }\n sources.set(source.id, source);\n applySink(source);\n for (const listener of listeners) {\n listener.onSourceRegistered?.(source);\n }\n },\n unregister(sourceId: string): void {\n const source = sources.get(sourceId);\n if (source === undefined) {\n return;\n }\n source._setSink(null);\n sources.delete(sourceId);\n for (const listener of listeners) {\n listener.onSourceUnregistered?.(sourceId);\n }\n },\n addListener(listener: IDevtoolsListenerLike): () => void {\n listeners.add(listener);\n for (const source of sources.values()) {\n applySink(source);\n listener.onSourceRegistered?.(source);\n }\n return () => {\n if (!listeners.delete(listener)) {\n return;\n }\n for (const source of sources.values()) {\n applySink(source);\n }\n };\n },\n };\n}\n\nexport function getOrCreateHookRegistry(): IDevtoolsHookRegistryLike {\n const globals = globalThis as unknown as Record<string, unknown>;\n const existing = globals[DEVTOOLS_HOOK_GLOBAL] as IDevtoolsHookRegistryLike | undefined;\n if (existing !== undefined) {\n if (existing.version !== DEVTOOLS_PROTOCOL_VERSION) {\n // 先勝ち固定。振る舞いは差し替えない(protocol §2)\n console.warn(\n `[wcstack/devtools] hook registry version mismatch: found ${existing.version}, expected ${DEVTOOLS_PROTOCOL_VERSION}. Keeping the existing registry (first-wins).`\n );\n }\n return existing;\n }\n const registry = createMinimalRegistry();\n globals[DEVTOOLS_HOOK_GLOBAL] = registry;\n return registry;\n}\n","/**\n * core/formatValue.ts\n *\n * 値フォーマッタ(devtools-tag-design.md §6)。\n *\n * 規範:\n * - primitive はそのまま(文字列は引用 + 80 文字上限)\n * - 配列 / plain object は深さ制限 + 要素数制限つきの要約\n * - それ以外(MediaStream, Blob, Element, class インスタンス等)は\n * `[[ClassName]]` タグ表示のみ\n * - structuredClone / JSON.stringify を全値に無差別適用しない\n * (生ハンドル・循環・巨大値対策。camera G1 との共存)\n */\n\nconst MAX_STRING = 80;\nconst MAX_ITEMS = 3;\n\nfunction isPlainObject(value: object): boolean {\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction className(value: object): string {\n const ctor = (value as { constructor?: { name?: string } }).constructor;\n const name = ctor?.name;\n return typeof name === \"string\" && name.length > 0 ? name : \"Object\";\n}\n\n/**\n * 任意の値を表示用の短い文字列へ変換する。\n * @param value 対象値\n * @param depth 再帰許容深さ(既定 2。0 で複合値は要約タグのみ)\n */\nexport function formatValue(value: unknown, depth: number = 2): string {\n switch (typeof value) {\n case \"string\": {\n const body = value.length > MAX_STRING ? value.slice(0, MAX_STRING) + \"…\" : value;\n return `\"${body}\"`;\n }\n case \"number\":\n case \"boolean\":\n case \"bigint\":\n return String(value);\n case \"symbol\":\n return value.toString();\n case \"undefined\":\n return \"undefined\";\n case \"function\":\n return \"[[Function]]\";\n default:\n break;\n }\n if (value === null) {\n return \"null\";\n }\n const objectValue = value as object;\n if (Array.isArray(objectValue)) {\n if (depth <= 0) {\n return `[[Array(${objectValue.length})]]`;\n }\n const shown = objectValue.slice(0, MAX_ITEMS).map((item) => formatValue(item, depth - 1));\n const rest = objectValue.length > MAX_ITEMS ? `, …(${objectValue.length})` : \"\";\n return `[${shown.join(\", \")}${rest}]`;\n }\n if (isPlainObject(objectValue)) {\n if (depth <= 0) {\n return \"[[Object]]\";\n }\n const keys = Object.keys(objectValue);\n const shown = keys.slice(0, MAX_ITEMS).map(\n (key) => `${key}: ${formatValue((objectValue as Record<string, unknown>)[key], depth - 1)}`\n );\n const rest = keys.length > MAX_ITEMS ? `, …(${keys.length})` : \"\";\n return `{${shown.join(\", \")}${rest}}`;\n }\n // DOM ノード・生ハンドル・class インスタンス等はタグ表示のみ\n return `[[${className(objectValue)}]]`;\n}\n\n/**\n * token 引数の要約(先頭 3 引数 × 各 80 文字上限、devtools-tag-design.md §6)。\n */\nexport function formatArgs(args: readonly unknown[]): string {\n if (args.length === 0) {\n return \"\";\n }\n const shown = args.slice(0, MAX_ITEMS).map((arg) => {\n const text = formatValue(arg, 1);\n return text.length > MAX_STRING ? text.slice(0, MAX_STRING) + \"…\" : text;\n });\n const rest = args.length > MAX_ITEMS ? `, …(${args.length})` : \"\";\n return `${shown.join(\", \")}${rest}`;\n}\n","/**\n * core/DevtoolsCore.ts\n *\n * hook client(devtools-tag-design.md §1)。DOM 非依存の純ロジック層。\n *\n * - registry への addListener / 解除(connect / disconnect)\n * - source 管理と roster(state 要素一覧)の維持\n * - 配線台帳(binding-added/removed イベントから構築。binding は WeakRef 保持)\n * - タイムライン ring buffer(既定 500 件 FIFO)\n * - 予約 prefix `wcs-devtools` の自己除外(protocol §5)\n *\n * 台帳はすべて devtools 側に置く(protocol 原則 2)。disconnect で\n * sources / roster / wiring をクリアし、残留参照を持たない。\n */\n\nimport { getOrCreateHookRegistry } from \"../protocol/registry\";\nimport {\n DevtoolsEventLike,\n IAbsoluteAddressLike,\n IBindingLike,\n IDevtoolsSourceLike,\n IStateElementSummaryLike,\n} from \"../protocol/types\";\nimport { formatArgs, formatValue } from \"./formatValue\";\n\n/** 予約 state 名 prefix(protocol §5)。この prefix の要素・イベントは常に除外 */\nexport const RESERVED_STATE_NAME_PREFIX = \"wcs-devtools\";\n\nconst DEFAULT_TIMELINE_CAPACITY = 500;\n\nexport type TimelineKind =\n | \"write\"\n | \"batch\"\n | \"command\"\n | \"event\"\n | \"element-registered\"\n | \"element-unregistered\";\n\nexport interface ITimelineEntry {\n readonly seq: number;\n readonly time: number;\n readonly sourceId: string;\n readonly kind: TimelineKind;\n readonly stateName: string | null;\n readonly label: string;\n readonly detail: string;\n readonly subscriberCount: number | null;\n}\n\nexport interface IRosterEntry {\n readonly sourceId: string;\n readonly name: string;\n readonly rootNode: Node;\n readonly summary: IStateElementSummaryLike;\n}\n\nexport interface IWiringEntry {\n readonly sourceId: string;\n readonly stateName: string;\n readonly path: string;\n readonly propName: string;\n readonly bindingType: string;\n readonly bindingRef: WeakRef<IBindingLike>;\n}\n\nexport type CoreChangeKind = \"sources\" | \"roster\" | \"wiring\" | \"timeline\";\nexport type CoreChangeListener = (kind: CoreChangeKind) => void;\n\nexport interface IDevtoolsCoreOptions {\n /** タイムライン ring buffer 件数(既定 500) */\n timelineCapacity?: number;\n /** 追加で除外する state 名(予約 prefix は常に除外) */\n hiddenStateNames?: readonly string[];\n}\n\nfunction pathKeyOf(stateName: string, path: string): string {\n return stateName + \"\u0000\" + path;\n}\n\nexport class DevtoolsCore {\n private _timelineCapacity: number;\n private _hiddenStateNames: Set<string>;\n private _removeListener: (() => void) | null = null;\n private _sources: Map<string, IDevtoolsSourceLike> = new Map();\n private _roster: Map<string, IRosterEntry[]> = new Map();\n private _wiringByPathKey: Map<string, Set<IWiringEntry>> = new Map();\n private _wiringEntryByBinding: WeakMap<IBindingLike, IWiringEntry> = new WeakMap();\n private _timeline: ITimelineEntry[] = [];\n private _seq: number = 0;\n private _paused: boolean = false;\n private _changeListeners: Set<CoreChangeListener> = new Set();\n\n constructor(options?: IDevtoolsCoreOptions) {\n this._timelineCapacity = options?.timelineCapacity ?? DEFAULT_TIMELINE_CAPACITY;\n this._hiddenStateNames = new Set(options?.hiddenStateNames ?? []);\n }\n\n get connected(): boolean {\n return this._removeListener !== null;\n }\n\n get paused(): boolean {\n return this._paused;\n }\n\n set paused(value: boolean) {\n this._paused = value;\n }\n\n /** 表示から除外する state 名か(予約 prefix + hiddenStateNames、protocol §5) */\n isHiddenStateName(name: string | null): boolean {\n if (name === null) {\n return false;\n }\n return name.startsWith(RESERVED_STATE_NAME_PREFIX) || this._hiddenStateNames.has(name);\n }\n\n connect(): void {\n if (this._removeListener !== null) {\n return;\n }\n const registry = getOrCreateHookRegistry();\n this._removeListener = registry.addListener({\n onSourceRegistered: (source) => {\n this._sources.set(source.id, source);\n this._refreshRosterOf(source);\n this._notify(\"sources\");\n },\n onSourceUnregistered: (sourceId) => {\n this._sources.delete(sourceId);\n this._roster.delete(sourceId);\n this._notify(\"sources\");\n this._notify(\"roster\");\n },\n onEvent: (sourceId, event) => {\n this._ingest(sourceId, event);\n },\n });\n }\n\n /** 購読解除 + 台帳クリア(タイムラインは保持。protocol §7-2 の残留ゼロ) */\n disconnect(): void {\n if (this._removeListener === null) {\n return;\n }\n this._removeListener();\n this._removeListener = null;\n this._sources.clear();\n this._roster.clear();\n this._wiringByPathKey.clear();\n this._wiringEntryByBinding = new WeakMap();\n this._notify(\"sources\");\n this._notify(\"roster\");\n this._notify(\"wiring\");\n }\n\n onChange(listener: CoreChangeListener): () => void {\n this._changeListeners.add(listener);\n return () => {\n this._changeListeners.delete(listener);\n };\n }\n\n getSources(): IDevtoolsSourceLike[] {\n return [...this._sources.values()];\n }\n\n getRoster(): IRosterEntry[] {\n const entries: IRosterEntry[] = [];\n for (const list of this._roster.values()) {\n entries.push(...list);\n }\n return entries;\n }\n\n /** 全 source の state 要素一覧を pull で取り直す */\n refreshRoster(): void {\n for (const source of this._sources.values()) {\n this._refreshRosterOf(source);\n }\n this._notify(\"roster\");\n }\n\n getTimeline(): readonly ITimelineEntry[] {\n return this._timeline;\n }\n\n clearTimeline(): void {\n this._timeline = [];\n this._notify(\"timeline\");\n }\n\n /** 指定パスに束縛された配線(生存している binding のみ) */\n getWiringForPath(stateName: string, path: string): IWiringEntry[] {\n const set = this._wiringByPathKey.get(pathKeyOf(stateName, path));\n if (set === undefined) {\n return [];\n }\n return this._collectAlive(set);\n }\n\n /** 全配線のスナップショット(生存している binding のみ) */\n getAllWiring(): IWiringEntry[] {\n const result: IWiringEntry[] = [];\n for (const set of this._wiringByPathKey.values()) {\n result.push(...this._collectAlive(set));\n }\n return result;\n }\n\n /** 指定ノード(またはその子孫のバインドノード)に載る配線 */\n getWiringForNode(node: Node): IWiringEntry[] {\n const result: IWiringEntry[] = [];\n for (const set of this._wiringByPathKey.values()) {\n for (const entry of this._collectAlive(set)) {\n const binding = entry.bindingRef.deref()!;\n if (\n binding.node === node ||\n binding.replaceNode === node ||\n node.contains(binding.node) ||\n node.contains(binding.replaceNode)\n ) {\n result.push(entry);\n }\n }\n }\n return result;\n }\n\n /** roster entry の state からトップレベルキーを列挙(keys 未実装ランタイムは空) */\n keysOf(entry: IRosterEntry): string[] {\n const source = this._sources.get(entry.sourceId);\n if (source === undefined || typeof source.keys !== \"function\") {\n return [];\n }\n return source.keys(entry.name, entry.rootNode);\n }\n\n readValue(entry: IRosterEntry, path: string, indexes?: number[]): unknown {\n const source = this._sources.get(entry.sourceId);\n if (source === undefined) {\n return undefined;\n }\n return source.read(entry.name, entry.rootNode, path, indexes);\n }\n\n writeValue(entry: IRosterEntry, path: string, value: unknown, indexes?: number[]): void {\n const source = this._sources.get(entry.sourceId);\n if (source === undefined) {\n return;\n }\n source.write(entry.name, entry.rootNode, path, value, indexes);\n }\n\n // --- internal ---\n\n private _notify(kind: CoreChangeKind): void {\n for (const listener of this._changeListeners) {\n listener(kind);\n }\n }\n\n private _refreshRosterOf(source: IDevtoolsSourceLike): void {\n const entries: IRosterEntry[] = [];\n for (const summary of source.getStateElements()) {\n if (this.isHiddenStateName(summary.name)) {\n continue;\n }\n entries.push({\n sourceId: source.id,\n name: summary.name,\n rootNode: summary.rootNode,\n summary,\n });\n }\n this._roster.set(source.id, entries);\n }\n\n private _collectAlive(set: Set<IWiringEntry>): IWiringEntry[] {\n const alive: IWiringEntry[] = [];\n for (const entry of set) {\n if (entry.bindingRef.deref() === undefined) {\n // GC 済み binding は遅延剪定(detach 漏れで DOM を残さないための WeakRef 側)\n set.delete(entry);\n continue;\n }\n alive.push(entry);\n }\n return alive;\n }\n\n private _appendTimeline(entry: Omit<ITimelineEntry, \"seq\" | \"time\">): void {\n if (this._paused) {\n return;\n }\n this._timeline.push({\n ...entry,\n seq: this._seq++,\n time: performance.now(),\n });\n const overflow = this._timeline.length - this._timelineCapacity;\n if (overflow > 0) {\n this._timeline.splice(0, overflow);\n }\n this._notify(\"timeline\");\n }\n\n private _labelOf(address: IAbsoluteAddressLike): string {\n const indexes = address.listIndex?.indexes;\n const path = address.absolutePathInfo.pathInfo.path;\n return indexes !== undefined ? `${path}[${indexes.join(\",\")}]` : path;\n }\n\n private _ingest(sourceId: string, event: DevtoolsEventLike): void {\n switch (event.type) {\n case \"state:element-registered\": {\n if (this.isHiddenStateName(event.name)) {\n return;\n }\n const source = this._sources.get(sourceId);\n if (source !== undefined) {\n this._refreshRosterOf(source);\n this._notify(\"roster\");\n }\n this._appendTimeline({\n sourceId,\n kind: \"element-registered\",\n stateName: event.name,\n label: event.name,\n detail: \"\",\n subscriberCount: null,\n });\n return;\n }\n case \"state:element-unregistered\": {\n if (this.isHiddenStateName(event.name)) {\n return;\n }\n const source = this._sources.get(sourceId);\n if (source !== undefined) {\n this._refreshRosterOf(source);\n this._notify(\"roster\");\n }\n this._appendTimeline({\n sourceId,\n kind: \"element-unregistered\",\n stateName: event.name,\n label: event.name,\n detail: \"\",\n subscriberCount: null,\n });\n return;\n }\n case \"state:write\": {\n const stateName = event.absoluteAddress.absolutePathInfo.stateName;\n if (this.isHiddenStateName(stateName)) {\n return;\n }\n const detail = event.hasOldValue\n ? `${formatValue(event.value)} (was ${formatValue(event.oldValue)})`\n : formatValue(event.value);\n this._appendTimeline({\n sourceId,\n kind: \"write\",\n stateName,\n label: this._labelOf(event.absoluteAddress),\n detail,\n subscriberCount: null,\n });\n return;\n }\n case \"state:update-batch\": {\n const labels: string[] = [];\n let total = 0;\n for (const address of event.addresses) {\n if (this.isHiddenStateName(address.absolutePathInfo.stateName)) {\n continue;\n }\n total++;\n if (labels.length < 3) {\n labels.push(this._labelOf(address));\n }\n }\n if (total === 0) {\n return;\n }\n const rest = total > labels.length ? `, …(${total})` : \"\";\n this._appendTimeline({\n sourceId,\n kind: \"batch\",\n stateName: null,\n label: `${total} address${total === 1 ? \"\" : \"es\"}`,\n detail: `${labels.join(\", \")}${rest}`,\n subscriberCount: null,\n });\n return;\n }\n case \"state:binding-added\": {\n const stateName = event.absoluteAddress.absolutePathInfo.stateName;\n if (this.isHiddenStateName(stateName)) {\n return;\n }\n const path = event.absoluteAddress.absolutePathInfo.pathInfo.path;\n const key = pathKeyOf(stateName, path);\n let set = this._wiringByPathKey.get(key);\n if (set === undefined) {\n set = new Set();\n this._wiringByPathKey.set(key, set);\n }\n const entry: IWiringEntry = {\n sourceId,\n stateName,\n path,\n propName: event.binding.propName,\n bindingType: event.binding.bindingType,\n bindingRef: new WeakRef(event.binding),\n };\n set.add(entry);\n this._wiringEntryByBinding.set(event.binding, entry);\n this._notify(\"wiring\");\n return;\n }\n case \"state:binding-removed\": {\n const entry = this._wiringEntryByBinding.get(event.binding);\n if (entry === undefined) {\n return;\n }\n this._wiringEntryByBinding.delete(event.binding);\n const key = pathKeyOf(entry.stateName, entry.path);\n const set = this._wiringByPathKey.get(key);\n if (set !== undefined) {\n set.delete(entry);\n if (set.size === 0) {\n this._wiringByPathKey.delete(key);\n }\n }\n this._notify(\"wiring\");\n return;\n }\n case \"state:binding-cleared\": {\n const stateName = event.absoluteAddress.absolutePathInfo.stateName;\n const path = event.absoluteAddress.absolutePathInfo.pathInfo.path;\n const key = pathKeyOf(stateName, path);\n if (this._wiringByPathKey.delete(key)) {\n this._notify(\"wiring\");\n }\n return;\n }\n case \"state:token-emit\": {\n if (this.isHiddenStateName(event.stateName)) {\n return;\n }\n this._appendTimeline({\n sourceId,\n kind: event.kind,\n stateName: event.stateName,\n label: event.tokenName,\n detail: formatArgs(event.args),\n subscriberCount: event.subscriberCount,\n });\n return;\n }\n }\n }\n}\n","/**\n * core/declaredScan.ts\n *\n * 遅延アタッチ時の declared ビュー(protocol §6)。\n *\n * binding 台帳はフック接続前の分を復元できないため、DOM に残っている\n * `data-wcs` 属性と `<!--wcs-*: -->` コメントを再スキャンして\n * 「宣言レベルの配線ビュー」を組む。ライブ台帳と違い binding 実体・\n * 接続状態は分からない(UI では \"declared\" バッジで区別する)。\n *\n * パースは表示目的の簡易版(`prop[#mod]: path[@state][|filters]` を\n * `;` 区切りで分解するだけ)。正確なセマンティクスの正本は\n * @wcstack/state の bindTextParser であり、ここでは追随しない。\n */\n\nexport interface IDeclaredBinding {\n /** 宣言が載っている要素(コメント由来の場合は親要素) */\n readonly element: Element;\n readonly propName: string;\n readonly path: string;\n readonly stateName: string;\n readonly filters: readonly string[];\n /** 宣言ソース: data-wcs 属性か comment ノードか */\n readonly origin: \"attribute\" | \"comment\";\n readonly raw: string;\n}\n\nconst DEFAULT_BIND_ATTRIBUTE = \"data-wcs\";\nconst COMMENT_PREFIXES = [\"wcs-text\", \"wcs-for\", \"wcs-if\", \"wcs-elseif\", \"wcs-else\"];\n\nfunction parseEntry(\n element: Element,\n raw: string,\n origin: \"attribute\" | \"comment\"\n): IDeclaredBinding | null {\n const trimmed = raw.trim();\n if (trimmed.length === 0) {\n return null;\n }\n const colon = trimmed.indexOf(\":\");\n if (colon < 0) {\n return null;\n }\n const propName = trimmed.slice(0, colon).trim();\n const rhs = trimmed.slice(colon + 1).trim();\n if (propName.length === 0 || rhs.length === 0) {\n return null;\n }\n const [pathPart, ...filterParts] = rhs.split(\"|\").map((part) => part.trim());\n let path = pathPart;\n let stateName = \"default\";\n const at = pathPart.lastIndexOf(\"@\");\n if (at > 0) {\n path = pathPart.slice(0, at).trim();\n stateName = pathPart.slice(at + 1).trim();\n }\n return {\n element,\n propName,\n path,\n stateName,\n filters: filterParts.filter((part) => part.length > 0),\n origin,\n raw: trimmed,\n };\n}\n\n/**\n * rootNode 配下の宣言配線を列挙する。\n * @param root 走査起点(Document / ShadowRoot / Element)\n * @param bindAttributeName バインド属性名(既定 data-wcs。setConfig で変えたページ用)\n */\nexport function scanDeclaredBindings(\n root: ParentNode,\n bindAttributeName: string = DEFAULT_BIND_ATTRIBUTE\n): IDeclaredBinding[] {\n const result: IDeclaredBinding[] = [];\n\n // data-wcs 属性(template の for/if 宣言もこの属性に載る)\n for (const element of root.querySelectorAll(`[${bindAttributeName}]`)) {\n // querySelectorAll の一致条件上、属性は必ず存在する\n const raw = element.getAttribute(bindAttributeName)!;\n for (const part of raw.split(\";\")) {\n const entry = parseEntry(element, part, \"attribute\");\n if (entry !== null) {\n result.push(entry);\n }\n }\n }\n\n // <!--wcs-text: path--> 等のコメントノード(mustache 展開後の姿)\n const document = root.ownerDocument ?? (root as Document);\n const walker = document.createTreeWalker(root as Node, NodeFilter.SHOW_COMMENT);\n let comment = walker.nextNode();\n while (comment !== null) {\n // コメントノードの textContent は常に文字列\n const text = comment.textContent!.trim();\n const prefix = COMMENT_PREFIXES.find(\n (candidate) => text === candidate || text.startsWith(candidate + \":\")\n );\n if (prefix !== undefined) {\n const parentElement =\n comment.parentNode instanceof Element ? comment.parentNode : null;\n if (parentElement !== null) {\n const body = text === prefix ? \"\" : text.slice(prefix.length + 1).trim();\n if (body.length > 0) {\n const propName = prefix === \"wcs-text\" ? \"textContent\" : prefix.slice(\"wcs-\".length);\n // propName / body とも非空のため parseEntry は必ず成功する\n result.push(parseEntry(parentElement, `${propName}: ${body}`, \"comment\")!);\n }\n }\n }\n comment = walker.nextNode();\n }\n\n return result;\n}\n","/**\n * shell/WcsDevtools.ts\n *\n * `<wcs-devtools>` — ページ内オーバーレイ DevTools 本体(devtools-tag-design.md)。\n *\n * - ShadowRoot 内で完結(ページの CSS/DOM を変更しない)\n * - ハイライトはページ要素の style/class を触らず、fixed 配置の\n * オーバーレイ枠で描く(devtools-tag-design.md §2)\n * - UI レンダリングは vanilla DOM(記録済み決定: inspected ランタイムの\n * updater キューに devtools 描画負荷を混ぜない = 観測者効果の排除。\n * wcs-state ドッグフーディングは Phase 2 で再評価)\n * - 描画は Core の change 通知を rAF で 1 回に合流(イベント毎 DOM 追加禁止、\n * devtools-tag-design.md §3.3)\n */\n\nimport { DevtoolsCore, IRosterEntry, ITimelineEntry, IWiringEntry } from \"../core/DevtoolsCore\";\nimport { formatValue } from \"../core/formatValue\";\nimport { IDeclaredBinding, scanDeclaredBindings } from \"../core/declaredScan\";\n\nconst STYLE_TEXT = /* css */ `\n:host {\n all: initial;\n position: fixed;\n z-index: 2147483647;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n inset: auto 0 0 auto;\n}\n* { box-sizing: border-box; }\n.badge {\n position: fixed;\n right: 12px;\n bottom: 12px;\n width: 40px;\n height: 40px;\n border-radius: 20px;\n border: 1px solid #2b4f78;\n background: #10263f;\n color: #9fd0ff;\n font-weight: 700;\n cursor: pointer;\n}\n.panel {\n position: fixed;\n display: flex;\n flex-direction: column;\n background: #0d1b2a;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n box-shadow: 0 0 24px rgba(0,0,0,.5);\n}\n.panel.dock-bottom { left: 0; right: 0; bottom: 0; height: 45vh; }\n.panel.dock-right { top: 0; right: 0; bottom: 0; width: 420px; }\n.panel[hidden] { display: none; }\nheader {\n display: flex;\n gap: 6px;\n align-items: center;\n padding: 6px 8px;\n border-bottom: 1px solid #2b4f78;\n background: #10263f;\n}\nheader .title { font-weight: 700; color: #9fd0ff; margin-right: 4px; }\nheader select, header button {\n font: inherit;\n background: #16324f;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n border-radius: 4px;\n padding: 2px 8px;\n cursor: pointer;\n}\nheader button[aria-pressed=\"true\"] { background: #2b5d8f; }\nheader .spacer { flex: 1; }\n.panes { display: flex; flex: 1; min-height: 0; }\n.pane { flex: 1; min-width: 0; overflow: auto; padding: 6px 8px; border-right: 1px solid #1d3a5c; }\n.pane:last-child { border-right: none; }\n.pane h3 {\n margin: 0 0 6px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: .08em;\n color: #7ba7d4;\n}\n.tree-row { display: flex; gap: 6px; padding: 1px 0; align-items: baseline; white-space: nowrap; }\n.tree-row .toggle { width: 14px; cursor: pointer; color: #7ba7d4; user-select: none; }\n.tree-row .key { color: #9fd0ff; cursor: pointer; }\n.tree-row .value { color: #ffd9a0; overflow: hidden; text-overflow: ellipsis; }\n.tree-row .value.editable { cursor: pointer; }\n.tree-row input { font: inherit; background: #16324f; color: #ffd9a0; border: 1px solid #2b4f78; }\n.badge-tag {\n display: inline-block;\n padding: 0 4px;\n border-radius: 3px;\n font-size: 10px;\n background: #26456a;\n color: #a8c6e8;\n}\n.badge-tag.warn { background: #6a3326; color: #ffb3a0; }\n.badge-tag.declared { background: #4a4426; color: #efe3a0; }\n.wiring-row, .timeline-row { padding: 1px 0; white-space: nowrap; }\n.wiring-row .prop { color: #b7f0c0; }\n.wiring-row .path { color: #9fd0ff; }\n.timeline-row .t { color: #6f88a3; }\n.timeline-row .label { color: #9fd0ff; }\n.timeline-row .detail { color: #ffd9a0; }\n.timeline-row .kind { display: inline-block; min-width: 52px; text-align: center; }\n.empty { color: #6f88a3; font-style: italic; padding: 4px 0; }\n.notice { color: #efe3a0; padding: 2px 0 6px; }\n.notice button { font: inherit; margin-left: 6px; cursor: pointer; }\n.hl-box {\n position: fixed;\n pointer-events: none;\n border: 1px solid #58c2ff;\n background: rgba(88,194,255,.18);\n}\n`;\n\ntype PaneName = \"state\" | \"wiring\" | \"timeline\";\n\n/** タイムラインの DOM 描画上限(buffer とは別。§3.3 のバースト圧縮の一部) */\nconst TIMELINE_RENDER_LIMIT = 200;\n/** リスト展開の 1 階層あたり表示件数上限 */\nconst LIST_CHILD_LIMIT = 20;\n\ninterface ITreeNodeRef {\n readonly path: string;\n readonly indexes: number[];\n}\n\nfunction nodeKeyOf(ref: ITreeNodeRef): string {\n return `${ref.path}#${ref.indexes.join(\",\")}`;\n}\n\nfunction isExpandable(value: unknown): boolean {\n if (Array.isArray(value)) {\n return true;\n }\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction coerceInput(text: string): unknown {\n const trimmed = text.trim();\n try {\n return JSON.parse(trimmed);\n } catch {\n return text;\n }\n}\n\nexport class WcsDevtools extends HTMLElement {\n static get observedAttributes(): string[] {\n return [\"open\", \"dock\", \"hotkey\"];\n }\n\n private _core: DevtoolsCore | null = null;\n private _removeCoreListener: (() => void) | null = null;\n private _panel: HTMLElement | null = null;\n private _badge: HTMLButtonElement | null = null;\n private _stateSelect: HTMLSelectElement | null = null;\n private _paneElements: Partial<Record<PaneName, HTMLElement>> = {};\n private _highlightLayer: HTMLElement | null = null;\n private _dirtyPanes: Set<PaneName> = new Set();\n private _renderScheduled: boolean = false;\n private _selectedRosterKey: string | null = null;\n private _selectedPath: string | null = null;\n private _pickedNode: Node | null = null;\n private _pickMode: boolean = false;\n private _expanded: Set<string> = new Set();\n private _hotkeyHandler: ((event: KeyboardEvent) => void) | null = null;\n private _pickHandler: ((event: MouseEvent) => void) | null = null;\n\n get core(): DevtoolsCore | null {\n return this._core;\n }\n\n connectedCallback(): void {\n // SSR では不活性(protocol 原則 6)\n if (document.documentElement.hasAttribute(\"data-wcs-server\")) {\n return;\n }\n if (this.shadowRoot === null) {\n this._buildShadow();\n }\n const capacity = Number(this.getAttribute(\"buffer\") ?? \"\");\n const hidden = (this.getAttribute(\"hidden-states\") ?? \"\")\n .split(\",\")\n .map((name) => name.trim())\n .filter((name) => name.length > 0);\n this._core = new DevtoolsCore({\n timelineCapacity: Number.isFinite(capacity) && capacity > 0 ? capacity : undefined,\n hiddenStateNames: hidden,\n });\n this._removeCoreListener = this._core.onChange((kind) => {\n if (kind === \"roster\" || kind === \"sources\") {\n this._markDirty(\"state\");\n this._markDirty(\"wiring\");\n } else if (kind === \"wiring\") {\n this._markDirty(\"wiring\");\n } else {\n this._markDirty(\"timeline\");\n }\n });\n this._core.connect();\n this._applyDock();\n this._applyOpen();\n this._installHotkey();\n this._markDirty(\"state\");\n this._markDirty(\"wiring\");\n this._markDirty(\"timeline\");\n }\n\n disconnectedCallback(): void {\n this._removeCoreListener?.();\n this._removeCoreListener = null;\n this._core?.disconnect();\n this._core = null;\n this._uninstallHotkey();\n this._exitPickMode();\n }\n\n attributeChangedCallback(name: string): void {\n if (this.shadowRoot === null) {\n return;\n }\n if (name === \"open\") {\n this._applyOpen();\n } else if (name === \"dock\") {\n this._applyDock();\n } else if (name === \"hotkey\") {\n this._uninstallHotkey();\n this._installHotkey();\n }\n }\n\n /** テスト用: rAF を待たずに保留中の描画を実行する */\n __flushRenderForTest(): void {\n this._renderDirty();\n }\n\n // --- shadow construction ---\n\n private _buildShadow(): void {\n const shadow = this.attachShadow({ mode: \"open\" });\n const style = document.createElement(\"style\");\n style.textContent = STYLE_TEXT;\n shadow.append(style);\n\n const badge = document.createElement(\"button\");\n badge.className = \"badge\";\n badge.title = \"wcstack DevTools\";\n badge.textContent = \"WCS\";\n badge.addEventListener(\"click\", () => this.toggle());\n shadow.append(badge);\n this._badge = badge;\n\n const panel = document.createElement(\"div\");\n panel.className = \"panel dock-bottom\";\n panel.hidden = true;\n\n const header = document.createElement(\"header\");\n const title = document.createElement(\"span\");\n title.className = \"title\";\n title.textContent = \"wcstack devtools\";\n header.append(title);\n\n const stateSelect = document.createElement(\"select\");\n stateSelect.title = \"state element\";\n stateSelect.addEventListener(\"change\", () => {\n this._selectedRosterKey = stateSelect.value || null;\n this._selectedPath = null;\n this._expanded.clear();\n this._markDirty(\"state\");\n this._markDirty(\"wiring\");\n });\n header.append(stateSelect);\n this._stateSelect = stateSelect;\n\n const pickButton = this._headerButton(header, \"⌖ pick\", \"pick a page element\");\n pickButton.addEventListener(\"click\", () => {\n if (this._pickMode) {\n this._exitPickMode();\n } else {\n this._enterPickMode();\n }\n pickButton.setAttribute(\"aria-pressed\", String(this._pickMode));\n });\n pickButton.dataset[\"role\"] = \"pick\";\n\n const pauseButton = this._headerButton(header, \"⏸\", \"pause timeline\");\n pauseButton.addEventListener(\"click\", () => {\n const core = this._core;\n if (core === null) {\n return;\n }\n core.paused = !core.paused;\n pauseButton.setAttribute(\"aria-pressed\", String(core.paused));\n });\n pauseButton.dataset[\"role\"] = \"pause\";\n\n const clearButton = this._headerButton(header, \"🗑\", \"clear timeline\");\n clearButton.addEventListener(\"click\", () => {\n this._core?.clearTimeline();\n });\n clearButton.dataset[\"role\"] = \"clear\";\n\n const spacer = document.createElement(\"span\");\n spacer.className = \"spacer\";\n header.append(spacer);\n\n const dockButton = this._headerButton(header, \"dock\", \"toggle dock position\");\n dockButton.addEventListener(\"click\", () => {\n const next = (this.getAttribute(\"dock\") ?? \"bottom\") === \"bottom\" ? \"right\" : \"bottom\";\n this.setAttribute(\"dock\", next);\n });\n dockButton.dataset[\"role\"] = \"dock\";\n\n const closeButton = this._headerButton(header, \"×\", \"close\");\n closeButton.addEventListener(\"click\", () => this.toggle(false));\n closeButton.dataset[\"role\"] = \"close\";\n\n panel.append(header);\n\n const panes = document.createElement(\"div\");\n panes.className = \"panes\";\n for (const [name, heading] of [\n [\"state\", \"State\"],\n [\"wiring\", \"Wiring\"],\n [\"timeline\", \"Timeline\"],\n ] as const) {\n const pane = document.createElement(\"section\");\n pane.className = `pane pane-${name}`;\n const h3 = document.createElement(\"h3\");\n h3.textContent = heading;\n const body = document.createElement(\"div\");\n body.className = \"pane-body\";\n pane.append(h3, body);\n panes.append(pane);\n this._paneElements[name] = body;\n }\n panel.append(panes);\n shadow.append(panel);\n this._panel = panel;\n\n const highlightLayer = document.createElement(\"div\");\n highlightLayer.className = \"hl-layer\";\n shadow.append(highlightLayer);\n this._highlightLayer = highlightLayer;\n }\n\n private _headerButton(header: HTMLElement, label: string, title: string): HTMLButtonElement {\n const button = document.createElement(\"button\");\n button.textContent = label;\n button.title = title;\n button.setAttribute(\"aria-pressed\", \"false\");\n header.append(button);\n return button;\n }\n\n // --- open/close/dock/hotkey ---\n\n get open(): boolean {\n return this.hasAttribute(\"open\");\n }\n\n toggle(force?: boolean): void {\n const next = force ?? !this.open;\n if (next) {\n this.setAttribute(\"open\", \"\");\n } else {\n this.removeAttribute(\"open\");\n }\n }\n\n private _applyOpen(): void {\n // shadowRoot 構築後にしか呼ばれない(attributeChangedCallback 側でガード済み)\n this._panel!.hidden = !this.open;\n this._badge!.hidden = this.open;\n if (this.open) {\n this._markDirty(\"state\");\n this._markDirty(\"wiring\");\n this._markDirty(\"timeline\");\n }\n }\n\n private _applyDock(): void {\n // shadowRoot 構築後にしか呼ばれない(attributeChangedCallback 側でガード済み)\n const dock = this.getAttribute(\"dock\") === \"right\" ? \"right\" : \"bottom\";\n this._panel!.classList.toggle(\"dock-right\", dock === \"right\");\n this._panel!.classList.toggle(\"dock-bottom\", dock === \"bottom\");\n }\n\n private _installHotkey(): void {\n const spec = this.getAttribute(\"hotkey\") ?? \"Alt+Shift+D\";\n if (spec === \"none\") {\n return;\n }\n const parts = spec.split(\"+\").map((part) => part.trim().toLowerCase());\n const key = parts[parts.length - 1];\n const alt = parts.includes(\"alt\");\n const shift = parts.includes(\"shift\");\n const ctrl = parts.includes(\"ctrl\");\n const meta = parts.includes(\"meta\");\n this._hotkeyHandler = (event: KeyboardEvent) => {\n if (\n event.key.toLowerCase() === key &&\n event.altKey === alt &&\n event.shiftKey === shift &&\n event.ctrlKey === ctrl &&\n event.metaKey === meta\n ) {\n event.preventDefault();\n this.toggle();\n }\n };\n window.addEventListener(\"keydown\", this._hotkeyHandler);\n }\n\n private _uninstallHotkey(): void {\n if (this._hotkeyHandler !== null) {\n window.removeEventListener(\"keydown\", this._hotkeyHandler);\n this._hotkeyHandler = null;\n }\n }\n\n // --- pick mode ---\n\n private _enterPickMode(): void {\n // 呼び出し元(pick ボタン)が toggle 済みのため、ここでは常に開始でよい\n this._pickMode = true;\n // click を capture で奪う(誤操作防止、devtools-tag-design.md G-U2 の既定側)\n this._pickHandler = (event: MouseEvent) => {\n const target = event.target as Node;\n // devtools 自身(実ブラウザでは retarget されて host、shadow 非 retarget 環境では\n // shadow 内ノード)は pick 対象外\n if (target.getRootNode() === this.shadowRoot || target === this) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n this._pickedNode = target;\n this._selectedPath = null;\n this._exitPickMode();\n this._markDirty(\"wiring\");\n };\n document.addEventListener(\"click\", this._pickHandler, { capture: true });\n }\n\n private _exitPickMode(): void {\n if (this._pickHandler !== null) {\n document.removeEventListener(\"click\", this._pickHandler, { capture: true });\n this._pickHandler = null;\n }\n this._pickMode = false;\n const pickButton = this.shadowRoot?.querySelector('button[data-role=\"pick\"]');\n pickButton?.setAttribute(\"aria-pressed\", \"false\");\n }\n\n // --- rendering ---\n\n private _markDirty(pane: PaneName): void {\n this._dirtyPanes.add(pane);\n if (this._renderScheduled) {\n return;\n }\n this._renderScheduled = true;\n requestAnimationFrame(() => {\n this._renderDirty();\n });\n }\n\n private _renderDirty(): void {\n this._renderScheduled = false;\n if (this._core === null || this.shadowRoot === null) {\n this._dirtyPanes.clear();\n return;\n }\n const dirty = this._dirtyPanes;\n this._dirtyPanes = new Set();\n if (dirty.has(\"state\")) {\n this._renderStatePane();\n }\n if (dirty.has(\"wiring\")) {\n this._renderWiringPane();\n }\n if (dirty.has(\"timeline\")) {\n this._renderTimelinePane();\n }\n }\n\n private _rosterKey(entry: IRosterEntry): string {\n return `${entry.sourceId}:${entry.name}`;\n }\n\n private _selectedRoster(): IRosterEntry | null {\n const core = this._core!;\n const roster = core.getRoster();\n if (roster.length === 0) {\n return null;\n }\n const found = roster.find((entry) => this._rosterKey(entry) === this._selectedRosterKey);\n return found ?? roster[0];\n }\n\n private _renderStatePane(): void {\n const core = this._core!;\n const body = this._paneElements[\"state\"]!;\n const select = this._stateSelect!;\n const roster = core.getRoster();\n const selected = this._selectedRoster();\n\n select.replaceChildren(\n ...roster.map((entry) => {\n const option = document.createElement(\"option\");\n option.value = this._rosterKey(entry);\n option.textContent = `${entry.name} (${entry.sourceId.slice(0, 12)})`;\n option.selected = selected !== null && this._rosterKey(entry) === this._rosterKey(selected);\n return option;\n })\n );\n\n body.replaceChildren();\n if (selected === null) {\n body.append(this._emptyRow(\"no <wcs-state> elements observed\"));\n return;\n }\n this._selectedRosterKey = this._rosterKey(selected);\n const keys = core.keysOf(selected);\n if (keys.length === 0) {\n body.append(this._emptyRow(\"no readable keys (runtime without keys() API?)\"));\n return;\n }\n for (const key of keys) {\n this._renderTreeNode(body, selected, { path: key, indexes: [] }, key, 0);\n }\n }\n\n private _renderTreeNode(\n container: HTMLElement,\n entry: IRosterEntry,\n ref: ITreeNodeRef,\n label: string,\n depth: number\n ): void {\n const core = this._core!;\n let value: unknown;\n let readable = true;\n try {\n value = core.readValue(entry, ref.path, ref.indexes);\n } catch {\n readable = false;\n }\n\n const row = document.createElement(\"div\");\n row.className = \"tree-row\";\n row.style.paddingLeft = `${depth * 14}px`;\n\n const expandable = readable && isExpandable(value);\n const key = nodeKeyOf(ref);\n const expanded = expandable && this._expanded.has(key);\n\n const toggle = document.createElement(\"span\");\n toggle.className = \"toggle\";\n toggle.textContent = expandable ? (expanded ? \"▾\" : \"▸\") : \"\";\n if (expandable) {\n toggle.addEventListener(\"click\", () => {\n if (this._expanded.has(key)) {\n this._expanded.delete(key);\n } else {\n this._expanded.add(key);\n }\n this._markDirty(\"state\");\n });\n }\n row.append(toggle);\n\n const keySpan = document.createElement(\"span\");\n keySpan.className = \"key\";\n keySpan.textContent = `${label}:`;\n keySpan.title = ref.path;\n keySpan.addEventListener(\"click\", () => {\n this._selectedPath = ref.path;\n this._pickedNode = null;\n this._markDirty(\"wiring\");\n this._highlightPath(entry, ref.path);\n });\n row.append(keySpan);\n\n const valueSpan = document.createElement(\"span\");\n valueSpan.className = \"value\";\n if (!readable) {\n valueSpan.textContent = \"(unreadable getter)\";\n } else {\n valueSpan.textContent = formatValue(value, 1);\n const editable = value === null || typeof value !== \"object\";\n if (editable && typeof value !== \"function\") {\n valueSpan.classList.add(\"editable\");\n valueSpan.title = \"click to edit\";\n valueSpan.addEventListener(\"click\", () => {\n this._beginEdit(row, valueSpan, entry, ref, value);\n });\n }\n }\n row.append(valueSpan);\n container.append(row);\n\n if (expanded) {\n if (Array.isArray(value)) {\n const limit = Math.min(value.length, LIST_CHILD_LIMIT);\n for (let index = 0; index < limit; index++) {\n this._renderTreeNode(\n container,\n entry,\n { path: `${ref.path}.*`, indexes: [...ref.indexes, index] },\n `[${index}]`,\n depth + 1\n );\n }\n if (value.length > limit) {\n const more = this._emptyRow(`…(${value.length} items)`);\n more.style.paddingLeft = `${(depth + 1) * 14}px`;\n container.append(more);\n }\n } else {\n for (const childKey of Object.keys(value as Record<string, unknown>)) {\n this._renderTreeNode(\n container,\n entry,\n { path: `${ref.path}.${childKey}`, indexes: ref.indexes },\n childKey,\n depth + 1\n );\n }\n }\n }\n }\n\n private _beginEdit(\n row: HTMLElement,\n valueSpan: HTMLElement,\n entry: IRosterEntry,\n ref: ITreeNodeRef,\n current: unknown\n ): void {\n const input = document.createElement(\"input\");\n input.value = typeof current === \"string\" ? current : String(current);\n const commit = (): void => {\n // 編集は通常のリアクティブパイプラインを通る(devtools-tag-design.md §3.1)\n this._core?.writeValue(entry, ref.path, coerceInput(input.value), ref.indexes);\n this._markDirty(\"state\");\n };\n input.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\") {\n commit();\n } else if (event.key === \"Escape\") {\n this._markDirty(\"state\");\n }\n });\n row.replaceChild(input, valueSpan);\n input.focus();\n }\n\n private _renderWiringPane(): void {\n const core = this._core!;\n const body = this._paneElements[\"wiring\"]!;\n body.replaceChildren();\n\n let entries: IWiringEntry[];\n let contextLabel: string;\n if (this._pickedNode !== null) {\n entries = core.getWiringForNode(this._pickedNode);\n const target = this._pickedNode;\n contextLabel =\n target instanceof Element ? `<${target.tagName.toLowerCase()}>` : target.nodeName;\n } else if (this._selectedPath !== null) {\n const selected = this._selectedRoster();\n entries =\n selected !== null ? core.getWiringForPath(selected.name, this._selectedPath) : [];\n contextLabel = this._selectedPath;\n } else {\n entries = core.getAllWiring();\n contextLabel = \"all\";\n }\n\n const info = document.createElement(\"div\");\n info.textContent = `context: ${contextLabel} — ${entries.length} live binding${entries.length === 1 ? \"\" : \"s\"}`;\n body.append(info);\n\n if (entries.length > 0) {\n for (const entry of entries) {\n body.append(this._wiringRow(entry));\n }\n return;\n }\n\n // ライブ台帳が空 → declared ビューへフォールバック(protocol §6)\n const selected = this._selectedRoster();\n const declared =\n selected !== null ? scanDeclaredBindings(this._scanRootOf(selected)) : [];\n if (declared.length === 0) {\n body.append(this._emptyRow(\"no bindings observed\"));\n return;\n }\n const notice = document.createElement(\"div\");\n notice.className = \"notice\";\n const tag = document.createElement(\"span\");\n tag.className = \"badge-tag declared\";\n tag.textContent = \"declared\";\n notice.append(tag, document.createTextNode(\" attached late — reload to capture live bindings \"));\n const reload = document.createElement(\"button\");\n reload.textContent = \"reload\";\n reload.addEventListener(\"click\", () => {\n location.reload();\n });\n notice.append(reload);\n body.append(notice);\n for (const entry of declared) {\n body.append(this._declaredRow(entry));\n }\n }\n\n private _scanRootOf(entry: IRosterEntry): ParentNode {\n // instanceof はテスト環境(happy-dom)の Document 実体と一致しないことがあるため\n // nodeType で判定する(DOCUMENT_FRAGMENT_NODE は ShadowRoot を含む)\n const rootNode = entry.rootNode;\n if (\n rootNode.nodeType === Node.DOCUMENT_NODE ||\n rootNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE\n ) {\n return rootNode as unknown as ParentNode;\n }\n return document;\n }\n\n private _wiringRow(entry: IWiringEntry): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"wiring-row\";\n const prop = document.createElement(\"span\");\n prop.className = \"prop\";\n prop.textContent = entry.propName;\n const arrow = document.createTextNode(\" ← \");\n const path = document.createElement(\"span\");\n path.className = \"path\";\n path.textContent = `${entry.path}@${entry.stateName}`;\n const type = document.createElement(\"span\");\n type.className = \"badge-tag\";\n type.textContent = entry.bindingType;\n row.append(type, document.createTextNode(\" \"), prop, arrow, path);\n row.addEventListener(\"click\", () => {\n const binding = entry.bindingRef.deref();\n if (binding !== undefined) {\n this._highlightNodes([binding.node, binding.replaceNode]);\n }\n });\n return row;\n }\n\n private _declaredRow(entry: IDeclaredBinding): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"wiring-row\";\n const type = document.createElement(\"span\");\n type.className = \"badge-tag declared\";\n type.textContent = entry.origin;\n const prop = document.createElement(\"span\");\n prop.className = \"prop\";\n prop.textContent = entry.propName;\n const path = document.createElement(\"span\");\n path.className = \"path\";\n path.textContent = `${entry.path}@${entry.stateName}`;\n row.append(type, document.createTextNode(\" \"), prop, document.createTextNode(\" ← \"), path);\n row.addEventListener(\"click\", () => {\n this._highlightNodes([entry.element]);\n });\n return row;\n }\n\n private _renderTimelinePane(): void {\n const core = this._core!;\n const body = this._paneElements[\"timeline\"]!;\n const timeline = core.getTimeline();\n const start = Math.max(0, timeline.length - TIMELINE_RENDER_LIMIT);\n const rows: HTMLElement[] = [];\n if (start > 0) {\n rows.push(this._emptyRow(`…(${start} earlier entries)`));\n }\n for (let index = start; index < timeline.length; index++) {\n rows.push(this._timelineRow(timeline[index]));\n }\n if (rows.length === 0) {\n rows.push(this._emptyRow(\"no activity yet\"));\n }\n body.replaceChildren(...rows);\n body.scrollTop = body.scrollHeight;\n }\n\n private _timelineRow(entry: ITimelineEntry): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"timeline-row\";\n const time = document.createElement(\"span\");\n time.className = \"t\";\n time.textContent = `${(entry.time / 1000).toFixed(3)}s `;\n const kind = document.createElement(\"span\");\n kind.className = \"badge-tag kind\";\n kind.textContent = entry.kind;\n // subscriber 0 の command/event 空撃ちは警告表示(devtools-tag-design.md §3.2)\n if (entry.subscriberCount === 0) {\n kind.classList.add(\"warn\");\n kind.title = \"emitted with no subscribers\";\n }\n const label = document.createElement(\"span\");\n label.className = \"label\";\n const stateName = entry.stateName !== null ? `@${entry.stateName}` : \"\";\n label.textContent = ` ${entry.label}${stateName} `;\n const detail = document.createElement(\"span\");\n detail.className = \"detail\";\n detail.textContent = entry.detail;\n row.append(time, kind, label, detail);\n return row;\n }\n\n private _emptyRow(text: string): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"empty\";\n row.textContent = text;\n return row;\n }\n\n // --- highlight ---\n\n private _highlightPath(entry: IRosterEntry, path: string): void {\n const core = this._core!;\n const nodes: Node[] = [];\n for (const wiring of core.getWiringForPath(entry.name, path)) {\n const binding = wiring.bindingRef.deref();\n if (binding !== undefined) {\n nodes.push(binding.node, binding.replaceNode);\n }\n }\n this._highlightNodes(nodes);\n }\n\n private _highlightNodes(nodes: readonly Node[]): void {\n // shadowRoot 構築後にしか呼ばれない(各リスナーは _buildShadow 内で配線される)\n const layer = this._highlightLayer!;\n layer.replaceChildren();\n const seen = new Set<Element>();\n for (const node of nodes) {\n const element = node instanceof Element ? node : node.parentElement;\n if (element === null || seen.has(element) || !element.isConnected) {\n continue;\n }\n seen.add(element);\n const rect = element.getBoundingClientRect();\n const box = document.createElement(\"div\");\n box.className = \"hl-box\";\n box.style.left = `${rect.left}px`;\n box.style.top = `${rect.top}px`;\n box.style.width = `${rect.width}px`;\n box.style.height = `${rect.height}px`;\n layer.append(box);\n }\n // 2 秒後に自動で消す(追従はしない — クリック時スナップショット表示)\n setTimeout(() => {\n layer.replaceChildren();\n }, 2000);\n }\n}\n","/**\n * bootstrapDevtools.ts\n *\n * `<wcs-devtools>` の登録と自動挿入(devtools-tag-design.md §2)。\n * - 既に定義済みなら再定義しない\n * - ページに `<wcs-devtools>` が無ければ body 末尾に 1 つ挿入\n * (手動で書かれていれば挿入しない)\n * - SSR では何もしない\n */\n\nimport { WcsDevtools } from \"./shell/WcsDevtools\";\n\nconst TAG_NAME = \"wcs-devtools\";\n\nfunction insertIfAbsent(): void {\n if (document.querySelector(TAG_NAME) !== null) {\n return;\n }\n document.body.appendChild(document.createElement(TAG_NAME));\n}\n\nexport function bootstrapDevtools(): void {\n if (document.documentElement.hasAttribute(\"data-wcs-server\")) {\n return;\n }\n if (!customElements.get(TAG_NAME)) {\n customElements.define(TAG_NAME, WcsDevtools);\n }\n if (document.body !== null) {\n insertIfAbsent();\n } else {\n document.addEventListener(\"DOMContentLoaded\", insertIfAbsent, { once: true });\n }\n}\n"],"names":["DEVTOOLS_HOOK_GLOBAL","getOrCreateHookRegistry","globals","globalThis","existing","undefined","version","console","warn","registry","sources","Map","listeners","Set","applySink","source","size","_setSink","sourceId","id","event","listener","onEvent","register","has","set","onSourceRegistered","unregister","get","delete","onSourceUnregistered","addListener","add","values","createMinimalRegistry","formatValue","value","depth","length","slice","String","toString","objectValue","Array","isArray","shown","map","item","rest","join","proto","Object","getPrototypeOf","prototype","isPlainObject","keys","key","ctor","constructor","name","className","formatArgs","args","arg","text","pathKeyOf","stateName","path","DevtoolsCore","_timelineCapacity","_hiddenStateNames","_removeListener","_sources","_roster","_wiringByPathKey","_wiringEntryByBinding","WeakMap","_timeline","_seq","_paused","_changeListeners","options","this","timelineCapacity","hiddenStateNames","connected","paused","isHiddenStateName","startsWith","connect","_refreshRosterOf","_notify","_ingest","disconnect","clear","onChange","getSources","getRoster","entries","list","push","refreshRoster","getTimeline","clearTimeline","getWiringForPath","_collectAlive","getAllWiring","result","getWiringForNode","node","entry","binding","bindingRef","deref","replaceNode","contains","keysOf","rootNode","readValue","indexes","read","writeValue","write","kind","summary","getStateElements","alive","_appendTimeline","seq","time","performance","now","overflow","splice","_labelOf","address","listIndex","absolutePathInfo","pathInfo","type","label","detail","subscriberCount","absoluteAddress","hasOldValue","oldValue","labels","total","addresses","propName","bindingType","WeakRef","tokenName","COMMENT_PREFIXES","parseEntry","element","raw","origin","trimmed","trim","colon","indexOf","rhs","pathPart","filterParts","split","part","at","lastIndexOf","filters","filter","WcsDevtools","HTMLElement","observedAttributes","_core","_removeCoreListener","_panel","_badge","_stateSelect","_paneElements","_highlightLayer","_dirtyPanes","_renderScheduled","_selectedRosterKey","_selectedPath","_pickedNode","_pickMode","_expanded","_hotkeyHandler","_pickHandler","core","connectedCallback","document","documentElement","hasAttribute","shadowRoot","_buildShadow","capacity","Number","getAttribute","hidden","isFinite","_markDirty","_applyDock","_applyOpen","_installHotkey","disconnectedCallback","_uninstallHotkey","_exitPickMode","attributeChangedCallback","__flushRenderForTest","_renderDirty","shadow","attachShadow","mode","style","createElement","textContent","append","badge","title","addEventListener","toggle","panel","header","stateSelect","pickButton","_headerButton","_enterPickMode","setAttribute","dataset","pauseButton","clearButton","spacer","dockButton","next","closeButton","panes","heading","pane","h3","body","highlightLayer","button","open","force","removeAttribute","dock","classList","spec","parts","toLowerCase","alt","includes","shift","ctrl","meta","altKey","shiftKey","ctrlKey","metaKey","preventDefault","window","removeEventListener","target","getRootNode","stopPropagation","capture","querySelector","requestAnimationFrame","dirty","_renderStatePane","_renderWiringPane","_renderTimelinePane","_rosterKey","_selectedRoster","roster","find","select","selected","replaceChildren","option","_emptyRow","_renderTreeNode","container","ref","readable","row","paddingLeft","expandable","isExpandable","nodeKeyOf","expanded","keySpan","_highlightPath","valueSpan","_beginEdit","limit","Math","min","index","more","childKey","current","input","commit","JSON","parse","coerceInput","replaceChild","focus","contextLabel","Element","tagName","nodeName","info","_wiringRow","declared","root","bindAttributeName","querySelectorAll","walker","ownerDocument","createTreeWalker","NodeFilter","SHOW_COMMENT","comment","nextNode","prefix","candidate","parentElement","parentNode","scanDeclaredBindings","_scanRootOf","notice","tag","createTextNode","reload","location","_declaredRow","nodeType","Node","DOCUMENT_NODE","DOCUMENT_FRAGMENT_NODE","prop","arrow","_highlightNodes","timeline","start","max","rows","_timelineRow","scrollTop","scrollHeight","toFixed","nodes","wiring","layer","seen","isConnected","rect","getBoundingClientRect","box","left","top","width","height","setTimeout","TAG_NAME","insertIfAbsent","appendChild","customElements","define","once"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/devtools",
3
- "version": "1.24.0",
3
+ "version": "1.26.0",
4
4
  "description": "In-page DevTools overlay for wcstack. Inspect state trees, bindings/wiring and update timelines via the DevTools Hook Protocol - one script tag, no build step.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",
package/dist/auto.js DELETED
@@ -1,3 +0,0 @@
1
- import { bootstrapDevtools } from "./index.esm.js";
2
-
3
- bootstrapDevtools();
@@ -1,2 +0,0 @@
1
- const e="__WCSTACK_DEVTOOLS_HOOK__",t=1;function n(){const t=globalThis,n=t[e];if(void 0!==n)return 1!==n.version&&console.warn(`[wcstack/devtools] hook registry version mismatch: found ${n.version}, expected 1. Keeping the existing registry (first-wins).`),n;const i=function(){const e=new Map,t=new Set,n=e=>{if(0===t.size)return void e._setSink(null);const n=e.id;e._setSink(e=>{for(const i of t)i.onEvent?.(n,e)})};return{version:1,sources:e,register(i){if(!e.has(i.id)){e.set(i.id,i),n(i);for(const e of t)e.onSourceRegistered?.(i)}},unregister(n){const i=e.get(n);if(void 0!==i){i._setSink(null),e.delete(n);for(const e of t)e.onSourceUnregistered?.(n)}},addListener(i){t.add(i);for(const t of e.values())n(t),i.onSourceRegistered?.(t);return()=>{if(t.delete(i))for(const t of e.values())n(t)}}}}();return t[e]=i,i}function i(e,t=2){switch(typeof e){case"string":return`"${e.length>80?e.slice(0,80)+"…":e}"`;case"number":case"boolean":case"bigint":return String(e);case"symbol":return e.toString();case"undefined":return"undefined";case"function":return"[[Function]]"}if(null===e)return"null";const n=e;if(Array.isArray(n)){if(t<=0)return`[[Array(${n.length})]]`;const e=n.slice(0,3).map(e=>i(e,t-1)),s=n.length>3?`, …(${n.length})`:"";return`[${e.join(", ")}${s}]`}if(function(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(n)){if(t<=0)return"[[Object]]";const e=Object.keys(n),s=e.slice(0,3).map(e=>`${e}: ${i(n[e],t-1)}`),o=e.length>3?`, …(${e.length})`:"";return`{${s.join(", ")}${o}}`}return`[[${function(e){const t=e.constructor,n=t?.name;return"string"==typeof n&&n.length>0?n:"Object"}(n)}]]`}function s(e){if(0===e.length)return"";const t=e.slice(0,3).map(e=>{const t=i(e,1);return t.length>80?t.slice(0,80)+"…":t}),n=e.length>3?`, …(${e.length})`:"";return`${t.join(", ")}${n}`}const o="wcs-devtools";function r(e,t){return e+"\0"+t}class a{_timelineCapacity;_hiddenStateNames;_removeListener=null;_sources=new Map;_roster=new Map;_wiringByPathKey=new Map;_wiringEntryByBinding=new WeakMap;_timeline=[];_seq=0;_paused=!1;_changeListeners=new Set;constructor(e){this._timelineCapacity=e?.timelineCapacity??500,this._hiddenStateNames=new Set(e?.hiddenStateNames??[])}get connected(){return null!==this._removeListener}get paused(){return this._paused}set paused(e){this._paused=e}isHiddenStateName(e){return null!==e&&(e.startsWith(o)||this._hiddenStateNames.has(e))}connect(){if(null!==this._removeListener)return;const e=n();this._removeListener=e.addListener({onSourceRegistered:e=>{this._sources.set(e.id,e),this._refreshRosterOf(e),this._notify("sources")},onSourceUnregistered:e=>{this._sources.delete(e),this._roster.delete(e),this._notify("sources"),this._notify("roster")},onEvent:(e,t)=>{this._ingest(e,t)}})}disconnect(){null!==this._removeListener&&(this._removeListener(),this._removeListener=null,this._sources.clear(),this._roster.clear(),this._wiringByPathKey.clear(),this._wiringEntryByBinding=new WeakMap,this._notify("sources"),this._notify("roster"),this._notify("wiring"))}onChange(e){return this._changeListeners.add(e),()=>{this._changeListeners.delete(e)}}getSources(){return[...this._sources.values()]}getRoster(){const e=[];for(const t of this._roster.values())e.push(...t);return e}refreshRoster(){for(const e of this._sources.values())this._refreshRosterOf(e);this._notify("roster")}getTimeline(){return this._timeline}clearTimeline(){this._timeline=[],this._notify("timeline")}getWiringForPath(e,t){const n=this._wiringByPathKey.get(r(e,t));return void 0===n?[]:this._collectAlive(n)}getAllWiring(){const e=[];for(const t of this._wiringByPathKey.values())e.push(...this._collectAlive(t));return e}getWiringForNode(e){const t=[];for(const n of this._wiringByPathKey.values())for(const i of this._collectAlive(n)){const n=i.bindingRef.deref();(n.node===e||n.replaceNode===e||e.contains(n.node)||e.contains(n.replaceNode))&&t.push(i)}return t}keysOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.keys?[]:t.keys(e.name,e.rootNode)}readValue(e,t,n){const i=this._sources.get(e.sourceId);if(void 0!==i)return i.read(e.name,e.rootNode,t,n)}writeValue(e,t,n,i){const s=this._sources.get(e.sourceId);void 0!==s&&s.write(e.name,e.rootNode,t,n,i)}_notify(e){for(const t of this._changeListeners)t(e)}_refreshRosterOf(e){const t=[];for(const n of e.getStateElements())this.isHiddenStateName(n.name)||t.push({sourceId:e.id,name:n.name,rootNode:n.rootNode,summary:n});this._roster.set(e.id,t)}_collectAlive(e){const t=[];for(const n of e)void 0!==n.bindingRef.deref()?t.push(n):e.delete(n);return t}_appendTimeline(e){if(this._paused)return;this._timeline.push({...e,seq:this._seq++,time:performance.now()});const t=this._timeline.length-this._timelineCapacity;t>0&&this._timeline.splice(0,t),this._notify("timeline")}_labelOf(e){const t=e.listIndex?.indexes,n=e.absolutePathInfo.pathInfo.path;return void 0!==t?`${n}[${t.join(",")}]`:n}_ingest(e,t){switch(t.type){case"state:element-registered":{if(this.isHiddenStateName(t.name))return;const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-registered",stateName:t.name,label:t.name,detail:"",subscriberCount:null})}case"state:element-unregistered":{if(this.isHiddenStateName(t.name))return;const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-unregistered",stateName:t.name,label:t.name,detail:"",subscriberCount:null})}case"state:write":{const n=t.absoluteAddress.absolutePathInfo.stateName;if(this.isHiddenStateName(n))return;const s=t.hasOldValue?`${i(t.value)} (was ${i(t.oldValue)})`:i(t.value);return void this._appendTimeline({sourceId:e,kind:"write",stateName:n,label:this._labelOf(t.absoluteAddress),detail:s,subscriberCount:null})}case"state:update-batch":{const n=[];let i=0;for(const e of t.addresses)this.isHiddenStateName(e.absolutePathInfo.stateName)||(i++,n.length<3&&n.push(this._labelOf(e)));if(0===i)return;const s=i>n.length?`, …(${i})`:"";return void this._appendTimeline({sourceId:e,kind:"batch",stateName:null,label:`${i} address${1===i?"":"es"}`,detail:`${n.join(", ")}${s}`,subscriberCount:null})}case"state:binding-added":{const n=t.absoluteAddress.absolutePathInfo.stateName;if(this.isHiddenStateName(n))return;const i=t.absoluteAddress.absolutePathInfo.pathInfo.path,s=r(n,i);let o=this._wiringByPathKey.get(s);void 0===o&&(o=new Set,this._wiringByPathKey.set(s,o));const a={sourceId:e,stateName:n,path:i,propName:t.binding.propName,bindingType:t.binding.bindingType,bindingRef:new WeakRef(t.binding)};return o.add(a),this._wiringEntryByBinding.set(t.binding,a),void this._notify("wiring")}case"state:binding-removed":{const e=this._wiringEntryByBinding.get(t.binding);if(void 0===e)return;this._wiringEntryByBinding.delete(t.binding);const n=r(e.stateName,e.path),i=this._wiringByPathKey.get(n);return void 0!==i&&(i.delete(e),0===i.size&&this._wiringByPathKey.delete(n)),void this._notify("wiring")}case"state:binding-cleared":{const e=r(t.absoluteAddress.absolutePathInfo.stateName,t.absoluteAddress.absolutePathInfo.pathInfo.path);return void(this._wiringByPathKey.delete(e)&&this._notify("wiring"))}case"state:token-emit":if(this.isHiddenStateName(t.stateName))return;return void this._appendTimeline({sourceId:e,kind:t.kind,stateName:t.stateName,label:t.tokenName,detail:s(t.args),subscriberCount:t.subscriberCount})}}}const l=["wcs-text","wcs-for","wcs-if","wcs-elseif","wcs-else"];function d(e,t,n){const i=t.trim();if(0===i.length)return null;const s=i.indexOf(":");if(s<0)return null;const o=i.slice(0,s).trim(),r=i.slice(s+1).trim();if(0===o.length||0===r.length)return null;const[a,...l]=r.split("|").map(e=>e.trim());let d=a,c="default";const h=a.lastIndexOf("@");return h>0&&(d=a.slice(0,h).trim(),c=a.slice(h+1).trim()),{element:e,propName:o,path:d,stateName:c,filters:l.filter(e=>e.length>0),origin:n,raw:i}}function c(e,t="data-wcs"){const n=[];for(const i of e.querySelectorAll(`[${t}]`)){const e=i.getAttribute(t);for(const t of e.split(";")){const e=d(i,t,"attribute");null!==e&&n.push(e)}}const i=(e.ownerDocument??e).createTreeWalker(e,NodeFilter.SHOW_COMMENT);let s=i.nextNode();for(;null!==s;){const e=s.textContent.trim(),t=l.find(t=>e===t||e.startsWith(t+":"));if(void 0!==t){const i=s.parentNode instanceof Element?s.parentNode:null;if(null!==i){const s=e===t?"":e.slice(t.length+1).trim();if(s.length>0){const e="wcs-text"===t?"textContent":t.slice(4);n.push(d(i,`${e}: ${s}`,"comment"))}}}s=i.nextNode()}return n}class h extends HTMLElement{static get observedAttributes(){return["open","dock","hotkey"]}_core=null;_removeCoreListener=null;_panel=null;_badge=null;_stateSelect=null;_paneElements={};_highlightLayer=null;_dirtyPanes=new Set;_renderScheduled=!1;_selectedRosterKey=null;_selectedPath=null;_pickedNode=null;_pickMode=!1;_expanded=new Set;_hotkeyHandler=null;_pickHandler=null;get core(){return this._core}connectedCallback(){if(document.documentElement.hasAttribute("data-wcs-server"))return;null===this.shadowRoot&&this._buildShadow();const e=Number(this.getAttribute("buffer")??""),t=(this.getAttribute("hidden-states")??"").split(",").map(e=>e.trim()).filter(e=>e.length>0);this._core=new a({timelineCapacity:Number.isFinite(e)&&e>0?e:void 0,hiddenStateNames:t}),this._removeCoreListener=this._core.onChange(e=>{"roster"===e||"sources"===e?(this._markDirty("state"),this._markDirty("wiring")):"wiring"===e?this._markDirty("wiring"):this._markDirty("timeline")}),this._core.connect(),this._applyDock(),this._applyOpen(),this._installHotkey(),this._markDirty("state"),this._markDirty("wiring"),this._markDirty("timeline")}disconnectedCallback(){this._removeCoreListener?.(),this._removeCoreListener=null,this._core?.disconnect(),this._core=null,this._uninstallHotkey(),this._exitPickMode()}attributeChangedCallback(e){null!==this.shadowRoot&&("open"===e?this._applyOpen():"dock"===e?this._applyDock():"hotkey"===e&&(this._uninstallHotkey(),this._installHotkey()))}__flushRenderForTest(){this._renderDirty()}_buildShadow(){const e=this.attachShadow({mode:"open"}),t=document.createElement("style");t.textContent='\n:host {\n all: initial;\n position: fixed;\n z-index: 2147483647;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n inset: auto 0 0 auto;\n}\n* { box-sizing: border-box; }\n.badge {\n position: fixed;\n right: 12px;\n bottom: 12px;\n width: 40px;\n height: 40px;\n border-radius: 20px;\n border: 1px solid #2b4f78;\n background: #10263f;\n color: #9fd0ff;\n font-weight: 700;\n cursor: pointer;\n}\n.panel {\n position: fixed;\n display: flex;\n flex-direction: column;\n background: #0d1b2a;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n box-shadow: 0 0 24px rgba(0,0,0,.5);\n}\n.panel.dock-bottom { left: 0; right: 0; bottom: 0; height: 45vh; }\n.panel.dock-right { top: 0; right: 0; bottom: 0; width: 420px; }\n.panel[hidden] { display: none; }\nheader {\n display: flex;\n gap: 6px;\n align-items: center;\n padding: 6px 8px;\n border-bottom: 1px solid #2b4f78;\n background: #10263f;\n}\nheader .title { font-weight: 700; color: #9fd0ff; margin-right: 4px; }\nheader select, header button {\n font: inherit;\n background: #16324f;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n border-radius: 4px;\n padding: 2px 8px;\n cursor: pointer;\n}\nheader button[aria-pressed="true"] { background: #2b5d8f; }\nheader .spacer { flex: 1; }\n.panes { display: flex; flex: 1; min-height: 0; }\n.pane { flex: 1; min-width: 0; overflow: auto; padding: 6px 8px; border-right: 1px solid #1d3a5c; }\n.pane:last-child { border-right: none; }\n.pane h3 {\n margin: 0 0 6px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: .08em;\n color: #7ba7d4;\n}\n.tree-row { display: flex; gap: 6px; padding: 1px 0; align-items: baseline; white-space: nowrap; }\n.tree-row .toggle { width: 14px; cursor: pointer; color: #7ba7d4; user-select: none; }\n.tree-row .key { color: #9fd0ff; cursor: pointer; }\n.tree-row .value { color: #ffd9a0; overflow: hidden; text-overflow: ellipsis; }\n.tree-row .value.editable { cursor: pointer; }\n.tree-row input { font: inherit; background: #16324f; color: #ffd9a0; border: 1px solid #2b4f78; }\n.badge-tag {\n display: inline-block;\n padding: 0 4px;\n border-radius: 3px;\n font-size: 10px;\n background: #26456a;\n color: #a8c6e8;\n}\n.badge-tag.warn { background: #6a3326; color: #ffb3a0; }\n.badge-tag.declared { background: #4a4426; color: #efe3a0; }\n.wiring-row, .timeline-row { padding: 1px 0; white-space: nowrap; }\n.wiring-row .prop { color: #b7f0c0; }\n.wiring-row .path { color: #9fd0ff; }\n.timeline-row .t { color: #6f88a3; }\n.timeline-row .label { color: #9fd0ff; }\n.timeline-row .detail { color: #ffd9a0; }\n.timeline-row .kind { display: inline-block; min-width: 52px; text-align: center; }\n.empty { color: #6f88a3; font-style: italic; padding: 4px 0; }\n.notice { color: #efe3a0; padding: 2px 0 6px; }\n.notice button { font: inherit; margin-left: 6px; cursor: pointer; }\n.hl-box {\n position: fixed;\n pointer-events: none;\n border: 1px solid #58c2ff;\n background: rgba(88,194,255,.18);\n}\n',e.append(t);const n=document.createElement("button");n.className="badge",n.title="wcstack DevTools",n.textContent="WCS",n.addEventListener("click",()=>this.toggle()),e.append(n),this._badge=n;const i=document.createElement("div");i.className="panel dock-bottom",i.hidden=!0;const s=document.createElement("header"),o=document.createElement("span");o.className="title",o.textContent="wcstack devtools",s.append(o);const r=document.createElement("select");r.title="state element",r.addEventListener("change",()=>{this._selectedRosterKey=r.value||null,this._selectedPath=null,this._expanded.clear(),this._markDirty("state"),this._markDirty("wiring")}),s.append(r),this._stateSelect=r;const a=this._headerButton(s,"⌖ pick","pick a page element");a.addEventListener("click",()=>{this._pickMode?this._exitPickMode():this._enterPickMode(),a.setAttribute("aria-pressed",String(this._pickMode))}),a.dataset.role="pick";const l=this._headerButton(s,"⏸","pause timeline");l.addEventListener("click",()=>{const e=this._core;null!==e&&(e.paused=!e.paused,l.setAttribute("aria-pressed",String(e.paused)))}),l.dataset.role="pause";const d=this._headerButton(s,"🗑","clear timeline");d.addEventListener("click",()=>{this._core?.clearTimeline()}),d.dataset.role="clear";const c=document.createElement("span");c.className="spacer",s.append(c);const h=this._headerButton(s,"dock","toggle dock position");h.addEventListener("click",()=>{const e="bottom"===(this.getAttribute("dock")??"bottom")?"right":"bottom";this.setAttribute("dock",e)}),h.dataset.role="dock";const u=this._headerButton(s,"×","close");u.addEventListener("click",()=>this.toggle(!1)),u.dataset.role="close",i.append(s);const p=document.createElement("div");p.className="panes";for(const[e,t]of[["state","State"],["wiring","Wiring"],["timeline","Timeline"]]){const n=document.createElement("section");n.className=`pane pane-${e}`;const i=document.createElement("h3");i.textContent=t;const s=document.createElement("div");s.className="pane-body",n.append(i,s),p.append(n),this._paneElements[e]=s}i.append(p),e.append(i),this._panel=i;const m=document.createElement("div");m.className="hl-layer",e.append(m),this._highlightLayer=m}_headerButton(e,t,n){const i=document.createElement("button");return i.textContent=t,i.title=n,i.setAttribute("aria-pressed","false"),e.append(i),i}get open(){return this.hasAttribute("open")}toggle(e){e??!this.open?this.setAttribute("open",""):this.removeAttribute("open")}_applyOpen(){this._panel.hidden=!this.open,this._badge.hidden=this.open,this.open&&(this._markDirty("state"),this._markDirty("wiring"),this._markDirty("timeline"))}_applyDock(){const e="right"===this.getAttribute("dock")?"right":"bottom";this._panel.classList.toggle("dock-right","right"===e),this._panel.classList.toggle("dock-bottom","bottom"===e)}_installHotkey(){const e=this.getAttribute("hotkey")??"Alt+Shift+D";if("none"===e)return;const t=e.split("+").map(e=>e.trim().toLowerCase()),n=t[t.length-1],i=t.includes("alt"),s=t.includes("shift"),o=t.includes("ctrl"),r=t.includes("meta");this._hotkeyHandler=e=>{e.key.toLowerCase()===n&&e.altKey===i&&e.shiftKey===s&&e.ctrlKey===o&&e.metaKey===r&&(e.preventDefault(),this.toggle())},window.addEventListener("keydown",this._hotkeyHandler)}_uninstallHotkey(){null!==this._hotkeyHandler&&(window.removeEventListener("keydown",this._hotkeyHandler),this._hotkeyHandler=null)}_enterPickMode(){this._pickMode=!0,this._pickHandler=e=>{const t=e.target;t.getRootNode()!==this.shadowRoot&&t!==this&&(e.preventDefault(),e.stopPropagation(),this._pickedNode=t,this._selectedPath=null,this._exitPickMode(),this._markDirty("wiring"))},document.addEventListener("click",this._pickHandler,{capture:!0})}_exitPickMode(){null!==this._pickHandler&&(document.removeEventListener("click",this._pickHandler,{capture:!0}),this._pickHandler=null),this._pickMode=!1;const e=this.shadowRoot?.querySelector('button[data-role="pick"]');e?.setAttribute("aria-pressed","false")}_markDirty(e){this._dirtyPanes.add(e),this._renderScheduled||(this._renderScheduled=!0,requestAnimationFrame(()=>{this._renderDirty()}))}_renderDirty(){if(this._renderScheduled=!1,null===this._core||null===this.shadowRoot)return void this._dirtyPanes.clear();const e=this._dirtyPanes;this._dirtyPanes=new Set,e.has("state")&&this._renderStatePane(),e.has("wiring")&&this._renderWiringPane(),e.has("timeline")&&this._renderTimelinePane()}_rosterKey(e){return`${e.sourceId}:${e.name}`}_selectedRoster(){const e=this._core.getRoster();if(0===e.length)return null;return e.find(e=>this._rosterKey(e)===this._selectedRosterKey)??e[0]}_renderStatePane(){const e=this._core,t=this._paneElements.state,n=this._stateSelect,i=e.getRoster(),s=this._selectedRoster();if(n.replaceChildren(...i.map(e=>{const t=document.createElement("option");return t.value=this._rosterKey(e),t.textContent=`${e.name} (${e.sourceId.slice(0,12)})`,t.selected=null!==s&&this._rosterKey(e)===this._rosterKey(s),t})),t.replaceChildren(),null===s)return void t.append(this._emptyRow("no <wcs-state> elements observed"));this._selectedRosterKey=this._rosterKey(s);const o=e.keysOf(s);if(0!==o.length)for(const e of o)this._renderTreeNode(t,s,{path:e,indexes:[]},e,0);else t.append(this._emptyRow("no readable keys (runtime without keys() API?)"))}_renderTreeNode(e,t,n,s,o){const r=this._core;let a,l=!0;try{a=r.readValue(t,n.path,n.indexes)}catch{l=!1}const d=document.createElement("div");d.className="tree-row",d.style.paddingLeft=14*o+"px";const c=l&&function(e){if(Array.isArray(e))return!0;if(null===e||"object"!=typeof e)return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(a),h=function(e){return`${e.path}#${e.indexes.join(",")}`}(n),u=c&&this._expanded.has(h),p=document.createElement("span");p.className="toggle",p.textContent=c?u?"▾":"▸":"",c&&p.addEventListener("click",()=>{this._expanded.has(h)?this._expanded.delete(h):this._expanded.add(h),this._markDirty("state")}),d.append(p);const m=document.createElement("span");m.className="key",m.textContent=`${s}:`,m.title=n.path,m.addEventListener("click",()=>{this._selectedPath=n.path,this._pickedNode=null,this._markDirty("wiring"),this._highlightPath(t,n.path)}),d.append(m);const g=document.createElement("span");if(g.className="value",l){g.textContent=i(a,1);(null===a||"object"!=typeof a)&&"function"!=typeof a&&(g.classList.add("editable"),g.title="click to edit",g.addEventListener("click",()=>{this._beginEdit(d,g,t,n,a)}))}else g.textContent="(unreadable getter)";if(d.append(g),e.append(d),u)if(Array.isArray(a)){const i=Math.min(a.length,20);for(let s=0;s<i;s++)this._renderTreeNode(e,t,{path:`${n.path}.*`,indexes:[...n.indexes,s]},`[${s}]`,o+1);if(a.length>i){const t=this._emptyRow(`…(${a.length} items)`);t.style.paddingLeft=14*(o+1)+"px",e.append(t)}}else for(const i of Object.keys(a))this._renderTreeNode(e,t,{path:`${n.path}.${i}`,indexes:n.indexes},i,o+1)}_beginEdit(e,t,n,i,s){const o=document.createElement("input");o.value="string"==typeof s?s:String(s);const r=()=>{this._core?.writeValue(n,i.path,function(e){const t=e.trim();try{return JSON.parse(t)}catch{return e}}(o.value),i.indexes),this._markDirty("state")};o.addEventListener("keydown",e=>{"Enter"===e.key?r():"Escape"===e.key&&this._markDirty("state")}),e.replaceChild(o,t),o.focus()}_renderWiringPane(){const e=this._core,t=this._paneElements.wiring;let n,i;if(t.replaceChildren(),null!==this._pickedNode){n=e.getWiringForNode(this._pickedNode);const t=this._pickedNode;i=t instanceof Element?`<${t.tagName.toLowerCase()}>`:t.nodeName}else if(null!==this._selectedPath){const t=this._selectedRoster();n=null!==t?e.getWiringForPath(t.name,this._selectedPath):[],i=this._selectedPath}else n=e.getAllWiring(),i="all";const s=document.createElement("div");if(s.textContent=`context: ${i} — ${n.length} live binding${1===n.length?"":"s"}`,t.append(s),n.length>0){for(const e of n)t.append(this._wiringRow(e));return}const o=this._selectedRoster(),r=null!==o?c(this._scanRootOf(o)):[];if(0===r.length)return void t.append(this._emptyRow("no bindings observed"));const a=document.createElement("div");a.className="notice";const l=document.createElement("span");l.className="badge-tag declared",l.textContent="declared",a.append(l,document.createTextNode(" attached late — reload to capture live bindings "));const d=document.createElement("button");d.textContent="reload",d.addEventListener("click",()=>{location.reload()}),a.append(d),t.append(a);for(const e of r)t.append(this._declaredRow(e))}_scanRootOf(e){const t=e.rootNode;return t.nodeType===Node.DOCUMENT_NODE||t.nodeType===Node.DOCUMENT_FRAGMENT_NODE?t:document}_wiringRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="prop",n.textContent=e.propName;const i=document.createTextNode(" ← "),s=document.createElement("span");s.className="path",s.textContent=`${e.path}@${e.stateName}`;const o=document.createElement("span");return o.className="badge-tag",o.textContent=e.bindingType,t.append(o,document.createTextNode(" "),n,i,s),t.addEventListener("click",()=>{const t=e.bindingRef.deref();void 0!==t&&this._highlightNodes([t.node,t.replaceNode])}),t}_declaredRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="badge-tag declared",n.textContent=e.origin;const i=document.createElement("span");i.className="prop",i.textContent=e.propName;const s=document.createElement("span");return s.className="path",s.textContent=`${e.path}@${e.stateName}`,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),s),t.addEventListener("click",()=>{this._highlightNodes([e.element])}),t}_renderTimelinePane(){const e=this._core,t=this._paneElements.timeline,n=e.getTimeline(),i=Math.max(0,n.length-200),s=[];i>0&&s.push(this._emptyRow(`…(${i} earlier entries)`));for(let e=i;e<n.length;e++)s.push(this._timelineRow(n[e]));0===s.length&&s.push(this._emptyRow("no activity yet")),t.replaceChildren(...s),t.scrollTop=t.scrollHeight}_timelineRow(e){const t=document.createElement("div");t.className="timeline-row";const n=document.createElement("span");n.className="t",n.textContent=`${(e.time/1e3).toFixed(3)}s `;const i=document.createElement("span");i.className="badge-tag kind",i.textContent=e.kind,0===e.subscriberCount&&(i.classList.add("warn"),i.title="emitted with no subscribers");const s=document.createElement("span");s.className="label";const o=null!==e.stateName?`@${e.stateName}`:"";s.textContent=` ${e.label}${o} `;const r=document.createElement("span");return r.className="detail",r.textContent=e.detail,t.append(n,i,s,r),t}_emptyRow(e){const t=document.createElement("div");return t.className="empty",t.textContent=e,t}_highlightPath(e,t){const n=this._core,i=[];for(const s of n.getWiringForPath(e.name,t)){const e=s.bindingRef.deref();void 0!==e&&i.push(e.node,e.replaceNode)}this._highlightNodes(i)}_highlightNodes(e){const t=this._highlightLayer;t.replaceChildren();const n=new Set;for(const i of e){const e=i instanceof Element?i:i.parentElement;if(null===e||n.has(e)||!e.isConnected)continue;n.add(e);const s=e.getBoundingClientRect(),o=document.createElement("div");o.className="hl-box",o.style.left=`${s.left}px`,o.style.top=`${s.top}px`,o.style.width=`${s.width}px`,o.style.height=`${s.height}px`,t.append(o)}setTimeout(()=>{t.replaceChildren()},2e3)}}const u="wcs-devtools";function p(){null===document.querySelector(u)&&document.body.appendChild(document.createElement(u))}function m(){document.documentElement.hasAttribute("data-wcs-server")||(customElements.get(u)||customElements.define(u,h),null!==document.body?p():document.addEventListener("DOMContentLoaded",p,{once:!0}))}export{e as DEVTOOLS_HOOK_GLOBAL,t as DEVTOOLS_PROTOCOL_VERSION,a as DevtoolsCore,o as RESERVED_STATE_NAME_PREFIX,h as WcsDevtools,m as bootstrapDevtools,s as formatArgs,i as formatValue,n as getOrCreateHookRegistry,c as scanDeclaredBindings};
2
- //# sourceMappingURL=index.esm.min.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.esm.min.js","sources":["../src/protocol/types.ts","../src/protocol/registry.ts","../src/core/formatValue.ts","../src/core/DevtoolsCore.ts","../src/core/declaredScan.ts","../src/shell/WcsDevtools.ts","../src/bootstrapDevtools.ts"],"sourcesContent":["/**\n * protocol/types.ts\n *\n * DevTools Hook Protocol (docs/devtools-hook-protocol.md) の devtools 側型定義。\n *\n * ランタイム(@wcstack/state)側の内部型は import しない — プロトコルは\n * 「文書化された構造」への構造的型付けで両側が独立に実装する(protocol §2)。\n * そのためランタイム内部オブジェクトは *Like インターフェースとして、\n * devtools が実際に触るプロパティだけを宣言する。\n */\n\n/** グローバル registry のプロパティ名 */\nexport const DEVTOOLS_HOOK_GLOBAL = \"__WCSTACK_DEVTOOLS_HOOK__\";\n\n/** プロトコル版。additive change では上げない(protocol §2) */\nexport const DEVTOOLS_PROTOCOL_VERSION = 1;\n\nexport interface IPathInfoLike {\n readonly path: string;\n}\n\nexport interface IAbsolutePathInfoLike {\n readonly stateName: string;\n readonly pathInfo: IPathInfoLike;\n}\n\nexport interface IListIndexLike {\n readonly index: number;\n readonly indexes: number[];\n}\n\nexport interface IAbsoluteAddressLike {\n readonly absolutePathInfo: IAbsolutePathInfoLike;\n readonly listIndex: IListIndexLike | null;\n}\n\nexport interface IBindingLike {\n readonly propName: string;\n readonly statePathName: string;\n readonly stateName: string;\n readonly bindingType: string;\n readonly node: Node;\n readonly replaceNode: Node;\n}\n\nexport interface IStateElementSummaryLike {\n readonly name: string;\n readonly rootNode: Node;\n readonly element: unknown;\n readonly paths: {\n readonly list: ReadonlySet<string>;\n readonly element: ReadonlySet<string>;\n readonly getter: ReadonlySet<string>;\n readonly setter: ReadonlySet<string>;\n };\n readonly commandTokenNames: ReadonlySet<string>;\n readonly eventTokenNames: ReadonlySet<string>;\n readonly staticDependency: ReadonlyMap<string, readonly string[]>;\n readonly dynamicDependency: ReadonlyMap<string, readonly string[]>;\n}\n\nexport type DevtoolsEventLike =\n | {\n readonly type: \"state:element-registered\";\n readonly name: string;\n readonly rootNode: Node;\n readonly element: unknown;\n }\n | {\n readonly type: \"state:element-unregistered\";\n readonly name: string;\n readonly rootNode: Node;\n readonly element: unknown;\n }\n | {\n readonly type: \"state:write\";\n readonly absoluteAddress: IAbsoluteAddressLike;\n readonly value: unknown;\n readonly oldValue: unknown;\n readonly hasOldValue: boolean;\n }\n | {\n readonly type: \"state:update-batch\";\n readonly addresses: ReadonlySet<IAbsoluteAddressLike>;\n }\n | {\n readonly type: \"state:binding-added\";\n readonly absoluteAddress: IAbsoluteAddressLike;\n readonly binding: IBindingLike;\n }\n | {\n readonly type: \"state:binding-removed\";\n readonly absoluteAddress: IAbsoluteAddressLike;\n readonly binding: IBindingLike;\n }\n | {\n readonly type: \"state:binding-cleared\";\n readonly absoluteAddress: IAbsoluteAddressLike;\n }\n | {\n readonly type: \"state:token-emit\";\n readonly kind: \"command\" | \"event\";\n readonly stateName: string | null;\n readonly tokenName: string;\n readonly args: readonly unknown[];\n readonly subscriberCount: number;\n };\n\nexport type DevtoolsSinkLike = (event: DevtoolsEventLike) => void;\n\nexport interface IDevtoolsSourceLike {\n readonly id: string;\n readonly kind: string;\n readonly packageVersion: string;\n getStateElements(): IStateElementSummaryLike[];\n /** protocol v1 追補 API。古いランタイムには無い可能性があるため optional 扱いで呼ぶ */\n keys?(name: string, rootNode: Node): string[];\n read(name: string, rootNode: Node, path: string, indexes?: number[]): unknown;\n write(name: string, rootNode: Node, path: string, value: unknown, indexes?: number[]): void;\n _setSink(sink: DevtoolsSinkLike | null): void;\n}\n\nexport interface IDevtoolsListenerLike {\n onSourceRegistered?(source: IDevtoolsSourceLike): void;\n onSourceUnregistered?(sourceId: string): void;\n onEvent?(sourceId: string, event: DevtoolsEventLike): void;\n}\n\nexport interface IDevtoolsHookRegistryLike {\n readonly version: number;\n readonly sources: Map<string, IDevtoolsSourceLike>;\n register(source: IDevtoolsSourceLike): void;\n unregister(sourceId: string): void;\n addListener(listener: IDevtoolsListenerLike): () => void;\n}\n","/**\n * protocol/registry.ts\n *\n * registry 最小実装の devtools 側コピー(protocol §2)。\n * ロード順非依存にするため、ランタイム側(@wcstack/state の bridge)と\n * devtools 側の両方が同一仕様の最小実装を持ち、先にロードされた方が\n * globalThis に置く(先勝ち・振る舞い差し替えなし)。\n */\n\nimport {\n DEVTOOLS_HOOK_GLOBAL,\n DEVTOOLS_PROTOCOL_VERSION,\n IDevtoolsHookRegistryLike,\n IDevtoolsListenerLike,\n IDevtoolsSourceLike,\n} from \"./types\";\n\nfunction createMinimalRegistry(): IDevtoolsHookRegistryLike {\n const sources = new Map<string, IDevtoolsSourceLike>();\n const listeners = new Set<IDevtoolsListenerLike>();\n const applySink = (source: IDevtoolsSourceLike): void => {\n if (listeners.size === 0) {\n source._setSink(null);\n return;\n }\n const sourceId = source.id;\n source._setSink((event) => {\n for (const listener of listeners) {\n listener.onEvent?.(sourceId, event);\n }\n });\n };\n return {\n version: DEVTOOLS_PROTOCOL_VERSION,\n sources,\n register(source: IDevtoolsSourceLike): void {\n if (sources.has(source.id)) {\n return;\n }\n sources.set(source.id, source);\n applySink(source);\n for (const listener of listeners) {\n listener.onSourceRegistered?.(source);\n }\n },\n unregister(sourceId: string): void {\n const source = sources.get(sourceId);\n if (source === undefined) {\n return;\n }\n source._setSink(null);\n sources.delete(sourceId);\n for (const listener of listeners) {\n listener.onSourceUnregistered?.(sourceId);\n }\n },\n addListener(listener: IDevtoolsListenerLike): () => void {\n listeners.add(listener);\n for (const source of sources.values()) {\n applySink(source);\n listener.onSourceRegistered?.(source);\n }\n return () => {\n if (!listeners.delete(listener)) {\n return;\n }\n for (const source of sources.values()) {\n applySink(source);\n }\n };\n },\n };\n}\n\nexport function getOrCreateHookRegistry(): IDevtoolsHookRegistryLike {\n const globals = globalThis as unknown as Record<string, unknown>;\n const existing = globals[DEVTOOLS_HOOK_GLOBAL] as IDevtoolsHookRegistryLike | undefined;\n if (existing !== undefined) {\n if (existing.version !== DEVTOOLS_PROTOCOL_VERSION) {\n // 先勝ち固定。振る舞いは差し替えない(protocol §2)\n console.warn(\n `[wcstack/devtools] hook registry version mismatch: found ${existing.version}, expected ${DEVTOOLS_PROTOCOL_VERSION}. Keeping the existing registry (first-wins).`\n );\n }\n return existing;\n }\n const registry = createMinimalRegistry();\n globals[DEVTOOLS_HOOK_GLOBAL] = registry;\n return registry;\n}\n","/**\n * core/formatValue.ts\n *\n * 値フォーマッタ(devtools-tag-design.md §6)。\n *\n * 規範:\n * - primitive はそのまま(文字列は引用 + 80 文字上限)\n * - 配列 / plain object は深さ制限 + 要素数制限つきの要約\n * - それ以外(MediaStream, Blob, Element, class インスタンス等)は\n * `[[ClassName]]` タグ表示のみ\n * - structuredClone / JSON.stringify を全値に無差別適用しない\n * (生ハンドル・循環・巨大値対策。camera G1 との共存)\n */\n\nconst MAX_STRING = 80;\nconst MAX_ITEMS = 3;\n\nfunction isPlainObject(value: object): boolean {\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction className(value: object): string {\n const ctor = (value as { constructor?: { name?: string } }).constructor;\n const name = ctor?.name;\n return typeof name === \"string\" && name.length > 0 ? name : \"Object\";\n}\n\n/**\n * 任意の値を表示用の短い文字列へ変換する。\n * @param value 対象値\n * @param depth 再帰許容深さ(既定 2。0 で複合値は要約タグのみ)\n */\nexport function formatValue(value: unknown, depth: number = 2): string {\n switch (typeof value) {\n case \"string\": {\n const body = value.length > MAX_STRING ? value.slice(0, MAX_STRING) + \"…\" : value;\n return `\"${body}\"`;\n }\n case \"number\":\n case \"boolean\":\n case \"bigint\":\n return String(value);\n case \"symbol\":\n return value.toString();\n case \"undefined\":\n return \"undefined\";\n case \"function\":\n return \"[[Function]]\";\n default:\n break;\n }\n if (value === null) {\n return \"null\";\n }\n const objectValue = value as object;\n if (Array.isArray(objectValue)) {\n if (depth <= 0) {\n return `[[Array(${objectValue.length})]]`;\n }\n const shown = objectValue.slice(0, MAX_ITEMS).map((item) => formatValue(item, depth - 1));\n const rest = objectValue.length > MAX_ITEMS ? `, …(${objectValue.length})` : \"\";\n return `[${shown.join(\", \")}${rest}]`;\n }\n if (isPlainObject(objectValue)) {\n if (depth <= 0) {\n return \"[[Object]]\";\n }\n const keys = Object.keys(objectValue);\n const shown = keys.slice(0, MAX_ITEMS).map(\n (key) => `${key}: ${formatValue((objectValue as Record<string, unknown>)[key], depth - 1)}`\n );\n const rest = keys.length > MAX_ITEMS ? `, …(${keys.length})` : \"\";\n return `{${shown.join(\", \")}${rest}}`;\n }\n // DOM ノード・生ハンドル・class インスタンス等はタグ表示のみ\n return `[[${className(objectValue)}]]`;\n}\n\n/**\n * token 引数の要約(先頭 3 引数 × 各 80 文字上限、devtools-tag-design.md §6)。\n */\nexport function formatArgs(args: readonly unknown[]): string {\n if (args.length === 0) {\n return \"\";\n }\n const shown = args.slice(0, MAX_ITEMS).map((arg) => {\n const text = formatValue(arg, 1);\n return text.length > MAX_STRING ? text.slice(0, MAX_STRING) + \"…\" : text;\n });\n const rest = args.length > MAX_ITEMS ? `, …(${args.length})` : \"\";\n return `${shown.join(\", \")}${rest}`;\n}\n","/**\n * core/DevtoolsCore.ts\n *\n * hook client(devtools-tag-design.md §1)。DOM 非依存の純ロジック層。\n *\n * - registry への addListener / 解除(connect / disconnect)\n * - source 管理と roster(state 要素一覧)の維持\n * - 配線台帳(binding-added/removed イベントから構築。binding は WeakRef 保持)\n * - タイムライン ring buffer(既定 500 件 FIFO)\n * - 予約 prefix `wcs-devtools` の自己除外(protocol §5)\n *\n * 台帳はすべて devtools 側に置く(protocol 原則 2)。disconnect で\n * sources / roster / wiring をクリアし、残留参照を持たない。\n */\n\nimport { getOrCreateHookRegistry } from \"../protocol/registry\";\nimport {\n DevtoolsEventLike,\n IAbsoluteAddressLike,\n IBindingLike,\n IDevtoolsSourceLike,\n IStateElementSummaryLike,\n} from \"../protocol/types\";\nimport { formatArgs, formatValue } from \"./formatValue\";\n\n/** 予約 state 名 prefix(protocol §5)。この prefix の要素・イベントは常に除外 */\nexport const RESERVED_STATE_NAME_PREFIX = \"wcs-devtools\";\n\nconst DEFAULT_TIMELINE_CAPACITY = 500;\n\nexport type TimelineKind =\n | \"write\"\n | \"batch\"\n | \"command\"\n | \"event\"\n | \"element-registered\"\n | \"element-unregistered\";\n\nexport interface ITimelineEntry {\n readonly seq: number;\n readonly time: number;\n readonly sourceId: string;\n readonly kind: TimelineKind;\n readonly stateName: string | null;\n readonly label: string;\n readonly detail: string;\n readonly subscriberCount: number | null;\n}\n\nexport interface IRosterEntry {\n readonly sourceId: string;\n readonly name: string;\n readonly rootNode: Node;\n readonly summary: IStateElementSummaryLike;\n}\n\nexport interface IWiringEntry {\n readonly sourceId: string;\n readonly stateName: string;\n readonly path: string;\n readonly propName: string;\n readonly bindingType: string;\n readonly bindingRef: WeakRef<IBindingLike>;\n}\n\nexport type CoreChangeKind = \"sources\" | \"roster\" | \"wiring\" | \"timeline\";\nexport type CoreChangeListener = (kind: CoreChangeKind) => void;\n\nexport interface IDevtoolsCoreOptions {\n /** タイムライン ring buffer 件数(既定 500) */\n timelineCapacity?: number;\n /** 追加で除外する state 名(予約 prefix は常に除外) */\n hiddenStateNames?: readonly string[];\n}\n\nfunction pathKeyOf(stateName: string, path: string): string {\n return stateName + \"\u0000\" + path;\n}\n\nexport class DevtoolsCore {\n private _timelineCapacity: number;\n private _hiddenStateNames: Set<string>;\n private _removeListener: (() => void) | null = null;\n private _sources: Map<string, IDevtoolsSourceLike> = new Map();\n private _roster: Map<string, IRosterEntry[]> = new Map();\n private _wiringByPathKey: Map<string, Set<IWiringEntry>> = new Map();\n private _wiringEntryByBinding: WeakMap<IBindingLike, IWiringEntry> = new WeakMap();\n private _timeline: ITimelineEntry[] = [];\n private _seq: number = 0;\n private _paused: boolean = false;\n private _changeListeners: Set<CoreChangeListener> = new Set();\n\n constructor(options?: IDevtoolsCoreOptions) {\n this._timelineCapacity = options?.timelineCapacity ?? DEFAULT_TIMELINE_CAPACITY;\n this._hiddenStateNames = new Set(options?.hiddenStateNames ?? []);\n }\n\n get connected(): boolean {\n return this._removeListener !== null;\n }\n\n get paused(): boolean {\n return this._paused;\n }\n\n set paused(value: boolean) {\n this._paused = value;\n }\n\n /** 表示から除外する state 名か(予約 prefix + hiddenStateNames、protocol §5) */\n isHiddenStateName(name: string | null): boolean {\n if (name === null) {\n return false;\n }\n return name.startsWith(RESERVED_STATE_NAME_PREFIX) || this._hiddenStateNames.has(name);\n }\n\n connect(): void {\n if (this._removeListener !== null) {\n return;\n }\n const registry = getOrCreateHookRegistry();\n this._removeListener = registry.addListener({\n onSourceRegistered: (source) => {\n this._sources.set(source.id, source);\n this._refreshRosterOf(source);\n this._notify(\"sources\");\n },\n onSourceUnregistered: (sourceId) => {\n this._sources.delete(sourceId);\n this._roster.delete(sourceId);\n this._notify(\"sources\");\n this._notify(\"roster\");\n },\n onEvent: (sourceId, event) => {\n this._ingest(sourceId, event);\n },\n });\n }\n\n /** 購読解除 + 台帳クリア(タイムラインは保持。protocol §7-2 の残留ゼロ) */\n disconnect(): void {\n if (this._removeListener === null) {\n return;\n }\n this._removeListener();\n this._removeListener = null;\n this._sources.clear();\n this._roster.clear();\n this._wiringByPathKey.clear();\n this._wiringEntryByBinding = new WeakMap();\n this._notify(\"sources\");\n this._notify(\"roster\");\n this._notify(\"wiring\");\n }\n\n onChange(listener: CoreChangeListener): () => void {\n this._changeListeners.add(listener);\n return () => {\n this._changeListeners.delete(listener);\n };\n }\n\n getSources(): IDevtoolsSourceLike[] {\n return [...this._sources.values()];\n }\n\n getRoster(): IRosterEntry[] {\n const entries: IRosterEntry[] = [];\n for (const list of this._roster.values()) {\n entries.push(...list);\n }\n return entries;\n }\n\n /** 全 source の state 要素一覧を pull で取り直す */\n refreshRoster(): void {\n for (const source of this._sources.values()) {\n this._refreshRosterOf(source);\n }\n this._notify(\"roster\");\n }\n\n getTimeline(): readonly ITimelineEntry[] {\n return this._timeline;\n }\n\n clearTimeline(): void {\n this._timeline = [];\n this._notify(\"timeline\");\n }\n\n /** 指定パスに束縛された配線(生存している binding のみ) */\n getWiringForPath(stateName: string, path: string): IWiringEntry[] {\n const set = this._wiringByPathKey.get(pathKeyOf(stateName, path));\n if (set === undefined) {\n return [];\n }\n return this._collectAlive(set);\n }\n\n /** 全配線のスナップショット(生存している binding のみ) */\n getAllWiring(): IWiringEntry[] {\n const result: IWiringEntry[] = [];\n for (const set of this._wiringByPathKey.values()) {\n result.push(...this._collectAlive(set));\n }\n return result;\n }\n\n /** 指定ノード(またはその子孫のバインドノード)に載る配線 */\n getWiringForNode(node: Node): IWiringEntry[] {\n const result: IWiringEntry[] = [];\n for (const set of this._wiringByPathKey.values()) {\n for (const entry of this._collectAlive(set)) {\n const binding = entry.bindingRef.deref()!;\n if (\n binding.node === node ||\n binding.replaceNode === node ||\n node.contains(binding.node) ||\n node.contains(binding.replaceNode)\n ) {\n result.push(entry);\n }\n }\n }\n return result;\n }\n\n /** roster entry の state からトップレベルキーを列挙(keys 未実装ランタイムは空) */\n keysOf(entry: IRosterEntry): string[] {\n const source = this._sources.get(entry.sourceId);\n if (source === undefined || typeof source.keys !== \"function\") {\n return [];\n }\n return source.keys(entry.name, entry.rootNode);\n }\n\n readValue(entry: IRosterEntry, path: string, indexes?: number[]): unknown {\n const source = this._sources.get(entry.sourceId);\n if (source === undefined) {\n return undefined;\n }\n return source.read(entry.name, entry.rootNode, path, indexes);\n }\n\n writeValue(entry: IRosterEntry, path: string, value: unknown, indexes?: number[]): void {\n const source = this._sources.get(entry.sourceId);\n if (source === undefined) {\n return;\n }\n source.write(entry.name, entry.rootNode, path, value, indexes);\n }\n\n // --- internal ---\n\n private _notify(kind: CoreChangeKind): void {\n for (const listener of this._changeListeners) {\n listener(kind);\n }\n }\n\n private _refreshRosterOf(source: IDevtoolsSourceLike): void {\n const entries: IRosterEntry[] = [];\n for (const summary of source.getStateElements()) {\n if (this.isHiddenStateName(summary.name)) {\n continue;\n }\n entries.push({\n sourceId: source.id,\n name: summary.name,\n rootNode: summary.rootNode,\n summary,\n });\n }\n this._roster.set(source.id, entries);\n }\n\n private _collectAlive(set: Set<IWiringEntry>): IWiringEntry[] {\n const alive: IWiringEntry[] = [];\n for (const entry of set) {\n if (entry.bindingRef.deref() === undefined) {\n // GC 済み binding は遅延剪定(detach 漏れで DOM を残さないための WeakRef 側)\n set.delete(entry);\n continue;\n }\n alive.push(entry);\n }\n return alive;\n }\n\n private _appendTimeline(entry: Omit<ITimelineEntry, \"seq\" | \"time\">): void {\n if (this._paused) {\n return;\n }\n this._timeline.push({\n ...entry,\n seq: this._seq++,\n time: performance.now(),\n });\n const overflow = this._timeline.length - this._timelineCapacity;\n if (overflow > 0) {\n this._timeline.splice(0, overflow);\n }\n this._notify(\"timeline\");\n }\n\n private _labelOf(address: IAbsoluteAddressLike): string {\n const indexes = address.listIndex?.indexes;\n const path = address.absolutePathInfo.pathInfo.path;\n return indexes !== undefined ? `${path}[${indexes.join(\",\")}]` : path;\n }\n\n private _ingest(sourceId: string, event: DevtoolsEventLike): void {\n switch (event.type) {\n case \"state:element-registered\": {\n if (this.isHiddenStateName(event.name)) {\n return;\n }\n const source = this._sources.get(sourceId);\n if (source !== undefined) {\n this._refreshRosterOf(source);\n this._notify(\"roster\");\n }\n this._appendTimeline({\n sourceId,\n kind: \"element-registered\",\n stateName: event.name,\n label: event.name,\n detail: \"\",\n subscriberCount: null,\n });\n return;\n }\n case \"state:element-unregistered\": {\n if (this.isHiddenStateName(event.name)) {\n return;\n }\n const source = this._sources.get(sourceId);\n if (source !== undefined) {\n this._refreshRosterOf(source);\n this._notify(\"roster\");\n }\n this._appendTimeline({\n sourceId,\n kind: \"element-unregistered\",\n stateName: event.name,\n label: event.name,\n detail: \"\",\n subscriberCount: null,\n });\n return;\n }\n case \"state:write\": {\n const stateName = event.absoluteAddress.absolutePathInfo.stateName;\n if (this.isHiddenStateName(stateName)) {\n return;\n }\n const detail = event.hasOldValue\n ? `${formatValue(event.value)} (was ${formatValue(event.oldValue)})`\n : formatValue(event.value);\n this._appendTimeline({\n sourceId,\n kind: \"write\",\n stateName,\n label: this._labelOf(event.absoluteAddress),\n detail,\n subscriberCount: null,\n });\n return;\n }\n case \"state:update-batch\": {\n const labels: string[] = [];\n let total = 0;\n for (const address of event.addresses) {\n if (this.isHiddenStateName(address.absolutePathInfo.stateName)) {\n continue;\n }\n total++;\n if (labels.length < 3) {\n labels.push(this._labelOf(address));\n }\n }\n if (total === 0) {\n return;\n }\n const rest = total > labels.length ? `, …(${total})` : \"\";\n this._appendTimeline({\n sourceId,\n kind: \"batch\",\n stateName: null,\n label: `${total} address${total === 1 ? \"\" : \"es\"}`,\n detail: `${labels.join(\", \")}${rest}`,\n subscriberCount: null,\n });\n return;\n }\n case \"state:binding-added\": {\n const stateName = event.absoluteAddress.absolutePathInfo.stateName;\n if (this.isHiddenStateName(stateName)) {\n return;\n }\n const path = event.absoluteAddress.absolutePathInfo.pathInfo.path;\n const key = pathKeyOf(stateName, path);\n let set = this._wiringByPathKey.get(key);\n if (set === undefined) {\n set = new Set();\n this._wiringByPathKey.set(key, set);\n }\n const entry: IWiringEntry = {\n sourceId,\n stateName,\n path,\n propName: event.binding.propName,\n bindingType: event.binding.bindingType,\n bindingRef: new WeakRef(event.binding),\n };\n set.add(entry);\n this._wiringEntryByBinding.set(event.binding, entry);\n this._notify(\"wiring\");\n return;\n }\n case \"state:binding-removed\": {\n const entry = this._wiringEntryByBinding.get(event.binding);\n if (entry === undefined) {\n return;\n }\n this._wiringEntryByBinding.delete(event.binding);\n const key = pathKeyOf(entry.stateName, entry.path);\n const set = this._wiringByPathKey.get(key);\n if (set !== undefined) {\n set.delete(entry);\n if (set.size === 0) {\n this._wiringByPathKey.delete(key);\n }\n }\n this._notify(\"wiring\");\n return;\n }\n case \"state:binding-cleared\": {\n const stateName = event.absoluteAddress.absolutePathInfo.stateName;\n const path = event.absoluteAddress.absolutePathInfo.pathInfo.path;\n const key = pathKeyOf(stateName, path);\n if (this._wiringByPathKey.delete(key)) {\n this._notify(\"wiring\");\n }\n return;\n }\n case \"state:token-emit\": {\n if (this.isHiddenStateName(event.stateName)) {\n return;\n }\n this._appendTimeline({\n sourceId,\n kind: event.kind,\n stateName: event.stateName,\n label: event.tokenName,\n detail: formatArgs(event.args),\n subscriberCount: event.subscriberCount,\n });\n return;\n }\n }\n }\n}\n","/**\n * core/declaredScan.ts\n *\n * 遅延アタッチ時の declared ビュー(protocol §6)。\n *\n * binding 台帳はフック接続前の分を復元できないため、DOM に残っている\n * `data-wcs` 属性と `<!--wcs-*: -->` コメントを再スキャンして\n * 「宣言レベルの配線ビュー」を組む。ライブ台帳と違い binding 実体・\n * 接続状態は分からない(UI では \"declared\" バッジで区別する)。\n *\n * パースは表示目的の簡易版(`prop[#mod]: path[@state][|filters]` を\n * `;` 区切りで分解するだけ)。正確なセマンティクスの正本は\n * @wcstack/state の bindTextParser であり、ここでは追随しない。\n */\n\nexport interface IDeclaredBinding {\n /** 宣言が載っている要素(コメント由来の場合は親要素) */\n readonly element: Element;\n readonly propName: string;\n readonly path: string;\n readonly stateName: string;\n readonly filters: readonly string[];\n /** 宣言ソース: data-wcs 属性か comment ノードか */\n readonly origin: \"attribute\" | \"comment\";\n readonly raw: string;\n}\n\nconst DEFAULT_BIND_ATTRIBUTE = \"data-wcs\";\nconst COMMENT_PREFIXES = [\"wcs-text\", \"wcs-for\", \"wcs-if\", \"wcs-elseif\", \"wcs-else\"];\n\nfunction parseEntry(\n element: Element,\n raw: string,\n origin: \"attribute\" | \"comment\"\n): IDeclaredBinding | null {\n const trimmed = raw.trim();\n if (trimmed.length === 0) {\n return null;\n }\n const colon = trimmed.indexOf(\":\");\n if (colon < 0) {\n return null;\n }\n const propName = trimmed.slice(0, colon).trim();\n const rhs = trimmed.slice(colon + 1).trim();\n if (propName.length === 0 || rhs.length === 0) {\n return null;\n }\n const [pathPart, ...filterParts] = rhs.split(\"|\").map((part) => part.trim());\n let path = pathPart;\n let stateName = \"default\";\n const at = pathPart.lastIndexOf(\"@\");\n if (at > 0) {\n path = pathPart.slice(0, at).trim();\n stateName = pathPart.slice(at + 1).trim();\n }\n return {\n element,\n propName,\n path,\n stateName,\n filters: filterParts.filter((part) => part.length > 0),\n origin,\n raw: trimmed,\n };\n}\n\n/**\n * rootNode 配下の宣言配線を列挙する。\n * @param root 走査起点(Document / ShadowRoot / Element)\n * @param bindAttributeName バインド属性名(既定 data-wcs。setConfig で変えたページ用)\n */\nexport function scanDeclaredBindings(\n root: ParentNode,\n bindAttributeName: string = DEFAULT_BIND_ATTRIBUTE\n): IDeclaredBinding[] {\n const result: IDeclaredBinding[] = [];\n\n // data-wcs 属性(template の for/if 宣言もこの属性に載る)\n for (const element of root.querySelectorAll(`[${bindAttributeName}]`)) {\n // querySelectorAll の一致条件上、属性は必ず存在する\n const raw = element.getAttribute(bindAttributeName)!;\n for (const part of raw.split(\";\")) {\n const entry = parseEntry(element, part, \"attribute\");\n if (entry !== null) {\n result.push(entry);\n }\n }\n }\n\n // <!--wcs-text: path--> 等のコメントノード(mustache 展開後の姿)\n const document = root.ownerDocument ?? (root as Document);\n const walker = document.createTreeWalker(root as Node, NodeFilter.SHOW_COMMENT);\n let comment = walker.nextNode();\n while (comment !== null) {\n // コメントノードの textContent は常に文字列\n const text = comment.textContent!.trim();\n const prefix = COMMENT_PREFIXES.find(\n (candidate) => text === candidate || text.startsWith(candidate + \":\")\n );\n if (prefix !== undefined) {\n const parentElement =\n comment.parentNode instanceof Element ? comment.parentNode : null;\n if (parentElement !== null) {\n const body = text === prefix ? \"\" : text.slice(prefix.length + 1).trim();\n if (body.length > 0) {\n const propName = prefix === \"wcs-text\" ? \"textContent\" : prefix.slice(\"wcs-\".length);\n // propName / body とも非空のため parseEntry は必ず成功する\n result.push(parseEntry(parentElement, `${propName}: ${body}`, \"comment\")!);\n }\n }\n }\n comment = walker.nextNode();\n }\n\n return result;\n}\n","/**\n * shell/WcsDevtools.ts\n *\n * `<wcs-devtools>` — ページ内オーバーレイ DevTools 本体(devtools-tag-design.md)。\n *\n * - ShadowRoot 内で完結(ページの CSS/DOM を変更しない)\n * - ハイライトはページ要素の style/class を触らず、fixed 配置の\n * オーバーレイ枠で描く(devtools-tag-design.md §2)\n * - UI レンダリングは vanilla DOM(記録済み決定: inspected ランタイムの\n * updater キューに devtools 描画負荷を混ぜない = 観測者効果の排除。\n * wcs-state ドッグフーディングは Phase 2 で再評価)\n * - 描画は Core の change 通知を rAF で 1 回に合流(イベント毎 DOM 追加禁止、\n * devtools-tag-design.md §3.3)\n */\n\nimport { DevtoolsCore, IRosterEntry, ITimelineEntry, IWiringEntry } from \"../core/DevtoolsCore\";\nimport { formatValue } from \"../core/formatValue\";\nimport { IDeclaredBinding, scanDeclaredBindings } from \"../core/declaredScan\";\n\nconst STYLE_TEXT = /* css */ `\n:host {\n all: initial;\n position: fixed;\n z-index: 2147483647;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n inset: auto 0 0 auto;\n}\n* { box-sizing: border-box; }\n.badge {\n position: fixed;\n right: 12px;\n bottom: 12px;\n width: 40px;\n height: 40px;\n border-radius: 20px;\n border: 1px solid #2b4f78;\n background: #10263f;\n color: #9fd0ff;\n font-weight: 700;\n cursor: pointer;\n}\n.panel {\n position: fixed;\n display: flex;\n flex-direction: column;\n background: #0d1b2a;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n box-shadow: 0 0 24px rgba(0,0,0,.5);\n}\n.panel.dock-bottom { left: 0; right: 0; bottom: 0; height: 45vh; }\n.panel.dock-right { top: 0; right: 0; bottom: 0; width: 420px; }\n.panel[hidden] { display: none; }\nheader {\n display: flex;\n gap: 6px;\n align-items: center;\n padding: 6px 8px;\n border-bottom: 1px solid #2b4f78;\n background: #10263f;\n}\nheader .title { font-weight: 700; color: #9fd0ff; margin-right: 4px; }\nheader select, header button {\n font: inherit;\n background: #16324f;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n border-radius: 4px;\n padding: 2px 8px;\n cursor: pointer;\n}\nheader button[aria-pressed=\"true\"] { background: #2b5d8f; }\nheader .spacer { flex: 1; }\n.panes { display: flex; flex: 1; min-height: 0; }\n.pane { flex: 1; min-width: 0; overflow: auto; padding: 6px 8px; border-right: 1px solid #1d3a5c; }\n.pane:last-child { border-right: none; }\n.pane h3 {\n margin: 0 0 6px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: .08em;\n color: #7ba7d4;\n}\n.tree-row { display: flex; gap: 6px; padding: 1px 0; align-items: baseline; white-space: nowrap; }\n.tree-row .toggle { width: 14px; cursor: pointer; color: #7ba7d4; user-select: none; }\n.tree-row .key { color: #9fd0ff; cursor: pointer; }\n.tree-row .value { color: #ffd9a0; overflow: hidden; text-overflow: ellipsis; }\n.tree-row .value.editable { cursor: pointer; }\n.tree-row input { font: inherit; background: #16324f; color: #ffd9a0; border: 1px solid #2b4f78; }\n.badge-tag {\n display: inline-block;\n padding: 0 4px;\n border-radius: 3px;\n font-size: 10px;\n background: #26456a;\n color: #a8c6e8;\n}\n.badge-tag.warn { background: #6a3326; color: #ffb3a0; }\n.badge-tag.declared { background: #4a4426; color: #efe3a0; }\n.wiring-row, .timeline-row { padding: 1px 0; white-space: nowrap; }\n.wiring-row .prop { color: #b7f0c0; }\n.wiring-row .path { color: #9fd0ff; }\n.timeline-row .t { color: #6f88a3; }\n.timeline-row .label { color: #9fd0ff; }\n.timeline-row .detail { color: #ffd9a0; }\n.timeline-row .kind { display: inline-block; min-width: 52px; text-align: center; }\n.empty { color: #6f88a3; font-style: italic; padding: 4px 0; }\n.notice { color: #efe3a0; padding: 2px 0 6px; }\n.notice button { font: inherit; margin-left: 6px; cursor: pointer; }\n.hl-box {\n position: fixed;\n pointer-events: none;\n border: 1px solid #58c2ff;\n background: rgba(88,194,255,.18);\n}\n`;\n\ntype PaneName = \"state\" | \"wiring\" | \"timeline\";\n\n/** タイムラインの DOM 描画上限(buffer とは別。§3.3 のバースト圧縮の一部) */\nconst TIMELINE_RENDER_LIMIT = 200;\n/** リスト展開の 1 階層あたり表示件数上限 */\nconst LIST_CHILD_LIMIT = 20;\n\ninterface ITreeNodeRef {\n readonly path: string;\n readonly indexes: number[];\n}\n\nfunction nodeKeyOf(ref: ITreeNodeRef): string {\n return `${ref.path}#${ref.indexes.join(\",\")}`;\n}\n\nfunction isExpandable(value: unknown): boolean {\n if (Array.isArray(value)) {\n return true;\n }\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction coerceInput(text: string): unknown {\n const trimmed = text.trim();\n try {\n return JSON.parse(trimmed);\n } catch {\n return text;\n }\n}\n\nexport class WcsDevtools extends HTMLElement {\n static get observedAttributes(): string[] {\n return [\"open\", \"dock\", \"hotkey\"];\n }\n\n private _core: DevtoolsCore | null = null;\n private _removeCoreListener: (() => void) | null = null;\n private _panel: HTMLElement | null = null;\n private _badge: HTMLButtonElement | null = null;\n private _stateSelect: HTMLSelectElement | null = null;\n private _paneElements: Partial<Record<PaneName, HTMLElement>> = {};\n private _highlightLayer: HTMLElement | null = null;\n private _dirtyPanes: Set<PaneName> = new Set();\n private _renderScheduled: boolean = false;\n private _selectedRosterKey: string | null = null;\n private _selectedPath: string | null = null;\n private _pickedNode: Node | null = null;\n private _pickMode: boolean = false;\n private _expanded: Set<string> = new Set();\n private _hotkeyHandler: ((event: KeyboardEvent) => void) | null = null;\n private _pickHandler: ((event: MouseEvent) => void) | null = null;\n\n get core(): DevtoolsCore | null {\n return this._core;\n }\n\n connectedCallback(): void {\n // SSR では不活性(protocol 原則 6)\n if (document.documentElement.hasAttribute(\"data-wcs-server\")) {\n return;\n }\n if (this.shadowRoot === null) {\n this._buildShadow();\n }\n const capacity = Number(this.getAttribute(\"buffer\") ?? \"\");\n const hidden = (this.getAttribute(\"hidden-states\") ?? \"\")\n .split(\",\")\n .map((name) => name.trim())\n .filter((name) => name.length > 0);\n this._core = new DevtoolsCore({\n timelineCapacity: Number.isFinite(capacity) && capacity > 0 ? capacity : undefined,\n hiddenStateNames: hidden,\n });\n this._removeCoreListener = this._core.onChange((kind) => {\n if (kind === \"roster\" || kind === \"sources\") {\n this._markDirty(\"state\");\n this._markDirty(\"wiring\");\n } else if (kind === \"wiring\") {\n this._markDirty(\"wiring\");\n } else {\n this._markDirty(\"timeline\");\n }\n });\n this._core.connect();\n this._applyDock();\n this._applyOpen();\n this._installHotkey();\n this._markDirty(\"state\");\n this._markDirty(\"wiring\");\n this._markDirty(\"timeline\");\n }\n\n disconnectedCallback(): void {\n this._removeCoreListener?.();\n this._removeCoreListener = null;\n this._core?.disconnect();\n this._core = null;\n this._uninstallHotkey();\n this._exitPickMode();\n }\n\n attributeChangedCallback(name: string): void {\n if (this.shadowRoot === null) {\n return;\n }\n if (name === \"open\") {\n this._applyOpen();\n } else if (name === \"dock\") {\n this._applyDock();\n } else if (name === \"hotkey\") {\n this._uninstallHotkey();\n this._installHotkey();\n }\n }\n\n /** テスト用: rAF を待たずに保留中の描画を実行する */\n __flushRenderForTest(): void {\n this._renderDirty();\n }\n\n // --- shadow construction ---\n\n private _buildShadow(): void {\n const shadow = this.attachShadow({ mode: \"open\" });\n const style = document.createElement(\"style\");\n style.textContent = STYLE_TEXT;\n shadow.append(style);\n\n const badge = document.createElement(\"button\");\n badge.className = \"badge\";\n badge.title = \"wcstack DevTools\";\n badge.textContent = \"WCS\";\n badge.addEventListener(\"click\", () => this.toggle());\n shadow.append(badge);\n this._badge = badge;\n\n const panel = document.createElement(\"div\");\n panel.className = \"panel dock-bottom\";\n panel.hidden = true;\n\n const header = document.createElement(\"header\");\n const title = document.createElement(\"span\");\n title.className = \"title\";\n title.textContent = \"wcstack devtools\";\n header.append(title);\n\n const stateSelect = document.createElement(\"select\");\n stateSelect.title = \"state element\";\n stateSelect.addEventListener(\"change\", () => {\n this._selectedRosterKey = stateSelect.value || null;\n this._selectedPath = null;\n this._expanded.clear();\n this._markDirty(\"state\");\n this._markDirty(\"wiring\");\n });\n header.append(stateSelect);\n this._stateSelect = stateSelect;\n\n const pickButton = this._headerButton(header, \"⌖ pick\", \"pick a page element\");\n pickButton.addEventListener(\"click\", () => {\n if (this._pickMode) {\n this._exitPickMode();\n } else {\n this._enterPickMode();\n }\n pickButton.setAttribute(\"aria-pressed\", String(this._pickMode));\n });\n pickButton.dataset[\"role\"] = \"pick\";\n\n const pauseButton = this._headerButton(header, \"⏸\", \"pause timeline\");\n pauseButton.addEventListener(\"click\", () => {\n const core = this._core;\n if (core === null) {\n return;\n }\n core.paused = !core.paused;\n pauseButton.setAttribute(\"aria-pressed\", String(core.paused));\n });\n pauseButton.dataset[\"role\"] = \"pause\";\n\n const clearButton = this._headerButton(header, \"🗑\", \"clear timeline\");\n clearButton.addEventListener(\"click\", () => {\n this._core?.clearTimeline();\n });\n clearButton.dataset[\"role\"] = \"clear\";\n\n const spacer = document.createElement(\"span\");\n spacer.className = \"spacer\";\n header.append(spacer);\n\n const dockButton = this._headerButton(header, \"dock\", \"toggle dock position\");\n dockButton.addEventListener(\"click\", () => {\n const next = (this.getAttribute(\"dock\") ?? \"bottom\") === \"bottom\" ? \"right\" : \"bottom\";\n this.setAttribute(\"dock\", next);\n });\n dockButton.dataset[\"role\"] = \"dock\";\n\n const closeButton = this._headerButton(header, \"×\", \"close\");\n closeButton.addEventListener(\"click\", () => this.toggle(false));\n closeButton.dataset[\"role\"] = \"close\";\n\n panel.append(header);\n\n const panes = document.createElement(\"div\");\n panes.className = \"panes\";\n for (const [name, heading] of [\n [\"state\", \"State\"],\n [\"wiring\", \"Wiring\"],\n [\"timeline\", \"Timeline\"],\n ] as const) {\n const pane = document.createElement(\"section\");\n pane.className = `pane pane-${name}`;\n const h3 = document.createElement(\"h3\");\n h3.textContent = heading;\n const body = document.createElement(\"div\");\n body.className = \"pane-body\";\n pane.append(h3, body);\n panes.append(pane);\n this._paneElements[name] = body;\n }\n panel.append(panes);\n shadow.append(panel);\n this._panel = panel;\n\n const highlightLayer = document.createElement(\"div\");\n highlightLayer.className = \"hl-layer\";\n shadow.append(highlightLayer);\n this._highlightLayer = highlightLayer;\n }\n\n private _headerButton(header: HTMLElement, label: string, title: string): HTMLButtonElement {\n const button = document.createElement(\"button\");\n button.textContent = label;\n button.title = title;\n button.setAttribute(\"aria-pressed\", \"false\");\n header.append(button);\n return button;\n }\n\n // --- open/close/dock/hotkey ---\n\n get open(): boolean {\n return this.hasAttribute(\"open\");\n }\n\n toggle(force?: boolean): void {\n const next = force ?? !this.open;\n if (next) {\n this.setAttribute(\"open\", \"\");\n } else {\n this.removeAttribute(\"open\");\n }\n }\n\n private _applyOpen(): void {\n // shadowRoot 構築後にしか呼ばれない(attributeChangedCallback 側でガード済み)\n this._panel!.hidden = !this.open;\n this._badge!.hidden = this.open;\n if (this.open) {\n this._markDirty(\"state\");\n this._markDirty(\"wiring\");\n this._markDirty(\"timeline\");\n }\n }\n\n private _applyDock(): void {\n // shadowRoot 構築後にしか呼ばれない(attributeChangedCallback 側でガード済み)\n const dock = this.getAttribute(\"dock\") === \"right\" ? \"right\" : \"bottom\";\n this._panel!.classList.toggle(\"dock-right\", dock === \"right\");\n this._panel!.classList.toggle(\"dock-bottom\", dock === \"bottom\");\n }\n\n private _installHotkey(): void {\n const spec = this.getAttribute(\"hotkey\") ?? \"Alt+Shift+D\";\n if (spec === \"none\") {\n return;\n }\n const parts = spec.split(\"+\").map((part) => part.trim().toLowerCase());\n const key = parts[parts.length - 1];\n const alt = parts.includes(\"alt\");\n const shift = parts.includes(\"shift\");\n const ctrl = parts.includes(\"ctrl\");\n const meta = parts.includes(\"meta\");\n this._hotkeyHandler = (event: KeyboardEvent) => {\n if (\n event.key.toLowerCase() === key &&\n event.altKey === alt &&\n event.shiftKey === shift &&\n event.ctrlKey === ctrl &&\n event.metaKey === meta\n ) {\n event.preventDefault();\n this.toggle();\n }\n };\n window.addEventListener(\"keydown\", this._hotkeyHandler);\n }\n\n private _uninstallHotkey(): void {\n if (this._hotkeyHandler !== null) {\n window.removeEventListener(\"keydown\", this._hotkeyHandler);\n this._hotkeyHandler = null;\n }\n }\n\n // --- pick mode ---\n\n private _enterPickMode(): void {\n // 呼び出し元(pick ボタン)が toggle 済みのため、ここでは常に開始でよい\n this._pickMode = true;\n // click を capture で奪う(誤操作防止、devtools-tag-design.md G-U2 の既定側)\n this._pickHandler = (event: MouseEvent) => {\n const target = event.target as Node;\n // devtools 自身(実ブラウザでは retarget されて host、shadow 非 retarget 環境では\n // shadow 内ノード)は pick 対象外\n if (target.getRootNode() === this.shadowRoot || target === this) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n this._pickedNode = target;\n this._selectedPath = null;\n this._exitPickMode();\n this._markDirty(\"wiring\");\n };\n document.addEventListener(\"click\", this._pickHandler, { capture: true });\n }\n\n private _exitPickMode(): void {\n if (this._pickHandler !== null) {\n document.removeEventListener(\"click\", this._pickHandler, { capture: true });\n this._pickHandler = null;\n }\n this._pickMode = false;\n const pickButton = this.shadowRoot?.querySelector('button[data-role=\"pick\"]');\n pickButton?.setAttribute(\"aria-pressed\", \"false\");\n }\n\n // --- rendering ---\n\n private _markDirty(pane: PaneName): void {\n this._dirtyPanes.add(pane);\n if (this._renderScheduled) {\n return;\n }\n this._renderScheduled = true;\n requestAnimationFrame(() => {\n this._renderDirty();\n });\n }\n\n private _renderDirty(): void {\n this._renderScheduled = false;\n if (this._core === null || this.shadowRoot === null) {\n this._dirtyPanes.clear();\n return;\n }\n const dirty = this._dirtyPanes;\n this._dirtyPanes = new Set();\n if (dirty.has(\"state\")) {\n this._renderStatePane();\n }\n if (dirty.has(\"wiring\")) {\n this._renderWiringPane();\n }\n if (dirty.has(\"timeline\")) {\n this._renderTimelinePane();\n }\n }\n\n private _rosterKey(entry: IRosterEntry): string {\n return `${entry.sourceId}:${entry.name}`;\n }\n\n private _selectedRoster(): IRosterEntry | null {\n const core = this._core!;\n const roster = core.getRoster();\n if (roster.length === 0) {\n return null;\n }\n const found = roster.find((entry) => this._rosterKey(entry) === this._selectedRosterKey);\n return found ?? roster[0];\n }\n\n private _renderStatePane(): void {\n const core = this._core!;\n const body = this._paneElements[\"state\"]!;\n const select = this._stateSelect!;\n const roster = core.getRoster();\n const selected = this._selectedRoster();\n\n select.replaceChildren(\n ...roster.map((entry) => {\n const option = document.createElement(\"option\");\n option.value = this._rosterKey(entry);\n option.textContent = `${entry.name} (${entry.sourceId.slice(0, 12)})`;\n option.selected = selected !== null && this._rosterKey(entry) === this._rosterKey(selected);\n return option;\n })\n );\n\n body.replaceChildren();\n if (selected === null) {\n body.append(this._emptyRow(\"no <wcs-state> elements observed\"));\n return;\n }\n this._selectedRosterKey = this._rosterKey(selected);\n const keys = core.keysOf(selected);\n if (keys.length === 0) {\n body.append(this._emptyRow(\"no readable keys (runtime without keys() API?)\"));\n return;\n }\n for (const key of keys) {\n this._renderTreeNode(body, selected, { path: key, indexes: [] }, key, 0);\n }\n }\n\n private _renderTreeNode(\n container: HTMLElement,\n entry: IRosterEntry,\n ref: ITreeNodeRef,\n label: string,\n depth: number\n ): void {\n const core = this._core!;\n let value: unknown;\n let readable = true;\n try {\n value = core.readValue(entry, ref.path, ref.indexes);\n } catch {\n readable = false;\n }\n\n const row = document.createElement(\"div\");\n row.className = \"tree-row\";\n row.style.paddingLeft = `${depth * 14}px`;\n\n const expandable = readable && isExpandable(value);\n const key = nodeKeyOf(ref);\n const expanded = expandable && this._expanded.has(key);\n\n const toggle = document.createElement(\"span\");\n toggle.className = \"toggle\";\n toggle.textContent = expandable ? (expanded ? \"▾\" : \"▸\") : \"\";\n if (expandable) {\n toggle.addEventListener(\"click\", () => {\n if (this._expanded.has(key)) {\n this._expanded.delete(key);\n } else {\n this._expanded.add(key);\n }\n this._markDirty(\"state\");\n });\n }\n row.append(toggle);\n\n const keySpan = document.createElement(\"span\");\n keySpan.className = \"key\";\n keySpan.textContent = `${label}:`;\n keySpan.title = ref.path;\n keySpan.addEventListener(\"click\", () => {\n this._selectedPath = ref.path;\n this._pickedNode = null;\n this._markDirty(\"wiring\");\n this._highlightPath(entry, ref.path);\n });\n row.append(keySpan);\n\n const valueSpan = document.createElement(\"span\");\n valueSpan.className = \"value\";\n if (!readable) {\n valueSpan.textContent = \"(unreadable getter)\";\n } else {\n valueSpan.textContent = formatValue(value, 1);\n const editable = value === null || typeof value !== \"object\";\n if (editable && typeof value !== \"function\") {\n valueSpan.classList.add(\"editable\");\n valueSpan.title = \"click to edit\";\n valueSpan.addEventListener(\"click\", () => {\n this._beginEdit(row, valueSpan, entry, ref, value);\n });\n }\n }\n row.append(valueSpan);\n container.append(row);\n\n if (expanded) {\n if (Array.isArray(value)) {\n const limit = Math.min(value.length, LIST_CHILD_LIMIT);\n for (let index = 0; index < limit; index++) {\n this._renderTreeNode(\n container,\n entry,\n { path: `${ref.path}.*`, indexes: [...ref.indexes, index] },\n `[${index}]`,\n depth + 1\n );\n }\n if (value.length > limit) {\n const more = this._emptyRow(`…(${value.length} items)`);\n more.style.paddingLeft = `${(depth + 1) * 14}px`;\n container.append(more);\n }\n } else {\n for (const childKey of Object.keys(value as Record<string, unknown>)) {\n this._renderTreeNode(\n container,\n entry,\n { path: `${ref.path}.${childKey}`, indexes: ref.indexes },\n childKey,\n depth + 1\n );\n }\n }\n }\n }\n\n private _beginEdit(\n row: HTMLElement,\n valueSpan: HTMLElement,\n entry: IRosterEntry,\n ref: ITreeNodeRef,\n current: unknown\n ): void {\n const input = document.createElement(\"input\");\n input.value = typeof current === \"string\" ? current : String(current);\n const commit = (): void => {\n // 編集は通常のリアクティブパイプラインを通る(devtools-tag-design.md §3.1)\n this._core?.writeValue(entry, ref.path, coerceInput(input.value), ref.indexes);\n this._markDirty(\"state\");\n };\n input.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\") {\n commit();\n } else if (event.key === \"Escape\") {\n this._markDirty(\"state\");\n }\n });\n row.replaceChild(input, valueSpan);\n input.focus();\n }\n\n private _renderWiringPane(): void {\n const core = this._core!;\n const body = this._paneElements[\"wiring\"]!;\n body.replaceChildren();\n\n let entries: IWiringEntry[];\n let contextLabel: string;\n if (this._pickedNode !== null) {\n entries = core.getWiringForNode(this._pickedNode);\n const target = this._pickedNode;\n contextLabel =\n target instanceof Element ? `<${target.tagName.toLowerCase()}>` : target.nodeName;\n } else if (this._selectedPath !== null) {\n const selected = this._selectedRoster();\n entries =\n selected !== null ? core.getWiringForPath(selected.name, this._selectedPath) : [];\n contextLabel = this._selectedPath;\n } else {\n entries = core.getAllWiring();\n contextLabel = \"all\";\n }\n\n const info = document.createElement(\"div\");\n info.textContent = `context: ${contextLabel} — ${entries.length} live binding${entries.length === 1 ? \"\" : \"s\"}`;\n body.append(info);\n\n if (entries.length > 0) {\n for (const entry of entries) {\n body.append(this._wiringRow(entry));\n }\n return;\n }\n\n // ライブ台帳が空 → declared ビューへフォールバック(protocol §6)\n const selected = this._selectedRoster();\n const declared =\n selected !== null ? scanDeclaredBindings(this._scanRootOf(selected)) : [];\n if (declared.length === 0) {\n body.append(this._emptyRow(\"no bindings observed\"));\n return;\n }\n const notice = document.createElement(\"div\");\n notice.className = \"notice\";\n const tag = document.createElement(\"span\");\n tag.className = \"badge-tag declared\";\n tag.textContent = \"declared\";\n notice.append(tag, document.createTextNode(\" attached late — reload to capture live bindings \"));\n const reload = document.createElement(\"button\");\n reload.textContent = \"reload\";\n reload.addEventListener(\"click\", () => {\n location.reload();\n });\n notice.append(reload);\n body.append(notice);\n for (const entry of declared) {\n body.append(this._declaredRow(entry));\n }\n }\n\n private _scanRootOf(entry: IRosterEntry): ParentNode {\n // instanceof はテスト環境(happy-dom)の Document 実体と一致しないことがあるため\n // nodeType で判定する(DOCUMENT_FRAGMENT_NODE は ShadowRoot を含む)\n const rootNode = entry.rootNode;\n if (\n rootNode.nodeType === Node.DOCUMENT_NODE ||\n rootNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE\n ) {\n return rootNode as unknown as ParentNode;\n }\n return document;\n }\n\n private _wiringRow(entry: IWiringEntry): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"wiring-row\";\n const prop = document.createElement(\"span\");\n prop.className = \"prop\";\n prop.textContent = entry.propName;\n const arrow = document.createTextNode(\" ← \");\n const path = document.createElement(\"span\");\n path.className = \"path\";\n path.textContent = `${entry.path}@${entry.stateName}`;\n const type = document.createElement(\"span\");\n type.className = \"badge-tag\";\n type.textContent = entry.bindingType;\n row.append(type, document.createTextNode(\" \"), prop, arrow, path);\n row.addEventListener(\"click\", () => {\n const binding = entry.bindingRef.deref();\n if (binding !== undefined) {\n this._highlightNodes([binding.node, binding.replaceNode]);\n }\n });\n return row;\n }\n\n private _declaredRow(entry: IDeclaredBinding): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"wiring-row\";\n const type = document.createElement(\"span\");\n type.className = \"badge-tag declared\";\n type.textContent = entry.origin;\n const prop = document.createElement(\"span\");\n prop.className = \"prop\";\n prop.textContent = entry.propName;\n const path = document.createElement(\"span\");\n path.className = \"path\";\n path.textContent = `${entry.path}@${entry.stateName}`;\n row.append(type, document.createTextNode(\" \"), prop, document.createTextNode(\" ← \"), path);\n row.addEventListener(\"click\", () => {\n this._highlightNodes([entry.element]);\n });\n return row;\n }\n\n private _renderTimelinePane(): void {\n const core = this._core!;\n const body = this._paneElements[\"timeline\"]!;\n const timeline = core.getTimeline();\n const start = Math.max(0, timeline.length - TIMELINE_RENDER_LIMIT);\n const rows: HTMLElement[] = [];\n if (start > 0) {\n rows.push(this._emptyRow(`…(${start} earlier entries)`));\n }\n for (let index = start; index < timeline.length; index++) {\n rows.push(this._timelineRow(timeline[index]));\n }\n if (rows.length === 0) {\n rows.push(this._emptyRow(\"no activity yet\"));\n }\n body.replaceChildren(...rows);\n body.scrollTop = body.scrollHeight;\n }\n\n private _timelineRow(entry: ITimelineEntry): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"timeline-row\";\n const time = document.createElement(\"span\");\n time.className = \"t\";\n time.textContent = `${(entry.time / 1000).toFixed(3)}s `;\n const kind = document.createElement(\"span\");\n kind.className = \"badge-tag kind\";\n kind.textContent = entry.kind;\n // subscriber 0 の command/event 空撃ちは警告表示(devtools-tag-design.md §3.2)\n if (entry.subscriberCount === 0) {\n kind.classList.add(\"warn\");\n kind.title = \"emitted with no subscribers\";\n }\n const label = document.createElement(\"span\");\n label.className = \"label\";\n const stateName = entry.stateName !== null ? `@${entry.stateName}` : \"\";\n label.textContent = ` ${entry.label}${stateName} `;\n const detail = document.createElement(\"span\");\n detail.className = \"detail\";\n detail.textContent = entry.detail;\n row.append(time, kind, label, detail);\n return row;\n }\n\n private _emptyRow(text: string): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"empty\";\n row.textContent = text;\n return row;\n }\n\n // --- highlight ---\n\n private _highlightPath(entry: IRosterEntry, path: string): void {\n const core = this._core!;\n const nodes: Node[] = [];\n for (const wiring of core.getWiringForPath(entry.name, path)) {\n const binding = wiring.bindingRef.deref();\n if (binding !== undefined) {\n nodes.push(binding.node, binding.replaceNode);\n }\n }\n this._highlightNodes(nodes);\n }\n\n private _highlightNodes(nodes: readonly Node[]): void {\n // shadowRoot 構築後にしか呼ばれない(各リスナーは _buildShadow 内で配線される)\n const layer = this._highlightLayer!;\n layer.replaceChildren();\n const seen = new Set<Element>();\n for (const node of nodes) {\n const element = node instanceof Element ? node : node.parentElement;\n if (element === null || seen.has(element) || !element.isConnected) {\n continue;\n }\n seen.add(element);\n const rect = element.getBoundingClientRect();\n const box = document.createElement(\"div\");\n box.className = \"hl-box\";\n box.style.left = `${rect.left}px`;\n box.style.top = `${rect.top}px`;\n box.style.width = `${rect.width}px`;\n box.style.height = `${rect.height}px`;\n layer.append(box);\n }\n // 2 秒後に自動で消す(追従はしない — クリック時スナップショット表示)\n setTimeout(() => {\n layer.replaceChildren();\n }, 2000);\n }\n}\n","/**\n * bootstrapDevtools.ts\n *\n * `<wcs-devtools>` の登録と自動挿入(devtools-tag-design.md §2)。\n * - 既に定義済みなら再定義しない\n * - ページに `<wcs-devtools>` が無ければ body 末尾に 1 つ挿入\n * (手動で書かれていれば挿入しない)\n * - SSR では何もしない\n */\n\nimport { WcsDevtools } from \"./shell/WcsDevtools\";\n\nconst TAG_NAME = \"wcs-devtools\";\n\nfunction insertIfAbsent(): void {\n if (document.querySelector(TAG_NAME) !== null) {\n return;\n }\n document.body.appendChild(document.createElement(TAG_NAME));\n}\n\nexport function bootstrapDevtools(): void {\n if (document.documentElement.hasAttribute(\"data-wcs-server\")) {\n return;\n }\n if (!customElements.get(TAG_NAME)) {\n customElements.define(TAG_NAME, WcsDevtools);\n }\n if (document.body !== null) {\n insertIfAbsent();\n } else {\n document.addEventListener(\"DOMContentLoaded\", insertIfAbsent, { once: true });\n }\n}\n"],"names":["DEVTOOLS_HOOK_GLOBAL","DEVTOOLS_PROTOCOL_VERSION","getOrCreateHookRegistry","globals","globalThis","existing","undefined","version","console","warn","registry","sources","Map","listeners","Set","applySink","source","size","_setSink","sourceId","id","event","listener","onEvent","register","has","set","onSourceRegistered","unregister","get","delete","onSourceUnregistered","addListener","add","values","createMinimalRegistry","formatValue","value","depth","length","slice","String","toString","objectValue","Array","isArray","shown","map","item","rest","join","proto","Object","getPrototypeOf","prototype","isPlainObject","keys","key","ctor","constructor","name","className","formatArgs","args","arg","text","RESERVED_STATE_NAME_PREFIX","pathKeyOf","stateName","path","DevtoolsCore","_timelineCapacity","_hiddenStateNames","_removeListener","_sources","_roster","_wiringByPathKey","_wiringEntryByBinding","WeakMap","_timeline","_seq","_paused","_changeListeners","options","this","timelineCapacity","hiddenStateNames","connected","paused","isHiddenStateName","startsWith","connect","_refreshRosterOf","_notify","_ingest","disconnect","clear","onChange","getSources","getRoster","entries","list","push","refreshRoster","getTimeline","clearTimeline","getWiringForPath","_collectAlive","getAllWiring","result","getWiringForNode","node","entry","binding","bindingRef","deref","replaceNode","contains","keysOf","rootNode","readValue","indexes","read","writeValue","write","kind","summary","getStateElements","alive","_appendTimeline","seq","time","performance","now","overflow","splice","_labelOf","address","listIndex","absolutePathInfo","pathInfo","type","label","detail","subscriberCount","absoluteAddress","hasOldValue","oldValue","labels","total","addresses","propName","bindingType","WeakRef","tokenName","COMMENT_PREFIXES","parseEntry","element","raw","origin","trimmed","trim","colon","indexOf","rhs","pathPart","filterParts","split","part","at","lastIndexOf","filters","filter","scanDeclaredBindings","root","bindAttributeName","querySelectorAll","getAttribute","walker","ownerDocument","createTreeWalker","NodeFilter","SHOW_COMMENT","comment","nextNode","textContent","prefix","find","candidate","parentElement","parentNode","Element","body","WcsDevtools","HTMLElement","observedAttributes","_core","_removeCoreListener","_panel","_badge","_stateSelect","_paneElements","_highlightLayer","_dirtyPanes","_renderScheduled","_selectedRosterKey","_selectedPath","_pickedNode","_pickMode","_expanded","_hotkeyHandler","_pickHandler","core","connectedCallback","document","documentElement","hasAttribute","shadowRoot","_buildShadow","capacity","Number","hidden","isFinite","_markDirty","_applyDock","_applyOpen","_installHotkey","disconnectedCallback","_uninstallHotkey","_exitPickMode","attributeChangedCallback","__flushRenderForTest","_renderDirty","shadow","attachShadow","mode","style","createElement","append","badge","title","addEventListener","toggle","panel","header","stateSelect","pickButton","_headerButton","_enterPickMode","setAttribute","dataset","pauseButton","clearButton","spacer","dockButton","next","closeButton","panes","heading","pane","h3","highlightLayer","button","open","force","removeAttribute","dock","classList","spec","parts","toLowerCase","alt","includes","shift","ctrl","meta","altKey","shiftKey","ctrlKey","metaKey","preventDefault","window","removeEventListener","target","getRootNode","stopPropagation","capture","querySelector","requestAnimationFrame","dirty","_renderStatePane","_renderWiringPane","_renderTimelinePane","_rosterKey","_selectedRoster","roster","select","selected","replaceChildren","option","_emptyRow","_renderTreeNode","container","ref","readable","row","paddingLeft","expandable","isExpandable","nodeKeyOf","expanded","keySpan","_highlightPath","valueSpan","_beginEdit","limit","Math","min","index","more","childKey","current","input","commit","JSON","parse","coerceInput","replaceChild","focus","contextLabel","tagName","nodeName","info","_wiringRow","declared","_scanRootOf","notice","tag","createTextNode","reload","location","_declaredRow","nodeType","Node","DOCUMENT_NODE","DOCUMENT_FRAGMENT_NODE","prop","arrow","_highlightNodes","timeline","start","max","rows","_timelineRow","scrollTop","scrollHeight","toFixed","nodes","wiring","layer","seen","isConnected","rect","getBoundingClientRect","box","left","top","width","height","setTimeout","TAG_NAME","insertIfAbsent","appendChild","bootstrapDevtools","customElements","define","once"],"mappings":"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"}