mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 03:46:16 -08:00
8 lines
8.3 KiB
JavaScript
8 lines
8.3 KiB
JavaScript
/*!
|
|
* artplayer-tool-iframe.js v1.1.0
|
|
* Github: https://github.com/zhw2590582/ArtPlayer
|
|
* (c) 2017-2026 Harvey Zhao
|
|
* Released under the MIT License.
|
|
*/
|
|
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.ArtplayerToolIframe=t(),define(function(){return e.ArtplayerToolIframe})):(e="undefined"!==typeof globalThis?globalThis:e||self).ArtplayerToolIframe=t()}(this,function(){"use strict";const e="artplayer-tool-iframe:session";function t(e){const t=e.__artplayerIframe;if(1===t?.version&&"string"===typeof t.document&&t.document&&["inject","message","ack","leave","resume","fragment"].includes(t.phase))return t}function n(e,t,n){return{...e,__artplayerIframe:{version:1,document:t,phase:n}}}function r(e,t){if(void 0!==e.source&&null!==e.source&&e.source!==t)return!1;const n=e.data;return"object"===typeof n&&null!==n&&"type"in n&&"string"===typeof n.type}let o;const s=new WeakMap,i=new WeakMap;let a=0;function c(e,t){t?i.set(e,t):i.delete(e)}function d(e,t=new Error("The instance has been destroyed")){const n=s.get(e);if(n)for(const r of[...n])r.cancel(t)}const u=new WeakMap;function f(e){const t=e.$iframe;return t.hasAttribute?.("srcdoc")?`srcdoc:${t.getAttribute("srcdoc")}`:`src:${n=t.src||"",n.split("#")[0]}`;var n}function m(e){const t=e.$iframe;return t.hasAttribute?.("srcdoc")?`srcdoc:${t.getAttribute("srcdoc")}`:`src:${t.getAttribute?.("src")??t.src??""}`}function h(e,t){t.waiting||(t.documentId?t.cancelPrevious=function(e){const t=[...s.get(e)||[]];return e=>{for(const n of t)n.cancel(e)}}(e):d(e,new Error("The iframe document has changed"))),t.waiting=!0,e.injected=!1}function l(e,t,n){const r=m(e);if(!n.length&&r===t.rawSource)return;const o=function(e,t,n){return f(e)!==t.source||!!t.documentId&&(m(e)!==t.rawSource||n.some(t=>"srcdoc"===t.attributeName||"src"===t.attributeName&&!e.$iframe.hasAttribute?.("srcdoc")))}(e,t,n);t.rawSource=r,t.source=f(e),o&&h(e,t)}function w(e){const t=u.get(e);if(!t||e.destroyed)return;const n=t.observer?.takeRecords()||[];l(e,t,n)}function p(t,r,o){r.hasHandshake&&r.documentId!==o&&(r.cancelPrevious?r.cancelPrevious(new Error("The iframe document has changed")):r.waiting||d(t,new Error("The iframe document has changed"))),r.cancelPrevious=void 0,r.documentId=o,r.hasHandshake=!0,r.waiting=!1,t.injected=!0;try{t.$iframe.contentWindow?.postMessage(n({type:e,data:void 0,id:0},o,"ack"),"*")}catch{}}function g(n,r){const o=u.get(n);if(!o)return!1;w(n);const s=t(r);if(s&&r.type===e)return"resume"===s.phase?p(n,o,s.document):s.document===o.documentId&&("leave"===s.phase?function(e,t){t.cancelPrevious?t.cancelPrevious(new Error("The iframe document has changed")):t.waiting||d(e,new Error("The iframe document has changed")),t.cancelPrevious=void 0,t.waiting=!0,e.injected=!1}(n,o):"fragment"===s.phase&&o.cancelPrevious&&!n.$iframe.hasAttribute?.("srcdoc")&&r.data===n.$iframe.src&&p(n,o,s.document)),!0;if("inject"===r.type){if("inject"===s?.phase){if(o.waiting&&s.document===o.documentId)return!0;p(n,o,s.document)}else o.waiting&&(o.cancelPrevious?.(new Error("The iframe document has changed")),o.cancelPrevious=void 0,o.documentId=void 0),o.hasHandshake=!0,o.waiting=!1;return!1}return Boolean(s&&(o.waiting&&!o.cancelPrevious||s.document!==o.documentId))}const y=new WeakMap;function v(e){const t=window,r=e.onMessage,o=[()=>t.removeEventListener("message",r)];y.set(e,()=>{let e,t=!1;for(const r of o)try{r()}catch(n){t||(t=!0,e=n)}if(t)throw e}),t.addEventListener("message",r),e.$iframe.src=e.url;const s=function(e){const t={source:f(e),rawSource:m(e),hasHandshake:!1,waiting:!1};return u.set(e,t),c(e,{prepare:()=>w(e),envelope:e=>t.documentId?n(e,t.documentId,"message"):e}),{start(){"function"===typeof window.MutationObserver&&(t.observer=new window.MutationObserver(n=>{e.destroyed||l(e,t,n)}),t.observer.observe(e.$iframe,{attributes:!0,attributeOldValue:!0,attributeFilter:["src","srcdoc"]}))},dispose(){u.delete(e),c(e,void 0),t.cancelPrevious=void 0,t.observer?.disconnect()}}}(e);o.push(s.dispose),s.start()}function b(e){const t=y.get(e);y.delete(e);try{t?.()}finally{d(e)}}class E{static get iframe(){return window.top!==window}static postMessage({type:e,data:t,id:r=0}){if(!E.iframe)throw new Error('The "ArtplayerToolIframe.postMessage" method can only be used in iframe');var s;window.parent.postMessage((s={type:e,data:t,id:r},o&&("inject"===s.type||o.acknowledged)?n(s,o.id,"inject"===s.type?"inject":"message"):s),"*")}static async onMessage(n){if(!E.iframe)throw new Error('The "ArtplayerToolIframe.onMessage" method can only be used in iframe');if(!r(n,window.parent)||function(n){const r=t(n);return!!r&&(n.type===e?(o&&r.document===o.id&&"ack"===r.phase&&(o.acknowledged=!0),!0):!o||r.document!==o.id)}(n.data))return;const{type:s,data:i,id:a}=n.data;if("commit"===s)try{if(i.match(/\bresolve\((.*?)\)/)){const e=`return new Promise(function(resolve){\n${i}\n})`,t=await new Function(e)();E.postMessage({type:"response",data:t,id:a})}else{const e=new Function(i)();E.postMessage({type:"response",data:e,id:a})}}catch(c){throw E.postMessage({type:"error",data:c.message,id:a}),c}}static inject(){if(!E.iframe)throw new Error('The "ArtplayerToolIframe.inject" method can only be used in iframe');!function(){if(o?.owner===window.document&&o)return;const e=new Uint32Array(4);window.crypto?.getRandomValues?window.crypto.getRandomValues(e):e.forEach((t,n)=>e[n]=Math.floor(4294967296*Math.random())),o={owner:window.document,id:`${Date.now()}-${Array.from(e).join("-")}`,acknowledged:!1,lifecycle:!1,receivers:new Set}}(),E.postMessage({type:"inject"}),function(t){const r=o,s=!r.receivers.has(t),i=!r.lifecycle,a=(t,o)=>{if(r.acknowledged)try{window.parent.postMessage(n({type:e,data:o,id:0},r.id,t),"*")}catch{}},c=()=>a("leave"),d=()=>a("fragment",window.location.href),u=e=>{e.persisted&&a("resume")};try{if(window.addEventListener("message",t),r.receivers.add(t),!i)return;window.addEventListener("pagehide",c),window.addEventListener("pageshow",u),window.addEventListener("hashchange",d),r.lifecycle=!0}catch(f){const e=[];i&&(e.push(()=>window.removeEventListener("pagehide",c)),e.push(()=>window.removeEventListener("pageshow",u)),e.push(()=>window.removeEventListener("hashchange",d))),s&&e.push(()=>window.removeEventListener("message",t));for(const t of e)try{t()}catch{}throw s&&r.receivers.delete(t),f}}(E.onMessage)}constructor({iframe:e,url:t}){if(e instanceof HTMLIFrameElement===!1)throw new TypeError('"option.iframe" needs to be a HTMLIFrameElement');if("string"!==typeof t)throw new TypeError('"option.url" needs to be a string');this.url=t,this.$iframe=e,this.promises={},this.injected=!1,this.destroyed=!1,this.messageCallback=()=>null,this.onMessage=this.onMessage.bind(this);try{v(this)}catch(n){this.destroyed=!0;try{b(this)}catch{}throw n}}onMessage(e){if(this.destroyed||!r(e,this.$iframe.contentWindow)||g(this,e.data))return;const{type:t,data:n,id:o}=e.data;if("inject"===t)this.injected=!0;void 0!==o&&Object.prototype.hasOwnProperty.call(this.promises,o)&&this.promises[o]&&("error"===t?this.promises[o].reject(new Error(n)):this.promises[o].resove(n),delete this.promises[o]),this.messageCallback&&this.messageCallback({type:t,data:n})}postMessage(e){return w(this),function(e,{type:t,data:n}){return new Promise((r,o)=>{if(e.destroyed)return void o(new Error("The instance has been destroyed"));const c=s.get(e)||new Set;s.set(e,c);const d=t=>!!c.delete(t)&&(void 0!==t.timer&&clearTimeout(t.timer),void 0!==t.id&&delete e.promises[t.id],c.size||s.delete(e),!0),u={callbacks:{resove(e){d(u)&&r(e)},reject(e){d(u)&&o(e)}},cancel(e){d(u)&&o(e)}};c.add(u);const f=()=>{if(u.timer=void 0,c.has(u))if(e.destroyed)u.cancel(new Error("The instance has been destroyed"));else try{if(i.get(e)?.prepare(),!c.has(u))return;if(e.injected){const r=Math.max(Date.now(),a+1);a=r,u.id=r,e.promises[r]=u.callbacks;const o={type:t,data:n,id:r};e.$iframe.contentWindow.postMessage(i.get(e)?.envelope(o)||o,"*")}else u.timer=setTimeout(f,200)}catch(r){u.cancel(r)}};f()})}(this,e)}commit(e){if("function"!==typeof e)throw new TypeError('"commit.callback" needs to be a function');const t=e.toString(),n=t.substring(t.indexOf("{")+1,t.lastIndexOf("}"));return this.postMessage({type:"commit",data:n})}message(e){if("function"!==typeof e)throw new TypeError('"message.callback" needs to be a function');this.messageCallback=e}destroy(){this.destroyed=!0,b(this)}}return E});
|