@wcstack/state 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +25 -17
- package/README.md +25 -17
- package/dist/auto.min.js +1 -1
- package/dist/auto.min.js.map +1 -1
- package/dist/define.d.ts +11 -7
- package/dist/index.d.ts +13 -7
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/manifest.d.ts +12 -1
- package/dist/manifest.esm.js +90 -35
- package/dist/split/chunks/declarationAliases.js +2 -0
- package/dist/split/chunks/declarationAliases.js.map +1 -0
- package/dist/split/chunks/filterRegistry.js +1 -1
- package/dist/split/chunks/filterRegistry.js.map +1 -1
- package/dist/split/chunks/mount.js +1 -1
- package/dist/split/chunks/mount.js.map +1 -1
- package/dist/split/chunks/pathDiagnostics.js +1 -1
- package/dist/split/chunks/pathDiagnostics.js.map +1 -1
- package/dist/split/chunks/registerComponents.js +1 -1
- package/dist/split/chunks/registerComponents.js.map +1 -1
- package/dist/split/chunks/version.js +1 -1
- package/dist/split/core.d.ts +11 -7
- package/dist/split/core.js +1 -1
- package/dist/split/core.js.map +1 -1
- package/dist/split/features/devtools.js +1 -1
- package/dist/split/features/devtools.js.map +1 -1
- package/dist/split/features/formats.js +1 -1
- package/dist/split/features/formats.js.map +1 -1
- package/dist/split/features/scopes.js +1 -1
- package/dist/split/features/scopes.js.map +1 -1
- package/dist/split/features/ssr.js +1 -1
- package/dist/split/features/ssr.js.map +1 -1
- package/dist/split/features/temporal.js +1 -1
- package/dist/split/features/temporal.js.map +1 -1
- package/dist/wcs-manifest.json +64 -25
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{c as t,S as e}from"../chunks/filterRegistry.js";import{P as n,Q as o,R as s,S as r,U as a,V as c,W as i,n as l,m as d,X as u,y as f,Y as p,L as m,o as h,D as N,Z as g,_ as y,v as b,$ as S,a0 as T,a1 as x,a2 as A,a3 as C,a4 as O,a5 as v,a6 as _,a7 as E,a8 as w,a9 as k,k as D,aa as M,ab as P,ac as j,ad as $,ae as W,g as B}from"../chunks/binder.js";import{H,a as q}from"../chunks/registerComponents.js";import{V as F}from"../chunks/version.js";import{W as R,I,g as z}from"../chunks/pathDiagnostics.js";import"../chunks/errorGuidance.js";import"../chunks/lifecycleHooks.js";import"../chunks/setAll.js";import"../chunks/getAllPropertyDescriptors.js";import"../chunks/checkDependency.js";import"../chunks/diagnosticsHooks.js";const J=/^@@wcs-(?:for|if|elseif|else):[^-]/,L=/^@@wcs-(for|if|elseif|else)-start:(.+)$/,V=/^@@wcs-(for|if|elseif|else)-end:(.+)$/,G=/^@@wcs-text-start:(.+)$/;function Q(t){return t.replace(/</g,"\\u003c").replace(/>/g,"\\u003e").replace(/&/g,"\\u0026").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}class U extends H{_stateData=null;_templates=null;_hydrateProps=null;get version(){return this.getAttribute("version")||""}get stateData(){return null===this._stateData&&(this._stateData=this._loadStateData()),this._stateData}get templates(){return null===this._templates&&(this._templates=this._loadTemplates()),this._templates}get hydrateProps(){return null===this._hydrateProps&&(this._hydrateProps=this._loadHydrateProps()),this._hydrateProps}getTemplate(t){return this.templates.get(t)??null}verifyVersion(){const t=this.version;if(!t)return!0;const e=t.split("."),n=F.split(".");return e[0]===n[0]&&e[1]===n[1]}setStateData(t){this._stateData=t}setHydrateProps(t){this._hydrateProps=t}_loadStateData(){const t=this.querySelector('script[type="application/json"]:not([data-wcs-ssr-props])');if(!t)return{};try{return JSON.parse(t.textContent||"{}")}catch{return{}}}_loadTemplates(){const t=new Map,e=this.querySelectorAll("template[id]");for(const n of e){const e=n.getAttribute("id");e&&t.set(e,n)}return t}_loadHydrateProps(){const t=this.querySelector("script[data-wcs-ssr-props]");if(!t)return{};try{return JSON.parse(t.textContent||"{}")}catch{return{}}}static find(e){const n=t.tagNames.ssr,o=e instanceof Element?e:e instanceof Document?e.documentElement:null;if(!o)return null;return o.querySelector(n)}static extractStateData(t){const e=t.__state;if(!e||"object"!=typeof e)return{};const n={};for(const t of Object.keys(e)){if(t.startsWith("$"))continue;const o=Object.getOwnPropertyDescriptor(e,t);if(void 0!==o&&"function"==typeof o.get)continue;const s=e[t];"function"!=typeof s&&(n[t]=s)}return n}static buildContent(e,c){const i=document.createElement("script");i.setAttribute("type","application/json"),i.textContent=Q(JSON.stringify(c)),e.appendChild(i);const l=n();for(const n of l){const s=o(n);if(!s)continue;const r=document.createElement("template");r.setAttribute("id",n);const a=s.parseBindTextResult,c="else"===a.bindingType?"else:":`${a.bindingType}: ${a.statePathName}`;r.setAttribute(t.bindAttributeName,c);const i=s.fragment.cloneNode(!0);r.content.appendChild(i),e.appendChild(r)}const d=s();if(d.length>0){const t={};for(let e=0;e<d.length;e++){const n=d[e],o=r(n);if(0===o.length)continue;const s=`wcs-ssr-${e}`;n.setAttribute("data-wcs-ssr-id",s);const a={};for(const t of o)a[t.propName]=t.value;t[s]=a}if(Object.keys(t).length>0){const n=document.createElement("script");n.setAttribute("type","application/json"),n.setAttribute("data-wcs-ssr-props",""),n.textContent=Q(JSON.stringify(t)),e.appendChild(n)}}a()}static removeBlockBoundaryComments(t){const e=document.createTreeWalker(t,NodeFilter.SHOW_COMMENT),n=[];for(;e.nextNode();){const t=e.currentNode;(L.test(t.data)||V.test(t.data))&&n.push(t)}for(const t of n)t.remove()}static removeStructuralComments(t){const e=document.createTreeWalker(t,NodeFilter.SHOW_COMMENT),n=[];for(;e.nextNode();){const t=e.currentNode;J.test(t.data)&&n.push(t)}for(const t of n)t.remove()}static restoreTextBindings(t){const e=document.createTreeWalker(t,NodeFilter.SHOW_COMMENT),n=[];for(;e.nextNode();){const t=e.currentNode,o=G.exec(t.data);o&&n.push({comment:t,path:o[1]})}for(const{comment:t,path:e}of n){const n=document.createComment(`@@: ${e}`);t.parentNode.insertBefore(n,t);let o=t.nextSibling;t.remove();const s=`@@wcs-text-end:${e}`;for(;o;){const t=o.nextSibling;if(o.nodeType===Node.COMMENT_NODE&&o.data===s){o.parentNode.removeChild(o);break}o.parentNode.removeChild(o),o=t}}}static cleanupDom(e){const n=document.body,o=e.querySelectorAll(t.tagNames.ssr),s=new Map;for(const t of o){const e=t.querySelectorAll("template[id]");for(const t of e){const e=t.getAttribute("id");e&&s.set(e,t)}}const r=document.createTreeWalker(n,NodeFilter.SHOW_COMMENT),a=[];for(;r.nextNode();){const t=r.currentNode;L.test(t.data)&&a.push(t)}for(const t of a){const e=L.exec(t.data),n=`@@wcs-${e[1]}-end:${e[2]}`;let o=t.nextSibling;for(;o;){const t=o.nextSibling;if(o.nodeType===Node.COMMENT_NODE&&o.data===n){o.remove();break}o.remove(),o=t}t.remove()}U.restoreTextBindings(n);const c=document.createTreeWalker(n,NodeFilter.SHOW_COMMENT),i=[];for(;c.nextNode();){const t=c.currentNode;if(J.test(t.data)){const e=t.data.split(":")[1];i.push({comment:t,uuid:e})}}for(const{comment:e,uuid:n}of i){const o=s.get(n);if(o){const n=document.createElement("template"),s=o.getAttribute(t.bindAttributeName);s&&n.setAttribute(t.bindAttributeName,s);const r=document.importNode(o.content,!0);if(r.childNodes.length>0)n.content.appendChild(r);else for(const t of Array.from(o.childNodes))n.content.appendChild(document.importNode(t,!0));e.parentNode.replaceChild(n,e)}}const l=e.querySelectorAll("[data-wcs-ssr-id]");for(const t of l)t.removeAttribute("data-wcs-ssr-id");for(const t of o)t.remove()}}const X={protocol:"wcs-ssr-snapshot",version:1,build:function(e){const n=t.tagNames.state,o=t.tagNames.ssr,s=e.querySelectorAll(`${n}[enable-ssr]:not([mount]):not([bind-component])`);for(const t of s){const e=t.previousElementSibling;if(null!==e&&e.tagName.toLowerCase()===o)continue;const n=document.createElement(o);n.setAttribute("version",F),U.buildContent(n,U.extractStateData(t)),t.parentNode?.insertBefore(n,t)}}};const Y=new Set(["for","if","elseif","else"]);function Z(t){const e=new j;if(0===t.length)return{bindingInfos:[],subscriberNodes:[],bindingSession:e};const n=t[0].parentNode,o=t[t.length-1].nextSibling,s=document.createElement("div");for(const e of t)s.appendChild(e);const[r,a]=i(s),c=e.initialize(a,{registerAddress:!1,applyOnReconnect:!1});if(n)for(;s.firstChild;)n.insertBefore(s.firstChild,o);return{bindingInfos:c,subscriberNodes:r,bindingSession:e}}function K(t,e,n){for(const o of e)"event"===o.bindingType||Y.has(o.bindingType)||o.node.nodeType===Node.COMMENT_NODE||o.statePathName in I||z(o.statePathName).wildcardCount>n||t.push(o)}function tt(e,n,o){const s={for:t.commentForPrefix,if:t.commentIfPrefix,elseif:t.commentElseIfPrefix,else:t.commentElsePrefix}[n];if(!s)return null;const r=`@@${s}:${o}`,a=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT);for(;a.nextNode();){const t=a.currentNode;if(t.data===r)return t}return null}function et(e,n){const o=e;let s=null;for(const[e,r]of n.templates){const n=r.getAttribute(t.bindAttributeName)||"";let a=N(n)[0];const c=a.bindingType;"else"===c&&s&&(a={...s,outFilters:[...s.outFilters,$()],bindingType:"else"}),"if"===c||"elseif"===c?s=a:"else"===c&&(s=null);const i=document.importNode(r.content,!0),l="for"===c?a.statePathName:void 0;g(i),"string"==typeof l&&y(i,l),b(o,i,l);const d={fragment:i,parseBindTextResult:a,nodeInfos:S(i)};T(e,o,d)}}const nt={hydrate:async function(e){await c(e);const n=e.querySelectorAll(t.tagNames.ssr);for(const t of n){const n=t;if(!n.verifyVersion())return console.warn(`[@wcstack/state] SSR version mismatch: server="${n.version}", client="${F}". Falling back to full render.`),U.cleanupDom(e),!1}for(const t of n)et(e,t);const s=function(t){const e=[],n=document.createTreeWalker(t,NodeFilter.SHOW_COMMENT),o=[];for(;n.nextNode();)o.push(n.currentNode);for(const t of o){const n=L.exec(t.data);if(!n)continue;const o=n[1],s=n[2],r=s.split(":");let a,c,i=null;"for"===o?(a=r[0],c=r[1],i=parseInt(r[2],10)):(a=r[0],c=r.slice(1).join(":"));const l=[];let d=t.nextSibling;const u=`@@wcs-${o}-end:${s}`;for(;d&&(d.nodeType!==Node.COMMENT_NODE||d.data!==u);)l.push(d),d=d.nextSibling;e.push({type:o,uuid:a,path:c,index:i,nodes:l})}return e}(document.body),r=function(t,e){const n=new Map,s=[];for(const o of e){if(0===o.nodes.length)continue;const e=x(o.nodes),{bindingInfos:r,subscriberNodes:a,bindingSession:c}=Z(o.nodes);A(e,c);for(const t of a)t.nodeType===Node.ELEMENT_NODE&&t.setAttribute("data-wcs-completed","");C(e,r),O(e,a);const i=[];for(const t of r)t.statePathName in I&&i.push(t);if(v(e,i),"for"===o.type&&null!==o.index){const a=tt(t,"for",o.uuid);if(a){const t=_(null,o.index);E(a,t,e);const i=o.nodes[o.nodes.length-1];w(a,i),k(a,e);const l=z(o.path+"."+R),d=D(l,t);M(e,d),c.initialize(r,{registerAddress:!0,registerPathInfo:!1,applyOnReconnect:!1}),K(s,r,l.wildcardCount);let u=n.get(o.uuid);u||(u=[],n.set(o.uuid,u)),u.push(t)}}else{const n=tt(t,o.type,o.uuid);n&&(k(n,e),c.initialize(r,{registerAddress:!0,registerPathInfo:!1,applyOnReconnect:!1}),K(s,r,0))}}for(const[e,s]of n){const n=tt(t,"for",e);if(!n)continue;const r=n.getRootNode(),a=o(e);if(!a)continue;const c=a.parseBindTextResult.statePathName,i=f(r);i&&i.createState("readonly",t=>{const e=t[c];Array.isArray(e)&&P(e,s)})}return s}(document.body,s);U.removeBlockBoundaryComments(document.body);const a=[];for(const t of n)t.parentNode&&(a.push({el:t,parent:t.parentNode,next:t.nextSibling}),t.remove());U.restoreTextBindings(document.body);const[N,g]=i(document.body);for(const t of N)if(t.nodeType===Node.ELEMENT_NODE){const e=t;e.hasAttribute("data-wcs-completed")||(l(t,null),e.setAttribute("data-wcs-completed",""))}else l(t,null);const y=[],b=[],S=d(document.body).initialize(g);for(const t of S)if("event"!==t.bindingType)if(Y.has(t.bindingType))b.push(t);else{if(t.statePathName.includes(R))continue;y.push(t)}for(const t of b)if("for"===t.bindingType){const e=u(t),n=t.replaceNode.getRootNode(),o=f(n);o&&o.createState("readonly",n=>{const o=n[t.statePathName];Array.isArray(o)&&(p(e,o),m(e,o))})}h([...y,...r]);for(const{el:t,parent:e,next:n}of a)e.insertBefore(t,n);const T=e.querySelectorAll(t.tagNames.ssr);for(const t of T){const n=t.hydrateProps;for(const[t,o]of Object.entries(n)){const n=e.querySelector(`[data-wcs-ssr-id="${t}"]`);if(n)for(const[t,e]of Object.entries(o))n[t]=e}}const j=e.querySelectorAll("[data-wcs-completed]");for(const t of j)t.removeAttribute("data-wcs-completed");return!0},loadState(t){const e=t.parentNode;if(!e)return null;const n=U.find(e);if(!n)return null;const o=n.stateData;return Object.keys(o).length>0?o:null},async emitSnapshot(e){await B(e.rootNode);const n=U.extractStateData(e),o=document.createElement(t.tagNames.ssr);o.setAttribute("version",F),U.buildContent(o,n),e.parentNode?.insertBefore(o,e)}};let ot=!1;function st(){ot||(ot=!0,W(nt),q(e=>{e.get(t.tagNames.ssr)||e.define(t.tagNames.ssr,U)}),function(){const t=globalThis;void 0===t[e]&&(t[e]=X)}())}const rt={name:"ssr",install(){st()}};export{rt as default,rt as ssr};
|
|
1
|
+
import{c as t,S as e}from"../chunks/filterRegistry.js";import{P as n,Q as o,R as s,S as r,U as a,V as i,W as c,n as l,m as d,X as u,y as f,Y as p,L as m,o as h,D as N,Z as g,_ as y,v as b,$ as S,a0 as T,a1 as x,a2 as A,a3 as C,a4 as O,a5 as v,a6 as _,a7 as E,a8 as w,a9 as k,k as D,aa as M,ab as P,ac as j,ad as $,ae as W,g as B}from"../chunks/binder.js";import{H,a as q}from"../chunks/registerComponents.js";import{V as F}from"../chunks/version.js";import{W as R,I,g as z}from"../chunks/pathDiagnostics.js";import"../chunks/errorGuidance.js";import"../chunks/lifecycleHooks.js";import"../chunks/declarationAliases.js";import"../chunks/setAll.js";import"../chunks/getAllPropertyDescriptors.js";import"../chunks/checkDependency.js";import"../chunks/diagnosticsHooks.js";const J=/^@@wcs-(?:for|if|elseif|else):[^-]/,L=/^@@wcs-(for|if|elseif|else)-start:(.+)$/,V=/^@@wcs-(for|if|elseif|else)-end:(.+)$/,G=/^@@wcs-text-start:(.+)$/;function Q(t){return t.replace(/</g,"\\u003c").replace(/>/g,"\\u003e").replace(/&/g,"\\u0026").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}class U extends H{_stateData=null;_templates=null;_hydrateProps=null;get version(){return this.getAttribute("version")||""}get stateData(){return null===this._stateData&&(this._stateData=this._loadStateData()),this._stateData}get templates(){return null===this._templates&&(this._templates=this._loadTemplates()),this._templates}get hydrateProps(){return null===this._hydrateProps&&(this._hydrateProps=this._loadHydrateProps()),this._hydrateProps}getTemplate(t){return this.templates.get(t)??null}verifyVersion(){const t=this.version;if(!t)return!0;const e=t.split("."),n=F.split(".");return e[0]===n[0]&&e[1]===n[1]}setStateData(t){this._stateData=t}setHydrateProps(t){this._hydrateProps=t}_loadStateData(){const t=this.querySelector('script[type="application/json"]:not([data-wcs-ssr-props])');if(!t)return{};try{return JSON.parse(t.textContent||"{}")}catch{return{}}}_loadTemplates(){const t=new Map,e=this.querySelectorAll("template[id]");for(const n of e){const e=n.getAttribute("id");e&&t.set(e,n)}return t}_loadHydrateProps(){const t=this.querySelector("script[data-wcs-ssr-props]");if(!t)return{};try{return JSON.parse(t.textContent||"{}")}catch{return{}}}static find(e){const n=t.tagNames.ssr,o=e instanceof Element?e:e instanceof Document?e.documentElement:null;if(!o)return null;return o.querySelector(n)}static extractStateData(t){const e=t.__state;if(!e||"object"!=typeof e)return{};const n={};for(const t of Object.keys(e)){if(t.startsWith("$"))continue;const o=Object.getOwnPropertyDescriptor(e,t);if(void 0!==o&&"function"==typeof o.get)continue;const s=e[t];"function"!=typeof s&&(n[t]=s)}return n}static buildContent(e,i){const c=document.createElement("script");c.setAttribute("type","application/json"),c.textContent=Q(JSON.stringify(i)),e.appendChild(c);const l=n();for(const n of l){const s=o(n);if(!s)continue;const r=document.createElement("template");r.setAttribute("id",n);const a=s.parseBindTextResult,i="else"===a.bindingType?"else:":`${a.bindingType}: ${a.statePathName}`;r.setAttribute(t.bindAttributeName,i);const c=s.fragment.cloneNode(!0);r.content.appendChild(c),e.appendChild(r)}const d=s();if(d.length>0){const t={};for(let e=0;e<d.length;e++){const n=d[e],o=r(n);if(0===o.length)continue;const s=`wcs-ssr-${e}`;n.setAttribute("data-wcs-ssr-id",s);const a={};for(const t of o)a[t.propName]=t.value;t[s]=a}if(Object.keys(t).length>0){const n=document.createElement("script");n.setAttribute("type","application/json"),n.setAttribute("data-wcs-ssr-props",""),n.textContent=Q(JSON.stringify(t)),e.appendChild(n)}}a()}static removeBlockBoundaryComments(t){const e=document.createTreeWalker(t,NodeFilter.SHOW_COMMENT),n=[];for(;e.nextNode();){const t=e.currentNode;(L.test(t.data)||V.test(t.data))&&n.push(t)}for(const t of n)t.remove()}static removeStructuralComments(t){const e=document.createTreeWalker(t,NodeFilter.SHOW_COMMENT),n=[];for(;e.nextNode();){const t=e.currentNode;J.test(t.data)&&n.push(t)}for(const t of n)t.remove()}static restoreTextBindings(t){const e=document.createTreeWalker(t,NodeFilter.SHOW_COMMENT),n=[];for(;e.nextNode();){const t=e.currentNode,o=G.exec(t.data);o&&n.push({comment:t,path:o[1]})}for(const{comment:t,path:e}of n){const n=document.createComment(`@@: ${e}`);t.parentNode.insertBefore(n,t);let o=t.nextSibling;t.remove();const s=`@@wcs-text-end:${e}`;for(;o;){const t=o.nextSibling;if(o.nodeType===Node.COMMENT_NODE&&o.data===s){o.parentNode.removeChild(o);break}o.parentNode.removeChild(o),o=t}}}static cleanupDom(e){const n=document.body,o=e.querySelectorAll(t.tagNames.ssr),s=new Map;for(const t of o){const e=t.querySelectorAll("template[id]");for(const t of e){const e=t.getAttribute("id");e&&s.set(e,t)}}const r=document.createTreeWalker(n,NodeFilter.SHOW_COMMENT),a=[];for(;r.nextNode();){const t=r.currentNode;L.test(t.data)&&a.push(t)}for(const t of a){const e=L.exec(t.data),n=`@@wcs-${e[1]}-end:${e[2]}`;let o=t.nextSibling;for(;o;){const t=o.nextSibling;if(o.nodeType===Node.COMMENT_NODE&&o.data===n){o.remove();break}o.remove(),o=t}t.remove()}U.restoreTextBindings(n);const i=document.createTreeWalker(n,NodeFilter.SHOW_COMMENT),c=[];for(;i.nextNode();){const t=i.currentNode;if(J.test(t.data)){const e=t.data.split(":")[1];c.push({comment:t,uuid:e})}}for(const{comment:e,uuid:n}of c){const o=s.get(n);if(o){const n=document.createElement("template"),s=o.getAttribute(t.bindAttributeName);s&&n.setAttribute(t.bindAttributeName,s);const r=document.importNode(o.content,!0);if(r.childNodes.length>0)n.content.appendChild(r);else for(const t of Array.from(o.childNodes))n.content.appendChild(document.importNode(t,!0));e.parentNode.replaceChild(n,e)}}const l=e.querySelectorAll("[data-wcs-ssr-id]");for(const t of l)t.removeAttribute("data-wcs-ssr-id");for(const t of o)t.remove()}}const X={protocol:"wcs-ssr-snapshot",version:1,build:function(e){const n=t.tagNames.state,o=t.tagNames.ssr,s=e.querySelectorAll(`${n}[enable-ssr]:not([mount]):not([bind-component])`);for(const t of s){const e=t.previousElementSibling;if(null!==e&&e.tagName.toLowerCase()===o)continue;const n=document.createElement(o);n.setAttribute("version",F),U.buildContent(n,U.extractStateData(t)),t.parentNode?.insertBefore(n,t)}}};const Y=new Set(["for","if","elseif","else"]);function Z(t){const e=new j;if(0===t.length)return{bindingInfos:[],subscriberNodes:[],bindingSession:e};const n=t[0].parentNode,o=t[t.length-1].nextSibling,s=document.createElement("div");for(const e of t)s.appendChild(e);const[r,a]=c(s),i=e.initialize(a,{registerAddress:!1,applyOnReconnect:!1});if(n)for(;s.firstChild;)n.insertBefore(s.firstChild,o);return{bindingInfos:i,subscriberNodes:r,bindingSession:e}}function K(t,e,n){for(const o of e)"event"===o.bindingType||Y.has(o.bindingType)||o.node.nodeType===Node.COMMENT_NODE||o.statePathName in I||z(o.statePathName).wildcardCount>n||t.push(o)}function tt(e,n,o){const s={for:t.commentForPrefix,if:t.commentIfPrefix,elseif:t.commentElseIfPrefix,else:t.commentElsePrefix}[n];if(!s)return null;const r=`@@${s}:${o}`,a=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT);for(;a.nextNode();){const t=a.currentNode;if(t.data===r)return t}return null}function et(e,n){const o=e;let s=null;for(const[e,r]of n.templates){const n=r.getAttribute(t.bindAttributeName)||"";let a=N(n)[0];const i=a.bindingType;"else"===i&&s&&(a={...s,outFilters:[...s.outFilters,$()],bindingType:"else"}),"if"===i||"elseif"===i?s=a:"else"===i&&(s=null);const c=document.importNode(r.content,!0),l="for"===i?a.statePathName:void 0;g(c),"string"==typeof l&&y(c,l),b(o,c,l);const d={fragment:c,parseBindTextResult:a,nodeInfos:S(c)};T(e,o,d)}}const nt={hydrate:async function(e){await i(e);const n=e.querySelectorAll(t.tagNames.ssr);for(const t of n){const n=t;if(!n.verifyVersion())return console.warn(`[@wcstack/state] SSR version mismatch: server="${n.version}", client="${F}". Falling back to full render.`),U.cleanupDom(e),!1}for(const t of n)et(e,t);const s=function(t){const e=[],n=document.createTreeWalker(t,NodeFilter.SHOW_COMMENT),o=[];for(;n.nextNode();)o.push(n.currentNode);for(const t of o){const n=L.exec(t.data);if(!n)continue;const o=n[1],s=n[2],r=s.split(":");let a,i,c=null;"for"===o?(a=r[0],i=r[1],c=parseInt(r[2],10)):(a=r[0],i=r.slice(1).join(":"));const l=[];let d=t.nextSibling;const u=`@@wcs-${o}-end:${s}`;for(;d&&(d.nodeType!==Node.COMMENT_NODE||d.data!==u);)l.push(d),d=d.nextSibling;e.push({type:o,uuid:a,path:i,index:c,nodes:l})}return e}(document.body),r=function(t,e){const n=new Map,s=[];for(const o of e){if(0===o.nodes.length)continue;const e=x(o.nodes),{bindingInfos:r,subscriberNodes:a,bindingSession:i}=Z(o.nodes);A(e,i);for(const t of a)t.nodeType===Node.ELEMENT_NODE&&t.setAttribute("data-wcs-completed","");C(e,r),O(e,a);const c=[];for(const t of r)t.statePathName in I&&c.push(t);if(v(e,c),"for"===o.type&&null!==o.index){const a=tt(t,"for",o.uuid);if(a){const t=_(null,o.index);E(a,t,e);const c=o.nodes[o.nodes.length-1];w(a,c),k(a,e);const l=z(o.path+"."+R),d=D(l,t);M(e,d),i.initialize(r,{registerAddress:!0,registerPathInfo:!1,applyOnReconnect:!1}),K(s,r,l.wildcardCount);let u=n.get(o.uuid);u||(u=[],n.set(o.uuid,u)),u.push(t)}}else{const n=tt(t,o.type,o.uuid);n&&(k(n,e),i.initialize(r,{registerAddress:!0,registerPathInfo:!1,applyOnReconnect:!1}),K(s,r,0))}}for(const[e,s]of n){const n=tt(t,"for",e);if(!n)continue;const r=n.getRootNode(),a=o(e);if(!a)continue;const i=a.parseBindTextResult.statePathName,c=f(r);c&&c.createState("readonly",t=>{const e=t[i];Array.isArray(e)&&P(e,s)})}return s}(document.body,s);U.removeBlockBoundaryComments(document.body);const a=[];for(const t of n)t.parentNode&&(a.push({el:t,parent:t.parentNode,next:t.nextSibling}),t.remove());U.restoreTextBindings(document.body);const[N,g]=c(document.body);for(const t of N)if(t.nodeType===Node.ELEMENT_NODE){const e=t;e.hasAttribute("data-wcs-completed")||(l(t,null),e.setAttribute("data-wcs-completed",""))}else l(t,null);const y=[],b=[],S=d(document.body).initialize(g);for(const t of S)if("event"!==t.bindingType)if(Y.has(t.bindingType))b.push(t);else{if(t.statePathName.includes(R))continue;y.push(t)}for(const t of b)if("for"===t.bindingType){const e=u(t),n=t.replaceNode.getRootNode(),o=f(n);o&&o.createState("readonly",n=>{const o=n[t.statePathName];Array.isArray(o)&&(p(e,o),m(e,o))})}h([...y,...r]);for(const{el:t,parent:e,next:n}of a)e.insertBefore(t,n);const T=e.querySelectorAll(t.tagNames.ssr);for(const t of T){const n=t.hydrateProps;for(const[t,o]of Object.entries(n)){const n=e.querySelector(`[data-wcs-ssr-id="${t}"]`);if(n)for(const[t,e]of Object.entries(o))n[t]=e}}const j=e.querySelectorAll("[data-wcs-completed]");for(const t of j)t.removeAttribute("data-wcs-completed");return!0},loadState(t){const e=t.parentNode;if(!e)return null;const n=U.find(e);if(!n)return null;const o=n.stateData;return Object.keys(o).length>0?o:null},async emitSnapshot(e){await B(e.rootNode);const n=U.extractStateData(e),o=document.createElement(t.tagNames.ssr);o.setAttribute("version",F),U.buildContent(o,n),e.parentNode?.insertBefore(o,e)}};let ot=!1;function st(){ot||(ot=!0,W(nt),q(e=>{e.get(t.tagNames.ssr)||e.define(t.tagNames.ssr,U)}),function(){const t=globalThis;void 0===t[e]&&(t[e]=X)}())}const rt={name:"ssr",install(){st()}};export{rt as default,rt as ssr};
|
|
2
2
|
//# sourceMappingURL=ssr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr.js","sources":["../../../../../src/ssr/Ssr.ts","../../../../../src/ssr/buildSsrDocument.ts","../../../../../src/ssr/hydrateBindings.ts","../../../../../src/ssr/install.ts","../../../../../src/features/ssr.ts"],"sourcesContent":["import { config } from \"../config\";\nimport { IState } from \"../types\";\nimport { VERSION } from \"../version\";\nimport { getAllFragmentUUIDs, getFragmentInfoByUUID } from \"../structural/fragmentInfoByUUID\";\nimport { getAllSsrPropertyNodes, getSsrProperties, clearSsrPropertyStore } from \"../apply/ssrPropertyStore\";\nimport { HTMLElementBase } from \"../platform/HTMLElementBase\";\n\nexport interface ISsrElement {\n readonly version: string;\n readonly stateData: IState;\n readonly templates: Map<string, HTMLTemplateElement>;\n readonly hydrateProps: Record<string, Record<string, unknown>>;\n getTemplate(uuid: string): HTMLTemplateElement | null;\n verifyVersion(): boolean;\n}\n\n// SSR コメントパターン\nconst SSR_PLACEHOLDER_COMMENT = /^@@wcs-(?:for|if|elseif|else):[^-]/;\nconst SSR_BLOCK_START = /^@@wcs-(for|if|elseif|else)-start:(.+)$/;\nconst SSR_BLOCK_END = /^@@wcs-(for|if|elseif|else)-end:(.+)$/;\nconst SSR_TEXT_START = /^@@wcs-text-start:(.+)$/;\n\nexport {\n SSR_PLACEHOLDER_COMMENT,\n SSR_BLOCK_START,\n SSR_BLOCK_END,\n SSR_TEXT_START,\n};\n\n/**\n * script 要素へ埋め込む JSON を HTML パーサから保護する。\n * HTML 直列化時、script の中身は生のまま出力されるため、state 値に\n * \"</script>\" や \"<!--\" を含む文字列があると script を脱出できてしまう。\n * \"<\" \">\" \"&\" と U+2028/U+2029 を JSON の \\uXXXX エスケープへ置換する\n * (JSON.parse では元の文字列と等価に復元される)。\n */\nfunction escapeJsonForScript(json: string): string {\n return json\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\nexport class Ssr extends HTMLElementBase implements ISsrElement {\n private _stateData: IState | null = null;\n private _templates: Map<string, HTMLTemplateElement> | null = null;\n private _hydrateProps: Record<string, Record<string, unknown>> | null = null;\n\n get version(): string {\n return this.getAttribute('version') || '';\n }\n\n get stateData(): IState {\n if (this._stateData === null) {\n this._stateData = this._loadStateData();\n }\n return this._stateData;\n }\n\n get templates(): Map<string, HTMLTemplateElement> {\n if (this._templates === null) {\n this._templates = this._loadTemplates();\n }\n return this._templates;\n }\n\n get hydrateProps(): Record<string, Record<string, unknown>> {\n if (this._hydrateProps === null) {\n this._hydrateProps = this._loadHydrateProps();\n }\n return this._hydrateProps;\n }\n\n getTemplate(uuid: string): HTMLTemplateElement | null {\n return this.templates.get(uuid) ?? null;\n }\n\n /**\n * サーバーの SSR バージョンとクライアントの state バージョンを検証する。\n * メジャー・マイナーバージョンが一致すればtrue。\n * version 属性がない場合は検証スキップ(true)。\n */\n verifyVersion(): boolean {\n const serverVersion = this.version;\n if (!serverVersion) return true;\n const serverParts = serverVersion.split('.');\n const clientParts = VERSION.split('.');\n // メジャー・マイナーが一致すれば互換\n return serverParts[0] === clientParts[0] && serverParts[1] === clientParts[1];\n }\n\n setStateData(data: IState): void {\n this._stateData = data;\n }\n\n setHydrateProps(props: Record<string, Record<string, unknown>>): void {\n this._hydrateProps = props;\n }\n\n private _loadStateData(): IState {\n const script = this.querySelector(\n `script[type=\"application/json\"]:not([data-wcs-ssr-props])`\n );\n if (!script) return {};\n try {\n return JSON.parse(script.textContent || '{}');\n } catch {\n return {};\n }\n }\n\n private _loadTemplates(): Map<string, HTMLTemplateElement> {\n const map = new Map<string, HTMLTemplateElement>();\n const templates = this.querySelectorAll<HTMLTemplateElement>('template[id]');\n for (const tpl of templates) {\n const id = tpl.getAttribute('id');\n if (id) {\n map.set(id, tpl);\n }\n }\n return map;\n }\n\n private _loadHydrateProps(): Record<string, Record<string, unknown>> {\n const script = this.querySelector('script[data-wcs-ssr-props]');\n if (!script) return {};\n try {\n return JSON.parse(script.textContent || '{}');\n } catch {\n return {};\n }\n }\n\n static find(root: Node): ISsrElement | null {\n const tagName = config.tagNames.ssr;\n const parentEl = root instanceof Element\n ? root\n : root instanceof Document\n ? root.documentElement\n : null;\n if (!parentEl) return null;\n const el = parentEl.querySelector(tagName);\n return el as ISsrElement | null;\n }\n\n /**\n * stateData と構造テンプレート・プロパティから <wcs-ssr> の中身を構築する。\n * server パッケージの renderToString から呼ばれる。\n */\n /**\n * wcs-state 要素から $ プレフィックスや関数を除いたデータを抽出する。\n */\n static extractStateData(stateEl: Element): Record<string, any> {\n const raw = (stateEl as any).__state;\n if (!raw || typeof raw !== 'object') return {};\n const data: Record<string, any> = {};\n for (const key of Object.keys(raw)) {\n if (key.startsWith('$')) continue;\n // **アクセサは評価しない。** スナップショットが運ぶのはデータで、派生値は\n // クライアントが同じ宣言から作り直す。ここは Object.entries で舐めていたので、\n // own かつ enumerable な getter を**生の state オブジェクト**を this にして\n // 評価していた — proxy の上でしか意味を持たない本体(`this[\"items.*.n\"]` や\n // `this.$getAll(...)`)が、パス getter なら NaN → JSON の null で静かに壊れ、\n // `$getAll` を呼ぶ getter なら TypeError でページ全体の SSR を落としていた\n // (docs/state-recursive-path-impl-plan.md §7)。\n const descriptor = Object.getOwnPropertyDescriptor(raw, key);\n if (descriptor !== undefined && typeof descriptor.get === 'function') continue;\n const value = (raw as Record<string, unknown>)[key];\n if (typeof value !== 'function') {\n data[key] = value;\n }\n }\n return data;\n }\n\n static buildContent(ssrEl: Element, stateData: Record<string, any>): void {\n // 初期データ JSON\n const jsonScript = document.createElement('script');\n jsonScript.setAttribute('type', 'application/json');\n jsonScript.textContent = escapeJsonForScript(JSON.stringify(stateData));\n ssrEl.appendChild(jsonScript);\n\n // UUID で管理されているテンプレートを復元して格納\n const uuids = getAllFragmentUUIDs();\n for (const uuid of uuids) {\n const fragmentInfo = getFragmentInfoByUUID(uuid);\n if (!fragmentInfo) continue;\n\n const tpl = document.createElement('template');\n tpl.setAttribute('id', uuid);\n\n const bindResult = fragmentInfo.parseBindTextResult;\n const bindText = bindResult.bindingType === 'else'\n ? 'else:'\n : `${bindResult.bindingType}: ${bindResult.statePathName}`;\n tpl.setAttribute(config.bindAttributeName, bindText);\n\n const content = fragmentInfo.fragment.cloneNode(true) as DocumentFragment;\n tpl.content.appendChild(content);\n\n ssrEl.appendChild(tpl);\n }\n\n // 属性で代替不可なプロパティをハイドレーション用に格納\n const ssrNodes = getAllSsrPropertyNodes();\n if (ssrNodes.length > 0) {\n const propsData: Record<string, Record<string, unknown>> = {};\n for (let i = 0; i < ssrNodes.length; i++) {\n const node = ssrNodes[i];\n const entries = getSsrProperties(node);\n if (entries.length === 0) continue;\n const id = `wcs-ssr-${i}`;\n (node as Element).setAttribute('data-wcs-ssr-id', id);\n const props: Record<string, unknown> = {};\n for (const entry of entries) {\n props[entry.propName] = entry.value;\n }\n propsData[id] = props;\n }\n if (Object.keys(propsData).length > 0) {\n const propsScript = document.createElement('script');\n propsScript.setAttribute('type', 'application/json');\n propsScript.setAttribute('data-wcs-ssr-props', '');\n propsScript.textContent = escapeJsonForScript(JSON.stringify(propsData));\n ssrEl.appendChild(propsScript);\n }\n }\n\n clearSsrPropertyStore();\n }\n\n /**\n * SSR ブロック境界コメント (@@wcs-*-start/end) を除去する\n */\n static removeBlockBoundaryComments(root: Node): void {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n const toRemove: Comment[] = [];\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n if (SSR_BLOCK_START.test(comment.data) || SSR_BLOCK_END.test(comment.data)) {\n toRemove.push(comment);\n }\n }\n for (const comment of toRemove) {\n comment.remove();\n }\n }\n\n /**\n * SSR の構造プレースホルダーコメント (@@wcs-for:uuid 等) を除去する\n */\n static removeStructuralComments(root: Node): void {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n const toRemove: Comment[] = [];\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n if (SSR_PLACEHOLDER_COMMENT.test(comment.data)) {\n toRemove.push(comment);\n }\n }\n for (const comment of toRemove) {\n comment.remove();\n }\n }\n\n /**\n * SSR テキストバインディングコメントを復元する。\n * <!--@@wcs-text-start:path-->text<!--@@wcs-text-end:path-->\n * → <!--@@: path--> (バインディングシステムが認識する形式)\n */\n static restoreTextBindings(root: Node): void {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n const startComments: { comment: Comment, path: string }[] = [];\n\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n const match = SSR_TEXT_START.exec(comment.data);\n if (match) {\n startComments.push({ comment, path: match[1] });\n }\n }\n\n for (const { comment, path } of startComments) {\n const bindComment = document.createComment(`@@: ${path}`);\n comment.parentNode!.insertBefore(bindComment, comment);\n\n let sibling: Node | null = comment.nextSibling;\n comment.remove();\n\n const endPattern = `@@wcs-text-end:${path}`;\n while (sibling) {\n const next: Node | null = sibling.nextSibling;\n if (sibling.nodeType === Node.COMMENT_NODE && (sibling as Comment).data === endPattern) {\n sibling.parentNode!.removeChild(sibling);\n break;\n }\n sibling.parentNode!.removeChild(sibling);\n sibling = next;\n }\n }\n }\n\n /**\n * SSR DOM をクリーンアップし、buildBindings が動作できる状態に戻す。\n * バージョン不一致時のフォールバック用。\n *\n * 1. SSR ブロック境界コメント間のレンダリング済みノードを除去\n * 2. SSR テキストバインディングを @@: 形式に復元\n * 3. プレースホルダーコメントを <wcs-ssr> 内のテンプレートで差し替え\n * 4. data-wcs-ssr-id 属性を除去\n * 5. <wcs-ssr> を除去\n */\n static cleanupDom(root: Document): void {\n const body = document.body;\n\n // <wcs-ssr> からテンプレート UUID マップを構築(カスタム要素未定義でも動作するよう DOM 直接走査)\n const ssrElements = root.querySelectorAll(config.tagNames.ssr);\n const templateByUuid = new Map<string, HTMLTemplateElement>();\n for (const ssrNode of ssrElements) {\n const templates = ssrNode.querySelectorAll<HTMLTemplateElement>('template[id]');\n for (const tpl of templates) {\n const id = tpl.getAttribute('id');\n if (id) {\n templateByUuid.set(id, tpl);\n }\n }\n }\n\n // SSR ブロック境界コメント間のレンダリング済みノードと境界コメントを除去\n const walker1 = document.createTreeWalker(body, NodeFilter.SHOW_COMMENT);\n const startComments: Comment[] = [];\n while (walker1.nextNode()) {\n const comment = walker1.currentNode as Comment;\n if (SSR_BLOCK_START.test(comment.data)) {\n startComments.push(comment);\n }\n }\n for (const startComment of startComments) {\n const match = SSR_BLOCK_START.exec(startComment.data)!;\n const type = match[1];\n const info = match[2];\n const endPattern = `@@wcs-${type}-end:${info}`;\n let sibling = startComment.nextSibling;\n while (sibling) {\n const next = sibling.nextSibling;\n if (sibling.nodeType === Node.COMMENT_NODE && (sibling as Comment).data === endPattern) {\n sibling.remove();\n break;\n }\n sibling.remove();\n sibling = next;\n }\n startComment.remove();\n }\n\n // SSR テキストバインディングを @@: 形式に復元\n Ssr.restoreTextBindings(body);\n\n // プレースホルダーコメント (@@wcs-for:uuid 等) をテンプレートに差し替え\n const walker2 = document.createTreeWalker(body, NodeFilter.SHOW_COMMENT);\n const placeholders: { comment: Comment, uuid: string }[] = [];\n while (walker2.nextNode()) {\n const comment = walker2.currentNode as Comment;\n if (SSR_PLACEHOLDER_COMMENT.test(comment.data)) {\n const uuid = comment.data.split(':')[1];\n placeholders.push({ comment, uuid });\n }\n }\n for (const { comment, uuid } of placeholders) {\n const tpl = templateByUuid.get(uuid);\n if (tpl) {\n const restored = document.createElement('template') as HTMLTemplateElement;\n const bindAttr = tpl.getAttribute(config.bindAttributeName);\n if (bindAttr) restored.setAttribute(config.bindAttributeName, bindAttr);\n const imported = document.importNode(tpl.content, true);\n if (imported.childNodes.length > 0) {\n restored.content.appendChild(imported);\n } else {\n for (const child of Array.from(tpl.childNodes)) {\n restored.content.appendChild(document.importNode(child, true));\n }\n }\n comment.parentNode!.replaceChild(restored, comment);\n }\n }\n\n // data-wcs-ssr-id 属性を除去\n const ssrIdElements = root.querySelectorAll('[data-wcs-ssr-id]');\n for (const el of ssrIdElements) {\n el.removeAttribute('data-wcs-ssr-id');\n }\n\n // <wcs-ssr> を除去\n for (const el of ssrElements) {\n el.remove();\n }\n }\n}\n","import { config } from \"../config\";\nimport { Ssr } from \"./Ssr\";\nimport { VERSION } from \"../version\";\nimport { IWcsSsrSnapshotBuilder, SSR_SNAPSHOT_BUILDER_KEY } from \"../protocol/ssrSnapshot\";\n\n/**\n * ssr-snapshot プロトコルの提供側(docs/ssr-router-design.md §5)。\n *\n * `<wcs-ssr>` スナップショットを document 全体に対する最終パスとして生成する。\n * connectedCallback 内の inline 生成は「その時点の DOM」しか見えず、router が\n * 後から挿入するルート内容の構造テンプレートを取り逃がすレースがあった\n * (state のロード方式と文書順に依存)。renderToString が全要素の完了と\n * バインディング構築の後にこれを呼ぶことで、スナップショットは常に確定後の\n * DOM を見る。\n *\n * 複数 `enable-ssr` state の意味論は inline 生成と同一に保つ(文書順に生成・\n * fragment レジストリはモジュール共有・props store は生成ごとにクリア)。\n * その整理は本プロトコルの範囲外の既存挙動として引き継ぐ。\n */\nexport function buildSsrDocument(root: Document): void {\n const stateTag = config.tagNames.state;\n const ssrTag = config.tagNames.ssr;\n // スナップショットはルートツリーに 1 本(D14): ボリューム(mount=)と bind-component は\n // 独立ツリー(__state)を持たないため、含めると空の <wcs-ssr> を生成してしまう。\n // Ssr.find は文書先頭一致なので、ルートより前の空スナップショットをルートが掴み、\n // ハイドレーション全体が無言で CSR 退化する\n const stateElements = root.querySelectorAll(`${stateTag}[enable-ssr]:not([mount]):not([bind-component])`);\n for (const stateEl of stateElements) {\n // 既に直前へ生成済み(旧 server との組み合わせで inline 生成された等)なら\n // 何もしない — build() は冪等でなければならない(プロトコル契約)\n const prev = stateEl.previousElementSibling;\n if (prev !== null && prev.tagName.toLowerCase() === ssrTag) {\n continue;\n }\n const ssrEl = document.createElement(ssrTag);\n ssrEl.setAttribute(\"version\", VERSION);\n Ssr.buildContent(ssrEl, Ssr.extractStateData(stateEl));\n stateEl.parentNode?.insertBefore(ssrEl, stateEl);\n }\n}\n\nconst builder: IWcsSsrSnapshotBuilder = {\n protocol: \"wcs-ssr-snapshot\",\n version: 1,\n build: buildSsrDocument,\n};\n\n/**\n * グローバル symbol へ自分を載せる。`bootstrapState` から呼ぶ。\n * binder(registerBinder)と同じ規範 — 既に別のコピーが載っているなら譲る\n * (そのコピーのレジストリが、そのページの正本だからである)。\n */\nexport function registerSsrSnapshotBuilder(): void {\n const globals = globalThis as Record<symbol, unknown>;\n if (globals[SSR_SNAPSHOT_BUILDER_KEY] === undefined) {\n globals[SSR_SNAPSHOT_BUILDER_KEY] = builder;\n }\n}\n\n/** テスト用: 登録を外す */\nexport function _unregisterSsrSnapshotBuilder(): void {\n const globals = globalThis as Record<symbol, unknown>;\n if (globals[SSR_SNAPSHOT_BUILDER_KEY] === builder) {\n delete globals[SSR_SNAPSHOT_BUILDER_KEY];\n }\n}\n","import { getAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding\";\nimport { setLastListValueByAbsoluteStateAddress } from \"../list/lastListValueByAbsoluteStateAddress\";\nimport { setStateListBaseline } from \"../list/stateListBaseline\";\nimport { parseBindTextsForElement } from \"../bindTextParser/parseBindTextsForElement\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { BindingSession, getOrCreateBindingSession } from \"../bindings/BindingSession\";\nimport { collectNodesAndBindingInfos } from \"../bindings/collectNodesAndBindingInfos\";\nimport { setBindingsByContent } from \"../bindings/bindingsByContent\";\nimport { setBindingSessionByContent } from \"../bindings/bindingSessionByContent\";\nimport { setIndexBindingsByContent } from \"../bindings/indexBindingsByContent\";\nimport { setNodesByContent } from \"../bindings/nodesByContent\";\nimport { bindLoopContextToContent } from \"../bindings/bindLoopContextToContent\";\nimport { config } from \"../config\";\nimport { WILDCARD, INDEX_BY_INDEX_NAME } from \"../define\";\nimport { Ssr, SSR_BLOCK_START } from \"./Ssr\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { setLoopContextByNode } from \"../list/loopContextByNode\";\nimport { applyChangeFromBindings } from \"../apply/applyChangeFromBindings\";\nimport { hydrateSetContent, hydrateSetLastNode } from \"../apply/applyChangeToFor\";\nimport { waitForStateInitialize } from \"../waitForStateInitialize\";\nimport { setFragmentInfoByUUID, getFragmentInfoByUUID } from \"../structural/fragmentInfoByUUID\";\nimport { setContentByNode } from \"../structural/contentsByNode\";\nimport { createContentFromNodes } from \"../structural/createContent\";\nimport { collectStructuralFragments } from \"../structural/collectStructuralFragments\";\nimport { createNotFilter } from \"../structural/createNotFilter\";\nimport { getFragmentNodeInfos } from \"../structural/getFragmentNodeInfos\";\nimport { optimizeFragment } from \"../structural/optimizeFragment\";\nimport { expandShorthandPaths } from \"../structural/expandShorthandPaths\";\nimport { createListIndex } from \"../list/createListIndex\";\nimport { IListIndex } from \"../list/types\";\nimport { setListIndexesByList } from \"../list/listIndexesByList\";\nimport { getPathInfo } from \"../address/PathInfo\";\nimport { createStateAddress } from \"../address/StateAddress\";\nimport { IBindingInfo } from \"../types\";\nimport { VERSION } from \"../version\";\n\n// ハイドレーション時にスキップするバインディングタイプ\nconst STRUCTURAL_TYPES = new Set(['for', 'if', 'elseif', 'else']);\n\n\ninterface ISsrBlock {\n type: string; // for, if, elseif, else\n uuid: string;\n path: string;\n index: number | null; // for のみ\n nodes: Node[]; // start〜end 間のノード\n}\n\n/**\n * SSR ブロック境界コメントを走査して、start〜end 間のノードを収集する\n */\nfunction collectSsrBlocks(root: Node): ISsrBlock[] {\n const blocks: ISsrBlock[] = [];\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n const startComments: Comment[] = [];\n\n // まず全コメントを収集\n while (walker.nextNode()) {\n startComments.push(walker.currentNode as Comment);\n }\n\n for (const comment of startComments) {\n const startMatch = SSR_BLOCK_START.exec(comment.data);\n if (!startMatch) continue;\n\n const type = startMatch[1];\n const info = startMatch[2]; // \"uuid:path:index\" or \"uuid:path\"\n const parts = info.split(':');\n\n let uuid: string;\n let path: string;\n let index: number | null = null;\n\n if (type === 'for') {\n // uuid:path:index\n uuid = parts[0];\n path = parts[1];\n index = parseInt(parts[2], 10);\n } else {\n // uuid:path\n uuid = parts[0];\n path = parts.slice(1).join(':');\n }\n\n // start と end の間のノードを収集\n const nodes: Node[] = [];\n let sibling = comment.nextSibling;\n const endPattern = `@@wcs-${type}-end:${info}`;\n while (sibling) {\n if (sibling.nodeType === Node.COMMENT_NODE && (sibling as Comment).data === endPattern) {\n break;\n }\n nodes.push(sibling);\n sibling = sibling.nextSibling;\n }\n\n blocks.push({ type, uuid, path, index, nodes });\n }\n\n return blocks;\n}\n\n/**\n * live DOM ノード群からバインディングを収集する。\n * ノードを一時的に DocumentFragment に移動して collectNodesAndBindingInfos を実行し、\n * 元の位置に戻す。\n */\nfunction collectBindingsFromLiveNodes(\n nodes: Node[],\n): { bindingInfos: IBindingInfo[], subscriberNodes: Node[], bindingSession: BindingSession } {\n const bindingSession = new BindingSession();\n if (nodes.length === 0) {\n return { bindingInfos: [], subscriberNodes: [], bindingSession };\n }\n\n // ノードの元の位置を記録\n const parent = nodes[0].parentNode;\n const nextSibling = nodes[nodes.length - 1].nextSibling;\n\n // 一時的に wrapper 要素に移動(collectNodesAndBindingInfos は Element を受け付ける)\n const wrapper = document.createElement('div');\n for (const node of nodes) {\n wrapper.appendChild(node);\n }\n\n // バインディング収集\n const [subscriberNodes, allBindings] = collectNodesAndBindingInfos(wrapper);\n\n const bindingInfos = bindingSession.initialize(allBindings, {\n registerAddress: false,\n applyOnReconnect: false,\n });\n\n // 元の位置に戻す\n if (parent) {\n while (wrapper.firstChild) {\n parent.insertBefore(wrapper.firstChild, nextSibling);\n }\n }\n\n return {\n bindingInfos,\n subscriberNodes,\n bindingSession,\n };\n}\n\n/**\n * ブロックの中で初回値を適用するバインディングを集める(#258 X6 — hydrateBindings の注記)。\n *\n * 除くもの:\n * - 構造バインディング(SSR が描画済み)とイベント。\n * - コメントに乗ったバインディング。ブロックを集める時点のコメントのバインディングは構造の置き場\n * (`<!--@@wcs-for:uuid-->`)だけで、テキストの `@@:` はこの後で `Ssr.restoreTextBindings` が戻す。\n * テンプレートを復帰できなかった入れ子の置き場は text として解釈される(`text: uuid`)ので、\n * 構造の種別だけでは除けない。\n * - 添字のバインディング(`$1` / `$2` …)。state に依存しないので依存辺のための適用が要らず、SSR が\n * 描いた添字のままでよい(入れ子の内側の `$2` は、外側のループ文脈しか持たないので読めもしない)。\n * - ループの深さより多いワイルドカードを持つバインディング。入れ子のブロックの行は外側のブロックの\n * Content に吸収され、外側のループ文脈しか持たない(入れ子ハイドレーションの既知の制限・\n * integration.listLedgerParentKey.test.ts)。\n * コメントと段数の足りないバインディングは、適用しても失敗の報告をハイドレーションのたびに増やすだけになる。\n */\nfunction collectBlockBindings(out: IBindingInfo[], bindings: readonly IBindingInfo[], loopDepth: number): void {\n for (const binding of bindings) {\n if (binding.bindingType === \"event\" || STRUCTURAL_TYPES.has(binding.bindingType)) {\n continue;\n }\n if (binding.node.nodeType === Node.COMMENT_NODE || binding.statePathName in INDEX_BY_INDEX_NAME) {\n continue;\n }\n if (getPathInfo(binding.statePathName).wildcardCount > loopDepth) {\n continue;\n }\n out.push(binding);\n }\n}\n\n/**\n * SSR ブロックの DOM ノードを Content 化し、バインディングを登録する。\n * 戻り値はブロックの中で初回値を適用するバインディング(`collectBlockBindings`)。\n */\nfunction hydrateBlocks(root: Node, blocks: ISsrBlock[]): IBindingInfo[] {\n // for ブロックの listIndex を UUID ごとに収集\n const listIndexesByUuid: Map<string, IListIndex[]> = new Map();\n const blockBindings: IBindingInfo[] = [];\n\n for (const block of blocks) {\n if (block.nodes.length === 0) continue;\n\n const content = createContentFromNodes(block.nodes);\n\n // Content のバインディングを収集\n const { bindingInfos, subscriberNodes, bindingSession } = collectBindingsFromLiveNodes(block.nodes);\n setBindingSessionByContent(content, bindingSession);\n\n // Content 内のノードに data-wcs-completed を付与\n // (メインの collectNodesAndBindingInfos で重複登録されないようにする)\n for (const node of subscriberNodes) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n (node as Element).setAttribute('data-wcs-completed', '');\n }\n }\n setBindingsByContent(content, bindingInfos);\n setNodesByContent(content, subscriberNodes);\n\n const indexBindings: IBindingInfo[] = [];\n for (const binding of bindingInfos) {\n if (binding.statePathName in INDEX_BY_INDEX_NAME) {\n indexBindings.push(binding);\n }\n }\n setIndexBindingsByContent(content, indexBindings);\n\n if (block.type === 'for' && block.index !== null) {\n const placeholderComment = findPlaceholderComment(root, 'for', block.uuid);\n if (placeholderComment) {\n const listIndex = createListIndex(null, block.index);\n hydrateSetContent(placeholderComment, listIndex, content);\n const lastNode = block.nodes[block.nodes.length - 1];\n hydrateSetLastNode(placeholderComment, lastNode);\n setContentByNode(placeholderComment, content);\n\n // ループコンテキストをバインドし、バインディングをアドレスに登録\n const pathInfo = getPathInfo(block.path + '.' + WILDCARD);\n const stateAddress = createStateAddress(pathInfo, listIndex);\n // ILoopContext は IStateAddress + listIndex なので、stateAddress をそのまま使う\n bindLoopContextToContent(content, stateAddress as any);\n\n bindingSession.initialize(bindingInfos, {\n registerAddress: true,\n registerPathInfo: false,\n applyOnReconnect: false,\n });\n collectBlockBindings(blockBindings, bindingInfos, pathInfo.wildcardCount);\n\n // listIndex を UUID ごとに収集(後で setListIndexesByList に渡す)\n let indexes = listIndexesByUuid.get(block.uuid);\n if (!indexes) {\n indexes = [];\n listIndexesByUuid.set(block.uuid, indexes);\n }\n indexes.push(listIndex);\n }\n } else {\n const placeholderComment = findPlaceholderComment(root, block.type, block.uuid);\n if (placeholderComment) {\n setContentByNode(placeholderComment, content);\n\n bindingSession.initialize(bindingInfos, {\n registerAddress: true,\n registerPathInfo: false,\n applyOnReconnect: false,\n });\n // if / elseif / else の中身はループの外(入れ子の行はここに吸収されても段数で除かれる)\n collectBlockBindings(blockBindings, bindingInfos, 0);\n }\n }\n }\n\n // for ブロックの listIndex を state のリスト値に紐づける\n for (const [uuid, indexes] of listIndexesByUuid) {\n const placeholderComment = findPlaceholderComment(root, 'for', uuid);\n if (!placeholderComment) continue;\n // state から現在のリスト値を取得して listIndexes を設定\n const rootNode = placeholderComment.getRootNode() as Node;\n // structuralBindings はまだ登録前なので、getParseBindTextResults を直接使う\n const fragmentInfo = getFragmentInfoByUUID(uuid);\n if (!fragmentInfo) continue;\n const statePathName = fragmentInfo.parseBindTextResult.statePathName;\n const stateElement = getStateElement(rootNode);\n if (!stateElement) continue;\n stateElement.createState(\"readonly\", (state) => {\n const list = state[statePathName];\n if (Array.isArray(list)) {\n setListIndexesByList(list, indexes);\n }\n });\n }\n return blockBindings;\n}\n\nfunction findPlaceholderComment(root: Node, type: string, uuid: string): Comment | null {\n const keywordMap: Record<string, string> = {\n 'for': config.commentForPrefix,\n 'if': config.commentIfPrefix,\n 'elseif': config.commentElseIfPrefix,\n 'else': config.commentElsePrefix,\n };\n const keyword = keywordMap[type];\n if (!keyword) return null;\n\n const pattern = `@@${keyword}:${uuid}`;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n if (comment.data === pattern) {\n return comment;\n }\n }\n return null;\n}\n\n/**\n * <wcs-ssr> 内のテンプレートを fragmentInfoByUUID に復帰させる。\n */\nfunction restoreFragments(root: Document, ssrEl: Ssr): void {\n const rootNode = root as Node;\n let lastIfParseResult: ParseBindTextResult | null = null;\n\n for (const [uuid, tpl] of ssrEl.templates) {\n const bindText = tpl.getAttribute(config.bindAttributeName) || '';\n const parseBindTextResults = parseBindTextsForElement(bindText);\n let parseBindTextResult = parseBindTextResults[0];\n const bindingType = parseBindTextResult.bindingType;\n\n // else: 直前の if 条件の not → 条件反転(elseif は独自条件のままでよい)\n if (bindingType === 'else' && lastIfParseResult) {\n parseBindTextResult = {\n ...lastIfParseResult,\n outFilters: [...lastIfParseResult.outFilters, createNotFilter()],\n bindingType: 'else',\n };\n }\n\n // if chain の追跡\n if (bindingType === 'if') {\n lastIfParseResult = parseBindTextResult;\n } else if (bindingType === 'elseif') {\n lastIfParseResult = parseBindTextResult;\n } else if (bindingType === 'else') {\n lastIfParseResult = null;\n }\n\n const fragment = document.importNode(tpl.content, true);\n const forPath = bindingType === \"for\" ? parseBindTextResult.statePathName : undefined;\n optimizeFragment(fragment);\n if (typeof forPath === \"string\") {\n expandShorthandPaths(fragment, forPath);\n }\n collectStructuralFragments(rootNode, fragment, forPath);\n\n const fragmentInfo = {\n fragment,\n parseBindTextResult,\n nodeInfos: getFragmentNodeInfos(fragment),\n };\n setFragmentInfoByUUID(uuid, rootNode, fragmentInfo);\n }\n}\n\n/**\n * SSR ハイドレーション用バインディング初期化。\n * バージョン不一致時は DOM をクリーンアップして false を返す\n * (呼び出し元で buildBindings にフォールバック)。\n */\nexport async function hydrateBindings(root: Document): Promise<boolean> {\n await waitForStateInitialize(root);\n\n // バージョン検証\n const ssrElements = root.querySelectorAll(config.tagNames.ssr);\n for (const ssrNode of ssrElements) {\n const ssrEl = ssrNode as Ssr;\n if (!ssrEl.verifyVersion()) {\n console.warn(\n `[@wcstack/state] SSR version mismatch: server=\"${ssrEl.version}\", client=\"${VERSION}\". Falling back to full render.`\n );\n Ssr.cleanupDom(root);\n return false;\n }\n }\n\n // <wcs-ssr> からテンプレートを fragmentInfoByUUID に復帰\n for (const ssrNode of ssrElements) {\n restoreFragments(root, ssrNode as Ssr);\n }\n\n // SSR ブロック境界コメントから既存 DOM を Content 化\n const blocks = collectSsrBlocks(document.body);\n const blockBindings = hydrateBlocks(document.body, blocks);\n\n // ブロック境界コメント (start/end) を除去\n Ssr.removeBlockBoundaryComments(document.body);\n\n // <wcs-ssr> を一時除去(バインディング走査に含めない)\n const ssrParents: { el: Element, parent: Node, next: Node | null }[] = [];\n for (const el of ssrElements) {\n if (el.parentNode) {\n ssrParents.push({ el, parent: el.parentNode, next: el.nextSibling });\n el.remove();\n }\n }\n\n // 構造プレースホルダーコメント (@@wcs-for:uuid 等) は残す\n // → バインディング走査で拾われ、状態変化時の再レンダリングに使われる\n\n // SSR テキストバインディングを @@: 形式に復元\n Ssr.restoreTextBindings(document.body);\n\n // ノードとバインディングを収集\n const [subscriberNodes, allBindings] = collectNodesAndBindingInfos(document.body);\n\n // 収集完了したノードに data-wcs-completed 属性を付与\n // for ブロック内ノード(hydrateBlocks で登録済み)にはループコンテキストをリセットしない\n for (const node of subscriberNodes) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n if (!el.hasAttribute('data-wcs-completed')) {\n setLoopContextByNode(node, null);\n el.setAttribute('data-wcs-completed', '');\n }\n } else {\n // コメントノード等\n setLoopContextByNode(node, null);\n }\n }\n\n // バインディングを構造系とそれ以外に分離\n const normalBindings: IBindingInfo[] = [];\n const structuralBindings: IBindingInfo[] = [];\n const bindingSession = getOrCreateBindingSession(document.body);\n const initializedBindings = bindingSession.initialize(allBindings);\n\n for (const binding of initializedBindings) {\n if (binding.bindingType === \"event\") continue;\n if (STRUCTURAL_TYPES.has(binding.bindingType)) {\n structuralBindings.push(binding);\n } else if (binding.statePathName.includes(WILDCARD)) {\n // for ブロック内のバインディング → Content のバインディングとして登録済み\n continue;\n } else {\n normalBindings.push(binding);\n }\n }\n\n // for バインディングの lastListValue を初期値として設定\n // (次回の状態変化時に差分計算の基準になる)\n for (const binding of structuralBindings) {\n if (binding.bindingType === 'for') {\n const absAddr = getAbsoluteStateAddressByBinding(binding);\n const rootNode = binding.replaceNode.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement) {\n stateElement.createState(\"readonly\", (state) => {\n const value = state[binding.statePathName];\n if (Array.isArray(value)) {\n setLastListValueByAbsoluteStateAddress(absAddr, value);\n // 描画の基準と同時に state 側の基準も進める(E1。applyChangeFromBindings と対称)\n setStateListBaseline(absAddr, value);\n }\n });\n }\n }\n }\n\n // 初回値の適用(構造バインディングは SSR 描画済みなので除く)。SSR ブロック(for の行・if の中身)の\n // 中のバインディングも適用する(#258 X6): getter の依存辺は getter を評価したときにしか張られない\n // ので、適用しないと行の `items.*.double` は `items.*.n` を書いても一度も再評価されず、サーバーが\n // 書いたテキストのまま固まる。値は SSR と同じ state から読むのでテキストは変わらない\n applyChangeFromBindings([...normalBindings, ...blockBindings]);\n\n // <wcs-ssr> を元に戻す\n for (const { el, parent, next } of ssrParents) {\n parent.insertBefore(el, next);\n }\n\n // hydrateProps 復元\n const restoredSsrElements = root.querySelectorAll(config.tagNames.ssr);\n for (const ssrNode of restoredSsrElements) {\n const ssrEl = ssrNode as Ssr;\n const props = ssrEl.hydrateProps;\n for (const [id, propMap] of Object.entries(props)) {\n const target = root.querySelector(`[data-wcs-ssr-id=\"${id}\"]`);\n if (!target) continue;\n for (const [propName, value] of Object.entries(propMap)) {\n (target as any)[propName] = value;\n }\n }\n }\n\n // ハイドレーション中の重複登録防止用属性を除去\n const completedEls = root.querySelectorAll('[data-wcs-completed]');\n for (const el of completedEls) {\n el.removeAttribute('data-wcs-completed');\n }\n\n return true;\n}\n\n/** @internal テスト用 */\nexport const __test = {\n collectSsrBlocks,\n collectBindingsFromLiveNodes,\n hydrateBlocks,\n findPlaceholderComment,\n restoreFragments,\n};\n","/**\n * ssr/install.ts — SSR 機能の install(設計案 H8、S5)。core の受け口(core/ssrHooks.ts と\n * registerComponents の definer)へこの機能の実装を置き、ssr-snapshot プロトコルを提供する。\n * 従来 `State` と `stateElementByName` と `registerComponents` に直書きされていた分岐で、\n * 理由のコメントは元の位置から移してある。\n */\nimport { config } from \"../config\";\nimport type { IStateElement } from \"../components/types\";\nimport { ISsrHooks, setSsrHooks } from \"../core/ssrHooks\";\nimport { registerComponentDefiner } from \"../registerComponents\";\nimport { getBindingsReady } from \"../stateElementByName\";\nimport { VERSION } from \"../version\";\nimport { registerSsrSnapshotBuilder } from \"./buildSsrDocument\";\nimport { hydrateBindings } from \"./hydrateBindings\";\nimport { Ssr } from \"./Ssr\";\n\nexport const ssrFeatureHooks: ISsrHooks = {\n hydrate: hydrateBindings,\n loadState(element) {\n const root = element.parentNode;\n if (!root) return null;\n const ssrEl = Ssr.find(root);\n if (!ssrEl) return null;\n const data = ssrEl.stateData;\n return Object.keys(data).length > 0 ? data : null;\n },\n async emitSnapshot(element) {\n await getBindingsReady((element as unknown as IStateElement).rootNode);\n const stateData = Ssr.extractStateData(element);\n const ssrEl = document.createElement(config.tagNames.ssr);\n ssrEl.setAttribute(\"version\", VERSION);\n Ssr.buildContent(ssrEl, stateData);\n element.parentNode?.insertBefore(ssrEl, element);\n },\n};\n\nlet installed = false;\n/** 冪等。full / auto では `bootstrapState()` が呼ぶ */\nexport function installSsr(): void {\n if (installed) return;\n installed = true;\n setSsrHooks(ssrFeatureHooks);\n registerComponentDefiner((registry) => {\n if (!registry.get(config.tagNames.ssr)) {\n registry.define(config.tagNames.ssr, Ssr);\n }\n });\n // ssr-snapshot プロトコルの提供(docs/ssr-router-design.md §5)。renderToString が\n // `<wcs-ssr>` 生成をサーバー主導の最終パスへ回せるようにする。登録は冪等\n registerSsrSnapshotBuilder();\n}\n","/**\n * features/ssr.ts — サーバー描画とハイドレーション(@wcstack/state/features/ssr)。\n */\nimport type { IStateFeature } from \"../core/features\";\nimport { installSsr } from \"../ssr/install\";\n\nexport const ssr: IStateFeature = {\n name: \"ssr\",\n install(): void {\n installSsr();\n },\n};\nexport default ssr;\n"],"names":["SSR_PLACEHOLDER_COMMENT","SSR_BLOCK_START","SSR_BLOCK_END","SSR_TEXT_START","escapeJsonForScript","json","replace","Ssr","HTMLElementBase","_stateData","_templates","_hydrateProps","version","this","getAttribute","stateData","_loadStateData","templates","_loadTemplates","hydrateProps","_loadHydrateProps","getTemplate","uuid","get","verifyVersion","serverVersion","serverParts","split","clientParts","VERSION","setStateData","data","setHydrateProps","props","script","querySelector","JSON","parse","textContent","map","Map","querySelectorAll","tpl","id","set","find","root","tagName","config","tagNames","ssr","parentEl","Element","Document","documentElement","extractStateData","stateEl","raw","__state","key","Object","keys","startsWith","descriptor","getOwnPropertyDescriptor","undefined","value","buildContent","ssrEl","jsonScript","document","createElement","setAttribute","stringify","appendChild","uuids","getAllFragmentUUIDs","fragmentInfo","getFragmentInfoByUUID","bindResult","parseBindTextResult","bindText","bindingType","statePathName","bindAttributeName","content","fragment","cloneNode","ssrNodes","getAllSsrPropertyNodes","length","propsData","i","node","entries","getSsrProperties","entry","propName","propsScript","clearSsrPropertyStore","removeBlockBoundaryComments","walker","createTreeWalker","NodeFilter","SHOW_COMMENT","toRemove","nextNode","comment","currentNode","test","push","remove","removeStructuralComments","restoreTextBindings","startComments","match","exec","path","bindComment","createComment","parentNode","insertBefore","sibling","nextSibling","endPattern","next","nodeType","Node","COMMENT_NODE","removeChild","cleanupDom","body","ssrElements","templateByUuid","ssrNode","walker1","startComment","walker2","placeholders","restored","bindAttr","imported","importNode","childNodes","child","Array","from","replaceChild","ssrIdElements","el","removeAttribute","builder","protocol","build","stateTag","state","ssrTag","stateElements","prev","previousElementSibling","toLowerCase","STRUCTURAL_TYPES","Set","collectBindingsFromLiveNodes","nodes","bindingSession","BindingSession","bindingInfos","subscriberNodes","parent","wrapper","allBindings","collectNodesAndBindingInfos","initialize","registerAddress","applyOnReconnect","firstChild","collectBlockBindings","out","bindings","loopDepth","binding","has","INDEX_BY_INDEX_NAME","getPathInfo","wildcardCount","findPlaceholderComment","type","keyword","for","commentForPrefix","if","commentIfPrefix","elseif","commentElseIfPrefix","else","commentElsePrefix","pattern","restoreFragments","rootNode","lastIfParseResult","parseBindTextsForElement","outFilters","createNotFilter","forPath","optimizeFragment","expandShorthandPaths","collectStructuralFragments","nodeInfos","getFragmentNodeInfos","setFragmentInfoByUUID","ssrFeatureHooks","hydrate","async","waitForStateInitialize","console","warn","blocks","startMatch","info","parts","index","parseInt","slice","join","collectSsrBlocks","blockBindings","listIndexesByUuid","block","createContentFromNodes","setBindingSessionByContent","ELEMENT_NODE","setBindingsByContent","setNodesByContent","indexBindings","setIndexBindingsByContent","placeholderComment","listIndex","createListIndex","hydrateSetContent","lastNode","hydrateSetLastNode","setContentByNode","pathInfo","WILDCARD","stateAddress","createStateAddress","bindLoopContextToContent","registerPathInfo","indexes","getRootNode","stateElement","getStateElement","createState","list","isArray","setListIndexesByList","hydrateBlocks","ssrParents","hasAttribute","setLoopContextByNode","normalBindings","structuralBindings","initializedBindings","getOrCreateBindingSession","includes","absAddr","getAbsoluteStateAddressByBinding","replaceNode","setLastListValueByAbsoluteStateAddress","setStateListBaseline","applyChangeFromBindings","restoredSsrElements","propMap","target","completedEls","loadState","element","emitSnapshot","getBindingsReady","installed","installSsr","setSsrHooks","registerComponentDefiner","registry","define","globals","globalThis","SSR_SNAPSHOT_BUILDER_KEY","registerSsrSnapshotBuilder","name","install"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ssr.js","sources":["../../../../../src/ssr/Ssr.ts","../../../../../src/ssr/buildSsrDocument.ts","../../../../../src/ssr/hydrateBindings.ts","../../../../../src/ssr/install.ts","../../../../../src/features/ssr.ts"],"sourcesContent":["import { config } from \"../config\";\nimport { IState } from \"../types\";\nimport { VERSION } from \"../version\";\nimport { getAllFragmentUUIDs, getFragmentInfoByUUID } from \"../structural/fragmentInfoByUUID\";\nimport { getAllSsrPropertyNodes, getSsrProperties, clearSsrPropertyStore } from \"../apply/ssrPropertyStore\";\nimport { HTMLElementBase } from \"../platform/HTMLElementBase\";\n\nexport interface ISsrElement {\n readonly version: string;\n readonly stateData: IState;\n readonly templates: Map<string, HTMLTemplateElement>;\n readonly hydrateProps: Record<string, Record<string, unknown>>;\n getTemplate(uuid: string): HTMLTemplateElement | null;\n verifyVersion(): boolean;\n}\n\n// SSR コメントパターン\nconst SSR_PLACEHOLDER_COMMENT = /^@@wcs-(?:for|if|elseif|else):[^-]/;\nconst SSR_BLOCK_START = /^@@wcs-(for|if|elseif|else)-start:(.+)$/;\nconst SSR_BLOCK_END = /^@@wcs-(for|if|elseif|else)-end:(.+)$/;\nconst SSR_TEXT_START = /^@@wcs-text-start:(.+)$/;\n\nexport {\n SSR_PLACEHOLDER_COMMENT,\n SSR_BLOCK_START,\n SSR_BLOCK_END,\n SSR_TEXT_START,\n};\n\n/**\n * script 要素へ埋め込む JSON を HTML パーサから保護する。\n * HTML 直列化時、script の中身は生のまま出力されるため、state 値に\n * \"</script>\" や \"<!--\" を含む文字列があると script を脱出できてしまう。\n * \"<\" \">\" \"&\" と U+2028/U+2029 を JSON の \\uXXXX エスケープへ置換する\n * (JSON.parse では元の文字列と等価に復元される)。\n */\nfunction escapeJsonForScript(json: string): string {\n return json\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\nexport class Ssr extends HTMLElementBase implements ISsrElement {\n private _stateData: IState | null = null;\n private _templates: Map<string, HTMLTemplateElement> | null = null;\n private _hydrateProps: Record<string, Record<string, unknown>> | null = null;\n\n get version(): string {\n return this.getAttribute('version') || '';\n }\n\n get stateData(): IState {\n if (this._stateData === null) {\n this._stateData = this._loadStateData();\n }\n return this._stateData;\n }\n\n get templates(): Map<string, HTMLTemplateElement> {\n if (this._templates === null) {\n this._templates = this._loadTemplates();\n }\n return this._templates;\n }\n\n get hydrateProps(): Record<string, Record<string, unknown>> {\n if (this._hydrateProps === null) {\n this._hydrateProps = this._loadHydrateProps();\n }\n return this._hydrateProps;\n }\n\n getTemplate(uuid: string): HTMLTemplateElement | null {\n return this.templates.get(uuid) ?? null;\n }\n\n /**\n * サーバーの SSR バージョンとクライアントの state バージョンを検証する。\n * メジャー・マイナーバージョンが一致すればtrue。\n * version 属性がない場合は検証スキップ(true)。\n */\n verifyVersion(): boolean {\n const serverVersion = this.version;\n if (!serverVersion) return true;\n const serverParts = serverVersion.split('.');\n const clientParts = VERSION.split('.');\n // メジャー・マイナーが一致すれば互換\n return serverParts[0] === clientParts[0] && serverParts[1] === clientParts[1];\n }\n\n setStateData(data: IState): void {\n this._stateData = data;\n }\n\n setHydrateProps(props: Record<string, Record<string, unknown>>): void {\n this._hydrateProps = props;\n }\n\n private _loadStateData(): IState {\n const script = this.querySelector(\n `script[type=\"application/json\"]:not([data-wcs-ssr-props])`\n );\n if (!script) return {};\n try {\n return JSON.parse(script.textContent || '{}');\n } catch {\n return {};\n }\n }\n\n private _loadTemplates(): Map<string, HTMLTemplateElement> {\n const map = new Map<string, HTMLTemplateElement>();\n const templates = this.querySelectorAll<HTMLTemplateElement>('template[id]');\n for (const tpl of templates) {\n const id = tpl.getAttribute('id');\n if (id) {\n map.set(id, tpl);\n }\n }\n return map;\n }\n\n private _loadHydrateProps(): Record<string, Record<string, unknown>> {\n const script = this.querySelector('script[data-wcs-ssr-props]');\n if (!script) return {};\n try {\n return JSON.parse(script.textContent || '{}');\n } catch {\n return {};\n }\n }\n\n static find(root: Node): ISsrElement | null {\n const tagName = config.tagNames.ssr;\n const parentEl = root instanceof Element\n ? root\n : root instanceof Document\n ? root.documentElement\n : null;\n if (!parentEl) return null;\n const el = parentEl.querySelector(tagName);\n return el as ISsrElement | null;\n }\n\n /**\n * stateData と構造テンプレート・プロパティから <wcs-ssr> の中身を構築する。\n * server パッケージの renderToString から呼ばれる。\n */\n /**\n * wcs-state 要素から $ プレフィックスや関数を除いたデータを抽出する。\n */\n static extractStateData(stateEl: Element): Record<string, any> {\n const raw = (stateEl as any).__state;\n if (!raw || typeof raw !== 'object') return {};\n const data: Record<string, any> = {};\n for (const key of Object.keys(raw)) {\n if (key.startsWith('$')) continue;\n // **アクセサは評価しない。** スナップショットが運ぶのはデータで、派生値は\n // クライアントが同じ宣言から作り直す。ここは Object.entries で舐めていたので、\n // own かつ enumerable な getter を**生の state オブジェクト**を this にして\n // 評価していた — proxy の上でしか意味を持たない本体(`this[\"items.*.n\"]` や\n // `this.$getAll(...)`)が、パス getter なら NaN → JSON の null で静かに壊れ、\n // `$getAll` を呼ぶ getter なら TypeError でページ全体の SSR を落としていた\n // (docs/state-recursive-path-impl-plan.md §7)。\n const descriptor = Object.getOwnPropertyDescriptor(raw, key);\n if (descriptor !== undefined && typeof descriptor.get === 'function') continue;\n const value = (raw as Record<string, unknown>)[key];\n if (typeof value !== 'function') {\n data[key] = value;\n }\n }\n return data;\n }\n\n static buildContent(ssrEl: Element, stateData: Record<string, any>): void {\n // 初期データ JSON\n const jsonScript = document.createElement('script');\n jsonScript.setAttribute('type', 'application/json');\n jsonScript.textContent = escapeJsonForScript(JSON.stringify(stateData));\n ssrEl.appendChild(jsonScript);\n\n // UUID で管理されているテンプレートを復元して格納\n const uuids = getAllFragmentUUIDs();\n for (const uuid of uuids) {\n const fragmentInfo = getFragmentInfoByUUID(uuid);\n if (!fragmentInfo) continue;\n\n const tpl = document.createElement('template');\n tpl.setAttribute('id', uuid);\n\n const bindResult = fragmentInfo.parseBindTextResult;\n const bindText = bindResult.bindingType === 'else'\n ? 'else:'\n : `${bindResult.bindingType}: ${bindResult.statePathName}`;\n tpl.setAttribute(config.bindAttributeName, bindText);\n\n const content = fragmentInfo.fragment.cloneNode(true) as DocumentFragment;\n tpl.content.appendChild(content);\n\n ssrEl.appendChild(tpl);\n }\n\n // 属性で代替不可なプロパティをハイドレーション用に格納\n const ssrNodes = getAllSsrPropertyNodes();\n if (ssrNodes.length > 0) {\n const propsData: Record<string, Record<string, unknown>> = {};\n for (let i = 0; i < ssrNodes.length; i++) {\n const node = ssrNodes[i];\n const entries = getSsrProperties(node);\n if (entries.length === 0) continue;\n const id = `wcs-ssr-${i}`;\n (node as Element).setAttribute('data-wcs-ssr-id', id);\n const props: Record<string, unknown> = {};\n for (const entry of entries) {\n props[entry.propName] = entry.value;\n }\n propsData[id] = props;\n }\n if (Object.keys(propsData).length > 0) {\n const propsScript = document.createElement('script');\n propsScript.setAttribute('type', 'application/json');\n propsScript.setAttribute('data-wcs-ssr-props', '');\n propsScript.textContent = escapeJsonForScript(JSON.stringify(propsData));\n ssrEl.appendChild(propsScript);\n }\n }\n\n clearSsrPropertyStore();\n }\n\n /**\n * SSR ブロック境界コメント (@@wcs-*-start/end) を除去する\n */\n static removeBlockBoundaryComments(root: Node): void {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n const toRemove: Comment[] = [];\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n if (SSR_BLOCK_START.test(comment.data) || SSR_BLOCK_END.test(comment.data)) {\n toRemove.push(comment);\n }\n }\n for (const comment of toRemove) {\n comment.remove();\n }\n }\n\n /**\n * SSR の構造プレースホルダーコメント (@@wcs-for:uuid 等) を除去する\n */\n static removeStructuralComments(root: Node): void {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n const toRemove: Comment[] = [];\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n if (SSR_PLACEHOLDER_COMMENT.test(comment.data)) {\n toRemove.push(comment);\n }\n }\n for (const comment of toRemove) {\n comment.remove();\n }\n }\n\n /**\n * SSR テキストバインディングコメントを復元する。\n * <!--@@wcs-text-start:path-->text<!--@@wcs-text-end:path-->\n * → <!--@@: path--> (バインディングシステムが認識する形式)\n */\n static restoreTextBindings(root: Node): void {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n const startComments: { comment: Comment, path: string }[] = [];\n\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n const match = SSR_TEXT_START.exec(comment.data);\n if (match) {\n startComments.push({ comment, path: match[1] });\n }\n }\n\n for (const { comment, path } of startComments) {\n const bindComment = document.createComment(`@@: ${path}`);\n comment.parentNode!.insertBefore(bindComment, comment);\n\n let sibling: Node | null = comment.nextSibling;\n comment.remove();\n\n const endPattern = `@@wcs-text-end:${path}`;\n while (sibling) {\n const next: Node | null = sibling.nextSibling;\n if (sibling.nodeType === Node.COMMENT_NODE && (sibling as Comment).data === endPattern) {\n sibling.parentNode!.removeChild(sibling);\n break;\n }\n sibling.parentNode!.removeChild(sibling);\n sibling = next;\n }\n }\n }\n\n /**\n * SSR DOM をクリーンアップし、buildBindings が動作できる状態に戻す。\n * バージョン不一致時のフォールバック用。\n *\n * 1. SSR ブロック境界コメント間のレンダリング済みノードを除去\n * 2. SSR テキストバインディングを @@: 形式に復元\n * 3. プレースホルダーコメントを <wcs-ssr> 内のテンプレートで差し替え\n * 4. data-wcs-ssr-id 属性を除去\n * 5. <wcs-ssr> を除去\n */\n static cleanupDom(root: Document): void {\n const body = document.body;\n\n // <wcs-ssr> からテンプレート UUID マップを構築(カスタム要素未定義でも動作するよう DOM 直接走査)\n const ssrElements = root.querySelectorAll(config.tagNames.ssr);\n const templateByUuid = new Map<string, HTMLTemplateElement>();\n for (const ssrNode of ssrElements) {\n const templates = ssrNode.querySelectorAll<HTMLTemplateElement>('template[id]');\n for (const tpl of templates) {\n const id = tpl.getAttribute('id');\n if (id) {\n templateByUuid.set(id, tpl);\n }\n }\n }\n\n // SSR ブロック境界コメント間のレンダリング済みノードと境界コメントを除去\n const walker1 = document.createTreeWalker(body, NodeFilter.SHOW_COMMENT);\n const startComments: Comment[] = [];\n while (walker1.nextNode()) {\n const comment = walker1.currentNode as Comment;\n if (SSR_BLOCK_START.test(comment.data)) {\n startComments.push(comment);\n }\n }\n for (const startComment of startComments) {\n const match = SSR_BLOCK_START.exec(startComment.data)!;\n const type = match[1];\n const info = match[2];\n const endPattern = `@@wcs-${type}-end:${info}`;\n let sibling = startComment.nextSibling;\n while (sibling) {\n const next = sibling.nextSibling;\n if (sibling.nodeType === Node.COMMENT_NODE && (sibling as Comment).data === endPattern) {\n sibling.remove();\n break;\n }\n sibling.remove();\n sibling = next;\n }\n startComment.remove();\n }\n\n // SSR テキストバインディングを @@: 形式に復元\n Ssr.restoreTextBindings(body);\n\n // プレースホルダーコメント (@@wcs-for:uuid 等) をテンプレートに差し替え\n const walker2 = document.createTreeWalker(body, NodeFilter.SHOW_COMMENT);\n const placeholders: { comment: Comment, uuid: string }[] = [];\n while (walker2.nextNode()) {\n const comment = walker2.currentNode as Comment;\n if (SSR_PLACEHOLDER_COMMENT.test(comment.data)) {\n const uuid = comment.data.split(':')[1];\n placeholders.push({ comment, uuid });\n }\n }\n for (const { comment, uuid } of placeholders) {\n const tpl = templateByUuid.get(uuid);\n if (tpl) {\n const restored = document.createElement('template') as HTMLTemplateElement;\n const bindAttr = tpl.getAttribute(config.bindAttributeName);\n if (bindAttr) restored.setAttribute(config.bindAttributeName, bindAttr);\n const imported = document.importNode(tpl.content, true);\n if (imported.childNodes.length > 0) {\n restored.content.appendChild(imported);\n } else {\n for (const child of Array.from(tpl.childNodes)) {\n restored.content.appendChild(document.importNode(child, true));\n }\n }\n comment.parentNode!.replaceChild(restored, comment);\n }\n }\n\n // data-wcs-ssr-id 属性を除去\n const ssrIdElements = root.querySelectorAll('[data-wcs-ssr-id]');\n for (const el of ssrIdElements) {\n el.removeAttribute('data-wcs-ssr-id');\n }\n\n // <wcs-ssr> を除去\n for (const el of ssrElements) {\n el.remove();\n }\n }\n}\n","import { config } from \"../config\";\nimport { Ssr } from \"./Ssr\";\nimport { VERSION } from \"../version\";\nimport { IWcsSsrSnapshotBuilder, SSR_SNAPSHOT_BUILDER_KEY } from \"../protocol/ssrSnapshot\";\n\n/**\n * ssr-snapshot プロトコルの提供側(docs/ssr-router-design.md §5)。\n *\n * `<wcs-ssr>` スナップショットを document 全体に対する最終パスとして生成する。\n * connectedCallback 内の inline 生成は「その時点の DOM」しか見えず、router が\n * 後から挿入するルート内容の構造テンプレートを取り逃がすレースがあった\n * (state のロード方式と文書順に依存)。renderToString が全要素の完了と\n * バインディング構築の後にこれを呼ぶことで、スナップショットは常に確定後の\n * DOM を見る。\n *\n * 複数 `enable-ssr` state の意味論は inline 生成と同一に保つ(文書順に生成・\n * fragment レジストリはモジュール共有・props store は生成ごとにクリア)。\n * その整理は本プロトコルの範囲外の既存挙動として引き継ぐ。\n */\nexport function buildSsrDocument(root: Document): void {\n const stateTag = config.tagNames.state;\n const ssrTag = config.tagNames.ssr;\n // スナップショットはルートツリーに 1 本(D14): ボリューム(mount=)と bind-component は\n // 独立ツリー(__state)を持たないため、含めると空の <wcs-ssr> を生成してしまう。\n // Ssr.find は文書先頭一致なので、ルートより前の空スナップショットをルートが掴み、\n // ハイドレーション全体が無言で CSR 退化する\n const stateElements = root.querySelectorAll(`${stateTag}[enable-ssr]:not([mount]):not([bind-component])`);\n for (const stateEl of stateElements) {\n // 既に直前へ生成済み(旧 server との組み合わせで inline 生成された等)なら\n // 何もしない — build() は冪等でなければならない(プロトコル契約)\n const prev = stateEl.previousElementSibling;\n if (prev !== null && prev.tagName.toLowerCase() === ssrTag) {\n continue;\n }\n const ssrEl = document.createElement(ssrTag);\n ssrEl.setAttribute(\"version\", VERSION);\n Ssr.buildContent(ssrEl, Ssr.extractStateData(stateEl));\n stateEl.parentNode?.insertBefore(ssrEl, stateEl);\n }\n}\n\nconst builder: IWcsSsrSnapshotBuilder = {\n protocol: \"wcs-ssr-snapshot\",\n version: 1,\n build: buildSsrDocument,\n};\n\n/**\n * グローバル symbol へ自分を載せる。`bootstrapState` から呼ぶ。\n * binder(registerBinder)と同じ規範 — 既に別のコピーが載っているなら譲る\n * (そのコピーのレジストリが、そのページの正本だからである)。\n */\nexport function registerSsrSnapshotBuilder(): void {\n const globals = globalThis as Record<symbol, unknown>;\n if (globals[SSR_SNAPSHOT_BUILDER_KEY] === undefined) {\n globals[SSR_SNAPSHOT_BUILDER_KEY] = builder;\n }\n}\n\n/** テスト用: 登録を外す */\nexport function _unregisterSsrSnapshotBuilder(): void {\n const globals = globalThis as Record<symbol, unknown>;\n if (globals[SSR_SNAPSHOT_BUILDER_KEY] === builder) {\n delete globals[SSR_SNAPSHOT_BUILDER_KEY];\n }\n}\n","import { getAbsoluteStateAddressByBinding } from \"../binding/getAbsoluteStateAddressByBinding\";\nimport { setLastListValueByAbsoluteStateAddress } from \"../list/lastListValueByAbsoluteStateAddress\";\nimport { setStateListBaseline } from \"../list/stateListBaseline\";\nimport { parseBindTextsForElement } from \"../bindTextParser/parseBindTextsForElement\";\nimport { ParseBindTextResult } from \"../bindTextParser/types\";\nimport { BindingSession, getOrCreateBindingSession } from \"../bindings/BindingSession\";\nimport { collectNodesAndBindingInfos } from \"../bindings/collectNodesAndBindingInfos\";\nimport { setBindingsByContent } from \"../bindings/bindingsByContent\";\nimport { setBindingSessionByContent } from \"../bindings/bindingSessionByContent\";\nimport { setIndexBindingsByContent } from \"../bindings/indexBindingsByContent\";\nimport { setNodesByContent } from \"../bindings/nodesByContent\";\nimport { bindLoopContextToContent } from \"../bindings/bindLoopContextToContent\";\nimport { config } from \"../config\";\nimport { WILDCARD, INDEX_BY_INDEX_NAME } from \"../define\";\nimport { Ssr, SSR_BLOCK_START } from \"./Ssr\";\nimport { getStateElement } from \"../stateElementByName\";\nimport { setLoopContextByNode } from \"../list/loopContextByNode\";\nimport { applyChangeFromBindings } from \"../apply/applyChangeFromBindings\";\nimport { hydrateSetContent, hydrateSetLastNode } from \"../apply/applyChangeToFor\";\nimport { waitForStateInitialize } from \"../waitForStateInitialize\";\nimport { setFragmentInfoByUUID, getFragmentInfoByUUID } from \"../structural/fragmentInfoByUUID\";\nimport { setContentByNode } from \"../structural/contentsByNode\";\nimport { createContentFromNodes } from \"../structural/createContent\";\nimport { collectStructuralFragments } from \"../structural/collectStructuralFragments\";\nimport { createNotFilter } from \"../structural/createNotFilter\";\nimport { getFragmentNodeInfos } from \"../structural/getFragmentNodeInfos\";\nimport { optimizeFragment } from \"../structural/optimizeFragment\";\nimport { expandShorthandPaths } from \"../structural/expandShorthandPaths\";\nimport { createListIndex } from \"../list/createListIndex\";\nimport { IListIndex } from \"../list/types\";\nimport { setListIndexesByList } from \"../list/listIndexesByList\";\nimport { getPathInfo } from \"../address/PathInfo\";\nimport { createStateAddress } from \"../address/StateAddress\";\nimport { IBindingInfo } from \"../types\";\nimport { VERSION } from \"../version\";\n\n// ハイドレーション時にスキップするバインディングタイプ\nconst STRUCTURAL_TYPES = new Set(['for', 'if', 'elseif', 'else']);\n\n\ninterface ISsrBlock {\n type: string; // for, if, elseif, else\n uuid: string;\n path: string;\n index: number | null; // for のみ\n nodes: Node[]; // start〜end 間のノード\n}\n\n/**\n * SSR ブロック境界コメントを走査して、start〜end 間のノードを収集する\n */\nfunction collectSsrBlocks(root: Node): ISsrBlock[] {\n const blocks: ISsrBlock[] = [];\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n const startComments: Comment[] = [];\n\n // まず全コメントを収集\n while (walker.nextNode()) {\n startComments.push(walker.currentNode as Comment);\n }\n\n for (const comment of startComments) {\n const startMatch = SSR_BLOCK_START.exec(comment.data);\n if (!startMatch) continue;\n\n const type = startMatch[1];\n const info = startMatch[2]; // \"uuid:path:index\" or \"uuid:path\"\n const parts = info.split(':');\n\n let uuid: string;\n let path: string;\n let index: number | null = null;\n\n if (type === 'for') {\n // uuid:path:index\n uuid = parts[0];\n path = parts[1];\n index = parseInt(parts[2], 10);\n } else {\n // uuid:path\n uuid = parts[0];\n path = parts.slice(1).join(':');\n }\n\n // start と end の間のノードを収集\n const nodes: Node[] = [];\n let sibling = comment.nextSibling;\n const endPattern = `@@wcs-${type}-end:${info}`;\n while (sibling) {\n if (sibling.nodeType === Node.COMMENT_NODE && (sibling as Comment).data === endPattern) {\n break;\n }\n nodes.push(sibling);\n sibling = sibling.nextSibling;\n }\n\n blocks.push({ type, uuid, path, index, nodes });\n }\n\n return blocks;\n}\n\n/**\n * live DOM ノード群からバインディングを収集する。\n * ノードを一時的に DocumentFragment に移動して collectNodesAndBindingInfos を実行し、\n * 元の位置に戻す。\n */\nfunction collectBindingsFromLiveNodes(\n nodes: Node[],\n): { bindingInfos: IBindingInfo[], subscriberNodes: Node[], bindingSession: BindingSession } {\n const bindingSession = new BindingSession();\n if (nodes.length === 0) {\n return { bindingInfos: [], subscriberNodes: [], bindingSession };\n }\n\n // ノードの元の位置を記録\n const parent = nodes[0].parentNode;\n const nextSibling = nodes[nodes.length - 1].nextSibling;\n\n // 一時的に wrapper 要素に移動(collectNodesAndBindingInfos は Element を受け付ける)\n const wrapper = document.createElement('div');\n for (const node of nodes) {\n wrapper.appendChild(node);\n }\n\n // バインディング収集\n const [subscriberNodes, allBindings] = collectNodesAndBindingInfos(wrapper);\n\n const bindingInfos = bindingSession.initialize(allBindings, {\n registerAddress: false,\n applyOnReconnect: false,\n });\n\n // 元の位置に戻す\n if (parent) {\n while (wrapper.firstChild) {\n parent.insertBefore(wrapper.firstChild, nextSibling);\n }\n }\n\n return {\n bindingInfos,\n subscriberNodes,\n bindingSession,\n };\n}\n\n/**\n * ブロックの中で初回値を適用するバインディングを集める(#258 X6 — hydrateBindings の注記)。\n *\n * 除くもの:\n * - 構造バインディング(SSR が描画済み)とイベント。\n * - コメントに乗ったバインディング。ブロックを集める時点のコメントのバインディングは構造の置き場\n * (`<!--@@wcs-for:uuid-->`)だけで、テキストの `@@:` はこの後で `Ssr.restoreTextBindings` が戻す。\n * テンプレートを復帰できなかった入れ子の置き場は text として解釈される(`text: uuid`)ので、\n * 構造の種別だけでは除けない。\n * - 添字のバインディング(`$1` / `$2` …)。state に依存しないので依存辺のための適用が要らず、SSR が\n * 描いた添字のままでよい(入れ子の内側の `$2` は、外側のループ文脈しか持たないので読めもしない)。\n * - ループの深さより多いワイルドカードを持つバインディング。入れ子のブロックの行は外側のブロックの\n * Content に吸収され、外側のループ文脈しか持たない(入れ子ハイドレーションの既知の制限・\n * integration.listLedgerParentKey.test.ts)。\n * コメントと段数の足りないバインディングは、適用しても失敗の報告をハイドレーションのたびに増やすだけになる。\n */\nfunction collectBlockBindings(out: IBindingInfo[], bindings: readonly IBindingInfo[], loopDepth: number): void {\n for (const binding of bindings) {\n if (binding.bindingType === \"event\" || STRUCTURAL_TYPES.has(binding.bindingType)) {\n continue;\n }\n if (binding.node.nodeType === Node.COMMENT_NODE || binding.statePathName in INDEX_BY_INDEX_NAME) {\n continue;\n }\n if (getPathInfo(binding.statePathName).wildcardCount > loopDepth) {\n continue;\n }\n out.push(binding);\n }\n}\n\n/**\n * SSR ブロックの DOM ノードを Content 化し、バインディングを登録する。\n * 戻り値はブロックの中で初回値を適用するバインディング(`collectBlockBindings`)。\n */\nfunction hydrateBlocks(root: Node, blocks: ISsrBlock[]): IBindingInfo[] {\n // for ブロックの listIndex を UUID ごとに収集\n const listIndexesByUuid: Map<string, IListIndex[]> = new Map();\n const blockBindings: IBindingInfo[] = [];\n\n for (const block of blocks) {\n if (block.nodes.length === 0) continue;\n\n const content = createContentFromNodes(block.nodes);\n\n // Content のバインディングを収集\n const { bindingInfos, subscriberNodes, bindingSession } = collectBindingsFromLiveNodes(block.nodes);\n setBindingSessionByContent(content, bindingSession);\n\n // Content 内のノードに data-wcs-completed を付与\n // (メインの collectNodesAndBindingInfos で重複登録されないようにする)\n for (const node of subscriberNodes) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n (node as Element).setAttribute('data-wcs-completed', '');\n }\n }\n setBindingsByContent(content, bindingInfos);\n setNodesByContent(content, subscriberNodes);\n\n const indexBindings: IBindingInfo[] = [];\n for (const binding of bindingInfos) {\n if (binding.statePathName in INDEX_BY_INDEX_NAME) {\n indexBindings.push(binding);\n }\n }\n setIndexBindingsByContent(content, indexBindings);\n\n if (block.type === 'for' && block.index !== null) {\n const placeholderComment = findPlaceholderComment(root, 'for', block.uuid);\n if (placeholderComment) {\n const listIndex = createListIndex(null, block.index);\n hydrateSetContent(placeholderComment, listIndex, content);\n const lastNode = block.nodes[block.nodes.length - 1];\n hydrateSetLastNode(placeholderComment, lastNode);\n setContentByNode(placeholderComment, content);\n\n // ループコンテキストをバインドし、バインディングをアドレスに登録\n const pathInfo = getPathInfo(block.path + '.' + WILDCARD);\n const stateAddress = createStateAddress(pathInfo, listIndex);\n // ILoopContext は IStateAddress + listIndex なので、stateAddress をそのまま使う\n bindLoopContextToContent(content, stateAddress as any);\n\n bindingSession.initialize(bindingInfos, {\n registerAddress: true,\n registerPathInfo: false,\n applyOnReconnect: false,\n });\n collectBlockBindings(blockBindings, bindingInfos, pathInfo.wildcardCount);\n\n // listIndex を UUID ごとに収集(後で setListIndexesByList に渡す)\n let indexes = listIndexesByUuid.get(block.uuid);\n if (!indexes) {\n indexes = [];\n listIndexesByUuid.set(block.uuid, indexes);\n }\n indexes.push(listIndex);\n }\n } else {\n const placeholderComment = findPlaceholderComment(root, block.type, block.uuid);\n if (placeholderComment) {\n setContentByNode(placeholderComment, content);\n\n bindingSession.initialize(bindingInfos, {\n registerAddress: true,\n registerPathInfo: false,\n applyOnReconnect: false,\n });\n // if / elseif / else の中身はループの外(入れ子の行はここに吸収されても段数で除かれる)\n collectBlockBindings(blockBindings, bindingInfos, 0);\n }\n }\n }\n\n // for ブロックの listIndex を state のリスト値に紐づける\n for (const [uuid, indexes] of listIndexesByUuid) {\n const placeholderComment = findPlaceholderComment(root, 'for', uuid);\n if (!placeholderComment) continue;\n // state から現在のリスト値を取得して listIndexes を設定\n const rootNode = placeholderComment.getRootNode() as Node;\n // structuralBindings はまだ登録前なので、getParseBindTextResults を直接使う\n const fragmentInfo = getFragmentInfoByUUID(uuid);\n if (!fragmentInfo) continue;\n const statePathName = fragmentInfo.parseBindTextResult.statePathName;\n const stateElement = getStateElement(rootNode);\n if (!stateElement) continue;\n stateElement.createState(\"readonly\", (state) => {\n const list = state[statePathName];\n if (Array.isArray(list)) {\n setListIndexesByList(list, indexes);\n }\n });\n }\n return blockBindings;\n}\n\nfunction findPlaceholderComment(root: Node, type: string, uuid: string): Comment | null {\n const keywordMap: Record<string, string> = {\n 'for': config.commentForPrefix,\n 'if': config.commentIfPrefix,\n 'elseif': config.commentElseIfPrefix,\n 'else': config.commentElsePrefix,\n };\n const keyword = keywordMap[type];\n if (!keyword) return null;\n\n const pattern = `@@${keyword}:${uuid}`;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n if (comment.data === pattern) {\n return comment;\n }\n }\n return null;\n}\n\n/**\n * <wcs-ssr> 内のテンプレートを fragmentInfoByUUID に復帰させる。\n */\nfunction restoreFragments(root: Document, ssrEl: Ssr): void {\n const rootNode = root as Node;\n let lastIfParseResult: ParseBindTextResult | null = null;\n\n for (const [uuid, tpl] of ssrEl.templates) {\n const bindText = tpl.getAttribute(config.bindAttributeName) || '';\n const parseBindTextResults = parseBindTextsForElement(bindText);\n let parseBindTextResult = parseBindTextResults[0];\n const bindingType = parseBindTextResult.bindingType;\n\n // else: 直前の if 条件の not → 条件反転(elseif は独自条件のままでよい)\n if (bindingType === 'else' && lastIfParseResult) {\n parseBindTextResult = {\n ...lastIfParseResult,\n outFilters: [...lastIfParseResult.outFilters, createNotFilter()],\n bindingType: 'else',\n };\n }\n\n // if chain の追跡\n if (bindingType === 'if') {\n lastIfParseResult = parseBindTextResult;\n } else if (bindingType === 'elseif') {\n lastIfParseResult = parseBindTextResult;\n } else if (bindingType === 'else') {\n lastIfParseResult = null;\n }\n\n const fragment = document.importNode(tpl.content, true);\n const forPath = bindingType === \"for\" ? parseBindTextResult.statePathName : undefined;\n optimizeFragment(fragment);\n if (typeof forPath === \"string\") {\n expandShorthandPaths(fragment, forPath);\n }\n collectStructuralFragments(rootNode, fragment, forPath);\n\n const fragmentInfo = {\n fragment,\n parseBindTextResult,\n nodeInfos: getFragmentNodeInfos(fragment),\n };\n setFragmentInfoByUUID(uuid, rootNode, fragmentInfo);\n }\n}\n\n/**\n * SSR ハイドレーション用バインディング初期化。\n * バージョン不一致時は DOM をクリーンアップして false を返す\n * (呼び出し元で buildBindings にフォールバック)。\n */\nexport async function hydrateBindings(root: Document): Promise<boolean> {\n await waitForStateInitialize(root);\n\n // バージョン検証\n const ssrElements = root.querySelectorAll(config.tagNames.ssr);\n for (const ssrNode of ssrElements) {\n const ssrEl = ssrNode as Ssr;\n if (!ssrEl.verifyVersion()) {\n console.warn(\n `[@wcstack/state] SSR version mismatch: server=\"${ssrEl.version}\", client=\"${VERSION}\". Falling back to full render.`\n );\n Ssr.cleanupDom(root);\n return false;\n }\n }\n\n // <wcs-ssr> からテンプレートを fragmentInfoByUUID に復帰\n for (const ssrNode of ssrElements) {\n restoreFragments(root, ssrNode as Ssr);\n }\n\n // SSR ブロック境界コメントから既存 DOM を Content 化\n const blocks = collectSsrBlocks(document.body);\n const blockBindings = hydrateBlocks(document.body, blocks);\n\n // ブロック境界コメント (start/end) を除去\n Ssr.removeBlockBoundaryComments(document.body);\n\n // <wcs-ssr> を一時除去(バインディング走査に含めない)\n const ssrParents: { el: Element, parent: Node, next: Node | null }[] = [];\n for (const el of ssrElements) {\n if (el.parentNode) {\n ssrParents.push({ el, parent: el.parentNode, next: el.nextSibling });\n el.remove();\n }\n }\n\n // 構造プレースホルダーコメント (@@wcs-for:uuid 等) は残す\n // → バインディング走査で拾われ、状態変化時の再レンダリングに使われる\n\n // SSR テキストバインディングを @@: 形式に復元\n Ssr.restoreTextBindings(document.body);\n\n // ノードとバインディングを収集\n const [subscriberNodes, allBindings] = collectNodesAndBindingInfos(document.body);\n\n // 収集完了したノードに data-wcs-completed 属性を付与\n // for ブロック内ノード(hydrateBlocks で登録済み)にはループコンテキストをリセットしない\n for (const node of subscriberNodes) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n if (!el.hasAttribute('data-wcs-completed')) {\n setLoopContextByNode(node, null);\n el.setAttribute('data-wcs-completed', '');\n }\n } else {\n // コメントノード等\n setLoopContextByNode(node, null);\n }\n }\n\n // バインディングを構造系とそれ以外に分離\n const normalBindings: IBindingInfo[] = [];\n const structuralBindings: IBindingInfo[] = [];\n const bindingSession = getOrCreateBindingSession(document.body);\n const initializedBindings = bindingSession.initialize(allBindings);\n\n for (const binding of initializedBindings) {\n if (binding.bindingType === \"event\") continue;\n if (STRUCTURAL_TYPES.has(binding.bindingType)) {\n structuralBindings.push(binding);\n } else if (binding.statePathName.includes(WILDCARD)) {\n // for ブロック内のバインディング → Content のバインディングとして登録済み\n continue;\n } else {\n normalBindings.push(binding);\n }\n }\n\n // for バインディングの lastListValue を初期値として設定\n // (次回の状態変化時に差分計算の基準になる)\n for (const binding of structuralBindings) {\n if (binding.bindingType === 'for') {\n const absAddr = getAbsoluteStateAddressByBinding(binding);\n const rootNode = binding.replaceNode.getRootNode() as Node;\n const stateElement = getStateElement(rootNode);\n if (stateElement) {\n stateElement.createState(\"readonly\", (state) => {\n const value = state[binding.statePathName];\n if (Array.isArray(value)) {\n setLastListValueByAbsoluteStateAddress(absAddr, value);\n // 描画の基準と同時に state 側の基準も進める(E1。applyChangeFromBindings と対称)\n setStateListBaseline(absAddr, value);\n }\n });\n }\n }\n }\n\n // 初回値の適用(構造バインディングは SSR 描画済みなので除く)。SSR ブロック(for の行・if の中身)の\n // 中のバインディングも適用する(#258 X6): getter の依存辺は getter を評価したときにしか張られない\n // ので、適用しないと行の `items.*.double` は `items.*.n` を書いても一度も再評価されず、サーバーが\n // 書いたテキストのまま固まる。値は SSR と同じ state から読むのでテキストは変わらない\n applyChangeFromBindings([...normalBindings, ...blockBindings]);\n\n // <wcs-ssr> を元に戻す\n for (const { el, parent, next } of ssrParents) {\n parent.insertBefore(el, next);\n }\n\n // hydrateProps 復元\n const restoredSsrElements = root.querySelectorAll(config.tagNames.ssr);\n for (const ssrNode of restoredSsrElements) {\n const ssrEl = ssrNode as Ssr;\n const props = ssrEl.hydrateProps;\n for (const [id, propMap] of Object.entries(props)) {\n const target = root.querySelector(`[data-wcs-ssr-id=\"${id}\"]`);\n if (!target) continue;\n for (const [propName, value] of Object.entries(propMap)) {\n (target as any)[propName] = value;\n }\n }\n }\n\n // ハイドレーション中の重複登録防止用属性を除去\n const completedEls = root.querySelectorAll('[data-wcs-completed]');\n for (const el of completedEls) {\n el.removeAttribute('data-wcs-completed');\n }\n\n return true;\n}\n\n/** @internal テスト用 */\nexport const __test = {\n collectSsrBlocks,\n collectBindingsFromLiveNodes,\n hydrateBlocks,\n findPlaceholderComment,\n restoreFragments,\n};\n","/**\n * ssr/install.ts — SSR 機能の install(設計案 H8、S5)。core の受け口(core/ssrHooks.ts と\n * registerComponents の definer)へこの機能の実装を置き、ssr-snapshot プロトコルを提供する。\n * 従来 `State` と `stateElementByName` と `registerComponents` に直書きされていた分岐で、\n * 理由のコメントは元の位置から移してある。\n */\nimport { config } from \"../config\";\nimport type { IStateElement } from \"../components/types\";\nimport { ISsrHooks, setSsrHooks } from \"../core/ssrHooks\";\nimport { registerComponentDefiner } from \"../registerComponents\";\nimport { getBindingsReady } from \"../stateElementByName\";\nimport { VERSION } from \"../version\";\nimport { registerSsrSnapshotBuilder } from \"./buildSsrDocument\";\nimport { hydrateBindings } from \"./hydrateBindings\";\nimport { Ssr } from \"./Ssr\";\n\nexport const ssrFeatureHooks: ISsrHooks = {\n hydrate: hydrateBindings,\n loadState(element) {\n const root = element.parentNode;\n if (!root) return null;\n const ssrEl = Ssr.find(root);\n if (!ssrEl) return null;\n const data = ssrEl.stateData;\n return Object.keys(data).length > 0 ? data : null;\n },\n async emitSnapshot(element) {\n await getBindingsReady((element as unknown as IStateElement).rootNode);\n const stateData = Ssr.extractStateData(element);\n const ssrEl = document.createElement(config.tagNames.ssr);\n ssrEl.setAttribute(\"version\", VERSION);\n Ssr.buildContent(ssrEl, stateData);\n element.parentNode?.insertBefore(ssrEl, element);\n },\n};\n\nlet installed = false;\n/** 冪等。full / auto では `bootstrapState()` が呼ぶ */\nexport function installSsr(): void {\n if (installed) return;\n installed = true;\n setSsrHooks(ssrFeatureHooks);\n registerComponentDefiner((registry) => {\n if (!registry.get(config.tagNames.ssr)) {\n registry.define(config.tagNames.ssr, Ssr);\n }\n });\n // ssr-snapshot プロトコルの提供(docs/ssr-router-design.md §5)。renderToString が\n // `<wcs-ssr>` 生成をサーバー主導の最終パスへ回せるようにする。登録は冪等\n registerSsrSnapshotBuilder();\n}\n","/**\n * features/ssr.ts — サーバー描画とハイドレーション(@wcstack/state/features/ssr)。\n */\nimport type { IStateFeature } from \"../core/features\";\nimport { installSsr } from \"../ssr/install\";\n\nexport const ssr: IStateFeature = {\n name: \"ssr\",\n install(): void {\n installSsr();\n },\n};\nexport default ssr;\n"],"names":["SSR_PLACEHOLDER_COMMENT","SSR_BLOCK_START","SSR_BLOCK_END","SSR_TEXT_START","escapeJsonForScript","json","replace","Ssr","HTMLElementBase","_stateData","_templates","_hydrateProps","version","this","getAttribute","stateData","_loadStateData","templates","_loadTemplates","hydrateProps","_loadHydrateProps","getTemplate","uuid","get","verifyVersion","serverVersion","serverParts","split","clientParts","VERSION","setStateData","data","setHydrateProps","props","script","querySelector","JSON","parse","textContent","map","Map","querySelectorAll","tpl","id","set","find","root","tagName","config","tagNames","ssr","parentEl","Element","Document","documentElement","extractStateData","stateEl","raw","__state","key","Object","keys","startsWith","descriptor","getOwnPropertyDescriptor","undefined","value","buildContent","ssrEl","jsonScript","document","createElement","setAttribute","stringify","appendChild","uuids","getAllFragmentUUIDs","fragmentInfo","getFragmentInfoByUUID","bindResult","parseBindTextResult","bindText","bindingType","statePathName","bindAttributeName","content","fragment","cloneNode","ssrNodes","getAllSsrPropertyNodes","length","propsData","i","node","entries","getSsrProperties","entry","propName","propsScript","clearSsrPropertyStore","removeBlockBoundaryComments","walker","createTreeWalker","NodeFilter","SHOW_COMMENT","toRemove","nextNode","comment","currentNode","test","push","remove","removeStructuralComments","restoreTextBindings","startComments","match","exec","path","bindComment","createComment","parentNode","insertBefore","sibling","nextSibling","endPattern","next","nodeType","Node","COMMENT_NODE","removeChild","cleanupDom","body","ssrElements","templateByUuid","ssrNode","walker1","startComment","walker2","placeholders","restored","bindAttr","imported","importNode","childNodes","child","Array","from","replaceChild","ssrIdElements","el","removeAttribute","builder","protocol","build","stateTag","state","ssrTag","stateElements","prev","previousElementSibling","toLowerCase","STRUCTURAL_TYPES","Set","collectBindingsFromLiveNodes","nodes","bindingSession","BindingSession","bindingInfos","subscriberNodes","parent","wrapper","allBindings","collectNodesAndBindingInfos","initialize","registerAddress","applyOnReconnect","firstChild","collectBlockBindings","out","bindings","loopDepth","binding","has","INDEX_BY_INDEX_NAME","getPathInfo","wildcardCount","findPlaceholderComment","type","keyword","for","commentForPrefix","if","commentIfPrefix","elseif","commentElseIfPrefix","else","commentElsePrefix","pattern","restoreFragments","rootNode","lastIfParseResult","parseBindTextsForElement","outFilters","createNotFilter","forPath","optimizeFragment","expandShorthandPaths","collectStructuralFragments","nodeInfos","getFragmentNodeInfos","setFragmentInfoByUUID","ssrFeatureHooks","hydrate","async","waitForStateInitialize","console","warn","blocks","startMatch","info","parts","index","parseInt","slice","join","collectSsrBlocks","blockBindings","listIndexesByUuid","block","createContentFromNodes","setBindingSessionByContent","ELEMENT_NODE","setBindingsByContent","setNodesByContent","indexBindings","setIndexBindingsByContent","placeholderComment","listIndex","createListIndex","hydrateSetContent","lastNode","hydrateSetLastNode","setContentByNode","pathInfo","WILDCARD","stateAddress","createStateAddress","bindLoopContextToContent","registerPathInfo","indexes","getRootNode","stateElement","getStateElement","createState","list","isArray","setListIndexesByList","hydrateBlocks","ssrParents","hasAttribute","setLoopContextByNode","normalBindings","structuralBindings","initializedBindings","getOrCreateBindingSession","includes","absAddr","getAbsoluteStateAddressByBinding","replaceNode","setLastListValueByAbsoluteStateAddress","setStateListBaseline","applyChangeFromBindings","restoredSsrElements","propMap","target","completedEls","loadState","element","emitSnapshot","getBindingsReady","installed","installSsr","setSsrHooks","registerComponentDefiner","registry","define","globals","globalThis","SSR_SNAPSHOT_BUILDER_KEY","registerSsrSnapshotBuilder","name","install"],"mappings":"iwBAiBA,MAAMA,EAA0B,qCAC1BC,EAAkB,0CAClBC,EAAgB,wCAChBC,EAAiB,0BAgBvB,SAASC,EAAoBC,GAC3B,OAAOA,EACJC,QAAQ,KAAM,WACdA,QAAQ,KAAM,WACdA,QAAQ,KAAM,WACdA,QAAQ,UAAW,WACnBA,QAAQ,UAAW,UACxB,CAEM,MAAOC,UAAYC,EACfC,WAA4B,KAC5BC,WAAsD,KACtDC,cAAgE,KAExE,WAAIC,GACF,OAAOC,KAAKC,aAAa,YAAc,EACzC,CAEA,aAAIC,GAIF,OAHwB,OAApBF,KAAKJ,aACPI,KAAKJ,WAAaI,KAAKG,kBAElBH,KAAKJ,UACd,CAEA,aAAIQ,GAIF,OAHwB,OAApBJ,KAAKH,aACPG,KAAKH,WAAaG,KAAKK,kBAElBL,KAAKH,UACd,CAEA,gBAAIS,GAIF,OAH2B,OAAvBN,KAAKF,gBACPE,KAAKF,cAAgBE,KAAKO,qBAErBP,KAAKF,aACd,CAEA,WAAAU,CAAYC,GACV,OAAOT,KAAKI,UAAUM,IAAID,IAAS,IACrC,CAOA,aAAAE,GACE,MAAMC,EAAgBZ,KAAKD,QAC3B,IAAKa,EAAe,OAAO,EAC3B,MAAMC,EAAcD,EAAcE,MAAM,KAClCC,EAAcC,EAAQF,MAAM,KAElC,OAAOD,EAAY,KAAOE,EAAY,IAAMF,EAAY,KAAOE,EAAY,EAC7E,CAEA,YAAAE,CAAaC,GACXlB,KAAKJ,WAAasB,CACpB,CAEA,eAAAC,CAAgBC,GACdpB,KAAKF,cAAgBsB,CACvB,CAEQ,cAAAjB,GACN,MAAMkB,EAASrB,KAAKsB,cAClB,6DAEF,IAAKD,EAAQ,MAAO,CAAA,EACpB,IACE,OAAOE,KAAKC,MAAMH,EAAOI,aAAe,KAC1C,CAAE,MACA,MAAO,CAAA,CACT,CACF,CAEQ,cAAApB,GACN,MAAMqB,EAAM,IAAIC,IACVvB,EAAYJ,KAAK4B,iBAAsC,gBAC7D,IAAK,MAAMC,KAAOzB,EAAW,CAC3B,MAAM0B,EAAKD,EAAI5B,aAAa,MACxB6B,GACFJ,EAAIK,IAAID,EAAID,EAEhB,CACA,OAAOH,CACT,CAEQ,iBAAAnB,GACN,MAAMc,EAASrB,KAAKsB,cAAc,8BAClC,IAAKD,EAAQ,MAAO,CAAA,EACpB,IACE,OAAOE,KAAKC,MAAMH,EAAOI,aAAe,KAC1C,CAAE,MACA,MAAO,CAAA,CACT,CACF,CAEA,WAAOO,CAAKC,GACV,MAAMC,EAAUC,EAAOC,SAASC,IAC1BC,EAAWL,aAAgBM,QAC7BN,EACAA,aAAgBO,SACdP,EAAKQ,gBACL,KACN,IAAKH,EAAU,OAAO,KAEtB,OADWA,EAAShB,cAAcY,EAEpC,CASA,uBAAOQ,CAAiBC,GACtB,MAAMC,EAAOD,EAAgBE,QAC7B,IAAKD,GAAsB,iBAARA,EAAkB,MAAO,CAAA,EAC5C,MAAM1B,EAA4B,CAAA,EAClC,IAAK,MAAM4B,KAAOC,OAAOC,KAAKJ,GAAM,CAClC,GAAIE,EAAIG,WAAW,KAAM,SAQzB,MAAMC,EAAaH,OAAOI,yBAAyBP,EAAKE,GACxD,QAAmBM,IAAfF,GAAsD,mBAAnBA,EAAWxC,IAAoB,SACtE,MAAM2C,EAAST,EAAgCE,GAC1B,mBAAVO,IACTnC,EAAK4B,GAAOO,EAEhB,CACA,OAAOnC,CACT,CAEA,mBAAOoC,CAAaC,EAAgBrD,GAElC,MAAMsD,EAAaC,SAASC,cAAc,UAC1CF,EAAWG,aAAa,OAAQ,oBAChCH,EAAW/B,YAAclC,EAAoBgC,KAAKqC,UAAU1D,IAC5DqD,EAAMM,YAAYL,GAGlB,MAAMM,EAAQC,IACd,IAAK,MAAMtD,KAAQqD,EAAO,CACxB,MAAME,EAAeC,EAAsBxD,GAC3C,IAAKuD,EAAc,SAEnB,MAAMnC,EAAM4B,SAASC,cAAc,YACnC7B,EAAI8B,aAAa,KAAMlD,GAEvB,MAAMyD,EAAaF,EAAaG,oBAC1BC,EAAsC,SAA3BF,EAAWG,YACxB,QACA,GAAGH,EAAWG,gBAAgBH,EAAWI,gBAC7CzC,EAAI8B,aAAaxB,EAAOoC,kBAAmBH,GAE3C,MAAMI,EAAUR,EAAaS,SAASC,WAAU,GAChD7C,EAAI2C,QAAQX,YAAYW,GAExBjB,EAAMM,YAAYhC,EACpB,CAGA,MAAM8C,EAAWC,IACjB,GAAID,EAASE,OAAS,EAAG,CACvB,MAAMC,EAAqD,CAAA,EAC3D,IAAK,IAAIC,EAAI,EAAGA,EAAIJ,EAASE,OAAQE,IAAK,CACxC,MAAMC,EAAOL,EAASI,GAChBE,EAAUC,EAAiBF,GACjC,GAAuB,IAAnBC,EAAQJ,OAAc,SAC1B,MAAM/C,EAAK,WAAWiD,IACrBC,EAAiBrB,aAAa,kBAAmB7B,GAClD,MAAMV,EAAiC,CAAA,EACvC,IAAK,MAAM+D,KAASF,EAClB7D,EAAM+D,EAAMC,UAAYD,EAAM9B,MAEhCyB,EAAUhD,GAAMV,CAClB,CACA,GAAI2B,OAAOC,KAAK8B,GAAWD,OAAS,EAAG,CACrC,MAAMQ,EAAc5B,SAASC,cAAc,UAC3C2B,EAAY1B,aAAa,OAAQ,oBACjC0B,EAAY1B,aAAa,qBAAsB,IAC/C0B,EAAY5D,YAAclC,EAAoBgC,KAAKqC,UAAUkB,IAC7DvB,EAAMM,YAAYwB,EACpB,CACF,CAEAC,GACF,CAKA,kCAAOC,CAA4BtD,GACjC,MAAMuD,EAAS/B,SAASgC,iBAAiBxD,EAAMyD,WAAWC,cACpDC,EAAsB,GAC5B,KAAOJ,EAAOK,YAAY,CACxB,MAAMC,EAAUN,EAAOO,aACnB3G,EAAgB4G,KAAKF,EAAQ5E,OAAS7B,EAAc2G,KAAKF,EAAQ5E,QACnE0E,EAASK,KAAKH,EAElB,CACA,IAAK,MAAMA,KAAWF,EACpBE,EAAQI,QAEZ,CAKA,+BAAOC,CAAyBlE,GAC9B,MAAMuD,EAAS/B,SAASgC,iBAAiBxD,EAAMyD,WAAWC,cACpDC,EAAsB,GAC5B,KAAOJ,EAAOK,YAAY,CACxB,MAAMC,EAAUN,EAAOO,YACnB5G,EAAwB6G,KAAKF,EAAQ5E,OACvC0E,EAASK,KAAKH,EAElB,CACA,IAAK,MAAMA,KAAWF,EACpBE,EAAQI,QAEZ,CAOA,0BAAOE,CAAoBnE,GACzB,MAAMuD,EAAS/B,SAASgC,iBAAiBxD,EAAMyD,WAAWC,cACpDU,EAAsD,GAE5D,KAAOb,EAAOK,YAAY,CACxB,MAAMC,EAAUN,EAAOO,YACjBO,EAAQhH,EAAeiH,KAAKT,EAAQ5E,MACtCoF,GACFD,EAAcJ,KAAK,CAAEH,UAASU,KAAMF,EAAM,IAE9C,CAEA,IAAK,MAAMR,QAAEA,EAAOU,KAAEA,KAAUH,EAAe,CAC7C,MAAMI,EAAchD,SAASiD,cAAc,OAAOF,KAClDV,EAAQa,WAAYC,aAAaH,EAAaX,GAE9C,IAAIe,EAAuBf,EAAQgB,YACnChB,EAAQI,SAER,MAAMa,EAAa,kBAAkBP,IACrC,KAAOK,GAAS,CACd,MAAMG,EAAoBH,EAAQC,YAClC,GAAID,EAAQI,WAAaC,KAAKC,cAAiBN,EAAoB3F,OAAS6F,EAAY,CACtFF,EAAQF,WAAYS,YAAYP,GAChC,KACF,CACAA,EAAQF,WAAYS,YAAYP,GAChCA,EAAUG,CACZ,CACF,CACF,CAYA,iBAAOK,CAAWpF,GAChB,MAAMqF,EAAO7D,SAAS6D,KAGhBC,EAActF,EAAKL,iBAAiBO,EAAOC,SAASC,KACpDmF,EAAiB,IAAI7F,IAC3B,IAAK,MAAM8F,KAAWF,EAAa,CACjC,MAAMnH,EAAYqH,EAAQ7F,iBAAsC,gBAChE,IAAK,MAAMC,KAAOzB,EAAW,CAC3B,MAAM0B,EAAKD,EAAI5B,aAAa,MACxB6B,GACF0F,EAAezF,IAAID,EAAID,EAE3B,CACF,CAGA,MAAM6F,EAAUjE,SAASgC,iBAAiB6B,EAAM5B,WAAWC,cACrDU,EAA2B,GACjC,KAAOqB,EAAQ7B,YAAY,CACzB,MAAMC,EAAU4B,EAAQ3B,YACpB3G,EAAgB4G,KAAKF,EAAQ5E,OAC/BmF,EAAcJ,KAAKH,EAEvB,CACA,IAAK,MAAM6B,KAAgBtB,EAAe,CACxC,MAAMC,EAAQlH,EAAgBmH,KAAKoB,EAAazG,MAG1C6F,EAAa,SAFNT,EAAM,UACNA,EAAM,KAEnB,IAAIO,EAAUc,EAAab,YAC3B,KAAOD,GAAS,CACd,MAAMG,EAAOH,EAAQC,YACrB,GAAID,EAAQI,WAAaC,KAAKC,cAAiBN,EAAoB3F,OAAS6F,EAAY,CACtFF,EAAQX,SACR,KACF,CACAW,EAAQX,SACRW,EAAUG,CACZ,CACAW,EAAazB,QACf,CAGAxG,EAAI0G,oBAAoBkB,GAGxB,MAAMM,EAAUnE,SAASgC,iBAAiB6B,EAAM5B,WAAWC,cACrDkC,EAAqD,GAC3D,KAAOD,EAAQ/B,YAAY,CACzB,MAAMC,EAAU8B,EAAQ7B,YACxB,GAAI5G,EAAwB6G,KAAKF,EAAQ5E,MAAO,CAC9C,MAAMT,EAAOqF,EAAQ5E,KAAKJ,MAAM,KAAK,GACrC+G,EAAa5B,KAAK,CAAEH,UAASrF,QAC/B,CACF,CACA,IAAK,MAAMqF,QAAEA,EAAOrF,KAAEA,KAAUoH,EAAc,CAC5C,MAAMhG,EAAM2F,EAAe9G,IAAID,GAC/B,GAAIoB,EAAK,CACP,MAAMiG,EAAWrE,SAASC,cAAc,YAClCqE,EAAWlG,EAAI5B,aAAakC,EAAOoC,mBACrCwD,GAAUD,EAASnE,aAAaxB,EAAOoC,kBAAmBwD,GAC9D,MAAMC,EAAWvE,SAASwE,WAAWpG,EAAI2C,SAAS,GAClD,GAAIwD,EAASE,WAAWrD,OAAS,EAC/BiD,EAAStD,QAAQX,YAAYmE,QAE7B,IAAK,MAAMG,KAASC,MAAMC,KAAKxG,EAAIqG,YACjCJ,EAAStD,QAAQX,YAAYJ,SAASwE,WAAWE,GAAO,IAG5DrC,EAAQa,WAAY2B,aAAaR,EAAUhC,EAC7C,CACF,CAGA,MAAMyC,EAAgBtG,EAAKL,iBAAiB,qBAC5C,IAAK,MAAM4G,KAAMD,EACfC,EAAGC,gBAAgB,mBAIrB,IAAK,MAAMD,KAAMjB,EACfiB,EAAGtC,QAEP,ECrWF,MAAMwC,EAAkC,CACtCC,SAAU,mBACV5I,QAAS,EACT6I,MAzBI,SAA2B3G,GAC/B,MAAM4G,EAAW1G,EAAOC,SAAS0G,MAC3BC,EAAS5G,EAAOC,SAASC,IAKzB2G,EAAgB/G,EAAKL,iBAAiB,GAAGiH,oDAC/C,IAAK,MAAMlG,KAAWqG,EAAe,CAGnC,MAAMC,EAAOtG,EAAQuG,uBACrB,GAAa,OAATD,GAAiBA,EAAK/G,QAAQiH,gBAAkBJ,EAClD,SAEF,MAAMxF,EAAQE,SAASC,cAAcqF,GACrCxF,EAAMI,aAAa,UAAW3C,GAC9BtB,EAAI4D,aAAaC,EAAO7D,EAAIgD,iBAAiBC,IAC7CA,EAAQgE,YAAYC,aAAarD,EAAOZ,EAC1C,CACF,GCFA,MAAMyG,EAAmB,IAAIC,IAAI,CAAC,MAAO,KAAM,SAAU,SAsEzD,SAASC,EACPC,GAEA,MAAMC,EAAiB,IAAIC,EAC3B,GAAqB,IAAjBF,EAAM1E,OACR,MAAO,CAAE6E,aAAc,GAAIC,gBAAiB,GAAIH,kBAIlD,MAAMI,EAASL,EAAM,GAAG5C,WAClBG,EAAcyC,EAAMA,EAAM1E,OAAS,GAAGiC,YAGtC+C,EAAUpG,SAASC,cAAc,OACvC,IAAK,MAAMsB,KAAQuE,EACjBM,EAAQhG,YAAYmB,GAItB,MAAO2E,EAAiBG,GAAeC,EAA4BF,GAE7DH,EAAeF,EAAeQ,WAAWF,EAAa,CAC1DG,iBAAiB,EACjBC,kBAAkB,IAIpB,GAAIN,EACF,KAAOC,EAAQM,YACbP,EAAOhD,aAAaiD,EAAQM,WAAYrD,GAI5C,MAAO,CACL4C,eACAC,kBACAH,iBAEJ,CAkBA,SAASY,EAAqBC,EAAqBC,EAAmCC,GACpF,IAAK,MAAMC,KAAWF,EACQ,UAAxBE,EAAQnG,aAA2B+E,EAAiBqB,IAAID,EAAQnG,cAGhEmG,EAAQxF,KAAKiC,WAAaC,KAAKC,cAAgBqD,EAAQlG,iBAAiBoG,GAGxEC,EAAYH,EAAQlG,eAAesG,cAAgBL,GAGvDF,EAAIpE,KAAKuE,EAEb,CA0GA,SAASK,GAAuB5I,EAAY6I,EAAcrK,GACxD,MAMMsK,EANqC,CACzCC,IAAO7I,EAAO8I,iBACdC,GAAM/I,EAAOgJ,gBACbC,OAAUjJ,EAAOkJ,oBACjBC,KAAQnJ,EAAOoJ,mBAEUT,GAC3B,IAAKC,EAAS,OAAO,KAErB,MAAMS,EAAU,KAAKT,KAAWtK,IAC1B+E,EAAS/B,SAASgC,iBAAiBxD,EAAMyD,WAAWC,cAC1D,KAAOH,EAAOK,YAAY,CACxB,MAAMC,EAAUN,EAAOO,YACvB,GAAID,EAAQ5E,OAASsK,EACnB,OAAO1F,CAEX,CACA,OAAO,IACT,CAKA,SAAS2F,GAAiBxJ,EAAgBsB,GACxC,MAAMmI,EAAWzJ,EACjB,IAAI0J,EAAgD,KAEpD,IAAK,MAAOlL,EAAMoB,KAAQ0B,EAAMnD,UAAW,CACzC,MAAMgE,EAAWvC,EAAI5B,aAAakC,EAAOoC,oBAAsB,GAE/D,IAAIJ,EADyByH,EAAyBxH,GACP,GAC/C,MAAMC,EAAcF,EAAoBE,YAGpB,SAAhBA,GAA0BsH,IAC5BxH,EAAsB,IACjBwH,EACHE,WAAY,IAAIF,EAAkBE,WAAYC,KAC9CzH,YAAa,SAKG,OAAhBA,GAEuB,WAAhBA,EADTsH,EAAoBxH,EAGK,SAAhBE,IACTsH,EAAoB,MAGtB,MAAMlH,EAAWhB,SAASwE,WAAWpG,EAAI2C,SAAS,GAC5CuH,EAA0B,QAAhB1H,EAAwBF,EAAoBG,mBAAgBlB,EAC5E4I,EAAiBvH,GACM,iBAAZsH,GACTE,EAAqBxH,EAAUsH,GAEjCG,EAA2BR,EAAUjH,EAAUsH,GAE/C,MAAM/H,EAAe,CACnBS,WACAN,sBACAgI,UAAWC,EAAqB3H,IAElC4H,EAAsB5L,EAAMiL,EAAU1H,EACxC,CACF,CC7UO,MAAMsI,GAA6B,CACxCC,QDmVKC,eAA+BvK,SAC9BwK,EAAuBxK,GAG7B,MAAMsF,EAActF,EAAKL,iBAAiBO,EAAOC,SAASC,KAC1D,IAAK,MAAMoF,KAAWF,EAAa,CACjC,MAAMhE,EAAQkE,EACd,IAAKlE,EAAM5C,gBAKT,OAJA+L,QAAQC,KACN,kDAAkDpJ,EAAMxD,qBAAqBiB,oCAE/EtB,EAAI2H,WAAWpF,IACR,CAEX,CAGA,IAAK,MAAMwF,KAAWF,EACpBkE,GAAiBxJ,EAAMwF,GAIzB,MAAMmF,EAvUR,SAA0B3K,GACxB,MAAM2K,EAAsB,GACtBpH,EAAS/B,SAASgC,iBAAiBxD,EAAMyD,WAAWC,cACpDU,EAA2B,GAGjC,KAAOb,EAAOK,YACZQ,EAAcJ,KAAKT,EAAOO,aAG5B,IAAK,MAAMD,KAAWO,EAAe,CACnC,MAAMwG,EAAazN,EAAgBmH,KAAKT,EAAQ5E,MAChD,IAAK2L,EAAY,SAEjB,MAAM/B,EAAO+B,EAAW,GAClBC,EAAOD,EAAW,GAClBE,EAAQD,EAAKhM,MAAM,KAEzB,IAAIL,EACA+F,EACAwG,EAAuB,KAEd,QAATlC,GAEFrK,EAAOsM,EAAM,GACbvG,EAAOuG,EAAM,GACbC,EAAQC,SAASF,EAAM,GAAI,MAG3BtM,EAAOsM,EAAM,GACbvG,EAAOuG,EAAMG,MAAM,GAAGC,KAAK,MAI7B,MAAM5D,EAAgB,GACtB,IAAI1C,EAAUf,EAAQgB,YACtB,MAAMC,EAAa,SAAS+D,SAAYgC,IACxC,KAAOjG,IACDA,EAAQI,WAAaC,KAAKC,cAAiBN,EAAoB3F,OAAS6F,IAG5EwC,EAAMtD,KAAKY,GACXA,EAAUA,EAAQC,YAGpB8F,EAAO3G,KAAK,CAAE6E,OAAMrK,OAAM+F,OAAMwG,QAAOzD,SACzC,CAEA,OAAOqD,CACT,CAsRiBQ,CAAiB3J,SAAS6D,MACnC+F,EArMR,SAAuBpL,EAAY2K,GAEjC,MAAMU,EAA+C,IAAI3L,IACnD0L,EAAgC,GAEtC,IAAK,MAAME,KAASX,EAAQ,CAC1B,GAA2B,IAAvBW,EAAMhE,MAAM1E,OAAc,SAE9B,MAAML,EAAUgJ,EAAuBD,EAAMhE,QAGvCG,aAAEA,EAAYC,gBAAEA,EAAeH,eAAEA,GAAmBF,EAA6BiE,EAAMhE,OAC7FkE,EAA2BjJ,EAASgF,GAIpC,IAAK,MAAMxE,KAAQ2E,EACb3E,EAAKiC,WAAaC,KAAKwG,cACxB1I,EAAiBrB,aAAa,qBAAsB,IAGzDgK,EAAqBnJ,EAASkF,GAC9BkE,EAAkBpJ,EAASmF,GAE3B,MAAMkE,EAAgC,GACtC,IAAK,MAAMrD,KAAWd,EAChBc,EAAQlG,iBAAiBoG,GAC3BmD,EAAc5H,KAAKuE,GAKvB,GAFAsD,EAA0BtJ,EAASqJ,GAEhB,QAAfN,EAAMzC,MAAkC,OAAhByC,EAAMP,MAAgB,CAChD,MAAMe,EAAqBlD,GAAuB5I,EAAM,MAAOsL,EAAM9M,MACrE,GAAIsN,EAAoB,CACtB,MAAMC,EAAYC,EAAgB,KAAMV,EAAMP,OAC9CkB,EAAkBH,EAAoBC,EAAWxJ,GACjD,MAAM2J,EAAWZ,EAAMhE,MAAMgE,EAAMhE,MAAM1E,OAAS,GAClDuJ,EAAmBL,EAAoBI,GACvCE,EAAiBN,EAAoBvJ,GAGrC,MAAM8J,EAAW3D,EAAY4C,EAAM/G,KAAO,IAAM+H,GAC1CC,EAAeC,EAAmBH,EAAUN,GAElDU,EAAyBlK,EAASgK,GAElChF,EAAeQ,WAAWN,EAAc,CACtCO,iBAAiB,EACjB0E,kBAAkB,EAClBzE,kBAAkB,IAEpBE,EAAqBiD,EAAe3D,EAAc4E,EAAS1D,eAG3D,IAAIgE,EAAUtB,EAAkB5M,IAAI6M,EAAM9M,MACrCmO,IACHA,EAAU,GACVtB,EAAkBvL,IAAIwL,EAAM9M,KAAMmO,IAEpCA,EAAQ3I,KAAK+H,EACf,CACF,KAAO,CACL,MAAMD,EAAqBlD,GAAuB5I,EAAMsL,EAAMzC,KAAMyC,EAAM9M,MACtEsN,IACFM,EAAiBN,EAAoBvJ,GAErCgF,EAAeQ,WAAWN,EAAc,CACtCO,iBAAiB,EACjB0E,kBAAkB,EAClBzE,kBAAkB,IAGpBE,EAAqBiD,EAAe3D,EAAc,GAEtD,CACF,CAGA,IAAK,MAAOjJ,EAAMmO,KAAYtB,EAAmB,CAC/C,MAAMS,EAAqBlD,GAAuB5I,EAAM,MAAOxB,GAC/D,IAAKsN,EAAoB,SAEzB,MAAMrC,EAAWqC,EAAmBc,cAE9B7K,EAAeC,EAAsBxD,GAC3C,IAAKuD,EAAc,SACnB,MAAMM,EAAgBN,EAAaG,oBAAoBG,cACjDwK,EAAeC,EAAgBrD,GAChCoD,GACLA,EAAaE,YAAY,WAAalG,IACpC,MAAMmG,EAAOnG,EAAMxE,GACf8D,MAAM8G,QAAQD,IAChBE,EAAqBF,EAAML,IAGjC,CACA,OAAOvB,CACT,CAmGwB+B,CAAc3L,SAAS6D,KAAMsF,GAGnDlN,EAAI6F,4BAA4B9B,SAAS6D,MAGzC,MAAM+H,EAAiE,GACvE,IAAK,MAAM7G,KAAMjB,EACXiB,EAAG7B,aACL0I,EAAWpJ,KAAK,CAAEuC,KAAIoB,OAAQpB,EAAG7B,WAAYK,KAAMwB,EAAG1B,cACtD0B,EAAGtC,UAQPxG,EAAI0G,oBAAoB3C,SAAS6D,MAGjC,MAAOqC,EAAiBG,GAAeC,EAA4BtG,SAAS6D,MAI5E,IAAK,MAAMtC,KAAQ2E,EACjB,GAAI3E,EAAKiC,WAAaC,KAAKwG,aAAc,CACvC,MAAMlF,EAAKxD,EACNwD,EAAG8G,aAAa,wBACnBC,EAAqBvK,EAAM,MAC3BwD,EAAG7E,aAAa,qBAAsB,IAE1C,MAEE4L,EAAqBvK,EAAM,MAK/B,MAAMwK,EAAiC,GACjCC,EAAqC,GAErCC,EADiBC,EAA0BlM,SAAS6D,MACf0C,WAAWF,GAEtD,IAAK,MAAMU,KAAWkF,EACpB,GAA4B,UAAxBlF,EAAQnG,YACZ,GAAI+E,EAAiBqB,IAAID,EAAQnG,aAC/BoL,EAAmBxJ,KAAKuE,OACnB,IAAIA,EAAQlG,cAAcsL,SAASrB,GAExC,SAEAiB,EAAevJ,KAAKuE,EACtB,CAKF,IAAK,MAAMA,KAAWiF,EACpB,GAA4B,QAAxBjF,EAAQnG,YAAuB,CACjC,MAAMwL,EAAUC,EAAiCtF,GAC3CkB,EAAWlB,EAAQuF,YAAYlB,cAC/BC,EAAeC,EAAgBrD,GACjCoD,GACFA,EAAaE,YAAY,WAAalG,IACpC,MAAMzF,EAAQyF,EAAM0B,EAAQlG,eACxB8D,MAAM8G,QAAQ7L,KAChB2M,EAAuCH,EAASxM,GAEhD4M,EAAqBJ,EAASxM,KAItC,CAOF6M,EAAwB,IAAIV,KAAmBnC,IAG/C,IAAK,MAAM7E,GAAEA,EAAEoB,OAAEA,EAAM5C,KAAEA,KAAUqI,EACjCzF,EAAOhD,aAAa4B,EAAIxB,GAI1B,MAAMmJ,EAAsBlO,EAAKL,iBAAiBO,EAAOC,SAASC,KAClE,IAAK,MAAMoF,KAAW0I,EAAqB,CACzC,MACM/O,EADQqG,EACMnH,aACpB,IAAK,MAAOwB,EAAIsO,KAAYrN,OAAOkC,QAAQ7D,GAAQ,CACjD,MAAMiP,EAASpO,EAAKX,cAAc,qBAAqBQ,OACvD,GAAKuO,EACL,IAAK,MAAOjL,EAAU/B,KAAUN,OAAOkC,QAAQmL,GAC5CC,EAAejL,GAAY/B,CAEhC,CACF,CAGA,MAAMiN,EAAerO,EAAKL,iBAAiB,wBAC3C,IAAK,MAAM4G,KAAM8H,EACf9H,EAAGC,gBAAgB,sBAGrB,OAAO,CACT,ECrdE,SAAA8H,CAAUC,GACR,MAAMvO,EAAOuO,EAAQ7J,WACrB,IAAK1E,EAAM,OAAO,KAClB,MAAMsB,EAAQ7D,EAAIsC,KAAKC,GACvB,IAAKsB,EAAO,OAAO,KACnB,MAAMrC,EAAOqC,EAAMrD,UACnB,OAAO6C,OAAOC,KAAK9B,GAAM2D,OAAS,EAAI3D,EAAO,IAC/C,EACA,kBAAMuP,CAAaD,SACXE,EAAkBF,EAAqC9E,UAC7D,MAAMxL,EAAYR,EAAIgD,iBAAiB8N,GACjCjN,EAAQE,SAASC,cAAcvB,EAAOC,SAASC,KACrDkB,EAAMI,aAAa,UAAW3C,GAC9BtB,EAAI4D,aAAaC,EAAOrD,GACxBsQ,EAAQ7J,YAAYC,aAAarD,EAAOiN,EAC1C,GAGF,IAAIG,IAAY,WAEAC,KACVD,KACJA,IAAY,EACZE,EAAYvE,IACZwE,EAA0BC,IACnBA,EAASrQ,IAAIyB,EAAOC,SAASC,MAChC0O,EAASC,OAAO7O,EAAOC,SAASC,IAAK3C,gBFSzC,MAAMuR,EAAUC,gBAC0B9N,IAAtC6N,EAAQE,KACVF,EAAQE,GAA4BzI,EAExC,CERE0I,GACF,CC5CO,MAAM/O,GAAqB,CAChCgP,KAAM,MACN,OAAAC,GACEV,IACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{g as e,r as t,N as n,a as o}from"../chunks/getAllPropertyDescriptors.js";import{S as s,a as r,D as a,W as i,b as c,g as u,M as l,c as f,d,e as $}from"../chunks/pathDiagnostics.js";import{r as m,L as p,d as h}from"../chunks/errorGuidance.js";import{c as y,d as g,e as w,l as b,f as v}from"../chunks/binder.js";import{g as k,c as O,a as j,s as S,m as A,b as P,r as I,h as E,i as _,d as R,e as x,f as z,w as W,n as M,p as D,j as L,k as N,l as C,o as F,q as G,t as T,u as q,v as U,x as H}from"../chunks/watchRuntime.js";import{i as K}from"../chunks/filterRegistry.js";const Q="[wcs/scan-declaration-invalid]",B=Object.freeze([]);function J(e){return`${s} entry "${e}"`}function V(e,t){for(const n of e.cumulativePaths)if(t.has(n))return n;return null}function X(e,t,n,o){return`[wcs/scan-source-computed] ${e} ${t} "${n}" ${o===n?"is a getter":o.includes(`${i}${i}`)?`is computed by the recursive getter "${o}"`:`is under the getter "${o}"`}. A getter re-evaluates whenever its inputs change, so folding it would count re-evaluations, not events. Fold the plain value the getter reads, or use "on" with an event token.${p}`}function Y(e,t,n){0===n.length&&m(`${Q} ${e} "${t}" must be a non-empty state path.${p}`),n.startsWith("$")&&m(`${Q} ${e} ${t} "${n}" must not start with "$" (reserved namespace).${p}`),n.includes("@")&&m(`${Q} ${e} ${t} "${n}" must not contain "@" — there is a single state tree per root.${p}`),n in Object.prototype&&m(`${Q} ${e} ${t} "${n}" must not be a property name inherited from Object.prototype (e.g. "__proto__", "constructor").${p}`);const o=u(n);for(const s of o.segments)0===s.length&&m(`${Q} ${e} ${t} "${n}" has an empty path segment.${p}`);return o.wildcardCount>l&&m(`${Q} ${e} ${t} "${n}" exceeds the maximum wildcard depth (${l}).`),o}function Z(e,t,n,o){const c=J(e);0===e.length&&m(`${Q} ${s} entry name must be a non-empty string.${p}`),(e.includes(a)||e.includes(i))&&m(`${Q} ${c} must be a flat property name ("${a}" and "${i}" are not allowed). The output is a property the runtime owns.${p}`),e.startsWith("$")&&m(`${Q} ${c} must not start with "$" (reserved namespace).${p}`),e in Object.prototype&&m(`${Q} ${c} must not be a property name inherited from Object.prototype (e.g. "__proto__", "constructor").${p}`),t.has(e)&&m(`${Q} ${c} conflicts with a getter declared on the state.${p}`),n.has(e)&&m(`${Q} ${c} conflicts with a setter declared on the state.${p}`),o.has(e)&&m(`${Q} ${c} conflicts with the ${r} entry of the same name — each output has exactly one owner.${p}`)}function ee(e,t,n){const o=t.get(e);t.has(e)&&o!==n.initial&&!W(e,o)&&m(`${Q} ${J(e)} conflicts with a method (a function-valued property) declared on the state. The output is a property the runtime owns.${p}`)}function te(e,t,n,o,s,r){const i=J(e),u=void 0!==t.from,l=void 0!==t.on;if(u===l&&m(`${Q} ${i} must declare exactly one of "from" (a state path) or "on" (an event-token name).${p}`),l){const e=t.on;return"string"==typeof e&&0!==e.length||m(`${Q} ${i} "on" must be a non-empty event-token name.${p}`),n.has(e)||m(`${Q} ${i} on "${e}" is not declared in ${c}.${h(e,n)}${p}`),{kind:"event",tokenName:e}}const f=t.from;"string"!=typeof f&&m(`${Q} ${i} "from" must be a state path string.${p}`);const d=Y(i,"from",f),$=V(d,o)??r?.recursiveGetterOwning(f)??null;null!==$&&m(X(i,"from",f,$));const y=V(d,s);return null!==y&&m(function(e,t,n){return`${Q} ${e} from "${t}" ${n===t?"is a setter without a getter":`is under the setter without a getter "${n}"`}, so it always reads undefined and every fold would receive undefined. Fold the plain value the setter writes, or use "on" with an event token.${p}`}(i,f,y)),(f===e||f.startsWith(e+a))&&m(`${Q} ${i} from "${f}" reads the entry's own output — the scan would fold its own writes forever.${p}`),{kind:"path",path:f,pathInfo:d}}function ne(e,t,n,o){if(void 0===t)return B;const s=J(e);Array.isArray(t)||m(`${Q} ${s} "resetOn" must be an array of state paths.${p}`);const r=[];for(const e of t){"string"!=typeof e&&m(`${Q} ${s} "resetOn" must contain only state path strings.${p}`);const t=Y(s,"resetOn",e);t.wildcardCount>0&&m(`${Q} ${s} resetOn "${e}" must not contain "${i}" — a reset returns the whole output to "initial".${p}`);const c=V(t,o);null!==c&&m(X(s,"resetOn",e,c)),"path"===n.kind&&e===n.path&&m(`${Q} ${s} resetOn "${e}" is the entry's own "from" — every change would reset instead of fold.${p}`),"path"===n.kind&&e.startsWith(n.path+a)&&m(`${Q} ${s} resetOn "${e}" sits under the entry's own "from" "${n.path}" — every write of "from" also lands it, so the reset would win every time and nothing would fold.${p}`),r.push(e)}return r}function oe(t,n,o=null){const a=t[s];if(void 0===a)return null;("object"!=typeof a||null===a||Array.isArray(a))&&m(`${Q} ${s} must be an object mapping output names to scan definitions ({ from | on, initial, fold, resetOn? }).${p}`);const i=new Set,c=new Set,l=new Set,f=new Map;for(const[n,o]of Object.entries(e(t)))"function"==typeof o.get?i.add(n):"function"==typeof o.set&&l.add(n),"function"==typeof o.set&&c.add(n),"function"==typeof o.value&&f.set(n,o.value);const d=function(e){const t=e[r];return"object"!=typeof t||null===t?new Set:new Set(Object.keys(t))}(t),$=[];let h=0;for(const[e,t]of Object.entries(a)){Z(e,i,c,d),("object"!=typeof t||null===t||Array.isArray(t))&&m(`${Q} ${J(e)} must be an object ({ from | on, initial, fold, resetOn? }).${p}`);const s=t;ee(e,f,s);const r=te(e,s,n,i,l,o);"initial"in s||m(`${Q} ${J(e)} requires "initial" — the seed of the accumulator and the value "resetOn" returns to.${p}`),"function"!=typeof s.fold&&m(`${Q} ${J(e)} fold must be a function.${p}`);const a=ne(e,s.resetOn,r,i);$.push({name:e,source:r,fold:s.fold,initial:s.initial,resetOn:a,order:h++})}return function(e){const t=new Set(e.map(e=>e.name)),n=new Map;for(const o of e){for(const e of o.resetOn){const n=u(e).segments[0];t.has(n)&&m(`${Q} ${J(o.name)} resetOn "${e}" reads the ${s} output "${n}" — a reset driven by an accumulator is a feedback loop. Reset on the plain inputs instead.${p}`)}if("path"===o.source.kind){const e=o.source.pathInfo.segments[0];t.has(e)&&n.set(o.name,e)}}for(const e of n.keys()){const o=[e];let r=n.get(e);for(;void 0!==r&&o.length<=t.size;)r===e&&m(`${Q} ${s} entries ${[...o,e].map(e=>`"${e}"`).join(" → ")} feed each other through "from" — each fold would re-trigger the next forever.${p}`),o.push(r),r=n.get(r)}}($),$.length>0?$:null}function se(e){const t=e.fold;return(n,o,...s)=>{const r=n;let a="read-output";try{const n=r[e.name];a="threw";const i=E(e),c=i&&!_(n,e.initial)?P(e.initial):n,u=t(c,o,...s);if(R(u))return void x(e.name,u);Object.is(u,n)||(a="write",r[e.name]=u,I(e.name,u)),i&&O(e)}catch(t){z(e.name,t,a)}}}const re="scanEntries",ae={order:8,validate(e,t,n){const o=oe(t,n.get("eventTokenNames")??new Set,n.get("recursionRegistry")??null);n.set(re,o)},applyEarly(e,t,n){const o=n.get(re)??null;null!==o&&(function(e,t){for(const n of t)if(!(n.name in e)){const t=P(n.initial);e[n.name]=t,I(n.name,t)}}(t,o),function(e,t){for(const n of t)"event"===n.source.kind&&g(e,n.source.tokenName).subscribe(se(n))}(e,o))},register(e,t,n){const o=n.get(re)??null,s=function(e){const t=new Map,n=k(e);if(void 0!==n)for(const e of n.entries)O(e)&&t.set(e.name,e.resetOn);return j(e),t}(e);e.setScanPaths?.(null===o?null:function(e,t,n){const o=S(e,t);for(const o of t){const t=n.get(o.name);"event"===o.source.kind&&void 0!==t&&o.resetOn.some(n=>t.includes(n)&&y().hasQueuedPath(e,n))&&A(o)}const s=new Set;for(const t of o.byFromPath.keys())s.add(t),e.setPathInfo(t,"prop","scan");for(const t of o.byResetPath.keys())e.setPathInfo(t,"prop","scan");return s.size>0?s:null}(e,o,s))}};let ie=!1;const ce=Object.freeze([]),ue=Object.freeze([]);function le(e,t,n){const o=new Set([n]),s=[n];for(;s.length>0;){const n=s.pop(),r=e.staticDependency.get(n)??ce,a=e.dynamicDependency.get(n)??ce,i=t.byFromPath.get(n)??ue;for(const e of[...r,...a,...i.map(e=>e.name)])o.has(e)||(o.add(e),s.push(e))}return o}const fe=(e,t)=>t,de=new Set;const $e=new WeakMap,me=new WeakMap;function pe(e,t,n){return new Proxy(Object.create(null),{get(t,o){if("string"!=typeof o)return;const s=N(e).get(o);return void 0!==s?n(s):void 0},has:(t,n)=>"string"==typeof n&&N(e).has(n),ownKeys:()=>Array.from(N(e).keys()),getOwnPropertyDescriptor(t,o){if("string"!=typeof o)return;const s=N(e).get(o);return void 0!==s?{configurable:!0,enumerable:!0,value:n(s)}:void 0},set(){m(`${t} namespace is read-only; assigning to it is not allowed.`)},deleteProperty(){m(`${t} namespace is read-only; deleting from it is not allowed.`)}})}function he(e){const t=$e.get(e);if(void 0!==t)return t;const n=pe(e,f,e=>e.status);return $e.set(e,n),n}function ye(e){const t=me.get(e);if(void 0!==t)return t;const n=pe(e,d,e=>e.error);return me.set(e,n),n}function ge(e){$e.delete(e),me.delete(e)}let we=null;function be(e,t){let n=e;for(let e=1;e<t.length;e++){if(Object(n)!==n)return;n=Reflect.get(n,t[e])}return n}const ve={read(e,t){!function(e,t){null!==we&&we.add(b(e,t))}(e,t);const o=t.pathInfo.segments[0];return o===f?be(he(e),t.pathInfo.segments):o===d?be(ye(e),t.pathInfo.segments):n},get:(e,t)=>t===f?he(e.stateElement):t===d?ye(e.stateElement):n};async function ke(e,t,n,o){let s=null,r=null;const a=()=>{if(s&&s!==r){r=s;try{s.return?.()?.then?.(void 0,()=>{})}catch{}}};n.addEventListener("abort",a,{once:!0});try{const r=await e(t,n);if(s=function(e,t){if("function"==typeof e?.getReader)return async function*(e,t){const n=e.getReader(),o=()=>{n.cancel().catch(()=>{})};t.addEventListener("abort",o,{once:!0});try{for(;;){const{done:e,value:t}=await n.read();if(e)return;yield t}}finally{t.removeEventListener("abort",o),n.releaseLock()}}(e,t);if("function"==typeof e?.[Symbol.asyncIterator])return e;throw new TypeError("[@wcstack/state] $streams: source must return an AsyncIterable or a ReadableStream (got neither).")}(r,n)[Symbol.asyncIterator](),n.aborted)return void a();for(;;){const e=await s.next();if(e.done)break;if(n.aborted)return;o.fold(e.value)}if(n.aborted)return;o.done()}catch(e){if(n.aborted)return;o.fail(e)}finally{n.removeEventListener("abort",a)}}function Oe(e){_e();const t=N(e);if(0!==t.size){G(e);for(const n of t.values())je(e,n)}}function je(e,t){t.controller?.abort();const n=new AbortController;t.controller=n;const o=function(e,t){const n=t.definition.args;if(null===n)return void t.depAddresses.clear();const o=we,s=new Set;let i;we=s;try{e.createState("readonly",e=>{i=n(e)})}finally{we=o}i instanceof Promise&&m(`${r} entry "${t.name}" args must be synchronous (it returned a Promise).`);const c=`${f}${a}${t.name}`,u=`${d}${a}${t.name}`;for(const n of s){const o=n.absolutePathInfo.pathInfo;n.absolutePathInfo.stateElement!==e||o.path!==t.name&&o.path!==c&&o.path!==u||m(`${r} entry "${t.name}" args must not read the stream itself ("${o.path}"): a self-dependency would restart the stream on its own writes (infinite loop).`),o.wildcardCount>0&&m(`${r} entry "${t.name}" args must not read wildcard paths ("${o.path}"): wildcard dependencies are out of scope.`)}return t.depAddresses=s,i}(e,t);!function(e,t){const n=k(e);if(void 0!==n&&0!==t.depAddresses.size)for(const o of n.entries){if("path"!==o.source.kind||o.source.pathInfo.segments[0]!==t.name)continue;const a=le(e,n,o.name);for(const e of t.depAddresses){const n=e.absolutePathInfo.pathInfo.path;a.has(n)&&m(`[wcs/scan-feedback-loop] ${r} entry "${t.name}" args read "${n}", which is derived from the ${s} output "${o.name}" that this stream feeds. Every landing would restart the stream on its own result. Advance the cursor from an event ($on) and keep it a plain property instead of deriving it from the accumulator.`)}}}(e,t),e.createState("writable",e=>{e[t.name]=t.definition.initial}),Se(e,t,"active",null);const i=t.definition,c={fold(n){e.createState("writable",e=>{e[t.name]=i.fold(e[t.name],n)})},done(){Se(e,t,"done",null)},fail(o){Se(e,t,"error",o),n.abort()}};ke(i.source,o,n.signal,c)}function Se(e,t,n,o){t.status=n,t.error=o;const s=q(e,t.name),r=s.status!==n,i=!Object.is(s.error,o);(r||i)&&(U(e,t.name,n,o),e.createState("writable",e=>{r&&e.$postUpdate(`${f}${a}${t.name}`),i&&e.$postUpdate(`${d}${a}${t.name}`)}))}function Ae(e){const t=T();if(0===t.size)return;const n=[];for(const o of t)for(const t of N(o).values())for(const s of t.depAddresses)if(e.has(s)){n.push({stateElement:o,entry:t});break}for(const{stateElement:e,entry:o}of n)if(t.has(e)&&N(e).get(o.name)===o)try{je(e,o)}catch(n){o.controller?.abort(),t.has(e)&&N(e).get(o.name)===o&&Se(e,o,"error",n)}}let Pe=!1;const Ie=new WeakMap,Ee={order:20,apply(e,t){ge(e),F(e),function(e,t){const n=t[r];if(void 0===n)return void D(e,de);"object"==typeof n&&null!==n||m(`${r} must be an object mapping stream names to stream definitions.`);const o=new Map;for(const[s,c]of Object.entries(n)){0===s.length&&m(`${r} entry name must be a non-empty string.`),s.includes(a)&&m(`${r} entry "${s}" must be a flat property name ("${a}" is not allowed).`),s.includes(i)&&m(`${r} entry "${s}" must be a flat property name ("${i}" is not allowed).`),s.startsWith("$")&&m(`${r} entry "${s}" must not start with "$" (reserved namespace).`),s in Object.prototype&&m(`${r} entry "${s}" must not be a property name inherited from Object.prototype (e.g. "__proto__", "constructor").`),e.getterPaths.has(s)&&m(`${r} entry "${s}" conflicts with a getter declared on the state.`),e.setterPaths.has(s)&&m(`${r} entry "${s}" conflicts with a setter declared on the state.`),"object"==typeof c&&null!==c||m(`${r} entry "${s}" must be an object ({ args?, source, fold?, initial? }).`);const n=c;"function"!=typeof n.source&&m(`${r} entry "${s}" source must be a function.`);const u=void 0!==n.fold;u&&"function"!=typeof n.fold&&m(`${r} entry "${s}" fold must be a function.`),u&&!("initial"in n)&&m(`${r} entry "${s}" requires "initial" when fold is specified (reduce needs a seed value).`),void 0!==n.args&&"function"!=typeof n.args&&m(`${r} entry "${s}" args must be a function.`);const l={name:s,definition:{args:n.args??null,source:n.source,fold:n.fold??fe,initial:n.initial},status:"idle",error:null,controller:null,depAddresses:new Set};s in t||(t[s]=l.definition.initial),o.set(s,l)}L(e,o),D(e,new Set(o.keys()))}(e,t),void 0!==t[r]&&e.attachAddressHooks?.("streams",r)},activate(e,t){if(!K()&&null!=e.connectedRootNode){if(null===t){if(!0!==e.initialized)return;return Oe(e),void Ie.set(e,e.connectGeneration??0)}t===e.connectGeneration&&Ie.get(e)!==t&&Oe(e)}},deactivate(e){C(e),ge(e)}};function _e(){Pe||(Pe=!0,o("streams",ve),t("streams",Ee),v(Ae,$))}const Re={name:"temporal",install(){H(),ie||(ie=!0,t("scan",ae),w(M)),_e()}};export{Re as default,Re as temporal};
|
|
1
|
+
import{g as e,r as t,N as n,a as o}from"../chunks/getAllPropertyDescriptors.js";import{S as s,a as r,D as a,W as i,b as c,g as u,M as l,c as f,d,e as $}from"../chunks/pathDiagnostics.js";import{n as m}from"../chunks/declarationAliases.js";import{r as p,L as h,d as y}from"../chunks/errorGuidance.js";import{c as g,d as w,e as b,l as v,f as k}from"../chunks/binder.js";import{g as j,c as O,a as S,s as A,m as P,b as I,r as E,h as _,i as R,d as x,e as z,f as W,w as M,n as D,p as L,j as N,k as C,l as F,o as G,q as T,t as q,u as U,v as H,x as K}from"../chunks/watchRuntime.js";import{i as Q}from"../chunks/filterRegistry.js";const B="[wcs/scan-declaration-invalid]",J=Object.freeze([]);function V(e){return`${s} entry "${e}"`}function X(e,t){for(const n of e.cumulativePaths)if(t.has(n))return n;return null}function Y(e,t,n,o){return`[wcs/scan-source-computed] ${e} ${t} "${n}" ${o===n?"is a getter":o.includes(`${i}${i}`)?`is computed by the recursive getter "${o}"`:`is under the getter "${o}"`}. A getter re-evaluates whenever its inputs change, so folding it would count re-evaluations, not events. Fold the plain value the getter reads, or use "on" with an event token.${h}`}function Z(e,t,n){0===n.length&&p(`${B} ${e} "${t}" must be a non-empty state path.${h}`),n.startsWith("$")&&p(`${B} ${e} ${t} "${n}" must not start with "$" (reserved namespace).${h}`),n.includes("@")&&p(`${B} ${e} ${t} "${n}" must not contain "@" — there is a single state tree per root.${h}`),n in Object.prototype&&p(`${B} ${e} ${t} "${n}" must not be a property name inherited from Object.prototype (e.g. "__proto__", "constructor").${h}`);const o=u(n);for(const s of o.segments)0===s.length&&p(`${B} ${e} ${t} "${n}" has an empty path segment.${h}`);return o.wildcardCount>l&&p(`${B} ${e} ${t} "${n}" exceeds the maximum wildcard depth (${l}).`),o}function ee(e,t,n,o){const c=V(e);0===e.length&&p(`${B} ${s} entry name must be a non-empty string.${h}`),(e.includes(a)||e.includes(i))&&p(`${B} ${c} must be a flat property name ("${a}" and "${i}" are not allowed). The output is a property the runtime owns.${h}`),e.startsWith("$")&&p(`${B} ${c} must not start with "$" (reserved namespace).${h}`),e in Object.prototype&&p(`${B} ${c} must not be a property name inherited from Object.prototype (e.g. "__proto__", "constructor").${h}`),t.has(e)&&p(`${B} ${c} conflicts with a getter declared on the state.${h}`),n.has(e)&&p(`${B} ${c} conflicts with a setter declared on the state.${h}`),o.has(e)&&p(`${B} ${c} conflicts with the ${r} entry of the same name — each output has exactly one owner.${h}`)}function te(e,t,n){const o=t.get(e);t.has(e)&&o!==n.initial&&!M(e,o)&&p(`${B} ${V(e)} conflicts with a method (a function-valued property) declared on the state. The output is a property the runtime owns.${h}`)}function ne(e,t,n,o,s,r){const i=V(e),u=void 0!==t.from,l=void 0!==t.on;if(u===l&&p(`${B} ${i} must declare exactly one of "from" (a state path) or "on" (an event-token name).${h}`),l){const e=t.on;return"string"==typeof e&&0!==e.length||p(`${B} ${i} "on" must be a non-empty event-token name.${h}`),n.has(e)||p(`${B} ${i} on "${e}" is not declared in ${c}.${y(e,n)}${h}`),{kind:"event",tokenName:e}}const f=t.from;"string"!=typeof f&&p(`${B} ${i} "from" must be a state path string.${h}`);const d=Z(i,"from",f),$=X(d,o)??r?.recursiveGetterOwning(f)??null;null!==$&&p(Y(i,"from",f,$));const m=X(d,s);return null!==m&&p(function(e,t,n){return`${B} ${e} from "${t}" ${n===t?"is a setter without a getter":`is under the setter without a getter "${n}"`}, so it always reads undefined and every fold would receive undefined. Fold the plain value the setter writes, or use "on" with an event token.${h}`}(i,f,m)),(f===e||f.startsWith(e+a))&&p(`${B} ${i} from "${f}" reads the entry's own output — the scan would fold its own writes forever.${h}`),{kind:"path",path:f,pathInfo:d}}function oe(e,t,n,o){if(void 0===t)return J;const s=V(e);Array.isArray(t)||p(`${B} ${s} "resetOn" must be an array of state paths.${h}`);const r=[];for(const e of t){"string"!=typeof e&&p(`${B} ${s} "resetOn" must contain only state path strings.${h}`);const t=Z(s,"resetOn",e);t.wildcardCount>0&&p(`${B} ${s} resetOn "${e}" must not contain "${i}" — a reset returns the whole output to "initial".${h}`);const c=X(t,o);null!==c&&p(Y(s,"resetOn",e,c)),"path"===n.kind&&e===n.path&&p(`${B} ${s} resetOn "${e}" is the entry's own "from" — every change would reset instead of fold.${h}`),"path"===n.kind&&e.startsWith(n.path+a)&&p(`${B} ${s} resetOn "${e}" sits under the entry's own "from" "${n.path}" — every write of "from" also lands it, so the reset would win every time and nothing would fold.${h}`),r.push(e)}return r}function se(t,n,o=null){const a=t[s];if(void 0===a)return null;("object"!=typeof a||null===a||Array.isArray(a))&&p(`${B} ${s} must be an object mapping output names to scan definitions ({ from | on, initial, fold, resetOn? }).${h}`);const i=new Set,c=new Set,l=new Set,f=new Map;for(const[n,o]of Object.entries(e(t)))"function"==typeof o.get?i.add(n):"function"==typeof o.set&&l.add(n),"function"==typeof o.set&&c.add(n),"function"==typeof o.value&&f.set(n,o.value);const d=function(e){m(e);const t=e[r];return"object"!=typeof t||null===t?new Set:new Set(Object.keys(t))}(t),$=[];let y=0;for(const[e,t]of Object.entries(a)){ee(e,i,c,d),("object"!=typeof t||null===t||Array.isArray(t))&&p(`${B} ${V(e)} must be an object ({ from | on, initial, fold, resetOn? }).${h}`);const s=t;te(e,f,s);const r=ne(e,s,n,i,l,o);"initial"in s||p(`${B} ${V(e)} requires "initial" — the seed of the accumulator and the value "resetOn" returns to.${h}`),"function"!=typeof s.fold&&p(`${B} ${V(e)} fold must be a function.${h}`);const a=oe(e,s.resetOn,r,i);$.push({name:e,source:r,fold:s.fold,initial:s.initial,resetOn:a,order:y++})}return function(e){const t=new Set(e.map(e=>e.name)),n=new Map;for(const o of e){for(const e of o.resetOn){const n=u(e).segments[0];t.has(n)&&p(`${B} ${V(o.name)} resetOn "${e}" reads the ${s} output "${n}" — a reset driven by an accumulator is a feedback loop. Reset on the plain inputs instead.${h}`)}if("path"===o.source.kind){const e=o.source.pathInfo.segments[0];t.has(e)&&n.set(o.name,e)}}for(const e of n.keys()){const o=[e];let r=n.get(e);for(;void 0!==r&&o.length<=t.size;)r===e&&p(`${B} ${s} entries ${[...o,e].map(e=>`"${e}"`).join(" → ")} feed each other through "from" — each fold would re-trigger the next forever.${h}`),o.push(r),r=n.get(r)}}($),$.length>0?$:null}function re(e){const t=e.fold;return(n,o,...s)=>{const r=n;let a="read-output";try{const n=r[e.name];a="threw";const i=_(e),c=i&&!R(n,e.initial)?I(e.initial):n,u=t(c,o,...s);if(x(u))return void z(e.name,u);Object.is(u,n)||(a="write",r[e.name]=u,E(e.name,u)),i&&O(e)}catch(t){W(e.name,t,a)}}}const ae="scanEntries",ie={order:8,validate(e,t,n){const o=se(t,n.get("eventTokenNames")??new Set,n.get("recursionRegistry")??null);n.set(ae,o)},applyEarly(e,t,n){const o=n.get(ae)??null;null!==o&&(function(e,t){for(const n of t)if(!(n.name in e)){const t=I(n.initial);e[n.name]=t,E(n.name,t)}}(t,o),function(e,t){for(const n of t)"event"===n.source.kind&&w(e,n.source.tokenName).subscribe(re(n))}(e,o))},register(e,t,n){const o=n.get(ae)??null,s=function(e){const t=new Map,n=j(e);if(void 0!==n)for(const e of n.entries)O(e)&&t.set(e.name,e.resetOn);return S(e),t}(e);e.setScanPaths?.(null===o?null:function(e,t,n){const o=A(e,t);for(const o of t){const t=n.get(o.name);"event"===o.source.kind&&void 0!==t&&o.resetOn.some(n=>t.includes(n)&&g().hasQueuedPath(e,n))&&P(o)}const s=new Set;for(const t of o.byFromPath.keys())s.add(t),e.setPathInfo(t,"prop","scan");for(const t of o.byResetPath.keys())e.setPathInfo(t,"prop","scan");return s.size>0?s:null}(e,o,s))}};let ce=!1;const ue=Object.freeze([]),le=Object.freeze([]);function fe(e,t,n){const o=new Set([n]),s=[n];for(;s.length>0;){const n=s.pop(),r=e.staticDependency.get(n)??ue,a=e.dynamicDependency.get(n)??ue,i=t.byFromPath.get(n)??le;for(const e of[...r,...a,...i.map(e=>e.name)])o.has(e)||(o.add(e),s.push(e))}return o}const de=(e,t)=>t,$e=new Set;const me=new WeakMap,pe=new WeakMap;function he(e,t,n){return new Proxy(Object.create(null),{get(t,o){if("string"!=typeof o)return;const s=C(e).get(o);return void 0!==s?n(s):void 0},has:(t,n)=>"string"==typeof n&&C(e).has(n),ownKeys:()=>Array.from(C(e).keys()),getOwnPropertyDescriptor(t,o){if("string"!=typeof o)return;const s=C(e).get(o);return void 0!==s?{configurable:!0,enumerable:!0,value:n(s)}:void 0},set(){p(`${t} namespace is read-only; assigning to it is not allowed.`)},deleteProperty(){p(`${t} namespace is read-only; deleting from it is not allowed.`)}})}function ye(e){const t=me.get(e);if(void 0!==t)return t;const n=he(e,f,e=>e.status);return me.set(e,n),n}function ge(e){const t=pe.get(e);if(void 0!==t)return t;const n=he(e,d,e=>e.error);return pe.set(e,n),n}function we(e){me.delete(e),pe.delete(e)}let be=null;function ve(e,t){let n=e;for(let e=1;e<t.length;e++){if(Object(n)!==n)return;n=Reflect.get(n,t[e])}return n}const ke={read(e,t){!function(e,t){null!==be&&be.add(v(e,t))}(e,t);const o=t.pathInfo.segments[0];return o===f?ve(ye(e),t.pathInfo.segments):o===d?ve(ge(e),t.pathInfo.segments):n},get:(e,t)=>t===f?ye(e.stateElement):t===d?ge(e.stateElement):n};async function je(e,t,n,o){let s=null,r=null;const a=()=>{if(s&&s!==r){r=s;try{s.return?.()?.then?.(void 0,()=>{})}catch{}}};n.addEventListener("abort",a,{once:!0});try{const r=await e(t,n);if(s=function(e,t){if("function"==typeof e?.getReader)return async function*(e,t){const n=e.getReader(),o=()=>{n.cancel().catch(()=>{})};t.addEventListener("abort",o,{once:!0});try{for(;;){const{done:e,value:t}=await n.read();if(e)return;yield t}}finally{t.removeEventListener("abort",o),n.releaseLock()}}(e,t);if("function"==typeof e?.[Symbol.asyncIterator])return e;throw new TypeError("[@wcstack/state] $streams: source must return an AsyncIterable or a ReadableStream (got neither).")}(r,n)[Symbol.asyncIterator](),n.aborted)return void a();for(;;){const e=await s.next();if(e.done)break;if(n.aborted)return;o.fold(e.value)}if(n.aborted)return;o.done()}catch(e){if(n.aborted)return;o.fail(e)}finally{n.removeEventListener("abort",a)}}function Oe(e){Re();const t=C(e);if(0!==t.size){T(e);for(const n of t.values())Se(e,n)}}function Se(e,t){t.controller?.abort();const n=new AbortController;t.controller=n;const o=function(e,t){const n=t.definition.args;if(null===n)return void t.depAddresses.clear();const o=be,s=new Set;let i;be=s;try{e.createState("readonly",e=>{i=n(e)})}finally{be=o}i instanceof Promise&&p(`${r} entry "${t.name}" args must be synchronous (it returned a Promise).`);const c=`${f}${a}${t.name}`,u=`${d}${a}${t.name}`;for(const n of s){const o=n.absolutePathInfo.pathInfo;n.absolutePathInfo.stateElement!==e||o.path!==t.name&&o.path!==c&&o.path!==u||p(`${r} entry "${t.name}" args must not read the stream itself ("${o.path}"): a self-dependency would restart the stream on its own writes (infinite loop).`),o.wildcardCount>0&&p(`${r} entry "${t.name}" args must not read wildcard paths ("${o.path}"): wildcard dependencies are out of scope.`)}return t.depAddresses=s,i}(e,t);!function(e,t){const n=j(e);if(void 0!==n&&0!==t.depAddresses.size)for(const o of n.entries){if("path"!==o.source.kind||o.source.pathInfo.segments[0]!==t.name)continue;const a=fe(e,n,o.name);for(const e of t.depAddresses){const n=e.absolutePathInfo.pathInfo.path;a.has(n)&&p(`[wcs/scan-feedback-loop] ${r} entry "${t.name}" args read "${n}", which is derived from the ${s} output "${o.name}" that this stream feeds. Every landing would restart the stream on its own result. Advance the cursor from an event ($on) and keep it a plain property instead of deriving it from the accumulator.`)}}}(e,t),e.createState("writable",e=>{e[t.name]=t.definition.initial}),Ae(e,t,"active",null);const i=t.definition,c={fold(n){e.createState("writable",e=>{e[t.name]=i.fold(e[t.name],n)})},done(){Ae(e,t,"done",null)},fail(o){Ae(e,t,"error",o),n.abort()}};je(i.source,o,n.signal,c)}function Ae(e,t,n,o){t.status=n,t.error=o;const s=U(e,t.name),r=s.status!==n,i=!Object.is(s.error,o);(r||i)&&(H(e,t.name,n,o),e.createState("writable",e=>{r&&e.$postUpdate(`${f}${a}${t.name}`),i&&e.$postUpdate(`${d}${a}${t.name}`)}))}function Pe(e){const t=q();if(0===t.size)return;const n=[];for(const o of t)for(const t of C(o).values())for(const s of t.depAddresses)if(e.has(s)){n.push({stateElement:o,entry:t});break}for(const{stateElement:e,entry:o}of n)if(t.has(e)&&C(e).get(o.name)===o)try{Se(e,o)}catch(n){o.controller?.abort(),t.has(e)&&C(e).get(o.name)===o&&Ae(e,o,"error",n)}}let Ie=!1;const Ee=new WeakMap,_e={order:20,apply(e,t){we(e),G(e),function(e,t){m(t);const n=t[r];if(void 0===n)return void L(e,$e);"object"==typeof n&&null!==n||p(`${r} must be an object mapping stream names to stream definitions.`);const o=new Map;for(const[s,c]of Object.entries(n)){0===s.length&&p(`${r} entry name must be a non-empty string.`),s.includes(a)&&p(`${r} entry "${s}" must be a flat property name ("${a}" is not allowed).`),s.includes(i)&&p(`${r} entry "${s}" must be a flat property name ("${i}" is not allowed).`),s.startsWith("$")&&p(`${r} entry "${s}" must not start with "$" (reserved namespace).`),s in Object.prototype&&p(`${r} entry "${s}" must not be a property name inherited from Object.prototype (e.g. "__proto__", "constructor").`),e.getterPaths.has(s)&&p(`${r} entry "${s}" conflicts with a getter declared on the state.`),e.setterPaths.has(s)&&p(`${r} entry "${s}" conflicts with a setter declared on the state.`),"object"==typeof c&&null!==c||p(`${r} entry "${s}" must be an object ({ args?, source, fold?, initial? }).`);const n=c;"function"!=typeof n.source&&p(`${r} entry "${s}" source must be a function.`);const u=void 0!==n.fold;u&&"function"!=typeof n.fold&&p(`${r} entry "${s}" fold must be a function.`),u&&!("initial"in n)&&p(`${r} entry "${s}" requires "initial" when fold is specified (reduce needs a seed value).`),void 0!==n.args&&"function"!=typeof n.args&&p(`${r} entry "${s}" args must be a function.`);const l={name:s,definition:{args:n.args??null,source:n.source,fold:n.fold??de,initial:n.initial},status:"idle",error:null,controller:null,depAddresses:new Set};s in t||(t[s]=l.definition.initial),o.set(s,l)}N(e,o),L(e,new Set(o.keys()))}(e,t),void 0!==t[r]&&e.attachAddressHooks?.("streams",r)},activate(e,t){if(!Q()&&null!=e.connectedRootNode){if(null===t){if(!0!==e.initialized)return;return Oe(e),void Ee.set(e,e.connectGeneration??0)}t===e.connectGeneration&&Ee.get(e)!==t&&Oe(e)}},deactivate(e){F(e),we(e)}};function Re(){Ie||(Ie=!0,o("streams",ke),t("streams",_e),k(Pe,$))}const xe={name:"temporal",install(){K(),ce||(ce=!0,t("scan",ie),b(D)),Re()}};export{xe as default,xe as temporal};
|
|
2
2
|
//# sourceMappingURL=temporal.js.map
|