diff --git a/docs/compiled/artplayer-plugin-vast.js b/docs/compiled/artplayer-plugin-vast.js index 584b1ee3a..1de2899bd 100644 --- a/docs/compiled/artplayer-plugin-vast.js +++ b/docs/compiled/artplayer-plugin-vast.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginVast=e(),define(function(){return t.artplayerPluginVast})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginVast=e()}(this,function(){"use strict";var t=null,e=function(){t=null};function i(t,e,i){return e&&function(t,e){for(var i=0;it.length)&&(e=t.length);for(var i=0,n=new Array(e);i-1&&(f(this,Q)[Q].splice(e,1),this.g(f(this,Q)[Q]))},n.resizeAd=function(t,e){f(this,j)[j]=t,f(this,N)[N]=e,f(this,M)[M]&&f(this,M)[M].resize(t,e,this.k()),f(this,_)[_].style.width=t+"px",f(this,_)[_].style.height=e+"px"},n.reset=function(t){void 0===t&&(t=!1),t&&(f(this,F)[F]=!1,f(this,G)[G]=!1,f(this,W)[W]=!1),this.C(),f(this,Q)[Q]=[],f(this,Z)[Z]=!1,f(this,$)[$]=void 0,f(this,M)[M]&&f(this,M)[M].destroy(),f(this,M)[M]=void 0,f(this,I)[I].settings.setAutoPlayAdBreaks(!0),t&&this.P(),f(this,_)[_].style.display="none"},n.P=function(){f(this,U)[U]&&(f(this,U)[U].removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),f(this,U)[U].removeEventListener(f(this,I)[I].AdErrorEvent.Type.AD_ERROR,this.l,!1),f(this,U)[U].destroy()),f(this,L)[L]&&f(this,L)[L].destroy()},n.destroy=function(){var t,e,i,n,r=this;this.reset(!0),f(this,C)[C].destroy(),T.forEach(function(t){f(r,D)[D].removeEventListener(t,r.o)}),null==(t=f(this,U)[U])||t.removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),null==(e=f(this,L)[L])||e.destroy(),null==(i=f(this,U)[U])||i.destroy(),f(this,F)[F]=!1,f(this,W)[W]=!1,f(this,G)[G]=!1,null==(n=f(this,B)[B])||n.disconnect()},n.isCustomPlaybackUsed=function(){return!1===f(this,I)[I].settings.getDisableCustomPlaybackForIOS10Plus()&&!f(this,_)[_].querySelector("video")},n.C=function(){window.clearTimeout(f(this,Y)[Y]),window.clearTimeout(f(this,X)[X]),f(this,Y)[Y]=void 0,f(this,X)[X]=void 0,f(this,V)[V]=void 0,f(this,q)[q]=void 0,f(this,K)[K]=void 0,f(this,_)[_].style.display="none",f(this,_)[_].classList.remove("nonlinear"),f(this,M)[M]&&this.R()},n.o=function(t){var e=this;if(f(this,C)[C].enabled||"volumechange"===t.type){if("timeupdate"===t.type){if(f(this,M)[M]){var i=f(this,M)[M].getCuePoints().filter(function(t){return t>=0&&t=.5&&(this.dispatchEvent(new A(R.MEDIA_IMPRESSION)),f(this,F)[F]=!0)}if("play"!==t.type||f(this,G)[G]||f(this,H)[H]||(this.dispatchEvent(new A(R.MEDIA_START)),f(this,G)[G]=!0),"ended"===t.type&&(this.isCustomPlaybackUsed()&&f(this,D)[D].currentTime===f(this,D)[D].duration&&f(this,Q)[Q].indexOf(-1)>-1&&(f(this,D)[D].currentTime=f(this,D)[D].duration-1e-5,f(this,W)[W]=!0),f(this,U)[U].contentComplete(),f(this,M)[M]||this.T()),!window.ResizeObserver&&f(this,z)[z].autoResize&&"loadedmetadata"===t.type){var n=f(this,D)[D],r=n.offsetHeight,s=n.offsetWidth;f(this,j)[j]=s,f(this,N)[N]=r,this.R()}f(this,H)[H]&&"volumechange"!==t.type||this.dispatchEvent(new A(t.type))}},n.S=function(t){var e=this,i=f(this,I)[I].AdEvent;switch(t.type){case i.Type.LOADED:var n=t.getAd();f(this,$)[$]&&0===f(this,Q)[Q].length?f(this,$)[$]({ad:n,start:function(){e.M(),f(e,$)[$]=void 0},startWithoutReset:function(){e.M()}}):f(this,x)[x]=n;break;case i.Type.AD_BREAK_READY:this.C(),f(this,$)[$]?(f(this,$)[$]({ad:f(this,x)[x],adBreakTime:t.getAdData().adBreakTime,start:function(){e.M(),f(e,$)[$]=void 0},startWithoutReset:function(){e.M()}}),f(this,x)[x]=void 0):this.M();break;case i.Type.STARTED:var r=f(this,V)[V]=t.getAd();r.getAdPodInfo().getAdPosition()>1&&f(this,M)[M].setVolume(f(this,M)[M].getVolume()),f(this,_)[_].classList.remove("nonlinear"),this.R(),r.isLinear()?(f(this,C)[C].disable(),f(this,K)[K]=r.getDuration(),f(this,q)[q]=0):(f(this,_)[_].classList.add("nonlinear"),this.I()),f(this,_)[_].style.display="",f(this,Z)[Z]&&(f(this,Z)[Z]=!1,f(this,M)[M].pause());break;case i.Type.ALL_ADS_COMPLETED:if(f(this,W)[W])return;this.isCustomPlaybackUsed()&&Boolean(f(this,V)[V])&&-1!==f(this,V)[V].getAdPodInfo().getTimeOffset()&&this.I(),this.reset();break;case i.Type.CONTENT_PAUSE_REQUESTED:this.C(),f(this,V)[V]=t.getAd(),f(this,_)[_].style.display="",f(this,D)[D].pause(),this.R(),f(this,V)[V]&&this.A(f(this,V)[V].getAdPodInfo().getTimeOffset()),f(this,M)[M].setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),f(this,C)[C].disable(),f(this,K)[K]=f(this,V)[V].getDuration(),f(this,q)[q]=0;break;case i.Type.CONTENT_RESUME_REQUESTED:var s=Boolean(f(this,V)[V]);if(s){var o=f(this,M)[M].getVolume();f(this,D)[D].muted=0===o,f(this,D)[D].volume=f(this,J)[J]}f(this,W)[W]&&(f(this,D)[D].currentTime=f(this,D)[D].duration+1,f(this,W)[W]=!1),f(this,D)[D].ended?(this.reset(),this.T()):this.C(),s&&(f(this,Z)[Z]=!1,this.I());break;case i.Type.AD_METADATA:this.g(f(this,M)[M].getCuePoints()),-1===f(this,Q)[Q].indexOf(0)&&(f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):this.I());break;case i.Type.AD_PROGRESS:var a=t.getAdData();f(this,q)[q]=a.currentTime,f(this,K)[K]=a.duration;break;case i.Type.LOG:var u=t.getAdData();f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):u.adError&&!f(this,V)[V]&&this.I();break;case i.Type.VOLUME_CHANGED:var h=f(this,M)[M].getVolume();h>0&&(f(this,J)[J]=h)}},n.l=function(t){this.j(this.B(t))},n.u=function(t){var e=this,i=f(this,I)[I],n=i.AdEvent,r=i.AdErrorEvent.Type.AD_ERROR;window.clearTimeout(f(this,Y)[Y]);var s=f(this,M)[M]=t.getAdsManager(f(this,C)[C],f(this,k)[k]);Object.keys(n.Type).forEach(function(t){s.addEventListener(n.Type[t],function(i){if(e.S(i),R[t]){var n=["LOG","AD_PROGRESS"].indexOf(t)>-1;e.dispatchEvent(new A(R[t],{detail:{ad:i.getAd()||f(e,V)[V],adData:n?i.getAdData():{}}}))}})}),s.addEventListener(r,function(t){return e.j(e.B(t))});try{var o;s.init(f(this,j)[j],f(this,N)[N],this.k()),s.setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),null==(o=f(this,L)[L])||o.initialize(),f(this,$)[$]||this.M()}catch(a){this.j(new S(a.message))}},n.M=function(){if(f(this,G)[G]||(this.dispatchEvent(new A(R.MEDIA_START)),f(this,G)[G]=!0),f(this,M)[M])try{f(this,M)[M].start()}catch(t){this.j(new S(t.message))}else this.I()},n.T=function(){var t=this;setTimeout(function(){f(t,F)[F]=!1,f(t,G)[G]=!1,f(t,W)[W]=!1,t.dispatchEvent(new A(R.MEDIA_STOP))},1)},n.v=function(t){for(var e,i=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(e)return(e=e.call(t)).next.bind(e);if(Array.isArray(t)||(e=function(t,e){if(t){if("string"==typeof t)return d(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?d(t,e):void 0}}(t))){e&&(t=e);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(t);!(e=i()).done;){var n=e.value;n.contentBoxSize&&1===n.contentBoxSize.length?(f(this,j)[j]=n.contentBoxSize[0].inlineSize,f(this,N)[N]=n.contentBoxSize[0].blockSize):n.contentBoxSize&&n.contentBoxSize.inlineSize?(f(this,j)[j]=n.contentBoxSize.inlineSize,f(this,N)[N]=n.contentBoxSize.blockSize):(f(this,j)[j]=n.contentRect.width,f(this,N)[N]=n.contentRect.height)}this.R()},n.R=function(){if(f(this,z)[z].autoResize&&f(this,M)[M]){var t=f(this,V)[V],e=this.k();t&&!t.isLinear()?t&&(t.getWidth()>f(this,j)[j]||t.getHeight()>f(this,N)[N]?this.resizeAd(f(this,j)[j],f(this,N)[N]):(f(this,M)[M].resize(t.getWidth(),t.getHeight()+20,e),f(this,_)[_].style.width=t.getWidth()+"px",f(this,_)[_].style.height=t.getHeight()+20+"px")):this.resizeAd(f(this,j)[j],f(this,N)[N])}},n.k=function(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||f(this,D)[D].webkitDisplayingFullscreen?f(this,I)[I].ViewMode.FULLSCREEN:f(this,I)[I].ViewMode.NORMAL},n.I=function(){var t=this;f(this,_)[_].style.display="none",f(this,D)[D].ended||(f(this,C)[C].enable(),f(this,Z)[Z]?(f(this,D)[D].pause(),this.dispatchEvent(new A("pause"))):(this.p().then(function(){}).catch(function(){t.dispatchEvent(new A("pause"))}),this.dispatchEvent(new A("play")),this.dispatchEvent(new A(R.MEDIA_RESUMED))),f(this,Z)[Z]=!1)},n.B=function(t){var e=t.getError(),i=new S(e.getMessage());return i.type=e.getType(),i.errorCode=e.getErrorCode(),i.vastErrorCode=e.getVastErrorCode&&e.getVastErrorCode(),i.innerError=e.getInnerError(),i},n.j=function(t){var e=this;this.dispatchEvent(new A(R.AD_ERROR,{detail:{error:t}})),this.C(),f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):this.I()},i(e,[{key:"volume",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?f(this,M)[M].getVolume():f(this,D)[D].volume},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t),f(this,D)[D].volume=t}},{key:"muted",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?0===f(this,M)[M].getVolume():f(this,D)[D].muted},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t?0:f(this,J)[J]),f(this,D)[D].muted=t}},{key:"currentTime",get:function(){return void 0!==f(this,q)[q]?f(this,q)[q]:f(this,D)[D].currentTime},set:function(t){f(this,C)[C].enabled&&(f(this,D)[D].currentTime=t)}},{key:"duration",get:function(){return void 0!==f(this,K)[K]?f(this,K)[K]:f(this,D)[D].duration}},{key:"cuePoints",get:function(){return[].concat(f(this,Q)[Q])}}]),e}(w);let it=0;function nt(t){const e=t.createElement("div");return e.id=`art-vast-${Date.now()}-${++it}`,t.setStyles(e,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"150",backgroundColor:"black",display:"none",pointerEvents:"auto"}),e}function rt(i){return async n=>{let r,s=!1;const o=()=>s||n.isDestroy,a={name:"artplayerPluginVast",destroy:()=>r?.destroy()};function u(){if(!s){s=!0;try{n.off("destroy",u)}finally{r?.destroy()}}}if(o())return a;n.on("destroy",u);try{if(o())return a;const s=await function(){var i=window;return i.google&&i.google.ima?Promise.resolve(i.google.ima):t||((t=new Promise(function(t,e){var i=document.createElement("script");i.async=!0,i.src="https://imasdk.googleapis.com/js/sdkloader/ima3.js",i.onload=t,i.onerror=e,document.body.appendChild(i)}).then(function(){return i.google.ima})).then(e).catch(e),t)}();if(o())return a;const h=n.constructor.utils;return r=function(t,e,i,n){const{$video:r,$player:s}=t.template,o=new e.AdsRenderingSettings;o.restoreCustomPlaybackStateOnAdBreakComplete=!0,o.enablePreloading=!0;const a=new P;let u=null,h=!1,d=0;const l=t=>u===t&&!t.released&&!n();function c(t){u===t&&(u=null),t.released=!0,t.playing=!1;const e=t.player;t.player=null;const i=t.listeners.splice(0);let n,r=!1;const s=t=>{try{t()}catch(e){r?console.error("VAST cleanup error:",e):(r=!0,n=e)}};d++;try{if(e){for(const[t,n]of i)s(()=>e.removeEventListener(t,n));s(()=>e.destroy())}s(()=>{t.container.parentNode&&t.container.parentNode.removeChild(t.container)})}finally{d--}if(r)throw n}function f(){if(n()||d)return null;if(h)throw new Error("VAST initialization is already in progress");if(u?.player)return u.player;let t;h=!0;try{if(t={container:nt(i),player:null,listeners:[],playing:!1,released:!1},u=t,!l(t))return c(t),null;if(s.appendChild(t.container),!l(t))return c(t),null;if(t.player=new et(e,r,t.container,o,a),!l(t))return c(t),null;const n=t;for(const[e,i]of[["AdContentPauseRequested",!0],["AdContentResumeRequested",!1],["AdStarted",!0],["AdError",!1]]){const r=t=>{l(n)&&("AdError"===e&&console.error("VAST Ad Error:",t.detail),n.playing=i,n.container.style.display=i?"block":"none")};if(t.listeners.push([e,r]),t.player.addEventListener(e,r),!l(t))return c(t),null}return t.player}catch(f){if(t)try{c(t)}catch(p){console.error("VAST cleanup error:",p)}throw f}finally{h=!1}}function p(t,i,r){if(n()||u?.playing)return;const s=f(),o=u;if(!s||!o)return;const a=function(t,e,i,n){const r=new t.AdsRequest;r[e]=i;const s=r;for(const o in n)s[o]=n[o];return r}(e,t,i,r);l(o)&&o.player===s&&s.playAds(a)}return{context:{art:t,playUrl:(t,e={})=>p("adTagUrl",t,e),playRes:(t,e={})=>p("adsResponse",t,e),init:f,ima:e,adsRenderingSettings:o,playerOptions:a,get imaPlayer(){return u?.player||null},get container(){return u?.container||null}},destroy:function(){u&&c(u)}}}(n,s,h,o),o()?(u(),a):("function"===typeof i&&await i(r.context),a)}catch(h){try{u()}catch(d){console.error("VAST cleanup error:",d)}throw h}}}return rt.default=rt,rt}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginVast=e(),define(function(){return t.artplayerPluginVast})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginVast=e()}(this,function(){"use strict";var t=null,e=function(){t=null};function i(t,e,i){return e&&function(t,e){for(var i=0;it.length)&&(e=t.length);for(var i=0,n=new Array(e);i-1&&(f(this,Q)[Q].splice(e,1),this.g(f(this,Q)[Q]))},n.resizeAd=function(t,e){f(this,j)[j]=t,f(this,N)[N]=e,f(this,M)[M]&&f(this,M)[M].resize(t,e,this.k()),f(this,_)[_].style.width=t+"px",f(this,_)[_].style.height=e+"px"},n.reset=function(t){void 0===t&&(t=!1),t&&(f(this,F)[F]=!1,f(this,G)[G]=!1,f(this,W)[W]=!1),this.C(),f(this,Q)[Q]=[],f(this,Z)[Z]=!1,f(this,K)[K]=void 0,f(this,M)[M]&&f(this,M)[M].destroy(),f(this,M)[M]=void 0,f(this,I)[I].settings.setAutoPlayAdBreaks(!0),t&&this.P(),f(this,_)[_].style.display="none"},n.P=function(){f(this,U)[U]&&(f(this,U)[U].removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),f(this,U)[U].removeEventListener(f(this,I)[I].AdErrorEvent.Type.AD_ERROR,this.l,!1),f(this,U)[U].destroy()),f(this,L)[L]&&f(this,L)[L].destroy()},n.destroy=function(){var t,e,i,n,r=this;this.reset(!0),f(this,C)[C].destroy(),T.forEach(function(t){f(r,D)[D].removeEventListener(t,r.o)}),null==(t=f(this,U)[U])||t.removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),null==(e=f(this,L)[L])||e.destroy(),null==(i=f(this,U)[U])||i.destroy(),f(this,F)[F]=!1,f(this,W)[W]=!1,f(this,G)[G]=!1,null==(n=f(this,B)[B])||n.disconnect()},n.isCustomPlaybackUsed=function(){return!1===f(this,I)[I].settings.getDisableCustomPlaybackForIOS10Plus()&&!f(this,_)[_].querySelector("video")},n.C=function(){window.clearTimeout(f(this,Y)[Y]),window.clearTimeout(f(this,X)[X]),f(this,Y)[Y]=void 0,f(this,X)[X]=void 0,f(this,V)[V]=void 0,f(this,q)[q]=void 0,f(this,$)[$]=void 0,f(this,_)[_].style.display="none",f(this,_)[_].classList.remove("nonlinear"),f(this,M)[M]&&this.R()},n.o=function(t){var e=this;if(f(this,C)[C].enabled||"volumechange"===t.type){if("timeupdate"===t.type){if(f(this,M)[M]){var i=f(this,M)[M].getCuePoints().filter(function(t){return t>=0&&t=.5&&(this.dispatchEvent(new A(P.MEDIA_IMPRESSION)),f(this,F)[F]=!0)}if("play"!==t.type||f(this,G)[G]||f(this,H)[H]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),"ended"===t.type&&(this.isCustomPlaybackUsed()&&f(this,D)[D].currentTime===f(this,D)[D].duration&&f(this,Q)[Q].indexOf(-1)>-1&&(f(this,D)[D].currentTime=f(this,D)[D].duration-1e-5,f(this,W)[W]=!0),f(this,U)[U].contentComplete(),f(this,M)[M]||this.T()),!window.ResizeObserver&&f(this,z)[z].autoResize&&"loadedmetadata"===t.type){var n=f(this,D)[D],r=n.offsetHeight,s=n.offsetWidth;f(this,j)[j]=s,f(this,N)[N]=r,this.R()}f(this,H)[H]&&"volumechange"!==t.type||this.dispatchEvent(new A(t.type))}},n.S=function(t){var e=this,i=f(this,I)[I].AdEvent;switch(t.type){case i.Type.LOADED:var n=t.getAd();f(this,K)[K]&&0===f(this,Q)[Q].length?f(this,K)[K]({ad:n,start:function(){e.M(),f(e,K)[K]=void 0},startWithoutReset:function(){e.M()}}):f(this,x)[x]=n;break;case i.Type.AD_BREAK_READY:this.C(),f(this,K)[K]?(f(this,K)[K]({ad:f(this,x)[x],adBreakTime:t.getAdData().adBreakTime,start:function(){e.M(),f(e,K)[K]=void 0},startWithoutReset:function(){e.M()}}),f(this,x)[x]=void 0):this.M();break;case i.Type.STARTED:var r=f(this,V)[V]=t.getAd();r.getAdPodInfo().getAdPosition()>1&&f(this,M)[M].setVolume(f(this,M)[M].getVolume()),f(this,_)[_].classList.remove("nonlinear"),this.R(),r.isLinear()?(f(this,C)[C].disable(),f(this,$)[$]=r.getDuration(),f(this,q)[q]=0):(f(this,_)[_].classList.add("nonlinear"),this.I()),f(this,_)[_].style.display="",f(this,Z)[Z]&&(f(this,Z)[Z]=!1,f(this,M)[M].pause());break;case i.Type.ALL_ADS_COMPLETED:if(f(this,W)[W])return;this.isCustomPlaybackUsed()&&Boolean(f(this,V)[V])&&-1!==f(this,V)[V].getAdPodInfo().getTimeOffset()&&this.I(),this.reset();break;case i.Type.CONTENT_PAUSE_REQUESTED:this.C(),f(this,V)[V]=t.getAd(),f(this,_)[_].style.display="",f(this,D)[D].pause(),this.R(),f(this,V)[V]&&this.A(f(this,V)[V].getAdPodInfo().getTimeOffset()),f(this,M)[M].setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),f(this,C)[C].disable(),f(this,$)[$]=f(this,V)[V].getDuration(),f(this,q)[q]=0;break;case i.Type.CONTENT_RESUME_REQUESTED:var s=Boolean(f(this,V)[V]);if(s){var o=f(this,M)[M].getVolume();f(this,D)[D].muted=0===o,f(this,D)[D].volume=f(this,J)[J]}f(this,W)[W]&&(f(this,D)[D].currentTime=f(this,D)[D].duration+1,f(this,W)[W]=!1),f(this,D)[D].ended?(this.reset(),this.T()):this.C(),s&&(f(this,Z)[Z]=!1,this.I());break;case i.Type.AD_METADATA:this.g(f(this,M)[M].getCuePoints()),-1===f(this,Q)[Q].indexOf(0)&&(f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):this.I());break;case i.Type.AD_PROGRESS:var a=t.getAdData();f(this,q)[q]=a.currentTime,f(this,$)[$]=a.duration;break;case i.Type.LOG:var u=t.getAdData();f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):u.adError&&!f(this,V)[V]&&this.I();break;case i.Type.VOLUME_CHANGED:var d=f(this,M)[M].getVolume();d>0&&(f(this,J)[J]=d)}},n.l=function(t){this.j(this.B(t))},n.u=function(t){var e=this,i=f(this,I)[I],n=i.AdEvent,r=i.AdErrorEvent.Type.AD_ERROR;window.clearTimeout(f(this,Y)[Y]);var s=f(this,M)[M]=t.getAdsManager(f(this,C)[C],f(this,k)[k]);Object.keys(n.Type).forEach(function(t){s.addEventListener(n.Type[t],function(i){if(e.S(i),P[t]){var n=["LOG","AD_PROGRESS"].indexOf(t)>-1;e.dispatchEvent(new A(P[t],{detail:{ad:i.getAd()||f(e,V)[V],adData:n?i.getAdData():{}}}))}})}),s.addEventListener(r,function(t){return e.j(e.B(t))});try{var o;s.init(f(this,j)[j],f(this,N)[N],this.k()),s.setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),null==(o=f(this,L)[L])||o.initialize(),f(this,K)[K]||this.M()}catch(a){this.j(new S(a.message))}},n.M=function(){if(f(this,G)[G]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),f(this,M)[M])try{f(this,M)[M].start()}catch(t){this.j(new S(t.message))}else this.I()},n.T=function(){var t=this;setTimeout(function(){f(t,F)[F]=!1,f(t,G)[G]=!1,f(t,W)[W]=!1,t.dispatchEvent(new A(P.MEDIA_STOP))},1)},n.v=function(t){for(var e,i=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(e)return(e=e.call(t)).next.bind(e);if(Array.isArray(t)||(e=function(t,e){if(t){if("string"==typeof t)return h(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?h(t,e):void 0}}(t))){e&&(t=e);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(t);!(e=i()).done;){var n=e.value;n.contentBoxSize&&1===n.contentBoxSize.length?(f(this,j)[j]=n.contentBoxSize[0].inlineSize,f(this,N)[N]=n.contentBoxSize[0].blockSize):n.contentBoxSize&&n.contentBoxSize.inlineSize?(f(this,j)[j]=n.contentBoxSize.inlineSize,f(this,N)[N]=n.contentBoxSize.blockSize):(f(this,j)[j]=n.contentRect.width,f(this,N)[N]=n.contentRect.height)}this.R()},n.R=function(){if(f(this,z)[z].autoResize&&f(this,M)[M]){var t=f(this,V)[V],e=this.k();t&&!t.isLinear()?t&&(t.getWidth()>f(this,j)[j]||t.getHeight()>f(this,N)[N]?this.resizeAd(f(this,j)[j],f(this,N)[N]):(f(this,M)[M].resize(t.getWidth(),t.getHeight()+20,e),f(this,_)[_].style.width=t.getWidth()+"px",f(this,_)[_].style.height=t.getHeight()+20+"px")):this.resizeAd(f(this,j)[j],f(this,N)[N])}},n.k=function(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||f(this,D)[D].webkitDisplayingFullscreen?f(this,I)[I].ViewMode.FULLSCREEN:f(this,I)[I].ViewMode.NORMAL},n.I=function(){var t=this;f(this,_)[_].style.display="none",f(this,D)[D].ended||(f(this,C)[C].enable(),f(this,Z)[Z]?(f(this,D)[D].pause(),this.dispatchEvent(new A("pause"))):(this.p().then(function(){}).catch(function(){t.dispatchEvent(new A("pause"))}),this.dispatchEvent(new A("play")),this.dispatchEvent(new A(P.MEDIA_RESUMED))),f(this,Z)[Z]=!1)},n.B=function(t){var e=t.getError(),i=new S(e.getMessage());return i.type=e.getType(),i.errorCode=e.getErrorCode(),i.vastErrorCode=e.getVastErrorCode&&e.getVastErrorCode(),i.innerError=e.getInnerError(),i},n.j=function(t){var e=this;this.dispatchEvent(new A(P.AD_ERROR,{detail:{error:t}})),this.C(),f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):this.I()},i(e,[{key:"volume",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?f(this,M)[M].getVolume():f(this,D)[D].volume},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t),f(this,D)[D].volume=t}},{key:"muted",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?0===f(this,M)[M].getVolume():f(this,D)[D].muted},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t?0:f(this,J)[J]),f(this,D)[D].muted=t}},{key:"currentTime",get:function(){return void 0!==f(this,q)[q]?f(this,q)[q]:f(this,D)[D].currentTime},set:function(t){f(this,C)[C].enabled&&(f(this,D)[D].currentTime=t)}},{key:"duration",get:function(){return void 0!==f(this,$)[$]?f(this,$)[$]:f(this,D)[D].duration}},{key:"cuePoints",get:function(){return[].concat(f(this,Q)[Q])}}]),e}(w);let it=0;function nt(t,e){const i=t.createElement("div");return i.id=`${e?"art-vast-":"art-"}${Date.now()}-${++it}`,t.setStyles(i,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"150",display:"none"}),e&&t.setStyles(i,{backgroundColor:"black",pointerEvents:"auto"}),i}function rt(i,n={}){const r=n.compatibility;if(void 0!==r&&"workspace-1.2"!==r)throw new TypeError("Unsupported VAST compatibility mode");const s="workspace-1.2"===r;return async n=>{let r,o=!1;const a=()=>o||n.isDestroy,u={name:"artplayerPluginVast",destroy:()=>r?.destroy()};function d(){if(!o){o=!0;try{n.off("destroy",d)}finally{r?.destroy()}}}if(a())return u;n.on("destroy",d);try{if(a())return u;const o=await function(){var i=window;return i.google&&i.google.ima?Promise.resolve(i.google.ima):t||((t=new Promise(function(t,e){var i=document.createElement("script");i.async=!0,i.src="https://imasdk.googleapis.com/js/sdkloader/ima3.js",i.onload=t,i.onerror=e,document.body.appendChild(i)}).then(function(){return i.google.ima})).then(e).catch(e),t)}();if(a())return u;const h=n.constructor.utils;return r=function(t,e,i,n,r){const{$video:s,$player:o}=t.template,a=new e.AdsRenderingSettings;r&&(a.restoreCustomPlaybackStateOnAdBreakComplete=!0,a.enablePreloading=!0);const u=new R;let d=null,h=!1,l=0;const c={art:t,playUrl:(t,e={})=>y("adTagUrl",t,e),playRes:(t,e={})=>y("adsResponse",t,e),init:v,ima:e,adsRenderingSettings:a,playerOptions:u,imaPlayer:null,id:null,$container:null,get container(){return d?.container||null}};r&&Object.defineProperties(c,{imaPlayer:{get:()=>d?.player||null},id:{get:()=>d?.container.id||null},$container:{get:()=>d?.container||null}});const f=t=>d===t&&!t.released&&!n();function p(t){d===t&&(d=null),t.released=!0,t.playing=!1;const e=t.player;t.player=null;const i=t.listeners.splice(0);let n,r=!1;const s=t=>{try{t()}catch(e){r?console.error("VAST cleanup error:",e):(r=!0,n=e)}};l++;try{if(e){for(const[t,n]of i)s(()=>e.removeEventListener(t,n));s(()=>e.destroy())}s(()=>{t.container.parentNode&&t.container.parentNode.removeChild(t.container)})}finally{l--}if(r)throw n}function v(){if(n()||l)return null;if(h)throw new Error("VAST initialization is already in progress");if(d?.player)return d.player;let t;h=!0;try{if(t={container:nt(i,r),player:null,listeners:[],playing:!1,released:!1},d=t,!f(t))return p(t),null;if(o.appendChild(t.container),!f(t))return p(t),null;if(t.player=new et(e,s,t.container,a,u),!f(t))return p(t),null;const n=t,h=r?[["AdContentPauseRequested",!0],["AdContentResumeRequested",!1],["AdStarted",!0],["AdError",!1]]:[];for(const[e,i]of h){const r=t=>{f(n)&&("AdError"===e&&console.error("VAST Ad Error:",t.detail),n.playing=i,n.container.style.display=i?"block":"none")};if(t.listeners.push([e,r]),t.player.addEventListener(e,r),!f(t))return p(t),null}return r||Object.defineProperties(c,{imaPlayer:{value:t.player},id:{value:t.container.id},$container:{value:t.container}}),t.player}catch(v){if(t)try{p(t)}catch(y){console.error("VAST cleanup error:",y)}throw v}finally{h=!1}}function y(t,i,s){if(n()||r&&d?.playing)return;const o=v(),a=d;if(!o||!a)return;const u=function(t,e,i,n){const r=new t.AdsRequest;r[e]=i;const s=r;for(const o in n)s[o]=n[o];return r}(e,t,i,s);f(a)&&a.player===o&&o.playAds(u)}return{context:c,destroy:function(){d&&p(d)}}}(n,o,h,a,s),a()?(d(),u):(!s&&(r.context.init(),a())||"function"===typeof i&&await i(r.context),u)}catch(h){try{d()}catch(l){console.error("VAST cleanup error:",l)}throw h}}}return rt.default=rt,rt}); diff --git a/docs/compiled/artplayer-plugin-vast.legacy.js b/docs/compiled/artplayer-plugin-vast.legacy.js index 504c05b1a..1161f5d78 100644 --- a/docs/compiled/artplayer-plugin-vast.legacy.js +++ b/docs/compiled/artplayer-plugin-vast.legacy.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginVast=e(),define(function(){return t.artplayerPluginVast})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginVast=e()}(this,function(){"use strict";var t=null,e=function(){t=null};function i(t,e,i){return e&&function(t,e){for(var i=0;it.length)&&(e=t.length);for(var i=0,n=new Array(e);i-1&&(f(this,Q)[Q].splice(e,1),this.g(f(this,Q)[Q]))},n.resizeAd=function(t,e){f(this,j)[j]=t,f(this,N)[N]=e,f(this,M)[M]&&f(this,M)[M].resize(t,e,this.k()),f(this,_)[_].style.width=t+"px",f(this,_)[_].style.height=e+"px"},n.reset=function(t){void 0===t&&(t=!1),t&&(f(this,F)[F]=!1,f(this,G)[G]=!1,f(this,W)[W]=!1),this.C(),f(this,Q)[Q]=[],f(this,Z)[Z]=!1,f(this,$)[$]=void 0,f(this,M)[M]&&f(this,M)[M].destroy(),f(this,M)[M]=void 0,f(this,I)[I].settings.setAutoPlayAdBreaks(!0),t&&this.P(),f(this,_)[_].style.display="none"},n.P=function(){f(this,U)[U]&&(f(this,U)[U].removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),f(this,U)[U].removeEventListener(f(this,I)[I].AdErrorEvent.Type.AD_ERROR,this.l,!1),f(this,U)[U].destroy()),f(this,L)[L]&&f(this,L)[L].destroy()},n.destroy=function(){var t,e,i,n,r=this;this.reset(!0),f(this,C)[C].destroy(),T.forEach(function(t){f(r,D)[D].removeEventListener(t,r.o)}),null==(t=f(this,U)[U])||t.removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),null==(e=f(this,L)[L])||e.destroy(),null==(i=f(this,U)[U])||i.destroy(),f(this,F)[F]=!1,f(this,W)[W]=!1,f(this,G)[G]=!1,null==(n=f(this,B)[B])||n.disconnect()},n.isCustomPlaybackUsed=function(){return!1===f(this,I)[I].settings.getDisableCustomPlaybackForIOS10Plus()&&!f(this,_)[_].querySelector("video")},n.C=function(){window.clearTimeout(f(this,Y)[Y]),window.clearTimeout(f(this,X)[X]),f(this,Y)[Y]=void 0,f(this,X)[X]=void 0,f(this,x)[x]=void 0,f(this,q)[q]=void 0,f(this,K)[K]=void 0,f(this,_)[_].style.display="none",f(this,_)[_].classList.remove("nonlinear"),f(this,M)[M]&&this.R()},n.o=function(t){var e=this;if(f(this,C)[C].enabled||"volumechange"===t.type){if("timeupdate"===t.type){if(f(this,M)[M]){var i=f(this,M)[M].getCuePoints().filter(function(t){return t>=0&&t=.5&&(this.dispatchEvent(new A(P.MEDIA_IMPRESSION)),f(this,F)[F]=!0)}if("play"!==t.type||f(this,G)[G]||f(this,H)[H]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),"ended"===t.type&&(this.isCustomPlaybackUsed()&&f(this,D)[D].currentTime===f(this,D)[D].duration&&f(this,Q)[Q].indexOf(-1)>-1&&(f(this,D)[D].currentTime=f(this,D)[D].duration-1e-5,f(this,W)[W]=!0),f(this,U)[U].contentComplete(),f(this,M)[M]||this.T()),!window.ResizeObserver&&f(this,z)[z].autoResize&&"loadedmetadata"===t.type){var n=f(this,D)[D],r=n.offsetHeight,s=n.offsetWidth;f(this,j)[j]=s,f(this,N)[N]=r,this.R()}f(this,H)[H]&&"volumechange"!==t.type||this.dispatchEvent(new A(t.type))}},n.S=function(t){var e=this,i=f(this,I)[I].AdEvent;switch(t.type){case i.Type.LOADED:var n=t.getAd();f(this,$)[$]&&0===f(this,Q)[Q].length?f(this,$)[$]({ad:n,start:function(){e.M(),f(e,$)[$]=void 0},startWithoutReset:function(){e.M()}}):f(this,V)[V]=n;break;case i.Type.AD_BREAK_READY:this.C(),f(this,$)[$]?(f(this,$)[$]({ad:f(this,V)[V],adBreakTime:t.getAdData().adBreakTime,start:function(){e.M(),f(e,$)[$]=void 0},startWithoutReset:function(){e.M()}}),f(this,V)[V]=void 0):this.M();break;case i.Type.STARTED:var r=f(this,x)[x]=t.getAd();r.getAdPodInfo().getAdPosition()>1&&f(this,M)[M].setVolume(f(this,M)[M].getVolume()),f(this,_)[_].classList.remove("nonlinear"),this.R(),r.isLinear()?(f(this,C)[C].disable(),f(this,K)[K]=r.getDuration(),f(this,q)[q]=0):(f(this,_)[_].classList.add("nonlinear"),this.I()),f(this,_)[_].style.display="",f(this,Z)[Z]&&(f(this,Z)[Z]=!1,f(this,M)[M].pause());break;case i.Type.ALL_ADS_COMPLETED:if(f(this,W)[W])return;this.isCustomPlaybackUsed()&&Boolean(f(this,x)[x])&&-1!==f(this,x)[x].getAdPodInfo().getTimeOffset()&&this.I(),this.reset();break;case i.Type.CONTENT_PAUSE_REQUESTED:this.C(),f(this,x)[x]=t.getAd(),f(this,_)[_].style.display="",f(this,D)[D].pause(),this.R(),f(this,x)[x]&&this.A(f(this,x)[x].getAdPodInfo().getTimeOffset()),f(this,M)[M].setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),f(this,C)[C].disable(),f(this,K)[K]=f(this,x)[x].getDuration(),f(this,q)[q]=0;break;case i.Type.CONTENT_RESUME_REQUESTED:var s=Boolean(f(this,x)[x]);if(s){var o=f(this,M)[M].getVolume();f(this,D)[D].muted=0===o,f(this,D)[D].volume=f(this,J)[J]}f(this,W)[W]&&(f(this,D)[D].currentTime=f(this,D)[D].duration+1,f(this,W)[W]=!1),f(this,D)[D].ended?(this.reset(),this.T()):this.C(),s&&(f(this,Z)[Z]=!1,this.I());break;case i.Type.AD_METADATA:this.g(f(this,M)[M].getCuePoints()),-1===f(this,Q)[Q].indexOf(0)&&(f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):this.I());break;case i.Type.AD_PROGRESS:var a=t.getAdData();f(this,q)[q]=a.currentTime,f(this,K)[K]=a.duration;break;case i.Type.LOG:var u=t.getAdData();f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):u.adError&&!f(this,x)[x]&&this.I();break;case i.Type.VOLUME_CHANGED:var h=f(this,M)[M].getVolume();h>0&&(f(this,J)[J]=h)}},n.l=function(t){this.j(this.B(t))},n.u=function(t){var e=this,i=f(this,I)[I],n=i.AdEvent,r=i.AdErrorEvent.Type.AD_ERROR;window.clearTimeout(f(this,Y)[Y]);var s=f(this,M)[M]=t.getAdsManager(f(this,C)[C],f(this,k)[k]);Object.keys(n.Type).forEach(function(t){s.addEventListener(n.Type[t],function(i){if(e.S(i),P[t]){var n=["LOG","AD_PROGRESS"].indexOf(t)>-1;e.dispatchEvent(new A(P[t],{detail:{ad:i.getAd()||f(e,x)[x],adData:n?i.getAdData():{}}}))}})}),s.addEventListener(r,function(t){return e.j(e.B(t))});try{var o;s.init(f(this,j)[j],f(this,N)[N],this.k()),s.setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),null==(o=f(this,L)[L])||o.initialize(),f(this,$)[$]||this.M()}catch(a){this.j(new S(a.message))}},n.M=function(){if(f(this,G)[G]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),f(this,M)[M])try{f(this,M)[M].start()}catch(t){this.j(new S(t.message))}else this.I()},n.T=function(){var t=this;setTimeout(function(){f(t,F)[F]=!1,f(t,G)[G]=!1,f(t,W)[W]=!1,t.dispatchEvent(new A(P.MEDIA_STOP))},1)},n.v=function(t){for(var e,i=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(e)return(e=e.call(t)).next.bind(e);if(Array.isArray(t)||(e=function(t,e){if(t){if("string"==typeof t)return d(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?d(t,e):void 0}}(t))){e&&(t=e);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(t);!(e=i()).done;){var n=e.value;n.contentBoxSize&&1===n.contentBoxSize.length?(f(this,j)[j]=n.contentBoxSize[0].inlineSize,f(this,N)[N]=n.contentBoxSize[0].blockSize):n.contentBoxSize&&n.contentBoxSize.inlineSize?(f(this,j)[j]=n.contentBoxSize.inlineSize,f(this,N)[N]=n.contentBoxSize.blockSize):(f(this,j)[j]=n.contentRect.width,f(this,N)[N]=n.contentRect.height)}this.R()},n.R=function(){if(f(this,z)[z].autoResize&&f(this,M)[M]){var t=f(this,x)[x],e=this.k();t&&!t.isLinear()?t&&(t.getWidth()>f(this,j)[j]||t.getHeight()>f(this,N)[N]?this.resizeAd(f(this,j)[j],f(this,N)[N]):(f(this,M)[M].resize(t.getWidth(),t.getHeight()+20,e),f(this,_)[_].style.width=t.getWidth()+"px",f(this,_)[_].style.height=t.getHeight()+20+"px")):this.resizeAd(f(this,j)[j],f(this,N)[N])}},n.k=function(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||f(this,D)[D].webkitDisplayingFullscreen?f(this,I)[I].ViewMode.FULLSCREEN:f(this,I)[I].ViewMode.NORMAL},n.I=function(){var t=this;f(this,_)[_].style.display="none",f(this,D)[D].ended||(f(this,C)[C].enable(),f(this,Z)[Z]?(f(this,D)[D].pause(),this.dispatchEvent(new A("pause"))):(this.p().then(function(){}).catch(function(){t.dispatchEvent(new A("pause"))}),this.dispatchEvent(new A("play")),this.dispatchEvent(new A(P.MEDIA_RESUMED))),f(this,Z)[Z]=!1)},n.B=function(t){var e=t.getError(),i=new S(e.getMessage());return i.type=e.getType(),i.errorCode=e.getErrorCode(),i.vastErrorCode=e.getVastErrorCode&&e.getVastErrorCode(),i.innerError=e.getInnerError(),i},n.j=function(t){var e=this;this.dispatchEvent(new A(P.AD_ERROR,{detail:{error:t}})),this.C(),f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):this.I()},i(e,[{key:"volume",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?f(this,M)[M].getVolume():f(this,D)[D].volume},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t),f(this,D)[D].volume=t}},{key:"muted",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?0===f(this,M)[M].getVolume():f(this,D)[D].muted},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t?0:f(this,J)[J]),f(this,D)[D].muted=t}},{key:"currentTime",get:function(){return void 0!==f(this,q)[q]?f(this,q)[q]:f(this,D)[D].currentTime},set:function(t){f(this,C)[C].enabled&&(f(this,D)[D].currentTime=t)}},{key:"duration",get:function(){return void 0!==f(this,K)[K]?f(this,K)[K]:f(this,D)[D].duration}},{key:"cuePoints",get:function(){return[].concat(f(this,Q)[Q])}}]),e}(w);let it=0;function nt(t){const e=t.createElement("div");return e.id=`art-vast-${Date.now()}-${++it}`,t.setStyles(e,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"150",backgroundColor:"black",display:"none",pointerEvents:"auto"}),e}function rt(i){return n=>{return r=null,s=null,o=function*(){let r,s=!1;const o=()=>s||n.isDestroy,a={name:"artplayerPluginVast",destroy:()=>null==r?void 0:r.destroy()};function u(){if(!s){s=!0;try{n.off("destroy",u)}finally{null==r||r.destroy()}}}if(o())return a;n.on("destroy",u);try{if(o())return a;const s=yield function(){var i=window;return i.google&&i.google.ima?Promise.resolve(i.google.ima):t||((t=new Promise(function(t,e){var i=document.createElement("script");i.async=!0,i.src="https://imasdk.googleapis.com/js/sdkloader/ima3.js",i.onload=t,i.onerror=e,document.body.appendChild(i)}).then(function(){return i.google.ima})).then(e).catch(e),t)}();if(o())return a;const h=n.constructor.utils;return r=function(t,e,i,n){const{$video:r,$player:s}=t.template,o=new e.AdsRenderingSettings;o.restoreCustomPlaybackStateOnAdBreakComplete=!0,o.enablePreloading=!0;const a=new R;let u=null,h=!1,d=0;const l=t=>u===t&&!t.released&&!n();function c(t){u===t&&(u=null),t.released=!0,t.playing=!1;const e=t.player;t.player=null;const i=t.listeners.splice(0);let n,r=!1;const s=t=>{try{t()}catch(e){r?console.error("VAST cleanup error:",e):(r=!0,n=e)}};d++;try{if(e){for(const[t,n]of i)s(()=>e.removeEventListener(t,n));s(()=>e.destroy())}s(()=>{t.container.parentNode&&t.container.parentNode.removeChild(t.container)})}finally{d--}if(r)throw n}function f(){if(n()||d)return null;if(h)throw new Error("VAST initialization is already in progress");if(null==u?void 0:u.player)return u.player;let t;h=!0;try{if(t={container:nt(i),player:null,listeners:[],playing:!1,released:!1},u=t,!l(t))return c(t),null;if(s.appendChild(t.container),!l(t))return c(t),null;if(t.player=new et(e,r,t.container,o,a),!l(t))return c(t),null;const n=t;for(const[e,i]of[["AdContentPauseRequested",!0],["AdContentResumeRequested",!1],["AdStarted",!0],["AdError",!1]]){const r=t=>{l(n)&&("AdError"===e&&console.error("VAST Ad Error:",t.detail),n.playing=i,n.container.style.display=i?"block":"none")};if(t.listeners.push([e,r]),t.player.addEventListener(e,r),!l(t))return c(t),null}return t.player}catch(f){if(t)try{c(t)}catch(p){console.error("VAST cleanup error:",p)}throw f}finally{h=!1}}function p(t,i,r){if(n()||(null==u?void 0:u.playing))return;const s=f(),o=u;if(!s||!o)return;const a=function(t,e,i,n){const r=new t.AdsRequest;r[e]=i;const s=r;for(const o in n)s[o]=n[o];return r}(e,t,i,r);l(o)&&o.player===s&&s.playAds(a)}return{context:{art:t,playUrl:(t,e={})=>p("adTagUrl",t,e),playRes:(t,e={})=>p("adsResponse",t,e),init:f,ima:e,adsRenderingSettings:o,playerOptions:a,get imaPlayer(){return(null==u?void 0:u.player)||null},get container(){return(null==u?void 0:u.container)||null}},destroy:function(){u&&c(u)}}}(n,s,h,o),o()?(u(),a):("function"===typeof i&&(yield i(r.context)),a)}catch(h){try{u()}catch(d){console.error("VAST cleanup error:",d)}throw h}},new Promise((t,e)=>{var i=t=>{try{a(o.next(t))}catch(i){e(i)}},n=t=>{try{a(o.throw(t))}catch(i){e(i)}},a=e=>e.done?t(e.value):Promise.resolve(e.value).then(i,n);a((o=o.apply(r,s)).next())});var r,s,o}}return rt.default=rt,rt}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginVast=e(),define(function(){return t.artplayerPluginVast})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginVast=e()}(this,function(){"use strict";var t=null,e=function(){t=null};function i(t,e,i){return e&&function(t,e){for(var i=0;it.length)&&(e=t.length);for(var i=0,n=new Array(e);i-1&&(f(this,Q)[Q].splice(e,1),this.g(f(this,Q)[Q]))},n.resizeAd=function(t,e){f(this,j)[j]=t,f(this,N)[N]=e,f(this,M)[M]&&f(this,M)[M].resize(t,e,this.k()),f(this,_)[_].style.width=t+"px",f(this,_)[_].style.height=e+"px"},n.reset=function(t){void 0===t&&(t=!1),t&&(f(this,F)[F]=!1,f(this,G)[G]=!1,f(this,W)[W]=!1),this.C(),f(this,Q)[Q]=[],f(this,Z)[Z]=!1,f(this,K)[K]=void 0,f(this,M)[M]&&f(this,M)[M].destroy(),f(this,M)[M]=void 0,f(this,I)[I].settings.setAutoPlayAdBreaks(!0),t&&this.P(),f(this,_)[_].style.display="none"},n.P=function(){f(this,U)[U]&&(f(this,U)[U].removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),f(this,U)[U].removeEventListener(f(this,I)[I].AdErrorEvent.Type.AD_ERROR,this.l,!1),f(this,U)[U].destroy()),f(this,L)[L]&&f(this,L)[L].destroy()},n.destroy=function(){var t,e,i,n,r=this;this.reset(!0),f(this,C)[C].destroy(),T.forEach(function(t){f(r,D)[D].removeEventListener(t,r.o)}),null==(t=f(this,U)[U])||t.removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),null==(e=f(this,L)[L])||e.destroy(),null==(i=f(this,U)[U])||i.destroy(),f(this,F)[F]=!1,f(this,W)[W]=!1,f(this,G)[G]=!1,null==(n=f(this,z)[z])||n.disconnect()},n.isCustomPlaybackUsed=function(){return!1===f(this,I)[I].settings.getDisableCustomPlaybackForIOS10Plus()&&!f(this,_)[_].querySelector("video")},n.C=function(){window.clearTimeout(f(this,Y)[Y]),window.clearTimeout(f(this,X)[X]),f(this,Y)[Y]=void 0,f(this,X)[X]=void 0,f(this,B)[B]=void 0,f(this,q)[q]=void 0,f(this,$)[$]=void 0,f(this,_)[_].style.display="none",f(this,_)[_].classList.remove("nonlinear"),f(this,M)[M]&&this.R()},n.o=function(t){var e=this;if(f(this,C)[C].enabled||"volumechange"===t.type){if("timeupdate"===t.type){if(f(this,M)[M]){var i=f(this,M)[M].getCuePoints().filter(function(t){return t>=0&&t=.5&&(this.dispatchEvent(new A(P.MEDIA_IMPRESSION)),f(this,F)[F]=!0)}if("play"!==t.type||f(this,G)[G]||f(this,H)[H]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),"ended"===t.type&&(this.isCustomPlaybackUsed()&&f(this,D)[D].currentTime===f(this,D)[D].duration&&f(this,Q)[Q].indexOf(-1)>-1&&(f(this,D)[D].currentTime=f(this,D)[D].duration-1e-5,f(this,W)[W]=!0),f(this,U)[U].contentComplete(),f(this,M)[M]||this.T()),!window.ResizeObserver&&f(this,x)[x].autoResize&&"loadedmetadata"===t.type){var n=f(this,D)[D],r=n.offsetHeight,s=n.offsetWidth;f(this,j)[j]=s,f(this,N)[N]=r,this.R()}f(this,H)[H]&&"volumechange"!==t.type||this.dispatchEvent(new A(t.type))}},n.S=function(t){var e=this,i=f(this,I)[I].AdEvent;switch(t.type){case i.Type.LOADED:var n=t.getAd();f(this,K)[K]&&0===f(this,Q)[Q].length?f(this,K)[K]({ad:n,start:function(){e.M(),f(e,K)[K]=void 0},startWithoutReset:function(){e.M()}}):f(this,V)[V]=n;break;case i.Type.AD_BREAK_READY:this.C(),f(this,K)[K]?(f(this,K)[K]({ad:f(this,V)[V],adBreakTime:t.getAdData().adBreakTime,start:function(){e.M(),f(e,K)[K]=void 0},startWithoutReset:function(){e.M()}}),f(this,V)[V]=void 0):this.M();break;case i.Type.STARTED:var r=f(this,B)[B]=t.getAd();r.getAdPodInfo().getAdPosition()>1&&f(this,M)[M].setVolume(f(this,M)[M].getVolume()),f(this,_)[_].classList.remove("nonlinear"),this.R(),r.isLinear()?(f(this,C)[C].disable(),f(this,$)[$]=r.getDuration(),f(this,q)[q]=0):(f(this,_)[_].classList.add("nonlinear"),this.I()),f(this,_)[_].style.display="",f(this,Z)[Z]&&(f(this,Z)[Z]=!1,f(this,M)[M].pause());break;case i.Type.ALL_ADS_COMPLETED:if(f(this,W)[W])return;this.isCustomPlaybackUsed()&&Boolean(f(this,B)[B])&&-1!==f(this,B)[B].getAdPodInfo().getTimeOffset()&&this.I(),this.reset();break;case i.Type.CONTENT_PAUSE_REQUESTED:this.C(),f(this,B)[B]=t.getAd(),f(this,_)[_].style.display="",f(this,D)[D].pause(),this.R(),f(this,B)[B]&&this.A(f(this,B)[B].getAdPodInfo().getTimeOffset()),f(this,M)[M].setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),f(this,C)[C].disable(),f(this,$)[$]=f(this,B)[B].getDuration(),f(this,q)[q]=0;break;case i.Type.CONTENT_RESUME_REQUESTED:var s=Boolean(f(this,B)[B]);if(s){var o=f(this,M)[M].getVolume();f(this,D)[D].muted=0===o,f(this,D)[D].volume=f(this,J)[J]}f(this,W)[W]&&(f(this,D)[D].currentTime=f(this,D)[D].duration+1,f(this,W)[W]=!1),f(this,D)[D].ended?(this.reset(),this.T()):this.C(),s&&(f(this,Z)[Z]=!1,this.I());break;case i.Type.AD_METADATA:this.g(f(this,M)[M].getCuePoints()),-1===f(this,Q)[Q].indexOf(0)&&(f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):this.I());break;case i.Type.AD_PROGRESS:var a=t.getAdData();f(this,q)[q]=a.currentTime,f(this,$)[$]=a.duration;break;case i.Type.LOG:var u=t.getAdData();f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):u.adError&&!f(this,B)[B]&&this.I();break;case i.Type.VOLUME_CHANGED:var l=f(this,M)[M].getVolume();l>0&&(f(this,J)[J]=l)}},n.l=function(t){this.j(this.B(t))},n.u=function(t){var e=this,i=f(this,I)[I],n=i.AdEvent,r=i.AdErrorEvent.Type.AD_ERROR;window.clearTimeout(f(this,Y)[Y]);var s=f(this,M)[M]=t.getAdsManager(f(this,C)[C],f(this,k)[k]);Object.keys(n.Type).forEach(function(t){s.addEventListener(n.Type[t],function(i){if(e.S(i),P[t]){var n=["LOG","AD_PROGRESS"].indexOf(t)>-1;e.dispatchEvent(new A(P[t],{detail:{ad:i.getAd()||f(e,B)[B],adData:n?i.getAdData():{}}}))}})}),s.addEventListener(r,function(t){return e.j(e.B(t))});try{var o;s.init(f(this,j)[j],f(this,N)[N],this.k()),s.setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),null==(o=f(this,L)[L])||o.initialize(),f(this,K)[K]||this.M()}catch(a){this.j(new S(a.message))}},n.M=function(){if(f(this,G)[G]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),f(this,M)[M])try{f(this,M)[M].start()}catch(t){this.j(new S(t.message))}else this.I()},n.T=function(){var t=this;setTimeout(function(){f(t,F)[F]=!1,f(t,G)[G]=!1,f(t,W)[W]=!1,t.dispatchEvent(new A(P.MEDIA_STOP))},1)},n.v=function(t){for(var e,i=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(e)return(e=e.call(t)).next.bind(e);if(Array.isArray(t)||(e=function(t,e){if(t){if("string"==typeof t)return d(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?d(t,e):void 0}}(t))){e&&(t=e);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(t);!(e=i()).done;){var n=e.value;n.contentBoxSize&&1===n.contentBoxSize.length?(f(this,j)[j]=n.contentBoxSize[0].inlineSize,f(this,N)[N]=n.contentBoxSize[0].blockSize):n.contentBoxSize&&n.contentBoxSize.inlineSize?(f(this,j)[j]=n.contentBoxSize.inlineSize,f(this,N)[N]=n.contentBoxSize.blockSize):(f(this,j)[j]=n.contentRect.width,f(this,N)[N]=n.contentRect.height)}this.R()},n.R=function(){if(f(this,x)[x].autoResize&&f(this,M)[M]){var t=f(this,B)[B],e=this.k();t&&!t.isLinear()?t&&(t.getWidth()>f(this,j)[j]||t.getHeight()>f(this,N)[N]?this.resizeAd(f(this,j)[j],f(this,N)[N]):(f(this,M)[M].resize(t.getWidth(),t.getHeight()+20,e),f(this,_)[_].style.width=t.getWidth()+"px",f(this,_)[_].style.height=t.getHeight()+20+"px")):this.resizeAd(f(this,j)[j],f(this,N)[N])}},n.k=function(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||f(this,D)[D].webkitDisplayingFullscreen?f(this,I)[I].ViewMode.FULLSCREEN:f(this,I)[I].ViewMode.NORMAL},n.I=function(){var t=this;f(this,_)[_].style.display="none",f(this,D)[D].ended||(f(this,C)[C].enable(),f(this,Z)[Z]?(f(this,D)[D].pause(),this.dispatchEvent(new A("pause"))):(this.p().then(function(){}).catch(function(){t.dispatchEvent(new A("pause"))}),this.dispatchEvent(new A("play")),this.dispatchEvent(new A(P.MEDIA_RESUMED))),f(this,Z)[Z]=!1)},n.B=function(t){var e=t.getError(),i=new S(e.getMessage());return i.type=e.getType(),i.errorCode=e.getErrorCode(),i.vastErrorCode=e.getVastErrorCode&&e.getVastErrorCode(),i.innerError=e.getInnerError(),i},n.j=function(t){var e=this;this.dispatchEvent(new A(P.AD_ERROR,{detail:{error:t}})),this.C(),f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):this.I()},i(e,[{key:"volume",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?f(this,M)[M].getVolume():f(this,D)[D].volume},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t),f(this,D)[D].volume=t}},{key:"muted",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?0===f(this,M)[M].getVolume():f(this,D)[D].muted},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t?0:f(this,J)[J]),f(this,D)[D].muted=t}},{key:"currentTime",get:function(){return void 0!==f(this,q)[q]?f(this,q)[q]:f(this,D)[D].currentTime},set:function(t){f(this,C)[C].enabled&&(f(this,D)[D].currentTime=t)}},{key:"duration",get:function(){return void 0!==f(this,$)[$]?f(this,$)[$]:f(this,D)[D].duration}},{key:"cuePoints",get:function(){return[].concat(f(this,Q)[Q])}}]),e}(w);let it=0;function nt(t,e){const i=t.createElement("div");return i.id=`${e?"art-vast-":"art-"}${Date.now()}-${++it}`,t.setStyles(i,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"150",display:"none"}),e&&t.setStyles(i,{backgroundColor:"black",pointerEvents:"auto"}),i}function rt(i,n={}){const r=n.compatibility;if(void 0!==r&&"workspace-1.2"!==r)throw new TypeError("Unsupported VAST compatibility mode");const s="workspace-1.2"===r;return n=>{return r=null,o=null,a=function*(){let r,o=!1;const a=()=>o||n.isDestroy,u={name:"artplayerPluginVast",destroy:()=>null==r?void 0:r.destroy()};function l(){if(!o){o=!0;try{n.off("destroy",l)}finally{null==r||r.destroy()}}}if(a())return u;n.on("destroy",l);try{if(a())return u;const o=yield function(){var i=window;return i.google&&i.google.ima?Promise.resolve(i.google.ima):t||((t=new Promise(function(t,e){var i=document.createElement("script");i.async=!0,i.src="https://imasdk.googleapis.com/js/sdkloader/ima3.js",i.onload=t,i.onerror=e,document.body.appendChild(i)}).then(function(){return i.google.ima})).then(e).catch(e),t)}();if(a())return u;const d=n.constructor.utils;return r=function(t,e,i,n,r){const{$video:s,$player:o}=t.template,a=new e.AdsRenderingSettings;r&&(a.restoreCustomPlaybackStateOnAdBreakComplete=!0,a.enablePreloading=!0);const u=new R;let l=null,d=!1,h=0;const c={art:t,playUrl:(t,e={})=>y("adTagUrl",t,e),playRes:(t,e={})=>y("adsResponse",t,e),init:v,ima:e,adsRenderingSettings:a,playerOptions:u,imaPlayer:null,id:null,$container:null,get container(){return(null==l?void 0:l.container)||null}};r&&Object.defineProperties(c,{imaPlayer:{get:()=>(null==l?void 0:l.player)||null},id:{get:()=>(null==l?void 0:l.container.id)||null},$container:{get:()=>(null==l?void 0:l.container)||null}});const f=t=>l===t&&!t.released&&!n();function p(t){l===t&&(l=null),t.released=!0,t.playing=!1;const e=t.player;t.player=null;const i=t.listeners.splice(0);let n,r=!1;const s=t=>{try{t()}catch(e){r?console.error("VAST cleanup error:",e):(r=!0,n=e)}};h++;try{if(e){for(const[t,n]of i)s(()=>e.removeEventListener(t,n));s(()=>e.destroy())}s(()=>{t.container.parentNode&&t.container.parentNode.removeChild(t.container)})}finally{h--}if(r)throw n}function v(){if(n()||h)return null;if(d)throw new Error("VAST initialization is already in progress");if(null==l?void 0:l.player)return l.player;let t;d=!0;try{if(t={container:nt(i,r),player:null,listeners:[],playing:!1,released:!1},l=t,!f(t))return p(t),null;if(o.appendChild(t.container),!f(t))return p(t),null;if(t.player=new et(e,s,t.container,a,u),!f(t))return p(t),null;const n=t,d=r?[["AdContentPauseRequested",!0],["AdContentResumeRequested",!1],["AdStarted",!0],["AdError",!1]]:[];for(const[e,i]of d){const r=t=>{f(n)&&("AdError"===e&&console.error("VAST Ad Error:",t.detail),n.playing=i,n.container.style.display=i?"block":"none")};if(t.listeners.push([e,r]),t.player.addEventListener(e,r),!f(t))return p(t),null}return r||Object.defineProperties(c,{imaPlayer:{value:t.player},id:{value:t.container.id},$container:{value:t.container}}),t.player}catch(v){if(t)try{p(t)}catch(y){console.error("VAST cleanup error:",y)}throw v}finally{d=!1}}function y(t,i,s){if(n()||r&&(null==l?void 0:l.playing))return;const o=v(),a=l;if(!o||!a)return;const u=function(t,e,i,n){const r=new t.AdsRequest;r[e]=i;const s=r;for(const o in n)s[o]=n[o];return r}(e,t,i,s);f(a)&&a.player===o&&o.playAds(u)}return{context:c,destroy:function(){l&&p(l)}}}(n,o,d,a,s),a()?(l(),u):(!s&&(r.context.init(),a())||"function"===typeof i&&(yield i(r.context)),u)}catch(d){try{l()}catch(h){console.error("VAST cleanup error:",h)}throw d}},new Promise((t,e)=>{var i=t=>{try{s(a.next(t))}catch(i){e(i)}},n=t=>{try{s(a.throw(t))}catch(i){e(i)}},s=e=>e.done?t(e.value):Promise.resolve(e.value).then(i,n);s((a=a.apply(r,o)).next())});var r,o,a}}return rt.default=rt,rt}); diff --git a/docs/compiled/artplayer-plugin-vast.mjs b/docs/compiled/artplayer-plugin-vast.mjs index db882b343..1ad7c018d 100644 --- a/docs/compiled/artplayer-plugin-vast.mjs +++ b/docs/compiled/artplayer-plugin-vast.mjs @@ -445,30 +445,54 @@ function createRequest(ima, field, value, config) { return request; } let nextId = 0; -function createContainer(utils) { +function createContainer(utils, workspaceMode) { const container = utils.createElement("div"); - container.id = `art-vast-${Date.now()}-${++nextId}`; + container.id = `${workspaceMode ? "art-vast-" : "art-"}${Date.now()}-${++nextId}`; utils.setStyles(container, { position: "absolute", inset: "0", width: "100%", height: "100%", zIndex: "150", - backgroundColor: "black", - display: "none", - pointerEvents: "auto" + display: "none" }); + if (workspaceMode) + utils.setStyles(container, { backgroundColor: "black", pointerEvents: "auto" }); return container; } -function createSession(art, ima, utils, closed) { +function createSession(art, ima, utils, closed, workspaceMode) { const { $video, $player } = art.template; const adsRenderingSettings = new ima.AdsRenderingSettings(); - adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; - adsRenderingSettings.enablePreloading = true; + if (workspaceMode) { + adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; + adsRenderingSettings.enablePreloading = true; + } const playerOptions = new E(); let current = null; let initializing = false; let releasing = 0; + const context = { + art, + playUrl: (url, config = {}) => play("adTagUrl", url, config), + playRes: (response, config = {}) => play("adsResponse", response, config), + init, + ima, + adsRenderingSettings, + playerOptions, + imaPlayer: null, + id: null, + $container: null, + get container() { + return current?.container || null; + } + }; + if (workspaceMode) { + Object.defineProperties(context, { + imaPlayer: { get: () => current?.player || null }, + id: { get: () => current?.container.id || null }, + $container: { get: () => current?.container || null } + }); + } const live = (owner) => current === owner && !owner.released && !closed(); function release(owner) { if (current === owner) @@ -519,7 +543,7 @@ function createSession(art, ima, utils, closed) { initializing = true; let owner; try { - owner = { container: createContainer(utils), player: null, listeners: [], playing: false, released: false }; + owner = { container: createContainer(utils, workspaceMode), player: null, listeners: [], playing: false, released: false }; current = owner; if (!live(owner)) { release(owner); @@ -536,12 +560,13 @@ function createSession(art, ima, utils, closed) { return null; } const allocated = owner; - for (const [name, playing] of [ + const events = workspaceMode ? [ ["AdContentPauseRequested", true], ["AdContentResumeRequested", false], ["AdStarted", true], ["AdError", false] - ]) { + ] : []; + for (const [name, playing] of events) { const callback = (event) => { if (!live(allocated)) return; @@ -557,6 +582,13 @@ function createSession(art, ima, utils, closed) { return null; } } + if (!workspaceMode) { + Object.defineProperties(context, { + imaPlayer: { value: owner.player }, + id: { value: owner.container.id }, + $container: { value: owner.container } + }); + } return owner.player; } catch (error) { if (owner) { @@ -572,7 +604,7 @@ function createSession(art, ima, utils, closed) { } } function play(field, value, config) { - if (closed() || current?.playing) + if (closed() || workspaceMode && current?.playing) return; const player = init(); const owner = current; @@ -586,24 +618,13 @@ function createSession(art, ima, utils, closed) { if (current) release(current); } - const context = { - art, - playUrl: (url, config = {}) => play("adTagUrl", url, config), - playRes: (response, config = {}) => play("adsResponse", response, config), - init, - ima, - adsRenderingSettings, - playerOptions, - get imaPlayer() { - return current?.player || null; - }, - get container() { - return current?.container || null; - } - }; return { context, destroy }; } -function artplayerPluginVast(callback) { +function artplayerPluginVast(callback, options = {}) { + const compatibility = options.compatibility; + if (compatibility !== void 0 && compatibility !== "workspace-1.2") + throw new TypeError("Unsupported VAST compatibility mode"); + const workspaceMode = compatibility === "workspace-1.2"; return async (art) => { let disposed = false; let session; @@ -629,11 +650,16 @@ function artplayerPluginVast(callback) { if (closed()) return result; const utils = art.constructor.utils; - session = createSession(art, ima, utils, closed); + session = createSession(art, ima, utils, closed, workspaceMode); if (closed()) { dispose(); return result; } + if (!workspaceMode) { + session.context.init(); + if (closed()) + return result; + } if (typeof callback === "function") await callback(session.context); return result; diff --git a/package.json b/package.json index a700ef700..3ce27a190 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "ci:build": "yarn build:types && yarn build all && yarn build:i18n && yarn build:ts && yarn build:llm && yarn build:vconsole && yarn build:site-notices && yarn build:test && yarn build:docs && yarn test:imports", "test:imports": "node --test test/esm.test.js test/i18n.test.js test/ssr.test.js test/asr-distribution.test.js", "typecheck": "node scripts/typecheck.mjs", - "test:unit": "node --test test/danmuku-setting.test.js test/danmuku-heatmap.test.js test/danmuku-renderer.test.js test/danmuku-scheduler.test.js test/danmuku-worker-client.test.js test/danmuku-input.test.js test/danmuku-parser.test.js test/danmuku-failures.test.js test/danmuku-mask-failures.test.js test/danmuku-mask-lifecycle.test.js test/asr-encoding.test.js test/asr-lifecycle.test.js test/asr-audio.test.js test/asr.test.js test/jassub.test.js test/jassub-registration.test.js test/jassub-runtime.test.js test/jassub-vendor-lifecycle.test.js test/jassub-frame-polyfill.test.js test/jassub-offscreen.test.js test/multiple-subtitles-ass.test.js test/multiple-subtitles-caption.test.js test/multiple-subtitles-merge.test.js test/multiple-subtitles-entities.test.js test/multiple-subtitles-lifecycle.test.js test/multiple-subtitles-failures.test.js test/multiple-subtitles.test.js test/multiple-subtitles-vendor.test.js test/vtt-thumbnail-parser.test.js test/vtt-thumbnail-lifecycle.test.js test/vtt-thumbnail.test.js test/auto-thumbnail-exports.test.js test/auto-thumbnail-canvas.test.js test/auto-thumbnail-frames.test.js test/auto-thumbnail-encoding.test.js test/auto-thumbnail-lifecycle.test.js test/auto-thumbnail.test.js test/thumbnail-emitter.test.js test/thumbnail-runtime.test.js test/thumbnail-vendor.test.js test/thumbnail-lifecycle.test.js test/thumbnail-input.test.js test/thumbnail.test.js test/iframe-navigation.test.js test/iframe-boundaries.test.js test/iframe-lifecycle.test.js test/iframe.test.js test/mediabunny.test.js test/mediabunny-shim.test.js test/mediabunny-coordination.test.js test/mediabunny-video.test.js test/mediabunny-audio.test.js test/mediabunny-hls.test.js test/mediabunny-entry.test.js test/mediabunny-capability.test.js test/mediabunny-load.test.js test/mediabunny-input.test.js test/dpip.test.js test/dpip-lifecycle.test.js test/canvas.test.js test/canvas-lifecycle.test.js test/ambilight.test.js test/ambilight-lifecycle.test.js test/ambilight-proxy.test.js test/vast-exports.test.js test/vast.test.js test/vast-lifecycle.test.js test/ads.test.js test/ads-lifecycle.test.js test/playback.test.js test/dash-control.test.js test/dash-contract.test.js test/dash-lifecycle.test.js test/dash-events.test.js test/hls-control.test.js test/audio-track.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js test/asr-fallback-routing.test.js test/asr-local-example.test.js test/asr-explicit-capture.test.js test/chromecast.test.js test/chromecast-failures.test.js test/chromecast-runtime.test.js", + "test:unit": "node --test test/danmuku-setting.test.js test/danmuku-heatmap.test.js test/danmuku-renderer.test.js test/danmuku-scheduler.test.js test/danmuku-worker-client.test.js test/danmuku-input.test.js test/danmuku-parser.test.js test/danmuku-failures.test.js test/danmuku-mask-failures.test.js test/danmuku-mask-lifecycle.test.js test/asr-encoding.test.js test/asr-lifecycle.test.js test/asr-audio.test.js test/asr.test.js test/jassub.test.js test/jassub-registration.test.js test/jassub-runtime.test.js test/jassub-vendor-lifecycle.test.js test/jassub-frame-polyfill.test.js test/jassub-offscreen.test.js test/multiple-subtitles-ass.test.js test/multiple-subtitles-caption.test.js test/multiple-subtitles-merge.test.js test/multiple-subtitles-entities.test.js test/multiple-subtitles-lifecycle.test.js test/multiple-subtitles-failures.test.js test/multiple-subtitles.test.js test/multiple-subtitles-vendor.test.js test/vtt-thumbnail-parser.test.js test/vtt-thumbnail-lifecycle.test.js test/vtt-thumbnail.test.js test/auto-thumbnail-exports.test.js test/auto-thumbnail-canvas.test.js test/auto-thumbnail-frames.test.js test/auto-thumbnail-encoding.test.js test/auto-thumbnail-lifecycle.test.js test/auto-thumbnail.test.js test/thumbnail-emitter.test.js test/thumbnail-runtime.test.js test/thumbnail-vendor.test.js test/thumbnail-lifecycle.test.js test/thumbnail-input.test.js test/thumbnail.test.js test/iframe-navigation.test.js test/iframe-boundaries.test.js test/iframe-lifecycle.test.js test/iframe.test.js test/mediabunny.test.js test/mediabunny-shim.test.js test/mediabunny-coordination.test.js test/mediabunny-video.test.js test/mediabunny-audio.test.js test/mediabunny-hls.test.js test/mediabunny-entry.test.js test/mediabunny-capability.test.js test/mediabunny-load.test.js test/mediabunny-input.test.js test/dpip.test.js test/dpip-lifecycle.test.js test/canvas.test.js test/canvas-lifecycle.test.js test/ambilight.test.js test/ambilight-lifecycle.test.js test/ambilight-proxy.test.js test/vast-exports.test.js test/vast.test.js test/vast-lifecycle.test.js test/vast-compatibility.test.js test/ads.test.js test/ads-lifecycle.test.js test/playback.test.js test/dash-control.test.js test/dash-contract.test.js test/dash-lifecycle.test.js test/dash-events.test.js test/hls-control.test.js test/audio-track.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js test/asr-fallback-routing.test.js test/asr-local-example.test.js test/asr-explicit-capture.test.js test/chromecast.test.js test/chromecast-failures.test.js test/chromecast-runtime.test.js", "test:coverage": "node --test test/coverage.test.js && node scripts/coverage.mjs", "test": "yarn test:node && yarn test:baseline", "test:browser": "playwright test", @@ -66,7 +66,7 @@ "test:dash-types-package": "node refactor/scripts/dash-package-types.mjs", "test:ads-types-package": "node refactor/scripts/ads-package-types.mjs", "test:ads-native-visibility": "node refactor/scripts/ads-native-visibility.mjs", - "test:vast": "node --test test/vast-exports.test.js test/vast.test.js test/vast-lifecycle.test.js", + "test:vast": "node --test test/vast-exports.test.js test/vast.test.js test/vast-lifecycle.test.js test/vast-compatibility.test.js", "check:commits": "node refactor/scripts/commit-audit.mjs", "check:impact": "node refactor/scripts/impact.mjs", "check:contracts": "node refactor/scripts/contracts.mjs", diff --git a/packages/artplayer-plugin-vast/ARCHITECTURE.md b/packages/artplayer-plugin-vast/ARCHITECTURE.md index 53d470067..1b27cedec 100644 --- a/packages/artplayer-plugin-vast/ARCHITECTURE.md +++ b/packages/artplayer-plugin-vast/ARCHITECTURE.md @@ -1,19 +1,21 @@ # VAST implementation and maintenance -This is the PKG-VAST-03 implementation checkpoint. The published-versus-workspace -initialization conflict remains open; this checkpoint is not release acceptance. +The runtime follows the accepted published-versus-workspace initialization decision. +Public declaration reconciliation and real IMA validation remain separate release gates. ## Module map - `src/index.ts` owns the core destroy subscription before SDK loading begins, awaits SDK loading and the user callback, and preserves original rejection values. - Its writable `.default` self-reference retains historical CommonJS default calls + It snapshots the optional compatibility mode at factory creation and initializes + the default session before the callback. Its writable `.default` self-reference retains historical CommonJS default calls alongside the current direct factory. It does not wrap registration or load IMA. - `src/sdk.ts` is the only runtime Glomex import boundary. It also constructs IMA requests, preserving own/inherited configuration fields and primary-field overrides. -- `src/session.ts` owns one current SDK/container pair, the four ad-event subscriptions, - active-ad request suppression, initialization rollback and explicit recreation. -- `src/view.ts` creates the existing overlay styles and distinct per-module container +- `src/session.ts` owns one current SDK/container pair, initialization rollback and + explicit recreation. Only workspace mode adds four ad-event subscriptions and + active-ad request suppression; default mode delegates those behaviors to the SDK. +- `src/view.ts` creates each mode's historical overlay styles and distinct per-module container IDs, including multiple instances initialized in the same millisecond. - `src/types.ts` describes the implementation context and SDK boundary. Public legacy declarations in `types/` remain separate pending PKG-VAST-04 reconciliation. @@ -50,17 +52,34 @@ it finishes. SDK content pause/resume behavior is not duplicated in this wrapper ## Compatibility and remaining work -The checkpoint retains the workspace callback order, lazy initialization, mutable -settings/options identities, default flags, void request methods, and asynchronous -outer attachment. The old `require(...).default(...)` call is restored, while the -current callable export remains callable. This does not recreate the old namespace -object's reflection shape. The `id`/`$container` aliases, eager -published initialization and contradictory public return types are not yet reconciled. -See [the explicit decision](../../refactor/vast-compatibility-decision.md). +Calling `artplayerPluginVast(callback)` preserves npm1.0.0 behavior: the SDK and +container exist before the callback, including when no callback was supplied. +`imaPlayer`, `id` and `$container` are writable/enumerable/configurable data fields. +SDK settings retain their own defaults. The wrapper forwards each explicit request +and leaves ad visibility to the SDK, without adding workspace event listeners. -The former timestamp-only overlay ID now has a monotonic suffix to avoid same-tick -collisions; the existing `art-vast-` prefix and CSS styles remain. IDs are internal -in the workspace context; published ID compatibility is tracked with the above decision. +Passing `{ compatibility: 'workspace-1.2' }` as the second argument retains unpublished +workspace behavior: no player/container until `init`, `playUrl` or `playRes`; callers +can mutate the original settings/options before initialization. Preloading and restore +custom playback state default to true. Four ad events control the black overlay and +active-ad suppression. Resource getters track the current session and become null +on release. The mode is captured once; an unknown value throws TypeError before loading. + +Default data fields retain their last allocated values after destroy, as published +snapshots; `container` is a live getter and becomes null. Explicit recreation updates +the data fields to the new session. Public writes to these snapshots do not transfer +resource ownership. Never use a retained disposed SDK as an active session. + +Both modes retain void request methods, async registration and SDK/callback rejection. +The old `require(...).default(...)` call and current callable export remain available; +this does not recreate the old namespace object's reflection shape. Contradictory +public return declarations and the new second-argument declaration remain task04. +See [the accepted decision](../../refactor/vast-compatibility-decision.md). + +Overlay IDs use the historical `art-` default prefix or `art-vast-` workspace prefix, +with a monotonic suffix to fix same-millisecond collisions. Default styles do not add +workspace's black background or pointer-events rule. Container identity/ownership, +initial display:none and existing position/inset/size/z-index are preserved. `@alugha/ima@2.1.0` is a direct pinned dependency because Glomex declarations import its types while Glomex lists it only as a development dependency. Runtime imports continue @@ -68,11 +87,16 @@ to use Glomex1.21.2. No new direct remote loader or SDK major upgrade was introd ## Validation -Run `yarn test:vast`, `yarn typecheck`, `yarn build artplayer-plugin-vast`, and -`yarn test:browser vast.spec.js` using the repository pinned toolchain. The node and +Run `yarn test:vast`, `node node_modules/typescript/bin/tsc -p +packages/artplayer-plugin-vast/tsconfig.json --noEmit`, `yarn build artplayer-plugin-vast`, +and `yarn test:browser:source test/browser/vast.spec.js --workers=2` using the pinned +toolchain. Do not use the historical `tsc` binary alias for source checking. The node and browser wrapper tests substitute only the Glomex SDK boundary. They cover current and -frozen historical sources, real core5.1.7/5.4.1/candidate registration, real DOM and +frozen historical sources, real published core5.1.7/5.4.0 and candidate5.4.1 registration, real DOM and main-video decoding; they do not certify Google IMA ads or final npm distribution. +Candidate default and explicit workspace cases execute identical compiled code with +different options; historical fixtures remain immutable. Compatibility tests compare +callback timing, data descriptors, defaults and request forwarding to actual npm source. `test/vast-exports.test.js` exercises bundled CommonJS/global/AMD and native ESM import, using an already destroyed host to verify registration without loading ads. diff --git a/packages/artplayer-plugin-vast/README.md b/packages/artplayer-plugin-vast/README.md index 79b920774..79ced5a4d 100644 --- a/packages/artplayer-plugin-vast/README.md +++ b/packages/artplayer-plugin-vast/README.md @@ -2,6 +2,32 @@ VAST plugin for ArtPlayer +## Initialization compatibility + +Existing npm calls keep creating the SDK player before the callback: + +```js +artplayerPluginVast(({ imaPlayer, playUrl }) => { + imaPlayer.addEventListener('AdStarted', onAdStarted) + playButton.onclick = () => playUrl(adTagUrl) +}) +``` + +Code using the unpublished workspace 1.2 lazy initialization must select it explicitly: + +```js +artplayerPluginVast((context) => { + context.playerOptions.autoResize = false + playButton.onclick = () => context.playUrl(adTagUrl) +}, { compatibility: 'workspace-1.2' }) +``` + +The callback may be asynchronous. Core destruction releases the ad session and prevents +later requests or recreation. Explicit plugin `destroy()` allows a new ad session while +the core is alive. See the architecture guide for mode-specific fields and defaults. +Public TypeScript declarations for the second argument are still being reconciled in +PKG-VAST-04; these are JavaScript usage examples, not completed declaration acceptance. + ## Maintenance Implementation modules, lifecycle ownership, test commands and pending compatibility diff --git a/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.js b/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.js index 584b1ee3a..1de2899bd 100644 --- a/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.js +++ b/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginVast=e(),define(function(){return t.artplayerPluginVast})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginVast=e()}(this,function(){"use strict";var t=null,e=function(){t=null};function i(t,e,i){return e&&function(t,e){for(var i=0;it.length)&&(e=t.length);for(var i=0,n=new Array(e);i-1&&(f(this,Q)[Q].splice(e,1),this.g(f(this,Q)[Q]))},n.resizeAd=function(t,e){f(this,j)[j]=t,f(this,N)[N]=e,f(this,M)[M]&&f(this,M)[M].resize(t,e,this.k()),f(this,_)[_].style.width=t+"px",f(this,_)[_].style.height=e+"px"},n.reset=function(t){void 0===t&&(t=!1),t&&(f(this,F)[F]=!1,f(this,G)[G]=!1,f(this,W)[W]=!1),this.C(),f(this,Q)[Q]=[],f(this,Z)[Z]=!1,f(this,$)[$]=void 0,f(this,M)[M]&&f(this,M)[M].destroy(),f(this,M)[M]=void 0,f(this,I)[I].settings.setAutoPlayAdBreaks(!0),t&&this.P(),f(this,_)[_].style.display="none"},n.P=function(){f(this,U)[U]&&(f(this,U)[U].removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),f(this,U)[U].removeEventListener(f(this,I)[I].AdErrorEvent.Type.AD_ERROR,this.l,!1),f(this,U)[U].destroy()),f(this,L)[L]&&f(this,L)[L].destroy()},n.destroy=function(){var t,e,i,n,r=this;this.reset(!0),f(this,C)[C].destroy(),T.forEach(function(t){f(r,D)[D].removeEventListener(t,r.o)}),null==(t=f(this,U)[U])||t.removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),null==(e=f(this,L)[L])||e.destroy(),null==(i=f(this,U)[U])||i.destroy(),f(this,F)[F]=!1,f(this,W)[W]=!1,f(this,G)[G]=!1,null==(n=f(this,B)[B])||n.disconnect()},n.isCustomPlaybackUsed=function(){return!1===f(this,I)[I].settings.getDisableCustomPlaybackForIOS10Plus()&&!f(this,_)[_].querySelector("video")},n.C=function(){window.clearTimeout(f(this,Y)[Y]),window.clearTimeout(f(this,X)[X]),f(this,Y)[Y]=void 0,f(this,X)[X]=void 0,f(this,V)[V]=void 0,f(this,q)[q]=void 0,f(this,K)[K]=void 0,f(this,_)[_].style.display="none",f(this,_)[_].classList.remove("nonlinear"),f(this,M)[M]&&this.R()},n.o=function(t){var e=this;if(f(this,C)[C].enabled||"volumechange"===t.type){if("timeupdate"===t.type){if(f(this,M)[M]){var i=f(this,M)[M].getCuePoints().filter(function(t){return t>=0&&t=.5&&(this.dispatchEvent(new A(R.MEDIA_IMPRESSION)),f(this,F)[F]=!0)}if("play"!==t.type||f(this,G)[G]||f(this,H)[H]||(this.dispatchEvent(new A(R.MEDIA_START)),f(this,G)[G]=!0),"ended"===t.type&&(this.isCustomPlaybackUsed()&&f(this,D)[D].currentTime===f(this,D)[D].duration&&f(this,Q)[Q].indexOf(-1)>-1&&(f(this,D)[D].currentTime=f(this,D)[D].duration-1e-5,f(this,W)[W]=!0),f(this,U)[U].contentComplete(),f(this,M)[M]||this.T()),!window.ResizeObserver&&f(this,z)[z].autoResize&&"loadedmetadata"===t.type){var n=f(this,D)[D],r=n.offsetHeight,s=n.offsetWidth;f(this,j)[j]=s,f(this,N)[N]=r,this.R()}f(this,H)[H]&&"volumechange"!==t.type||this.dispatchEvent(new A(t.type))}},n.S=function(t){var e=this,i=f(this,I)[I].AdEvent;switch(t.type){case i.Type.LOADED:var n=t.getAd();f(this,$)[$]&&0===f(this,Q)[Q].length?f(this,$)[$]({ad:n,start:function(){e.M(),f(e,$)[$]=void 0},startWithoutReset:function(){e.M()}}):f(this,x)[x]=n;break;case i.Type.AD_BREAK_READY:this.C(),f(this,$)[$]?(f(this,$)[$]({ad:f(this,x)[x],adBreakTime:t.getAdData().adBreakTime,start:function(){e.M(),f(e,$)[$]=void 0},startWithoutReset:function(){e.M()}}),f(this,x)[x]=void 0):this.M();break;case i.Type.STARTED:var r=f(this,V)[V]=t.getAd();r.getAdPodInfo().getAdPosition()>1&&f(this,M)[M].setVolume(f(this,M)[M].getVolume()),f(this,_)[_].classList.remove("nonlinear"),this.R(),r.isLinear()?(f(this,C)[C].disable(),f(this,K)[K]=r.getDuration(),f(this,q)[q]=0):(f(this,_)[_].classList.add("nonlinear"),this.I()),f(this,_)[_].style.display="",f(this,Z)[Z]&&(f(this,Z)[Z]=!1,f(this,M)[M].pause());break;case i.Type.ALL_ADS_COMPLETED:if(f(this,W)[W])return;this.isCustomPlaybackUsed()&&Boolean(f(this,V)[V])&&-1!==f(this,V)[V].getAdPodInfo().getTimeOffset()&&this.I(),this.reset();break;case i.Type.CONTENT_PAUSE_REQUESTED:this.C(),f(this,V)[V]=t.getAd(),f(this,_)[_].style.display="",f(this,D)[D].pause(),this.R(),f(this,V)[V]&&this.A(f(this,V)[V].getAdPodInfo().getTimeOffset()),f(this,M)[M].setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),f(this,C)[C].disable(),f(this,K)[K]=f(this,V)[V].getDuration(),f(this,q)[q]=0;break;case i.Type.CONTENT_RESUME_REQUESTED:var s=Boolean(f(this,V)[V]);if(s){var o=f(this,M)[M].getVolume();f(this,D)[D].muted=0===o,f(this,D)[D].volume=f(this,J)[J]}f(this,W)[W]&&(f(this,D)[D].currentTime=f(this,D)[D].duration+1,f(this,W)[W]=!1),f(this,D)[D].ended?(this.reset(),this.T()):this.C(),s&&(f(this,Z)[Z]=!1,this.I());break;case i.Type.AD_METADATA:this.g(f(this,M)[M].getCuePoints()),-1===f(this,Q)[Q].indexOf(0)&&(f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):this.I());break;case i.Type.AD_PROGRESS:var a=t.getAdData();f(this,q)[q]=a.currentTime,f(this,K)[K]=a.duration;break;case i.Type.LOG:var u=t.getAdData();f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):u.adError&&!f(this,V)[V]&&this.I();break;case i.Type.VOLUME_CHANGED:var h=f(this,M)[M].getVolume();h>0&&(f(this,J)[J]=h)}},n.l=function(t){this.j(this.B(t))},n.u=function(t){var e=this,i=f(this,I)[I],n=i.AdEvent,r=i.AdErrorEvent.Type.AD_ERROR;window.clearTimeout(f(this,Y)[Y]);var s=f(this,M)[M]=t.getAdsManager(f(this,C)[C],f(this,k)[k]);Object.keys(n.Type).forEach(function(t){s.addEventListener(n.Type[t],function(i){if(e.S(i),R[t]){var n=["LOG","AD_PROGRESS"].indexOf(t)>-1;e.dispatchEvent(new A(R[t],{detail:{ad:i.getAd()||f(e,V)[V],adData:n?i.getAdData():{}}}))}})}),s.addEventListener(r,function(t){return e.j(e.B(t))});try{var o;s.init(f(this,j)[j],f(this,N)[N],this.k()),s.setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),null==(o=f(this,L)[L])||o.initialize(),f(this,$)[$]||this.M()}catch(a){this.j(new S(a.message))}},n.M=function(){if(f(this,G)[G]||(this.dispatchEvent(new A(R.MEDIA_START)),f(this,G)[G]=!0),f(this,M)[M])try{f(this,M)[M].start()}catch(t){this.j(new S(t.message))}else this.I()},n.T=function(){var t=this;setTimeout(function(){f(t,F)[F]=!1,f(t,G)[G]=!1,f(t,W)[W]=!1,t.dispatchEvent(new A(R.MEDIA_STOP))},1)},n.v=function(t){for(var e,i=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(e)return(e=e.call(t)).next.bind(e);if(Array.isArray(t)||(e=function(t,e){if(t){if("string"==typeof t)return d(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?d(t,e):void 0}}(t))){e&&(t=e);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(t);!(e=i()).done;){var n=e.value;n.contentBoxSize&&1===n.contentBoxSize.length?(f(this,j)[j]=n.contentBoxSize[0].inlineSize,f(this,N)[N]=n.contentBoxSize[0].blockSize):n.contentBoxSize&&n.contentBoxSize.inlineSize?(f(this,j)[j]=n.contentBoxSize.inlineSize,f(this,N)[N]=n.contentBoxSize.blockSize):(f(this,j)[j]=n.contentRect.width,f(this,N)[N]=n.contentRect.height)}this.R()},n.R=function(){if(f(this,z)[z].autoResize&&f(this,M)[M]){var t=f(this,V)[V],e=this.k();t&&!t.isLinear()?t&&(t.getWidth()>f(this,j)[j]||t.getHeight()>f(this,N)[N]?this.resizeAd(f(this,j)[j],f(this,N)[N]):(f(this,M)[M].resize(t.getWidth(),t.getHeight()+20,e),f(this,_)[_].style.width=t.getWidth()+"px",f(this,_)[_].style.height=t.getHeight()+20+"px")):this.resizeAd(f(this,j)[j],f(this,N)[N])}},n.k=function(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||f(this,D)[D].webkitDisplayingFullscreen?f(this,I)[I].ViewMode.FULLSCREEN:f(this,I)[I].ViewMode.NORMAL},n.I=function(){var t=this;f(this,_)[_].style.display="none",f(this,D)[D].ended||(f(this,C)[C].enable(),f(this,Z)[Z]?(f(this,D)[D].pause(),this.dispatchEvent(new A("pause"))):(this.p().then(function(){}).catch(function(){t.dispatchEvent(new A("pause"))}),this.dispatchEvent(new A("play")),this.dispatchEvent(new A(R.MEDIA_RESUMED))),f(this,Z)[Z]=!1)},n.B=function(t){var e=t.getError(),i=new S(e.getMessage());return i.type=e.getType(),i.errorCode=e.getErrorCode(),i.vastErrorCode=e.getVastErrorCode&&e.getVastErrorCode(),i.innerError=e.getInnerError(),i},n.j=function(t){var e=this;this.dispatchEvent(new A(R.AD_ERROR,{detail:{error:t}})),this.C(),f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):this.I()},i(e,[{key:"volume",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?f(this,M)[M].getVolume():f(this,D)[D].volume},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t),f(this,D)[D].volume=t}},{key:"muted",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?0===f(this,M)[M].getVolume():f(this,D)[D].muted},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t?0:f(this,J)[J]),f(this,D)[D].muted=t}},{key:"currentTime",get:function(){return void 0!==f(this,q)[q]?f(this,q)[q]:f(this,D)[D].currentTime},set:function(t){f(this,C)[C].enabled&&(f(this,D)[D].currentTime=t)}},{key:"duration",get:function(){return void 0!==f(this,K)[K]?f(this,K)[K]:f(this,D)[D].duration}},{key:"cuePoints",get:function(){return[].concat(f(this,Q)[Q])}}]),e}(w);let it=0;function nt(t){const e=t.createElement("div");return e.id=`art-vast-${Date.now()}-${++it}`,t.setStyles(e,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"150",backgroundColor:"black",display:"none",pointerEvents:"auto"}),e}function rt(i){return async n=>{let r,s=!1;const o=()=>s||n.isDestroy,a={name:"artplayerPluginVast",destroy:()=>r?.destroy()};function u(){if(!s){s=!0;try{n.off("destroy",u)}finally{r?.destroy()}}}if(o())return a;n.on("destroy",u);try{if(o())return a;const s=await function(){var i=window;return i.google&&i.google.ima?Promise.resolve(i.google.ima):t||((t=new Promise(function(t,e){var i=document.createElement("script");i.async=!0,i.src="https://imasdk.googleapis.com/js/sdkloader/ima3.js",i.onload=t,i.onerror=e,document.body.appendChild(i)}).then(function(){return i.google.ima})).then(e).catch(e),t)}();if(o())return a;const h=n.constructor.utils;return r=function(t,e,i,n){const{$video:r,$player:s}=t.template,o=new e.AdsRenderingSettings;o.restoreCustomPlaybackStateOnAdBreakComplete=!0,o.enablePreloading=!0;const a=new P;let u=null,h=!1,d=0;const l=t=>u===t&&!t.released&&!n();function c(t){u===t&&(u=null),t.released=!0,t.playing=!1;const e=t.player;t.player=null;const i=t.listeners.splice(0);let n,r=!1;const s=t=>{try{t()}catch(e){r?console.error("VAST cleanup error:",e):(r=!0,n=e)}};d++;try{if(e){for(const[t,n]of i)s(()=>e.removeEventListener(t,n));s(()=>e.destroy())}s(()=>{t.container.parentNode&&t.container.parentNode.removeChild(t.container)})}finally{d--}if(r)throw n}function f(){if(n()||d)return null;if(h)throw new Error("VAST initialization is already in progress");if(u?.player)return u.player;let t;h=!0;try{if(t={container:nt(i),player:null,listeners:[],playing:!1,released:!1},u=t,!l(t))return c(t),null;if(s.appendChild(t.container),!l(t))return c(t),null;if(t.player=new et(e,r,t.container,o,a),!l(t))return c(t),null;const n=t;for(const[e,i]of[["AdContentPauseRequested",!0],["AdContentResumeRequested",!1],["AdStarted",!0],["AdError",!1]]){const r=t=>{l(n)&&("AdError"===e&&console.error("VAST Ad Error:",t.detail),n.playing=i,n.container.style.display=i?"block":"none")};if(t.listeners.push([e,r]),t.player.addEventListener(e,r),!l(t))return c(t),null}return t.player}catch(f){if(t)try{c(t)}catch(p){console.error("VAST cleanup error:",p)}throw f}finally{h=!1}}function p(t,i,r){if(n()||u?.playing)return;const s=f(),o=u;if(!s||!o)return;const a=function(t,e,i,n){const r=new t.AdsRequest;r[e]=i;const s=r;for(const o in n)s[o]=n[o];return r}(e,t,i,r);l(o)&&o.player===s&&s.playAds(a)}return{context:{art:t,playUrl:(t,e={})=>p("adTagUrl",t,e),playRes:(t,e={})=>p("adsResponse",t,e),init:f,ima:e,adsRenderingSettings:o,playerOptions:a,get imaPlayer(){return u?.player||null},get container(){return u?.container||null}},destroy:function(){u&&c(u)}}}(n,s,h,o),o()?(u(),a):("function"===typeof i&&await i(r.context),a)}catch(h){try{u()}catch(d){console.error("VAST cleanup error:",d)}throw h}}}return rt.default=rt,rt}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginVast=e(),define(function(){return t.artplayerPluginVast})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginVast=e()}(this,function(){"use strict";var t=null,e=function(){t=null};function i(t,e,i){return e&&function(t,e){for(var i=0;it.length)&&(e=t.length);for(var i=0,n=new Array(e);i-1&&(f(this,Q)[Q].splice(e,1),this.g(f(this,Q)[Q]))},n.resizeAd=function(t,e){f(this,j)[j]=t,f(this,N)[N]=e,f(this,M)[M]&&f(this,M)[M].resize(t,e,this.k()),f(this,_)[_].style.width=t+"px",f(this,_)[_].style.height=e+"px"},n.reset=function(t){void 0===t&&(t=!1),t&&(f(this,F)[F]=!1,f(this,G)[G]=!1,f(this,W)[W]=!1),this.C(),f(this,Q)[Q]=[],f(this,Z)[Z]=!1,f(this,K)[K]=void 0,f(this,M)[M]&&f(this,M)[M].destroy(),f(this,M)[M]=void 0,f(this,I)[I].settings.setAutoPlayAdBreaks(!0),t&&this.P(),f(this,_)[_].style.display="none"},n.P=function(){f(this,U)[U]&&(f(this,U)[U].removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),f(this,U)[U].removeEventListener(f(this,I)[I].AdErrorEvent.Type.AD_ERROR,this.l,!1),f(this,U)[U].destroy()),f(this,L)[L]&&f(this,L)[L].destroy()},n.destroy=function(){var t,e,i,n,r=this;this.reset(!0),f(this,C)[C].destroy(),T.forEach(function(t){f(r,D)[D].removeEventListener(t,r.o)}),null==(t=f(this,U)[U])||t.removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),null==(e=f(this,L)[L])||e.destroy(),null==(i=f(this,U)[U])||i.destroy(),f(this,F)[F]=!1,f(this,W)[W]=!1,f(this,G)[G]=!1,null==(n=f(this,B)[B])||n.disconnect()},n.isCustomPlaybackUsed=function(){return!1===f(this,I)[I].settings.getDisableCustomPlaybackForIOS10Plus()&&!f(this,_)[_].querySelector("video")},n.C=function(){window.clearTimeout(f(this,Y)[Y]),window.clearTimeout(f(this,X)[X]),f(this,Y)[Y]=void 0,f(this,X)[X]=void 0,f(this,V)[V]=void 0,f(this,q)[q]=void 0,f(this,$)[$]=void 0,f(this,_)[_].style.display="none",f(this,_)[_].classList.remove("nonlinear"),f(this,M)[M]&&this.R()},n.o=function(t){var e=this;if(f(this,C)[C].enabled||"volumechange"===t.type){if("timeupdate"===t.type){if(f(this,M)[M]){var i=f(this,M)[M].getCuePoints().filter(function(t){return t>=0&&t=.5&&(this.dispatchEvent(new A(P.MEDIA_IMPRESSION)),f(this,F)[F]=!0)}if("play"!==t.type||f(this,G)[G]||f(this,H)[H]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),"ended"===t.type&&(this.isCustomPlaybackUsed()&&f(this,D)[D].currentTime===f(this,D)[D].duration&&f(this,Q)[Q].indexOf(-1)>-1&&(f(this,D)[D].currentTime=f(this,D)[D].duration-1e-5,f(this,W)[W]=!0),f(this,U)[U].contentComplete(),f(this,M)[M]||this.T()),!window.ResizeObserver&&f(this,z)[z].autoResize&&"loadedmetadata"===t.type){var n=f(this,D)[D],r=n.offsetHeight,s=n.offsetWidth;f(this,j)[j]=s,f(this,N)[N]=r,this.R()}f(this,H)[H]&&"volumechange"!==t.type||this.dispatchEvent(new A(t.type))}},n.S=function(t){var e=this,i=f(this,I)[I].AdEvent;switch(t.type){case i.Type.LOADED:var n=t.getAd();f(this,K)[K]&&0===f(this,Q)[Q].length?f(this,K)[K]({ad:n,start:function(){e.M(),f(e,K)[K]=void 0},startWithoutReset:function(){e.M()}}):f(this,x)[x]=n;break;case i.Type.AD_BREAK_READY:this.C(),f(this,K)[K]?(f(this,K)[K]({ad:f(this,x)[x],adBreakTime:t.getAdData().adBreakTime,start:function(){e.M(),f(e,K)[K]=void 0},startWithoutReset:function(){e.M()}}),f(this,x)[x]=void 0):this.M();break;case i.Type.STARTED:var r=f(this,V)[V]=t.getAd();r.getAdPodInfo().getAdPosition()>1&&f(this,M)[M].setVolume(f(this,M)[M].getVolume()),f(this,_)[_].classList.remove("nonlinear"),this.R(),r.isLinear()?(f(this,C)[C].disable(),f(this,$)[$]=r.getDuration(),f(this,q)[q]=0):(f(this,_)[_].classList.add("nonlinear"),this.I()),f(this,_)[_].style.display="",f(this,Z)[Z]&&(f(this,Z)[Z]=!1,f(this,M)[M].pause());break;case i.Type.ALL_ADS_COMPLETED:if(f(this,W)[W])return;this.isCustomPlaybackUsed()&&Boolean(f(this,V)[V])&&-1!==f(this,V)[V].getAdPodInfo().getTimeOffset()&&this.I(),this.reset();break;case i.Type.CONTENT_PAUSE_REQUESTED:this.C(),f(this,V)[V]=t.getAd(),f(this,_)[_].style.display="",f(this,D)[D].pause(),this.R(),f(this,V)[V]&&this.A(f(this,V)[V].getAdPodInfo().getTimeOffset()),f(this,M)[M].setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),f(this,C)[C].disable(),f(this,$)[$]=f(this,V)[V].getDuration(),f(this,q)[q]=0;break;case i.Type.CONTENT_RESUME_REQUESTED:var s=Boolean(f(this,V)[V]);if(s){var o=f(this,M)[M].getVolume();f(this,D)[D].muted=0===o,f(this,D)[D].volume=f(this,J)[J]}f(this,W)[W]&&(f(this,D)[D].currentTime=f(this,D)[D].duration+1,f(this,W)[W]=!1),f(this,D)[D].ended?(this.reset(),this.T()):this.C(),s&&(f(this,Z)[Z]=!1,this.I());break;case i.Type.AD_METADATA:this.g(f(this,M)[M].getCuePoints()),-1===f(this,Q)[Q].indexOf(0)&&(f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):this.I());break;case i.Type.AD_PROGRESS:var a=t.getAdData();f(this,q)[q]=a.currentTime,f(this,$)[$]=a.duration;break;case i.Type.LOG:var u=t.getAdData();f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):u.adError&&!f(this,V)[V]&&this.I();break;case i.Type.VOLUME_CHANGED:var d=f(this,M)[M].getVolume();d>0&&(f(this,J)[J]=d)}},n.l=function(t){this.j(this.B(t))},n.u=function(t){var e=this,i=f(this,I)[I],n=i.AdEvent,r=i.AdErrorEvent.Type.AD_ERROR;window.clearTimeout(f(this,Y)[Y]);var s=f(this,M)[M]=t.getAdsManager(f(this,C)[C],f(this,k)[k]);Object.keys(n.Type).forEach(function(t){s.addEventListener(n.Type[t],function(i){if(e.S(i),P[t]){var n=["LOG","AD_PROGRESS"].indexOf(t)>-1;e.dispatchEvent(new A(P[t],{detail:{ad:i.getAd()||f(e,V)[V],adData:n?i.getAdData():{}}}))}})}),s.addEventListener(r,function(t){return e.j(e.B(t))});try{var o;s.init(f(this,j)[j],f(this,N)[N],this.k()),s.setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),null==(o=f(this,L)[L])||o.initialize(),f(this,K)[K]||this.M()}catch(a){this.j(new S(a.message))}},n.M=function(){if(f(this,G)[G]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),f(this,M)[M])try{f(this,M)[M].start()}catch(t){this.j(new S(t.message))}else this.I()},n.T=function(){var t=this;setTimeout(function(){f(t,F)[F]=!1,f(t,G)[G]=!1,f(t,W)[W]=!1,t.dispatchEvent(new A(P.MEDIA_STOP))},1)},n.v=function(t){for(var e,i=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(e)return(e=e.call(t)).next.bind(e);if(Array.isArray(t)||(e=function(t,e){if(t){if("string"==typeof t)return h(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?h(t,e):void 0}}(t))){e&&(t=e);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(t);!(e=i()).done;){var n=e.value;n.contentBoxSize&&1===n.contentBoxSize.length?(f(this,j)[j]=n.contentBoxSize[0].inlineSize,f(this,N)[N]=n.contentBoxSize[0].blockSize):n.contentBoxSize&&n.contentBoxSize.inlineSize?(f(this,j)[j]=n.contentBoxSize.inlineSize,f(this,N)[N]=n.contentBoxSize.blockSize):(f(this,j)[j]=n.contentRect.width,f(this,N)[N]=n.contentRect.height)}this.R()},n.R=function(){if(f(this,z)[z].autoResize&&f(this,M)[M]){var t=f(this,V)[V],e=this.k();t&&!t.isLinear()?t&&(t.getWidth()>f(this,j)[j]||t.getHeight()>f(this,N)[N]?this.resizeAd(f(this,j)[j],f(this,N)[N]):(f(this,M)[M].resize(t.getWidth(),t.getHeight()+20,e),f(this,_)[_].style.width=t.getWidth()+"px",f(this,_)[_].style.height=t.getHeight()+20+"px")):this.resizeAd(f(this,j)[j],f(this,N)[N])}},n.k=function(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||f(this,D)[D].webkitDisplayingFullscreen?f(this,I)[I].ViewMode.FULLSCREEN:f(this,I)[I].ViewMode.NORMAL},n.I=function(){var t=this;f(this,_)[_].style.display="none",f(this,D)[D].ended||(f(this,C)[C].enable(),f(this,Z)[Z]?(f(this,D)[D].pause(),this.dispatchEvent(new A("pause"))):(this.p().then(function(){}).catch(function(){t.dispatchEvent(new A("pause"))}),this.dispatchEvent(new A("play")),this.dispatchEvent(new A(P.MEDIA_RESUMED))),f(this,Z)[Z]=!1)},n.B=function(t){var e=t.getError(),i=new S(e.getMessage());return i.type=e.getType(),i.errorCode=e.getErrorCode(),i.vastErrorCode=e.getVastErrorCode&&e.getVastErrorCode(),i.innerError=e.getInnerError(),i},n.j=function(t){var e=this;this.dispatchEvent(new A(P.AD_ERROR,{detail:{error:t}})),this.C(),f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):this.I()},i(e,[{key:"volume",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?f(this,M)[M].getVolume():f(this,D)[D].volume},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t),f(this,D)[D].volume=t}},{key:"muted",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?0===f(this,M)[M].getVolume():f(this,D)[D].muted},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t?0:f(this,J)[J]),f(this,D)[D].muted=t}},{key:"currentTime",get:function(){return void 0!==f(this,q)[q]?f(this,q)[q]:f(this,D)[D].currentTime},set:function(t){f(this,C)[C].enabled&&(f(this,D)[D].currentTime=t)}},{key:"duration",get:function(){return void 0!==f(this,$)[$]?f(this,$)[$]:f(this,D)[D].duration}},{key:"cuePoints",get:function(){return[].concat(f(this,Q)[Q])}}]),e}(w);let it=0;function nt(t,e){const i=t.createElement("div");return i.id=`${e?"art-vast-":"art-"}${Date.now()}-${++it}`,t.setStyles(i,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"150",display:"none"}),e&&t.setStyles(i,{backgroundColor:"black",pointerEvents:"auto"}),i}function rt(i,n={}){const r=n.compatibility;if(void 0!==r&&"workspace-1.2"!==r)throw new TypeError("Unsupported VAST compatibility mode");const s="workspace-1.2"===r;return async n=>{let r,o=!1;const a=()=>o||n.isDestroy,u={name:"artplayerPluginVast",destroy:()=>r?.destroy()};function d(){if(!o){o=!0;try{n.off("destroy",d)}finally{r?.destroy()}}}if(a())return u;n.on("destroy",d);try{if(a())return u;const o=await function(){var i=window;return i.google&&i.google.ima?Promise.resolve(i.google.ima):t||((t=new Promise(function(t,e){var i=document.createElement("script");i.async=!0,i.src="https://imasdk.googleapis.com/js/sdkloader/ima3.js",i.onload=t,i.onerror=e,document.body.appendChild(i)}).then(function(){return i.google.ima})).then(e).catch(e),t)}();if(a())return u;const h=n.constructor.utils;return r=function(t,e,i,n,r){const{$video:s,$player:o}=t.template,a=new e.AdsRenderingSettings;r&&(a.restoreCustomPlaybackStateOnAdBreakComplete=!0,a.enablePreloading=!0);const u=new R;let d=null,h=!1,l=0;const c={art:t,playUrl:(t,e={})=>y("adTagUrl",t,e),playRes:(t,e={})=>y("adsResponse",t,e),init:v,ima:e,adsRenderingSettings:a,playerOptions:u,imaPlayer:null,id:null,$container:null,get container(){return d?.container||null}};r&&Object.defineProperties(c,{imaPlayer:{get:()=>d?.player||null},id:{get:()=>d?.container.id||null},$container:{get:()=>d?.container||null}});const f=t=>d===t&&!t.released&&!n();function p(t){d===t&&(d=null),t.released=!0,t.playing=!1;const e=t.player;t.player=null;const i=t.listeners.splice(0);let n,r=!1;const s=t=>{try{t()}catch(e){r?console.error("VAST cleanup error:",e):(r=!0,n=e)}};l++;try{if(e){for(const[t,n]of i)s(()=>e.removeEventListener(t,n));s(()=>e.destroy())}s(()=>{t.container.parentNode&&t.container.parentNode.removeChild(t.container)})}finally{l--}if(r)throw n}function v(){if(n()||l)return null;if(h)throw new Error("VAST initialization is already in progress");if(d?.player)return d.player;let t;h=!0;try{if(t={container:nt(i,r),player:null,listeners:[],playing:!1,released:!1},d=t,!f(t))return p(t),null;if(o.appendChild(t.container),!f(t))return p(t),null;if(t.player=new et(e,s,t.container,a,u),!f(t))return p(t),null;const n=t,h=r?[["AdContentPauseRequested",!0],["AdContentResumeRequested",!1],["AdStarted",!0],["AdError",!1]]:[];for(const[e,i]of h){const r=t=>{f(n)&&("AdError"===e&&console.error("VAST Ad Error:",t.detail),n.playing=i,n.container.style.display=i?"block":"none")};if(t.listeners.push([e,r]),t.player.addEventListener(e,r),!f(t))return p(t),null}return r||Object.defineProperties(c,{imaPlayer:{value:t.player},id:{value:t.container.id},$container:{value:t.container}}),t.player}catch(v){if(t)try{p(t)}catch(y){console.error("VAST cleanup error:",y)}throw v}finally{h=!1}}function y(t,i,s){if(n()||r&&d?.playing)return;const o=v(),a=d;if(!o||!a)return;const u=function(t,e,i,n){const r=new t.AdsRequest;r[e]=i;const s=r;for(const o in n)s[o]=n[o];return r}(e,t,i,s);f(a)&&a.player===o&&o.playAds(u)}return{context:c,destroy:function(){d&&p(d)}}}(n,o,h,a,s),a()?(d(),u):(!s&&(r.context.init(),a())||"function"===typeof i&&await i(r.context),u)}catch(h){try{d()}catch(l){console.error("VAST cleanup error:",l)}throw h}}}return rt.default=rt,rt}); diff --git a/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.legacy.js b/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.legacy.js index 504c05b1a..1161f5d78 100644 --- a/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.legacy.js +++ b/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.legacy.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginVast=e(),define(function(){return t.artplayerPluginVast})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginVast=e()}(this,function(){"use strict";var t=null,e=function(){t=null};function i(t,e,i){return e&&function(t,e){for(var i=0;it.length)&&(e=t.length);for(var i=0,n=new Array(e);i-1&&(f(this,Q)[Q].splice(e,1),this.g(f(this,Q)[Q]))},n.resizeAd=function(t,e){f(this,j)[j]=t,f(this,N)[N]=e,f(this,M)[M]&&f(this,M)[M].resize(t,e,this.k()),f(this,_)[_].style.width=t+"px",f(this,_)[_].style.height=e+"px"},n.reset=function(t){void 0===t&&(t=!1),t&&(f(this,F)[F]=!1,f(this,G)[G]=!1,f(this,W)[W]=!1),this.C(),f(this,Q)[Q]=[],f(this,Z)[Z]=!1,f(this,$)[$]=void 0,f(this,M)[M]&&f(this,M)[M].destroy(),f(this,M)[M]=void 0,f(this,I)[I].settings.setAutoPlayAdBreaks(!0),t&&this.P(),f(this,_)[_].style.display="none"},n.P=function(){f(this,U)[U]&&(f(this,U)[U].removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),f(this,U)[U].removeEventListener(f(this,I)[I].AdErrorEvent.Type.AD_ERROR,this.l,!1),f(this,U)[U].destroy()),f(this,L)[L]&&f(this,L)[L].destroy()},n.destroy=function(){var t,e,i,n,r=this;this.reset(!0),f(this,C)[C].destroy(),T.forEach(function(t){f(r,D)[D].removeEventListener(t,r.o)}),null==(t=f(this,U)[U])||t.removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),null==(e=f(this,L)[L])||e.destroy(),null==(i=f(this,U)[U])||i.destroy(),f(this,F)[F]=!1,f(this,W)[W]=!1,f(this,G)[G]=!1,null==(n=f(this,B)[B])||n.disconnect()},n.isCustomPlaybackUsed=function(){return!1===f(this,I)[I].settings.getDisableCustomPlaybackForIOS10Plus()&&!f(this,_)[_].querySelector("video")},n.C=function(){window.clearTimeout(f(this,Y)[Y]),window.clearTimeout(f(this,X)[X]),f(this,Y)[Y]=void 0,f(this,X)[X]=void 0,f(this,x)[x]=void 0,f(this,q)[q]=void 0,f(this,K)[K]=void 0,f(this,_)[_].style.display="none",f(this,_)[_].classList.remove("nonlinear"),f(this,M)[M]&&this.R()},n.o=function(t){var e=this;if(f(this,C)[C].enabled||"volumechange"===t.type){if("timeupdate"===t.type){if(f(this,M)[M]){var i=f(this,M)[M].getCuePoints().filter(function(t){return t>=0&&t=.5&&(this.dispatchEvent(new A(P.MEDIA_IMPRESSION)),f(this,F)[F]=!0)}if("play"!==t.type||f(this,G)[G]||f(this,H)[H]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),"ended"===t.type&&(this.isCustomPlaybackUsed()&&f(this,D)[D].currentTime===f(this,D)[D].duration&&f(this,Q)[Q].indexOf(-1)>-1&&(f(this,D)[D].currentTime=f(this,D)[D].duration-1e-5,f(this,W)[W]=!0),f(this,U)[U].contentComplete(),f(this,M)[M]||this.T()),!window.ResizeObserver&&f(this,z)[z].autoResize&&"loadedmetadata"===t.type){var n=f(this,D)[D],r=n.offsetHeight,s=n.offsetWidth;f(this,j)[j]=s,f(this,N)[N]=r,this.R()}f(this,H)[H]&&"volumechange"!==t.type||this.dispatchEvent(new A(t.type))}},n.S=function(t){var e=this,i=f(this,I)[I].AdEvent;switch(t.type){case i.Type.LOADED:var n=t.getAd();f(this,$)[$]&&0===f(this,Q)[Q].length?f(this,$)[$]({ad:n,start:function(){e.M(),f(e,$)[$]=void 0},startWithoutReset:function(){e.M()}}):f(this,V)[V]=n;break;case i.Type.AD_BREAK_READY:this.C(),f(this,$)[$]?(f(this,$)[$]({ad:f(this,V)[V],adBreakTime:t.getAdData().adBreakTime,start:function(){e.M(),f(e,$)[$]=void 0},startWithoutReset:function(){e.M()}}),f(this,V)[V]=void 0):this.M();break;case i.Type.STARTED:var r=f(this,x)[x]=t.getAd();r.getAdPodInfo().getAdPosition()>1&&f(this,M)[M].setVolume(f(this,M)[M].getVolume()),f(this,_)[_].classList.remove("nonlinear"),this.R(),r.isLinear()?(f(this,C)[C].disable(),f(this,K)[K]=r.getDuration(),f(this,q)[q]=0):(f(this,_)[_].classList.add("nonlinear"),this.I()),f(this,_)[_].style.display="",f(this,Z)[Z]&&(f(this,Z)[Z]=!1,f(this,M)[M].pause());break;case i.Type.ALL_ADS_COMPLETED:if(f(this,W)[W])return;this.isCustomPlaybackUsed()&&Boolean(f(this,x)[x])&&-1!==f(this,x)[x].getAdPodInfo().getTimeOffset()&&this.I(),this.reset();break;case i.Type.CONTENT_PAUSE_REQUESTED:this.C(),f(this,x)[x]=t.getAd(),f(this,_)[_].style.display="",f(this,D)[D].pause(),this.R(),f(this,x)[x]&&this.A(f(this,x)[x].getAdPodInfo().getTimeOffset()),f(this,M)[M].setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),f(this,C)[C].disable(),f(this,K)[K]=f(this,x)[x].getDuration(),f(this,q)[q]=0;break;case i.Type.CONTENT_RESUME_REQUESTED:var s=Boolean(f(this,x)[x]);if(s){var o=f(this,M)[M].getVolume();f(this,D)[D].muted=0===o,f(this,D)[D].volume=f(this,J)[J]}f(this,W)[W]&&(f(this,D)[D].currentTime=f(this,D)[D].duration+1,f(this,W)[W]=!1),f(this,D)[D].ended?(this.reset(),this.T()):this.C(),s&&(f(this,Z)[Z]=!1,this.I());break;case i.Type.AD_METADATA:this.g(f(this,M)[M].getCuePoints()),-1===f(this,Q)[Q].indexOf(0)&&(f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):this.I());break;case i.Type.AD_PROGRESS:var a=t.getAdData();f(this,q)[q]=a.currentTime,f(this,K)[K]=a.duration;break;case i.Type.LOG:var u=t.getAdData();f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):u.adError&&!f(this,x)[x]&&this.I();break;case i.Type.VOLUME_CHANGED:var h=f(this,M)[M].getVolume();h>0&&(f(this,J)[J]=h)}},n.l=function(t){this.j(this.B(t))},n.u=function(t){var e=this,i=f(this,I)[I],n=i.AdEvent,r=i.AdErrorEvent.Type.AD_ERROR;window.clearTimeout(f(this,Y)[Y]);var s=f(this,M)[M]=t.getAdsManager(f(this,C)[C],f(this,k)[k]);Object.keys(n.Type).forEach(function(t){s.addEventListener(n.Type[t],function(i){if(e.S(i),P[t]){var n=["LOG","AD_PROGRESS"].indexOf(t)>-1;e.dispatchEvent(new A(P[t],{detail:{ad:i.getAd()||f(e,x)[x],adData:n?i.getAdData():{}}}))}})}),s.addEventListener(r,function(t){return e.j(e.B(t))});try{var o;s.init(f(this,j)[j],f(this,N)[N],this.k()),s.setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),null==(o=f(this,L)[L])||o.initialize(),f(this,$)[$]||this.M()}catch(a){this.j(new S(a.message))}},n.M=function(){if(f(this,G)[G]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),f(this,M)[M])try{f(this,M)[M].start()}catch(t){this.j(new S(t.message))}else this.I()},n.T=function(){var t=this;setTimeout(function(){f(t,F)[F]=!1,f(t,G)[G]=!1,f(t,W)[W]=!1,t.dispatchEvent(new A(P.MEDIA_STOP))},1)},n.v=function(t){for(var e,i=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(e)return(e=e.call(t)).next.bind(e);if(Array.isArray(t)||(e=function(t,e){if(t){if("string"==typeof t)return d(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?d(t,e):void 0}}(t))){e&&(t=e);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(t);!(e=i()).done;){var n=e.value;n.contentBoxSize&&1===n.contentBoxSize.length?(f(this,j)[j]=n.contentBoxSize[0].inlineSize,f(this,N)[N]=n.contentBoxSize[0].blockSize):n.contentBoxSize&&n.contentBoxSize.inlineSize?(f(this,j)[j]=n.contentBoxSize.inlineSize,f(this,N)[N]=n.contentBoxSize.blockSize):(f(this,j)[j]=n.contentRect.width,f(this,N)[N]=n.contentRect.height)}this.R()},n.R=function(){if(f(this,z)[z].autoResize&&f(this,M)[M]){var t=f(this,x)[x],e=this.k();t&&!t.isLinear()?t&&(t.getWidth()>f(this,j)[j]||t.getHeight()>f(this,N)[N]?this.resizeAd(f(this,j)[j],f(this,N)[N]):(f(this,M)[M].resize(t.getWidth(),t.getHeight()+20,e),f(this,_)[_].style.width=t.getWidth()+"px",f(this,_)[_].style.height=t.getHeight()+20+"px")):this.resizeAd(f(this,j)[j],f(this,N)[N])}},n.k=function(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||f(this,D)[D].webkitDisplayingFullscreen?f(this,I)[I].ViewMode.FULLSCREEN:f(this,I)[I].ViewMode.NORMAL},n.I=function(){var t=this;f(this,_)[_].style.display="none",f(this,D)[D].ended||(f(this,C)[C].enable(),f(this,Z)[Z]?(f(this,D)[D].pause(),this.dispatchEvent(new A("pause"))):(this.p().then(function(){}).catch(function(){t.dispatchEvent(new A("pause"))}),this.dispatchEvent(new A("play")),this.dispatchEvent(new A(P.MEDIA_RESUMED))),f(this,Z)[Z]=!1)},n.B=function(t){var e=t.getError(),i=new S(e.getMessage());return i.type=e.getType(),i.errorCode=e.getErrorCode(),i.vastErrorCode=e.getVastErrorCode&&e.getVastErrorCode(),i.innerError=e.getInnerError(),i},n.j=function(t){var e=this;this.dispatchEvent(new A(P.AD_ERROR,{detail:{error:t}})),this.C(),f(this,$)[$]?f(this,$)[$]({start:function(){e.I(),f(e,$)[$]=void 0},startWithoutReset:function(){e.I()}}):this.I()},i(e,[{key:"volume",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?f(this,M)[M].getVolume():f(this,D)[D].volume},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t),f(this,D)[D].volume=t}},{key:"muted",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?0===f(this,M)[M].getVolume():f(this,D)[D].muted},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t?0:f(this,J)[J]),f(this,D)[D].muted=t}},{key:"currentTime",get:function(){return void 0!==f(this,q)[q]?f(this,q)[q]:f(this,D)[D].currentTime},set:function(t){f(this,C)[C].enabled&&(f(this,D)[D].currentTime=t)}},{key:"duration",get:function(){return void 0!==f(this,K)[K]?f(this,K)[K]:f(this,D)[D].duration}},{key:"cuePoints",get:function(){return[].concat(f(this,Q)[Q])}}]),e}(w);let it=0;function nt(t){const e=t.createElement("div");return e.id=`art-vast-${Date.now()}-${++it}`,t.setStyles(e,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"150",backgroundColor:"black",display:"none",pointerEvents:"auto"}),e}function rt(i){return n=>{return r=null,s=null,o=function*(){let r,s=!1;const o=()=>s||n.isDestroy,a={name:"artplayerPluginVast",destroy:()=>null==r?void 0:r.destroy()};function u(){if(!s){s=!0;try{n.off("destroy",u)}finally{null==r||r.destroy()}}}if(o())return a;n.on("destroy",u);try{if(o())return a;const s=yield function(){var i=window;return i.google&&i.google.ima?Promise.resolve(i.google.ima):t||((t=new Promise(function(t,e){var i=document.createElement("script");i.async=!0,i.src="https://imasdk.googleapis.com/js/sdkloader/ima3.js",i.onload=t,i.onerror=e,document.body.appendChild(i)}).then(function(){return i.google.ima})).then(e).catch(e),t)}();if(o())return a;const h=n.constructor.utils;return r=function(t,e,i,n){const{$video:r,$player:s}=t.template,o=new e.AdsRenderingSettings;o.restoreCustomPlaybackStateOnAdBreakComplete=!0,o.enablePreloading=!0;const a=new R;let u=null,h=!1,d=0;const l=t=>u===t&&!t.released&&!n();function c(t){u===t&&(u=null),t.released=!0,t.playing=!1;const e=t.player;t.player=null;const i=t.listeners.splice(0);let n,r=!1;const s=t=>{try{t()}catch(e){r?console.error("VAST cleanup error:",e):(r=!0,n=e)}};d++;try{if(e){for(const[t,n]of i)s(()=>e.removeEventListener(t,n));s(()=>e.destroy())}s(()=>{t.container.parentNode&&t.container.parentNode.removeChild(t.container)})}finally{d--}if(r)throw n}function f(){if(n()||d)return null;if(h)throw new Error("VAST initialization is already in progress");if(null==u?void 0:u.player)return u.player;let t;h=!0;try{if(t={container:nt(i),player:null,listeners:[],playing:!1,released:!1},u=t,!l(t))return c(t),null;if(s.appendChild(t.container),!l(t))return c(t),null;if(t.player=new et(e,r,t.container,o,a),!l(t))return c(t),null;const n=t;for(const[e,i]of[["AdContentPauseRequested",!0],["AdContentResumeRequested",!1],["AdStarted",!0],["AdError",!1]]){const r=t=>{l(n)&&("AdError"===e&&console.error("VAST Ad Error:",t.detail),n.playing=i,n.container.style.display=i?"block":"none")};if(t.listeners.push([e,r]),t.player.addEventListener(e,r),!l(t))return c(t),null}return t.player}catch(f){if(t)try{c(t)}catch(p){console.error("VAST cleanup error:",p)}throw f}finally{h=!1}}function p(t,i,r){if(n()||(null==u?void 0:u.playing))return;const s=f(),o=u;if(!s||!o)return;const a=function(t,e,i,n){const r=new t.AdsRequest;r[e]=i;const s=r;for(const o in n)s[o]=n[o];return r}(e,t,i,r);l(o)&&o.player===s&&s.playAds(a)}return{context:{art:t,playUrl:(t,e={})=>p("adTagUrl",t,e),playRes:(t,e={})=>p("adsResponse",t,e),init:f,ima:e,adsRenderingSettings:o,playerOptions:a,get imaPlayer(){return(null==u?void 0:u.player)||null},get container(){return(null==u?void 0:u.container)||null}},destroy:function(){u&&c(u)}}}(n,s,h,o),o()?(u(),a):("function"===typeof i&&(yield i(r.context)),a)}catch(h){try{u()}catch(d){console.error("VAST cleanup error:",d)}throw h}},new Promise((t,e)=>{var i=t=>{try{a(o.next(t))}catch(i){e(i)}},n=t=>{try{a(o.throw(t))}catch(i){e(i)}},a=e=>e.done?t(e.value):Promise.resolve(e.value).then(i,n);a((o=o.apply(r,s)).next())});var r,s,o}}return rt.default=rt,rt}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginVast=e(),define(function(){return t.artplayerPluginVast})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginVast=e()}(this,function(){"use strict";var t=null,e=function(){t=null};function i(t,e,i){return e&&function(t,e){for(var i=0;it.length)&&(e=t.length);for(var i=0,n=new Array(e);i-1&&(f(this,Q)[Q].splice(e,1),this.g(f(this,Q)[Q]))},n.resizeAd=function(t,e){f(this,j)[j]=t,f(this,N)[N]=e,f(this,M)[M]&&f(this,M)[M].resize(t,e,this.k()),f(this,_)[_].style.width=t+"px",f(this,_)[_].style.height=e+"px"},n.reset=function(t){void 0===t&&(t=!1),t&&(f(this,F)[F]=!1,f(this,G)[G]=!1,f(this,W)[W]=!1),this.C(),f(this,Q)[Q]=[],f(this,Z)[Z]=!1,f(this,K)[K]=void 0,f(this,M)[M]&&f(this,M)[M].destroy(),f(this,M)[M]=void 0,f(this,I)[I].settings.setAutoPlayAdBreaks(!0),t&&this.P(),f(this,_)[_].style.display="none"},n.P=function(){f(this,U)[U]&&(f(this,U)[U].removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),f(this,U)[U].removeEventListener(f(this,I)[I].AdErrorEvent.Type.AD_ERROR,this.l,!1),f(this,U)[U].destroy()),f(this,L)[L]&&f(this,L)[L].destroy()},n.destroy=function(){var t,e,i,n,r=this;this.reset(!0),f(this,C)[C].destroy(),T.forEach(function(t){f(r,D)[D].removeEventListener(t,r.o)}),null==(t=f(this,U)[U])||t.removeEventListener(f(this,I)[I].AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,this.u,!1),null==(e=f(this,L)[L])||e.destroy(),null==(i=f(this,U)[U])||i.destroy(),f(this,F)[F]=!1,f(this,W)[W]=!1,f(this,G)[G]=!1,null==(n=f(this,z)[z])||n.disconnect()},n.isCustomPlaybackUsed=function(){return!1===f(this,I)[I].settings.getDisableCustomPlaybackForIOS10Plus()&&!f(this,_)[_].querySelector("video")},n.C=function(){window.clearTimeout(f(this,Y)[Y]),window.clearTimeout(f(this,X)[X]),f(this,Y)[Y]=void 0,f(this,X)[X]=void 0,f(this,B)[B]=void 0,f(this,q)[q]=void 0,f(this,$)[$]=void 0,f(this,_)[_].style.display="none",f(this,_)[_].classList.remove("nonlinear"),f(this,M)[M]&&this.R()},n.o=function(t){var e=this;if(f(this,C)[C].enabled||"volumechange"===t.type){if("timeupdate"===t.type){if(f(this,M)[M]){var i=f(this,M)[M].getCuePoints().filter(function(t){return t>=0&&t=.5&&(this.dispatchEvent(new A(P.MEDIA_IMPRESSION)),f(this,F)[F]=!0)}if("play"!==t.type||f(this,G)[G]||f(this,H)[H]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),"ended"===t.type&&(this.isCustomPlaybackUsed()&&f(this,D)[D].currentTime===f(this,D)[D].duration&&f(this,Q)[Q].indexOf(-1)>-1&&(f(this,D)[D].currentTime=f(this,D)[D].duration-1e-5,f(this,W)[W]=!0),f(this,U)[U].contentComplete(),f(this,M)[M]||this.T()),!window.ResizeObserver&&f(this,x)[x].autoResize&&"loadedmetadata"===t.type){var n=f(this,D)[D],r=n.offsetHeight,s=n.offsetWidth;f(this,j)[j]=s,f(this,N)[N]=r,this.R()}f(this,H)[H]&&"volumechange"!==t.type||this.dispatchEvent(new A(t.type))}},n.S=function(t){var e=this,i=f(this,I)[I].AdEvent;switch(t.type){case i.Type.LOADED:var n=t.getAd();f(this,K)[K]&&0===f(this,Q)[Q].length?f(this,K)[K]({ad:n,start:function(){e.M(),f(e,K)[K]=void 0},startWithoutReset:function(){e.M()}}):f(this,V)[V]=n;break;case i.Type.AD_BREAK_READY:this.C(),f(this,K)[K]?(f(this,K)[K]({ad:f(this,V)[V],adBreakTime:t.getAdData().adBreakTime,start:function(){e.M(),f(e,K)[K]=void 0},startWithoutReset:function(){e.M()}}),f(this,V)[V]=void 0):this.M();break;case i.Type.STARTED:var r=f(this,B)[B]=t.getAd();r.getAdPodInfo().getAdPosition()>1&&f(this,M)[M].setVolume(f(this,M)[M].getVolume()),f(this,_)[_].classList.remove("nonlinear"),this.R(),r.isLinear()?(f(this,C)[C].disable(),f(this,$)[$]=r.getDuration(),f(this,q)[q]=0):(f(this,_)[_].classList.add("nonlinear"),this.I()),f(this,_)[_].style.display="",f(this,Z)[Z]&&(f(this,Z)[Z]=!1,f(this,M)[M].pause());break;case i.Type.ALL_ADS_COMPLETED:if(f(this,W)[W])return;this.isCustomPlaybackUsed()&&Boolean(f(this,B)[B])&&-1!==f(this,B)[B].getAdPodInfo().getTimeOffset()&&this.I(),this.reset();break;case i.Type.CONTENT_PAUSE_REQUESTED:this.C(),f(this,B)[B]=t.getAd(),f(this,_)[_].style.display="",f(this,D)[D].pause(),this.R(),f(this,B)[B]&&this.A(f(this,B)[B].getAdPodInfo().getTimeOffset()),f(this,M)[M].setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),f(this,C)[C].disable(),f(this,$)[$]=f(this,B)[B].getDuration(),f(this,q)[q]=0;break;case i.Type.CONTENT_RESUME_REQUESTED:var s=Boolean(f(this,B)[B]);if(s){var o=f(this,M)[M].getVolume();f(this,D)[D].muted=0===o,f(this,D)[D].volume=f(this,J)[J]}f(this,W)[W]&&(f(this,D)[D].currentTime=f(this,D)[D].duration+1,f(this,W)[W]=!1),f(this,D)[D].ended?(this.reset(),this.T()):this.C(),s&&(f(this,Z)[Z]=!1,this.I());break;case i.Type.AD_METADATA:this.g(f(this,M)[M].getCuePoints()),-1===f(this,Q)[Q].indexOf(0)&&(f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):this.I());break;case i.Type.AD_PROGRESS:var a=t.getAdData();f(this,q)[q]=a.currentTime,f(this,$)[$]=a.duration;break;case i.Type.LOG:var u=t.getAdData();f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):u.adError&&!f(this,B)[B]&&this.I();break;case i.Type.VOLUME_CHANGED:var l=f(this,M)[M].getVolume();l>0&&(f(this,J)[J]=l)}},n.l=function(t){this.j(this.B(t))},n.u=function(t){var e=this,i=f(this,I)[I],n=i.AdEvent,r=i.AdErrorEvent.Type.AD_ERROR;window.clearTimeout(f(this,Y)[Y]);var s=f(this,M)[M]=t.getAdsManager(f(this,C)[C],f(this,k)[k]);Object.keys(n.Type).forEach(function(t){s.addEventListener(n.Type[t],function(i){if(e.S(i),P[t]){var n=["LOG","AD_PROGRESS"].indexOf(t)>-1;e.dispatchEvent(new A(P[t],{detail:{ad:i.getAd()||f(e,B)[B],adData:n?i.getAdData():{}}}))}})}),s.addEventListener(r,function(t){return e.j(e.B(t))});try{var o;s.init(f(this,j)[j],f(this,N)[N],this.k()),s.setVolume(f(this,D)[D].muted?0:f(this,D)[D].volume),null==(o=f(this,L)[L])||o.initialize(),f(this,K)[K]||this.M()}catch(a){this.j(new S(a.message))}},n.M=function(){if(f(this,G)[G]||(this.dispatchEvent(new A(P.MEDIA_START)),f(this,G)[G]=!0),f(this,M)[M])try{f(this,M)[M].start()}catch(t){this.j(new S(t.message))}else this.I()},n.T=function(){var t=this;setTimeout(function(){f(t,F)[F]=!1,f(t,G)[G]=!1,f(t,W)[W]=!1,t.dispatchEvent(new A(P.MEDIA_STOP))},1)},n.v=function(t){for(var e,i=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(e)return(e=e.call(t)).next.bind(e);if(Array.isArray(t)||(e=function(t,e){if(t){if("string"==typeof t)return d(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?d(t,e):void 0}}(t))){e&&(t=e);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(t);!(e=i()).done;){var n=e.value;n.contentBoxSize&&1===n.contentBoxSize.length?(f(this,j)[j]=n.contentBoxSize[0].inlineSize,f(this,N)[N]=n.contentBoxSize[0].blockSize):n.contentBoxSize&&n.contentBoxSize.inlineSize?(f(this,j)[j]=n.contentBoxSize.inlineSize,f(this,N)[N]=n.contentBoxSize.blockSize):(f(this,j)[j]=n.contentRect.width,f(this,N)[N]=n.contentRect.height)}this.R()},n.R=function(){if(f(this,x)[x].autoResize&&f(this,M)[M]){var t=f(this,B)[B],e=this.k();t&&!t.isLinear()?t&&(t.getWidth()>f(this,j)[j]||t.getHeight()>f(this,N)[N]?this.resizeAd(f(this,j)[j],f(this,N)[N]):(f(this,M)[M].resize(t.getWidth(),t.getHeight()+20,e),f(this,_)[_].style.width=t.getWidth()+"px",f(this,_)[_].style.height=t.getHeight()+20+"px")):this.resizeAd(f(this,j)[j],f(this,N)[N])}},n.k=function(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||f(this,D)[D].webkitDisplayingFullscreen?f(this,I)[I].ViewMode.FULLSCREEN:f(this,I)[I].ViewMode.NORMAL},n.I=function(){var t=this;f(this,_)[_].style.display="none",f(this,D)[D].ended||(f(this,C)[C].enable(),f(this,Z)[Z]?(f(this,D)[D].pause(),this.dispatchEvent(new A("pause"))):(this.p().then(function(){}).catch(function(){t.dispatchEvent(new A("pause"))}),this.dispatchEvent(new A("play")),this.dispatchEvent(new A(P.MEDIA_RESUMED))),f(this,Z)[Z]=!1)},n.B=function(t){var e=t.getError(),i=new S(e.getMessage());return i.type=e.getType(),i.errorCode=e.getErrorCode(),i.vastErrorCode=e.getVastErrorCode&&e.getVastErrorCode(),i.innerError=e.getInnerError(),i},n.j=function(t){var e=this;this.dispatchEvent(new A(P.AD_ERROR,{detail:{error:t}})),this.C(),f(this,K)[K]?f(this,K)[K]({start:function(){e.I(),f(e,K)[K]=void 0},startWithoutReset:function(){e.I()}}):this.I()},i(e,[{key:"volume",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?f(this,M)[M].getVolume():f(this,D)[D].volume},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t),f(this,D)[D].volume=t}},{key:"muted",get:function(){return!f(this,C)[C].enabled&&f(this,M)[M]?0===f(this,M)[M].getVolume():f(this,D)[D].muted},set:function(t){!f(this,C)[C].enabled&&f(this,M)[M]&&f(this,M)[M].setVolume(t?0:f(this,J)[J]),f(this,D)[D].muted=t}},{key:"currentTime",get:function(){return void 0!==f(this,q)[q]?f(this,q)[q]:f(this,D)[D].currentTime},set:function(t){f(this,C)[C].enabled&&(f(this,D)[D].currentTime=t)}},{key:"duration",get:function(){return void 0!==f(this,$)[$]?f(this,$)[$]:f(this,D)[D].duration}},{key:"cuePoints",get:function(){return[].concat(f(this,Q)[Q])}}]),e}(w);let it=0;function nt(t,e){const i=t.createElement("div");return i.id=`${e?"art-vast-":"art-"}${Date.now()}-${++it}`,t.setStyles(i,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"150",display:"none"}),e&&t.setStyles(i,{backgroundColor:"black",pointerEvents:"auto"}),i}function rt(i,n={}){const r=n.compatibility;if(void 0!==r&&"workspace-1.2"!==r)throw new TypeError("Unsupported VAST compatibility mode");const s="workspace-1.2"===r;return n=>{return r=null,o=null,a=function*(){let r,o=!1;const a=()=>o||n.isDestroy,u={name:"artplayerPluginVast",destroy:()=>null==r?void 0:r.destroy()};function l(){if(!o){o=!0;try{n.off("destroy",l)}finally{null==r||r.destroy()}}}if(a())return u;n.on("destroy",l);try{if(a())return u;const o=yield function(){var i=window;return i.google&&i.google.ima?Promise.resolve(i.google.ima):t||((t=new Promise(function(t,e){var i=document.createElement("script");i.async=!0,i.src="https://imasdk.googleapis.com/js/sdkloader/ima3.js",i.onload=t,i.onerror=e,document.body.appendChild(i)}).then(function(){return i.google.ima})).then(e).catch(e),t)}();if(a())return u;const d=n.constructor.utils;return r=function(t,e,i,n,r){const{$video:s,$player:o}=t.template,a=new e.AdsRenderingSettings;r&&(a.restoreCustomPlaybackStateOnAdBreakComplete=!0,a.enablePreloading=!0);const u=new R;let l=null,d=!1,h=0;const c={art:t,playUrl:(t,e={})=>y("adTagUrl",t,e),playRes:(t,e={})=>y("adsResponse",t,e),init:v,ima:e,adsRenderingSettings:a,playerOptions:u,imaPlayer:null,id:null,$container:null,get container(){return(null==l?void 0:l.container)||null}};r&&Object.defineProperties(c,{imaPlayer:{get:()=>(null==l?void 0:l.player)||null},id:{get:()=>(null==l?void 0:l.container.id)||null},$container:{get:()=>(null==l?void 0:l.container)||null}});const f=t=>l===t&&!t.released&&!n();function p(t){l===t&&(l=null),t.released=!0,t.playing=!1;const e=t.player;t.player=null;const i=t.listeners.splice(0);let n,r=!1;const s=t=>{try{t()}catch(e){r?console.error("VAST cleanup error:",e):(r=!0,n=e)}};h++;try{if(e){for(const[t,n]of i)s(()=>e.removeEventListener(t,n));s(()=>e.destroy())}s(()=>{t.container.parentNode&&t.container.parentNode.removeChild(t.container)})}finally{h--}if(r)throw n}function v(){if(n()||h)return null;if(d)throw new Error("VAST initialization is already in progress");if(null==l?void 0:l.player)return l.player;let t;d=!0;try{if(t={container:nt(i,r),player:null,listeners:[],playing:!1,released:!1},l=t,!f(t))return p(t),null;if(o.appendChild(t.container),!f(t))return p(t),null;if(t.player=new et(e,s,t.container,a,u),!f(t))return p(t),null;const n=t,d=r?[["AdContentPauseRequested",!0],["AdContentResumeRequested",!1],["AdStarted",!0],["AdError",!1]]:[];for(const[e,i]of d){const r=t=>{f(n)&&("AdError"===e&&console.error("VAST Ad Error:",t.detail),n.playing=i,n.container.style.display=i?"block":"none")};if(t.listeners.push([e,r]),t.player.addEventListener(e,r),!f(t))return p(t),null}return r||Object.defineProperties(c,{imaPlayer:{value:t.player},id:{value:t.container.id},$container:{value:t.container}}),t.player}catch(v){if(t)try{p(t)}catch(y){console.error("VAST cleanup error:",y)}throw v}finally{d=!1}}function y(t,i,s){if(n()||r&&(null==l?void 0:l.playing))return;const o=v(),a=l;if(!o||!a)return;const u=function(t,e,i,n){const r=new t.AdsRequest;r[e]=i;const s=r;for(const o in n)s[o]=n[o];return r}(e,t,i,s);f(a)&&a.player===o&&o.playAds(u)}return{context:c,destroy:function(){l&&p(l)}}}(n,o,d,a,s),a()?(l(),u):(!s&&(r.context.init(),a())||"function"===typeof i&&(yield i(r.context)),u)}catch(d){try{l()}catch(h){console.error("VAST cleanup error:",h)}throw d}},new Promise((t,e)=>{var i=t=>{try{s(a.next(t))}catch(i){e(i)}},n=t=>{try{s(a.throw(t))}catch(i){e(i)}},s=e=>e.done?t(e.value):Promise.resolve(e.value).then(i,n);s((a=a.apply(r,o)).next())});var r,o,a}}return rt.default=rt,rt}); diff --git a/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.mjs b/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.mjs index db882b343..1ad7c018d 100644 --- a/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.mjs +++ b/packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.mjs @@ -445,30 +445,54 @@ function createRequest(ima, field, value, config) { return request; } let nextId = 0; -function createContainer(utils) { +function createContainer(utils, workspaceMode) { const container = utils.createElement("div"); - container.id = `art-vast-${Date.now()}-${++nextId}`; + container.id = `${workspaceMode ? "art-vast-" : "art-"}${Date.now()}-${++nextId}`; utils.setStyles(container, { position: "absolute", inset: "0", width: "100%", height: "100%", zIndex: "150", - backgroundColor: "black", - display: "none", - pointerEvents: "auto" + display: "none" }); + if (workspaceMode) + utils.setStyles(container, { backgroundColor: "black", pointerEvents: "auto" }); return container; } -function createSession(art, ima, utils, closed) { +function createSession(art, ima, utils, closed, workspaceMode) { const { $video, $player } = art.template; const adsRenderingSettings = new ima.AdsRenderingSettings(); - adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; - adsRenderingSettings.enablePreloading = true; + if (workspaceMode) { + adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; + adsRenderingSettings.enablePreloading = true; + } const playerOptions = new E(); let current = null; let initializing = false; let releasing = 0; + const context = { + art, + playUrl: (url, config = {}) => play("adTagUrl", url, config), + playRes: (response, config = {}) => play("adsResponse", response, config), + init, + ima, + adsRenderingSettings, + playerOptions, + imaPlayer: null, + id: null, + $container: null, + get container() { + return current?.container || null; + } + }; + if (workspaceMode) { + Object.defineProperties(context, { + imaPlayer: { get: () => current?.player || null }, + id: { get: () => current?.container.id || null }, + $container: { get: () => current?.container || null } + }); + } const live = (owner) => current === owner && !owner.released && !closed(); function release(owner) { if (current === owner) @@ -519,7 +543,7 @@ function createSession(art, ima, utils, closed) { initializing = true; let owner; try { - owner = { container: createContainer(utils), player: null, listeners: [], playing: false, released: false }; + owner = { container: createContainer(utils, workspaceMode), player: null, listeners: [], playing: false, released: false }; current = owner; if (!live(owner)) { release(owner); @@ -536,12 +560,13 @@ function createSession(art, ima, utils, closed) { return null; } const allocated = owner; - for (const [name, playing] of [ + const events = workspaceMode ? [ ["AdContentPauseRequested", true], ["AdContentResumeRequested", false], ["AdStarted", true], ["AdError", false] - ]) { + ] : []; + for (const [name, playing] of events) { const callback = (event) => { if (!live(allocated)) return; @@ -557,6 +582,13 @@ function createSession(art, ima, utils, closed) { return null; } } + if (!workspaceMode) { + Object.defineProperties(context, { + imaPlayer: { value: owner.player }, + id: { value: owner.container.id }, + $container: { value: owner.container } + }); + } return owner.player; } catch (error) { if (owner) { @@ -572,7 +604,7 @@ function createSession(art, ima, utils, closed) { } } function play(field, value, config) { - if (closed() || current?.playing) + if (closed() || workspaceMode && current?.playing) return; const player = init(); const owner = current; @@ -586,24 +618,13 @@ function createSession(art, ima, utils, closed) { if (current) release(current); } - const context = { - art, - playUrl: (url, config = {}) => play("adTagUrl", url, config), - playRes: (response, config = {}) => play("adsResponse", response, config), - init, - ima, - adsRenderingSettings, - playerOptions, - get imaPlayer() { - return current?.player || null; - }, - get container() { - return current?.container || null; - } - }; return { context, destroy }; } -function artplayerPluginVast(callback) { +function artplayerPluginVast(callback, options = {}) { + const compatibility = options.compatibility; + if (compatibility !== void 0 && compatibility !== "workspace-1.2") + throw new TypeError("Unsupported VAST compatibility mode"); + const workspaceMode = compatibility === "workspace-1.2"; return async (art) => { let disposed = false; let session; @@ -629,11 +650,16 @@ function artplayerPluginVast(callback) { if (closed()) return result; const utils = art.constructor.utils; - session = createSession(art, ima, utils, closed); + session = createSession(art, ima, utils, closed, workspaceMode); if (closed()) { dispose(); return result; } + if (!workspaceMode) { + session.context.init(); + if (closed()) + return result; + } if (typeof callback === "function") await callback(session.context); return result; diff --git a/packages/artplayer-plugin-vast/src/index.ts b/packages/artplayer-plugin-vast/src/index.ts index dd58e57eb..ff0bbcca4 100644 --- a/packages/artplayer-plugin-vast/src/index.ts +++ b/packages/artplayer-plugin-vast/src/index.ts @@ -1,9 +1,13 @@ import type Artplayer from 'artplayer' -import type { Callback, Result } from './types' +import type { Callback, CompatibilityOptions, Result } from './types' import { loadImaSdk } from './sdk' import { createSession } from './session' -function artplayerPluginVast(callback?: Callback) { +function artplayerPluginVast(callback?: Callback, options: CompatibilityOptions = {}) { + const compatibility = options.compatibility + if (compatibility !== undefined && compatibility !== 'workspace-1.2') + throw new TypeError('Unsupported VAST compatibility mode') + const workspaceMode = compatibility === 'workspace-1.2' return async (art: Artplayer): Promise => { let disposed = false let session: ReturnType | undefined @@ -28,11 +32,16 @@ function artplayerPluginVast(callback?: Callback) { if (closed()) return result const utils = (art.constructor as typeof Artplayer).utils - session = createSession(art, ima, utils, closed) + session = createSession(art, ima, utils, closed, workspaceMode) if (closed()) { dispose() return result } + if (!workspaceMode) { + session.context.init() + if (closed()) + return result + } if (typeof callback === 'function') await callback(session.context) return result diff --git a/packages/artplayer-plugin-vast/src/session.ts b/packages/artplayer-plugin-vast/src/session.ts index 0c8cf01d3..417dbfcee 100644 --- a/packages/artplayer-plugin-vast/src/session.ts +++ b/packages/artplayer-plugin-vast/src/session.ts @@ -12,16 +12,39 @@ interface Owner { released: boolean } -export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, closed: () => boolean) { +export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, closed: () => boolean, workspaceMode: boolean) { const { $video, $player } = art.template const adsRenderingSettings = new ima.AdsRenderingSettings() - adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true - adsRenderingSettings.enablePreloading = true + if (workspaceMode) { + adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true + adsRenderingSettings.enablePreloading = true + } const playerOptions = new PlayerOptions() let current: Owner | null = null let initializing = false let releasing = 0 + const context: Context = { + art, + playUrl: (url, config = {}) => play('adTagUrl', url, config), + playRes: (response, config = {}) => play('adsResponse', response, config), + init, + ima, + adsRenderingSettings, + playerOptions, + imaPlayer: null, + id: null, + $container: null, + get container() { return current?.container || null }, + } + if (workspaceMode) { + Object.defineProperties(context, { + imaPlayer: { get: () => current?.player || null }, + id: { get: () => current?.container.id || null }, + $container: { get: () => current?.container || null }, + }) + } + const live = (owner: Owner) => current === owner && !owner.released && !closed() function release(owner: Owner): void { @@ -77,7 +100,7 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo initializing = true let owner: Owner | undefined try { - owner = { container: createContainer(utils), player: null, listeners: [], playing: false, released: false } + owner = { container: createContainer(utils, workspaceMode), player: null, listeners: [], playing: false, released: false } current = owner if (!live(owner)) { release(owner) @@ -94,12 +117,15 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo return null } const allocated = owner - for (const [name, playing] of [ - ['AdContentPauseRequested', true], - ['AdContentResumeRequested', false], - ['AdStarted', true], - ['AdError', false], - ] as const) { + const events = workspaceMode + ? [ + ['AdContentPauseRequested', true], + ['AdContentResumeRequested', false], + ['AdStarted', true], + ['AdError', false], + ] as const + : [] + for (const [name, playing] of events) { const callback: EventListener = (event) => { if (!live(allocated)) return @@ -115,6 +141,14 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo return null } } + if (!workspaceMode) { + // Published fields are writable data properties, not the workspace getters. + Object.defineProperties(context, { + imaPlayer: { value: owner.player }, + id: { value: owner.container.id }, + $container: { value: owner.container }, + }) + } return owner.player } catch (error) { @@ -132,7 +166,7 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo } function play(field: 'adTagUrl' | 'adsResponse', value: string, config: RequestConfig): void { - if (closed() || current?.playing) + if (closed() || (workspaceMode && current?.playing)) return const player = init() const owner = current @@ -149,16 +183,5 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo release(current) } - const context: Context = { - art, - playUrl: (url, config = {}) => play('adTagUrl', url, config), - playRes: (response, config = {}) => play('adsResponse', response, config), - init, - ima, - adsRenderingSettings, - playerOptions, - get imaPlayer() { return current?.player || null }, - get container() { return current?.container || null }, - } return { context, destroy } } diff --git a/packages/artplayer-plugin-vast/src/types.ts b/packages/artplayer-plugin-vast/src/types.ts index b7517788c..db0a7b187 100644 --- a/packages/artplayer-plugin-vast/src/types.ts +++ b/packages/artplayer-plugin-vast/src/types.ts @@ -5,6 +5,10 @@ import type Artplayer from 'artplayer' export type Utilities = Pick export type RequestConfig = Record +export interface CompatibilityOptions { + compatibility?: 'workspace-1.2' +} + export interface Context { art: Artplayer playUrl: (url: string, config?: RequestConfig) => void @@ -14,6 +18,8 @@ export interface Context { adsRenderingSettings: google.ima.AdsRenderingSettings playerOptions: PlayerOptions readonly imaPlayer: Player | null + readonly id: string | null + readonly $container: HTMLDivElement | null readonly container: HTMLDivElement | null } diff --git a/packages/artplayer-plugin-vast/src/view.ts b/packages/artplayer-plugin-vast/src/view.ts index b62521a40..200742920 100644 --- a/packages/artplayer-plugin-vast/src/view.ts +++ b/packages/artplayer-plugin-vast/src/view.ts @@ -2,18 +2,18 @@ import type { Utilities } from './types' let nextId = 0 -export function createContainer(utils: Utilities): HTMLDivElement { +export function createContainer(utils: Utilities, workspaceMode: boolean): HTMLDivElement { const container = utils.createElement('div') - container.id = `art-vast-${Date.now()}-${++nextId}` + container.id = `${workspaceMode ? 'art-vast-' : 'art-'}${Date.now()}-${++nextId}` utils.setStyles(container, { position: 'absolute', inset: '0', width: '100%', height: '100%', zIndex: '150', - backgroundColor: 'black', display: 'none', - pointerEvents: 'auto', }) + if (workspaceMode) + utils.setStyles(container, { backgroundColor: 'black', pointerEvents: 'auto' }) return container } diff --git a/refactor/baselines/vast-compatibility-validation.json b/refactor/baselines/vast-compatibility-validation.json new file mode 100644 index 000000000..13a6277e0 --- /dev/null +++ b/refactor/baselines/vast-compatibility-validation.json @@ -0,0 +1,12526 @@ +{ + "task": "PKG-VAST-03", + "date": "2026-09-14", + "baselineCommit": "314a1c3163e4c5bc8d1a9f1432726824ea3af7dc", + "node": "24.21.0", + "yarn": "1.22.22", + "typescript": "5.9.3", + "browserVersions": { + "chromium": "153.0.8010.12", + "firefox": "155.0", + "webkit": "26.6" + }, + "authorization": "User accepted published eager default and explicit workspace-1.2 lazy mode on 2026-09-14.", + "sourceCompiler": "node node_modules/typescript/bin/tsc -p packages/artplayer-plugin-vast/tsconfig.json --noEmit", + "logs": [ + { + "path": "refactor/.cache/vast03-compatibility-red.log", + "sha256": "8ed6779319fef902917768f65f46f8ceaa35d36783f61bb387a488d343767dca", + "pass": 2, + "fail": 5 + }, + { + "path": "refactor/.cache/vast03-compatibility-first.log", + "sha256": "64c043eea17231581b9544c53dfe2ecaafc5e36f38323f634fda3ba21239efc1", + "pass": 7, + "fail": 0 + }, + { + "path": "refactor/.cache/vast03-modes-node-release.log", + "sha256": "8a1be5ddc4eb6a8df79be756a202c55f25360a6134bb402d4dd34c3a8cd7c548", + "pass": 82, + "fail": 0 + }, + { + "path": "refactor/.cache/vast03-script-tests.log", + "sha256": "58af5209cd059ccb85d98a5a1a168d134fb1569978f98e8a71b61ef5fc044824", + "pass": 12, + "fail": 0 + }, + { + "path": "refactor/.cache/vast03-artifact-js.log", + "sha256": "507e5ca6a3375704928558a1ee320134d37eb99f71ed683918858ce6400c8efe", + "pass": 4, + "fail": 0 + }, + { + "path": "refactor/.cache/vast03-artifact-legacy.js.log", + "sha256": "f2b55fe086415a3f3dfb68b66c545d12d44f68978d1329d8bac441a201a99b07", + "pass": 4, + "fail": 0 + } + ], + "checks": [ + { + "path": "refactor/.cache/vast03-source-types-final.log", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "exitCode": 0 + }, + { + "path": "refactor/.cache/vast03-lint-final.log", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "exitCode": 0 + }, + { + "path": "refactor/.cache/vast03-build.log", + "sha256": "401f18f99b75fd552ab564b62c8e3f7c2d1794e2b5c13afd29c9919dde85252f", + "exitCode": 0 + }, + { + "path": "refactor/.cache/vast03-toolchain.log", + "sha256": "4c11c00ffeb93d2d3804291a155493350f29d7838067b5df3aa3417254a0b870", + "exitCode": 0 + } + ], + "initialLint": { + "path": "refactor/.cache/vast03-lint.log", + "sha256": "d0e247eea0868e45cabe96377ba860408425d4bbd742c38ef03d8b62622e1932", + "errors": 6, + "resolved": true + }, + "browserLogs": [ + { + "path": "refactor/.cache/vast03-modes-browser-first.log", + "sha256": "6c78bf09e049bdd6bf275437d60de2e276082d481db6962d00cb5567e70b5e24" + }, + { + "path": "refactor/.cache/vast03-modes-browser-final.log", + "sha256": "435fcaccaa278868f3e98a3579edb78f9d4063c3a76a14c3d833df67774a1bb4" + }, + { + "path": "refactor/.cache/vast03-modes-browser-release.log", + "sha256": "fecc2e82378c70e8f96f05de866777d63928602ede69ba82f03dd2f5bfe04c06" + } + ], + "preLintBrowser": { + "path": "refactor/.cache/vast03-modes-browser-prelint-report/report.json", + "sha256": "1a95d44fdd266d60f5ce8cf902377b35d58030f658900fdac370ee19ecdf435f" + }, + "firstBrowser": { + "report": { + "path": "refactor/.cache/vast03-modes-browser-first-report/report.json", + "sha256": "e6b33fb6c30eac6c4839f97a2413ea2d2cc9b5d9c9475d88527af4b7f662673e" + }, + "stats": { + "startTime": "2026-09-14T14:25:51.894Z", + "duration": 120905.141, + "expected": 153, + "skipped": 0, + "unexpected": 9, + "flaky": 0 + }, + "cases": [ + { + "name": "published-5.1.7 / source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 288, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 713, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 172, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "unexpected", + "results": [ + { + "status": "failed", + "retry": 0, + "duration": 7230, + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js", + "column": 33, + "line": 198 + }, + "message": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeVisible\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[id^=\"art-vast-\"]')\nExpected: visible\nTimeout: 7000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"toBeVisible\" locator('[id^=\"art-vast-\"]') with timeout 7000ms\u001b[22m\n\u001b[2m - waiting for locator('[id^=\"art-vast-\"]')\u001b[22m\n\n\n 196 | })\n 197 | const container = page.locator('[id^=\"art-vast-\"]')\n> 198 | await expect(container).toBeVisible()\n | ^\n 199 | await page.evaluate(() => {\n 200 | window.art.plugins.artplayerPluginVast.destroy()\n 201 | window.vastContext.playUrl('/two.xml')\n at D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js:198:33" + } + ], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 186, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 226, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 608, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 268, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 163, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 222, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 220, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 206, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 628, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 193, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 204, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 591, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 261, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 160, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 192, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 605, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 157, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "unexpected", + "results": [ + { + "status": "failed", + "retry": 0, + "duration": 7269, + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js", + "column": 33, + "line": 198 + }, + "message": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeVisible\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[id^=\"art-vast-\"]')\nExpected: visible\nTimeout: 7000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"toBeVisible\" locator('[id^=\"art-vast-\"]') with timeout 7000ms\u001b[22m\n\u001b[2m - waiting for locator('[id^=\"art-vast-\"]')\u001b[22m\n\n\n 196 | })\n 197 | const container = page.locator('[id^=\"art-vast-\"]')\n> 198 | await expect(container).toBeVisible()\n | ^\n 199 | await page.evaluate(() => {\n 200 | window.art.plugins.artplayerPluginVast.destroy()\n 201 | window.vastContext.playUrl('/two.xml')\n at D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js:198:33" + } + ], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 231, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 220, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 590, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 277, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 158, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 246, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 186, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 239, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 608, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 215, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 184, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 608, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 352, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 176, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 199, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 614, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 176, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "unexpected", + "results": [ + { + "status": "failed", + "retry": 0, + "duration": 7228, + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js", + "column": 33, + "line": 198 + }, + "message": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeVisible\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[id^=\"art-vast-\"]')\nExpected: visible\nTimeout: 7000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"toBeVisible\" locator('[id^=\"art-vast-\"]') with timeout 7000ms\u001b[22m\n\u001b[2m - waiting for locator('[id^=\"art-vast-\"]')\u001b[22m\n\n\n 196 | })\n 197 | const container = page.locator('[id^=\"art-vast-\"]')\n> 198 | await expect(container).toBeVisible()\n | ^\n 199 | await page.evaluate(() => {\n 200 | window.art.plugins.artplayerPluginVast.destroy()\n 201 | window.vastContext.playUrl('/two.xml')\n at D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js:198:33" + } + ], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 202, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 240, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 640, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 299, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 242, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 262, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 277, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 247, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 625, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 165, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 187, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 626, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 277, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 173, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1697, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1818, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 397, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "unexpected", + "results": [ + { + "status": "failed", + "retry": 0, + "duration": 7478, + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js", + "column": 33, + "line": 198 + }, + "message": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeVisible\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[id^=\"art-vast-\"]')\nExpected: visible\nTimeout: 7000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"toBeVisible\" locator('[id^=\"art-vast-\"]') with timeout 7000ms\u001b[22m\n\u001b[2m - waiting for locator('[id^=\"art-vast-\"]')\u001b[22m\n\n\n 196 | })\n 197 | const container = page.locator('[id^=\"art-vast-\"]')\n> 198 | await expect(container).toBeVisible()\n | ^\n 199 | await page.evaluate(() => {\n 200 | window.art.plugins.artplayerPluginVast.destroy()\n 201 | window.vastContext.playUrl('/two.xml')\n at D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js:198:33" + } + ], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 422, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 407, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 830, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 479, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 387, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 422, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 438, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 579, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1435, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 498, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 485, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1010, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1498, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 409, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 426, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1045, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 360, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "unexpected", + "results": [ + { + "status": "failed", + "retry": 0, + "duration": 7613, + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js", + "column": 33, + "line": 198 + }, + "message": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeVisible\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[id^=\"art-vast-\"]')\nExpected: visible\nTimeout: 7000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"toBeVisible\" locator('[id^=\"art-vast-\"]') with timeout 7000ms\u001b[22m\n\u001b[2m - waiting for locator('[id^=\"art-vast-\"]')\u001b[22m\n\n\n 196 | })\n 197 | const container = page.locator('[id^=\"art-vast-\"]')\n> 198 | await expect(container).toBeVisible()\n | ^\n 199 | await page.evaluate(() => {\n 200 | window.art.plugins.artplayerPluginVast.destroy()\n 201 | window.vastContext.playUrl('/two.xml')\n at D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js:198:33" + } + ], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 390, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 402, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 830, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 534, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 329, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 427, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 414, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 529, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1380, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 515, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 401, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 823, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1856, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 426, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 438, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 959, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 478, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "unexpected", + "results": [ + { + "status": "failed", + "retry": 0, + "duration": 7529, + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js", + "column": 33, + "line": 198 + }, + "message": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeVisible\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[id^=\"art-vast-\"]')\nExpected: visible\nTimeout: 7000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"toBeVisible\" locator('[id^=\"art-vast-\"]') with timeout 7000ms\u001b[22m\n\u001b[2m - waiting for locator('[id^=\"art-vast-\"]')\u001b[22m\n\n\n 196 | })\n 197 | const container = page.locator('[id^=\"art-vast-\"]')\n> 198 | await expect(container).toBeVisible()\n | ^\n 199 | await page.evaluate(() => {\n 200 | window.art.plugins.artplayerPluginVast.destroy()\n 201 | window.vastContext.playUrl('/two.xml')\n at D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js:198:33" + } + ], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 451, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 546, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 974, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 572, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 383, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 468, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 496, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 595, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1288, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 417, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1555, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 830, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 517, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 391, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1052, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 2167, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 800, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "unexpected", + "results": [ + { + "status": "failed", + "retry": 0, + "duration": 7944, + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js", + "column": 33, + "line": 198 + }, + "message": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeVisible\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[id^=\"art-vast-\"]')\nExpected: visible\nTimeout: 7000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"toBeVisible\" locator('[id^=\"art-vast-\"]') with timeout 7000ms\u001b[22m\n\u001b[2m - waiting for locator('[id^=\"art-vast-\"]')\u001b[22m\n\n\n 196 | })\n 197 | const container = page.locator('[id^=\"art-vast-\"]')\n> 198 | await expect(container).toBeVisible()\n | ^\n 199 | await page.evaluate(() => {\n 200 | window.art.plugins.artplayerPluginVast.destroy()\n 201 | window.vastContext.playUrl('/two.xml')\n at D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js:198:33" + } + ], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1002, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1109, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1832, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1755, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1076, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1075, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 937, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1186, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1848, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1003, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1229, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1748, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1469, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 5705, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 942, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1625, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1057, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "unexpected", + "results": [ + { + "status": "failed", + "retry": 0, + "duration": 7968, + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js", + "column": 33, + "line": 198 + }, + "message": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeVisible\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[id^=\"art-vast-\"]')\nExpected: visible\nTimeout: 7000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"toBeVisible\" locator('[id^=\"art-vast-\"]') with timeout 7000ms\u001b[22m\n\u001b[2m - waiting for locator('[id^=\"art-vast-\"]')\u001b[22m\n\n\n 196 | })\n 197 | const container = page.locator('[id^=\"art-vast-\"]')\n> 198 | await expect(container).toBeVisible()\n | ^\n 199 | await page.evaluate(() => {\n 200 | window.art.plugins.artplayerPluginVast.destroy()\n 201 | window.vastContext.playUrl('/two.xml')\n at D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js:198:33" + } + ], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 988, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1082, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1740, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1532, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 704, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1045, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1010, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1120, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1781, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1273, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1050, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1871, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1677, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1141, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1043, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1890, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1268, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "unexpected", + "results": [ + { + "status": "failed", + "retry": 0, + "duration": 8111, + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js", + "column": 33, + "line": 198 + }, + "message": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeVisible\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[id^=\"art-vast-\"]')\nExpected: visible\nTimeout: 7000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"toBeVisible\" locator('[id^=\"art-vast-\"]') with timeout 7000ms\u001b[22m\n\u001b[2m - waiting for locator('[id^=\"art-vast-\"]')\u001b[22m\n\n\n 196 | })\n 197 | const container = page.locator('[id^=\"art-vast-\"]')\n> 198 | await expect(container).toBeVisible()\n | ^\n 199 | await page.evaluate(() => {\n 200 | window.art.plugins.artplayerPluginVast.destroy()\n 201 | window.vastContext.playUrl('/two.xml')\n at D:\\github\\ArtPlayer\\test\\browser\\vast.spec.js:198:33" + } + ], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1005, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1004, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1777, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1630, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1386, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1148, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1217, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "sha256": "b3b7fa37d93c8eadb5db9251b453c1f51e2ae093e50b8fb534252543d40dc2d3", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1058, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1966, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1447, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1311, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1917, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1931, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1281, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + } + ] + }, + "finalBrowser": { + "report": { + "path": "refactor/.cache/vast03-modes-browser-release-report/report.json", + "sha256": "ddd6d007078e30c433026d67981ebd45ae0af78d58c3314a45e8c408f77938a6" + }, + "stats": { + "startTime": "2026-09-14T14:35:44.810Z", + "duration": 79196.26599999999, + "expected": 162, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "name": "published-5.1.7 / source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 343, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 767, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 201, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 274, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 299, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 261, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 653, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 352, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 194, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 271, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 220, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 257, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 758, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 222, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 291, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 676, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 324, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 223, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 257, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 662, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 193, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 289, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 220, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 307, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 658, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 334, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 178, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 294, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 238, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 251, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 662, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 205, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 207, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 642, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 307, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 189, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 264, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 671, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 212, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 248, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 248, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 325, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 683, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 323, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 226, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 274, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 236, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 242, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 640, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 204, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 229, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 657, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 387, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "chromium", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 219, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "153.0.8010.12", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1940, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 2325, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 504, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 535, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 538, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 591, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1009, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 696, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 465, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 528, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 466, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 518, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 935, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 467, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 482, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1189, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 712, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 605, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1106, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1462, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 414, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 430, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 439, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 460, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 883, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 543, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 381, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 458, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 393, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 469, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 886, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 411, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 429, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 900, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 547, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 525, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 711, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1235, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1661, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1600, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 534, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 583, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1071, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 765, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 519, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 618, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 623, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 674, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1044, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 574, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 670, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1225, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 819, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "firefox", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 541, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "155.0", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1146, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1928, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 893, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1132, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 973, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1103, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1899, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1553, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 907, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1003, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 905, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1230, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1999, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 877, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1009, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1791, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1508, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published-5.1.7 / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 895, + "errors": [], + "inputs": { + "core": "published-5.1.7", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.1.7" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1108, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1961, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 955, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1062, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1139, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1083, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1830, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1559, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 773, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1097, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1095, + "errors": [], + "inputs": { + "core": "published", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1044, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1746, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1123, + "errors": [], + "inputs": { + "core": "published", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1035, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1844, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1603, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "published / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1151, + "errors": [], + "inputs": { + "core": "published", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.0" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 996, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1777, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1121, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1048, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 943, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source", + "options": {}, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1035, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1895, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1609, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate suppresses late SDK initialization after real core destruction", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1173, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate isolates stale events and terminates recreated ads on core destroy", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1038, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "players": [ + { + "requests": [ + { + "adTagUrl": "/one.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "block" + }, + { + "requests": [ + { + "adTagUrl": "/two.xml" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / source-workspace: candidate callback rejection cleans allocated SDK and DOM without destroying the core", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1142, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "source-workspace", + "options": { + "compatibility": "workspace-1.2" + }, + "sha256": "6bee5af9439fbd46268c2c9fc84a5b29257d86cae891c6ae0ec93c9802b5af58", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [], + "destroyCalls": 1, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1079, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1828, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / published-1.0.0-source historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1206, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "published-1.0.0-source", + "options": {}, + "sha256": "2d41a516b07abf90d92d84ff6e4ea6873bb2d4ebfd00d4d21f0935aed372ee03", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: async SDK and callback gate real core registration and preserve requests", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1063, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/test/ad-tag.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: SDK rejection stays observable and core can still play content", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1802, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0: real overlay follows SDK events and explicit cleanup supports inactive recreation", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1667, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": false, + "players": [ + { + "requests": [ + { + "adTagUrl": "/first.xml" + }, + { + "adsResponse": "" + } + ], + "destroyCalls": 1, + "connected": false, + "display": "none" + }, + { + "requests": [ + { + "adTagUrl": "/new-session.xml" + } + ], + "destroyCalls": 0, + "connected": true, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + }, + { + "name": "candidate / frozen-workspace-1.2.0 historical: late SDK after destroy allocates into the detached player", + "project": "webkit", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "duration": 1152, + "errors": [], + "inputs": { + "core": "candidate", + "implementation": "frozen-workspace-1.2.0", + "options": {}, + "sha256": "ac391200c572c8e68431212e6b5f102956f959196ad98da54fa2f42b4d8888bf", + "sdk": "controlled wrapper recorder, no IMA execution" + }, + "state": { + "destroyed": true, + "callbackCalls": 1, + "players": [ + { + "requests": [ + { + "adTagUrl": "/late.xml" + } + ], + "destroyCalls": 0, + "connected": false, + "display": "none" + } + ], + "coreVersion": "5.4.1" + }, + "browserVersion": "26.6", + "platform": "win32" + } + ] + } + ] + }, + "resources": { + "/candidate/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "/compiled/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931, + "aliasOf": "/candidate/artplayer.js" + }, + "/uncompiled/artplayer/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931, + "aliasOf": "/candidate/artplayer.js" + }, + "/candidate/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529 + }, + "/compiled/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/uncompiled/artplayer-plugin-chapter/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/published/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "/published/artplayer-plugin-chapter.js": { + "source": { + "kind": "npm-release", + "version": "1.1.0", + "integrity": "sha512-ji66Lr2K2S+OjFMuMby3yq+pefWlOC51Sbpop/DIr2N6w3F0smrF+YZbshN1Dy8/Tx1TYpT7N6WkkZWy5Jix1w==", + "member": "package/dist/artplayer-plugin-chapter.js" + }, + "sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0", + "bytes": 4973 + }, + "/test/pattern.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.mp4" + }, + "sha256": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233", + "bytes": 251538 + }, + "/test/pattern.webm": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.webm" + }, + "sha256": "9d3c2b3dec9581a599de2d6732992ef7846790e0d1368e6e131bd339b39e984f", + "bytes": 162073 + }, + "/published-4.5.5/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "4.5.5", + "integrity": "sha512-HeAKbe3od9ZgFQVSBCg5FlixJsefDEBC8txVG19yZgvzlcJuiurxPlasap+GHuex/ftG+jmSXnTRtuNrTki2Kw==", + "member": "package/dist/artplayer.js" + }, + "sha256": "3467e626ca29d2f7884e75eb75b8b90de74a25761ffa2e272576c9b5a98fa0a4", + "bytes": 153582 + }, + "/published-5.1.7/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.1.7", + "integrity": "sha512-N/QdNlTwsIHUsWOHMPj0pq97v3qmgXZHfhy1q7I+8YN3/XakJiJJyVJgGaeBjU+y/fUIrzBhwpBaX+NFwK9/qw==", + "member": "package/dist/artplayer.js" + }, + "sha256": "484ccc3f22446ec6fd0dd8b8a5602c740b601d55097a1ae043262d92aab35357", + "bytes": 155940 + }, + "/published-4.5.9/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "4.5.9", + "integrity": "sha512-x5JzGdXkw4GFdztvPkVnm8TOWrGDcvGKKMPb9wuP6UfyftlLM3UQctmmalfAMnQSxugJwq2Kb9ix9OG2SgbJJA==", + "member": "package/dist/artplayer.js" + }, + "sha256": "09a9f09e3a64a02ca7c27af710d7254f886f0bfb09fd54bf3a728ce863e5a497", + "bytes": 156408 + }, + "/published-5.3.0/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.3.0", + "integrity": "sha512-yExO39MpEg4P+bxgChxx1eJfiUPE4q1QQRLCmqGhlsj+ANuaoEkR8hF93LdI5ZyrAcIbJkuEndxEiUoKobifDw==", + "member": "package/dist/artplayer.js" + }, + "sha256": "54ffaf7598b910d5a88d2d2eec1aa6faa806583915b99b892dd32129c53e421a", + "bytes": 159238 + }, + "/published-5.1.6/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.1.6", + "integrity": "sha512-cqnVVLKCKWCryKl6Pmop50/Di9IQwOeNNQs5qWGzJDPiM0qTC7Q/Enusa+8JQid8p09fvp4Vc32ViSSYutdEeQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "6a7b1f3007ecda9f399e6cff606490dd745c495e19ce10e864a401ff09996172", + "bytes": 155714 + }, + "/published-5.1.2/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.1.2", + "integrity": "sha512-eIWlxiP2ghgftaZWIGnclkOpXGFZTOf5xrm6sGZCGx5A8wGbTHRSMe+ZiyPFpbNhBVupi/QObSjX/FcD+YbS1Q==", + "member": "package/dist/artplayer.js" + }, + "sha256": "3dfd035b4cde34c9d9dd1b303f95bfbb42bde105bcb3e5671a8d375a719290b1", + "bytes": 154583 + }, + "/test/audio-tone.m4a": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/audio-tone.m4a" + }, + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436 + }, + "/test/thumbnail-pattern.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/thumbnail-pattern.mp4" + }, + "sha256": "4c977be04d97f6ac1342ac4959b8e61678f390d88a088430e4d0200137a03d1c", + "bytes": 752916 + }, + "/test/auto-thumbnail-timeline.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/auto-thumbnail-timeline.mp4" + }, + "sha256": "10370156cffada462d3ea00aae0caadd62752369cd6538cc55248b3ddd7bf994", + "bytes": 8602 + }, + "/test/declaration-cues.vtt": { + "source": { + "kind": "test-subtitles", + "file": "test/browser/media/declaration-cues.vtt" + }, + "sha256": "5d149d4e641ce41cbb83376835c03daf1fb89f3b9f568fa59e064d51e2b57704", + "bytes": 54 + }, + "/test/thumbnail-grid.svg": { + "source": { + "kind": "test-thumbnail-grid", + "file": "test/browser/media/thumbnail-grid.svg" + }, + "sha256": "bb3f1ec9895d37def77ca4b192d3cd73577a2668558cc99de1588f511d65d3e6", + "bytes": 14969 + }, + "/test/legacy-safe-area.js": { + "source": { + "kind": "frozen-own-source", + "file": "test/helpers/legacy-safe-area.js", + "commit": "ccf77c4e" + }, + "sha256": "ce0368618ef6363b78271b8bcc7973abd0478e797cc464ddd912929e6dfa501a", + "bytes": 795 + }, + "/test/iframe-boundary-child.html": { + "source": { + "kind": "iframe-fixture", + "file": "test/browser/iframe-boundary-child.html" + }, + "sha256": "4721de185f606de7d576e71395127257e476765455e2a947ded79df4ebed901a", + "bytes": 1451 + }, + "/published-5.3.1-beta.1/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "/assets/sample/video.mp4": { + "source": { + "kind": "docs-media", + "file": "docs/assets/sample/video.mp4" + }, + "sha256": "30a2de667ba267b6bc605edcee1c4bd728c048ed76f500ea0e73d1f1a6f8f980", + "bytes": 5818706 + }, + "/test/performance.js": { + "source": { + "kind": "adapted-baseline-fixture", + "file": "refactor/fixtures/performance.js" + }, + "sha256": "c5a8a8611db004aadd6c3b82c61b8ae242319c1a12e73bf784c1da06fcebed72", + "bytes": 9251 + } + }, + "files": [ + { + "path": "package.json", + "sha256": "b73d3a65b84166b8a854123681d4f9cbf9837b2bf3b5a9ffba8065dd8f92b721" + }, + { + "path": "packages/artplayer-plugin-vast/src/index.ts", + "sha256": "4221668a9e96cc7feef0f98f6276261c174431ef24b9b8c81d0f5d84261a6cd1" + }, + { + "path": "packages/artplayer-plugin-vast/src/sdk.ts", + "sha256": "aaff7c1e4a31ff99261b045648663caa46f66b5a25ad129e5fc929facaf1ff89" + }, + { + "path": "packages/artplayer-plugin-vast/src/session.ts", + "sha256": "08ad97deaa386d26034711e17fba001f326c842960efb83cb858db3a2bd09e48" + }, + { + "path": "packages/artplayer-plugin-vast/src/types.ts", + "sha256": "ce35e64057e059bea40325baa2dee68ba9f32a794f6989ed65f6053c56c9672d" + }, + { + "path": "packages/artplayer-plugin-vast/src/view.ts", + "sha256": "15e5b186bdcb8f9f60379e726eedec4b31ca61df27efe1891effccb1e56db491" + }, + { + "path": "test/vast-compatibility.test.js", + "sha256": "39f868f917d703b8e684df1d2c49745ac34f685821a3e0a46a13c2b4adfadf75" + }, + { + "path": "test/vast.test.js", + "sha256": "4dc15cfb158982d215d0dd418ea152282c0a2e6bda83eceb7a306c6bcdbe84a9" + }, + { + "path": "test/vast-lifecycle.test.js", + "sha256": "3e56629f66a3069357906224f81a23b556285e710dfaa0318dfd00e38f7531a6" + }, + { + "path": "test/vast-exports.test.js", + "sha256": "437fe773065d071afcecfe58c139a67b5b7b259baee1d44235e2f1b2bfc5f41c" + }, + { + "path": "test/helpers/vast.js", + "sha256": "a75d84890d0c5f44a586dc971fbf2f89b85643a1308c189c92e056cbc10e45b5" + }, + { + "path": "test/helpers/vast-sdk.js", + "sha256": "f8bc792ef16da9396bafefaf89f1b53b6254bf263d0c3019b87ee188eac35bd1" + }, + { + "path": "test/browser/vast.spec.js", + "sha256": "73fe175cd203af417f78e03980e59006f3c33af81d0f06822edcf7a87d09bacb" + } + ], + "artifactCopies": [ + { + "artifact": { + "path": "packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.js", + "sha256": "cebaf6a44f80079841205498c4f855ba4e5c804ae7958c06eadda524d728e079" + }, + "docs": { + "path": "docs/compiled/artplayer-plugin-vast.js", + "sha256": "cebaf6a44f80079841205498c4f855ba4e5c804ae7958c06eadda524d728e079" + } + }, + { + "artifact": { + "path": "packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.legacy.js", + "sha256": "8ebb4ebdd4c0fc5ddc467d5ee15b18ab7e5c078c15bbfd37dc33aa89eac1de92" + }, + "docs": { + "path": "docs/compiled/artplayer-plugin-vast.legacy.js", + "sha256": "8ebb4ebdd4c0fc5ddc467d5ee15b18ab7e5c078c15bbfd37dc33aa89eac1de92" + } + }, + { + "artifact": { + "path": "packages/artplayer-plugin-vast/dist/artplayer-plugin-vast.mjs", + "sha256": "a63e6e8b27032ea690fe740e9ec0a98646346f1fcd3622740f1f5363f234a72b" + }, + "docs": { + "path": "docs/compiled/artplayer-plugin-vast.mjs", + "sha256": "a63e6e8b27032ea690fe740e9ec0a98646346f1fcd3622740f1f5363f234a72b" + } + } + ], + "limitations": [ + "SDK boundary is a controlled recorder; no real Google IMA ad playback or device acceptance.", + "Artifact export tests use an already destroyed host; full installed distribution remains task06.", + "Public declaration and second parameter consumption remain task04; runtime authorization does not waive type compatibility.", + "Actual core baselines are npm5.1.7/npm5.4.0 and candidate5.4.1; earlier prose claiming published5.4.1 was incorrect.", + "Initial browser failures preserve the stale workspace-only expectations, not a claim of an IMA vendor regression." + ] +} diff --git a/refactor/changes/2026-09-14-PKG-VAST-03-compatibility.md b/refactor/changes/2026-09-14-PKG-VAST-03-compatibility.md new file mode 100644 index 000000000..1af0bd51a --- /dev/null +++ b/refactor/changes/2026-09-14-PKG-VAST-03-compatibility.md @@ -0,0 +1,61 @@ +# PKG-VAST-03:按已确认决策完成运行时兼容与资源整理 + +基线314a1c3163e4c5bc8d1a9f1432726824ea3af7dc;本记录完成早期 +[03检查点](2026-09-12-PKG-VAST-03-lifecycle.md)的剩余初始化兼容任务。 +2026-09-14用户明确接受“保留 npm 默认行为,显式选择工作区惰性模式”, +[具体决策与迁移示例](../vast-compatibility-decision.md)现在是实现依据。 + +## 实现及兼容边界 + +五个TS模块已分离工厂/异步注册、SDK边界、会话资源、DOM样式和内部类型。 +默认工厂在callback前创建Player,恢复实际npm1.0.0的id/$container/imaPlayer +可写数据属性与SDK默认设置。默认包装层不添加工作区四事件显隐或活动请求抑制, +透明容器保留发布样式,显式请求继续逐次转发;没有把SDK行为复制到包装层。 + +可选第二参数`{ compatibility: 'workspace-1.2' }`保留未发布工作区的惰性初始化、 +设置/选项原对象、两个默认flags、黑色overlay、四事件显隐、活动广告抑制和资源 +实时getter。模式在工厂创建时快照一次,未知值在加载SDK前抛TypeError。 +普通已发布JS调用无需变化;依赖未发布默认惰性的代码必须按已批准方案增加选项。 + +两种模式共享早期修复的core销毁终止、晚到SDK/回调取消、失败回滚、会话身份隔离、 +重复清理与显式重建。默认发布数据字段保留已释放资源快照,扩展container getter归零; +后续显式重建更新数据字段,core销毁禁止重建。工作区资源getter随当前会话归零。 +ID保留各自art-/art-vast-前缀并增加递增后缀,保留已复现同毫秒碰撞的修复。 + +公开声明没有在本任务完成:04仍须协调历史同步误声明、回调字段、第二参数和准确 +类型入口;本次运行时授权不自动授权其他类型取舍。实际Google IMA由05验收,最终 +安装分发由06验收。README明确JS示例及当前声明门槛;未改变包版本或依赖/lockfile。 +现有docs/assets/example/vast.js使用默认回调和playUrl,符合npm模式,不需改写。 + +## 验证与失败记录 + +完整输入/日志/产物指纹见[验证索引](../baselines/vast-compatibility-validation.json)。 + +- 新兼容文件初始7项:旧候选2通过5失败,包含默认初始化、旧字段与提前构造失败。 + 修复后7通过,再补回调失败的二次清理异常、显式重建和选项快照/非法值,最终10通过。 +- 当前完整`yarn test:vast`82通过、零跳过;包括旧发布/冻结工作区观察、显式模式及默认 + 生命周期。该文件进入test:vast/test:unit;工程脚本相关12项测试通过。 +- 三桌面引擎×三个核心×四种实现/模式162通过:99候选、63历史。核验异步注册门控、 + 回调开始前资源、字段描述符、默认值、真实DOM显隐/清理、主片解码及切源。 + 候选两模式执行同一份编译源码,以选项区分;第三方SDK为明确标记的受控记录器。 + 本次报告确认核心实际为npm5.1.7、npm5.4.0、候选5.4.1;早期文档将published路径 + 写成5.4.1不准确,以附件中的来源哈希和实际coreVersion为准,本次更正维护说明。 +- 首轮153通过9失败:旧candidate显隐用例沿用工作区art-vast-选择器与四事件显隐, + 和已确认的npm默认语义不符。保留原日志/trace;按两种历史行为验证实际容器数、 + 0/4监听、显隐,再验证重建/销毁。回调失败也按实际容器前缀检测,避免虚假零残留。 + 增加回调开始时字段/时机断言后162通过;源码lint整理后最终162再次通过。 +- 严格TS5.9.3及源/测试lint通过。初次lint6项格式/声明顺序错误已修正并保留日志; + 没有引入禁用规则。严格固定工具链检查通过。 +- 正常VAST构建三格式成功,dist与docs/compiled对应文件哈希一致。实际main+ESM和 + legacy+ESM分别4项导出用例通过:CommonJS/global/AMD和原生ESM,均验证default别名。 + 这些产物用例使用已销毁宿主,不执行IMA;不能把它们解释为正式SDK广告播放通过。 + +## 任务边界及回退 + +PKG-VAST-03完成运行时结构/资源/初始化协调,VAST-CONTEXT-01按用户决策接受限定范围。 +VAST-LIFE-01保留实际供应商恢复验证门槛;VAST-TYPE/DIST及04/05/06仍开放。 +没有使用VPN例外、模拟广告成功、远端CI或npm发布声明。 + +本任务独立本地commit包含源、测试、构建、文档、任务及风险索引,提交后核验审计。 +回退本提交并重建VAST会恢复此前默认工作区初始化,也撤销本次兼容选择;旧已发布 +默认调用的失败将重现。早期资源修复检查点不随本提交回退而消失。 diff --git a/refactor/plan.md b/refactor/plan.md index ad94bc3ea..33a9a0d18 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -4,7 +4,7 @@ 基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 262 项,范围 22 个包及工作区/示例。 -状态:todo 48 / doing 21 / blocked 0 / done 193 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 48 / doing 20 / blocked 0 / done 194 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -296,7 +296,7 @@ | --- | --- | --- | --- | --- | --- | --- | | PKG-VAST-01 | artplayer-plugin-vast
核对包契约与历史用法 | BASE-05 | 异步工厂、callback context、playUrl/playRes/init 与 SDK 版本;实际 npm 1.0.0 与未发布 1.2.0、SDK 1.21.0/1.21.2 的60成员归档和发布关联核心5.1.7 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | H | done | | PKG-VAST-02 | artplayer-plugin-vast
建立特有行为与错误测试 | PKG-VAST-01, ENG-03, ENG-05 | SDK 失败、重复初始化、广告事件、内容恢复和销毁竞态;发布 id/$container/eager 与工作区 lazy/config 覆盖、callback拒绝、加载中销毁、同毫秒多实例与晚到事件 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done | -| PKG-VAST-03 | artplayer-plugin-vast
整理内部职责与资源 | PKG-VAST-02, CORE-10, CORE-13 | SDK loader、IMA adapter、广告状态和 DOM 清理分离;保持发布 callback 别名,明确初始化冲突;核心终止与显式 destroy 后重建区分 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | doing | +| PKG-VAST-03 | artplayer-plugin-vast
整理内部职责与资源 | PKG-VAST-02, CORE-10, CORE-13 | SDK loader、IMA adapter、广告状态和 DOM 清理分离;保持发布 callback 别名,明确初始化冲突;核心终止与显式 destroy 后重建区分 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | done | | PKG-VAST-04 | artplayer-plugin-vast
迁移自有源码和公开类型 | PKG-VAST-03, ENG-04, ENG-06, CORE-07, PKG-VAST-07 | IMA/context/Promise 真实类型,外部 SDK 动态对象限定边界;修复 @alugha/ima 声明依赖链,保留 export= 和 require.default 消费;同步错误声明的兼容决策单列 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo | | PKG-VAST-05 | artplayer-plugin-vast
验证新旧核心和组合 | PKG-VAST-04, CORE-22 | 官方测试广告或受控 SDK 环境,错误后主视频状态恢复;核验真实5.1.7/5.4.1/候选核心,VAST VPN外部脚本例外逐项记录,不将受控SDK当作实际IMA验收 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo | | PKG-VAST-06 | artplayer-plugin-vast
验证分发并同步文档 | PKG-VAST-05, ENG-07 | vast.js、SDK 资源、声明消费和独立版本记录;核验实际发布 namespace default、历史深路径、ESM和准确声明,版本按政策2.0.0由REL-09统一处理 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo | @@ -600,7 +600,7 @@ - PKG-ADS-05: [记录](changes/2026-09-12-PKG-ADS-05-browser.md) [记录](baselines/ads-ui-visibility-validation.json) - PKG-VAST-01: [记录](baselines/vast-contract.md) [记录](baselines/vast-release.json) [记录](changes/2026-09-12-PKG-VAST-01-contract.md) [记录](baselines/vast-contract-validation.json) - PKG-VAST-02: [记录](changes/2026-09-12-PKG-VAST-02-tests.md) [记录](baselines/vast-behavior-validation.json) [记录](baselines/vast-core.json) [记录](vast-validation.md) -- PKG-VAST-03: [记录](changes/2026-09-12-PKG-VAST-03-lifecycle.md) [记录](baselines/vast-lifecycle-validation.json) [记录](vast-compatibility-decision.md) +- PKG-VAST-03: [记录](changes/2026-09-12-PKG-VAST-03-lifecycle.md) [记录](baselines/vast-lifecycle-validation.json) [记录](vast-compatibility-decision.md) [记录](changes/2026-09-14-PKG-VAST-03-compatibility.md) [记录](baselines/vast-compatibility-validation.json) - PKG-CAST-01: [记录](baselines/chromecast-release.json) [记录](baselines/chromecast-contract.md) [记录](baselines/chromecast-contract-validation.json) [记录](changes/2026-09-13-PKG-CAST-01-contracts.md) - PKG-CAST-02: [记录](changes/2026-09-13-PKG-CAST-02-failures.md) [记录](baselines/chromecast-failures-validation.json) - PKG-CAST-03: [记录](changes/2026-09-13-PKG-CAST-03-runtime.md) [记录](baselines/chromecast-runtime-validation.json) diff --git a/refactor/progress.md b/refactor/progress.md index 4f0763c01..4b3ae48df 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,25 @@ # 进度与证据 +## PKG-VAST-03 已确认初始化策略与运行时资源整理完成 + +用户于2026-09-14明确接受npm提前初始化默认、显式workspace-1.2惰性模式。 +默认恢复回调前Player、id/$container/imaPlayer可写数据字段及SDK原默认设置; +显式模式保留工作区四事件显隐、活动请求抑制、可变设置和资源实时getter。 +两者共享销毁终止、失败回滚、旧会话隔离和显式重建修复;模块地图/迁移JS示例同步。 + +当前Node82通过,三浏览器162通过(99候选、63历史),工程脚本12通过;严格 +TS5.9.3、lint和工具链检查通过。首轮浏览器153通过9失败保留:旧断言误用 +工作区选择器/显隐语义,现按历史责任分模式并补充回调起始状态断言,未放宽清理。 +实际核心为npm5.1.7/npm5.4.0/候选5.4.1,纠正旧维护说明误称published5.4.1。 +正常构建三格式及docs副本一致,实际main+ESM/legacy+ESM各4项导出检查通过。 + +详见[变更](changes/2026-09-14-PKG-VAST-03-compatibility.md)、 +[指纹和结果](baselines/vast-compatibility-validation.json)及 +[接受的决策](vast-compatibility-decision.md)。本项完成,262项现194 done、 +20 doing、48 todo;初始化风险按用户决定限定接受。SDK仍受控,实际IMA恢复、 +公开声明(包括第二参数)、安装分发分别留在05/04/06;未用VPN例外,未push/发布。 +本任务独立本地提交,提交后先核验审计;下一步处理VAST公开类型04。 + ## PKG-DANMUKU-MASK-LOAD-01 真实模型负载漏显与积压修复 连续播放采样补回主线程卡顿跨过的既有wait行,公开readys窗口不变;允许重叠 diff --git a/refactor/risk-table.md b/refactor/risk-table.md index 2d1d4dbab..4b993bcd3 100644 --- a/refactor/risk-table.md +++ b/refactor/risk-table.md @@ -147,7 +147,7 @@ | ADS-LIFE-01 | resolved / 已复现 | Ads 计时链、重复/过早调用、工厂复用与销毁缺乏资源边界 | PKG-ADS-02, PKG-ADS-03, PKG-ADS-05 | | ADS-MEDIA-01 | open / 已复现 | Ads metadata 与 play 拒绝、隐藏页媒体状态和内容恢复仍缺真实验证 | PKG-ADS-02, PKG-ADS-03, PKG-ADS-05 | | ADS-UI-01 | resolved / 已复现 | Ads 零等待跳过与初始状态不符,全屏图标/外部状态需核验 | PKG-ADS-02, PKG-ADS-03, PKG-ADS-05 | -| VAST-CONTEXT-01 | open / 已复现 | Published VAST callback aliases and eager Player differ from the unpublished lazy workspace | PKG-VAST-02, PKG-VAST-03, PKG-VAST-04 | +| VAST-CONTEXT-01 | accepted-with-scope / 已复现 | Published VAST callback aliases and eager Player differ from the unpublished lazy workspace | PKG-VAST-02, PKG-VAST-03, PKG-VAST-04 | | VAST-TYPE-01 | open / 已复现 | VAST declares an async factory as synchronous and imports an unavailable SDK type dependency | PKG-VAST-04, PKG-VAST-06 | | VAST-LIFE-01 | open / 已复现 | VAST SDK and container lack core destruction ownership and pending work cancellation | PKG-VAST-02, PKG-VAST-03, PKG-VAST-05 | | VAST-DIST-01 | open / 已复现 | Published VAST CommonJS default namespace differs from the current callable distribution | PKG-VAST-04, PKG-VAST-06, PKG-VAST-07 | diff --git a/refactor/risks.json b/refactor/risks.json index ad326d999..dce882cb3 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -3255,7 +3255,7 @@ "id": "VAST-CONTEXT-01", "title": "Published VAST callback aliases and eager Player differ from the unpublished lazy workspace", "confirmation": "reproduced", - "status": "open", + "status": "accepted-with-scope", "owners": [ "PKG-VAST-02", "PKG-VAST-03", @@ -3266,10 +3266,18 @@ "refactor/baselines/vast-release.json", "refactor/changes/2026-09-12-PKG-VAST-01-contract.md", "refactor/baselines/vast-contract-validation.json", + "refactor/vast-compatibility-decision.md", + "refactor/changes/2026-09-14-PKG-VAST-03-compatibility.md", + "refactor/baselines/vast-compatibility-validation.json" + ], + "compatibleResolution": "User accepted npm eager default and explicit workspace-1.2 lazy mode. Published callback data fields, SDK defaults, container styles and request forwarding are preserved; workspace extensions are opt-in.", + "closureCriteria": "Published and workspace consumer fixtures cover all callback fields and initialization timing; any irreconcilable behavior has a concrete decision rather than implicit waiver.", + "resolutionEvidence": [ + "refactor/changes/2026-09-14-PKG-VAST-03-compatibility.md", + "refactor/baselines/vast-compatibility-validation.json", "refactor/vast-compatibility-decision.md" ], - "compatibleResolution": "Restore published id/$container access and reconcile eager non-null Player with lazy workspace usage using explicit consumer evidence.", - "closureCriteria": "Published and workspace consumer fixtures cover all callback fields and initialization timing; any irreconcilable behavior has a concrete decision rather than implicit waiver." + "resolutionRationale": "The mutually exclusive initialization timing is explicitly approved and covered by published/workspace consumer tests. Unpublished lazy callers add the second option; public declarations remain VAST-TYPE-01/task04 and real IMA remains task05." }, { "id": "VAST-TYPE-01", @@ -3312,11 +3320,13 @@ "refactor/baselines/vast-core.json", "refactor/vast-validation.md", "refactor/baselines/vast-lifecycle-validation.json", - "refactor/changes/2026-09-12-PKG-VAST-03-lifecycle.md" + "refactor/changes/2026-09-12-PKG-VAST-03-lifecycle.md", + "refactor/changes/2026-09-14-PKG-VAST-03-compatibility.md", + "refactor/baselines/vast-compatibility-validation.json" ], "compatibleResolution": "Reproduce pending SDK/callback destruction, errors, duplicate IDs and stale ad events before adding compatible cleanup and state ownership.", "closureCriteria": "Tests prove cleanup during load/callback rejection/core destruction and distinguish explicit plugin recreation from terminal core destruction; vendor media restoration is separately verified.", - "workspaceState": "45 Node tests include 16 frozen historical observations across 10 lifecycle/error categories. Real browser core destruction plus late SDK resolution leaves a newly allocated recorder in the detached player across 5.1.7/5.4.1/candidate. Google IMA allocation itself is not simulated as evidence; exact wrapper SDK boundary is controlled. All production fixes remain PKG-VAST-03 work. PKG-VAST-03 checkpoint: 15 candidate lifecycle assertions fail on frozen workspace and pass after TS ownership changes; 117 real browser wrapper checks pass with controlled SDK. Risk stays open pending full compatibility and actual vendor acceptance." + "workspaceState": "Task03 runtime ownership and both approved modes pass82 Node and162 real-browser wrapper checks (99 candidate,63 historical), with controlled SDK only. Eager callback errors/cancellation, rollback and explicit recreation are covered. Risk remains open for actual vendor media restoration in task05; no VPN exception was used." }, { "id": "VAST-DIST-01", diff --git a/refactor/tasks.json b/refactor/tasks.json index 105c3350b..f9ec66340 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -3086,14 +3086,16 @@ "CORE-10", "CORE-13" ], - "status": "doing", + "status": "done", "risk": "H", "deliverable": "SDK loader、IMA adapter、广告状态和 DOM 清理分离;保持发布 callback 别名,明确初始化冲突;核心终止与显式 destroy 后重建区分", "acceptance": "结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过", "evidence": [ "changes/2026-09-12-PKG-VAST-03-lifecycle.md", "baselines/vast-lifecycle-validation.json", - "vast-compatibility-decision.md" + "vast-compatibility-decision.md", + "changes/2026-09-14-PKG-VAST-03-compatibility.md", + "baselines/vast-compatibility-validation.json" ] }, { diff --git a/refactor/vast-compatibility-decision.md b/refactor/vast-compatibility-decision.md index 5587405c4..ca30a88e7 100644 --- a/refactor/vast-compatibility-decision.md +++ b/refactor/vast-compatibility-decision.md @@ -1,4 +1,8 @@ -# VAST 初始化兼容决策:待用户选择 +# VAST 初始化兼容决策:已确认并完成运行时实施 + +2026-09-14用户明确接受:“保留 npm 默认行为,显式选择工作区惰性模式”。 +以下推荐方案现在是实施依据,不再等待此项授权。生命周期、类型、实际IMA与 +分发仍须分别验证;本确认不豁免这些门槛,也不授权发布。 来源:[真实发布契约](baselines/vast-contract.md);已可重跑的 `vast-contract.test.mjs`及`test/vast.test.js`固定以下矛盾: @@ -14,12 +18,12 @@ 用户操作调用`init()`。在同一默认调用中无法同时保留非null和null,以及相反初始化时机。 添加别名或getter也无法同时满足两种值;按callback源码猜测用户版本不可取。 -## 推荐的具体处置(尚未实现) +## 已接受并实施的具体处置 优先保持实际npm1.0.0默认行为:回调前初始化、提供id/$container,SDK默认设置保持 发布语义;保留workspace新增的init/container/settings等字段作为扩展。 -确实依赖未发布1.2.0惰性行为的代码,拟通过新的可选第二参数明确选择该兼容模式: +确实依赖未发布1.2.0惰性行为的代码,通过新的可选第二参数明确选择该兼容模式: ```js // npm旧用法保持原样 @@ -35,11 +39,27 @@ artplayerPluginVast((context) => { ``` 这意味着依赖未发布1.2.0默认惰性的代码需要增加一个参数。普通npm1.0.0用户保持 -原调用;这不是声称两种相反语义完全兼容。第二参数仅为待确认方案,当前生产代码 -尚未新增它;类型误声明、CJS.default和分发路径仍各自单独验证。 +原调用;这不是声称两种相反语义完全兼容。第二参数已获用户明确授权,生产代码 +由PKG-VAST-03落实;公开类型由04协调,CJS.default和完整分发各自单独验证。 -## 当前检查点 +默认模式同时保持发布版的可写数据字段、SDK默认设置、透明容器和每次显式请求 +转发;包装层不订阅工作区新增的四个广告事件,不代替SDK管理广告显隐。 +显式工作区模式保留黑色容器、四事件显隐、活动广告期间请求抑制及实时getter。 +两者共享已修复的资源所有权、初始化回滚和终止规则。 -生命周期与资源修复不依赖该选择,已经推进;默认初始化暂保持工作区行为,不把 -PKG-VAST-03或VAST-CONTEXT-01标完成。用户针对Ads的类型推导批准不适用于本决策。 -需要用户确认是否按推荐方案优先实际发布默认行为;也可指定其他取舍。 +默认模式销毁后保留三个发布数据字段的快照,容器已移除、SDK已释放;扩展的 +container getter返回null。显式重建会更新三个数据字段;核心销毁则禁止重建。 +工作区模式所有资源getter随当前session归零。默认ID保留art-前缀,工作区保留 +art-vast-;两者增加单模块递增后缀修复同毫秒ID碰撞,不恢复已复现的重复ID缺陷。 + +兼容选项在工厂调用时读取一次,后续修改原options不改变已创建的注册函数。 +未知compatibility值抛TypeError,发生在加载SDK之前。公开声明尚由04负责, +本步骤的JS示例不是宣称新的第二参数已完成TypeScript消费验收。 + +## 当前验收边界 + +PKG-VAST-03已落实默认模式、显式工作区模式与发布字段,82项Node、162项三浏览器 +受控SDK检查通过;初始化风险按本次用户决定限定接受。详见 +[完成记录](changes/2026-09-14-PKG-VAST-03-compatibility.md)。实际IMA播放和公开声明 +尚未完成。此前Ads的类型推导批准与本次VAST运行时决定分别记录;未来类型协调 +继续以实际发布声明为基线。 diff --git a/refactor/vast-validation.md b/refactor/vast-validation.md index cdab3ccc3..ec8318329 100644 --- a/refactor/vast-validation.md +++ b/refactor/vast-validation.md @@ -1,34 +1,50 @@ # VAST 测试维护 -当前完成 PKG-VAST-01/02;生产重构由03/04继续。来源见 +PKG-VAST-03现已落实用户确认的两种初始化模式;公开声明继续由04协调。来源见 [实际契约](baselines/vast-contract.md)、[VAST/SDK归档](baselines/vast-release.json) 和 [核心5.1.7归档](baselines/vast-core.json)。工作区1.2.0不是npm发布版本。 -03检查点:新增`test/vast-lifecycle.test.js`的15项候选修复断言,冻结工作区全部失败、 +早期03检查点:新增`test/vast-lifecycle.test.js`的15项候选修复断言,冻结工作区全部失败、 当前5个TS模块全部通过;现有测试共60项Node、117项浏览器通过。覆盖终止/回调失败、 初始化回滚、活动广告重建、旧事件、配置getter和SDK同步重入;完整CI900项通过。 该文件已纳入`yarn test:vast`和`test:unit`。实际资源所有权见 [包内架构](../packages/artplayer-plugin-vast/ARCHITECTURE.md); -[初始化冲突](vast-compatibility-decision.md)未决定,03仍doing。以下缺陷清单保留历史 +[初始化冲突](vast-compatibility-decision.md)当时尚未决定。以下缺陷清单保留历史 来源,不代表候选实现仍包含这些已获可控修复证据的问题;真实IMA验收仍待05。 ## 文件与执行 -PKG-VAST-07补回工厂`.default`自身别名,不改变初始化决策。当前`yarn test:vast` +PKG-VAST-07补回工厂`.default`自身别名,不改变初始化决策。当时`yarn test:vast` 65项通过;实际main/legacy加ESM各4项导出通过。117项三浏览器检查通过,其中候选 异步注册场景使用`.default`,其他场景保留直接调用。浏览器仍替换SDK边界,实际 打包SDK只做无广告的导出/已销毁宿主验证。详见 [变更](changes/2026-09-14-PKG-VAST-07-default-alias.md)。 +2026-09-14用户确认默认保留npm语义、显式选择workspace惰性模式。当前Node82项 +通过,三浏览器×三核心×四插件实现/模式162项通过(99候选,63历史)。主片解码 +是真实浏览器行为,SDK仍受控。首次新增7项Node中5项在原候选失败,修复后新增 +10项全过;首轮浏览器153过9失败来自默认模式仍被旧断言当作工作区显隐,原报告 +保留。修正为各自历史前缀、监听数和显隐责任,并补充回调开始时资源/数据字段 +检查;未删除清理/重建断言。最终源码格式整理后重跑,完整证据见 +[03完成记录](changes/2026-09-14-PKG-VAST-03-compatibility.md)。 +版本以实际附件为准:npm核心5.1.7/5.4.0、候选5.4.1;早期文档把published路径 +写为5.4.1不准确,本轮报告已按来源及实际coreVersion纠正。 + - `test/vast-exports.test.js`:源码构建或环境变量指定的实际main/legacy/ESM导出。 保持现有callable,不宣称复刻旧namespace对象的反射形状;新文件纳入test:vast/test:unit。 - `test/helpers/vast-sdk.js`:可在Node和浏览器使用的SDK记录器,控制加载、构造、 监听、请求、销毁失败和晚到事件;不实现IMA、广告请求或主片暂停恢复。 - `test/helpers/vast.js`:只在精确的`@glomex/vast-ima-player`导入边界替换SDK。 当前JS/TS入口可打包加载;两套历史源码必须来自哈希验证的npm归档/Git内容。 + source与source-workspace是相同编译代码,后者显式传第二参数;published字段 + 表示行为模式,historical才表示历史代码。浏览器附件记录实际选项,避免混计。 Node宿主仅提供事件和DOM所有权意图,不模拟布局或视频解码。 - `test/vast.test.js`:共享契约、工作区新增功能、独立的历史缺陷观察。 修复时为当前候选增加正确行为断言,保留历史缺陷复现,不能把旧缺陷移入共享契约。 +- `test/vast-compatibility.test.js`:对照实际npm源码,验证提前初始化、原数据属性、 + SDK默认设置、重复请求、回调拒绝/取消、构造重入、销毁重建及显式模式选择。 + 与原生命周期文件一起纳入test:vast/test:unit;后者保留工作区专属getter/四事件 + 故障断言,默认模式由兼容文件和共享/浏览器矩阵覆盖。 - `test/browser/vast.spec.js`:三真实浏览器×三核心,测试异步注册、加载失败、真实 DOM显隐、显式清理重建、主片解码/切源和销毁后晚到初始化。SDK仍是同一受控记录器。 - `refactor/scripts/vast-core.test.mjs`:实际5.1.7 tarball、197成员和发布关联检查。 @@ -54,9 +70,9 @@ VAST-LIFE-01由源码观察提升为受控运行复现,问题如下: 9. 工作区SDK destroy抛错阻止DOM及引用清理。 10. 工作区事件注册失败后留下不完整SDK,下一次init错误地认为它已就绪。 -03应建立明确的生命周期/SDK/DOM所有权,并区分可重建的显式广告destroy与终止性的 -核心destroy。04处理准确类型、SDK声明依赖和同步误声明;初始化冲突应以发布及 -工作区消费者证据明确处置,Ads的专属类型批准不能扩展到VAST。 +03已建立生命周期/SDK/DOM所有权,区分可重建的显式广告destroy与终止性的核心destroy。 +初始化差异按用户本次独立确认处置;04处理准确类型、SDK声明依赖和同步误声明。 +运行时确认没有扩大Ads类型批准范围,也不自动豁免VAST声明兼容。 ## 验证边界 @@ -65,4 +81,4 @@ VAST-LIFE-01由源码观察提升为受控运行复现,问题如下: 使用精确注入;Node固定Date.now用于同毫秒ID复现,未改变生产时钟。 只有实际VAST外部脚本持续因VPN无法加载时,可按用户授权记录并跳过该网络验证; -它不豁免类型、生命周期或其他包。到02为止未用该例外。03~06和SDK-07继续开放。 +它不豁免类型、生命周期或其他包。本次未用该例外。04~06和SDK-07继续开放。 diff --git a/test/browser/vast.spec.js b/test/browser/vast.spec.js index 4f4535692..f23bcb925 100644 --- a/test/browser/vast.spec.js +++ b/test/browser/vast.spec.js @@ -8,11 +8,12 @@ const implementations = await vastImplementations() async function setup(page, core, implementation, testInfo, deferLoad = false) { await page.goto(`/test/player.html?core=${core}`) await page.addScriptTag({ content: `window.createVastSdk = ${createVastSdk.toString()};` }) - await page.evaluate((deferLoad) => { + await page.evaluate(({ deferLoad, options }) => { window.vastSdk = window.createVastSdk({ deferLoad }) + window.vastOptions = options window.google = { ima: window.vastSdk.ima } window.art = new window.Artplayer({ container: '.player', url: '/test/pattern.mp4', muted: true }) - }, deferLoad) + }, { deferLoad, options: implementation.options }) await page.addScriptTag({ content: `(() => { const module = { exports: {} }; const exports = module.exports; @@ -23,7 +24,7 @@ async function setup(page, core, implementation, testInfo, deferLoad = false) { ${implementation.code} window.artplayerPluginVast = module.exports.default || module.exports; })();` }) - await testInfo.attach('vast-inputs', { contentType: 'application/json', body: JSON.stringify({ core, implementation: implementation.name, sha256: hash(implementation.code), sdk: 'controlled wrapper recorder, no IMA execution' }) }) + await testInfo.attach('vast-inputs', { contentType: 'application/json', body: JSON.stringify({ core, implementation: implementation.name, options: implementation.options || {}, sha256: hash(implementation.code), sdk: 'controlled wrapper recorder, no IMA execution' }) }) } test.afterEach(async ({ page }, testInfo) => { @@ -62,7 +63,7 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) { await gate context.playUrl('/test/ad-tag.xml') context.playRes('') - })).then(() => { + }, window.vastOptions)).then(() => { window.vastDone = true }) }, !implementation.historical) @@ -71,6 +72,19 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) { await expect.poll(() => page.evaluate(() => window.vastCalls)).toBe(1) expect(await page.evaluate(() => window.vastDone)).toBe(false) expect(await page.evaluate(() => Object.hasOwn(window.art.plugins, 'artplayerPluginVast'))).toBe(false) + const beforeRequests = await page.evaluate(() => { + const context = window.vastContext + const player = window.vastSdk.state.players[0] + return { + players: window.vastSdk.state.players.length, + allocated: context.imaPlayer !== null, + publishedAliases: !!player && context.$container === player.args[2] && context.id === player.args[2].id, + writablePlayer: Object.getOwnPropertyDescriptor(context, 'imaPlayer').writable === true, + preloading: player?.args[3].enablePreloading === true, + background: player?.args[2].style.backgroundColor || '', + } + }) + expect(beforeRequests).toEqual({ players: implementation.published ? 1 : 0, allocated: !!implementation.published, publishedAliases: !!implementation.published, writablePlayer: !!implementation.published, preloading: false, background: '' }) await page.evaluate(() => window.finishVastCallback()) await page.evaluate(() => window.vastRegistration) const result = await page.evaluate(() => ({ @@ -88,7 +102,7 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) { const result = await page.evaluate(async () => { const failure = new Error('controlled SDK failure') let calls = 0 - const registration = window.art.plugins.add(window.artplayerPluginVast(() => calls++)) + const registration = window.art.plugins.add(window.artplayerPluginVast(() => calls++, window.vastOptions)) const observed = registration.catch(error => error === failure) window.vastSdk.rejectLoad(failure) return { sameFailure: await observed, calls, players: window.vastSdk.state.players.length, registered: Object.hasOwn(window.art.plugins, 'artplayerPluginVast') } @@ -109,7 +123,7 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) { await page.evaluate(async () => { await window.art.plugins.add(window.artplayerPluginVast((context) => { window.vastContext = context - })) + }, window.vastOptions)) window.vastContext.playUrl('/first.xml') }) const container = page.locator('[id^="art-vast-"]') @@ -154,7 +168,7 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) { window.vastRegistration = window.art.plugins.add(window.artplayerPluginVast((context) => { window.vastCalls++ context.playUrl('/late.xml') - })) + }, window.vastOptions)) window.art.destroy() window.vastSdk.resolveLoad() }) @@ -173,7 +187,7 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) { await setup(page, core, implementation, testInfo, true) const state = await page.evaluate(async () => { let calls = 0 - const registration = window.art.plugins.add(window.artplayerPluginVast(() => calls++)) + const registration = window.art.plugins.add(window.artplayerPluginVast(() => calls++, window.vastOptions)) window.art.destroy() window.vastSdk.resolveLoad() await registration @@ -187,14 +201,21 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) { await page.evaluate(async () => { await window.art.plugins.add(window.artplayerPluginVast((context) => { window.vastContext = context - })) + }, window.vastOptions)) window.vastContext.playUrl('/one.xml') const first = window.vastContext.imaPlayer window.lateVastEvents = [...first.listeners.values()].flatMap(values => [...values]) first.emit('AdStarted') }) - const container = page.locator('[id^="art-vast-"]') - await expect(container).toBeVisible() + const container = page.locator(implementation.published ? '[id^="art-"]' : '[id^="art-vast-"]') + await expect(container).toHaveCount(1) + expect(await page.evaluate(() => window.lateVastEvents.length)).toBe(implementation.published ? 0 : 4) + // The published wrapper delegates overlay visibility to the real SDK. + // This recorder does not implement that SDK behavior. + if (implementation.published) + await expect(container).toBeHidden() + else + await expect(container).toBeVisible() await page.evaluate(() => { window.art.plugins.artplayerPluginVast.destroy() window.vastContext.playUrl('/two.xml') @@ -218,11 +239,11 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) { const registration = window.art.plugins.add(window.artplayerPluginVast((context) => { context.init() return Promise.reject(failure) - })) + }, window.vastOptions)) return { sameError: await registration.catch(error => error === failure), destroys: window.vastSdk.state.players[0].destroyCalls, coreDestroyed: window.art.isDestroy } }) expect(result).toEqual({ sameError: true, destroys: 1, coreDestroyed: false }) - await expect(page.locator('[id^="art-vast-"]')).toHaveCount(0) + await expect(page.locator(implementation.published ? '[id^="art-"]' : '[id^="art-vast-"]')).toHaveCount(0) }) } } diff --git a/test/helpers/vast.js b/test/helpers/vast.js index 0c19e2732..7cbc72e4b 100644 --- a/test/helpers/vast.js +++ b/test/helpers/vast.js @@ -12,7 +12,8 @@ export async function vastImplementations() { const { outputFiles } = await build({ entryPoints: [resolveSource('packages/artplayer-plugin-vast/src/index')], bundle: true, write: false, format: 'cjs', platform: 'browser', external: ['@glomex/vast-ima-player'] }) const frozen = async source => (await transform(source, { loader: 'js', format: 'cjs', target: 'es2020' })).code return [ - { name: 'source', code: outputFiles[0].text }, + { name: 'source', published: true, code: outputFiles[0].text }, + { name: 'source-workspace', options: { compatibility: 'workspace-1.2' }, code: outputFiles[0].text }, { name: 'published-1.0.0-source', historical: true, published: true, code: await frozen(readMember(archive, 'package/src/index.js').toString()) }, { name: 'frozen-workspace-1.2.0', historical: true, code: await frozen(contract.sources.get('packages/artplayer-plugin-vast/src/index.js')) }, ] diff --git a/test/vast-compatibility.test.js b/test/vast-compatibility.test.js new file mode 100644 index 000000000..9194bef79 --- /dev/null +++ b/test/vast-compatibility.test.js @@ -0,0 +1,181 @@ +import assert from 'node:assert/strict' +// eslint-disable-next-line test/no-import-node-test -- Published and candidate callback contracts use controlled SDKs. +import test from 'node:test' +import { deferred, vastEnvironment, vastImplementations } from './helpers/vast.js' + +const implementations = await vastImplementations() +const source = implementations.find(item => item.name === 'source') + +for (const implementation of implementations.filter(item => item.name === 'source' || item.published)) { + test(`${implementation.name}: npm callback receives an allocated SDK and original data fields without changing SDK defaults`, async () => { + const env = vastEnvironment(implementation) + const host = env.host() + let context + await env.factory((value) => { + context = value + assert.equal(env.state.players.length, 1) + assert.equal(value.imaPlayer, env.state.players[0]) + assert.equal(value.$container, host.parent.children[0]) + assert.equal(value.id, value.$container.id) + assert.match(value.id, /^art-\d/) + value.imaPlayer.addEventListener('custom', () => {}) + for (const key of ['imaPlayer', 'id', '$container']) { + const descriptor = Object.getOwnPropertyDescriptor(value, key) + assert.equal(descriptor.get, undefined) + assert.equal(descriptor.writable, true) + assert.equal(descriptor.enumerable, true) + assert.equal(descriptor.configurable, true) + } + })(host.art) + const player = env.state.players[0] + assert.equal(player.args[3].enablePreloading, undefined) + assert.equal(player.args[3].restoreCustomPlaybackStateOnAdBreakComplete, undefined) + assert.equal(context.$container.style.backgroundColor, undefined) + assert.equal(context.$container.style.pointerEvents, undefined) + context.playUrl('/first.xml') + player.emit('AdStarted') + context.playUrl('/second.xml') + assert.equal(player.requests.length, 2, 'The published wrapper forwards both explicit requests') + }) +} + +test('VAST explicit workspace mode retains lazy initialization and caller option identities', async () => { + const env = vastEnvironment(source) + const host = env.host() + let context + await env.factory((value) => { + context = value + assert.equal(value.imaPlayer, null) + assert.equal(value.container, null) + assert.equal(env.state.players.length, 0) + value.playerOptions.custom = 'before initialization' + }, { compatibility: 'workspace-1.2' })(host.art) + const player = context.init() + assert.equal(player.args[3], context.adsRenderingSettings) + assert.equal(player.args[4], context.playerOptions) + assert.equal(player.args[4].custom, 'before initialization') + assert.equal(player.args[3].enablePreloading, true) + assert.equal(player.args[3].restoreCustomPlaybackStateOnAdBreakComplete, true) + assert.match(context.container.id, /^art-vast-/) + context.playUrl('/first.xml') + player.emit('AdStarted') + context.playUrl('/suppressed.xml') + assert.equal(player.requests.length, 1) + host.art.destroy() + assert.equal(player.destroyCalls, 1) + assert.equal(context.imaPlayer, null) +}) + +test('VAST default initializes even without a callback and releases on core destruction', async () => { + const env = vastEnvironment(source) + const host = env.host() + await env.factory()(host.art) + assert.equal(env.state.players.length, 1) + host.art.destroy() + assert.equal(env.state.players[0].destroyCalls, 1) + assert.equal(host.parent.children.length, 0) +}) + +test('VAST eager constructor failure rejects registration before callback and removes owned DOM', async () => { + const failure = new Error('eager allocation failed') + const env = vastEnvironment(source, { constructError: failure }) + const host = env.host() + let called = false + await assert.rejects(env.factory(() => { + called = true + })(host.art), error => error === failure) + assert.equal(called, false) + assert.equal(host.parent.children.length, 0) + assert.equal(host.listeners.get('destroy').size, 0) +}) + +test('VAST eager allocation reentered by core destruction never invokes callback', async () => { + const env = vastEnvironment(source) + const host = env.host() + env.state.onConstruct = () => host.art.destroy() + let called = false + await env.factory(() => { + called = true + })(host.art) + assert.equal(called, false) + assert.equal(env.state.players[0].destroyCalls, 1) + assert.equal(host.parent.children.length, 0) +}) + +test('VAST eager callback cancellation releases the live SDK without rewriting its published snapshots', async () => { + const env = vastEnvironment(source) + const host = env.host() + const gate = deferred() + const started = deferred() + let context + const pending = env.factory(async (value) => { + context = value + started.resolve() + await gate.promise + value.playUrl('/too-late.xml') + })(host.art) + await started.promise + const player = context.imaPlayer + assert(player) + const container = context.$container + host.art.destroy() + gate.resolve() + await pending + assert.equal(context.imaPlayer, player) + assert.equal(context.$container, container) + assert.equal(container.parentNode, null) + assert.equal(player.destroyCalls, 1) + assert.equal(player.requests.length, 0) + assert.equal(context.init(), null) +}) + +test('VAST default callback rejection releases allocation and keeps the original failure', async () => { + for (const destroyError of [null, new Error('secondary cleanup')]) { + const env = vastEnvironment(source, { destroyError }) + const host = env.host() + const failure = new Error('callback failed') + let context + await assert.rejects(env.factory((value) => { + context = value + return Promise.reject(failure) + })(host.art), error => error === failure) + assert.equal(env.state.players[0].destroyCalls, 1) + assert.equal(host.parent.children.length, 0) + assert.equal(host.listeners.get('destroy').size, 0) + assert.equal(context.init(), null) + } +}) + +test('VAST default explicit destroy and recreation update aliases without reusing disposed resources', async () => { + const env = vastEnvironment(source) + const host = env.host() + let context + const result = await env.factory((value) => { + context = value + })(host.art) + const first = context.imaPlayer + const firstId = context.id + result.destroy() + result.destroy() + assert.equal(context.imaPlayer, first) + assert.equal(first.destroyCalls, 1) + context.playUrl('/fresh.xml') + assert.notEqual(context.imaPlayer, first) + assert.notEqual(context.id, firstId) + assert.equal(context.$container, context.container) + assert.equal(context.imaPlayer.requests[0].adTagUrl, '/fresh.xml') + assert.equal(host.parent.children.length, 1) + host.art.destroy() + assert.deepEqual(env.state.players.map(player => player.destroyCalls), [1, 1]) +}) + +test('VAST rejects an unknown mode before loading the SDK and snapshots a valid mode once', async () => { + const env = vastEnvironment(source) + assert.throws(() => env.factory(undefined, { compatibility: 'typo' }), /Unsupported VAST compatibility mode/) + assert.equal(env.state.loads, 0) + const options = { compatibility: 'workspace-1.2' } + const attach = env.factory(undefined, options) + options.compatibility = 'changed later' + await attach(env.host().art) + assert.equal(env.state.players.length, 0) +}) diff --git a/test/vast-lifecycle.test.js b/test/vast-lifecycle.test.js index 98901c64f..c39053216 100644 --- a/test/vast-lifecycle.test.js +++ b/test/vast-lifecycle.test.js @@ -3,7 +3,7 @@ import assert from 'node:assert/strict' import test from 'node:test' import { deferred, vastEnvironment, vastImplementations } from './helpers/vast.js' -const candidates = (await vastImplementations()).filter(item => !item.historical) +const candidates = (await vastImplementations()).filter(item => !item.historical && !item.published) for (const implementation of candidates) { const { name } = implementation @@ -14,7 +14,7 @@ for (const implementation of candidates) { const result = await env.factory((value) => { context = value value.playUrl('/first.xml') - })(host.art) + }, implementation.options)(host.art) const player = context.imaPlayer host.art.destroy() result.destroy() @@ -32,7 +32,7 @@ for (const implementation of candidates) { const env = vastEnvironment(implementation, { deferLoad: true }) const host = env.host() let calls = 0 - const attaching = env.factory(() => calls++)(host.art) + const attaching = env.factory(() => calls++, implementation.options)(host.art) assert.equal(host.listeners.get('destroy').size, 1) host.art.destroy() env.resolveLoad() @@ -47,7 +47,7 @@ for (const implementation of candidates) { const env = vastEnvironment(implementation) const host = env.host() host.art.destroy() - await env.factory(() => assert.fail('Unexpected callback'))(host.art) + await env.factory(() => assert.fail('Unexpected callback'), implementation.options)(host.art) assert.equal(env.state.loads, 0) assert.equal(host.listeners.size, 0) }) @@ -55,7 +55,7 @@ for (const implementation of candidates) { test(`${name}: SDK rejection unregisters the pending core listener`, async () => { const env = vastEnvironment(implementation, { deferLoad: true }) const host = env.host() - const attaching = env.factory()(host.art) + const attaching = env.factory(undefined, implementation.options)(host.art) const failure = new Error('load failure') const rejected = assert.rejects(attaching, error => error === failure) env.rejectLoad(failure) @@ -73,7 +73,7 @@ for (const implementation of candidates) { context = value context.init() throw failure - })(host.art), error => error === failure) + }, implementation.options)(host.art), error => error === failure) assert.equal(env.state.players[0].destroyCalls, 1) assert.equal(host.parent.children.length, 0) assert.equal(host.listeners.get('destroy').size, 0) @@ -94,7 +94,7 @@ for (const implementation of candidates) { await finish.promise context.playUrl('/late.xml') assert.equal(context.init(), null) - })(host.art) + }, implementation.options)(host.art) await started.promise host.art.destroy() finish.resolve() @@ -113,7 +113,7 @@ for (const implementation of candidates) { let context await env.factory((value) => { context = value - })(host.art) + }, implementation.options)(host.art) assert.throws(() => context.init(), error => error === failure) assert.equal(host.parent.children.length, 0) assert.equal(context.imaPlayer, null) @@ -133,7 +133,7 @@ for (const implementation of candidates) { const attach = env.factory((context) => { context.init() contexts.push(context) - }) + }, implementation.options) const one = env.host() const two = env.host() const [result] = await Promise.all([attach(one.art), attach(two.art)]) @@ -150,7 +150,7 @@ for (const implementation of candidates) { let context const result = await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) context.playUrl('/first.xml') context.imaPlayer.emit('AdStarted') result.destroy() @@ -164,7 +164,7 @@ for (const implementation of candidates) { let context const result = await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) const first = context.init() const late = [...first.listeners.values()].flatMap(listeners => [...listeners]) result.destroy() @@ -184,7 +184,7 @@ for (const implementation of candidates) { let context const result = await env.factory((value) => { context = value - })(host.art) + }, implementation.options)(host.art) const player = context.init() assert.throws(() => result.destroy(), error => error === failure) assert.equal(context.container, null) @@ -202,7 +202,7 @@ for (const implementation of candidates) { let context await env.factory((value) => { context = value - })(host.art) + }, implementation.options)(host.art) context.playUrl('/cancelled.xml', { get extra() { host.art.destroy() return 1 @@ -217,7 +217,7 @@ for (const implementation of candidates) { let context const result = await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) context.playUrl('/stale.xml', { get extra() { result.destroy() context.init() @@ -237,7 +237,7 @@ for (const implementation of candidates) { let context await env.factory((value) => { context = value - })(host.art) + }, implementation.options)(host.art) env.state[hook] = () => host.art.destroy() assert.equal(context.init(), null) assert.equal(env.state.players[0].destroyCalls, 1) @@ -251,7 +251,7 @@ for (const implementation of candidates) { let context const result = await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) context.init() env.state.onDestroy = () => { assert.equal(context.init(), null) diff --git a/test/vast.test.js b/test/vast.test.js index f93bca95e..da8c110ec 100644 --- a/test/vast.test.js +++ b/test/vast.test.js @@ -42,7 +42,7 @@ for (const implementation of implementations) { calls++ started.resolve(context) await finish.promise - })(host.art) + }, implementation.options)(host.art) attaching.then(() => { settled = true }) @@ -63,7 +63,7 @@ for (const implementation of implementations) { const env = vastEnvironment(implementation, { deferLoad: true }) const host = env.host() let calls = 0 - const attaching = env.factory(() => calls++)(host.art) + const attaching = env.factory(() => calls++, implementation.options)(host.art) const failure = new Error('SDK unavailable') const rejected = assert.rejects(attaching, error => error === failure) env.rejectLoad(failure) @@ -75,7 +75,7 @@ for (const implementation of implementations) { test(`${name}: absent callback remains accepted at runtime`, async () => { const env = vastEnvironment(implementation) - const result = await env.factory()(env.host().art) + const result = await env.factory(undefined, implementation.options)(env.host().art) assert.equal(result.name, 'artplayerPluginVast') }) @@ -84,7 +84,7 @@ for (const implementation of implementations) { let context await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) assert.equal(context.playUrl('https://example.test/ad.xml'), undefined) assert.equal(context.playRes(''), undefined) const [player] = env.state.players @@ -97,7 +97,7 @@ for (const implementation of implementations) { test(`${name}: one attach factory creates independent contexts, players and requests`, async () => { const env = vastEnvironment(implementation) const contexts = [] - const attach = env.factory(context => contexts.push(context)) + const attach = env.factory(context => contexts.push(context), implementation.options) const one = env.host() const two = env.host() await Promise.all([attach(one.art), attach(two.art)]) @@ -117,7 +117,7 @@ for (const implementation of implementations) { let context await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) assert.throws(() => context.playUrl('/ad.xml'), error => error === failure) env.state.playError = null context.playUrl('/retry.xml') @@ -132,7 +132,7 @@ for (const implementation of implementations) { if (asynchronous) return Promise.reject(failure) throw failure - })(env.host().art) + }, implementation.options)(env.host().art) await assert.rejects(attaching, error => error === failure) } }) @@ -146,7 +146,7 @@ for (const implementation of implementations) { let context await env.factory((value) => { context = value - })(host.art) + }, implementation.options)(host.art) assert.equal(context.imaPlayer, null) assert.equal(context.container, null) context.playerOptions.custom = 'caller option' @@ -166,7 +166,7 @@ for (const implementation of implementations) { let context await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) const config = Object.assign(Object.create({ inherited: 'legacy field' }), { adTagUrl: '/override.xml', adsResponse: 'override response' }) context.playUrl('/ignored.xml', config) config.adTagUrl = '/changed.xml' @@ -183,7 +183,7 @@ for (const implementation of implementations) { let context await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) context.playUrl('/first.xml') const player = context.imaPlayer assert.equal(context.container.style.display, 'none') @@ -211,7 +211,7 @@ for (const implementation of implementations) { let context const result = await env.factory((value) => { context = value - })(host.art) + }, implementation.options)(host.art) const first = context.init() assert.equal(result.destroy(), undefined) result.destroy() @@ -232,7 +232,7 @@ for (const implementation of implementations.filter(item => item.historical)) { test(`${name} historical: core destroy leaves the SDK allocated`, async () => { const env = vastEnvironment(implementation) const host = env.host() - await env.factory(context => initialize(context))(host.art) + await env.factory(context => initialize(context), implementation.options)(host.art) const [player] = env.state.players host.art.destroy() assert.equal(player.destroyCalls, 0) @@ -246,7 +246,7 @@ for (const implementation of implementations.filter(item => item.historical)) { const attaching = env.factory((context) => { calls++ initialize(context) - })(host.art) + }, implementation.options)(host.art) host.art.destroy() env.resolveLoad() await attaching @@ -262,7 +262,7 @@ for (const implementation of implementations.filter(item => item.historical)) { await assert.rejects(env.factory((context) => { initialize(context) return Promise.reject(failure) - })(host.art), error => error === failure) + }, implementation.options)(host.art), error => error === failure) assert.equal(env.state.players[0].destroyCalls, 0) assert.equal(host.parent.children.length, 1) }) @@ -276,7 +276,7 @@ for (const implementation of implementations.filter(item => item.historical)) { started.resolve() await finish.promise context.playUrl('/late.xml') - })(host.art) + }, implementation.options)(host.art) await started.promise host.art.destroy() finish.resolve() @@ -289,7 +289,7 @@ for (const implementation of implementations.filter(item => item.historical)) { const failure = new Error('constructor failure') const env = vastEnvironment(implementation, { constructError: failure }) const host = env.host() - await assert.rejects(env.factory(context => initialize(context))(host.art), error => error === failure) + await assert.rejects(env.factory(context => initialize(context), implementation.options)(host.art), error => error === failure) assert.equal(host.parent.children.length, 1) assert.equal(env.state.players.length, 0) }) @@ -298,7 +298,7 @@ for (const implementation of implementations.filter(item => item.historical)) { const env = vastEnvironment(implementation) const one = env.host() const two = env.host() - const attach = env.factory(context => initialize(context)) + const attach = env.factory(context => initialize(context), implementation.options) await Promise.all([attach(one.art), attach(two.art)]) assert.equal(one.parent.children[0].id, two.parent.children[0].id) assert.notEqual(one.parent.children[0], two.parent.children[0]) @@ -312,7 +312,7 @@ for (const implementation of implementations.filter(item => item.historical)) { let context const result = await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) context.playUrl('/first.xml') context.imaPlayer.emit('AdStarted') result.destroy() @@ -326,7 +326,7 @@ for (const implementation of implementations.filter(item => item.historical)) { let context const result = await env.factory((value) => { context = value - })(env.host().art) + }, implementation.options)(env.host().art) const first = context.init() const lateStart = [...first.listeners.get('AdStarted')][0] result.destroy() @@ -345,7 +345,7 @@ for (const implementation of implementations.filter(item => item.historical)) { let context const result = await env.factory((value) => { context = value - })(host.art) + }, implementation.options)(host.art) const player = context.init() assert.throws(() => result.destroy(), error => error === failure) assert.equal(context.imaPlayer, player) @@ -359,7 +359,7 @@ for (const implementation of implementations.filter(item => item.historical)) { let context await env.factory((value) => { context = value - })(host.art) + }, implementation.options)(host.art) assert.throws(() => context.init(), error => error === failure) env.state.listenError = null const player = context.init()