@web-sandbox.js/web-widget
Version:
3 lines (2 loc) • 12.8 kB
JavaScript
"use strict";function t(){const t=new Map;return{[Symbol("data")]:t,get:e=>t.get(e),define(e,n){t.set(e,n)}}}function e(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}Object.defineProperty(exports,"__esModule",{value:!0});let n=0;const i="WebWidgetModuleCache";let o;const r="function"==typeof window.queueMicrotask?window.queueMicrotask.bind(window):t=>(o||(o=Promise.resolve())).then(t).catch((t=>setTimeout((()=>{throw t}),0))),s="bootstrapped",a="mounted",l="load-error",c="bootstrap-error",d="mount-error";var u=Object.freeze({__proto__:null,INITIAL:"initial",LOADING:"loading",LOADED:"loaded",BOOTSTRAPPING:"bootstrapping",BOOTSTRAPPED:s,MOUNTING:"mounting",MOUNTED:a,UPDATING:"updating",UNMOUNTING:"unmounting",UNLOADING:"unloading",LOAD_ERROR:l,BOOTSTRAP_ERROR:c,MOUNT_ERROR:d,UPDATE_ERROR:"update-error",UNMOUNT_ERROR:"unmount-error",UNLOAD_ERROR:"unload-error"});const h=Symbol("bootstrap"),m=Symbol("bootstrapPromise"),b=Symbol("childrenWidget"),p=Symbol("loadPromise"),g=Symbol("mount"),f=Symbol("mountPromise"),w=Symbol("name"),y=Symbol("portalDestinations"),E=Symbol("portals"),W=Symbol("prefetch"),S=Symbol("setState"),O=Symbol("timeouts"),x=Symbol("unload"),v=Symbol("unloadPromise"),R=Symbol("unmount"),T=Symbol("unmountPromise"),A=Symbol("update");function L(t,e){const n=`WebWidget applications[${t[w]}]`;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 P={bootstrap:{millis:4e3,dieOnTimeout:!1,warningMillis:1e3},mount:{millis:3e3,dieOnTimeout:!1,warningMillis:1e3},unmount:{millis:3e3,dieOnTimeout:!1,warningMillis:1e3},unload:{millis:3e3,dieOnTimeout:!1,warningMillis:1e3},update:{millis:3e3,dieOnTimeout:!1,warningMillis:1e3}};function M(t,e){return new Promise(((n,i)=>{const o={[h]:"bootstrap",[g]:"mount",[x]:"unload",[R]:"unmount",[A]:"update"}[e],r=t[O][o],s=r.warningMillis,a=`Lifecycle function ${o} for ${t[w]} lifecycle did not resolve or reject for ${r.millis} ms`;let l=!1,c=!1;function d(e){if(!l)if(!0===e)c=!0,r.dieOnTimeout?i(L(t,new Error(a))):console.error(L(t,new Error(a)));else if(!c){const n=e,i=n*s;console.warn(L(t,new Error(a))),i+s<r.millis&&setTimeout((()=>d(n+1)),s)}}t[e](t.dependencies).then((t=>{l=!0,n(t)})).catch((t=>{l=!0,i(t)})),setTimeout((()=>d(1)),s),setTimeout((()=>d(!0)),r.millis)}))}function N(t){const e={};for(const n in P)e[n]={...P[n],...t&&t[n]||{}};return e}function C(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(L(t,new Error(`The lifecycle function at array index ${o} did not return a promise`)))}))),Promise.resolve())}async function D(t){return t[v]||(t[S]("unloading"),t[v]=(t.state===l?Promise.resolve():M(t,x)).then((()=>{!function(t){Object.assign(t,{[h]:null,[p]:null,[m]:null,[p]:null,[g]:null,[f]:null,[y]:null,[E]:null,[O]:null,[x]:null,[v]:null,[R]:null,[T]:null,[A]:null}),t[S]("initial"),Object.getOwnPropertyNames(t.dependencies).forEach((e=>{Reflect.deleteProperty(t.dependencies,e)}))}(t)})).catch((e=>{throw t[S]("unload-error"),t[v]=null,L(t,e)}))),t[v]}function U(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 U(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[y].get(e))return i[y].get(e);i=i.parent}while(i);return n.portalDestinations.get(e)})(i,e);if(r&&(o=r()),!o)throw L(i,new Error(`The portal cannot be found: ${e}`));if(!(o instanceof n))throw L(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[E].push(o),U(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[y].get(...arguments)},define(){return t[y].define(...arguments)}}}get sandboxed(){const{sandboxed:t}=this.ownerElement;return t}}const k=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=k.get(this);if(t||(t=new WeakMap,k.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 j=Symbol("application"),$=Symbol("data"),I=Symbol("firstConnect"),_=Symbol("initialization"),H=Symbol("moveing"),z=Symbol("parentWidget"),G=Symbol("state"),B=Symbol("statechangeCallback"),J=t(),q=t(),F=t=>!t.inactive,K=t=>t.isConnected&&(t.src||t.application||t.text),Q=t=>F(t)&&K(t),V=F,X=new IntersectionObserver((t=>{t.forEach((({isIntersecting:t,target:e})=>{t&&Q(e)&&(e.mount(),X.unobserve(e))}))}),{rootMargin:"80%"});function Y(t){r((()=>{throw t}))}function Z(t){r((()=>{Q(t)?t.mount().catch(Y):(t=>t.inactive&&t.src)(t)&&t[W]()}))}class HTMLWebWidgetElement extends HTMLElement{constructor(){super(),this.addEventListener("statechange",this[B])}get application(){return this[j]||null}set application(t){"function"==typeof t&&(this[j]=t,Z(this))}get csp(){return this.getAttribute("csp")||""}set csp(t){this.setAttribute("csp",t)}get data(){if(void 0!==this[$])return this[$];const t=this.getAttribute("data");if(t)try{return this[$]=JSON.parse(t),this[$]}catch(t){Y(t)}return this.dataset}set data(t){"object"==typeof t&&(this[$]=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[G]||"initial"}[S](t){t!==this[G]&&(this[G]=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[_]){if(!K(this))throw new Error("Cannot load: Not initialized");const{application:t}=this;if(this[w]=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[_]=!0,this.sandboxed&&!this.sandbox.window)throw new Error("Sandbox mode is not implemented")}await async function(e){return e[p]||(e[S]("loading"),e[p]=e.loader(e.dependencies).then((n=>{"function"==typeof n&&(n=n()),n=n||{},Object.assign(e,{[h]:C(e,n,"bootstrap"),[g]:C(e,n,"mount"),[y]:t(),[E]:[],[O]:N(n.timeouts),[x]:C(e,n,"unload"),[R]:C(e,n,"unmount"),[A]:C(e,n,"update")}),e[S]("loaded")})).catch((t=>{throw e[S](l),e[p]=null,L(e,t)}))),e[p]}(this)}async bootstrap(){"loaded"!==this.state&&await this.load(),await async function(t){return t[m]||(t[S]("bootstrapping"),t[m]=M(t,h).then((()=>{t[S](s)})).catch((e=>{throw t[S](c),t[m]=null,L(t,e)}))),t[m]}(this)}async mount(){this.state!==s&&await this.bootstrap(),await async function(t){return t[f]||(t[S]("mounting"),t[f]=M(t,g).then((()=>{t[S](a),t[T]=null})).catch((async e=>{throw t[S](d),t[f]=null,L(t,e)}))),t[f]}(this)}async update(t={}){if(this.state!==a)throw new Error("Cannot update: Not mounted");Object.assign(this.dependencies,t),await async function(t){return t[S]("updating"),M(t,A).then((()=>{t[S](a)})).catch((e=>{throw t[S]("update-error"),L(t,e)}))}(this)}async unmount(){this.state===a&&await async function(t){if(t[T])return t[T];t[S]("unmounting");const e=t[b]().map((async t=>t.unmount().catch((t=>{r((()=>{throw t}))}))));return t[T]=Promise.all(e).then((()=>M(t,R).then((()=>{t[S](s),t[f]=null})).catch((e=>{throw t[S]("unmount-error"),t[T]=null,L(t,e)})))),t[T]}(this)}async unload(){this.state===a&&await this.unmount(),[s,a].includes(this.state)&&await D(this)}connectedCallback(){this[I]?this[H]&&this.movedCallback():(this.firstConnectedCallback(),this[I]=!0)}firstConnectedCallback(){if(this[z]()){const{sandboxed:t,csp:e}=this[z]();t&&(this.sandboxed=t),e&&(this.csp=e)}var t;"lazy"===this.loading?(t=this,X.observe(t)):Z(this)}disconnectedCallback(){this[H]=!0,r((()=>{this.isConnected||(this[H]=!1,this.destroyedCallback())}))}attributeChangedCallback(t){"data"===t&&delete this[$],"lazy"!==this.loading&&Z(this)}destroyedCallback(){var t;"lazy"===this.loading&&(t=this,X.unobserve(t)),function(t){r((()=>{V(t)&&(t.unload().catch(Y),t.sandboxed&&t.sandbox.unload())}))}(this)}[B](){const t=this.state;if([a,l,c,d].includes(t)){let e,n;const i=t!==a;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)}}[W](){!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)}[z](){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)}[b](){return function(t,n){let i;const o=t.dependencies.container;o instanceof ShadowRoot&&(i=o);const r=e(t,n);return i&&r.push(...e(i,n)),[...new Set([...r,...t[E]].map((t=>t)))]}(this,this.constructor)}static get observedAttributes(){return["data","src","text","inactive"]}static get portalDestinations(){return J}static get loaders(){return q}}Object.assign(HTMLWebWidgetElement,u),q.define("module",(async function(t){const{src:e,text:o,sandboxed:r,sandbox:s}=t,a=r?s.window:window,{document:l,Blob:c,URL:d,Error:u}=a,h=a[i]=a[i]||new Map;if(e&&h.has(e))return h.get(e);const m=new Promise(((t,s)=>{const h=`${i}Temp${n++}`;let m=l.createElement("script");const b=e?`window[${JSON.stringify(h)}] = import(${JSON.stringify(e)})`:`\n const url = URL.createObjectURL(new Blob(\n [${JSON.stringify(o)}],\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 c([b],{type:"application/javascript"}),g=d.createObjectURL(p),f=()=>{delete a[h],m.parentNode.removeChild(m),m=null,d.revokeObjectURL(g)};m.type="module",m.src=g,m.onload=()=>{a[h]?a[h].then((e=>t(e)),s):s(new u(r?"The sandbox does not support ES module":"Load error")),f()},m.onerror=t=>{s(t),f()},l.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,exports.HTMLWebWidgetElement=HTMLWebWidgetElement,exports.WebWidgetDependencies=WebWidgetDependencies,exports.WebWidgetSandbox=WebWidgetSandbox;
//# sourceMappingURL=web-widget.js.map