vertigo 0.13.1

Reactive Real-DOM library with SSR for Rust
Documentation
1
2
const e=new TextDecoder("utf-8"),t=new TextEncoder;class n{constructor(e,t){this.getUint8Memory=e,this.pointer=0,this.ptr=Number(t>>32n),this.size=Number(t%2n**32n),this.dataView=new DataView(this.getUint8Memory().buffer,this.ptr,this.size)}getByte(){const e=this.dataView.getUint8(this.pointer);return this.pointer+=1,e}setByte(e){this.dataView.setUint8(this.pointer,e),this.pointer+=1}getU16(){const e=this.dataView.getUint16(this.pointer);return this.pointer+=2,e}setU16(e){this.dataView.setUint16(this.pointer,e),this.pointer+=2}getU32(){const e=this.dataView.getUint32(this.pointer);return this.pointer+=4,e}setU32(e){this.dataView.setUint32(this.pointer,e),this.pointer+=4}getF64(){const e=this.dataView.getFloat64(this.pointer);return this.pointer+=8,e}setF64(e){this.dataView.setFloat64(this.pointer,e),this.pointer+=8}getBuffer(){const e=this.getU32(),t=this.getUint8Memory().subarray(this.ptr+this.pointer,this.ptr+this.pointer+e);return this.pointer+=e,t}setBuffer(e){const t=e.length;this.setU32(t);this.getUint8Memory().subarray(this.ptr+this.pointer,this.ptr+this.pointer+t).set(e),this.pointer+=t}getString(){return e.decode(this.getBuffer())}setString(e){const n=t.encode(e);this.setBuffer(n)}}const o=1,s=2,r=3,i=4,a=5,c=6,l=7,d=8,h=9,u=e=>{if(!0===e||!1===e||null==e)return 1;if("string"==typeof e)return 5+t.encode(e).length;if("number"==typeof e)return 9;if(e instanceof Uint8Array)return 5+e.length;if(Array.isArray(e)){let t=5;for(const n of e)t+=u(n);return t}if("object"==typeof e&&null!==e){let n=3;for(const[o,s]of Object.entries(e))n+=4+t.encode(o).length,n+=u(s);return n}throw new Error("jsJsonGetSize: Unknown type "+typeof e)},m=e=>{const t=e.getByte();if(t===o)return!0;if(t===s)return!1;if(t===r)return null;if(t!==i){if(t===a)return e.getString();if(t===c)return e.getF64();if(t===l){const t=e.getU32(),n=[];for(let o=0;o<t;o++)n.push(m(e));return n}if(t===d){const t=e.getU16(),n={};for(let o=0;o<t;o++){const t=e.getString(),o=m(e);n[t]=o}return n}if(t===h)return e.getBuffer().slice();throw new Error(`jsJsonDecodeItem: Unknown type id ${t}`)}},f=(e,t)=>{if(!0!==e)if(!1!==e)if(null!==e)if(void 0!==e){if("string"==typeof e)return t.setByte(a),void t.setString(e);if("number"==typeof e)return t.setByte(c),void t.setF64(e);if(e instanceof Uint8Array)return t.setByte(h),void t.setBuffer(e);if(!Array.isArray(e)){if("object"==typeof e&&null!==e){const n=Object.entries(e);t.setByte(d),t.setU16(n.length);for(const[e,o]of n)t.setString(e),f(o,t);return}throw new Error("saveJsJsonToBufferItem: Unknown type "+typeof e)}t.setByte(l),t.setU32(e.length);for(const n of e)f(n,t)}else t.setByte(i);else t.setByte(r);else t.setByte(s);else t.setByte(o)},g=async(e,t)=>{const o=await(async(e,t)=>{if("function"==typeof WebAssembly.instantiateStreaming){const n=fetch(e);try{return await WebAssembly.instantiateStreaming(n,t)}catch(e){console.warn("`WebAssembly.instantiateStreaming` failed. This could happen if your server does not serve wasm with `application/wasm` MIME type, but check the original error too. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",e)}}console.info("fetchModule by WebAssembly.instantiate");const n=await fetch(e),o=await n.arrayBuffer();return await WebAssembly.instantiate(o,t)})(e,t);let s=new Uint8Array(1);const r=()=>{if(o.instance.exports.memory instanceof WebAssembly.Memory)return s.buffer!==o.instance.exports.memory.buffer&&(s=new Uint8Array(o.instance.exports.memory.buffer)),s;throw Error("Missing memory")},i=o.instance.exports;return{exports:i,getUint8Memory:r,wasmCommand:e=>{const t=u(e),o=i.vertigo_export_alloc_block(t),s=new n(r,o);f(e,s);let a=i.vertigo_export_wasm_command(o);if(0n===a)return null;const c=new n(r,a),l=m(c);return i.vertigo_export_free_block(a),l}}};class p{constructor(){this.events=new Set}on(e){let t=!0;const n=n=>{t&&e(n)};return this.events.add(n),()=>{t=!1,this.events.delete(n)}}trigger(e){const t=Array.from(this.events.values());for(const n of t)try{n(e)}catch(e){console.error(e)}}}class v{constructor(){this.inner=null,this.resolve=e=>{const t=this.inner;this.inner=null,null!==t&&t.resolve(e)},this.isFulfilled=()=>null===this.inner;const[e,t]=(()=>{let e=null,t=null;const n=new Promise((n,o)=>{e=n,t=o});if(null===e)throw Error("createPromiseValue - resolve is null");if(null===t)throw Error("createPromiseValue - reject is null");return[{resolve:e,reject:t},n]})();this.inner=e,this.promise=t}}const w=async(e,t)=>{console.info(`${e} wait ${t}ms`),await(async e=>new Promise(t=>{setTimeout(t,e)}))(t),console.info(`${e} go forth`)};class y{constructor(e){this.host=e,this.formatLog=e=>`Socket ${this.host} ==> ${e}`}}class b{constructor(e,t){this.eventMessage=new p,this.close=e,this.send=t}static connect(e,t,n){const o=new v,s=new v,r=new WebSocket(t);let i=!1;console.info(e.formatLog("starting ..."));const a=()=>{i||(console.info(e.formatLog("close")),i=!0,o.resolve(null),s.resolve(),r.close())},c=new b(a,e=>{i||r.send(e)});setTimeout(()=>{!1===o.isFulfilled()&&(console.error(e.formatLog(`timeout (${n}ms)`)),a())},n);return r.addEventListener("open",()=>{console.info(e.formatLog("open")),o.resolve(c)}),r.addEventListener("error",t=>{console.error(e.formatLog("error"),t),a()}),r.addEventListener("close",a),r.addEventListener("message",t=>{if(i)return;const n=t.data;"string"!=typeof n?console.error(e.formatLog("onMessage - expected string"),n):c.eventMessage.trigger(n)}),{socket:o.promise,done:s.promise}}static startSocket(e,t,n,o){let s=!0,r=null;const i=new y(e);return(async()=>{for(;s;){const a=b.connect(i,e,t),c=await a.socket;if(null!==c){if(r=c,o({type:"socket",socket:c}),c.eventMessage.on(e=>{o({type:"message",message:e})}),await a.done,o({type:"close"}),!s)return void console.info(i.formatLog("disconnect (1)"));await w(i.formatLog("reconnect after close"),n)}else await w(i.formatLog("reconnect after error"),n)}console.info(i.formatLog("disconnect (2)"))})().catch(e=>{console.error(e)}),{send:e=>{null===r?console.error("send fail - missing connection",e):r.send(e)},dispose:()=>{s=!1,r?.close()}}}}const k=e=>{try{return JSON.parse(e)}catch{throw console.error("Failed to parse websocket message",e),Error(e)}},E=(e,t,n)=>{e.wasmCommand({Websocket:{callback:t,message:n}})};class C{constructor(e){this.websocket_register_callback=(e,t)=>{const n=this.getWasm();let o=b.startSocket(e,5e3,3e3,e=>{if(!1!==this.controllerList.has(t)){if("socket"===e.type)return this.socket.set(t,e.socket),void E(n,t,"Connected");if("message"!==e.type)return"close"===e.type?(this.socket.delete(t),void E(n,t,"Disconnected")):(e=>{throw console.error(e),Error("unknown message")})(e);E(n,t,{Message:{message:k(e.message)}})}});this.controllerList.set(t,o)},this.websocket_unregister_callback=e=>{const t=this.controllerList.get(e);void 0!==t?(t.dispose(),this.controllerList.delete(e)):console.error("Expected controller")},this.websocket_send_message=(e,t)=>{const n=this.socket.get(e);var o;void 0===n?console.error(`Missing socket connection for callback_id=${e}`):n.send((o=t,JSON.stringify(o)))},this.getWasm=e,this.controllerList=new Map,this.socket=new Map}}const x=e=>{const t={};for(const{k:n,v:o}of e)t[n]=o;return t},T=e=>{if("None"!==e)return JSON.stringify(e.Data.data)},N=async e=>{const t=e.status,n=e.headers.get("Content-Type");try{if(n?.startsWith("text/plain;"))return{Ok:{status:t,response:{Text:await e.text()}}};return{Ok:{status:t,response:{Json:0===(o=await e.text()).length?null:JSON.parse(o)}}}}catch(e){return{Err:{message:String(e)}}}var o};class _{constructor(e){this.timerSet=(e,t,n)=>{switch(n){case"Interval":{const n=setInterval(()=>{this.getWasm().wasmCommand({TimerCall:{callback:e}})},t);this.data.set(e,{kind:"Interval",timerId:n});break}case"Timeout":{const n=setTimeout(()=>{this.getWasm().wasmCommand({TimerCall:{callback:e}})},t);this.data.set(e,{kind:"Timeout",timerId:n});break}}},this.timerClear=e=>{const t=this.data.get(e);if(void 0===t)throw Error("panic");switch(t.kind){case"Interval":clearInterval(t.timerId);break;case"Timeout":clearTimeout(t.timerId)}},this.getWasm=e,this.data=new Map}}class A{constructor(e,t,n,o,s){this.getWasm=e,this.get=n,this.pushValue=o,this.replaceValue=s,this.callback=new Map,this.trigger=()=>{for(const e of Array.from(this.callback.values()))e()},this.add=e=>{this.callback.set(e,()=>{this.getWasm().wasmCommand({LocationCall:{callback:e,value:this.get()}})})},this.remove=e=>{this.callback.delete(e)},this.push=e=>{this.get()!==e&&this.pushValue(e,this.trigger)},this.replace=e=>{this.get()!==e&&this.replaceValue(e,this.trigger)},window.addEventListener(t,this.trigger)}}class S{constructor(e){this.callback=(e,t,n)=>{switch(t){case"Add":return void this.locations[e].add(n);case"Remove":return void this.locations[e].remove(n)}},this.set=(e,t,n)=>{switch(t){case"Push":return void this.locations[e].push(n);case"Replace":return void this.locations[e].replace(n)}},this.get=e=>this.locations[e].get(),this.locations={Hash:new A(e,"hashchange",()=>decodeURIComponent(location.hash.substr(1)),(e,t)=>{location.hash=e,t()},e=>{history.replaceState(null,"",`#${e}`)}),History:new A(e,"popstate",()=>window.location.pathname+window.location.search+window.location.hash,(e,t)=>{window.history.pushState(null,"",e),t()},(e,t)=>{window.history.replaceState(null,"",e),t()})}}}class L{constructor(){this.get=e=>{for(const t of document.cookie.split(";")){if(""===t)continue;const n=t.trim().split("=");if(2!==n.length){console.warn(`Cookies.get: Incorrect number of cookieChunk => ${n.length} in ${t}`);continue}const o=n[0],s=n[1];if(void 0!==o&&void 0!==s){if(o===e)return decodeURIComponent(s)}else console.warn(`Cookies.get: Broken cookie part => ${t}`)}return""},this.getJson=e=>{let t=this.get(e);if(0!==t.length)try{return JSON.parse(t)}catch(e){console.error("Error deserializing cookie",e)}return null},this.set=(e,t,n)=>{const o=null==t?"":encodeURIComponent(t),s=new Date;s.setTime(s.getTime()+1e3*n);let r="expires="+s.toUTCString();document.cookie=`${e}=${o};${r};path=/; samesite=Strict`},this.setJson=(e,t,n)=>{let o=JSON.stringify(t);this.set(e,o,n)}}}const $=(e,t)=>{const n=t-e+1;return e+Math.floor(Math.random()*n)},M=e=>e.arrayBuffer().then(t=>({name:e.name,data:new Uint8Array(t)}));const R=(e,t,n)=>{Promise.all(e).then(e=>{const n=[];for(const t of e)n.push([t.name,Array.from(t.data)]);t([n])}).catch(e=>{console.error(n,e)})},I=(e,t)=>{t(void 0)},U=(e,t)=>{e.preventDefault(),t(void 0)},B=(e,t)=>{t(void 0)&&e.preventDefault()},O=e=>(t,n)=>{const o=t.target;o instanceof HTMLInputElement||o instanceof HTMLTextAreaElement||e&&o instanceof HTMLSelectElement?n(o.value):console.warn("event input ignore",o)},W=(e,t)=>{if(e instanceof KeyboardEvent){return void(!0===t([e.key,e.code,e.altKey,e.ctrlKey,e.shiftKey,e.metaKey])&&(e.preventDefault(),e.stopPropagation()))}console.warn("keydown ignore",e)},D={click:(e,t)=>{e.preventDefault();let n=t(void 0);null===n||"object"!=typeof n||Array.isArray(n)||("stop_propagation"in n&&!0===n.stop_propagation&&e.stopPropagation(),"prevent_default"in n&&!0===n.prevent_default&&e.preventDefault())},submit:U,input:O(!1),change:O(!0),blur:I,mousedown:B,mouseup:B,mouseenter:I,mouseleave:I,keydown:W,hook_keydown:W,drop:(e,t)=>{if(e.preventDefault(),e instanceof DragEvent)if(null===e.dataTransfer)console.error("dom -> drop -> dataTransfer null");else{const n=function(e){const t=[];for(let n=0;n<e.length;n++){const o=e[n];if(void 0===o)console.error("dom -> drop -> item - undefined");else{const e=o.getAsFile();null===e?console.error(`dom -> drop -> index:${n} -> It's not a file`):t.push(M(e))}}return t}(e.dataTransfer.items);n.length?R(n,t,"callback_drop -> promise.all -> "):console.error("No files to send")}else console.warn("event drop ignore",e)},load:U,change_file:(e,t)=>{const n=e.target;if(n instanceof HTMLInputElement&&null!==n.files&&n.files.length>0){const e=[];for(let t=0;t<n.files.length;t++){const o=n.files[t];void 0!==o&&e.push(M(o))}return e.length>0&&R(e,t,"changeFile ->"),void(n.value="")}console.warn("changeFile: not a file input or no files",n)}};class F{constructor(e){this.getWasm=e,this.callbacks=new Map,this.observers=new Map}add(e,t,n,o){if("intersect"===n)return this.intersectAdd(e,t,o);const s=e=>this.wasmCallback(o,e),r=e=>{const t=D[n];void 0!==t?t(e,s):console.error(`No support for the event ${n}`)};if(this.callbacks.has(o))console.error(`There was already a callback added with the callback_id=${o}`);else if(this.callbacks.set(o,r),"hook_keydown"===n)document.addEventListener("keydown",r,!1);else{const o=e.get("callback_add",t),s="change_file"===n?"change":n;o.addEventListener(s,r,!1)}}remove(e,t,n,o){if("intersect"===n)return this.intersectRemove(o);const s=this.callbacks.get(o);if(this.callbacks.delete(o),void 0!==s)if("hook_keydown"===n)document.removeEventListener("keydown",s);else{const o="change_file"===n?"change":n;e.get("callback_remove",t).removeEventListener(o,s)}else console.error(`The callback is missing with the id=${o}`)}wasmCallback(e,t){return this.getWasm().wasmCommand({CallbackCall:{callback_id:e,value:t}})}intersectAdd(e,t,n){if(this.observers.has(n))return void console.error(`There was already an intersect observer added with the callback_id=${n}`);const o=e.getNode("callback_add",t),s=new IntersectionObserver(e=>{for(const t of e)this.wasmCallback(n,[t.isIntersecting,t.intersectionRatio,t.boundingClientRect.top,t.boundingClientRect.bottom,t.boundingClientRect.height])});s.observe(o),this.observers.set(n,s)}intersectRemove(e){const t=this.observers.get(e);this.observers.delete(e),void 0!==t?t.disconnect():console.error(`The intersect observer is missing with the id=${e}`)}}function H(e,t){e.addEventListener("click",n=>{let o=e.getAttribute("href");null!==o&&(o.startsWith("#")||o.startsWith("http://")||o.startsWith("https://")||o.startsWith("//")||(n.preventDefault(),t.set("History","Push",o),window.scrollTo(0,0)))})}const J=new Set(["animate","animateMotion","animateTransform","circle","clipPath","defs","desc","discard","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","foreignObject","g","hatch","hatchpath","image","line","linearGradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialGradient","rect","set","stop","svg","switch","symbol","text","textPath","tspan","use","view","svg:a","svg:title","svg:desc","svg:script","svg:style"]);class V{constructor(e,t,n){this.depth=-1,this.matched=0,this.nodes=t,this.appLocation=n,this.virtualNodes=this.createVirtualNodes(e)}hydrate(){const e=this.virtualNodes.get(3),t=this.virtualNodes.get(2),n={rootFound:void 0!==e,matched:0,...this.countHydratable(),total:this.virtualNodes.size};if(!e)return console.error("Hydration skipped: the first DOM batch carries no <body> (node id 3), so the server-rendered markup cannot be matched and will be replaced. The app flushed DOM changes before the root element was built - see `mount` in exports.rs.",n),this.publish(n),n;this.hydrateNode(3,document.body),t&&this.hydrateNode(2,document.head),n.matched=this.matched;const o=0===n.hydratable?"100.00":(100*n.matched/n.hydratable).toFixed(2),s=`Hydration complete: ${n.matched}/${n.hydratable} matched (${o}%), ${n.skipped} markers skipped, ${n.total} vnodes in batch.`;return n.matched<n.hydratable?console.warn(s):console.log(s),this.publish(n),n}publish(e){try{window.__vertigo_hydration=e}catch(e){}}countHydratable(){let e=0,t=0;const n=new Set,o=(s,r)=>{if(n.has(s))return;n.add(s);const i=this.virtualNodes.get(s);if(r||(void 0===i||void 0===i.name&&void 0===i.value?t++:e++),i)for(const e of i.children)o(e,!1)};return o(3,!0),o(2,!0),{hydratable:e,skipped:t}}hydrateNode(e,t){const n=this.virtualNodes.get(e);if(!n)return;const o=Array.from(t.childNodes);let s=0;this.depth++;let r=!1;for(const e of n.children){const t=this.virtualNodes.get(e);if(t)if(r&&void 0!==t.value)this.matched++;else{r=!1;for(let n=s;n<o.length;n++){const i=o[n];if(!i)continue;let a=!1;if(t.name?a=this.checkElementMatch(i,t):void 0!==t.value&&(i.nodeType===Node.TEXT_NODE?(this.checkTextMatch(i,t),a=!0,r=!0):console.error(`Hydration ${this.depth}: Text node mismatch`,t,i)),a){this.removeSkippedNodes(o,s,n),this.claimNode(i,e),this.matched++,t.name&&this.hydrateNode(e,i),s=n+1;break}}}}this.removeSkippedNodes(o,s,o.length),this.depth--}checkElementMatch(e,t){let n=!1;const o=void 0===t.name?void 0:(s=t.name,J.has(s)?s.replace("svg:",""):s.toUpperCase());var s;if(e.nodeType===Node.ELEMENT_NODE&&e.tagName===o){n=!0;const o=e,s=t.attributes;for(const e of o.getAttributeNames())s&&s.has(e)||o.removeAttribute(e);if(s)for(const[e,t]of s)o.getAttribute(e)!==t&&o.setAttribute(e,t)}return n}checkTextMatch(e,t){e.textContent?.replace("\n"," ").trim()!==t.value?.replace("\n"," ").trim()&&(e.textContent=t.value||"")}claimNode(e,t){var n,o;(e instanceof Element||e instanceof Comment||e instanceof Text)&&(this.nodes.claimNode(t,e),e instanceof Element&&(n=e,o=this.appLocation,"a"===n.tagName.toLowerCase()&&H(n,o)))}removeSkippedNodes(e,t,n){for(let o=t;o<n;o++){const t=e[o];t&&(0!==this.depth&&t.nodeType!==Node.TEXT_NODE&&console.warn(`Hydration ${this.depth}: Removing node`,t),t.remove())}}createVirtualNodes(e){const t=new Map,n=e=>{let n=t.get(e);return n||(n={id:e,children:[]},t.set(e,n)),n},o=e=>{for(const n of t.values()){const t=n.children.indexOf(e);-1!==t&&n.children.splice(t,1)}},s=e=>{o(e),t.delete(e)};for(const r of e)if("CreateNode"in r){n(r.CreateNode.id).name=r.CreateNode.name}else if("CreateText"in r){n(r.CreateText.id).value=r.CreateText.value}else if("UpdateText"in r){n(r.UpdateText.id).value=r.UpdateText.value}else if("InsertBefore"in r){const e=n(r.InsertBefore.parent),t=r.InsertBefore.child,s=r.InsertBefore.ref_id;if(o(t),null==s)e.children.push(t);else{const n=e.children.indexOf(s);-1!==n?e.children.splice(n,0,t):(console.warn(`Hydration: ref_id ${s} not found in parent ${r.InsertBefore.parent}`),e.children.push(t))}}else if("SetAttr"in r){const e=n(r.SetAttr.id);e.attributes||(e.attributes=new Map),e.attributes.set(r.SetAttr.name,r.SetAttr.value)}else"RemoveAttr"in r?t.get(r.RemoveAttr.id)?.attributes?.delete(r.RemoveAttr.name):"RemoveNode"in r?s(r.RemoveNode.id):"RemoveText"in r?s(r.RemoveText.id):"RemoveComment"in r&&s(r.RemoveComment.id);return t}}const j=1,G=2,P=3,z=4,K=5,q=6,X=7,Q=8,Y=9,Z=10,ee=11,te=12,ne=13;class oe{constructor(e){this.bytes=e,this.at=0}isEmpty(){return this.at>=this.bytes.length}where(){return`offset ${this.at} of ${this.bytes.length}`}byte(){const e=this.bytes[this.at];if(void 0===e)throw new Error("dom command: buffer ended early");return this.at+=1,e}varint(){let e=0,t=1;for(;;){const n=this.byte();if(e+=(127&n)*t,!(128&n))return e;t*=128}}string(){const t=this.varint(),n=this.at+t;if(n>this.bytes.length)throw new Error("dom command: string runs past the end of the buffer");const o=e.decode(this.bytes.subarray(this.at,n));return this.at=n,o}name(e){const t=this.varint(),n=e[t];if(void 0===n)throw new Error(`dom command: name index ${t} is not in the dictionary`);return n}optionalId(){const e=this.varint();return 0===e?null:e}}const se=e=>{const t=e.varint(),n=[];for(let o=0;o<t;o++)n.push(e.string());return n},re=e=>e.varint(),ie=e=>e.string(),ae=(e,t)=>e.name(t),ce={[j]:["CreateNode",[["id",re],["name",ae]]],[G]:["CreateText",[["id",re],["value",ie]]],[P]:["UpdateText",[["id",re],["value",ie]]],[z]:["SetAttr",[["id",re],["name",ae],["value",ie]]],[K]:["RemoveAttr",[["id",re],["name",ae]]],[q]:["RemoveNode",[["id",re]]],[X]:["RemoveText",[["id",re]]],[Q]:["InsertBefore",[["parent",re],["child",re],["ref_id",e=>e.optionalId()]]],[Y]:["InsertCss",[["selector",e=>0===e.byte()?null:e.string()],["value",ie]]],[Z]:["CreateComment",[["id",re],["value",ie]]],[ee]:["RemoveComment",[["id",re]]],[te]:["CallbackAdd",[["id",re],["event_name",ie],["callback_id",re]]],[ne]:["CallbackRemove",[["id",re],["event_name",ie],["callback_id",re]]]};class le{constructor(){this.data=new Map,this.initNodes=[...this.getRootHead().childNodes,...this.getRootBody().childNodes],this.style=document.createElement("style")}getRootHtml(){return document.documentElement}getRootHead(){return document.head}getRootBody(){return document.body}set(e,t){1===e||2===e||3===e||this.data.set(e,t)}getAnyOption(e){return 1===e?this.getRootHtml():2===e?this.getRootHead():3===e?this.getRootBody():this.data.get(e)}getAny(e,t){const n=this.getAnyOption(t);if(void 0===n)throw Error(`${e} -> item not found=${t}`);return n}get(e,t){const n=this.getAnyOption(t);if(void 0===n)throw new Error(`${e}->get: Item id not found = ${t}`);return n}expect(e,t,n,o){const s=this.get(e,t);if(s instanceof n)return s;throw Error(`Expected id=${t} as ${o}`)}getNodeElement(e,t){return this.expect(e,t,HTMLElement,"HTMLElement")}getNode(e,t){return this.expect(e,t,Element,"Element")}getText(e,t){return this.expect(e,t,Text,"Text")}delete(e,t){const n=this.getAnyOption(t);if(this.data.delete(t),void 0===n)throw new Error(`${e}->delete: Item id not found = ${t}`);return n}insertCss(e,t){if(null!==e){const n=document.createTextNode(`\n${e} { ${t} }`);this.style.appendChild(n)}else{const e=document.createTextNode(`\n${t}`);this.style.appendChild(e)}}removeInitNodes(){const e=this.initNodes;if(this.initNodes=null,null!==e)for(const t of e)t.remove()}insertBefore(e,t,n){const o=this.get("insert_before",e),s=this.getAny("insert_before child",t);if(null==n)o.insertBefore(s,null);else{const e=this.getAny("insert_before ref",n);o.insertBefore(s,e)}}addStyles(){this.getRootHead().appendChild(this.style)}hasInitNodes(){return null!==this.initNodes}claimNode(e,t){if(this.data.set(e,t),this.initNodes){const e=this.initNodes.indexOf(t);e>-1&&this.initNodes.splice(e,1)}}has(e){return 1===e||2===e||3===e||this.data.has(e)}}const de=(e,t)=>{console.error("bulk_update - item",t,e)},he=(e,t)=>e.findIndex(e=>e.toLowerCase()===t);class ue{constructor(e,t,n){this.metadata=e,this.update=e=>{this.nodes.hasInitNodes()&&this.metadata.getEnabledHydration()&&((e,t,n)=>{new V(e,t,n).hydrate()})((e=>{const t=new oe(e),n=se(t),o=[];for(;!t.isEmpty();){const e=t.byte(),s=ce[e];if(void 0===s)throw new Error(`dom command: unknown tag ${e}`);const[r,i]=s,a={};for(const[e,o]of i)a[e]=o(t,n);o.push({[r]:a})}return o})(e),this.nodes,this.appLocation);const t=new oe(e),n=se(t),o=he(n,"autofocus"),s=he(n,"a"),r=new Set;try{for(;!t.isEmpty();){const e=t.byte();switch(e){case j:{const e=t.varint(),o=t.varint();try{this.createNode(e,n[o]??"",o===s)}catch(e){de(e,"CreateNode")}break}case G:{const e=t.varint(),n=t.string();try{this.createText(e,n)}catch(e){de(e,"CreateText")}break}case P:{const e=t.varint(),n=t.string();try{this.updateText(e,n)}catch(e){de(e,"UpdateText")}break}case z:{const e=t.varint(),s=t.varint(),i=t.string();s===o&&r.add(e);try{this.writeAttr("set_attribute",e,n[s]??"",i)}catch(e){de(e,"SetAttr")}break}case K:{const e=t.varint(),o=t.varint();try{this.writeAttr("remove_attribute",e,n[o]??"",null)}catch(e){de(e,"RemoveAttr")}break}case q:{const e=t.varint();try{this.removeNode(e)}catch(e){de(e,"RemoveNode")}break}case X:{const e=t.varint();try{this.removeText(e)}catch(e){de(e,"RemoveText")}break}case Q:{const e=t.varint(),n=t.varint(),o=t.optionalId();try{this.nodes.insertBefore(e,n,o)}catch(e){de(e,"InsertBefore")}break}case Y:{const e=0===t.byte()?null:t.string(),n=t.string();try{this.nodes.insertCss(e,n)}catch(e){de(e,"InsertCss")}break}case Z:{const e=t.varint(),n=t.string();try{this.nodes.set(e,document.createComment(n))}catch(e){de(e,"CreateComment")}break}case ee:{const e=t.varint();try{this.nodes.delete("remove_comment",e).remove()}catch(e){de(e,"RemoveComment")}break}case te:{const e=t.varint(),n=t.string(),o=t.varint();try{this.callbacks.add(this.nodes,e,n,o)}catch(e){de(e,"CallbackAdd")}break}case ne:{const e=t.varint(),n=t.string(),o=t.varint();try{this.callbacks.remove(this.nodes,e,n,o)}catch(e){de(e,"CallbackRemove")}break}default:throw new Error(`bulk_update: unknown command tag ${e}`)}}}catch(e){console.error(`bulk_update - stream is unreadable at ${t.where()}, dropping the rest of the batch`,e)}r.size>0&&setTimeout(()=>{for(const e of r){this.nodes.getNodeElement(`set focus ${e}`,e).focus()}},0),this.nodes.removeInitNodes(),this.nodes.addStyles()},this.appLocation=t,this.nodes=new le,this.callbacks=new F(n),document.addEventListener("dragover",e=>{e.preventDefault()})}createNode(e,t,n){if(1===e||2===e||3===e)return;if(this.nodes.has(e))return;const o=(e=>J.has(e)?document.createElementNS("http://www.w3.org/2000/svg",e.replace("svg:","")):document.createElement(e))(t);this.nodes.set(e,o),n&&H(o,this.appLocation)}writeAttr(e,t,n,o){const s=this.nodes.getNode(e,t);if(null===o?s.removeAttribute(n):s.setAttribute(n,o),"value"==n){const e=o??"";if(s instanceof HTMLInputElement)return void(s.value=e);if(s instanceof HTMLTextAreaElement)return s.value=e,void(s.defaultValue=e)}}removeNode(e){if(1===e||2===e||3===e)return;this.nodes.delete("remove_node",e).remove()}createText(e,t){if(this.nodes.has(e))return;const n=document.createTextNode(t);this.nodes.set(e,n)}removeText(e){this.nodes.delete("remove_node",e).remove()}updateText(e,t){this.nodes.getText("set_attribute",e).textContent=t}}const me={Debug:"debug",Info:"info",Log:"log",Warn:"warn",Error:"error"};class fe{constructor(e,t){this.metadata=e,this.getWasm=t;const n=new S(t);this.dom=new ue(e,n,t),this.websocket=new C(t),this.interval=new _(t),this.location=n,this.cookie=new L}exec(e){const t=e;if("FetchCacheGet"===t)return{data:this.metadata.getFetchCache()};if("IsBrowser"===t)return{value:!0};if("GetDateNow"===t)return{value:Date.now()};if("TimezoneOffset"===t)return{value:(new Date).getTimezoneOffset()};if("HistoryBack"===t)return window.history.back(),null;const n=t,[o,s]=Object.entries(n)[0]??[];switch(o){case"FetchExec":return(async(e,t,n)=>{const o=e(),s=e=>{o.wasmCommand({FetchExecResponse:{response:e,callback:t}})};try{const e=await fetch(n.url,{method:n.method,headers:x(n.headers),body:T(n.body)});s(await N(e))}catch(e){console.error("fetch error (1)",e),s({Err:{message:new String(e).toString()}})}})(this.getWasm,s.callback,s.request),null;case"WebsocketRegister":return this.websocket.websocket_register_callback(s.host,s.callback),null;case"WebsocketSendMessage":return this.websocket.websocket_send_message(s.callback,s.message),null;case"WebsocketUnregister":return this.websocket.websocket_unregister_callback(s.callback),null;case"TimerSet":return this.interval.timerSet(s.callback,s.duration,s.kind),null;case"TimerClear":return this.interval.timerClear(s.callback),null;case"LocationGet":return{value:this.location.get(s.target)};case"LocationCallback":return this.location.callback(s.target,s.mode,s.callback),null;case"LocationSet":return this.location.set(s.target,s.mode,s.value),null;case"CookieGet":return{value:this.cookie.get(s.name)};case"CookieSet":return this.cookie.set(s.name,s.value,s.expires_in),null;case"CookieJsonGet":return{value:this.cookie.getJson(s.name)};case"CookieJsonSet":return this.cookie.setJson(s.name,s.value,s.expires_in),null;case"GetEnv":return{value:this.metadata.getEnv(s.name)};case"Log":return console[me[s.kind]](s.message,s.arg2,s.arg3,s.arg4),null;case"GetRandom":return{value:$(s.min,s.max)};case"JsApiCall":return this.executeJsApiCall(s.commands);case"DomBulkUpdate":return this.dom.update(s.commands),null;default:return console.info("exec_command: Arg",t),(()=>{throw Error("assert never")})()}}executeJsApiCall(e){let t=null;for(const n of e)if("Root"in n)if("window"===n.Root.name)t=window;else{if("document"!==n.Root.name)return console.error(`Unknown root: ${n.Root.name}`),null;t=document}else if("RootElement"in n){const e=n.RootElement.dom_id,o=this.dom.nodes.getAnyOption(e);if(void 0===o)return console.error(`Element not found: ${e}`),null;t=o}else if("Get"in n){if(null===t)return console.error("Get called on null"),null;t=t[n.Get.property]}else if("Set"in n){if(null===t)return console.error("Set called on null"),null;t[n.Set.property]=n.Set.value,t=void 0}else if("Call"in n){if(null===t)return console.error("Call called on null"),null;t=t[n.Call.method](...n.Call.args)}const n=e=>{if(null==e)return null;if("boolean"==typeof e)return e;if("string"==typeof e)return e;if("number"==typeof e)return e;if(e instanceof Uint8Array)return e;if(Array.isArray(e))return e.map(e=>n(e));if((e=>{if(null===e)return!1;if("object"!=typeof e)return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t})(e)){const t={};for(const o of Object.keys(e))t[o]=n(e[o]);return t}return null};return n(t)}}class ge{constructor(){this.get=e=>this.metadata.getAttribute(e),this.getEnabledHydration=()=>"true"!==this.get("data-env-disable-hydration");const e=document.getElementById("v-metadata");if(null===e)throw Error("Expected v-metadata");this.metadata=e,e.remove()}getEnv(e){return this.get(`data-env-${e}`)}getFetchCache(){return this.get("data-fetch-cache")}}class pe{constructor(e){this.wasm=e}vertigoEntryFunction(e,t){this.wasm.exports.vertigo_entry_function(e,t)}static async create(t){let o=null;const s=()=>{if(null===o)throw Error("Wasm is no initialized");return o},r=new ge,i=new fe(r,s);return window.$vertigoApi=i,o=await g(t,{mod:{panic_message:t=>{const n=Number(t%2n**32n),o=Number(t>>32n),r=s().getUint8Memory().subarray(o,o+n),i=e.decode(r);console.error("PANIC",i)},dom_access:e=>{if(0n===e)return console.error("dom_access - null pointer"),0n;const t=new n(()=>s().getUint8Memory(),e),o=m(t);s().exports.vertigo_export_free_block(e);const r=i.exec(o),a=u(r),c=s().exports.vertigo_export_alloc_block(a),l=new n(()=>s().getUint8Memory(),c);return f(r,l),c}}}),new pe(o)}}const ve=new Set,we=async()=>{document.querySelectorAll("*[data-vertigo-run-wasm]").forEach(e=>{const t=e.getAttribute("data-vertigo-run-wasm");"string"==typeof t?(async e=>{if(ve.has(e))return;if(ve.size>0)return void console.error("Only one wasm module can be run",{moduleRun:ve,wasm:e});ve.add(e),console.info(`Wasm module: "${e}" -> start`);const t=await pe.create(e);console.info(`Wasm module: "${e}" -> initialized`),t.vertigoEntryFunction(0,13),console.info(`Wasm module: "${e}" -> launched vertigoEntryFunction with version 0.13`)})(t):console.error("Run error",e)})};window.addEventListener("load",we),setTimeout(we,3e3);
//# sourceMappingURL=wasm_run.js.map