@web-sandbox.js/web-widget
Version:
3 lines (2 loc) • 13 kB
JavaScript
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).HTMLWebWidgetElement={})}(this,(function(t){"use strict";function e(){const t=new Map;return{[Symbol("data")]:t,get:e=>t.get(e),define(e,n){t.set(e,n)}}}function n(t,e){const n=[],i=[...t.children];for(;i.length;){const t=i.pop();t instanceof e?n.push(t):i.unshift(...t.children)}return n}let i=0;const o="WebWidgetModuleCache";let r;const s="function"==typeof window.queueMicrotask?window.queueMicrotask.bind(window):t=>(r||(r=Promise.resolve())).then(t).catch((t=>setTimeout((()=>{throw t}),0))),a="initial",c="loading",l="loaded",d="bootstrapping",u="bootstrapped",h="mounting",m="mounted",b="updating",p="unmounting",f="unloading",g="load-error",w="bootstrap-error",y="mount-error",E="update-error",W="unmount-error",S="unload-error";var O=Object.freeze({__proto__:null,INITIAL:a,LOADING:c,LOADED:l,BOOTSTRAPPING:d,BOOTSTRAPPED:u,MOUNTING:h,MOUNTED:m,UPDATING:b,UNMOUNTING:p,UNLOADING:f,LOAD_ERROR:g,BOOTSTRAP_ERROR:w,MOUNT_ERROR:y,UPDATE_ERROR:E,UNMOUNT_ERROR:W,UNLOAD_ERROR:S});const x=Symbol("bootstrap"),T=Symbol("bootstrapPromise"),v=Symbol("childrenWidget"),R=Symbol("loadPromise"),A=Symbol("mount"),L=Symbol("mountPromise"),M=Symbol("name"),P=Symbol("portalDestinations"),N=Symbol("portals"),C=Symbol("prefetch"),D=Symbol("setState"),U=Symbol("timeouts"),j=Symbol("unload"),k=Symbol("unloadPromise"),$=Symbol("unmount"),I=Symbol("unmountPromise"),_=Symbol("update");function H(t,e){const n=`WebWidget applications[${t[M]}]`;return"object"!=typeof e&&(e=new Error(e)),e.message.includes(n)||Reflect.defineProperty(e,"message",{value:`${n}: ${e.message}`,writable:!0,configurable:!0}),e}const z=1e3,G={bootstrap:{millis:4e3,dieOnTimeout:!1,warningMillis:z},mount:{millis:3e3,dieOnTimeout:!1,warningMillis:z},unmount:{millis:3e3,dieOnTimeout:!1,warningMillis:z},unload:{millis:3e3,dieOnTimeout:!1,warningMillis:z},update:{millis:3e3,dieOnTimeout:!1,warningMillis:z}};function B(t,e){return new Promise(((n,i)=>{const o={[x]:"bootstrap",[A]:"mount",[j]:"unload",[$]:"unmount",[_]:"update"}[e],r=t[U][o],s=r.warningMillis,a=`Lifecycle function ${o} for ${t[M]} lifecycle did not resolve or reject for ${r.millis} ms`;let c=!1,l=!1;function d(e){if(!c)if(!0===e)l=!0,r.dieOnTimeout?i(H(t,new Error(a))):console.error(H(t,new Error(a)));else if(!l){const n=e,i=n*s;console.warn(H(t,new Error(a))),i+s<r.millis&&setTimeout((()=>d(n+1)),s)}}t[e](t.dependencies).then((t=>{c=!0,n(t)})).catch((t=>{c=!0,i(t)})),setTimeout((()=>d(1)),s),setTimeout((()=>d(!0)),r.millis)}))}function J(t){const e={};for(const n in G)e[n]={...G[n],...t&&t[n]||{}};return e}function q(t,e,n){let i=e[n]||(async()=>{});return i=Array.isArray(i)?i:[i],0===i.length&&(i=[()=>Promise.resolve()]),e=>i.reduce(((n,i,o)=>n.then((()=>{const n=i(e);return function(t){return t&&"function"==typeof t.then&&"function"==typeof t.catch}(n)?n:Promise.reject(H(t,new Error(`The lifecycle function at array index ${o} did not return a promise`)))}))),Promise.resolve())}async function F(t){return t[k]||(t[D](f),t[k]=(t.state===g?Promise.resolve():B(t,j)).then((()=>{!function(t){Object.assign(t,{[x]:null,[R]:null,[T]:null,[R]:null,[A]:null,[L]:null,[P]:null,[N]:null,[U]:null,[j]:null,[k]:null,[$]:null,[I]:null,[_]:null}),t[D](a),Object.getOwnPropertyNames(t.dependencies).forEach((e=>{Reflect.deleteProperty(t.dependencies,e)}))}(t)})).catch((e=>{throw t[D](S),t[k]=null,H(t,e)}))),t[k]}function K(t){return{mount:()=>t.mount(),update:e=>t.update(e),unmount:()=>t.unmount()}}class WebWidgetDependencies{constructor(t){Reflect.defineProperty(this,"ownerElement",{get:()=>t})}get attributes(){return[...this.ownerElement.attributes].reduce(((t,{name:e,value:n})=>(t[e]=n,t)),{})}get container(){const t=this.ownerElement,{sandboxed:e,sandbox:n}=t;if(e){const t=n.window.document,e=t.createElement("style");return e.textContent="body{margin:0}",t.head.appendChild(e),t.body}return t.attachShadow({mode:"closed"})}get context(){return K(this.ownerElement)}get createPortal(){return(t,e)=>{const n=this.ownerElement.constructor,i=this.ownerElement;let o;const r=((t,e)=>{let i=t;do{if(i[P].get(e))return i[P].get(e);i=i.parent}while(i);return n.portalDestinations.get(e)})(i,e);if(r&&(o=r()),!o)throw H(i,new Error(`The portal cannot be found: ${e}`));if(!(o instanceof n))throw H(i,new Error(`Portal must be an instance of "HTMLWebWidgetElement": ${e}`));this.sandboxed&&!t.isConnected&&this.container.appendChild(t),t.slot||(t.slot="");const s=o.querySelector(`[slot="${t.slot}"]`);return s&&o.removeChild(s),o.appendChild(t),o.mount(),i[N].push(o),K(o)}}get data(){const t=this.ownerElement.data;return Array.isArray(t)?[...t]:{...t}}set data(t){this.ownerElement.data=t}get dataset(){return{...this.ownerElement.dataset}}get name(){return this.ownerElement.name}get portalDestinations(){const t=this.ownerElement;return{get(){return t[P].get(...arguments)},define(){return t[P].define(...arguments)}}}get sandboxed(){const{sandboxed:t}=this.ownerElement;return t}}const Q=new WeakMap;["container","context","createPortal","name","portalDestinations"].forEach((t=>{!function(t,e,n){Reflect.defineProperty(t,e,n(Reflect.getOwnPropertyDescriptor(t,e)))}(WebWidgetDependencies.prototype,t,(t=>{var e;return t.get=(e=t.get,function(){let t=Q.get(this);if(t||(t=new WeakMap,Q.set(this,t)),t.has(e))return t.get(e);const n=e.apply(this,arguments);return t.set(e,n),n}),t}))})),window.WebWidgetDependencies=WebWidgetDependencies;class WebWidgetSandbox{constructor(t){Reflect.defineProperty(this,"ownerElement",{get:()=>t})}unload(){}get window(){return null}}window.WebWidgetSandbox=WebWidgetSandbox;const V=Symbol("application"),X=Symbol("data"),Y=Symbol("firstConnect"),Z=Symbol("initialization"),tt=Symbol("moveing"),et=Symbol("parentWidget"),nt=Symbol("state"),it=Symbol("statechangeCallback"),ot=e(),rt=e(),st=t=>!t.inactive,at=t=>t.isConnected&&(t.src||t.application||t.text),ct=t=>st(t)&&at(t),lt=st,dt=new IntersectionObserver((t=>{t.forEach((({isIntersecting:t,target:e})=>{t&&ct(e)&&(e.mount(),dt.unobserve(e))}))}),{rootMargin:"80%"});function ut(t){s((()=>{throw t}))}function ht(t){s((()=>{ct(t)?t.mount().catch(ut):(t=>t.inactive&&t.src)(t)&&t[C]()}))}class HTMLWebWidgetElement extends HTMLElement{constructor(){super(),this.addEventListener("statechange",this[it])}get application(){return this[V]||null}set application(t){"function"==typeof t&&(this[V]=t,ht(this))}get csp(){return this.getAttribute("csp")||""}set csp(t){this.setAttribute("csp",t)}get data(){if(void 0!==this[X])return this[X];const t=this.getAttribute("data");if(t)try{return this[X]=JSON.parse(t),this[X]}catch(t){ut(t)}return this.dataset}set data(t){"object"==typeof t&&(this[X]=t)}get inactive(){return this.hasAttribute("inactive")}set inactive(t){t?this.setAttribute("inactive",""):this.removeAttribute("inactive")}get importance(){return this.getAttribute("importance")||"auto"}set importance(t){this.setAttribute("importance",t)}get loading(){return this.getAttribute("loading")||"auto"}set loading(t){this.setAttribute("loading",t)}get type(){return this.getAttribute("type")||"module"}set type(t){this.setAttribute("type",t)}get state(){return this[nt]||a}[D](t){t!==this[nt]&&(this[nt]=t,this.dispatchEvent(new Event("statechange")))}get sandboxed(){return this.hasAttribute("sandboxed")}set sandboxed(t){t?this.setAttribute("sandboxed",""):this.removeAttribute("sandboxed")}get name(){return this.getAttribute("name")||""}set name(t){this.setAttribute("name",t)}get src(){const t=this.getAttribute("src");return null===t?"":new URL(t,this.baseURI).href}set src(t){this.setAttribute("src",t)}get text(){return this.getAttribute("text")||""}set text(t){this.setAttribute("text",t)}createDependencies(){return new WebWidgetDependencies(this)}createSandbox(){return new WebWidgetSandbox(this)}async createLoader(){const{type:t}=this,e=this.constructor.loaders.get(t);if(!e)throw Error(`Loader is not defined: ${t}`);return e(this)}async load(){if(!this[Z]){if(!at(this))throw new Error("Cannot load: Not initialized");const{application:t}=this;if(this[M]=this.name||(t?t.name:this.name||this.localName),this.dependencies=this.createDependencies(),this.sandbox=this.sandboxed?this.createSandbox():null,this.loader=t?async()=>t:this.createLoader.bind(this),this[Z]=!0,this.sandboxed&&!this.sandbox.window)throw new Error("Sandbox mode is not implemented")}await async function(t){return t[R]||(t[D](c),t[R]=t.loader(t.dependencies).then((n=>{"function"==typeof n&&(n=n()),n=n||{},Object.assign(t,{[x]:q(t,n,"bootstrap"),[A]:q(t,n,"mount"),[P]:e(),[N]:[],[U]:J(n.timeouts),[j]:q(t,n,"unload"),[$]:q(t,n,"unmount"),[_]:q(t,n,"update")}),t[D](l)})).catch((e=>{throw t[D](g),t[R]=null,H(t,e)}))),t[R]}(this)}async bootstrap(){this.state!==l&&await this.load(),await async function(t){return t[T]||(t[D](d),t[T]=B(t,x).then((()=>{t[D](u)})).catch((e=>{throw t[D](w),t[T]=null,H(t,e)}))),t[T]}(this)}async mount(){this.state!==u&&await this.bootstrap(),await async function(t){return t[L]||(t[D](h),t[L]=B(t,A).then((()=>{t[D](m),t[I]=null})).catch((async e=>{throw t[D](y),t[L]=null,H(t,e)}))),t[L]}(this)}async update(t={}){if(this.state!==m)throw new Error("Cannot update: Not mounted");Object.assign(this.dependencies,t),await async function(t){return t[D](b),B(t,_).then((()=>{t[D](m)})).catch((e=>{throw t[D](E),H(t,e)}))}(this)}async unmount(){this.state===m&&await async function(t){if(t[I])return t[I];t[D](p);const e=t[v]().map((async t=>t.unmount().catch((t=>{s((()=>{throw t}))}))));return t[I]=Promise.all(e).then((()=>B(t,$).then((()=>{t[D](u),t[L]=null})).catch((e=>{throw t[D](W),t[I]=null,H(t,e)})))),t[I]}(this)}async unload(){this.state===m&&await this.unmount(),[u,m].includes(this.state)&&await F(this)}connectedCallback(){this[Y]?this[tt]&&this.movedCallback():(this.firstConnectedCallback(),this[Y]=!0)}firstConnectedCallback(){if(this[et]()){const{sandboxed:t,csp:e}=this[et]();t&&(this.sandboxed=t),e&&(this.csp=e)}var t;"lazy"===this.loading?(t=this,dt.observe(t)):ht(this)}disconnectedCallback(){this[tt]=!0,s((()=>{this.isConnected||(this[tt]=!1,this.destroyedCallback())}))}attributeChangedCallback(t){"data"===t&&delete this[X],"lazy"!==this.loading&&ht(this)}destroyedCallback(){var t;"lazy"===this.loading&&(t=this,dt.unobserve(t)),function(t){s((()=>{lt(t)&&(t.unload().catch(ut),t.sandboxed&&t.sandbox.unload())}))}(this)}[it](){const t=this.state;if([m,g,w,y].includes(t)){let e,n;const i=t!==m;for(const t of this.children){const i=t.localName;"placeholder"===i?e=t:"fallback"===i&&(n=t)}e&&n?(e.hidden=i,n.hidden=!i):e?i||(e.hidden=!0):n&&(n.hidden=!i)}}[C](){!function(t){if(!document.head.querySelector(`link[href="${t}"]`)){const e=document.createElement("link");e.rel="prefetch",e.href=t,document.head.appendChild(e)}}(this.src,this.importance)}[et](){return function(t,e){const n=function(t,e){let n=t;do{if(n=n.getRootNode().host,n&&n instanceof e)return n}while(n);return null}(t,e);return n||null}(this,this.constructor)}[v](){return function(t,e){let i;const o=t.dependencies.container;o instanceof ShadowRoot&&(i=o);const r=n(t,e);return i&&r.push(...n(i,e)),[...new Set([...r,...t[N]].map((t=>t)))]}(this,this.constructor)}static get observedAttributes(){return["data","src","text","inactive"]}static get portalDestinations(){return ot}static get loaders(){return rt}}Object.assign(HTMLWebWidgetElement,O),rt.define("module",(async function(t){const{src:e,text:n,sandboxed:r,sandbox:s}=t,a=r?s.window:window,{document:c,Blob:l,URL:d,Error:u}=a,h=a[o]=a[o]||new Map;if(e&&h.has(e))return h.get(e);const m=new Promise(((t,s)=>{const h=`${o}Temp${i++}`;let m=c.createElement("script");const b=e?`window[${JSON.stringify(h)}] = import(${JSON.stringify(e)})`:`\n const url = URL.createObjectURL(new Blob(\n [${JSON.stringify(n)}],\n { type: 'application/javascript' }\n ));\n window[${JSON.stringify(h)}] = import(url).then(module => {\n URL.revokeObjectURL(url);\n return module;\n }, error => {\n URL.revokeObjectURL(url);\n throw error;\n })`,p=new l([b],{type:"application/javascript"}),f=d.createObjectURL(p),g=()=>{delete a[h],m.parentNode.removeChild(m),m=null,d.revokeObjectURL(f)};m.type="module",m.src=f,m.onload=()=>{a[h]?a[h].then((e=>t(e)),s):s(new u(r?"The sandbox does not support ES module":"Load error")),g()},m.onerror=t=>{s(t),g()},c.head.appendChild(m)})).then((t=>function(t){return t.default||t}(t)));return e&&h.set(e,m.catch((t=>{throw h.delete(e),t}))),m})),customElements.define("web-widget",HTMLWebWidgetElement),window.WebWidget=HTMLWebWidgetElement,window.HTMLWebWidgetElement=HTMLWebWidgetElement,t.HTMLWebWidgetElement=HTMLWebWidgetElement,t.WebWidgetDependencies=WebWidgetDependencies,t.WebWidgetSandbox=WebWidgetSandbox,Object.defineProperty(t,"__esModule",{value:!0})}));
//# sourceMappingURL=web-widget.js.map